From 4673818140a776bfd15299f5c8e2796cf7c16884 Mon Sep 17 00:00:00 2001 From: Colin Hirsch Date: Wed, 8 Nov 2017 14:20:27 +0100 Subject: [PATCH 1/7] Experimental use of taocpp/json to parse json. Improve and extend taocpp/json integration. Update taocpp/json. Update taocpp/json. Improve and extend taocpp/json integration. --- LICENSE.taocpp | 21 + include/tao/json.hpp | 70 + include/tao/json/binary.hpp | 100 + include/tao/json/byte_view.hpp | 445 ++++ include/tao/json/cbor.hpp | 13 + include/tao/json/cbor/from_string.hpp | 40 + include/tao/json/cbor/to_stream.hpp | 35 + include/tao/json/cbor/to_string.hpp | 36 + include/tao/json/events/apply.hpp | 28 + include/tao/json/events/binary_to_base64.hpp | 34 + .../tao/json/events/binary_to_base64url.hpp | 36 + .../tao/json/events/binary_to_exception.hpp | 35 + include/tao/json/events/binary_to_hex.hpp | 34 + include/tao/json/events/cbor/from_string.hpp | 47 + include/tao/json/events/cbor/grammar.hpp | 444 ++++ include/tao/json/events/cbor/major.hpp | 40 + include/tao/json/events/cbor/to_stream.hpp | 166 ++ include/tao/json/events/cbor/to_string.hpp | 43 + include/tao/json/events/compare.hpp | 259 ++ include/tao/json/events/debug.hpp | 153 ++ include/tao/json/events/discard.hpp | 88 + include/tao/json/events/from_stream.hpp | 41 + include/tao/json/events/from_string.hpp | 47 + include/tao/json/events/from_value.hpp | 194 ++ include/tao/json/events/hash.hpp | 176 ++ include/tao/json/events/jaxn/from_stream.hpp | 45 + include/tao/json/events/jaxn/from_string.hpp | 51 + include/tao/json/events/jaxn/parse_file.hpp | 40 + .../tao/json/events/jaxn/to_pretty_stream.hpp | 76 + include/tao/json/events/jaxn/to_stream.hpp | 75 + .../events/key_camel_case_to_snake_case.hpp | 71 + .../events/key_snake_case_to_camel_case.hpp | 66 + .../tao/json/events/msgpack/from_string.hpp | 46 + include/tao/json/events/msgpack/grammar.hpp | 261 ++ include/tao/json/events/msgpack/to_stream.hpp | 218 ++ include/tao/json/events/msgpack/to_string.hpp | 44 + .../json/events/non_finite_to_exception.hpp | 39 + .../tao/json/events/non_finite_to_null.hpp | 40 + .../tao/json/events/non_finite_to_string.hpp | 48 + include/tao/json/events/parse_file.hpp | 36 + include/tao/json/events/prefer_signed.hpp | 40 + include/tao/json/events/prefer_unsigned.hpp | 40 + include/tao/json/events/ref.hpp | 120 + include/tao/json/events/tee.hpp | 417 ++++ include/tao/json/events/to_pretty_stream.hpp | 170 ++ include/tao/json/events/to_stream.hpp | 149 ++ include/tao/json/events/to_string.hpp | 42 + include/tao/json/events/to_value.hpp | 152 ++ include/tao/json/events/transformer.hpp | 41 + .../tao/json/events/ubjson/from_string.hpp | 47 + include/tao/json/events/ubjson/grammar.hpp | 279 +++ include/tao/json/events/ubjson/to_stream.hpp | 188 ++ include/tao/json/events/ubjson/to_string.hpp | 44 + .../tao/json/events/validate_event_order.hpp | 387 +++ include/tao/json/events/validate_keys.hpp | 58 + .../tao/json/external/akrzemi1/CMakeLists.txt | 46 + include/tao/json/external/akrzemi1/LICENSE | 23 + .../json/external/akrzemi1/LICENSE_1_0.txt | 23 + include/tao/json/external/akrzemi1/README.md | 39 + .../tao/json/external/akrzemi1/copyright.txt | 10 + .../tao/json/external/akrzemi1/optional.hpp | 1052 ++++++++ .../json/external/akrzemi1/test_optional.cpp | 1520 ++++++++++++ .../external/akrzemi1/test_type_traits.cpp | 66 + include/tao/json/external/byte.hpp | 109 + include/tao/json/external/double.hpp | 2136 +++++++++++++++++ include/tao/json/external/operators.hpp | 658 +++++ include/tao/json/external/optional.hpp | 46 + include/tao/json/external/pegtl.hpp | 31 + .../pegtl/analysis/analyze_cycles.hpp | 134 ++ .../json/external/pegtl/analysis/counted.hpp | 29 + .../json/external/pegtl/analysis/generic.hpp | 39 + .../external/pegtl/analysis/grammar_info.hpp | 40 + .../external/pegtl/analysis/insert_guard.hpp | 66 + .../external/pegtl/analysis/insert_rules.hpp | 45 + .../external/pegtl/analysis/rule_info.hpp | 37 + .../external/pegtl/analysis/rule_type.hpp | 29 + include/tao/json/external/pegtl/analyze.hpp | 25 + .../tao/json/external/pegtl/apply_mode.hpp | 23 + .../tao/json/external/pegtl/argv_input.hpp | 52 + include/tao/json/external/pegtl/ascii.hpp | 67 + .../tao/json/external/pegtl/buffer_input.hpp | 179 ++ include/tao/json/external/pegtl/config.hpp | 15 + .../tao/json/external/pegtl/contrib/abnf.hpp | 43 + .../json/external/pegtl/contrib/alphabet.hpp | 75 + .../json/external/pegtl/contrib/changes.hpp | 86 + .../json/external/pegtl/contrib/counter.hpp | 58 + .../tao/json/external/pegtl/contrib/http.hpp | 152 ++ .../tao/json/external/pegtl/contrib/json.hpp | 98 + .../external/pegtl/contrib/parse_tree.hpp | 183 ++ .../external/pegtl/contrib/raw_string.hpp | 247 ++ .../pegtl/contrib/rep_one_min_max.hpp | 72 + .../json/external/pegtl/contrib/to_string.hpp | 42 + .../json/external/pegtl/contrib/tracer.hpp | 111 + .../json/external/pegtl/contrib/unescape.hpp | 203 ++ .../tao/json/external/pegtl/contrib/uri.hpp | 116 + .../tao/json/external/pegtl/cstream_input.hpp | 34 + include/tao/json/external/pegtl/eol.hpp | 54 + .../tao/json/external/pegtl/file_input.hpp | 37 + .../tao/json/external/pegtl/input_error.hpp | 41 + .../json/external/pegtl/internal/action.hpp | 52 + .../external/pegtl/internal/action_input.hpp | 108 + .../json/external/pegtl/internal/alnum.hpp | 26 + .../json/external/pegtl/internal/alpha.hpp | 26 + .../tao/json/external/pegtl/internal/any.hpp | 68 + .../json/external/pegtl/internal/apply.hpp | 79 + .../json/external/pegtl/internal/apply0.hpp | 77 + .../tao/json/external/pegtl/internal/at.hpp | 62 + .../tao/json/external/pegtl/internal/bof.hpp | 41 + .../tao/json/external/pegtl/internal/bol.hpp | 41 + .../external/pegtl/internal/bump_help.hpp | 64 + .../external/pegtl/internal/bump_impl.hpp | 53 + .../json/external/pegtl/internal/bytes.hpp | 46 + .../json/external/pegtl/internal/control.hpp | 52 + .../external/pegtl/internal/cr_crlf_eol.hpp | 39 + .../json/external/pegtl/internal/cr_eol.hpp | 39 + .../json/external/pegtl/internal/crlf_eol.hpp | 39 + .../pegtl/internal/cstream_reader.hpp | 48 + .../pegtl/internal/cstring_reader.hpp | 49 + .../json/external/pegtl/internal/demangle.hpp | 44 + .../pegtl/internal/demangle_cxxabi.hpp | 41 + .../external/pegtl/internal/demangle_nop.hpp | 28 + .../pegtl/internal/demangle_sanitise.hpp | 48 + .../json/external/pegtl/internal/disable.hpp | 52 + .../json/external/pegtl/internal/discard.hpp | 42 + .../external/pegtl/internal/dusel_mode.hpp | 27 + .../external/pegtl/internal/duseltronik.hpp | 167 ++ .../json/external/pegtl/internal/enable.hpp | 52 + .../tao/json/external/pegtl/internal/eof.hpp | 41 + .../tao/json/external/pegtl/internal/eol.hpp | 42 + .../tao/json/external/pegtl/internal/eolf.hpp | 43 + .../external/pegtl/internal/file_mapper.hpp | 91 + .../external/pegtl/internal/file_opener.hpp | 70 + .../external/pegtl/internal/file_reader.hpp | 96 + .../external/pegtl/internal/has_apply.hpp | 33 + .../external/pegtl/internal/has_apply0.hpp | 33 + .../external/pegtl/internal/identifier.hpp | 30 + .../json/external/pegtl/internal/if_apply.hpp | 90 + .../json/external/pegtl/internal/if_must.hpp | 27 + .../external/pegtl/internal/if_must_else.hpp | 27 + .../external/pegtl/internal/if_then_else.hpp | 59 + .../external/pegtl/internal/input_pair.hpp | 35 + .../pegtl/internal/integer_sequence.hpp | 86 + .../pegtl/internal/istream_reader.hpp | 47 + .../json/external/pegtl/internal/istring.hpp | 107 + .../json/external/pegtl/internal/iterator.hpp | 53 + .../external/pegtl/internal/lf_crlf_eol.hpp | 44 + .../json/external/pegtl/internal/lf_eol.hpp | 39 + .../tao/json/external/pegtl/internal/list.hpp | 27 + .../external/pegtl/internal/list_must.hpp | 28 + .../external/pegtl/internal/list_tail.hpp | 28 + .../external/pegtl/internal/list_tail_pad.hpp | 30 + .../json/external/pegtl/internal/marker.hpp | 93 + .../json/external/pegtl/internal/minus.hpp | 69 + .../tao/json/external/pegtl/internal/must.hpp | 79 + .../json/external/pegtl/internal/not_at.hpp | 62 + .../tao/json/external/pegtl/internal/one.hpp | 81 + .../tao/json/external/pegtl/internal/opt.hpp | 67 + .../tao/json/external/pegtl/internal/pad.hpp | 27 + .../json/external/pegtl/internal/pad_opt.hpp | 28 + .../external/pegtl/internal/peek_char.hpp | 37 + .../external/pegtl/internal/peek_utf16.hpp | 54 + .../external/pegtl/internal/peek_utf32.hpp | 46 + .../external/pegtl/internal/peek_utf8.hpp | 88 + .../external/pegtl/internal/pegtl_string.hpp | 98 + .../tao/json/external/pegtl/internal/plus.hpp | 61 + .../json/external/pegtl/internal/raise.hpp | 57 + .../json/external/pegtl/internal/range.hpp | 60 + .../json/external/pegtl/internal/ranges.hpp | 102 + .../tao/json/external/pegtl/internal/rep.hpp | 75 + .../json/external/pegtl/internal/rep_min.hpp | 28 + .../external/pegtl/internal/rep_min_max.hpp | 88 + .../json/external/pegtl/internal/rep_opt.hpp | 54 + .../json/external/pegtl/internal/require.hpp | 52 + .../pegtl/internal/result_on_found.hpp | 27 + .../pegtl/internal/rule_conjunction.hpp | 63 + .../json/external/pegtl/internal/rules.hpp | 61 + .../tao/json/external/pegtl/internal/seq.hpp | 80 + .../external/pegtl/internal/skip_control.hpp | 35 + .../tao/json/external/pegtl/internal/sor.hpp | 74 + .../tao/json/external/pegtl/internal/star.hpp | 56 + .../external/pegtl/internal/star_must.hpp | 27 + .../json/external/pegtl/internal/state.hpp | 83 + .../json/external/pegtl/internal/string.hpp | 68 + .../json/external/pegtl/internal/trivial.hpp | 42 + .../pegtl/internal/try_catch_type.hpp | 72 + .../json/external/pegtl/internal/until.hpp | 91 + .../tao/json/external/pegtl/istream_input.hpp | 34 + .../tao/json/external/pegtl/memory_input.hpp | 285 +++ .../tao/json/external/pegtl/mmap_input.hpp | 55 + include/tao/json/external/pegtl/normal.hpp | 89 + include/tao/json/external/pegtl/nothing.hpp | 27 + include/tao/json/external/pegtl/parse.hpp | 53 + .../tao/json/external/pegtl/parse_error.hpp | 45 + include/tao/json/external/pegtl/position.hpp | 54 + .../tao/json/external/pegtl/read_input.hpp | 52 + .../tao/json/external/pegtl/rewind_mode.hpp | 24 + include/tao/json/external/pegtl/rules.hpp | 69 + .../tao/json/external/pegtl/string_input.hpp | 51 + .../tao/json/external/pegtl/tracking_mode.hpp | 23 + include/tao/json/external/pegtl/utf16.hpp | 36 + include/tao/json/external/pegtl/utf32.hpp | 36 + include/tao/json/external/pegtl/utf8.hpp | 36 + include/tao/json/external/pegtl/version.hpp | 13 + include/tao/json/external/string_view.hpp | 565 +++++ include/tao/json/from_stream.hpp | 49 + include/tao/json/from_string.hpp | 45 + include/tao/json/internal/action.hpp | 242 ++ include/tao/json/internal/base64.hpp | 63 + include/tao/json/internal/base64url.hpp | 61 + include/tao/json/internal/control.hpp | 53 + include/tao/json/internal/endian.hpp | 70 + include/tao/json/internal/endian_gcc.hpp | 202 ++ include/tao/json/internal/endian_win.hpp | 91 + include/tao/json/internal/errors.hpp | 98 + include/tao/json/internal/escape.hpp | 77 + include/tao/json/internal/get_by_enum.hpp | 172 ++ include/tao/json/internal/grammar.hpp | 238 ++ include/tao/json/internal/hexdump.hpp | 39 + include/tao/json/internal/identity.hpp | 20 + include/tao/json/internal/jaxn/action.hpp | 335 +++ .../tao/json/internal/jaxn/binary_state.hpp | 43 + .../json/internal/jaxn/bunescape_action.hpp | 123 + include/tao/json/internal/jaxn/control.hpp | 64 + include/tao/json/internal/jaxn/errors.hpp | 121 + include/tao/json/internal/jaxn/grammar.hpp | 357 +++ .../json/internal/jaxn/unescape_action.hpp | 38 + include/tao/json/internal/key_state.hpp | 37 + include/tao/json/internal/number_state.hpp | 86 + include/tao/json/internal/sha256.hpp | 218 ++ include/tao/json/internal/string_state.hpp | 37 + include/tao/json/internal/throw.hpp | 24 + include/tao/json/internal/unescape_action.hpp | 32 + include/tao/json/internal/uri_fragment.hpp | 188 ++ include/tao/json/internal/value_union.hpp | 62 + include/tao/json/jaxn.hpp | 14 + include/tao/json/jaxn/from_stream.hpp | 54 + include/tao/json/jaxn/from_string.hpp | 50 + include/tao/json/jaxn/is_identifier.hpp | 35 + include/tao/json/jaxn/parse_file.hpp | 41 + include/tao/json/jaxn/to_stream.hpp | 44 + include/tao/json/jaxn/to_string.hpp | 41 + include/tao/json/msgpack.hpp | 13 + include/tao/json/msgpack/from_string.hpp | 40 + include/tao/json/msgpack/to_stream.hpp | 35 + include/tao/json/msgpack/to_string.hpp | 36 + include/tao/json/pair.hpp | 66 + include/tao/json/parse_file.hpp | 36 + include/tao/json/patch.hpp | 109 + include/tao/json/pointer.hpp | 307 +++ include/tao/json/reference.hpp | 122 + include/tao/json/schema.hpp | 1786 ++++++++++++++ include/tao/json/self_contained.hpp | 137 ++ include/tao/json/single.hpp | 49 + include/tao/json/stream.hpp | 39 + include/tao/json/to_stream.hpp | 38 + include/tao/json/to_string.hpp | 27 + include/tao/json/traits.hpp | 1091 +++++++++ include/tao/json/type.hpp | 121 + include/tao/json/ubjson.hpp | 13 + include/tao/json/ubjson/from_string.hpp | 40 + include/tao/json/ubjson/to_stream.hpp | 36 + include/tao/json/ubjson/to_string.hpp | 37 + include/tao/json/value.hpp | 1905 +++++++++++++++ include/velocypack/Json.h | 263 ++ include/velocypack/Parser.h | 208 +- src/Parser.cpp | 610 +---- 266 files changed, 30551 insertions(+), 771 deletions(-) create mode 100644 LICENSE.taocpp create mode 100644 include/tao/json.hpp create mode 100644 include/tao/json/binary.hpp create mode 100644 include/tao/json/byte_view.hpp create mode 100644 include/tao/json/cbor.hpp create mode 100644 include/tao/json/cbor/from_string.hpp create mode 100644 include/tao/json/cbor/to_stream.hpp create mode 100644 include/tao/json/cbor/to_string.hpp create mode 100644 include/tao/json/events/apply.hpp create mode 100644 include/tao/json/events/binary_to_base64.hpp create mode 100644 include/tao/json/events/binary_to_base64url.hpp create mode 100644 include/tao/json/events/binary_to_exception.hpp create mode 100644 include/tao/json/events/binary_to_hex.hpp create mode 100644 include/tao/json/events/cbor/from_string.hpp create mode 100644 include/tao/json/events/cbor/grammar.hpp create mode 100644 include/tao/json/events/cbor/major.hpp create mode 100644 include/tao/json/events/cbor/to_stream.hpp create mode 100644 include/tao/json/events/cbor/to_string.hpp create mode 100644 include/tao/json/events/compare.hpp create mode 100644 include/tao/json/events/debug.hpp create mode 100644 include/tao/json/events/discard.hpp create mode 100644 include/tao/json/events/from_stream.hpp create mode 100644 include/tao/json/events/from_string.hpp create mode 100644 include/tao/json/events/from_value.hpp create mode 100644 include/tao/json/events/hash.hpp create mode 100644 include/tao/json/events/jaxn/from_stream.hpp create mode 100644 include/tao/json/events/jaxn/from_string.hpp create mode 100644 include/tao/json/events/jaxn/parse_file.hpp create mode 100644 include/tao/json/events/jaxn/to_pretty_stream.hpp create mode 100644 include/tao/json/events/jaxn/to_stream.hpp create mode 100644 include/tao/json/events/key_camel_case_to_snake_case.hpp create mode 100644 include/tao/json/events/key_snake_case_to_camel_case.hpp create mode 100644 include/tao/json/events/msgpack/from_string.hpp create mode 100644 include/tao/json/events/msgpack/grammar.hpp create mode 100644 include/tao/json/events/msgpack/to_stream.hpp create mode 100644 include/tao/json/events/msgpack/to_string.hpp create mode 100644 include/tao/json/events/non_finite_to_exception.hpp create mode 100644 include/tao/json/events/non_finite_to_null.hpp create mode 100644 include/tao/json/events/non_finite_to_string.hpp create mode 100644 include/tao/json/events/parse_file.hpp create mode 100644 include/tao/json/events/prefer_signed.hpp create mode 100644 include/tao/json/events/prefer_unsigned.hpp create mode 100644 include/tao/json/events/ref.hpp create mode 100644 include/tao/json/events/tee.hpp create mode 100644 include/tao/json/events/to_pretty_stream.hpp create mode 100644 include/tao/json/events/to_stream.hpp create mode 100644 include/tao/json/events/to_string.hpp create mode 100644 include/tao/json/events/to_value.hpp create mode 100644 include/tao/json/events/transformer.hpp create mode 100644 include/tao/json/events/ubjson/from_string.hpp create mode 100644 include/tao/json/events/ubjson/grammar.hpp create mode 100644 include/tao/json/events/ubjson/to_stream.hpp create mode 100644 include/tao/json/events/ubjson/to_string.hpp create mode 100644 include/tao/json/events/validate_event_order.hpp create mode 100644 include/tao/json/events/validate_keys.hpp create mode 100644 include/tao/json/external/akrzemi1/CMakeLists.txt create mode 100644 include/tao/json/external/akrzemi1/LICENSE create mode 100644 include/tao/json/external/akrzemi1/LICENSE_1_0.txt create mode 100644 include/tao/json/external/akrzemi1/README.md create mode 100644 include/tao/json/external/akrzemi1/copyright.txt create mode 100644 include/tao/json/external/akrzemi1/optional.hpp create mode 100644 include/tao/json/external/akrzemi1/test_optional.cpp create mode 100644 include/tao/json/external/akrzemi1/test_type_traits.cpp create mode 100644 include/tao/json/external/byte.hpp create mode 100644 include/tao/json/external/double.hpp create mode 100644 include/tao/json/external/operators.hpp create mode 100644 include/tao/json/external/optional.hpp create mode 100644 include/tao/json/external/pegtl.hpp create mode 100644 include/tao/json/external/pegtl/analysis/analyze_cycles.hpp create mode 100644 include/tao/json/external/pegtl/analysis/counted.hpp create mode 100644 include/tao/json/external/pegtl/analysis/generic.hpp create mode 100644 include/tao/json/external/pegtl/analysis/grammar_info.hpp create mode 100644 include/tao/json/external/pegtl/analysis/insert_guard.hpp create mode 100644 include/tao/json/external/pegtl/analysis/insert_rules.hpp create mode 100644 include/tao/json/external/pegtl/analysis/rule_info.hpp create mode 100644 include/tao/json/external/pegtl/analysis/rule_type.hpp create mode 100644 include/tao/json/external/pegtl/analyze.hpp create mode 100644 include/tao/json/external/pegtl/apply_mode.hpp create mode 100644 include/tao/json/external/pegtl/argv_input.hpp create mode 100644 include/tao/json/external/pegtl/ascii.hpp create mode 100644 include/tao/json/external/pegtl/buffer_input.hpp create mode 100644 include/tao/json/external/pegtl/config.hpp create mode 100644 include/tao/json/external/pegtl/contrib/abnf.hpp create mode 100644 include/tao/json/external/pegtl/contrib/alphabet.hpp create mode 100644 include/tao/json/external/pegtl/contrib/changes.hpp create mode 100644 include/tao/json/external/pegtl/contrib/counter.hpp create mode 100644 include/tao/json/external/pegtl/contrib/http.hpp create mode 100644 include/tao/json/external/pegtl/contrib/json.hpp create mode 100644 include/tao/json/external/pegtl/contrib/parse_tree.hpp create mode 100644 include/tao/json/external/pegtl/contrib/raw_string.hpp create mode 100644 include/tao/json/external/pegtl/contrib/rep_one_min_max.hpp create mode 100644 include/tao/json/external/pegtl/contrib/to_string.hpp create mode 100644 include/tao/json/external/pegtl/contrib/tracer.hpp create mode 100644 include/tao/json/external/pegtl/contrib/unescape.hpp create mode 100644 include/tao/json/external/pegtl/contrib/uri.hpp create mode 100644 include/tao/json/external/pegtl/cstream_input.hpp create mode 100644 include/tao/json/external/pegtl/eol.hpp create mode 100644 include/tao/json/external/pegtl/file_input.hpp create mode 100644 include/tao/json/external/pegtl/input_error.hpp create mode 100644 include/tao/json/external/pegtl/internal/action.hpp create mode 100644 include/tao/json/external/pegtl/internal/action_input.hpp create mode 100644 include/tao/json/external/pegtl/internal/alnum.hpp create mode 100644 include/tao/json/external/pegtl/internal/alpha.hpp create mode 100644 include/tao/json/external/pegtl/internal/any.hpp create mode 100644 include/tao/json/external/pegtl/internal/apply.hpp create mode 100644 include/tao/json/external/pegtl/internal/apply0.hpp create mode 100644 include/tao/json/external/pegtl/internal/at.hpp create mode 100644 include/tao/json/external/pegtl/internal/bof.hpp create mode 100644 include/tao/json/external/pegtl/internal/bol.hpp create mode 100644 include/tao/json/external/pegtl/internal/bump_help.hpp create mode 100644 include/tao/json/external/pegtl/internal/bump_impl.hpp create mode 100644 include/tao/json/external/pegtl/internal/bytes.hpp create mode 100644 include/tao/json/external/pegtl/internal/control.hpp create mode 100644 include/tao/json/external/pegtl/internal/cr_crlf_eol.hpp create mode 100644 include/tao/json/external/pegtl/internal/cr_eol.hpp create mode 100644 include/tao/json/external/pegtl/internal/crlf_eol.hpp create mode 100644 include/tao/json/external/pegtl/internal/cstream_reader.hpp create mode 100644 include/tao/json/external/pegtl/internal/cstring_reader.hpp create mode 100644 include/tao/json/external/pegtl/internal/demangle.hpp create mode 100644 include/tao/json/external/pegtl/internal/demangle_cxxabi.hpp create mode 100644 include/tao/json/external/pegtl/internal/demangle_nop.hpp create mode 100644 include/tao/json/external/pegtl/internal/demangle_sanitise.hpp create mode 100644 include/tao/json/external/pegtl/internal/disable.hpp create mode 100644 include/tao/json/external/pegtl/internal/discard.hpp create mode 100644 include/tao/json/external/pegtl/internal/dusel_mode.hpp create mode 100644 include/tao/json/external/pegtl/internal/duseltronik.hpp create mode 100644 include/tao/json/external/pegtl/internal/enable.hpp create mode 100644 include/tao/json/external/pegtl/internal/eof.hpp create mode 100644 include/tao/json/external/pegtl/internal/eol.hpp create mode 100644 include/tao/json/external/pegtl/internal/eolf.hpp create mode 100644 include/tao/json/external/pegtl/internal/file_mapper.hpp create mode 100644 include/tao/json/external/pegtl/internal/file_opener.hpp create mode 100644 include/tao/json/external/pegtl/internal/file_reader.hpp create mode 100644 include/tao/json/external/pegtl/internal/has_apply.hpp create mode 100644 include/tao/json/external/pegtl/internal/has_apply0.hpp create mode 100644 include/tao/json/external/pegtl/internal/identifier.hpp create mode 100644 include/tao/json/external/pegtl/internal/if_apply.hpp create mode 100644 include/tao/json/external/pegtl/internal/if_must.hpp create mode 100644 include/tao/json/external/pegtl/internal/if_must_else.hpp create mode 100644 include/tao/json/external/pegtl/internal/if_then_else.hpp create mode 100644 include/tao/json/external/pegtl/internal/input_pair.hpp create mode 100644 include/tao/json/external/pegtl/internal/integer_sequence.hpp create mode 100644 include/tao/json/external/pegtl/internal/istream_reader.hpp create mode 100644 include/tao/json/external/pegtl/internal/istring.hpp create mode 100644 include/tao/json/external/pegtl/internal/iterator.hpp create mode 100644 include/tao/json/external/pegtl/internal/lf_crlf_eol.hpp create mode 100644 include/tao/json/external/pegtl/internal/lf_eol.hpp create mode 100644 include/tao/json/external/pegtl/internal/list.hpp create mode 100644 include/tao/json/external/pegtl/internal/list_must.hpp create mode 100644 include/tao/json/external/pegtl/internal/list_tail.hpp create mode 100644 include/tao/json/external/pegtl/internal/list_tail_pad.hpp create mode 100644 include/tao/json/external/pegtl/internal/marker.hpp create mode 100644 include/tao/json/external/pegtl/internal/minus.hpp create mode 100644 include/tao/json/external/pegtl/internal/must.hpp create mode 100644 include/tao/json/external/pegtl/internal/not_at.hpp create mode 100644 include/tao/json/external/pegtl/internal/one.hpp create mode 100644 include/tao/json/external/pegtl/internal/opt.hpp create mode 100644 include/tao/json/external/pegtl/internal/pad.hpp create mode 100644 include/tao/json/external/pegtl/internal/pad_opt.hpp create mode 100644 include/tao/json/external/pegtl/internal/peek_char.hpp create mode 100644 include/tao/json/external/pegtl/internal/peek_utf16.hpp create mode 100644 include/tao/json/external/pegtl/internal/peek_utf32.hpp create mode 100644 include/tao/json/external/pegtl/internal/peek_utf8.hpp create mode 100644 include/tao/json/external/pegtl/internal/pegtl_string.hpp create mode 100644 include/tao/json/external/pegtl/internal/plus.hpp create mode 100644 include/tao/json/external/pegtl/internal/raise.hpp create mode 100644 include/tao/json/external/pegtl/internal/range.hpp create mode 100644 include/tao/json/external/pegtl/internal/ranges.hpp create mode 100644 include/tao/json/external/pegtl/internal/rep.hpp create mode 100644 include/tao/json/external/pegtl/internal/rep_min.hpp create mode 100644 include/tao/json/external/pegtl/internal/rep_min_max.hpp create mode 100644 include/tao/json/external/pegtl/internal/rep_opt.hpp create mode 100644 include/tao/json/external/pegtl/internal/require.hpp create mode 100644 include/tao/json/external/pegtl/internal/result_on_found.hpp create mode 100644 include/tao/json/external/pegtl/internal/rule_conjunction.hpp create mode 100644 include/tao/json/external/pegtl/internal/rules.hpp create mode 100644 include/tao/json/external/pegtl/internal/seq.hpp create mode 100644 include/tao/json/external/pegtl/internal/skip_control.hpp create mode 100644 include/tao/json/external/pegtl/internal/sor.hpp create mode 100644 include/tao/json/external/pegtl/internal/star.hpp create mode 100644 include/tao/json/external/pegtl/internal/star_must.hpp create mode 100644 include/tao/json/external/pegtl/internal/state.hpp create mode 100644 include/tao/json/external/pegtl/internal/string.hpp create mode 100644 include/tao/json/external/pegtl/internal/trivial.hpp create mode 100644 include/tao/json/external/pegtl/internal/try_catch_type.hpp create mode 100644 include/tao/json/external/pegtl/internal/until.hpp create mode 100644 include/tao/json/external/pegtl/istream_input.hpp create mode 100644 include/tao/json/external/pegtl/memory_input.hpp create mode 100644 include/tao/json/external/pegtl/mmap_input.hpp create mode 100644 include/tao/json/external/pegtl/normal.hpp create mode 100644 include/tao/json/external/pegtl/nothing.hpp create mode 100644 include/tao/json/external/pegtl/parse.hpp create mode 100644 include/tao/json/external/pegtl/parse_error.hpp create mode 100644 include/tao/json/external/pegtl/position.hpp create mode 100644 include/tao/json/external/pegtl/read_input.hpp create mode 100644 include/tao/json/external/pegtl/rewind_mode.hpp create mode 100644 include/tao/json/external/pegtl/rules.hpp create mode 100644 include/tao/json/external/pegtl/string_input.hpp create mode 100644 include/tao/json/external/pegtl/tracking_mode.hpp create mode 100644 include/tao/json/external/pegtl/utf16.hpp create mode 100644 include/tao/json/external/pegtl/utf32.hpp create mode 100644 include/tao/json/external/pegtl/utf8.hpp create mode 100644 include/tao/json/external/pegtl/version.hpp create mode 100644 include/tao/json/external/string_view.hpp create mode 100644 include/tao/json/from_stream.hpp create mode 100644 include/tao/json/from_string.hpp create mode 100644 include/tao/json/internal/action.hpp create mode 100644 include/tao/json/internal/base64.hpp create mode 100644 include/tao/json/internal/base64url.hpp create mode 100644 include/tao/json/internal/control.hpp create mode 100644 include/tao/json/internal/endian.hpp create mode 100644 include/tao/json/internal/endian_gcc.hpp create mode 100644 include/tao/json/internal/endian_win.hpp create mode 100644 include/tao/json/internal/errors.hpp create mode 100644 include/tao/json/internal/escape.hpp create mode 100644 include/tao/json/internal/get_by_enum.hpp create mode 100644 include/tao/json/internal/grammar.hpp create mode 100644 include/tao/json/internal/hexdump.hpp create mode 100644 include/tao/json/internal/identity.hpp create mode 100644 include/tao/json/internal/jaxn/action.hpp create mode 100644 include/tao/json/internal/jaxn/binary_state.hpp create mode 100644 include/tao/json/internal/jaxn/bunescape_action.hpp create mode 100644 include/tao/json/internal/jaxn/control.hpp create mode 100644 include/tao/json/internal/jaxn/errors.hpp create mode 100644 include/tao/json/internal/jaxn/grammar.hpp create mode 100644 include/tao/json/internal/jaxn/unescape_action.hpp create mode 100644 include/tao/json/internal/key_state.hpp create mode 100644 include/tao/json/internal/number_state.hpp create mode 100644 include/tao/json/internal/sha256.hpp create mode 100644 include/tao/json/internal/string_state.hpp create mode 100644 include/tao/json/internal/throw.hpp create mode 100644 include/tao/json/internal/unescape_action.hpp create mode 100644 include/tao/json/internal/uri_fragment.hpp create mode 100644 include/tao/json/internal/value_union.hpp create mode 100644 include/tao/json/jaxn.hpp create mode 100644 include/tao/json/jaxn/from_stream.hpp create mode 100644 include/tao/json/jaxn/from_string.hpp create mode 100644 include/tao/json/jaxn/is_identifier.hpp create mode 100644 include/tao/json/jaxn/parse_file.hpp create mode 100644 include/tao/json/jaxn/to_stream.hpp create mode 100644 include/tao/json/jaxn/to_string.hpp create mode 100644 include/tao/json/msgpack.hpp create mode 100644 include/tao/json/msgpack/from_string.hpp create mode 100644 include/tao/json/msgpack/to_stream.hpp create mode 100644 include/tao/json/msgpack/to_string.hpp create mode 100644 include/tao/json/pair.hpp create mode 100644 include/tao/json/parse_file.hpp create mode 100644 include/tao/json/patch.hpp create mode 100644 include/tao/json/pointer.hpp create mode 100644 include/tao/json/reference.hpp create mode 100644 include/tao/json/schema.hpp create mode 100644 include/tao/json/self_contained.hpp create mode 100644 include/tao/json/single.hpp create mode 100644 include/tao/json/stream.hpp create mode 100644 include/tao/json/to_stream.hpp create mode 100644 include/tao/json/to_string.hpp create mode 100644 include/tao/json/traits.hpp create mode 100644 include/tao/json/type.hpp create mode 100644 include/tao/json/ubjson.hpp create mode 100644 include/tao/json/ubjson/from_string.hpp create mode 100644 include/tao/json/ubjson/to_stream.hpp create mode 100644 include/tao/json/ubjson/to_string.hpp create mode 100644 include/tao/json/value.hpp create mode 100644 include/velocypack/Json.h diff --git a/LICENSE.taocpp b/LICENSE.taocpp new file mode 100644 index 00000000..4d55d91d --- /dev/null +++ b/LICENSE.taocpp @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2007-2017 Dr. Colin Hirsch and Daniel Frey + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/include/tao/json.hpp b/include/tao/json.hpp new file mode 100644 index 00000000..ca505a46 --- /dev/null +++ b/include/tao/json.hpp @@ -0,0 +1,70 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_JSON_HPP +#define TAOCPP_JSON_INCLUDE_JSON_HPP + +// JSON Value +#include "json/value.hpp" + +// Events producers +#include "json/events/from_stream.hpp" +#include "json/events/from_string.hpp" +#include "json/events/from_value.hpp" +#include "json/events/parse_file.hpp" + +// Events consumers +#include "json/events/to_pretty_stream.hpp" +#include "json/events/to_stream.hpp" +#include "json/events/to_string.hpp" +#include "json/events/to_value.hpp" + +// Events transformer +#include "json/events/binary_to_base64.hpp" +#include "json/events/binary_to_base64url.hpp" +#include "json/events/binary_to_exception.hpp" +#include "json/events/binary_to_hex.hpp" +#include "json/events/key_camel_case_to_snake_case.hpp" +#include "json/events/key_snake_case_to_camel_case.hpp" +#include "json/events/non_finite_to_exception.hpp" +#include "json/events/non_finite_to_null.hpp" +#include "json/events/non_finite_to_string.hpp" +#include "json/events/prefer_signed.hpp" +#include "json/events/prefer_unsigned.hpp" + +// Events other +#include "json/events/debug.hpp" +#include "json/events/discard.hpp" +#include "json/events/hash.hpp" +#include "json/events/tee.hpp" +#include "json/events/validate_event_order.hpp" +#include "json/events/validate_keys.hpp" + +// Value producers +#include "json/from_stream.hpp" +#include "json/from_string.hpp" +#include "json/parse_file.hpp" + +// Value writers +#include "json/stream.hpp" // operator<< +#include "json/to_stream.hpp" +#include "json/to_string.hpp" + +// Value support +#include "json/patch.hpp" +#include "json/self_contained.hpp" +//#include "json/diff.hpp" +#include "json/schema.hpp" + +// Relaxed JSON +#include "json/jaxn.hpp" + +// Binary literals +#include "json/binary.hpp" + +// Binary formats +#include "json/cbor.hpp" +#include "json/msgpack.hpp" +#include "json/ubjson.hpp" + +#endif diff --git a/include/tao/json/binary.hpp b/include/tao/json/binary.hpp new file mode 100644 index 00000000..cd66a6d9 --- /dev/null +++ b/include/tao/json/binary.hpp @@ -0,0 +1,100 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_BINARY_HPP +#define TAOCPP_JSON_INCLUDE_BINARY_HPP + +#include + +#include "external/byte.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + constexpr char unhex_char( const char c ) noexcept + { + return ( c < 'A' ) ? ( c - '0' ) : ( ( c < 'a' ) ? ( c - 'A' + 10 ) : ( c - 'a' + 10 ) ); + } + + template< typename V, V... > + struct vlist; + + template< typename T, typename L, char... Cs > + struct unhex_helper; + + template< typename T, typename V, V... Vs > + struct unhex_helper< T, vlist< V, Vs... > > + { + static constexpr T unhex() + { + return T{ Vs... }; + } + }; + + template< typename T, typename V, V... Vs, char C > + struct unhex_helper< T, vlist< V, Vs... >, C > + : unhex_helper< T, vlist< V > > + { + static_assert( sizeof( T ) == 0, "digits must occur in pairs" ); + }; + + template< typename T, typename V, V... Vs, char C1, char... Cs > + struct unhex_helper< T, vlist< V, Vs... >, '\'', C1, Cs... > + : unhex_helper< T, vlist< V, Vs... >, C1, Cs... > + { + }; + + template< typename T, typename V, V... Vs, char C0, char... Cs > + struct unhex_helper< T, vlist< V, Vs... >, C0, '\'', Cs... > + : unhex_helper< T, vlist< V > > + { + static_assert( sizeof( T ) == 0, "digit separator only allowed between pairs of digits" ); + }; + + template< typename T, typename V, V... Vs, char C0, char C1, char... Cs > + struct unhex_helper< T, vlist< V, Vs... >, C0, C1, Cs... > + : unhex_helper< T, vlist< V, Vs..., V( ( unhex_char( C0 ) << 4 ) + unhex_char( C1 ) ) >, Cs... > + { + }; + + template< typename T, typename V, char C > + constexpr T unhex() + { + static_assert( sizeof( T ) == 0, "not a hex literal" ); + return T{}; + } + + template< typename T, typename V, char C0, char C1, char... Cs > + constexpr T unhex() + { + static_assert( C0 == '0', "not a hex literal" ); + static_assert( C1 == 'x' || C1 == 'X', "not a hex literal" ); + return unhex_helper< T, vlist< V >, Cs... >::unhex(); + } + + template< typename T, char... Cs > + constexpr T unhex() + { + return unhex< T, typename T::value_type, Cs... >(); + } + + } // namespace internal + + inline namespace literals + { + template< char... Cs > + std::vector< tao::byte > operator"" _binary() + { + return internal::unhex< std::vector< tao::byte >, Cs... >(); + } + + } // namespace literals + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/byte_view.hpp b/include/tao/json/byte_view.hpp new file mode 100644 index 00000000..f9c2d79a --- /dev/null +++ b/include/tao/json/byte_view.hpp @@ -0,0 +1,445 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_INCLUDE_BYTE_VIEW_HPP +#define TAOCPP_INCLUDE_BYTE_VIEW_HPP + +#include +#include +#include +#include +#include +#include +#include + +#include "internal/identity.hpp" + +#include "external/byte.hpp" + +namespace tao +{ + // modelled after C++17's basic_string_view + template< class byteT > + class basic_byte_view + { + public: + using value_type = byteT; + using pointer = value_type*; + using const_pointer = const value_type*; + using reference = value_type&; + using const_reference = const value_type&; + using const_iterator = const value_type*; + using iterator = const_iterator; + using const_reverse_iterator = std::reverse_iterator< const_iterator >; + using reverse_iterator = const_reverse_iterator; + using size_type = size_t; + using difference_type = ptrdiff_t; + + static constexpr size_type npos = size_type( -1 ); + + constexpr basic_byte_view() noexcept + : data_( nullptr ), size_( 0 ) + { + } + + constexpr basic_byte_view( const byteT* str, size_type len ) noexcept + : data_( str ), size_( len ) + { + } + + constexpr basic_byte_view( const byteT* b, const byteT* e ) noexcept + : data_( b ), size_( e - b ) + { + } + + constexpr basic_byte_view( const std::vector< byteT >& str ) noexcept + : data_( str.data() ), size_( str.size() ) + { + } + + constexpr basic_byte_view( const basic_byte_view& ) noexcept = default; + /*constexpr*/ basic_byte_view& operator=( const basic_byte_view& ) noexcept = default; + + constexpr const_iterator begin() const noexcept + { + return data_; + } + + constexpr const_iterator end() const noexcept + { + return begin() + size(); + } + + constexpr const_iterator cbegin() const noexcept + { + return begin(); + } + + constexpr const_iterator cend() const noexcept + { + return begin() + size(); + } + + constexpr const_reverse_iterator rbegin() const noexcept + { + return const_reverse_iterator( end() ); + } + + constexpr const_reverse_iterator rend() const noexcept + { + return const_reverse_iterator( begin() ); + } + + constexpr const_reverse_iterator crbegin() const noexcept + { + return const_reverse_iterator( end() ); + } + + constexpr const_reverse_iterator crend() const noexcept + { + return const_reverse_iterator( begin() ); + } + + constexpr size_type size() const noexcept + { + return size_; + } + + constexpr size_type length() const noexcept + { + return size_; + } + + constexpr size_type max_size() const noexcept + { + return npos - 1; + } + + constexpr bool empty() const noexcept + { + return size_ == 0; + } + + constexpr const_reference operator[]( size_type pos ) const noexcept + { + return data_[ pos ]; + } + + constexpr const_reference at( size_type pos ) const + { + return ( pos >= size() ) ? throw std::out_of_range( "index out of range in tao::basic_byte_view::at" ) : data_[ pos ]; + } + + constexpr const_reference front() const noexcept + { + return data_[ 0 ]; + } + + constexpr const_reference back() const noexcept + { + return data_[ size() - 1 ]; + } + + constexpr const_pointer data() const noexcept + { + return data_; + } + + /*constexpr*/ void remove_prefix( size_type n ) noexcept + { + data_ += n; + size_ -= n; + } + + /*constexpr*/ void remove_suffix( size_type n ) noexcept + { + size_ -= n; + } + + /*constexpr*/ void swap( basic_byte_view& s ) noexcept + { + std::swap( data_, s.data_ ); + std::swap( size_, s.size_ ); + } + + size_type copy( byteT* s, size_type n, size_type pos = 0 ) const + { + if( pos > size() ) { + throw std::out_of_range( "index out of range in tao::basic_byte_view::copy" ); + } + const size_type rlen = std::min( n, size() - pos ); + std::memcpy( s, data() + pos, rlen ); + return rlen; + } + + constexpr basic_byte_view substr( size_type pos = 0, size_type n = npos ) const + { + return ( pos > size() ) ? throw std::out_of_range( "index out of range in tao::basic_byte_view::substr" ) : basic_byte_view( data() + pos, std::min( n, size() - pos ) ); + } + + /*constexpr*/ int compare( basic_byte_view s ) const noexcept + { + const size_type rlen = std::min( size(), s.size() ); + const int result = std::memcmp( data(), s.data(), rlen ); + if( result == 0 && size() != s.size() ) { + return ( size() < s.size() ) ? -1 : 1; + } + return result; + } + + constexpr int compare( size_type pos1, size_type n1, basic_byte_view s ) const + { + return substr( pos1, n1 ).compare( s ); + } + + constexpr int compare( size_type pos1, size_type n1, basic_byte_view s, size_type pos2, size_type n2 ) const + { + return substr( pos1, n1 ).compare( s.substr( pos2, n2 ) ); + } + + constexpr int compare( const byteT* s ) const + { + return compare( basic_byte_view( s ) ); + } + + constexpr int compare( size_type pos1, size_type n1, const byteT* s, size_type n2 ) const + { + return substr( pos1, n1 ).compare( basic_byte_view( s, n2 ) ); + } + + /*constexpr*/ size_type find( basic_byte_view s, size_type pos = 0 ) const noexcept + { + if( pos > size() - s.size() ) { + return npos; + } + const auto iter = std::search( begin() + pos, end(), s.begin(), s.end() ); + return iter == end() ? npos : iter - begin(); + } + + constexpr size_type find( byteT c, size_type pos = 0 ) const noexcept + { + return find( basic_byte_view( &c, 1 ), pos ); + } + + constexpr size_type find( const byteT* s, size_type pos, size_type n ) const noexcept + { + return find( basic_byte_view( s, n ), pos ); + } + + /*constexpr*/ size_type rfind( basic_byte_view s, size_type pos = npos ) const noexcept + { + if( pos > size() - s.size() ) { + return npos; + } + const auto iter = std::find_end( begin() + pos, end(), s.begin(), s.end() ); + return iter == end() ? npos : iter - begin(); + } + + constexpr size_type rfind( byteT c, size_type pos = npos ) const noexcept + { + return rfind( basic_byte_view( &c, 1 ), pos ); + } + + constexpr size_type rfind( const byteT* s, size_type pos, size_type n ) const noexcept + { + return rfind( basic_byte_view( s, n ), pos ); + } + + /*constexpr*/ size_type find_first_of( basic_byte_view s, size_type pos = 0 ) const noexcept + { + if( pos > size() - 1 ) { + return npos; + } + const auto iter = std::find_first_of( begin() + pos, end(), s.begin(), s.end() ); + return iter == end() ? npos : iter - begin(); + } + + constexpr size_type find_first_of( byteT c, size_type pos = 0 ) const noexcept + { + return find_first_of( basic_byte_view( &c, 1 ), pos ); + } + + constexpr size_type find_first_of( const byteT* s, size_type pos, size_type n ) const noexcept + { + return find_first_of( basic_byte_view( s, n ), pos ); + } + + /*constexpr*/ size_type find_last_of( basic_byte_view s, size_type pos = npos ) const noexcept + { + if( pos > size() - 1 ) { + return npos; + } + const auto iter = std::find_first_of( rbegin() + pos, rend(), s.begin(), s.end() ); + return iter == rend() ? npos : iter.base() - 1 - begin(); + } + + constexpr size_type find_last_of( byteT c, size_type pos = npos ) const noexcept + { + return find_last_of( basic_byte_view( &c, 1 ), pos ); + } + + constexpr size_type find_last_of( const byteT* s, size_type pos, size_type n ) const noexcept + { + return find_last_of( basic_byte_view( s, n ), pos ); + } + + /*constexpr*/ size_type find_first_not_of( basic_byte_view s, size_type pos = 0 ) const noexcept + { + if( pos > size() - 1 ) { + return npos; + } + const auto iter = std::find_if( begin() + pos, end(), [&]( char c ) { + return std::find( s.begin(), s.end(), c ) == s.end(); + } ); + return iter == end() ? npos : iter - begin(); + } + + constexpr size_type find_first_not_of( byteT c, size_type pos = 0 ) const noexcept + { + return find_first_not_of( basic_byte_view( &c, 1 ), pos ); + } + + constexpr size_type find_first_not_of( const byteT* s, size_type pos, size_type n ) const noexcept + { + return find_first_not_of( basic_byte_view( s, n ), pos ); + } + + /*constexpr*/ size_type find_last_not_of( basic_byte_view s, size_type pos = npos ) const noexcept + { + if( pos > size() - 1 ) { + return npos; + } + const auto iter = std::find_if( rbegin() + pos, rend(), [&]( char c ) { + return std::find( s.begin(), s.end(), c ) == s.end(); + } ); + return iter == rend() ? npos : iter.base() - 1 - begin(); + } + + constexpr size_type find_last_not_of( byteT c, size_type pos = npos ) const noexcept + { + return find_last_not_of( basic_byte_view( &c, 1 ), pos ); + } + + constexpr size_type find_last_not_of( const byteT* s, size_type pos, size_type n ) const noexcept + { + return find_first_not_of( basic_byte_view( s, n ), pos ); + } + + private: + const_pointer data_; + size_type size_; + }; + + template< class byteT > + constexpr bool operator==( basic_byte_view< byteT > x, basic_byte_view< byteT > y ) noexcept + { + return x.compare( y ) == 0; + } + + template< class byteT > + constexpr bool operator==( basic_byte_view< byteT > x, internal::identity< basic_byte_view< byteT > > y ) noexcept + { + return x.compare( y ) == 0; + } + + template< class byteT > + constexpr bool operator==( internal::identity< basic_byte_view< byteT > > x, basic_byte_view< byteT > y ) noexcept + { + return x.compare( y ) == 0; + } + + template< class byteT > + constexpr bool operator!=( basic_byte_view< byteT > x, basic_byte_view< byteT > y ) noexcept + { + return x.compare( y ) != 0; + } + + template< class byteT > + constexpr bool operator!=( basic_byte_view< byteT > x, internal::identity< basic_byte_view< byteT > > y ) noexcept + { + return x.compare( y ) != 0; + } + + template< class byteT > + constexpr bool operator!=( internal::identity< basic_byte_view< byteT > > x, basic_byte_view< byteT > y ) noexcept + { + return x.compare( y ) != 0; + } + + template< class byteT > + constexpr bool operator<( basic_byte_view< byteT > x, basic_byte_view< byteT > y ) noexcept + { + return x.compare( y ) < 0; + } + + template< class byteT > + constexpr bool operator<( basic_byte_view< byteT > x, internal::identity< basic_byte_view< byteT > > y ) noexcept + { + return x.compare( y ) < 0; + } + + template< class byteT > + constexpr bool operator<( internal::identity< basic_byte_view< byteT > > x, basic_byte_view< byteT > y ) noexcept + { + return x.compare( y ) < 0; + } + + template< class byteT > + constexpr bool operator>( basic_byte_view< byteT > x, basic_byte_view< byteT > y ) noexcept + { + return x.compare( y ) > 0; + } + + template< class byteT > + constexpr bool operator>( basic_byte_view< byteT > x, internal::identity< basic_byte_view< byteT > > y ) noexcept + { + return x.compare( y ) > 0; + } + + template< class byteT > + constexpr bool operator>( internal::identity< basic_byte_view< byteT > > x, basic_byte_view< byteT > y ) noexcept + { + return x.compare( y ) > 0; + } + + template< class byteT > + constexpr bool operator<=( basic_byte_view< byteT > x, basic_byte_view< byteT > y ) noexcept + { + return x.compare( y ) <= 0; + } + + template< class byteT > + constexpr bool operator<=( basic_byte_view< byteT > x, internal::identity< basic_byte_view< byteT > > y ) noexcept + { + return x.compare( y ) <= 0; + } + + template< class byteT > + constexpr bool operator<=( internal::identity< basic_byte_view< byteT > > x, basic_byte_view< byteT > y ) noexcept + { + return x.compare( y ) <= 0; + } + + template< class byteT > + constexpr bool operator>=( basic_byte_view< byteT > x, basic_byte_view< byteT > y ) noexcept + { + return x.compare( y ) >= 0; + } + + template< class byteT > + constexpr bool operator>=( basic_byte_view< byteT > x, internal::identity< basic_byte_view< byteT > > y ) noexcept + { + return x.compare( y ) >= 0; + } + + template< class byteT > + constexpr bool operator>=( internal::identity< basic_byte_view< byteT > > x, basic_byte_view< byteT > y ) noexcept + { + return x.compare( y ) >= 0; + } + + using byte_view = basic_byte_view< tao::byte >; + +} // namespace tao + +#endif diff --git a/include/tao/json/cbor.hpp b/include/tao/json/cbor.hpp new file mode 100644 index 00000000..cf5935dd --- /dev/null +++ b/include/tao/json/cbor.hpp @@ -0,0 +1,13 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_CBOR_HPP +#define TAOCPP_JSON_INCLUDE_CBOR_HPP + +#include "../json.hpp" + +#include "cbor/from_string.hpp" +#include "cbor/to_stream.hpp" +#include "cbor/to_string.hpp" + +#endif diff --git a/include/tao/json/cbor/from_string.hpp b/include/tao/json/cbor/from_string.hpp new file mode 100644 index 00000000..b5a4d112 --- /dev/null +++ b/include/tao/json/cbor/from_string.hpp @@ -0,0 +1,40 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_CBOR_FROM_STRING_HPP +#define TAOCPP_JSON_INCLUDE_CBOR_FROM_STRING_HPP + +#include + +#include "../events/to_value.hpp" +#include "../events/transformer.hpp" + +#include "../events/cbor/from_string.hpp" + +namespace tao +{ + namespace json + { + namespace cbor + { + template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > + basic_value< Traits > basic_from_string( Ts&&... ts ) + { + events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; + events::cbor::from_string( consumer, std::forward< Ts >( ts )... ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers, typename... Ts > + value from_string( Ts&&... ts ) + { + return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); + } + + } // namespace cbor + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/cbor/to_stream.hpp b/include/tao/json/cbor/to_stream.hpp new file mode 100644 index 00000000..f91f4d9b --- /dev/null +++ b/include/tao/json/cbor/to_stream.hpp @@ -0,0 +1,35 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_CBOR_TO_STREAM_HPP +#define TAOCPP_JSON_INCLUDE_CBOR_TO_STREAM_HPP + +#include + +#include "../value.hpp" + +#include "../events/from_value.hpp" +#include "../events/transformer.hpp" + +#include "../events/cbor/to_stream.hpp" + +namespace tao +{ + namespace json + { + namespace cbor + { + template< template< typename... > class... Transformers, template< typename... > class Traits > + void to_stream( std::ostream& os, const basic_value< Traits >& v ) + { + events::transformer< events::cbor::to_stream, Transformers... > consumer( os ); + events::from_value( consumer, v ); + } + + } // namespace cbor + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/cbor/to_string.hpp b/include/tao/json/cbor/to_string.hpp new file mode 100644 index 00000000..cf2eb45d --- /dev/null +++ b/include/tao/json/cbor/to_string.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_CBOR_TO_STRING_HPP +#define TAOCPP_JSON_INCLUDE_CBOR_TO_STRING_HPP + +#include + +#include "../value.hpp" + +#include "../events/from_value.hpp" +#include "../events/transformer.hpp" + +#include "../events/cbor/to_string.hpp" + +namespace tao +{ + namespace json + { + namespace cbor + { + template< template< typename... > class... Transformers, template< typename... > class Traits > + std::string to_string( const basic_value< Traits >& v ) + { + events::transformer< events::cbor::to_string, Transformers... > consumer; + events::from_value( consumer, v ); + return consumer.value(); + } + + } // namespace cbor + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/apply.hpp b/include/tao/json/events/apply.hpp new file mode 100644 index 00000000..8a772d8a --- /dev/null +++ b/include/tao/json/events/apply.hpp @@ -0,0 +1,28 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_APPLY_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_APPLY_HPP + +#include "ref.hpp" +#include "transformer.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + template< template< typename... > class... Transformer, typename Consumer > + transformer< ref< Consumer >, Transformer... > apply( Consumer& c ) noexcept( noexcept( transformer< ref< Consumer >, Transformer... >( c ) ) ) + { + return transformer< ref< Consumer >, Transformer... >( c ); + } + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/binary_to_base64.hpp b/include/tao/json/events/binary_to_base64.hpp new file mode 100644 index 00000000..a8729ead --- /dev/null +++ b/include/tao/json/events/binary_to_base64.hpp @@ -0,0 +1,34 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_BINARY_TO_BASE64_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_BINARY_TO_BASE64_HPP + +#include "../byte_view.hpp" +#include "../internal/base64.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + template< typename Consumer > + struct binary_to_base64 + : public Consumer + { + using Consumer::Consumer; + + void binary( const tao::byte_view v ) + { + Consumer::string( internal::base64( v ) ); + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/binary_to_base64url.hpp b/include/tao/json/events/binary_to_base64url.hpp new file mode 100644 index 00000000..9d46e014 --- /dev/null +++ b/include/tao/json/events/binary_to_base64url.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_BINARY_TO_BASE64URL_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_BINARY_TO_BASE64URL_HPP + +#include + +#include "../byte_view.hpp" +#include "../internal/base64url.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + template< typename Consumer > + struct binary_to_base64url + : public Consumer + { + using Consumer::Consumer; + + void binary( const tao::byte_view v ) + { + Consumer::string( internal::base64url( v ) ); + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/binary_to_exception.hpp b/include/tao/json/events/binary_to_exception.hpp new file mode 100644 index 00000000..9101ac08 --- /dev/null +++ b/include/tao/json/events/binary_to_exception.hpp @@ -0,0 +1,35 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_BINARY_TO_EXCEPTION_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_BINARY_TO_EXCEPTION_HPP + +#include + +#include "../byte_view.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + template< typename Consumer > + struct binary_to_exception + : public Consumer + { + using Consumer::Consumer; + + void binary( const tao::byte_view ) + { + throw std::runtime_error( "invalid binary data" ); + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/binary_to_hex.hpp b/include/tao/json/events/binary_to_hex.hpp new file mode 100644 index 00000000..0c85c4dc --- /dev/null +++ b/include/tao/json/events/binary_to_hex.hpp @@ -0,0 +1,34 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_BINARY_TO_HEX_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_BINARY_TO_HEX_HPP + +#include "../byte_view.hpp" +#include "../internal/hexdump.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + template< typename Consumer > + struct binary_to_hex + : public Consumer + { + using Consumer::Consumer; + + void binary( const tao::byte_view v ) + { + Consumer::string( internal::hexdump( v ) ); + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/cbor/from_string.hpp b/include/tao/json/events/cbor/from_string.hpp new file mode 100644 index 00000000..25de7275 --- /dev/null +++ b/include/tao/json/events/cbor/from_string.hpp @@ -0,0 +1,47 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_CBOR_FROM_STRING_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_CBOR_FROM_STRING_HPP + +#include "../../external/pegtl/parse.hpp" +#include "../../external/string_view.hpp" + +#include "grammar.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + namespace cbor + { + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t byte_in_line = 0 ) + { + json_pegtl::memory_input< json_pegtl::tracking_mode::LAZY, json_pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::cbor::from_string", byte, line, byte_in_line ); + json_pegtl::parse< cbor::grammar >( in, consumer ); + } + + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) + { + cbor::from_string( consumer, data, size, source.c_str(), byte, line, column ); + } + + template< typename Consumer, typename... Ts > + void from_string( Consumer& consumer, const tao::string_view data, Ts&&... ts ) + { + cbor::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); + } + + } // namespace cbor + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/cbor/grammar.hpp b/include/tao/json/events/cbor/grammar.hpp new file mode 100644 index 00000000..193af008 --- /dev/null +++ b/include/tao/json/events/cbor/grammar.hpp @@ -0,0 +1,444 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_CBOR_GRAMMAR_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_CBOR_GRAMMAR_HPP + +#include +#include +#include + +#include "major.hpp" + +#include "../../external/byte.hpp" +#include "../../external/pegtl.hpp" +#include "../../internal/endian.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + namespace cbor + { + namespace internal + { + template< typename Input > + void throw_on_empty( Input& in ) + { + if( in.empty() ) { + throw json_pegtl::parse_error( "unexpected end of input", in ); + } + } + + template< typename Input > + major peek_major( Input& in ) + { + return static_cast< major >( in.peek_byte() & major_mask ); + } + + template< typename Input > + std::uint8_t peek_minor( Input& in ) + { + return in.peek_byte() & minor_mask; + } + + template< typename Input > + std::uint8_t peek_byte_safe( Input& in ) + { + throw_on_empty( in ); + return in.peek_byte(); + } + + template< typename Input > + major peek_major_safe( Input& in ) + { + return static_cast< major >( peek_byte_safe( in ) & major_mask ); + } + + } // namespace internal + + struct data + { + using analyze_t = json_pegtl::analysis::generic< json_pegtl::analysis::rule_type::ANY >; + + template< json_pegtl::apply_mode A, + json_pegtl::rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename Consumer > + static bool match( Input& in, Consumer& consumer ) + { + // This rule never returns false unless the input is empty. + return ( !in.empty() ) && match_impl( in, consumer ); + } + + template< typename Input, typename Consumer > + static bool match_impl( Input& in, Consumer& consumer ) + { + switch( internal::peek_major( in ) ) { + case major::UNSIGNED: + return match_unsigned( in, consumer ); + case major::NEGATIVE: + return match_negative( in, consumer ); + case major::BINARY: + return match_binary( in, consumer ); + case major::STRING: + return match_string( in, consumer ); + case major::ARRAY: + return match_array( in, consumer ); + case major::OBJECT: + return match_object( in, consumer ); + case major::TAG: + return match_tag( in, consumer ); + case major::OTHER: + return match_other( in, consumer ); + } + // LCOV_EXCL_START + assert( false ); + return false; + // LCOV_EXCL_STOP + } + + template< typename Input > + static void skip_unsigned( Input& in ) + { + // Assumes in.size( 1 ) >= 1 and in.peek_byte() is the byte with major/minor. + + switch( internal::peek_minor( in ) ) { + default: + in.bump_in_this_line(); + return; + case 24: + in.bump_in_this_line( 2 ); + return; + case 25: + in.bump_in_this_line( 3 ); + return; + case 26: + in.bump_in_this_line( 5 ); + return; + case 27: + in.bump_in_this_line( 9 ); + return; + case 28: + case 29: + case 30: + case 31: + throw json_pegtl::parse_error( "unexpected minor for number or length", in ); + } + } + + template< typename Input > + static std::uint64_t read_embedded_impl( Input& in ) + { + const auto result = internal::peek_minor( in ) & minor_mask; + in.bump_in_this_line(); + return result; + } + + template< typename Unsigned, typename Input > + static std::uint64_t read_unsigned_impl( Input& in ) + { + if( in.size( sizeof( Unsigned ) ) > sizeof( Unsigned ) ) { + const Unsigned result = json::internal::be_to_h< Unsigned >( in.current() + 1 ); + in.bump_in_this_line( 1 + sizeof( Unsigned ) ); + return result; + } + throw json_pegtl::parse_error( "unexpected end of input", in ); + } + + template< typename Input > + static std::uint64_t read_unsigned( Input& in ) + { + // Assumes in.size( 1 ) >= 1 and in.peek_byte() is the byte with major/minor. + + switch( internal::peek_minor( in ) ) { + default: + return read_embedded_impl( in ); + case 24: + return read_unsigned_impl< std::uint8_t >( in ); + case 25: + return read_unsigned_impl< std::uint16_t >( in ); + case 26: + return read_unsigned_impl< std::uint32_t >( in ); + case 27: + return read_unsigned_impl< std::uint64_t >( in ); + case 28: + case 29: + case 30: + case 31: + throw json_pegtl::parse_error( "unexpected minor for number or length", in ); + } + } + + template< typename Input, typename Consumer > + static bool match_unsigned( Input& in, Consumer& consumer ) + { + consumer.number( read_unsigned( in ) ); + return true; + } + + template< typename Input, typename Consumer > + static bool match_negative( Input& in, Consumer& consumer ) + { + const auto u = read_unsigned( in ); + if( u > 9223372036854775808ull ) { + throw json_pegtl::parse_error( "negative integer overflow", in ); + } + consumer.number( std::int64_t( ~u ) ); + return true; + } + + // TODO: Check text strings and text string chunks for valid UTF-8 as per RFC 7049? + + template< typename Result, typename Input > + static Result read_string_1( Input& in ) + { + using value_t = typename Result::value_type; + const auto size = read_unsigned( in ); + if( in.size( size ) < size ) { + throw json_pegtl::parse_error( "unexpected end of input", in ); + } + const value_t* pointer = reinterpret_cast< const value_t* >( in.current() ); + Result result( pointer, size ); + in.bump_in_this_line( size ); + return result; + } + + template< typename Result, typename Input > + static Result read_string_n( Input& in, const major m ) + { + using value_t = typename Result::value_type; + + Result result; + in.bump_in_this_line(); + while( internal::peek_byte_safe( in ) != 0xff ) { + if( internal::peek_major( in ) != m ) { + throw json_pegtl::parse_error( "non-matching fragment in indefinite length string", in ); // "String" is text or byte string in RFC 7049 terminology. + } + const auto size = read_unsigned( in ); + if( in.size( size ) < size ) { + throw json_pegtl::parse_error( "unexpected end of input", in ); + } + const value_t* pointer = reinterpret_cast< const value_t* >( in.current() ); + result.insert( result.end(), pointer, pointer + size ); + in.bump_in_this_line( size ); + } + in.bump_in_this_line(); + return result; + } + + template< typename Input, typename Consumer > + static bool match_string( Input& in, Consumer& consumer ) + { + // Assumes in.size( 1 ) >= 1 and in.peek_byte() is the byte with major/minor. + + if( internal::peek_minor( in ) != minor_mask ) { + consumer.string( read_string_1< tao::string_view >( in ) ); + } + else { + consumer.string( read_string_n< std::string >( in, major::STRING ) ); + } + return true; + } + + template< typename Input, typename Consumer > + static bool match_binary( Input& in, Consumer& consumer ) + { + // Assumes in.size( 1 ) >= 1 and in.peek_byte() is the byte with major/minor. + + if ( internal::peek_minor( in ) != minor_mask ) { + consumer.binary( read_string_1< tao::byte_view >( in ) ); + } + else { + consumer.binary( read_string_n< std::vector< tao::byte > >( in, major::BINARY ) ); + } + return true; + } + + template< typename Input, typename Consumer > + static void match_array_1( Input& in, Consumer& consumer ) + { + const auto size = read_unsigned( in ); + consumer.begin_array( size ); + for( std::uint64_t i = 0; i < size; ++i ) { + internal::throw_on_empty( in ); + match_impl( in, consumer ); + consumer.element(); + } + consumer.end_array( size ); + } + + template< typename Input, typename Consumer > + static void match_array_n( Input& in, Consumer& consumer ) + { + in.bump_in_this_line(); + consumer.begin_array(); + while( internal::peek_byte_safe( in ) != 0xff ) { + match_impl( in, consumer ); + consumer.element(); + } + in.bump_in_this_line(); + consumer.end_array(); + } + + template< typename Input, typename Consumer > + static bool match_array( Input& in, Consumer& consumer ) + { + if( internal::peek_minor( in ) != minor_mask ) { + match_array_1( in, consumer ); + } + else { + match_array_n( in, consumer ); + } + return true; + } + + template< typename Input, typename Consumer > + static void match_object_1( Input& in, Consumer& consumer ) + { + const auto size = read_unsigned( in ); + consumer.begin_object( size ); + for( std::uint64_t i = 0; i < size; ++i ) { + if( internal::peek_major_safe( in ) != major::STRING ) { + throw json_pegtl::parse_error( "non-string object key", in ); + } + internal::throw_on_empty( in ); + if ( internal::peek_minor( in ) != minor_mask ) { + consumer.key( read_string_1< tao::string_view >( in ) ); + } + else { + consumer.key( read_string_n< std::string >( in, major::STRING ) ); + } + internal::throw_on_empty( in ); + match_impl( in, consumer ); + consumer.member(); + } + consumer.end_object( size ); + } + + template< typename Input, typename Consumer > + static void match_object_n( Input& in, Consumer& consumer ) + { + in.bump_in_this_line(); + consumer.begin_object(); + while( internal::peek_byte_safe( in ) != 0xff ) { + if( internal::peek_major( in ) != major::STRING ) { + throw json_pegtl::parse_error( "non-string object key", in ); + } + if ( internal::peek_minor( in ) != minor_mask ) { + consumer.key( read_string_1< tao::string_view >( in ) ); + } + else { + consumer.key( read_string_n< std::string >( in, major::STRING ) ); + } + internal::throw_on_empty( in ); + match_impl( in, consumer ); + consumer.member(); + } + in.bump_in_this_line(); + consumer.end_object(); + } + + template< typename Input, typename Consumer > + static bool match_object( Input& in, Consumer& consumer ) + { + if( internal::peek_minor( in ) != minor_mask ) { + match_object_1( in, consumer ); + } + else { + match_object_n( in, consumer ); + } + return true; + } + + template< typename Input, typename Consumer > + static bool match_tag( Input& in, Consumer& ) + { + skip_unsigned( in ); + return true; + } + + template< typename Floating, typename Input > + static double read_floating_impl( Input& in ) + { + if( in.size( sizeof( Floating ) ) >= 1 + sizeof( Floating ) ) { + const Floating result = json::internal::be_to_h< Floating >( in.current() + 1 ); + in.bump_in_this_line( 1 + sizeof( Floating ) ); + return result; + } + throw json_pegtl::parse_error( "unexpected end of input", in ); + } + + template< typename Input > + static double read_floating_half_impl( Input& in ) + { + if( in.size( 3 ) < 3 ) { + throw json_pegtl::parse_error( "unexpected end of input", in ); + } + const int half = ( in.peek_byte( 1 ) << 8 ) + in.peek_byte( 2 ); + const int exp = ( half >> 10 ) & 0x1f; + const int mant = half & 0x3ff; + + double val; + if( exp == 0 ) { + val = std::ldexp( mant, -24 ); + } + else if( exp != 31 ) { + val = std::ldexp( mant + 1024, exp - 25 ); + } + else { + val = ( mant == 0 ) ? INFINITY : NAN; + } + in.bump_in_this_line( 3 ); + return half & 0x8000 ? -val : val; + } + + template< typename Input, typename Consumer > + static bool match_other( Input& in, Consumer& consumer ) + { + switch( internal::peek_minor( in ) ) { + case 20: + consumer.boolean( false ); + in.bump_in_this_line(); + return true; + case 21: + consumer.boolean( true ); + in.bump_in_this_line(); + return true; + case 22: + consumer.null(); + in.bump_in_this_line(); + return true; + case 25: + consumer.number( read_floating_half_impl( in ) ); + return true; + case 26: + consumer.number( read_floating_impl< float >( in ) ); + return true; + case 27: + consumer.number( read_floating_impl< double >( in ) ); + return true; + case 24: + default: + throw json_pegtl::parse_error( "unsupported minor for major 7", in ); + } + } + }; + + struct grammar : json_pegtl::must< data, json_pegtl::eof > + { + }; + + } // namespace cbor + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/cbor/major.hpp b/include/tao/json/events/cbor/major.hpp new file mode 100644 index 00000000..afe5f511 --- /dev/null +++ b/include/tao/json/events/cbor/major.hpp @@ -0,0 +1,40 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_CBOR_MAJOR_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_CBOR_MAJOR_HPP + +#include + +namespace tao +{ + namespace json + { + namespace events + { + namespace cbor + { + enum class major : std::uint8_t + { + UNSIGNED = 0, + NEGATIVE = 0x20, + BINARY = 0x40, + STRING = 0x60, + ARRAY = 0x80, + OBJECT = 0xa0, + TAG = 0xc0, + OTHER = 0xe0 + }; + + static constexpr std::uint8_t major_mask = 0xe0; + static constexpr std::uint8_t minor_mask = 0x1f; + + } // namespace cbor + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/cbor/to_stream.hpp b/include/tao/json/events/cbor/to_stream.hpp new file mode 100644 index 00000000..b67b0d10 --- /dev/null +++ b/include/tao/json/events/cbor/to_stream.hpp @@ -0,0 +1,166 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_CBOR_TO_STREAM_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_CBOR_TO_STREAM_HPP + +#include +#include +#include + +#include "major.hpp" + +#include "../../internal/endian.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + namespace cbor + { + class to_stream + { + private: + std::ostream& os; + + public: + explicit to_stream( std::ostream& in_os ) noexcept + : os( in_os ) + { + } + + void null() + { + os.put( char( std::uint8_t( major::OTHER ) + 22 ) ); + } + + void boolean( const bool v ) + { + os.put( char( std::uint8_t( major::OTHER ) + 20 + std::uint8_t( v ) ) ); + } + + void number( const major m, const std::uint64_t v ) + { + if( v < 24 ) { + os.put( char( std::uint8_t( m ) + v ) ); + } + else if( v < 256 ) { + os.put( char( std::uint8_t( m ) + 24 ) ); + os.put( char( v ) ); + } + else if( v < 65536 ) { + os.put( char( std::uint8_t( m ) + 25 ) ); + const std::uint16_t x = json::internal::h_to_be( std::uint16_t( v ) ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else if( v < 4294967296ull ) { + os.put( char( std::uint8_t( m ) + 26 ) ); + const std::uint32_t x = json::internal::h_to_be( std::uint32_t( v ) ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else { + os.put( char( std::uint8_t( m ) + 27 ) ); + const std::uint64_t x = json::internal::h_to_be( v ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + } + + void number( const std::int64_t v ) + { + if( v >= 0 ) { + number( major::UNSIGNED, v ); + } + else { + number( major::NEGATIVE, -( v + 1 ) ); + } + } + + void number( const std::uint64_t v ) + { + number( major::UNSIGNED, v ); + } + + void number( const double v ) + { + std::uint64_t n; + std::memcpy( &n, &v, sizeof( n ) ); + n = json::internal::h_to_be( n ); + os.put( char( std::uint8_t( major::OTHER ) + 27 ) ); + os.write( reinterpret_cast< const char* >( &n ), sizeof( n ) ); + } + + void string( const tao::string_view v ) + { + number( major::STRING, v.size() ); + os.write( v.data(), v.size() ); + } + + void binary( const tao::byte_view v ) + { + number( major::BINARY, v.size() ); + os.write( reinterpret_cast< const char* >( v.data() ), v.size() ); + } + + void begin_array() + { + os.put( char( std::uint8_t( major::ARRAY ) + minor_mask ) ); + } + + void begin_array( const std::size_t size ) + { + number( major::ARRAY, size ); + } + + void element() noexcept + { + } + + void end_array() + { + os.put( char( 0xff ) ); + } + + void end_array( const std::size_t ) noexcept + { + } + + void begin_object() + { + os.put( char( std::uint8_t( major::OBJECT ) + minor_mask ) ); + } + + void begin_object( const std::size_t size ) + { + number( major::OBJECT, size ); + } + + void key( const tao::string_view v ) + { + string( v ); + } + + void member() noexcept + { + } + + void end_object() + { + os.put( char( 0xff ) ); + } + + void end_object( const std::size_t ) noexcept + { + } + }; + + } // namespace cbor + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/cbor/to_string.hpp b/include/tao/json/events/cbor/to_string.hpp new file mode 100644 index 00000000..0bea1cf2 --- /dev/null +++ b/include/tao/json/events/cbor/to_string.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JSON_CBOR_TO_STRING_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_JSON_CBOR_TO_STRING_HPP + +#include + +#include "to_stream.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + namespace cbor + { + struct to_string + : public to_stream + { + std::ostringstream oss; + + to_string() + : to_stream( oss ) + { + } + + std::string value() const + { + return oss.str(); + } + }; + + } // namespace cbor + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/compare.hpp b/include/tao/json/events/compare.hpp new file mode 100644 index 00000000..7ea73d15 --- /dev/null +++ b/include/tao/json/events/compare.hpp @@ -0,0 +1,259 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_COMPARE_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_COMPARE_HPP + +#include +#include +#include +#include +#include + +#include "../value.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + template< template< typename... > class Traits > + class events_compare + { + protected: + std::vector< const basic_value< Traits >* > m_current; + std::vector< std::size_t > m_array_index; + // TODO: use std::unordered_set? or even std::vector!? + std::vector< std::set< const basic_value< Traits >* > > m_object_keys; + bool m_match = true; + + public: + events_compare() = default; + + events_compare( const events_compare& ) = delete; + events_compare( events_compare&& ) = delete; + + void operator=( const events_compare& ) = delete; + void operator=( events_compare&& ) = delete; + + void reset() noexcept + { + m_current.clear(); + m_array_index.clear(); + m_object_keys.clear(); + m_match = true; + } + + static const basic_value< Traits >* skip_pointer( const basic_value< Traits >* p ) noexcept + { + while( p && p->is_raw_ptr() ) { + p = p->unsafe_get_raw_ptr(); + } + return p; + } + + void push( const basic_value< Traits >* p ) + { + m_current.push_back( skip_pointer( p ) ); + } + + bool match() const noexcept + { + return m_match; + } + + const basic_value< Traits >& current() const noexcept + { + return *m_current.back(); + } + + void null() noexcept + { + m_match = m_match && ( m_current.back() != nullptr ) && ( current().is_null() ); + } + + void boolean( const bool v ) noexcept + { + m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); + } + + void number( const std::int64_t v ) noexcept + { + m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); + } + + void number( const std::uint64_t v ) noexcept + { + m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); + } + + void number( const double v ) noexcept + { + m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); + } + + void string( const tao::string_view v ) noexcept + { + m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); + } + + void binary( const tao::byte_view v ) noexcept + { + m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); + } + + void begin_array( const std::size_t = 0 ) + { + if( m_current.back() == nullptr ) { + m_match = false; + m_current.push_back( nullptr ); + } + else { + const auto& a = current(); + if( !a.is_array() ) { + m_match = false; + m_current.push_back( nullptr ); + } + else if( !a.unsafe_get_array().empty() ) { + push( &a.unsafe_get_array().front() ); + } + else { + m_current.push_back( nullptr ); + } + } + m_array_index.push_back( 0 ); + } + + void element() noexcept + { + const auto i = ++m_array_index.back(); + if( m_match ) { + if( m_current.back() != nullptr ) { + const auto& a = ( *( m_current.end() - 2 ) )->unsafe_get_array(); + if( i < a.size() ) { + m_current.back() = skip_pointer( &a[ i ] ); + } + else { + m_current.back() = nullptr; + } + } + } + } + + void end_array( const std::size_t = 0 ) noexcept + { + m_current.pop_back(); + if( m_match ) { + if( m_array_index.back() != current().unsafe_get_array().size() ) { + m_match = false; + } + } + m_array_index.pop_back(); + } + + void begin_object( const std::size_t = 0 ) + { + if( m_current.back() == nullptr ) { + m_match = false; + } + else { + const auto& o = current(); + if( !o.is_object() ) { + m_match = false; + } + } + m_object_keys.emplace_back(); + } + + void key( const std::string& v ) + { + if( !m_match ) { + m_current.push_back( nullptr ); + } + else if( const auto* p = current().unsafe_find( v ) ) { + if( !m_object_keys.back().insert( p ).second ) { + m_match = false; // duplicate key found! -> fail + m_current.push_back( nullptr ); + } + else { + push( p ); + } + } + else { + m_match = false; + m_current.push_back( nullptr ); + } + } + + void key( const tao::string_view v ) + { + key( std::string( v.data(), v.size() ) ); + } + + void key( const char* v ) + { + key( std::string( v ) ); + } + + void member() noexcept + { + m_current.pop_back(); + } + + void end_object( const std::size_t = 0 ) noexcept + { + if( m_match ) { + if( m_object_keys.back().size() != current().unsafe_get_object().size() ) { + m_match = false; + } + } + m_object_keys.pop_back(); + } + }; + + } // namespace internal + + namespace events + { + // Events consumer that compares against a JSON Value. + + template< template< typename... > class Traits > + class basic_compare + : public internal::events_compare< Traits > + { + private: + const basic_value< Traits > m_value; + + public: + explicit basic_compare( const basic_value< Traits >& v ) + : m_value( v ) + { + reset(); + } + + explicit basic_compare( basic_value< Traits >&& v ) + : m_value( std::move( v ) ) + { + reset(); + } + + basic_compare( const basic_compare& ) = delete; + void operator=( const basic_compare& ) = delete; + + void reset() + { + internal::events_compare< Traits >::reset(); + internal::events_compare< Traits >::push( &m_value ); + } + }; + + using compare = basic_compare< traits >; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/debug.hpp b/include/tao/json/events/debug.hpp new file mode 100644 index 00000000..cd7c8e6d --- /dev/null +++ b/include/tao/json/events/debug.hpp @@ -0,0 +1,153 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_DEBUG_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_DEBUG_HPP + +#include +#include +#include +#include +#include + +#include "../byte_view.hpp" +#include "../external/double.hpp" + +#include "../internal/escape.hpp" +#include "../internal/hexdump.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + // Events consumer that writes the events to a stream for debug purposes. + + class debug + { + private: + std::ostream& os; + + public: + explicit debug( std::ostream& in_os ) noexcept + : os( in_os ) + { + } + + void null() + { + os << "null\n"; + } + + void boolean( const bool v ) + { + if( v ) { + os << "boolean: true\n"; + } + else { + os << "boolean: false\n"; + } + } + + void number( const std::int64_t v ) + { + os << "std::int64_t: " << v << '\n'; + } + + void number( const std::uint64_t v ) + { + os << "std::uint64_t: " << v << '\n'; + } + + void number( const double v ) + { + os << "double: "; + if( !std::isfinite( v ) ) { + os << v; + } + else { + json_double_conversion::Dtostr( os, v ); + } + os << '\n'; + } + + void string( const tao::string_view v ) + { + os << "string: \""; + internal::escape( os, v ); + os << "\"\n"; + } + + void binary( const tao::byte_view v ) + { + os << "binary: "; + internal::hexdump( os, v ); + os << '\n'; + } + + void begin_array() + { + os << "begin array\n"; + } + + void begin_array( const std::size_t size ) + { + os << "begin array " << size << '\n'; + } + + void element() + { + os << "element\n"; + } + + void end_array() + { + os << "end array\n"; + } + + void end_array( const std::size_t size ) + { + os << "end array " << size << '\n'; + } + + void begin_object() + { + os << "begin object\n"; + } + + void begin_object( const std::size_t size ) + { + os << "begin object " << size << '\n'; + } + + void key( const tao::string_view v ) + { + os << "key: \""; + internal::escape( os, v ); + os << "\"\n"; + } + + void member() + { + os << "member\n"; + } + + void end_object() + { + os << "end object\n"; + } + + void end_object( const std::size_t size ) + { + os << "end object " << size << '\n'; + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/discard.hpp b/include/tao/json/events/discard.hpp new file mode 100644 index 00000000..a12026b2 --- /dev/null +++ b/include/tao/json/events/discard.hpp @@ -0,0 +1,88 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_DISCARD_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_DISCARD_HPP + +#include +#include +#include + +#include "../byte_view.hpp" + +#include "../external/string_view.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + // Events consumer that discards events. + + struct discard + { + void null() noexcept + { + } + + void boolean( const bool ) noexcept + { + } + + void number( const std::int64_t ) noexcept + { + } + + void number( const std::uint64_t ) noexcept + { + } + + void number( const double ) noexcept + { + } + + void string( const tao::string_view ) noexcept + { + } + + void binary( const tao::byte_view ) noexcept + { + } + + void begin_array( const std::size_t = 0 ) noexcept + { + } + + void element() noexcept + { + } + + void end_array( const std::size_t = 0 ) noexcept + { + } + + void begin_object( const std::size_t = 0 ) noexcept + { + } + + void key( const tao::string_view ) noexcept + { + } + + void member() noexcept + { + } + + void end_object( const std::size_t = 0 ) noexcept + { + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/from_stream.hpp b/include/tao/json/events/from_stream.hpp new file mode 100644 index 00000000..273a3152 --- /dev/null +++ b/include/tao/json/events/from_stream.hpp @@ -0,0 +1,41 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_FROM_STREAM_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_FROM_STREAM_HPP + +#include + +#include "../external/pegtl/internal/istream_reader.hpp" +#include "../external/pegtl/parse.hpp" + +#include "../internal/action.hpp" +#include "../internal/control.hpp" +#include "../internal/grammar.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + template< typename Consumer > + void from_stream( Consumer& consumer, std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) + { + json_pegtl::istream_input<> in( stream, maximum_buffer_size, source ? source : "tao::json::events::from_stream" ); + json_pegtl::parse< internal::grammar, internal::action, internal::control >( in, consumer ); + } + + template< typename Consumer > + void from_stream( Consumer& consumer, std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) + { + events::from_stream( consumer, stream, source.c_str(), maximum_buffer_size ); + } + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/from_string.hpp b/include/tao/json/events/from_string.hpp new file mode 100644 index 00000000..70517ac7 --- /dev/null +++ b/include/tao/json/events/from_string.hpp @@ -0,0 +1,47 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_FROM_STRING_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_FROM_STRING_HPP + +#include "../external/pegtl/parse.hpp" +#include "../external/string_view.hpp" + +#include "../internal/action.hpp" +#include "../internal/control.hpp" +#include "../internal/grammar.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + // Events producer to parse a JSON string representation. + + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) + { + json_pegtl::memory_input< json_pegtl::tracking_mode::LAZY, json_pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::events::from_string", byte, line, column ); + json_pegtl::parse< internal::grammar, internal::action, internal::control >( in, consumer ); + } + + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) + { + events::from_string( consumer, data, size, source.c_str(), byte, line, column ); + } + + template< typename Consumer, typename... Ts > + void from_string( Consumer& consumer, const tao::string_view data, Ts&&... ts ) + { + events::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); + } + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/from_value.hpp b/include/tao/json/events/from_value.hpp new file mode 100644 index 00000000..77cb9860 --- /dev/null +++ b/include/tao/json/events/from_value.hpp @@ -0,0 +1,194 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_FROM_VALUE_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_FROM_VALUE_HPP + +#include + +#include "../value.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + // Events producer to generate events from a JSON Value. + + template< typename Consumer, template< typename... > class Traits > + void from_value( Consumer& consumer, const basic_value< Traits >& v ) + { + switch( v.type() ) { + case type::UNINITIALIZED: + throw std::logic_error( "unable to produce events from uninitialized values" ); + + case type::DISCARDED: + throw std::logic_error( "unable to produce events from discarded values" ); + + case type::DESTROYED: + throw std::logic_error( "unable to produce events from destroyed values" ); + + case type::NULL_: + consumer.null(); + return; + + case type::BOOLEAN: + consumer.boolean( v.unsafe_get_boolean() ); + return; + + case type::SIGNED: + consumer.number( v.unsafe_get_signed() ); + return; + + case type::UNSIGNED: + consumer.number( v.unsafe_get_unsigned() ); + return; + + case type::DOUBLE: + consumer.number( v.unsafe_get_double() ); + return; + + case type::STRING: + consumer.string( v.unsafe_get_string() ); + return; + + case type::STRING_VIEW: + consumer.string( v.unsafe_get_string_view() ); + return; + + case type::BINARY: + consumer.binary( v.unsafe_get_binary() ); + return; + + case type::BINARY_VIEW: + consumer.binary( v.unsafe_get_binary_view() ); + return; + + case type::ARRAY: { + const auto& a = v.unsafe_get_array(); + const auto s = a.size(); + consumer.begin_array( s ); + for( const auto& e : a ) { + events::from_value( consumer, e ); + consumer.element(); + } + consumer.end_array( s ); + return; + } + + case type::OBJECT: { + const auto& o = v.unsafe_get_object(); + const auto s = o.size(); + consumer.begin_object( s ); + for( const auto& e : o ) { + consumer.key( e.first ); + events::from_value( consumer, e.second ); + consumer.member(); + } + consumer.end_object( s ); + return; + } + + case type::RAW_PTR: + if( const basic_value< Traits >* p = v.unsafe_get_raw_ptr() ) { + events::from_value( consumer, *p ); + } + else { + consumer.null(); + } + return; + } + throw std::logic_error( "invalid value for tao::json::type" ); // LCOV_EXCL_LINE + } + + // Events producer to generate events from an rvalue JSON value. + // Note: Strings from the source might be moved to the consumer. + + template< typename Consumer, template< typename... > class Traits > + void from_value( Consumer& consumer, basic_value< Traits >&& v ) + { + switch( v.type() ) { + case type::UNINITIALIZED: + throw std::logic_error( "unable to produce events from uninitialized values" ); + + case type::DISCARDED: + throw std::logic_error( "unable to produce events from discarded values" ); + + case type::DESTROYED: + throw std::logic_error( "unable to produce events from destroyed values" ); + + case type::NULL_: + consumer.null(); + return; + + case type::BOOLEAN: + consumer.boolean( v.unsafe_get_boolean() ); + return; + + case type::SIGNED: + consumer.number( v.unsafe_get_signed() ); + return; + + case type::UNSIGNED: + consumer.number( v.unsafe_get_unsigned() ); + return; + + case type::DOUBLE: + consumer.number( v.unsafe_get_double() ); + return; + + case type::STRING: + consumer.string( std::move( v.unsafe_get_string() ) ); + return; + + case type::STRING_VIEW: + consumer.string( v.unsafe_get_string_view() ); + return; + + case type::BINARY: + consumer.binary( std::move( v.unsafe_get_binary() ) ); + return; + + case type::BINARY_VIEW: + consumer.binary( v.unsafe_get_binary_view() ); + return; + + case type::ARRAY: + consumer.begin_array( v.unsafe_get_array().size() ); + for( auto&& e : v.unsafe_get_array() ) { + events::from_value( consumer, std::move( e ) ); + consumer.element(); + } + consumer.end_array( v.unsafe_get_array().size() ); + return; + + case type::OBJECT: + consumer.begin_object( v.unsafe_get_object().size() ); + for( auto&& e : v.unsafe_get_object() ) { + consumer.key( e.first ); + events::from_value( consumer, std::move( e.second ) ); + consumer.member(); + } + consumer.end_object( v.unsafe_get_object().size() ); + return; + + case type::RAW_PTR: + if( const basic_value< Traits >* p = v.unsafe_get_raw_ptr() ) { + events::from_value( consumer, *p ); + } + else { + consumer.null(); + } + return; + } + throw std::logic_error( "invalid value for tao::json::type" ); // LCOV_EXCL_LINE + } + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/hash.hpp b/include/tao/json/events/hash.hpp new file mode 100644 index 00000000..8907c963 --- /dev/null +++ b/include/tao/json/events/hash.hpp @@ -0,0 +1,176 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_HASH_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_HASH_HPP + +#include +#include +#include +#include +#include +#include +#include + +#include "../internal/sha256.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + // Events consumer that calculates an SHA-256 hash. + + class hash + { + private: + std::vector< std::unique_ptr< internal::sha256 > > m_digests; + std::vector< std::string > m_keys; + std::vector< std::map< std::string, std::string > > m_properties; + + void push() + { + m_digests.emplace_back( new internal::sha256 ); + } + + public: + hash() + { + push(); + } + + hash( const hash& ) = delete; + hash( hash&& ) = delete; + + void operator=( const hash& ) = delete; + void operator=( hash&& ) = delete; + + std::string value() const + { + return m_digests.back()->get(); + } + + void reset() + { + m_digests.back()->reset(); + } + + void null() + { + m_digests.back()->feed( 'n' ); + } + + void boolean( const bool v ) + { + m_digests.back()->feed( v ? 't' : 'f' ); + } + + void number( const std::int64_t v ) + { + if( v >= 0 ) { + number( static_cast< std::uint64_t >( v ) ); + } + else { + m_digests.back()->feed( 'i' ); + m_digests.back()->feed( &v, sizeof( v ) ); + } + } + + void number( const std::uint64_t v ) + { + m_digests.back()->feed( 'u' ); + m_digests.back()->feed( &v, sizeof( v ) ); + } + + void number( const double v ) + { + if( v >= 0 ) { + const std::uint64_t u = v; + if( u == v ) { + number( u ); + return; + } + } + const std::int64_t i = v; + if( i == v ) { + number( i ); + return; + } + m_digests.back()->feed( 'd' ); + m_digests.back()->feed( &v, sizeof( v ) ); + } + + void string( const tao::string_view v ) + { + m_digests.back()->feed( 's' ); + const auto s = v.size(); + m_digests.back()->feed( &s, sizeof( s ) ); + m_digests.back()->feed( v.data(), v.size() ); + } + + void binary( const tao::byte_view v ) + { + m_digests.back()->feed( 'x' ); + const auto s = v.size(); + m_digests.back()->feed( &s, sizeof( s ) ); + m_digests.back()->feed( v.data(), v.size() ); + } + + void begin_array( const std::size_t = 0 ) + { + m_digests.back()->feed( '[' ); + } + + void element() + { + } + + void end_array( const std::size_t = 0 ) + { + m_digests.back()->feed( ']' ); + } + + void begin_object( const std::size_t = 0 ) + { + m_digests.back()->feed( '{' ); + m_properties.emplace_back(); + push(); + } + + void key( const tao::string_view v ) + { + m_digests.back()->feed( v.data(), v.size() ); + m_keys.emplace_back( m_digests.back()->get() ); + if( m_properties.back().count( m_keys.back() ) != 0 ) { + throw std::runtime_error( "duplicate JSON object key: " + std::string( v.data(), v.size() ) ); + } + m_digests.back()->reset(); + } + + void member() + { + m_properties.back().emplace( std::move( m_keys.back() ), m_digests.back()->get() ); + m_keys.pop_back(); + m_digests.back()->reset(); + } + + void end_object( const std::size_t = 0 ) + { + m_digests.pop_back(); + for( const auto& e : m_properties.back() ) { + m_digests.back()->feed( e.first ); + m_digests.back()->feed( e.second ); + } + m_properties.pop_back(); + m_digests.back()->feed( '}' ); + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/jaxn/from_stream.hpp b/include/tao/json/events/jaxn/from_stream.hpp new file mode 100644 index 00000000..444da8b0 --- /dev/null +++ b/include/tao/json/events/jaxn/from_stream.hpp @@ -0,0 +1,45 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JAXN_FROM_STREAM_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_JAXN_FROM_STREAM_HPP + +#include + +#include "../../external/pegtl/internal/istream_reader.hpp" +#include "../../external/pegtl/parse.hpp" + +#include "../../internal/jaxn/action.hpp" +#include "../../internal/jaxn/control.hpp" +#include "../../internal/jaxn/grammar.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + namespace jaxn + { + template< typename Consumer > + void from_stream( Consumer& consumer, std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) + { + json_pegtl::istream_input<> in( stream, maximum_buffer_size, source ? source : "tao::json::events::jaxn::from_stream" ); + json_pegtl::parse< internal::jaxn::grammar, internal::jaxn::action, internal::jaxn::control >( in, consumer ); + } + + template< typename Consumer > + void from_stream( Consumer& consumer, std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) + { + jaxn::from_stream( consumer, stream, source.c_str(), maximum_buffer_size ); + } + + } // namespace jaxn + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/jaxn/from_string.hpp b/include/tao/json/events/jaxn/from_string.hpp new file mode 100644 index 00000000..c91941cc --- /dev/null +++ b/include/tao/json/events/jaxn/from_string.hpp @@ -0,0 +1,51 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JAXN_FROM_STRING_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_JAXN_FROM_STRING_HPP + +#include "../../external/pegtl/parse.hpp" +#include "../../external/string_view.hpp" + +#include "../../internal/jaxn/action.hpp" +#include "../../internal/jaxn/control.hpp" +#include "../../internal/jaxn/grammar.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + namespace jaxn + { + // Events producer to parse a JAXN string representation. + + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) + { + json_pegtl::memory_input< json_pegtl::tracking_mode::LAZY, json_pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::events::jaxn::from_string", byte, line, column ); + json_pegtl::parse< internal::jaxn::grammar, internal::jaxn::action, internal::jaxn::control >( in, consumer ); + } + + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) + { + jaxn::from_string( consumer, data, size, source.c_str(), byte, line, column ); + } + + template< typename Consumer, typename... Ts > + void from_string( Consumer& consumer, const tao::string_view data, Ts&&... ts ) + { + jaxn::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); + } + + } // namespace jaxn + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/jaxn/parse_file.hpp b/include/tao/json/events/jaxn/parse_file.hpp new file mode 100644 index 00000000..ffc12708 --- /dev/null +++ b/include/tao/json/events/jaxn/parse_file.hpp @@ -0,0 +1,40 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JAXN_PARSE_FILE_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_JAXN_PARSE_FILE_HPP + +#include + +#include "../../internal/jaxn/action.hpp" +#include "../../internal/jaxn/control.hpp" +#include "../../internal/jaxn/grammar.hpp" + +#include "../../external/pegtl/file_input.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + namespace jaxn + { + // Events producer to parse a file containing a JAXN string representation. + + template< typename T, typename Consumer > + void parse_file( Consumer& consumer, T&& filename ) + { + json_pegtl::file_input< json_pegtl::tracking_mode::LAZY > in( std::forward< T >( filename ) ); + json_pegtl::parse< internal::jaxn::grammar, internal::jaxn::action, internal::jaxn::control >( in, consumer ); + } + + } // namespace jaxn + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/jaxn/to_pretty_stream.hpp b/include/tao/json/events/jaxn/to_pretty_stream.hpp new file mode 100644 index 00000000..66100e74 --- /dev/null +++ b/include/tao/json/events/jaxn/to_pretty_stream.hpp @@ -0,0 +1,76 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JAXN_TO_PRETTY_STREAM_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_JAXN_TO_PRETTY_STREAM_HPP + +#include "../../internal/hexdump.hpp" +#include "../../jaxn/is_identifier.hpp" +#include "../to_pretty_stream.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + namespace jaxn + { + // Events consumer to build a JAXN string representation. + + struct to_pretty_stream : events::to_pretty_stream + { + using events::to_pretty_stream::to_pretty_stream; + + using events::to_pretty_stream::number; + + void number( const double v ) + { + next(); + if( !std::isfinite( v ) ) { + if( std::isnan( v ) ) { + os.write( "NaN", 3 ); + } + else if( v < 0 ) { + os.write( "-Infinity", 9 ); + } + else { + os.write( "Infinity", 8 ); + } + } + else { + json_double_conversion::Dtostr( os, v ); + } + } + + void key( const tao::string_view v ) + { + if( json::jaxn::is_identifier( v ) ) { + next(); + os.write( v.data(), v.size() ); + } + else { + string( v ); + } + os.write( ": ", 2 ); + first = true; + after_key = true; + } + + void binary( const tao::byte_view v ) + { + next(); + os.put( '$' ); + internal::hexdump( os, v ); + } + }; + + } // namespace jaxn + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/jaxn/to_stream.hpp b/include/tao/json/events/jaxn/to_stream.hpp new file mode 100644 index 00000000..bf2c33c4 --- /dev/null +++ b/include/tao/json/events/jaxn/to_stream.hpp @@ -0,0 +1,75 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JAXN_TO_STREAM_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_JAXN_TO_STREAM_HPP + +#include "../../internal/hexdump.hpp" +#include "../../jaxn/is_identifier.hpp" +#include "../to_stream.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + namespace jaxn + { + // Events consumer to build a JAXN string representation. + + struct to_stream : events::to_stream + { + using events::to_stream::to_stream; + + using events::to_stream::number; + + void number( const double v ) + { + next(); + if( !std::isfinite( v ) ) { + if( std::isnan( v ) ) { + os << "NaN"; + } + else if( v < 0 ) { + os << "-Infinity"; + } + else { + os << "Infinity"; + } + } + else { + json_double_conversion::Dtostr( os, v ); + } + } + + void key( const tao::string_view v ) + { + if( json::jaxn::is_identifier( v ) ) { + next(); + os.write( v.data(), v.size() ); + } + else { + string( v ); + } + os.put( ':' ); + first = true; + } + + void binary( const tao::byte_view v ) + { + next(); + os.put( '$' ); + internal::hexdump( os, v ); + } + }; + + } // namespace jaxn + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/key_camel_case_to_snake_case.hpp b/include/tao/json/events/key_camel_case_to_snake_case.hpp new file mode 100644 index 00000000..5b3a244f --- /dev/null +++ b/include/tao/json/events/key_camel_case_to_snake_case.hpp @@ -0,0 +1,71 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_KEY_CAMEL_CASE_TO_SNAKE_CASE_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_KEY_CAMEL_CASE_TO_SNAKE_CASE_HPP + +#include +#include + +#include "../external/string_view.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + template< typename Consumer > + struct key_camel_case_to_snake_case + : public Consumer + { + using Consumer::Consumer; + + void key( const tao::string_view v ) + { + std::string t; + bool last_upper = false; + for( const auto c : v ) { + if( std::isupper( c ) ) { + last_upper = true; + t += c; + } + else { + if( last_upper ) { + const char o = t.back(); + t.pop_back(); + if( !t.empty() && t.back() != '_' ) { + t += '_'; + } + t += o; + } + last_upper = false; + t += c; + } + } + std::string r; + bool last_lower = false; + for( const auto c : t ) { + if( std::isupper( c ) ) { + if( last_lower ) { + r += '_'; + } + last_lower = false; + r += std::tolower( c ); + } + else { + last_lower = std::islower( c ); + r += c; + } + } + Consumer::key( std::move( r ) ); + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/key_snake_case_to_camel_case.hpp b/include/tao/json/events/key_snake_case_to_camel_case.hpp new file mode 100644 index 00000000..6a659305 --- /dev/null +++ b/include/tao/json/events/key_snake_case_to_camel_case.hpp @@ -0,0 +1,66 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_KEY_SNAKE_CASE_TO_CAMEL_CASE_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_KEY_SNAKE_CASE_TO_CAMEL_CASE_HPP + +#include +#include + +#include "../external/string_view.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + template< typename Consumer > + struct key_snake_case_to_camel_case + : public Consumer + { + using Consumer::Consumer; + + void key( const tao::string_view v ) + { + std::string r; + r.reserve( v.size() ); + bool active = false; + for( const auto c : v ) { + if( active ) { + if( c == '_' ) { + r += c; + } + else if( std::isupper( c ) ) { + r += '_'; + r += c; + active = false; + } + else { + r += std::toupper( c ); + active = false; + } + } + else { + if( c == '_' ) { + active = true; + } + else { + r += c; + } + } + } + if( active ) { + r += '_'; + } + Consumer::key( std::move( r ) ); + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/msgpack/from_string.hpp b/include/tao/json/events/msgpack/from_string.hpp new file mode 100644 index 00000000..b670c62f --- /dev/null +++ b/include/tao/json/events/msgpack/from_string.hpp @@ -0,0 +1,46 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_MSGPACK_FROM_STRING_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_MSGPACK_FROM_STRING_HPP + +#include "../../external/pegtl/parse.hpp" + +#include "grammar.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + namespace msgpack + { + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t byte_in_line = 0 ) + { + json_pegtl::memory_input< json_pegtl::tracking_mode::LAZY, json_pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::msgpack::from_string", byte, line, byte_in_line ); + json_pegtl::parse< msgpack::grammar >( in, consumer ); + } + + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t byte_in_line = 0 ) + { + msgpack::from_string( consumer, data, size, source.c_str(), byte, line, byte_in_line ); + } + + template< typename Consumer, typename... Ts > + void from_string( Consumer& consumer, const tao::string_view data, Ts&&... ts ) + { + msgpack::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); + } + + } // namespace msgpack + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/msgpack/grammar.hpp b/include/tao/json/events/msgpack/grammar.hpp new file mode 100644 index 00000000..7fc504ed --- /dev/null +++ b/include/tao/json/events/msgpack/grammar.hpp @@ -0,0 +1,261 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_MSGPACK_GRAMMAR_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_MSGPACK_GRAMMAR_HPP + +#include + +#include "../../external/byte.hpp" +#include "../../internal/endian.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + namespace msgpack + { + struct data + { + using analyze_t = json_pegtl::analysis::generic< json_pegtl::analysis::rule_type::ANY >; + + template< json_pegtl::apply_mode A, + json_pegtl::rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename Consumer > + static bool match( Input& in, Consumer& consumer ) + { + // This rule never returns false unless the input is empty. + return ( !in.empty() ) && match_impl( in, consumer ); + } + + template< typename Input, typename Consumer > + static bool match_impl( Input& in, Consumer& consumer ) + { + const auto b = in.peek_byte(); + if( b <= 0x7f ) { + consumer.number( std::uint64_t( b ) ); + in.bump_in_this_line(); + return true; + } + else if( b >= 0xe0 ) { + consumer.number( std::int64_t( std::int8_t( b ) ) ); + in.bump_in_this_line(); + return true; + } + else if( ( 0x80 <= b ) && ( b <= 0x8f ) ) { + in.bump_in_this_line(); + return match_object( in, consumer, b - 0x80 ); + } + else if( ( 0x90 <= b ) && ( b <= 0x9f ) ) { + in.bump_in_this_line(); + return match_array( in, consumer, b - 0x90 ); + } + else if( ( 0xa0 <= b ) && ( b <= 0xbf ) ) { + in.bump_in_this_line(); + consumer.string( read_container< tao::string_view >( in, b - 0xa0 ) ); + return true; + } + switch( b ) { + case 0xc0: + consumer.null(); + in.bump_in_this_line(); + return true; + case 0xc1: + throw json_pegtl::parse_error( "unused msgpack first byte 0xc1", in ); + case 0xc2: + case 0xc3: + consumer.boolean( b & 1 ); + in.bump_in_this_line(); + return true; + case 0xc4: + consumer.binary( read_container< tao::byte_view >( in, read_number< std::size_t, std::uint8_t >( in ) ) ); + return true; + case 0xc5: + consumer.binary( read_container< tao::byte_view >( in, read_number< std::size_t, std::uint16_t >( in ) ) ); + return true; + case 0xc6: + consumer.binary( read_container< tao::byte_view >( in, read_number< std::size_t, std::uint32_t >( in ) ) ); + return true; + case 0xc7: + discard( in, read_number< std::size_t, std::uint8_t >( in ) + 1 ); + return true; + case 0xc8: + discard( in, read_number< std::size_t, std::uint16_t >( in ) + 1 ); + return true; + case 0xc9: + discard( in, read_number< std::size_t, std::uint32_t >( in ) + 1 ); + return true; + case 0xca: + consumer.number( read_number< double, float >( in ) ); + return true; + case 0xcb: + consumer.number( read_number< double, double >( in ) ); + return true; + case 0xcc: + consumer.number( read_number< std::uint64_t, std::uint8_t >( in ) ); + return true; + case 0xcd: + consumer.number( read_number< std::uint64_t, std::uint16_t >( in ) ); + return true; + case 0xce: + consumer.number( read_number< std::uint64_t, std::uint32_t >( in ) ); + return true; + case 0xcf: + consumer.number( read_number< std::uint64_t, std::uint64_t >( in ) ); + return true; + case 0xd0: + consumer.number( read_number< std::int64_t, std::int8_t >( in ) ); + return true; + case 0xd1: + consumer.number( read_number< std::int64_t, std::int16_t >( in ) ); + return true; + case 0xd2: + consumer.number( read_number< std::int64_t, std::int32_t >( in ) ); + return true; + case 0xd3: + consumer.number( read_number< std::int64_t, std::int64_t >( in ) ); + return true; + case 0xd4: + discard( in, 3 ); + return true; + case 0xd5: + discard( in, 4 ); + return true; + case 0xd6: + discard( in, 6 ); + return true; + case 0xd7: + discard( in, 10 ); + return true; + case 0xd8: + discard( in, 18 ); + return true; + case 0xd9: + consumer.string( read_container< tao::string_view >( in, read_number< std::size_t, std::uint8_t >( in ) ) ); + return true; + case 0xda: + consumer.string( read_container< tao::string_view >( in, read_number< std::size_t, std::uint16_t >( in ) ) ); + return true; + case 0xdb: + consumer.string( read_container< tao::string_view >( in, read_number< std::size_t, std::uint32_t >( in ) ) ); + return true; + case 0xdc: + return match_array( in, consumer, read_number< std::size_t, std::uint16_t >( in ) ); + case 0xdd: + return match_array( in, consumer, read_number< std::size_t, std::uint32_t >( in ) ); + case 0xde: + return match_object( in, consumer, read_number< std::size_t, std::uint16_t >( in ) ); + case 0xdf: + return match_object( in, consumer, read_number< std::size_t, std::uint32_t >( in ) ); + } + // LCOV_EXCL_START + assert( false ); + return false; + // LCOV_EXCL_STOP + } + + template< typename Input > + static void discard( Input& in, const std::size_t count ) + { + if( in.size( count ) < count ) { + throw json_pegtl::parse_error( "unexpected end of input", in ); + } + in.bump_in_this_line( count ); + } + + template< typename Result, typename Number, typename Input > + static Result read_number( Input& in ) + { + if( in.size( sizeof( Number ) ) > sizeof( Number ) ) { + const Result result = json::internal::be_to_h< Number >( in.current() + 1 ); + in.bump_in_this_line( 1 + sizeof( Number ) ); + return result; + } + throw json_pegtl::parse_error( "unexpected end of msgpack input", in ); + } + + template< typename Result, typename Input > + static Result read_container( Input& in, const std::size_t size ) + { + using value_t = typename Result::value_type; + if( in.size( size ) < size ) { + throw json_pegtl::parse_error( "unexpected end of input", in ); + } + const value_t* pointer = reinterpret_cast< const value_t* >( in.current() ); + Result result( pointer, size ); + in.bump_in_this_line( size ); + return result; + } + + template< typename Input > + static tao::string_view read_key( Input& in ) + { + if( in.empty() ) { + throw json_pegtl::parse_error( "unexpected end of input", in ); + } + const auto b = in.peek_byte(); + if ( ( 0xa0 <= b ) && ( b <= 0xbf ) ) { + in.bump_in_this_line(); + return read_container< tao::string_view >( in, b - 0xa0 ); + } + switch( b ) { + case 0xd9: + return read_container< tao::string_view >( in, read_number< std::size_t, std::uint8_t >( in ) ); + case 0xda: + return read_container< tao::string_view >( in, read_number< std::size_t, std::uint16_t >( in ) ); + case 0xdb: + return read_container< tao::string_view >( in, read_number< std::size_t, std::uint32_t >( in ) ); + } + throw json_pegtl::parse_error( "unexpected key type", in ); + } + + template< typename Input, typename Consumer > + static bool match_array( Input& in, Consumer& consumer, const std::size_t size ) + { + consumer.begin_array( size ); + for( std::size_t i = 0; i < size; ++i ) { + if( in.empty() ) { + throw json_pegtl::parse_error( "unexpected end of input", in ); + } + match_impl( in, consumer ); + consumer.element(); + } + consumer.end_array( size ); + return true; + } + + template< typename Input, typename Consumer > + static bool match_object( Input& in, Consumer& consumer, const std::size_t size ) + { + consumer.begin_object( size ); + for( std::size_t i = 0; i < size; ++i ) { + consumer.key( read_key( in ) ); + if( in.empty() ) { + throw json_pegtl::parse_error( "unexpected end of input", in ); + } + match_impl( in, consumer ); + consumer.member(); + } + consumer.end_object( size ); + return true; + } + }; + + struct grammar : json_pegtl::must< data, json_pegtl::eof > + { + }; + + } // namespace msgpack + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/msgpack/to_stream.hpp b/include/tao/json/events/msgpack/to_stream.hpp new file mode 100644 index 00000000..23b2df89 --- /dev/null +++ b/include/tao/json/events/msgpack/to_stream.hpp @@ -0,0 +1,218 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JSON_MSGPACK_TO_STREAM_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_JSON_MSGPACK_TO_STREAM_HPP + +#include +#include +#include +#include + +#include "../../external/byte.hpp" +#include "../../internal/endian.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + namespace msgpack + { + class to_stream + { + private: + std::ostream& os; + + public: + explicit to_stream( std::ostream& in_os ) noexcept + : os( in_os ) + { + } + + void null() + { + os.put( char( 0xc0 ) ); + } + + void boolean( const bool v ) + { + os.put( char( 0xc2 ) + char( v ) ); + } + + template< typename Integer > + void number_impl( const unsigned char tag, const std::uint64_t v ) + { + os.put( char( tag ) ); + const Integer x = internal::h_to_be( Integer( v ) ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + + void number( const std::int64_t v ) + { + if( ( v >= -32 ) && ( v <= -1 ) ) { + const std::int8_t x = v; + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else if( ( v >= -128 ) && ( v <= 127 ) ) { + number_impl< std::uint8_t >( 0xd0, v ); + } + else if( ( v >= -32768 ) && ( v <= 32767 ) ) { + number_impl< std::uint16_t >( 0xd1, v ); + } + else if( ( v >= -2147483648 ) && ( v <= 2147483647 ) ) { + number_impl< std::uint32_t >( 0xd2, v ); + } + else { + number_impl< std::uint64_t >( 0xd3, v ); + } + } + + void number( const std::uint64_t v ) + { + if( v <= 127 ) { + const std::uint8_t x = v; + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else if( v <= 255 ) { + number_impl< std::uint8_t >( 0xcc, v ); + } + else if( v <= 65535 ) { + number_impl< std::uint16_t >( 0xcd, v ); + } + else if( v <= 4294967295ul ) { + number_impl< std::uint32_t >( 0xce, v ); + } + else { + number_impl< std::uint64_t >( 0xcf, v ); + } + } + + void number( const double v ) + { + os.put( char( 0xcb ) ); + const auto x = internal::h_to_be( v ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + + void string( const tao::string_view v ) + { + if( v.size() <= 31 ) { + os.put( char( v.size() + 0xa0 ) ); + } + else if( v.size() <= 255 ) { + number_impl< std::uint8_t >( 0xd9, v.size() ); + } + else if( v.size() <= 65535 ) { + number_impl< std::uint16_t >( 0xda, v.size() ); + } + else if( v.size() <= 4294967295ul ) { + number_impl< std::uint32_t >( 0xdb, v.size() ); + } + else { + throw std::runtime_error( "string too long for msgpack" ); + } + os.write( v.data(), v.size() ); + } + + void binary( const tao::byte_view v ) + { + if( v.size() <= 255 ) { + number_impl< std::uint8_t >( 0xc4, v.size() ); + } + else if( v.size() <= 65535 ) { + number_impl< std::uint16_t >( 0xc5, v.size() ); + } + else if( v.size() <= 4294967295ul ) { + number_impl< std::uint32_t >( 0xc6, v.size() ); + } + else { + throw std::runtime_error( "binary too long for msgpack" ); + } + os.write( reinterpret_cast< const char* >( v.data() ), v.size() ); + } + + void begin_array() + { + throw std::runtime_error( "msgpack requires array size" ); // TODO: Fix this by counting and buffering? + } + + void begin_array( const std::size_t size ) + { + if( size <= 15 ) { + os.put( char( 0x90 + size ) ); + } + else if( size <= 65535 ) { + number_impl< std::uint16_t >( 0xdc, size ); + } + else if( size <= 4294967295ul ) { + number_impl< std::uint32_t >( 0xdd, size ); + } + else { + throw std::runtime_error( "array too large for msgpack" ); + } + } + + void element() noexcept + { + } + + void end_array() + { + assert( false ); // LCOV_EXCL_LINE + } + + void end_array( const std::size_t ) noexcept + { + } + + void begin_object() + { + throw std::runtime_error( "msgpack requires object size" ); // TODO: Fix this by counting and buffering? + } + + void begin_object( const std::size_t size ) + { + if( size <= 15 ) { + os.put( char( 0x80 + size ) ); + } + else if( size <= 65535 ) { + number_impl< std::uint16_t >( 0xde, size ); + } + else if( size <= 4294967295ul ) { + number_impl< std::uint32_t >( 0xdf, size ); + } + else { + throw std::runtime_error( "array too large for msgpack" ); + } + } + + void key( const tao::string_view v ) + { + string( v ); + } + + void member() noexcept + { + } + + void end_object() + { + assert( false ); // LCOV_EXCL_LINE + } + + void end_object( const std::size_t ) noexcept + { + } + }; + + } // namespace msgpack + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/msgpack/to_string.hpp b/include/tao/json/events/msgpack/to_string.hpp new file mode 100644 index 00000000..668a8f03 --- /dev/null +++ b/include/tao/json/events/msgpack/to_string.hpp @@ -0,0 +1,44 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JSON_MSGPACK_TO_STRING_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_JSON_MSGPACK_TO_STRING_HPP + +#include +#include + +#include "to_stream.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + namespace msgpack + { + struct to_string + : public to_stream + { + std::ostringstream oss; + + to_string() + : to_stream( oss ) + { + } + + std::string value() const + { + return oss.str(); + } + }; + + } // namespace msgpack + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/non_finite_to_exception.hpp b/include/tao/json/events/non_finite_to_exception.hpp new file mode 100644 index 00000000..023b3a91 --- /dev/null +++ b/include/tao/json/events/non_finite_to_exception.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_NON_FINITE_TO_EXCEPTION_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_NON_FINITE_TO_EXCEPTION_HPP + +#include +#include + +namespace tao +{ + namespace json + { + namespace events + { + template< typename Consumer > + struct non_finite_to_exception + : public Consumer + { + using Consumer::Consumer; + + using Consumer::number; + + void number( const double v ) + { + if( !std::isfinite( v ) ) { + throw std::runtime_error( "invalid non-finite double value" ); + } + Consumer::number( v ); + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/non_finite_to_null.hpp b/include/tao/json/events/non_finite_to_null.hpp new file mode 100644 index 00000000..70e8c69a --- /dev/null +++ b/include/tao/json/events/non_finite_to_null.hpp @@ -0,0 +1,40 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_NON_FINITE_TO_NULL_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_NON_FINITE_TO_NULL_HPP + +#include + +namespace tao +{ + namespace json + { + namespace events + { + template< typename Consumer > + struct non_finite_to_null + : public Consumer + { + using Consumer::Consumer; + + using Consumer::number; + + void number( const double v ) + { + if( !std::isfinite( v ) ) { + Consumer::null(); + } + else { + Consumer::number( v ); + } + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/non_finite_to_string.hpp b/include/tao/json/events/non_finite_to_string.hpp new file mode 100644 index 00000000..0e2cd09b --- /dev/null +++ b/include/tao/json/events/non_finite_to_string.hpp @@ -0,0 +1,48 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_NON_FINITE_TO_STRING_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_NON_FINITE_TO_STRING_HPP + +#include + +namespace tao +{ + namespace json + { + namespace events + { + template< typename Consumer > + struct non_finite_to_string + : public Consumer + { + using Consumer::Consumer; + + using Consumer::number; + + void number( const double v ) + { + if( !std::isfinite( v ) ) { + if( std::isnan( v ) ) { + Consumer::string( "NaN" ); + } + else if( v > 0 ) { + Consumer::string( "Infinity" ); + } + else { + Consumer::string( "-Infinity" ); + } + } + else { + Consumer::number( v ); + } + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/parse_file.hpp b/include/tao/json/events/parse_file.hpp new file mode 100644 index 00000000..3673fa13 --- /dev/null +++ b/include/tao/json/events/parse_file.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_PARSE_FILE_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_PARSE_FILE_HPP + +#include + +#include "../internal/action.hpp" +#include "../internal/control.hpp" +#include "../internal/grammar.hpp" + +#include "../external/pegtl/file_input.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + // Events producer to parse a file containing a JSON string representation. + + template< typename T, typename Consumer > + void parse_file( Consumer& consumer, T&& filename ) + { + json_pegtl::file_input< json_pegtl::tracking_mode::LAZY > in( std::forward< T >( filename ) ); + json_pegtl::parse< internal::grammar, internal::action, internal::control >( in, consumer ); + } + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/prefer_signed.hpp b/include/tao/json/events/prefer_signed.hpp new file mode 100644 index 00000000..779774b3 --- /dev/null +++ b/include/tao/json/events/prefer_signed.hpp @@ -0,0 +1,40 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_PREFER_SIGNED_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_PREFER_SIGNED_HPP + +#include + +namespace tao +{ + namespace json + { + namespace events + { + template< typename Consumer > + struct prefer_signed + : public Consumer + { + using Consumer::Consumer; + + using Consumer::number; + + void number( const std::uint64_t v ) + { + if( v <= 9223372036854775807ull ) { + Consumer::number( std::int64_t( v ) ); + } + else { + Consumer::number( v ); + } + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/prefer_unsigned.hpp b/include/tao/json/events/prefer_unsigned.hpp new file mode 100644 index 00000000..780d58c9 --- /dev/null +++ b/include/tao/json/events/prefer_unsigned.hpp @@ -0,0 +1,40 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_PREFER_UNSIGNED_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_PREFER_UNSIGNED_HPP + +#include + +namespace tao +{ + namespace json + { + namespace events + { + template< typename Consumer > + struct prefer_unsigned + : public Consumer + { + using Consumer::Consumer; + + using Consumer::number; + + void number( const std::int64_t v ) + { + if( v >= 0 ) { + Consumer::number( std::uint64_t( v ) ); + } + else { + Consumer::number( v ); + } + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/ref.hpp b/include/tao/json/events/ref.hpp new file mode 100644 index 00000000..04e37225 --- /dev/null +++ b/include/tao/json/events/ref.hpp @@ -0,0 +1,120 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_REF_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_REF_HPP + +#include +#include + +namespace tao +{ + namespace json + { + namespace events + { + template< typename Consumer > + class ref + { + private: + Consumer& r_; + + public: + explicit ref( Consumer& r ) noexcept + : r_( r ) + { + } + + void null() noexcept( noexcept( r_.null() ) ) + { + r_.null(); + } + + template< typename T > + void boolean( T&& v ) noexcept( noexcept( r_.boolean( std::forward< T >( v ) ) ) ) + { + r_.boolean( std::forward< T >( v ) ); + } + + template< typename T > + void number( T&& v ) noexcept( noexcept( r_.number( std::forward< T >( v ) ) ) ) + { + r_.number( std::forward< T >( v ) ); + } + + template< typename T > + void string( T&& v ) noexcept( noexcept( r_.string( std::forward< T >( v ) ) ) ) + { + r_.string( std::forward< T >( v ) ); + } + + template< typename T > + void binary( T&& v ) noexcept( noexcept( r_.binary( std::forward< T >( v ) ) ) ) + { + r_.binary( std::forward< T >( v ) ); + } + + void begin_array() noexcept( noexcept( r_.begin_array() ) ) + { + r_.begin_array(); + } + + void begin_array( const std::size_t size ) noexcept( noexcept( r_.begin_array( size ) ) ) + { + r_.begin_array( size ); + } + + void element() noexcept( noexcept( r_.element() ) ) + { + r_.element(); + } + + void end_array() noexcept( noexcept( r_.end_array() ) ) + { + r_.end_array(); + } + + void end_array( const std::size_t size ) noexcept( noexcept( r_.end_array( size ) ) ) + { + r_.end_array( size ); + } + + void begin_object() noexcept( noexcept( r_.begin_object() ) ) + { + r_.begin_object(); + } + + void begin_object( const std::size_t size ) noexcept( noexcept( r_.begin_object( size ) ) ) + { + r_.begin_object( size ); + } + + template< typename T > + void key( T&& v ) noexcept( noexcept( r_.key( std::forward< T >( v ) ) ) ) + { + r_.key( std::forward< T >( v ) ); + } + + void member() noexcept( noexcept( r_.member() ) ) + { + r_.member(); + } + + void end_object() noexcept( noexcept( r_.end_object() ) ) + { + r_.end_object(); + } + + void end_object( const std::size_t size ) noexcept( noexcept( r_.end_object( size ) ) ) + { + r_.end_object( size ); + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/tee.hpp b/include/tao/json/events/tee.hpp new file mode 100644 index 00000000..57e42701 --- /dev/null +++ b/include/tao/json/events/tee.hpp @@ -0,0 +1,417 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_TEE_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_TEE_HPP + +#include +#include +#include +#include +#include +#include + +#include "discard.hpp" + +#include "../external/pegtl/internal/integer_sequence.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + template< typename T > + struct strip_reference_wrapper + { + using type = T; + }; + + template< typename T > + struct strip_reference_wrapper< std::reference_wrapper< T > > + { + using type = T&; + }; + + template< typename T > + using decay_and_strip_t = typename strip_reference_wrapper< typename std::decay< T >::type >::type; + + template< typename > + struct events_apply; + + template<> + struct events_apply< TAOCPP_JSON_PEGTL_NAMESPACE::internal::index_sequence<> > + { + template< typename... Ts > + static void null( std::tuple< Ts... >& ) + { + } + + template< typename... Ts > + static void boolean( std::tuple< Ts... >&, const bool ) + { + } + + template< typename... Ts > + static void number( std::tuple< Ts... >&, const std::int64_t ) + { + } + + template< typename... Ts > + static void number( std::tuple< Ts... >&, const std::uint64_t ) + { + } + + template< typename... Ts > + static void number( std::tuple< Ts... >&, const double ) + { + } + + template< typename... Ts > + static void string( std::tuple< Ts... >&, const tao::string_view ) + { + } + + template< typename... Ts > + static void binary( std::tuple< Ts... >&, const tao::byte_view ) + { + } + + template< typename... Ts > + static void begin_array( std::tuple< Ts... >& ) + { + } + + template< typename... Ts > + static void begin_array( std::tuple< Ts... >&, const std::size_t ) + { + } + + template< typename... Ts > + static void element( std::tuple< Ts... >& ) + { + } + + template< typename... Ts > + static void end_array( std::tuple< Ts... >& ) + { + } + + template< typename... Ts > + static void end_array( std::tuple< Ts... >&, const std::size_t ) + { + } + + template< typename... Ts > + static void begin_object( std::tuple< Ts... >& ) + { + } + + template< typename... Ts > + static void begin_object( std::tuple< Ts... >&, const std::size_t ) + { + } + + template< typename... Ts > + static void key( std::tuple< Ts... >&, const tao::string_view ) + { + } + + template< typename... Ts > + static void member( std::tuple< Ts... >& ) + { + } + + template< typename... Ts > + static void end_object( std::tuple< Ts... >& ) + { + } + + template< typename... Ts > + static void end_object( std::tuple< Ts... >&, const std::size_t ) + { + } + }; + + template< std::size_t... Is > + struct events_apply< TAOCPP_JSON_PEGTL_NAMESPACE::internal::index_sequence< Is... > > + { + using sink = bool[]; + + template< typename... Ts > + static void null( std::tuple< Ts... >& t ) + { + (void)sink{ ( std::get< Is >( t ).null(), true )... }; + } + + template< typename... Ts > + static void boolean( std::tuple< Ts... >& t, const bool v ) + { + (void)sink{ ( std::get< Is >( t ).boolean( v ), true )... }; + } + + template< typename... Ts > + static void number( std::tuple< Ts... >& t, const std::int64_t v ) + { + (void)sink{ ( std::get< Is >( t ).number( v ), true )... }; + } + + template< typename... Ts > + static void number( std::tuple< Ts... >& t, const std::uint64_t v ) + { + (void)sink{ ( std::get< Is >( t ).number( v ), true )... }; + } + + template< typename... Ts > + static void number( std::tuple< Ts... >& t, const double v ) + { + (void)sink{ ( std::get< Is >( t ).number( v ), true )... }; + } + + template< typename... Ts > + static void string( std::tuple< Ts... >& t, const tao::string_view v ) + { + (void)sink{ ( std::get< Is >( t ).string( v ), true )... }; + } + + template< typename... Ts > + static void binary( std::tuple< Ts... >& t, const tao::byte_view v ) + { + (void)sink{ ( std::get< Is >( t ).binary( v ), true )... }; + } + + template< typename... Ts > + static void begin_array( std::tuple< Ts... >& t ) + { + (void)sink{ ( std::get< Is >( t ).begin_array(), true )... }; + } + + template< typename... Ts > + static void begin_array( std::tuple< Ts... >& t, const std::size_t size ) + { + (void)sink{ ( std::get< Is >( t ).begin_array( size ), true )... }; + } + + template< typename... Ts > + static void element( std::tuple< Ts... >& t ) + { + (void)sink{ ( std::get< Is >( t ).element(), true )... }; + } + + template< typename... Ts > + static void end_array( std::tuple< Ts... >& t ) + { + (void)sink{ ( std::get< Is >( t ).end_array(), true )... }; + } + + template< typename... Ts > + static void end_array( std::tuple< Ts... >& t, const std::size_t size ) + { + (void)sink{ ( std::get< Is >( t ).end_array( size ), true )... }; + } + + template< typename... Ts > + static void begin_object( std::tuple< Ts... >& t ) + { + (void)sink{ ( std::get< Is >( t ).begin_object(), true )... }; + } + + template< typename... Ts > + static void begin_object( std::tuple< Ts... >& t, const std::size_t size ) + { + (void)sink{ ( std::get< Is >( t ).begin_object( size ), true )... }; + } + + template< typename... Ts > + static void key( std::tuple< Ts... >& t, const tao::string_view v ) + { + (void)sink{ ( std::get< Is >( t ).key( v ), true )... }; + } + + template< typename... Ts > + static void member( std::tuple< Ts... >& t ) + { + (void)sink{ ( std::get< Is >( t ).member(), true )... }; + } + + template< typename... Ts > + static void end_object( std::tuple< Ts... >& t ) + { + (void)sink{ ( std::get< Is >( t ).end_object(), true )... }; + } + + template< typename... Ts > + static void end_object( std::tuple< Ts... >& t, const std::size_t size ) + { + (void)sink{ ( std::get< Is >( t ).end_object( size ), true )... }; + } + }; + + } // namespace internal + + namespace events + { + // Events consumer that forwards to multiple nested consumers. + + template< typename... Ts > + class tee + { + private: + static constexpr std::size_t S = sizeof...( Ts ); + + using I = TAOCPP_JSON_PEGTL_NAMESPACE::internal::make_index_sequence< S >; + using H = TAOCPP_JSON_PEGTL_NAMESPACE::internal::make_index_sequence< S - 1 >; + + std::tuple< Ts... > ts; + + public: + template< typename... Us > + tee( Us&&... us ) + : ts( std::forward< Us >( us )... ) + { + } + + void null() + { + internal::events_apply< I >::null( ts ); + } + + void boolean( const bool v ) + { + internal::events_apply< I >::boolean( ts, v ); + } + + void number( const std::int64_t v ) + { + internal::events_apply< I >::number( ts, v ); + } + + void number( const std::uint64_t v ) + { + internal::events_apply< I >::number( ts, v ); + } + + void number( const double v ) + { + internal::events_apply< I >::number( ts, v ); + } + + void string( const tao::string_view v ) + { + internal::events_apply< I >::string( ts, v ); + } + + void string( const char* v ) + { + internal::events_apply< I >::string( ts, v ); + } + + void string( std::string&& v ) + { + internal::events_apply< H >::string( ts, v ); + std::get< S - 1 >( ts ).string( std::move( v ) ); + } + + void binary( const tao::byte_view v ) + { + internal::events_apply< I >::binary( ts, v ); + } + + void binary( std::vector< tao::byte >&& v ) + { + internal::events_apply< H >::binary( ts, v ); + std::get< S - 1 >( ts ).binary( std::move( v ) ); + } + + void begin_array() + { + internal::events_apply< I >::begin_array( ts ); + } + + void begin_array( const std::size_t size ) + { + internal::events_apply< I >::begin_array( ts, size ); + } + + void element() + { + internal::events_apply< I >::element( ts ); + } + + void end_array() + { + internal::events_apply< I >::end_array( ts ); + } + + void end_array( const std::size_t size ) + { + internal::events_apply< I >::end_array( ts, size ); + } + + void begin_object() + { + internal::events_apply< I >::begin_object( ts ); + } + + void begin_object( const std::size_t size ) + { + internal::events_apply< I >::begin_object( ts, size ); + } + + void key( const tao::string_view v ) + { + internal::events_apply< I >::key( ts, v ); + } + + void key( const char* v ) + { + internal::events_apply< I >::key( ts, v ); + } + + void key( std::string&& v ) + { + internal::events_apply< H >::key( ts, v ); + std::get< S - 1 >( ts ).key( std::move( v ) ); + } + + void member() + { + internal::events_apply< I >::member( ts ); + } + + void end_object() + { + internal::events_apply< I >::end_object( ts ); + } + + void end_object( const std::size_t size ) + { + internal::events_apply< I >::end_object( ts, size ); + } + }; + + template<> + class tee<> + : public discard + { + }; + + template< typename... T > + tee< internal::decay_and_strip_t< T >... > make_tee( T&&... t ) + { + return tee< internal::decay_and_strip_t< T >... >( std::forward< T >( t )... ); + } + + template< typename... T > + tee< T&... > tie( T&... t ) + { + return tee< T&... >( t... ); + } + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/to_pretty_stream.hpp b/include/tao/json/events/to_pretty_stream.hpp new file mode 100644 index 00000000..e188fae1 --- /dev/null +++ b/include/tao/json/events/to_pretty_stream.hpp @@ -0,0 +1,170 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_TO_PRETTY_STREAM_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_TO_PRETTY_STREAM_HPP + +#include +#include +#include +#include +#include +#include +#include + +#include "../external/byte.hpp" +#include "../external/double.hpp" + +#include "../internal/escape.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + // Events consumer to build a JSON pretty string representation. + + class to_pretty_stream + { + protected: + std::ostream& os; + const std::size_t indent; + + std::string current = "\n"; + bool first = true; + bool after_key = true; + + void next() + { + if( !first ) { + os.put( ',' ); + } + if( after_key ) { + after_key = false; + } + else { + os << current; + } + } + + public: + to_pretty_stream( std::ostream& in_os, const std::size_t in_indent ) + : os( in_os ), + indent( in_indent ), + first( true ) + { + } + + void null() + { + next(); + os.write( "null", 4 ); + } + + void boolean( const bool v ) + { + next(); + if( v ) { + os.write( "true", 4 ); + } + else { + os.write( "false", 5 ); + } + } + + void number( const std::int64_t v ) + { + next(); + os << v; + } + + void number( const std::uint64_t v ) + { + next(); + os << v; + } + + void number( const double v ) + { + next(); + if( !std::isfinite( v ) ) { + throw std::runtime_error( "non-finite double value invalid for JSON string representation" ); + } + json_double_conversion::Dtostr( os, v ); + } + + void string( const tao::string_view v ) + { + next(); + os.put( '"' ); + internal::escape( os, v ); + os.put( '"' ); + } + + void binary( const tao::byte_view ) + { + // if this throws, consider using binary_to_* wrappers + throw std::runtime_error( "binary data invalid for JSON string representation" ); + } + + void begin_array( const std::size_t = 0 ) + { + next(); + os.put( '[' ); + current.resize( current.size() + indent, ' ' ); + first = true; + } + + void element() noexcept + { + first = false; + } + + void end_array( const std::size_t = 0 ) + { + current.resize( current.size() - indent ); + if( !first ) { + os << current; + } + os.put( ']' ); + } + + void begin_object( const std::size_t = 0 ) + { + next(); + os.put( '{' ); + current.resize( current.size() + indent, ' ' ); + first = true; + } + + void key( const tao::string_view v ) + { + string( v ); + os.write( ": ", 2 ); + first = true; + after_key = true; + } + + void member() noexcept + { + first = false; + } + + void end_object( const std::size_t = 0 ) + { + current.resize( current.size() - indent ); + if( !first ) { + os << current; + } + os.put( '}' ); + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/to_stream.hpp b/include/tao/json/events/to_stream.hpp new file mode 100644 index 00000000..b469c6f3 --- /dev/null +++ b/include/tao/json/events/to_stream.hpp @@ -0,0 +1,149 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_TO_STREAM_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_TO_STREAM_HPP + +#include +#include +#include +#include +#include +#include + +#include "../byte_view.hpp" + +#include "../external/double.hpp" +#include "../external/string_view.hpp" + +#include "../internal/escape.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + // Events consumer to build a JSON string representation. + + class to_stream + { + protected: + std::ostream& os; + bool first; + + void next() + { + if( !first ) { + os.put( ',' ); + } + } + + public: + explicit to_stream( std::ostream& in_os ) noexcept + : os( in_os ), + first( true ) + { + } + + void null() + { + next(); + os.write( "null", 4 ); + } + + void boolean( const bool v ) + { + next(); + if( v ) { + os.write( "true", 4 ); + } + else { + os.write( "false", 5 ); + } + } + + void number( const std::int64_t v ) + { + next(); + os << v; + } + + void number( const std::uint64_t v ) + { + next(); + os << v; + } + + void number( const double v ) + { + next(); + if( !std::isfinite( v ) ) { + throw std::runtime_error( "non-finite double value invalid for JSON string representation" ); + } + json_double_conversion::Dtostr( os, v ); + } + + void string( const tao::string_view v ) + { + next(); + os.put( '"' ); + internal::escape( os, v ); + os.put( '"' ); + } + + void binary( const tao::byte_view ) + { + // if this throws, consider using binary_to_* wrappers + throw std::runtime_error( "binary data invalid for JSON string representation" ); + } + + void begin_array( const std::size_t = 0 ) + { + next(); + os.put( '[' ); + first = true; + } + + void element() noexcept + { + first = false; + } + + void end_array( const std::size_t = 0 ) + { + os.put( ']' ); + } + + void begin_object( const std::size_t = 0 ) + { + next(); + os.put( '{' ); + first = true; + } + + void key( const tao::string_view v ) + { + string( v ); + os.put( ':' ); + first = true; + } + + void member() noexcept + { + first = false; + } + + void end_object( const std::size_t = 0 ) + { + os.put( '}' ); + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/to_string.hpp b/include/tao/json/events/to_string.hpp new file mode 100644 index 00000000..d91d8e2f --- /dev/null +++ b/include/tao/json/events/to_string.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_TO_STRING_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_TO_STRING_HPP + +#include +#include + +#include "to_stream.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + // Events consumer to build a JSON string representation. + + struct to_string + : public to_stream + { + std::ostringstream oss; + + to_string() + : to_stream( oss ) + { + } + + std::string value() const + { + return oss.str(); + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/to_value.hpp b/include/tao/json/events/to_value.hpp new file mode 100644 index 00000000..9417b9a0 --- /dev/null +++ b/include/tao/json/events/to_value.hpp @@ -0,0 +1,152 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_TO_VALUE_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_TO_VALUE_HPP + +#include +#include +#include +#include +#include + +#include "../external/byte.hpp" +#include "../external/string_view.hpp" + +#include "../byte_view.hpp" +#include "../value.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + // Events consumer to build a JSON Value. + + template< template< typename... > class Traits > + class to_basic_value + { + private: + std::vector< basic_value< Traits > > stack_; + std::vector< std::string > keys_; + + public: + basic_value< Traits > value; + + void null() + { + value.unsafe_assign_null(); + } + + void boolean( const bool v ) + { + value.unsafe_assign_bool( v ); + } + + void number( const std::int64_t v ) + { + value.unsafe_assign_signed( v ); + } + + void number( const std::uint64_t v ) + { + value.unsafe_assign_unsigned( v ); + } + + void number( const double v ) + { + value.unsafe_assign_double( v ); + } + + void string( const tao::string_view v ) + { + value.unsafe_emplace_string( v.data(), v.size() ); + } + + void string( const char* v ) + { + value.unsafe_emplace_string( v ); + } + + void string( std::string&& v ) + { + value.unsafe_assign_string( std::move( v ) ); + } + + void binary( const tao::byte_view v ) + { + value.unsafe_emplace_binary( v.begin(), v.end() ); + } + + void binary( std::vector< tao::byte >&& v ) + { + value.unsafe_assign_binary( std::move( v ) ); + } + + void begin_array() + { + stack_.push_back( empty_array ); + } + + void begin_array( const std::size_t size ) + { + begin_array(); + stack_.back().unsafe_get_array().reserve( size ); + } + + void element() + { + stack_.back().unsafe_emplace_back( std::move( value ) ); + value.discard(); + } + + void end_array( const std::size_t = 0 ) + { + value = std::move( stack_.back() ); + stack_.pop_back(); + } + + void begin_object( const std::size_t = 0 ) + { + stack_.push_back( empty_object ); + } + + void key( const tao::string_view v ) + { + keys_.emplace_back( v.data(), v.size() ); + } + + void key( const char* v ) + { + keys_.emplace_back( v ); + } + + void key( std::string&& v ) + { + keys_.push_back( std::move( v ) ); + } + + void member() + { + stack_.back().unsafe_emplace( std::move( keys_.back() ), std::move( value ) ); + value.discard(); + keys_.pop_back(); + } + + void end_object( const std::size_t = 0 ) + { + value = std::move( stack_.back() ); + stack_.pop_back(); + } + }; + + using to_value = to_basic_value< traits >; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/transformer.hpp b/include/tao/json/events/transformer.hpp new file mode 100644 index 00000000..4125d9e7 --- /dev/null +++ b/include/tao/json/events/transformer.hpp @@ -0,0 +1,41 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_TRANSFORMER_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_TRANSFORMER_HPP + +namespace tao +{ + namespace json + { + namespace internal + { + template< typename Consumer, template< typename... > class... Transformer > + struct transformer; + + template< typename Consumer > + struct transformer< Consumer > + { + using type = Consumer; + }; + + template< typename Consumer, template< typename... > class Head, template< typename... > class... Tail > + struct transformer< Consumer, Head, Tail... > + { + using type = Head< typename transformer< Consumer, Tail... >::type >; + }; + + } // namespace internal + + namespace events + { + template< typename Consumer, template< typename... > class... Transformer > + using transformer = typename internal::transformer< Consumer, Transformer... >::type; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/ubjson/from_string.hpp b/include/tao/json/events/ubjson/from_string.hpp new file mode 100644 index 00000000..d685f36f --- /dev/null +++ b/include/tao/json/events/ubjson/from_string.hpp @@ -0,0 +1,47 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_UBJSON_FROM_STRING_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_UBJSON_FROM_STRING_HPP + +#include "../../external/pegtl/parse.hpp" +#include "../../external/string_view.hpp" + +#include "grammar.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + namespace ubjson + { + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t byte_in_line = 0 ) + { + json_pegtl::memory_input< json_pegtl::tracking_mode::LAZY, json_pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::ubjson::from_string", byte, line, byte_in_line ); + json_pegtl::parse< ubjson::grammar >( in, consumer ); + } + + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) + { + ubjson::from_string( consumer, data, size, source.c_str(), byte, line, column ); + } + + template< typename Consumer, typename... Ts > + void from_string( Consumer& consumer, const tao::string_view data, Ts&&... ts ) + { + ubjson::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); + } + + } // namespace ubjson + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/ubjson/grammar.hpp b/include/tao/json/events/ubjson/grammar.hpp new file mode 100644 index 00000000..f8fff13e --- /dev/null +++ b/include/tao/json/events/ubjson/grammar.hpp @@ -0,0 +1,279 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_UBJSON_GRAMMAR_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_UBJSON_GRAMMAR_HPP + +#include + +#include "../../internal/action.hpp" +#include "../../internal/control.hpp" +#include "../../internal/endian.hpp" +#include "../../internal/grammar.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + namespace ubjson + { + struct number + { + using analyze_t = json_pegtl::analysis::generic< json_pegtl::analysis::rule_type::ANY >; + + template< json_pegtl::apply_mode A, + json_pegtl::rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename Consumer > + static bool match_impl( Input& in, Consumer& consumer ) + { + if( in.peek_char() == '-' ) { + in.bump_in_this_line(); + if( in.empty() || !internal::rules::sor_value::match_number< true, A, json_pegtl::rewind_mode::DONTCARE, Action, Control >( in, consumer ) ) { + throw json_pegtl::parse_error( "incomplete number", in ); + } + return true; + } + return internal::rules::sor_value::match_number< false, A, M, Action, Control >( in, consumer ); + } + + template< json_pegtl::apply_mode A, + json_pegtl::rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename Consumer > + static bool match( Input& in, Consumer& consumer ) + { + if( in.size( 2 ) && match_impl< A, M, Action, Control >( in, consumer ) ) { + in.discard(); + return true; + } + return false; + } + }; + + } // namespace ubjson + + } // namespace events + + namespace internal + { + // clang-format off + template<> WEAK_PREFIX const std::string errors< events::ubjson::number >::error_message WEAK_SUFFIX = "invalid ubjson high-precision number"; + // clang-format on + + } // namespace internal + + namespace events + { + namespace ubjson + { + struct data + { + using analyze_t = json_pegtl::analysis::generic< json_pegtl::analysis::rule_type::ANY >; + + template< json_pegtl::apply_mode A, + json_pegtl::rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename Consumer > + static bool match( Input& in, Consumer& consumer ) + { + // This rule never returns false unless the input is empty. + return ( !in.empty() ) && match_impl( in, consumer ); + } + + template< typename Input, typename Consumer > + static bool match_impl( Input& in, Consumer& consumer ) + { + switch( in.peek_char() ) { + case 'Z': + consumer.null(); + in.bump_in_this_line(); + return true; + case 'N': + in.bump_in_this_line(); + return true; + case 'T': + consumer.boolean( true ); + in.bump_in_this_line(); + return true; + case 'F': + consumer.boolean( false ); + in.bump_in_this_line(); + return true; + case 'i': + consumer.number( read_number< std::int64_t, std::int8_t >( in ) ); + return true; + case 'U': + consumer.number( read_number< std::uint64_t, std::uint8_t >( in ) ); + return true; + case 'I': + consumer.number( read_number< std::int64_t, std::int16_t >( in ) ); + return true; + case 'l': + consumer.number( read_number< std::int64_t, std::int32_t >( in ) ); + return true; + case 'L': + consumer.number( read_number< std::int64_t, std::int64_t >( in ) ); + return true; + case 'd': + consumer.number( read_number< double, float >( in ) ); + return true; + case 'D': + consumer.number( read_number< double, double >( in ) ); + return true; + case 'H': + return match_high_precision( in, consumer ); + case 'C': + return match_char( in, consumer ); + case 'S': + consumer.string( read_container< tao::string_view >( in, read_size( in ) ) ); + } + throw json_pegtl::parse_error( "unknown ubjson marker", in ); + } + + template< typename Input, typename Consumer > + static bool match_char( Input& in, Consumer& consumer ) + { + if( ( in.size( 2 ) < 2 ) || ( in.peek_byte( 1 ) > 127 ) ) { + throw json_pegtl::parse_error( "invalid ubjson char", in ); + } + consumer.string( std::string( 1, in.peek_char( 1 ) ) ); + in.bump_in_this_line( 2 ); + return true; + } + + template< typename Input > + static std::size_t read_size( Input& in ) + { + in.bump_in_this_line(); // Skip marker byte. + if( !in.size( 1 ) ) { + throw json_pegtl::parse_error( "unexpected end of ubjson input", in ); + } + switch( in.peek_char() ) { + case 'i': + return read_number< std::int64_t, std::int8_t >( in ); + case 'U': + return read_number< std::int64_t, std::uint8_t >( in ); + case 'I': + return read_number< std::int64_t, std::int16_t >( in ); + case 'l': + return read_number< std::int64_t, std::int32_t >( in ); + case 'L': + return read_number< std::int64_t, std::int64_t >( in ); + case 'd': + return read_number< std::int64_t, float >( in ); + case 'D': + return read_number< std::int64_t, double >( in ); + } + throw json_pegtl::parse_error( "unexpected ubjson high precision number size marker", in ); + } + + template< typename Input, typename Consumer > + static bool match_high_precision( Input& in, Consumer& consumer ) + { + const auto size = read_size( in ); + if( size < 0 ) { + throw json_pegtl::parse_error( "negative ubjson high precision number size", in ); + } + if( in.size( size ) < size ) { + throw json_pegtl::parse_error( "unexpected end of ubjson input", in ); + } + json_pegtl::memory_input< json_pegtl::tracking_mode::LAZY, json_pegtl::eol::lf_crlf, const char* > i2( in.current(), in.current() + size, "UBJSON" ); + json_pegtl::parse_nested< json_pegtl::must< number, json_pegtl::eof >, internal::action, internal::control >( in, i2, consumer ); + return true; + } + + template< typename Result, typename Number, typename Input > + static Result read_number( Input& in ) + { + if( in.size( sizeof( Number ) ) > sizeof( Number ) ) { + const Result result = json::internal::be_to_h< Number >( in.current() + 1 ); + in.bump_in_this_line( 1 + sizeof( Number ) ); + return result; + } + throw json_pegtl::parse_error( "unexpected end of ubjson input", in ); + } + + template< typename Result, typename Input > + static Result read_container( Input& in, const std::size_t size ) + { + using value_t = typename Result::value_type; + if( in.size( size ) < size ) { + throw json_pegtl::parse_error( "unexpected end of ubjson input", in ); + } + const value_t* pointer = reinterpret_cast< const value_t* >( in.current() ); + Result result( pointer, size ); + in.bump_in_this_line( size ); + return result; + } + + template< typename Input > + static tao::string_view read_key( Input& in ) + { + if( in.empty() ) { + throw json_pegtl::parse_error( "unexpected end of ubjson input", in ); + } + switch( in.peek_byte() ) { + case 0xd9: + return read_container< tao::string_view >( in, read_number< std::size_t, std::uint8_t >( in ) ); + case 0xda: + return read_container< tao::string_view >( in, read_number< std::size_t, std::uint16_t >( in ) ); + case 0xdb: + return read_container< tao::string_view >( in, read_number< std::size_t, std::uint32_t >( in ) ); + } + throw json_pegtl::parse_error( "unexpected key type", in ); + } + + template< typename Input, typename Consumer > + static bool match_array( Input& in, Consumer& consumer, const std::size_t size ) + { + consumer.begin_array( size ); + for( std::size_t i = 0; i < size; ++i ) { + if( in.empty() ) { + throw json_pegtl::parse_error( "unexpected end of ubjson input", in ); + } + match_impl( in, consumer ); + consumer.element(); + } + consumer.end_array( size ); + return true; + } + + template< typename Input, typename Consumer > + static bool match_object( Input& in, Consumer& consumer, const std::size_t size ) + { + consumer.begin_object( size ); + for( std::size_t i = 0; i < size; ++i ) { + consumer.key( read_key( in ) ); + if( in.empty() ) { + throw json_pegtl::parse_error( "unexpected end of ubjson input", in ); + } + match_impl( in, consumer ); + consumer.member(); + } + consumer.end_object( size ); + return true; + } + }; + + struct grammar : json_pegtl::must< data, json_pegtl::eof > + { + }; + + } // namespace ubjson + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/ubjson/to_stream.hpp b/include/tao/json/events/ubjson/to_stream.hpp new file mode 100644 index 00000000..356c7fdc --- /dev/null +++ b/include/tao/json/events/ubjson/to_stream.hpp @@ -0,0 +1,188 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JSON_UBJSON_TO_STREAM_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_JSON_UBJSON_TO_STREAM_HPP + +#include +#include +#include +#include + +#include "../../internal/endian.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + namespace ubjson + { + class to_stream + { + private: + std::ostream& os; + + public: + explicit to_stream( std::ostream& in_os ) noexcept + : os( in_os ) + { + } + + void null() + { + os.put( 'Z' ); + } + + void boolean( const bool v ) + { + os.put( v ? 'T' : 'F' ); + } + + void number( const std::int64_t v ) + { + if( ( v >= -128 ) && ( v <= 127 ) ) { + os.put( 'i' ); + const std::int8_t x = v; + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else if( ( v >= -32768 ) && ( v <= 32767 ) ) { + os.put( 'I' ); + const std::uint16_t x = internal::h_to_be( std::uint16_t( v ) ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else if( ( v >= -2147483648 ) && ( v <= 2147483647 ) ) { + os.put( 'l' ); + const std::uint32_t x = internal::h_to_be( std::uint32_t( v ) ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else { + os.put( 'L' ); + const std::uint64_t x = internal::h_to_be( std::uint64_t( v ) ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + } + + void number( const std::uint64_t v ) + { + if( v <= 255 ) { + os.put( 'U' ); + const std::uint8_t x = v; + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else if( v <= 32767 ) { + os.put( 'I' ); + const std::uint16_t x = internal::h_to_be( std::uint16_t( v ) ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else if( v <= 2147483647ul ) { + os.put( 'l' ); + const std::uint32_t x = internal::h_to_be( std::uint32_t( v ) ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else if( v <= 9223372036854775807ull ) { + os.put( 'L' ); + const std::uint64_t x = internal::h_to_be( v ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else { + os.put( 'H' ); + os.put( 'U' ); + os.put( char( 19 ) + char( v >= 10000000000000000000ull ) ); + os << v; + } + } + + void number( const double v ) + { + os.put( 'D' ); + const auto x = internal::h_to_be( v ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + + void string( const tao::string_view v ) + { + if( ( v.size() == 1 ) && ( ( v[ 0 ] & 0x80 ) == 0 ) ) { + os.put( 'C' ); + os.put( v[ 0 ] ); + } + else { + os.put( 'S' ); + number( std::uint64_t( v.size() ) ); + os.write( v.data(), v.size() ); + } + } + + void binary( const tao::byte_view v ) + { + // NOTE: UBJSON encodes binary data as 'strongly typed array of uint8 values'. + os.write( "[$U#", 4 ); + number( std::uint64_t( v.size() ) ); + os.write( reinterpret_cast< const char* >( v.data() ), v.size() ); + } + + void begin_array() + { + os.put( '[' ); + } + + void begin_array( const std::size_t size ) + { + os.write( "[#", 2 ); + number( std::uint64_t( size ) ); + } + + void element() noexcept + { + } + + void end_array() + { + os.put( ']' ); + } + + void end_array( const std::size_t ) noexcept + { + } + + void begin_object() + { + os.put( '{' ); + } + + void begin_object( const std::size_t size ) + { + os.write( "{#", 2 ); + number( std::uint64_t( size ) ); + } + + void key( const tao::string_view v ) + { + number( std::uint64_t( v.size() ) ); + os.write( v.data(), v.size() ); + } + + void member() noexcept + { + } + + void end_object() + { + os.put( '}' ); + } + + void end_object( const std::size_t ) noexcept + { + } + }; + + } // namespace ubjson + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/ubjson/to_string.hpp b/include/tao/json/events/ubjson/to_string.hpp new file mode 100644 index 00000000..b5b248af --- /dev/null +++ b/include/tao/json/events/ubjson/to_string.hpp @@ -0,0 +1,44 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JSON_UBJSON_TO_STRING_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_JSON_UBJSON_TO_STRING_HPP + +#include +#include + +#include "to_stream.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + namespace ubjson + { + struct to_string + : public to_stream + { + std::ostringstream oss; + + to_string() + : to_stream( oss ) + { + } + + std::string value() const + { + return oss.str(); + } + }; + + } // namespace ubjson + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/validate_event_order.hpp b/include/tao/json/events/validate_event_order.hpp new file mode 100644 index 00000000..121da3cd --- /dev/null +++ b/include/tao/json/events/validate_event_order.hpp @@ -0,0 +1,387 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_VALIDATE_EVENT_ORDER_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_VALIDATE_EVENT_ORDER_HPP + +#include +#include +#include +#include +#include + +#include "../external/byte.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + // Events consumer that validates the order of events. + + class validate_event_order + { + private: + enum state_t + { + EXPECT_TOP_LEVEL_VALUE, + EXPECT_ARRAY_VALUE_OR_END, + EXPECT_ARRAY_ELEMENT, + EXPECT_OBJECT_KEY_OR_END, + EXPECT_OBJECT_VALUE, + EXPECT_OBJECT_MEMBER, + EXPECT_NOTHING + }; + + state_t state = EXPECT_TOP_LEVEL_VALUE; + std::vector< state_t > stack; + // TODO: Another stack for array/object sizes. + + public: + bool is_complete() const noexcept + { + return state == EXPECT_NOTHING; + } + + void null() + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + state = EXPECT_NOTHING; + return; + case EXPECT_ARRAY_VALUE_OR_END: + state = EXPECT_ARRAY_ELEMENT; + return; + case EXPECT_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but null() was called" ); + case EXPECT_OBJECT_KEY_OR_END: + throw std::logic_error( "expected key() or end_object(), but null() was called" ); + case EXPECT_OBJECT_VALUE: + state = EXPECT_OBJECT_MEMBER; + return; + case EXPECT_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but null() was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but null() was called" ); + } + throw std::logic_error( "invalid state" ); + } + + void boolean( const bool ) + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + state = EXPECT_NOTHING; + return; + case EXPECT_ARRAY_VALUE_OR_END: + state = EXPECT_ARRAY_ELEMENT; + return; + case EXPECT_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but boolean() was called" ); + case EXPECT_OBJECT_KEY_OR_END: + throw std::logic_error( "expected key() or end_object(), but boolean() was called" ); + case EXPECT_OBJECT_VALUE: + state = EXPECT_OBJECT_MEMBER; + return; + case EXPECT_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but boolean() was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but boolean() was called" ); + } + throw std::logic_error( "invalid state" ); + } + + void number( const std::int64_t ) + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + state = EXPECT_NOTHING; + return; + case EXPECT_ARRAY_VALUE_OR_END: + state = EXPECT_ARRAY_ELEMENT; + return; + case EXPECT_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but number(std::int64_t) was called" ); + case EXPECT_OBJECT_KEY_OR_END: + throw std::logic_error( "expected key() or end_object(), but number(std::int64_t) was called" ); + case EXPECT_OBJECT_VALUE: + state = EXPECT_OBJECT_MEMBER; + return; + case EXPECT_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but number(std::int64_t) was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but number(std::int64_t) was called" ); + } + throw std::logic_error( "invalid state" ); + } + + void number( const std::uint64_t ) + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + state = EXPECT_NOTHING; + return; + case EXPECT_ARRAY_VALUE_OR_END: + state = EXPECT_ARRAY_ELEMENT; + return; + case EXPECT_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but number(std::uint64_t) was called" ); + case EXPECT_OBJECT_KEY_OR_END: + throw std::logic_error( "expected key() or end_object(), but number(std::uint64_t) was called" ); + case EXPECT_OBJECT_VALUE: + state = EXPECT_OBJECT_MEMBER; + return; + case EXPECT_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but number(std::uint64_t) was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but number(std::uint64_t) was called" ); + } + throw std::logic_error( "invalid state" ); + } + + void number( const double ) + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + state = EXPECT_NOTHING; + return; + case EXPECT_ARRAY_VALUE_OR_END: + state = EXPECT_ARRAY_ELEMENT; + return; + case EXPECT_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but number(double) was called" ); + case EXPECT_OBJECT_KEY_OR_END: + throw std::logic_error( "expected key() or end_object(), but number(double) was called" ); + case EXPECT_OBJECT_VALUE: + state = EXPECT_OBJECT_MEMBER; + return; + case EXPECT_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but number(double) was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but number(double) was called" ); + } + throw std::logic_error( "invalid state" ); + } + + void string( const tao::string_view ) + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + state = EXPECT_NOTHING; + return; + case EXPECT_ARRAY_VALUE_OR_END: + state = EXPECT_ARRAY_ELEMENT; + return; + case EXPECT_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but string() was called" ); + case EXPECT_OBJECT_KEY_OR_END: + throw std::logic_error( "expected key() or end_object(), but string() was called" ); + case EXPECT_OBJECT_VALUE: + state = EXPECT_OBJECT_MEMBER; + return; + case EXPECT_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but string() was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but string() was called" ); + } + throw std::logic_error( "invalid state" ); + } + + void binary( const tao::byte_view ) + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + state = EXPECT_NOTHING; + return; + case EXPECT_ARRAY_VALUE_OR_END: + state = EXPECT_ARRAY_ELEMENT; + return; + case EXPECT_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but binary() was called" ); + case EXPECT_OBJECT_KEY_OR_END: + throw std::logic_error( "expected key() or end_object(), but binary() was called" ); + case EXPECT_OBJECT_VALUE: + state = EXPECT_OBJECT_MEMBER; + return; + case EXPECT_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but binary() was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but binary() was called" ); + } + throw std::logic_error( "invalid state" ); + } + + void begin_array( const std::size_t = 0 ) + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + stack.push_back( EXPECT_NOTHING ); + state = EXPECT_ARRAY_VALUE_OR_END; + return; + case EXPECT_ARRAY_VALUE_OR_END: + stack.push_back( EXPECT_ARRAY_ELEMENT ); + return; + case EXPECT_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but begin_array() was called" ); + case EXPECT_OBJECT_KEY_OR_END: + throw std::logic_error( "expected key() or end_object(), but begin_array() was called" ); + case EXPECT_OBJECT_VALUE: + stack.push_back( EXPECT_OBJECT_MEMBER ); + state = EXPECT_ARRAY_VALUE_OR_END; + return; + case EXPECT_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but begin_array() was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but begin_array() was called" ); + } + throw std::logic_error( "invalid state" ); + } + + void element() + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + throw std::logic_error( "expected any value, but element() was called" ); + case EXPECT_ARRAY_VALUE_OR_END: + throw std::logic_error( "expected any value or end_array(), but element() was called" ); + case EXPECT_ARRAY_ELEMENT: + state = EXPECT_ARRAY_VALUE_OR_END; + return; + case EXPECT_OBJECT_KEY_OR_END: + throw std::logic_error( "expected key() or end_object(), but element() was called" ); + case EXPECT_OBJECT_VALUE: + throw std::logic_error( "expected any value, but element() was called" ); + case EXPECT_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but element() was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but element() was called" ); + } + throw std::logic_error( "invalid state" ); + } + + void end_array( const std::size_t = 0 ) + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + throw std::logic_error( "expected any value, but end_array() was called" ); + case EXPECT_ARRAY_VALUE_OR_END: + state = stack.back(); + stack.pop_back(); + return; + case EXPECT_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but end_array() was called" ); + case EXPECT_OBJECT_KEY_OR_END: + throw std::logic_error( "expected key() or end_object(), but end_array() was called" ); + case EXPECT_OBJECT_VALUE: + throw std::logic_error( "expected any value, but end_array() was called" ); + case EXPECT_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but end_array() was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but end_array() was called" ); + } + throw std::logic_error( "invalid state" ); + } + + void begin_object( const std::size_t = 0 ) + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + stack.push_back( EXPECT_NOTHING ); + state = EXPECT_OBJECT_KEY_OR_END; + return; + case EXPECT_ARRAY_VALUE_OR_END: + stack.push_back( EXPECT_ARRAY_ELEMENT ); + state = EXPECT_OBJECT_KEY_OR_END; + return; + case EXPECT_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but begin_object() was called" ); + case EXPECT_OBJECT_KEY_OR_END: + throw std::logic_error( "expected key() or end_object(), but begin_object() was called" ); + case EXPECT_OBJECT_VALUE: + stack.push_back( EXPECT_OBJECT_MEMBER ); + state = EXPECT_OBJECT_KEY_OR_END; + return; + case EXPECT_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but begin_object() was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but begin_object() was called" ); + } + throw std::logic_error( "invalid state" ); + } + + void key( const tao::string_view ) + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + throw std::logic_error( "expected any value, but key() was called" ); + case EXPECT_ARRAY_VALUE_OR_END: + throw std::logic_error( "expected any value or end_array(), but key() was called" ); + case EXPECT_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but key() was called" ); + case EXPECT_OBJECT_KEY_OR_END: + state = EXPECT_OBJECT_VALUE; + return; + case EXPECT_OBJECT_VALUE: + throw std::logic_error( "expected any value, but key() was called" ); + case EXPECT_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but key() was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but key() was called" ); + } + throw std::logic_error( "invalid state" ); + } + + void member() + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + throw std::logic_error( "expected any value, but member() was called" ); + case EXPECT_ARRAY_VALUE_OR_END: + throw std::logic_error( "expected any value or end_array(), but member() was called" ); + case EXPECT_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but member() was called" ); + case EXPECT_OBJECT_KEY_OR_END: + throw std::logic_error( "expected key() or end_object(), but member() was called" ); + case EXPECT_OBJECT_VALUE: + throw std::logic_error( "expected any value, but member() was called" ); + case EXPECT_OBJECT_MEMBER: + state = EXPECT_OBJECT_KEY_OR_END; + return; + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but member() was called" ); + } + throw std::logic_error( "invalid state" ); + } + + void end_object( const std::size_t = 0 ) + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + throw std::logic_error( "expected any value, but end_object() was called" ); + case EXPECT_ARRAY_VALUE_OR_END: + throw std::logic_error( "expected any value or end_array(), but end_object() was called" ); + case EXPECT_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but end_object() was called" ); + case EXPECT_OBJECT_KEY_OR_END: + state = stack.back(); + stack.pop_back(); + return; + case EXPECT_OBJECT_VALUE: + throw std::logic_error( "expected any value, but end_object() was called" ); + case EXPECT_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but end_object() was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but end_object() was called" ); + } + throw std::logic_error( "invalid state" ); + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/events/validate_keys.hpp b/include/tao/json/events/validate_keys.hpp new file mode 100644 index 00000000..8c6ec000 --- /dev/null +++ b/include/tao/json/events/validate_keys.hpp @@ -0,0 +1,58 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_EVENTS_VALIDATE_KEYS_HPP +#define TAOCPP_JSON_INCLUDE_EVENTS_VALIDATE_KEYS_HPP + +#include +#include +#include + +#include "../external/pegtl.hpp" + +namespace tao +{ + namespace json + { + namespace events + { + template< typename Consumer, typename Rule > + struct validate_keys + : public Consumer + { + using Consumer::Consumer; + + void validate_key( const tao::string_view v ) + { + json_pegtl::memory_input< json_pegtl::tracking_mode::LAZY > in( v.data(), v.size(), __PRETTY_FUNCTION__ ); + if( !json_pegtl::parse< Rule >( in ) ) { + throw std::runtime_error( "invalid key: " + std::string( v.data(), v.size() ) ); + } + } + + void key( const tao::string_view v ) + { + validate_key( v ); + Consumer::key( v ); + } + + void key( const char* v ) + { + validate_key( v ); + Consumer::key( v ); + } + + void key( std::string&& v ) + { + validate_key( v ); + Consumer::key( std::move( v ) ); + } + }; + + } // namespace events + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/external/akrzemi1/CMakeLists.txt b/include/tao/json/external/akrzemi1/CMakeLists.txt new file mode 100644 index 00000000..1af707f6 --- /dev/null +++ b/include/tao/json/external/akrzemi1/CMakeLists.txt @@ -0,0 +1,46 @@ +# if CMAKE_VERSION >= 3.0 this project installs an INTERFACE target for +# the optional.hpp file. +# +# Usage: +# +# In your project's CMakeLists.txt: +# +# find_package(akrzemi1_optional REQUIRED) +# ... +# target_link_libraries(mytarget ... akrzemi1::optional ...) +# +# In your C++ source file: +# +# #include "akrzemi1/optional.hpp" +# + +project(optional) +cmake_minimum_required(VERSION 2.8) +enable_testing() + +if(CMAKE_VERSION VERSION_LESS 3.1) + set(CMAKE_CXX_FLAGS "-std=c++11") +elseif(NOT CMAKE_CXX_STANDARD) # don't override c++ standard if already set + set(CMAKE_CXX_STANDARD 11) +endif() + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") + +# if CMAKE_VERSION >= 3.0 +if(NOT (CMAKE_VERSION VERSION_LESS 3.0)) + add_library(optional INTERFACE) + target_include_directories(optional INTERFACE + $ + $) + install(TARGETS optional EXPORT optional-targets) + install(EXPORT optional-targets DESTINATION lib/cmake/akrzemi1_optional + FILE akrzemi1_optional-config.cmake + NAMESPACE akrzemi1::) + install(FILES optional.hpp DESTINATION include/akrzemi1) +endif() + +add_executable(test_optional test_optional.cpp) +add_executable(test_type_traits test_type_traits.cpp) + +add_test(test_optional test_optional) +add_test(test_type_traits test_type_traits) diff --git a/include/tao/json/external/akrzemi1/LICENSE b/include/tao/json/external/akrzemi1/LICENSE new file mode 100644 index 00000000..36b7cd93 --- /dev/null +++ b/include/tao/json/external/akrzemi1/LICENSE @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/include/tao/json/external/akrzemi1/LICENSE_1_0.txt b/include/tao/json/external/akrzemi1/LICENSE_1_0.txt new file mode 100644 index 00000000..36b7cd93 --- /dev/null +++ b/include/tao/json/external/akrzemi1/LICENSE_1_0.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/include/tao/json/external/akrzemi1/README.md b/include/tao/json/external/akrzemi1/README.md new file mode 100644 index 00000000..881390ae --- /dev/null +++ b/include/tao/json/external/akrzemi1/README.md @@ -0,0 +1,39 @@ +Optional +======== + +A single-header header-only library for representing optional (nullable) objects for C++14 (and C++11 to some extent) and passing them by value. This is the reference implementation of proposal N3793 (see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3793.html). Optional is now accepted into Library Fundamentals Technical Specification (see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3848.html). The interface is based on Fernando Cacciola's Boost.Optional library (see http://www.boost.org/doc/libs/1_52_0/libs/optional/doc/html/index.html) + + +Usage +----- + +```cpp +optional readInt(); // this function may return int or a not-an-int + +if (optional oi = readInt()) // did I get a real int + cout << "my int is: " << *oi; // use my int +else + cout << "I have no int"; +``` + +For more usage examples and the overview see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3527.html + + +Supported compilers +------------------- + +Clang 3.2, Clang 3.4, G++ 4.7.2, G++ 4.8.1. Tested only with libstdc++, versions 20130531, 20120920, 20110428. Others have reported it also works with libc++. + + + +Known Issues +------------ + + - Currently, the reference (and the only known) implementation of certain pieces of functionality explore what C++11 identifies as undefined behavior (see national body comment FI 15: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3770.html#FI15). This is mostly why Optional was removed from C++14 and put into Library Fundamentals TS. Luckily what the Standard identifies as UB is well defined on all known platforms. We expect that the C++14 wil fix this problem, so that our trick becomes well-defined. + - In libstdc++ versions below 20130531 the constructor taking `initializer_list` argument is not `constexpr`. This is because `initializer_list` operations are not `constexpr` in C++11. This works however in version 20130531. It is also not enabled for libc++ because I do not have access to it and do not know if it provides `constexpr` `initializer_list`. + - In G++ 4.7.2 and 4.8.0 member function `value_or` does not have rvalue reference overload. These compilers do not support rvalue overloding on `*this`. + - In order for the library to work with slightly older compilers, we emulate some missing type traits. On some platforms we cannot correctly detect the available features, and attempts at workarounds for missing type trait definitions can cause compile-time errors. Define macro `TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS` if you know that all the necessary type traits are defined, and no emulation is required. + +License +------- +Distributed under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt). diff --git a/include/tao/json/external/akrzemi1/copyright.txt b/include/tao/json/external/akrzemi1/copyright.txt new file mode 100644 index 00000000..b1088ac0 --- /dev/null +++ b/include/tao/json/external/akrzemi1/copyright.txt @@ -0,0 +1,10 @@ +Copyright (C) 2011-2016 Andrzej Krzemienski + +Distributed under the Boost Software License, Version 1.0 +(see accompanying file LICENSE_1_0.txt or a copy at +http://www.boost.org/LICENSE_1_0.txt) + +The idea and interface is based on Boost.Optional library +authored by Fernando Luis Cacciola Carballal + +Home at https://github.com/akrzemi1/Optional diff --git a/include/tao/json/external/akrzemi1/optional.hpp b/include/tao/json/external/akrzemi1/optional.hpp new file mode 100644 index 00000000..7b9148f3 --- /dev/null +++ b/include/tao/json/external/akrzemi1/optional.hpp @@ -0,0 +1,1052 @@ +// Copyright (C) 2011 - 2012 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The idea and interface is based on Boost.Optional library +// authored by Fernando Luis Cacciola Carballal + +# ifndef ___OPTIONAL_HPP___ +# define ___OPTIONAL_HPP___ + +# include +# include +# include +# include +# include +# include +# include + +# define TR2_OPTIONAL_REQUIRES(...) typename enable_if<__VA_ARGS__::value, bool>::type = false + +# if defined __GNUC__ // NOTE: GNUC is also defined for Clang +# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) +# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ +# elif (__GNUC__ > 4) +# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ +# endif +# +# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7) +# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ +# elif (__GNUC__ > 4) +# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ +# endif +# +# if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1) +# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9) +# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# elif (__GNUC__ > 4) +# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# endif +# endif +# +# if defined __clang_major__ +# if (__clang_major__ == 3 && __clang_minor__ >= 5) +# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +# elif (__clang_major__ > 3) +# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +# endif +# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ +# elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2) +# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ +# endif +# endif +# +# if defined _MSC_VER +# if (_MSC_VER >= 1900) +# define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ +# endif +# endif + +# if defined __clang__ +# if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9) +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# else +# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 +# endif +# elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# else +# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 +# endif + + +# if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1 +# define OPTIONAL_CONSTEXPR_INIT_LIST constexpr +# else +# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0 +# define OPTIONAL_CONSTEXPR_INIT_LIST +# endif + +# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L) +# define OPTIONAL_HAS_MOVE_ACCESSORS 1 +# else +# define OPTIONAL_HAS_MOVE_ACCESSORS 0 +# endif + +# // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr +# if (defined __cplusplus) && (__cplusplus == 201103L) +# define OPTIONAL_MUTABLE_CONSTEXPR +# else +# define OPTIONAL_MUTABLE_CONSTEXPR constexpr +# endif + +namespace std{ + +namespace experimental{ + +// BEGIN workaround for missing is_trivially_destructible +# if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ + // leave it: it is already there +# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ + // leave it: it is already there +# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ + // leave it: it is already there +# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS + // leave it: the user doesn't want it +# else + template + using is_trivially_destructible = std::has_trivial_destructor; +# endif +// END workaround for missing is_trivially_destructible + +# if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___) + // leave it; our metafunctions are already defined. +# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ + // leave it; our metafunctions are already defined. +# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ + // leave it: it is already there +# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS + // leave it: the user doesn't want it +# else + + +// workaround for missing traits in GCC and CLANG +template +struct is_nothrow_move_constructible +{ + constexpr static bool value = std::is_nothrow_constructible::value; +}; + + +template +struct is_assignable +{ + template + constexpr static bool has_assign(...) { return false; } + + template () = std::declval(), true)) > + // the comma operator is necessary for the cases where operator= returns void + constexpr static bool has_assign(bool) { return true; } + + constexpr static bool value = has_assign(true); +}; + + +template +struct is_nothrow_move_assignable +{ + template + struct has_nothrow_move_assign { + constexpr static bool value = false; + }; + + template + struct has_nothrow_move_assign { + constexpr static bool value = noexcept( std::declval() = std::declval() ); + }; + + constexpr static bool value = has_nothrow_move_assign::value>::value; +}; +// end workaround + + +# endif + + + +// 20.5.4, optional for object types +template class optional; + +// 20.5.5, optional for lvalue reference types +template class optional; + + +// workaround: std utility functions aren't constexpr yet +template inline constexpr T&& constexpr_forward(typename std::remove_reference::type& t) noexcept +{ + return static_cast(t); +} + +template inline constexpr T&& constexpr_forward(typename std::remove_reference::type&& t) noexcept +{ + static_assert(!std::is_lvalue_reference::value, "!!"); + return static_cast(t); +} + +template inline constexpr typename std::remove_reference::type&& constexpr_move(T&& t) noexcept +{ + return static_cast::type&&>(t); +} + + +#if defined NDEBUG +# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) +#else +# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR))) +#endif + + +namespace detail_ +{ + +// static_addressof: a constexpr version of addressof +template +struct has_overloaded_addressof +{ + template + constexpr static bool has_overload(...) { return false; } + + template ().operator&()) > + constexpr static bool has_overload(bool) { return true; } + + constexpr static bool value = has_overload(true); +}; + +template )> +constexpr T* static_addressof(T& ref) +{ + return &ref; +} + +template )> +T* static_addressof(T& ref) +{ + return std::addressof(ref); +} + + +// the call to convert(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A +template +constexpr U convert(U v) { return v; } + +} // namespace detail + + +constexpr struct trivial_init_t{} trivial_init{}; + + +// 20.5.6, In-place construction +constexpr struct in_place_t{} in_place{}; + + +// 20.5.7, Disengaged state indicator +struct nullopt_t +{ + struct init{}; + constexpr explicit nullopt_t(init){} +}; +constexpr nullopt_t nullopt{nullopt_t::init()}; + + +// 20.5.8, class bad_optional_access +class bad_optional_access : public logic_error { +public: + explicit bad_optional_access(const string& what_arg) : logic_error{what_arg} {} + explicit bad_optional_access(const char* what_arg) : logic_error{what_arg} {} +}; + + +template +union storage_t +{ + unsigned char dummy_; + T value_; + + constexpr storage_t( trivial_init_t ) noexcept : dummy_() {}; + + template + constexpr storage_t( Args&&... args ) : value_(constexpr_forward(args)...) {} + + ~storage_t(){} +}; + + +template +union constexpr_storage_t +{ + unsigned char dummy_; + T value_; + + constexpr constexpr_storage_t( trivial_init_t ) noexcept : dummy_() {}; + + template + constexpr constexpr_storage_t( Args&&... args ) : value_(constexpr_forward(args)...) {} + + ~constexpr_storage_t() = default; +}; + + +template +struct optional_base +{ + bool init_; + storage_t storage_; + + constexpr optional_base() noexcept : init_(false), storage_(trivial_init) {}; + + explicit constexpr optional_base(const T& v) : init_(true), storage_(v) {} + + explicit constexpr optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} + + template explicit optional_base(in_place_t, Args&&... args) + : init_(true), storage_(constexpr_forward(args)...) {} + + template >)> + explicit optional_base(in_place_t, std::initializer_list il, Args&&... args) + : init_(true), storage_(il, std::forward(args)...) {} + + ~optional_base() { if (init_) storage_.value_.T::~T(); } +}; + + +template +struct constexpr_optional_base +{ + bool init_; + constexpr_storage_t storage_; + + constexpr constexpr_optional_base() noexcept : init_(false), storage_(trivial_init) {}; + + explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_(v) {} + + explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} + + template explicit constexpr constexpr_optional_base(in_place_t, Args&&... args) + : init_(true), storage_(constexpr_forward(args)...) {} + + template >)> + OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, std::initializer_list il, Args&&... args) + : init_(true), storage_(il, std::forward(args)...) {} + + ~constexpr_optional_base() = default; +}; + +template +using OptionalBase = typename std::conditional< + is_trivially_destructible::value, // if possible + constexpr_optional_base::type>, // use base with trivial destructor + optional_base::type> +>::type; + + + +template +class optional : private OptionalBase +{ + static_assert( !std::is_same::type, nullopt_t>::value, "bad T" ); + static_assert( !std::is_same::type, in_place_t>::value, "bad T" ); + + + constexpr bool initialized() const noexcept { return OptionalBase::init_; } + typename std::remove_const::type* dataptr() { return std::addressof(OptionalBase::storage_.value_); } + constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase::storage_.value_); } + +# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 + constexpr const T& contained_val() const& { return OptionalBase::storage_.value_; } +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return std::move(OptionalBase::storage_.value_); } + OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase::storage_.value_; } +# else + T& contained_val() & { return OptionalBase::storage_.value_; } + T&& contained_val() && { return std::move(OptionalBase::storage_.value_); } +# endif +# else + constexpr const T& contained_val() const { return OptionalBase::storage_.value_; } + T& contained_val() { return OptionalBase::storage_.value_; } +# endif + + void clear() noexcept { + if (initialized()) dataptr()->T::~T(); + OptionalBase::init_ = false; + } + + template + void initialize(Args&&... args) noexcept(noexcept(T(std::forward(args)...))) + { + assert(!OptionalBase::init_); + ::new (static_cast(dataptr())) T(std::forward(args)...); + OptionalBase::init_ = true; + } + + template + void initialize(std::initializer_list il, Args&&... args) noexcept(noexcept(T(il, std::forward(args)...))) + { + assert(!OptionalBase::init_); + ::new (static_cast(dataptr())) T(il, std::forward(args)...); + OptionalBase::init_ = true; + } + +public: + typedef T value_type; + + // 20.5.5.1, constructors + constexpr optional() noexcept : OptionalBase() {}; + constexpr optional(nullopt_t) noexcept : OptionalBase() {}; + + optional(const optional& rhs) + : OptionalBase() + { + if (rhs.initialized()) { + ::new (static_cast(dataptr())) T(*rhs); + OptionalBase::init_ = true; + } + } + + optional(optional&& rhs) noexcept(is_nothrow_move_constructible::value) + : OptionalBase() + { + if (rhs.initialized()) { + ::new (static_cast(dataptr())) T(std::move(*rhs)); + OptionalBase::init_ = true; + } + } + + constexpr optional(const T& v) : OptionalBase(v) {} + + constexpr optional(T&& v) : OptionalBase(constexpr_move(v)) {} + + template + explicit constexpr optional(in_place_t, Args&&... args) + : OptionalBase(in_place_t{}, constexpr_forward(args)...) {} + + template >)> + OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, std::initializer_list il, Args&&... args) + : OptionalBase(in_place_t{}, il, constexpr_forward(args)...) {} + + // 20.5.4.2, Destructor + ~optional() = default; + + // 20.5.4.3, assignment + optional& operator=(nullopt_t) noexcept + { + clear(); + return *this; + } + + optional& operator=(const optional& rhs) + { + if (initialized() == true && rhs.initialized() == false) clear(); + else if (initialized() == false && rhs.initialized() == true) initialize(*rhs); + else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs; + return *this; + } + + optional& operator=(optional&& rhs) + noexcept(is_nothrow_move_assignable::value && is_nothrow_move_constructible::value) + { + if (initialized() == true && rhs.initialized() == false) clear(); + else if (initialized() == false && rhs.initialized() == true) initialize(std::move(*rhs)); + else if (initialized() == true && rhs.initialized() == true) contained_val() = std::move(*rhs); + return *this; + } + + template + auto operator=(U&& v) + -> typename enable_if + < + is_same::type, T>::value, + optional& + >::type + { + if (initialized()) { contained_val() = std::forward(v); } + else { initialize(std::forward(v)); } + return *this; + } + + + template + void emplace(Args&&... args) + { + clear(); + initialize(std::forward(args)...); + } + + template + void emplace(initializer_list il, Args&&... args) + { + clear(); + initialize(il, std::forward(args)...); + } + + // 20.5.4.4, Swap + void swap(optional& rhs) noexcept(is_nothrow_move_constructible::value && noexcept(swap(declval(), declval()))) + { + if (initialized() == true && rhs.initialized() == false) { rhs.initialize(std::move(**this)); clear(); } + else if (initialized() == false && rhs.initialized() == true) { initialize(std::move(*rhs)); rhs.clear(); } + else if (initialized() == true && rhs.initialized() == true) { using std::swap; swap(**this, *rhs); } + } + + // 20.5.4.5, Observers + + explicit constexpr operator bool() const noexcept { return initialized(); } + constexpr bool has_value() const noexcept { return initialized(); } + + constexpr T const* operator ->() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr()); + } + +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + + OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() { + assert (initialized()); + return dataptr(); + } + + constexpr T const& operator *() const& { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); + } + + OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & { + assert (initialized()); + return contained_val(); + } + + OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && { + assert (initialized()); + return constexpr_move(contained_val()); + } + + constexpr T const& value() const& { + return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); + } + + OPTIONAL_MUTABLE_CONSTEXPR T& value() & { + return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); + } + + OPTIONAL_MUTABLE_CONSTEXPR T&& value() && { + if (!initialized()) throw bad_optional_access("bad optional access"); + return std::move(contained_val()); + } + +# else + + T* operator ->() { + assert (initialized()); + return dataptr(); + } + + constexpr T const& operator *() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); + } + + T& operator *() { + assert (initialized()); + return contained_val(); + } + + constexpr T const& value() const { + return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); + } + + T& value() { + return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); + } + +# endif + +# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 + + template + constexpr T value_or(V&& v) const& + { + return *this ? **this : detail_::convert(constexpr_forward(v)); + } + +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + + template + OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) && + { + return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v)); + } + +# else + + template + T value_or(V&& v) && + { + return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v)); + } + +# endif + +# else + + template + constexpr T value_or(V&& v) const + { + return *this ? **this : detail_::convert(constexpr_forward(v)); + } + +# endif + + // 20.6.3.6, modifiers + void reset() noexcept { clear(); } +}; + + +template +class optional +{ + static_assert( !std::is_same::value, "bad T" ); + static_assert( !std::is_same::value, "bad T" ); + T* ref; + +public: + + // 20.5.5.1, construction/destruction + constexpr optional() noexcept : ref(nullptr) {} + + constexpr optional(nullopt_t) noexcept : ref(nullptr) {} + + constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {} + + optional(T&&) = delete; + + constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {} + + explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {} + + explicit optional(in_place_t, T&&) = delete; + + ~optional() = default; + + // 20.5.5.2, mutation + optional& operator=(nullopt_t) noexcept { + ref = nullptr; + return *this; + } + + // optional& operator=(const optional& rhs) noexcept { + // ref = rhs.ref; + // return *this; + // } + + // optional& operator=(optional&& rhs) noexcept { + // ref = rhs.ref; + // return *this; + // } + + template + auto operator=(U&& rhs) noexcept + -> typename enable_if + < + is_same::type, optional>::value, + optional& + >::type + { + ref = rhs.ref; + return *this; + } + + template + auto operator=(U&& rhs) noexcept + -> typename enable_if + < + !is_same::type, optional>::value, + optional& + >::type + = delete; + + void emplace(T& v) noexcept { + ref = detail_::static_addressof(v); + } + + void emplace(T&&) = delete; + + + void swap(optional& rhs) noexcept + { + std::swap(ref, rhs.ref); + } + + // 20.5.5.3, observers + constexpr T* operator->() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref); + } + + constexpr T& operator*() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref); + } + + constexpr T& value() const { + return ref ? *ref : (throw bad_optional_access("bad optional access"), *ref); + } + + explicit constexpr operator bool() const noexcept { + return ref != nullptr; + } + + constexpr bool has_value() const noexcept { + return ref != nullptr; + } + + template + constexpr typename decay::type value_or(V&& v) const + { + return *this ? **this : detail_::convert::type>(constexpr_forward(v)); + } + + // x.x.x.x, modifiers + void reset() noexcept { ref = nullptr; } +}; + + +template +class optional +{ + static_assert( sizeof(T) == 0, "optional rvalue references disallowed" ); +}; + + +// 20.5.8, Relational operators +template constexpr bool operator==(const optional& x, const optional& y) +{ + return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y; +} + +template constexpr bool operator!=(const optional& x, const optional& y) +{ + return !(x == y); +} + +template constexpr bool operator<(const optional& x, const optional& y) +{ + return (!y) ? false : (!x) ? true : *x < *y; +} + +template constexpr bool operator>(const optional& x, const optional& y) +{ + return (y < x); +} + +template constexpr bool operator<=(const optional& x, const optional& y) +{ + return !(y < x); +} + +template constexpr bool operator>=(const optional& x, const optional& y) +{ + return !(x < y); +} + + +// 20.5.9, Comparison with nullopt +template constexpr bool operator==(const optional& x, nullopt_t) noexcept +{ + return (!x); +} + +template constexpr bool operator==(nullopt_t, const optional& x) noexcept +{ + return (!x); +} + +template constexpr bool operator!=(const optional& x, nullopt_t) noexcept +{ + return bool(x); +} + +template constexpr bool operator!=(nullopt_t, const optional& x) noexcept +{ + return bool(x); +} + +template constexpr bool operator<(const optional&, nullopt_t) noexcept +{ + return false; +} + +template constexpr bool operator<(nullopt_t, const optional& x) noexcept +{ + return bool(x); +} + +template constexpr bool operator<=(const optional& x, nullopt_t) noexcept +{ + return (!x); +} + +template constexpr bool operator<=(nullopt_t, const optional&) noexcept +{ + return true; +} + +template constexpr bool operator>(const optional& x, nullopt_t) noexcept +{ + return bool(x); +} + +template constexpr bool operator>(nullopt_t, const optional&) noexcept +{ + return false; +} + +template constexpr bool operator>=(const optional&, nullopt_t) noexcept +{ + return true; +} + +template constexpr bool operator>=(nullopt_t, const optional& x) noexcept +{ + return (!x); +} + + + +// 20.5.10, Comparison with T +template constexpr bool operator==(const optional& x, const T& v) +{ + return bool(x) ? *x == v : false; +} + +template constexpr bool operator==(const T& v, const optional& x) +{ + return bool(x) ? v == *x : false; +} + +template constexpr bool operator!=(const optional& x, const T& v) +{ + return bool(x) ? *x != v : true; +} + +template constexpr bool operator!=(const T& v, const optional& x) +{ + return bool(x) ? v != *x : true; +} + +template constexpr bool operator<(const optional& x, const T& v) +{ + return bool(x) ? *x < v : true; +} + +template constexpr bool operator>(const T& v, const optional& x) +{ + return bool(x) ? v > *x : true; +} + +template constexpr bool operator>(const optional& x, const T& v) +{ + return bool(x) ? *x > v : false; +} + +template constexpr bool operator<(const T& v, const optional& x) +{ + return bool(x) ? v < *x : false; +} + +template constexpr bool operator>=(const optional& x, const T& v) +{ + return bool(x) ? *x >= v : false; +} + +template constexpr bool operator<=(const T& v, const optional& x) +{ + return bool(x) ? v <= *x : false; +} + +template constexpr bool operator<=(const optional& x, const T& v) +{ + return bool(x) ? *x <= v : true; +} + +template constexpr bool operator>=(const T& v, const optional& x) +{ + return bool(x) ? v >= *x : true; +} + + +// Comparison of optional with T +template constexpr bool operator==(const optional& x, const T& v) +{ + return bool(x) ? *x == v : false; +} + +template constexpr bool operator==(const T& v, const optional& x) +{ + return bool(x) ? v == *x : false; +} + +template constexpr bool operator!=(const optional& x, const T& v) +{ + return bool(x) ? *x != v : true; +} + +template constexpr bool operator!=(const T& v, const optional& x) +{ + return bool(x) ? v != *x : true; +} + +template constexpr bool operator<(const optional& x, const T& v) +{ + return bool(x) ? *x < v : true; +} + +template constexpr bool operator>(const T& v, const optional& x) +{ + return bool(x) ? v > *x : true; +} + +template constexpr bool operator>(const optional& x, const T& v) +{ + return bool(x) ? *x > v : false; +} + +template constexpr bool operator<(const T& v, const optional& x) +{ + return bool(x) ? v < *x : false; +} + +template constexpr bool operator>=(const optional& x, const T& v) +{ + return bool(x) ? *x >= v : false; +} + +template constexpr bool operator<=(const T& v, const optional& x) +{ + return bool(x) ? v <= *x : false; +} + +template constexpr bool operator<=(const optional& x, const T& v) +{ + return bool(x) ? *x <= v : true; +} + +template constexpr bool operator>=(const T& v, const optional& x) +{ + return bool(x) ? v >= *x : true; +} + +// Comparison of optional with T +template constexpr bool operator==(const optional& x, const T& v) +{ + return bool(x) ? *x == v : false; +} + +template constexpr bool operator==(const T& v, const optional& x) +{ + return bool(x) ? v == *x : false; +} + +template constexpr bool operator!=(const optional& x, const T& v) +{ + return bool(x) ? *x != v : true; +} + +template constexpr bool operator!=(const T& v, const optional& x) +{ + return bool(x) ? v != *x : true; +} + +template constexpr bool operator<(const optional& x, const T& v) +{ + return bool(x) ? *x < v : true; +} + +template constexpr bool operator>(const T& v, const optional& x) +{ + return bool(x) ? v > *x : true; +} + +template constexpr bool operator>(const optional& x, const T& v) +{ + return bool(x) ? *x > v : false; +} + +template constexpr bool operator<(const T& v, const optional& x) +{ + return bool(x) ? v < *x : false; +} + +template constexpr bool operator>=(const optional& x, const T& v) +{ + return bool(x) ? *x >= v : false; +} + +template constexpr bool operator<=(const T& v, const optional& x) +{ + return bool(x) ? v <= *x : false; +} + +template constexpr bool operator<=(const optional& x, const T& v) +{ + return bool(x) ? *x <= v : true; +} + +template constexpr bool operator>=(const T& v, const optional& x) +{ + return bool(x) ? v >= *x : true; +} + + +// 20.5.12, Specialized algorithms +template +void swap(optional& x, optional& y) noexcept(noexcept(x.swap(y))) +{ + x.swap(y); +} + + +template +constexpr optional::type> make_optional(T&& v) +{ + return optional::type>(constexpr_forward(v)); +} + +template +constexpr optional make_optional(reference_wrapper v) +{ + return optional(v.get()); +} + + +} // namespace experimental +} // namespace std + +namespace std +{ + template + struct hash> + { + typedef typename hash::result_type result_type; + typedef std::experimental::optional argument_type; + + constexpr result_type operator()(argument_type const& arg) const { + return arg ? std::hash{}(*arg) : result_type{}; + } + }; + + template + struct hash> + { + typedef typename hash::result_type result_type; + typedef std::experimental::optional argument_type; + + constexpr result_type operator()(argument_type const& arg) const { + return arg ? std::hash{}(*arg) : result_type{}; + } + }; +} + +# undef TR2_OPTIONAL_REQUIRES +# undef TR2_OPTIONAL_ASSERTED_EXPRESSION + +# endif //___OPTIONAL_HPP___ diff --git a/include/tao/json/external/akrzemi1/test_optional.cpp b/include/tao/json/external/akrzemi1/test_optional.cpp new file mode 100644 index 00000000..1b2d6cc1 --- /dev/null +++ b/include/tao/json/external/akrzemi1/test_optional.cpp @@ -0,0 +1,1520 @@ +// Copyright (C) 2011 - 2016 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The idea and interface is based on Boost.Optional library +// authored by Fernando Luis Cacciola Carballal + +# include "optional.hpp" +# include +# include +# include +# include + + + +struct caller { + template caller(T fun) { fun(); } +}; +# define CAT2(X, Y) X ## Y +# define CAT(X, Y) CAT2(X, Y) +# define TEST(NAME) caller CAT(__VAR, __LINE__) = [] + +enum State +{ + sDefaultConstructed, + sValueCopyConstructed, + sValueMoveConstructed, + sCopyConstructed, + sMoveConstructed, + sMoveAssigned, + sCopyAssigned, + sValueCopyAssigned, + sValueMoveAssigned, + sMovedFrom, + sValueConstructed +}; + +struct OracleVal +{ + State s; + int i; + OracleVal(int i = 0) : s(sValueConstructed), i(i) {} +}; + +struct Oracle +{ + State s; + OracleVal val; + + Oracle() : s(sDefaultConstructed) {} + Oracle(const OracleVal& v) : s(sValueCopyConstructed), val(v) {} + Oracle(OracleVal&& v) : s(sValueMoveConstructed), val(std::move(v)) {v.s = sMovedFrom;} + Oracle(const Oracle& o) : s(sCopyConstructed), val(o.val) {} + Oracle(Oracle&& o) : s(sMoveConstructed), val(std::move(o.val)) {o.s = sMovedFrom;} + + Oracle& operator=(const OracleVal& v) { s = sValueCopyConstructed; val = v; return *this; } + Oracle& operator=(OracleVal&& v) { s = sValueMoveConstructed; val = std::move(v); v.s = sMovedFrom; return *this; } + Oracle& operator=(const Oracle& o) { s = sCopyConstructed; val = o.val; return *this; } + Oracle& operator=(Oracle&& o) { s = sMoveConstructed; val = std::move(o.val); o.s = sMovedFrom; return *this; } +}; + +struct Guard +{ + std::string val; + Guard() : val{} {} + explicit Guard(std::string s, int = 0) : val(s) {} + Guard(const Guard&) = delete; + Guard(Guard&&) = delete; + void operator=(const Guard&) = delete; + void operator=(Guard&&) = delete; +}; + +struct ExplicitStr +{ + std::string s; + explicit ExplicitStr(const char* chp) : s(chp) {}; +}; + +struct Date +{ + int i; + Date() = delete; + Date(int i) : i{i} {}; + Date(Date&& d) : i(d.i) { d.i = 0; } + Date(const Date&) = delete; + Date& operator=(const Date&) = delete; + Date& operator=(Date&& d) { i = d.i; d.i = 0; return *this;}; +}; + +bool operator==( Oracle const& a, Oracle const& b ) { return a.val.i == b.val.i; } +bool operator!=( Oracle const& a, Oracle const& b ) { return a.val.i != b.val.i; } + + +namespace tr2 = std::experimental; + + +TEST(disengaged_ctor) +{ + tr2::optional o1; + assert (!o1); + + tr2::optional o2 = tr2::nullopt; + assert (!o2); + + tr2::optional o3 = o2; + assert (!o3); + + assert (o1 == tr2::nullopt); + assert (o1 == tr2::optional{}); + assert (!o1); + assert (bool(o1) == false); + + assert (o2 == tr2::nullopt); + assert (o2 == tr2::optional{}); + assert (!o2); + assert (bool(o2) == false); + + assert (o3 == tr2::nullopt); + assert (o3 == tr2::optional{}); + assert (!o3); + assert (bool(o3) == false); + + assert (o1 == o2); + assert (o2 == o1); + assert (o1 == o3); + assert (o3 == o1); + assert (o2 == o3); + assert (o3 == o2); +}; + + +TEST(value_ctor) +{ + OracleVal v; + tr2::optional oo1(v); + assert (oo1 != tr2::nullopt); + assert (oo1 != tr2::optional{}); + assert (oo1 == tr2::optional{v}); + assert (!!oo1); + assert (bool(oo1)); + // NA: assert (oo1->s == sValueCopyConstructed); + assert (oo1->s == sMoveConstructed); + assert (v.s == sValueConstructed); + + tr2::optional oo2(std::move(v)); + assert (oo2 != tr2::nullopt); + assert (oo2 != tr2::optional{}); + assert (oo2 == oo1); + assert (!!oo2); + assert (bool(oo2)); + // NA: assert (oo2->s == sValueMoveConstructed); + assert (oo2->s == sMoveConstructed); + assert (v.s == sMovedFrom); + + { + OracleVal v; + tr2::optional oo1{tr2::in_place, v}; + assert (oo1 != tr2::nullopt); + assert (oo1 != tr2::optional{}); + assert (oo1 == tr2::optional{v}); + assert (!!oo1); + assert (bool(oo1)); + assert (oo1->s == sValueCopyConstructed); + assert (v.s == sValueConstructed); + + tr2::optional oo2{tr2::in_place, std::move(v)}; + assert (oo2 != tr2::nullopt); + assert (oo2 != tr2::optional{}); + assert (oo2 == oo1); + assert (!!oo2); + assert (bool(oo2)); + assert (oo2->s == sValueMoveConstructed); + assert (v.s == sMovedFrom); + } +}; + + +TEST(assignment) +{ + tr2::optional oi; + oi = tr2::optional{1}; + assert (*oi == 1); + + oi = tr2::nullopt; + assert (!oi); + + oi = 2; + assert (*oi == 2); + + oi = {}; + assert (!oi); +}; + + +template +struct MoveAware +{ + T val; + bool moved; + MoveAware(T val) : val(val), moved(false) {} + MoveAware(MoveAware const&) = delete; + MoveAware(MoveAware&& rhs) : val(rhs.val), moved(rhs.moved) { + rhs.moved = true; + } + MoveAware& operator=(MoveAware const&) = delete; + MoveAware& operator=(MoveAware&& rhs) { + val = (rhs.val); + moved = (rhs.moved); + rhs.moved = true; + return *this; + } +}; + +TEST(moved_from_state) +{ + // first, test mock: + MoveAware i{1}, j{2}; + assert (i.val == 1); + assert (!i.moved); + assert (j.val == 2); + assert (!j.moved); + + MoveAware k = std::move(i); + assert (k.val == 1); + assert (!k.moved); + assert (i.val == 1); + assert (i.moved); + + k = std::move(j); + assert (k.val == 2); + assert (!k.moved); + assert (j.val == 2); + assert (j.moved); + + // now, test optional + tr2::optional> oi{1}, oj{2}; + assert (oi); + assert (!oi->moved); + assert (oj); + assert (!oj->moved); + + tr2::optional> ok = std::move(oi); + assert (ok); + assert (!ok->moved); + assert (oi); + assert (oi->moved); + + ok = std::move(oj); + assert (ok); + assert (!ok->moved); + assert (oj); + assert (oj->moved); +}; + + +TEST(copy_move_ctor_optional_int) +{ + tr2::optional oi; + tr2::optional oj = oi; + + assert (!oj); + assert (oj == oi); + assert (oj == tr2::nullopt); + assert (!bool(oj)); + + oi = 1; + tr2::optional ok = oi; + assert (!!ok); + assert (bool(ok)); + assert (ok == oi); + assert (ok != oj); + assert (*ok == 1); + + tr2::optional ol = std::move(oi); + assert (!!ol); + assert (bool(ol)); + assert (ol == oi); + assert (ol != oj); + assert (*ol == 1); +}; + + +TEST(optional_optional) +{ + tr2::optional> oi1 = tr2::nullopt; + assert (oi1 == tr2::nullopt); + assert (!oi1); + + { + tr2::optional> oi2 {tr2::in_place}; + assert (oi2 != tr2::nullopt); + assert (bool(oi2)); + assert (*oi2 == tr2::nullopt); + //assert (!(*oi2)); + //std::cout << typeid(**oi2).name() << std::endl; + } + + { + tr2::optional> oi2 {tr2::in_place, tr2::nullopt}; + assert (oi2 != tr2::nullopt); + assert (bool(oi2)); + assert (*oi2 == tr2::nullopt); + assert (!*oi2); + } + + { + tr2::optional> oi2 {tr2::optional{}}; + assert (oi2 != tr2::nullopt); + assert (bool(oi2)); + assert (*oi2 == tr2::nullopt); + assert (!*oi2); + } + + tr2::optional oi; + auto ooi = tr2::make_optional(oi); + static_assert( std::is_same>, decltype(ooi)>::value, ""); + +}; + +TEST(example_guard) +{ + using namespace tr2; + //FAILS: optional ogx(Guard("res1")); + //FAILS: optional ogx = "res1"; + //FAILS: optional ogx("res1"); + optional oga; // Guard is non-copyable (and non-moveable) + optional ogb(in_place, "res1"); // initialzes the contained value with "res1" + assert (bool(ogb)); + assert (ogb->val == "res1"); + + optional ogc(in_place); // default-constructs the contained value + assert (bool(ogc)); + assert (ogc->val == ""); + + oga.emplace("res1"); // initialzes the contained value with "res1" + assert (bool(oga)); + assert (oga->val == "res1"); + + oga.emplace(); // destroys the contained value and + // default-constructs the new one + assert (bool(oga)); + assert (oga->val == ""); + + oga = nullopt; // OK: make disengaged the optional Guard + assert (!(oga)); + //FAILS: ogb = {}; // ERROR: Guard is not Moveable +}; + + +void process(){} +void process(int ){} +void processNil(){} + + +TEST(example1) +{ + using namespace tr2; + optional oi; // create disengaged object + optional oj = nullopt; // alternative syntax + oi = oj; // assign disengaged object + optional ok = oj; // ok is disengaged + + if (oi) assert(false); // 'if oi is engaged...' + if (!oi) assert(true); // 'if oi is disengaged...' + + if (oi != nullopt) assert(false); // 'if oi is engaged...' + if (oi == nullopt) assert(true); // 'if oi is disengaged...' + + assert(oi == ok); // two disengaged optionals compare equal + + /////////////////////////////////////////////////////////////////////////// + optional ol{1}; // ol is engaged; its contained value is 1 + ok = 2; // ok becomes engaged; its contained value is 2 + oj = ol; // oj becomes engaged; its contained value is 1 + + assert(oi != ol); // disengaged != engaged + assert(ok != ol); // different contained values + assert(oj == ol); // same contained value + assert(oi < ol); // disengaged < engaged + assert(ol < ok); // less by contained value + + ///////////////////////////////////////////////////////////////////////////// + optional om{1}; // om is engaged; its contained value is 1 + optional on = om; // on is engaged; its contained value is 1 + om = 2; // om is engaged; its contained value is 2 + assert (on != om); // on still contains 3. They are not pointers + + ///////////////////////////////////////////////////////////////////////////// + int i = *ol; // i obtains the value contained in ol + assert (i == 1); + *ol = 9; // the object contained in ol becomes 9 + assert(*ol == 9); + assert(ol == make_optional(9)); + + /////////////////////////////////// + int p = 1; + optional op = p; + assert(*op == 1); + p = 2; + assert(*op == 1); // value contained in op is separated from p + + //////////////////////////////// + if (ol) + process(*ol); // use contained value if present + else + process(); // proceed without contained value + + if (!om) + processNil(); + else + process(*om); + + ///////////////////////////////////////// + process(ol.value_or(0)); // use 0 if ol is disengaged + + //////////////////////////////////////////// + ok = nullopt; // if ok was engaged calls T's dtor + oj = {}; // assigns a temporary disengaged optional +}; + + +TEST(example_guard) +{ + using std::experimental::optional; + const optional c = 4; + int i = *c; // i becomes 4 + assert (i == 4); + // FAILS: *c = i; // ERROR: cannot assign to const int& +}; + + +TEST(example_ref) +{ + using namespace std::experimental; + int i = 1; + int j = 2; + optional ora; // disengaged optional reference to int + optional orb = i; // contained reference refers to object i + + *orb = 3; // i becomes 3 + // FAILS: ora = j; // ERROR: optional refs do not have assignment from T + // FAILS: ora = {j}; // ERROR: optional refs do not have copy/move assignment + // FAILS: ora = orb; // ERROR: no copy/move assignment + ora.emplace(j); // OK: contained reference refers to object j + ora.emplace(i); // OK: contained reference now refers to object i + + ora = nullopt; // OK: ora becomes disengaged +}; + + +template +T getValue( tr2::optional newVal = tr2::nullopt, tr2::optional storeHere = tr2::nullopt ) +{ + T cached{}; + + if (newVal) { + cached = *newVal; + + if (storeHere) { + *storeHere = *newVal; // LEGAL: assigning T to T + } + } + return cached; +} + +TEST(example_optional_arg) +{ + int iii = 0; + iii = getValue(iii, iii); + iii = getValue(iii); + iii = getValue(); + + { + using namespace std::experimental; + optional grd1{in_place, "res1", 1}; // guard 1 initialized + optional grd2; + + grd2.emplace("res2", 2); // guard 2 initialized + grd1 = nullopt; // guard 1 released + + } // guard 2 released (in dtor) +}; + + +std::tuple getStartMidEnd() { return std::tuple{Date{1}, Date{2}, Date{3}}; } +void run(Date const&, Date const&, Date const&) {} + +TEST(example_date) +{ + using namespace std::experimental; + optional start, mid, end; // Date doesn't have default ctor (no good default date) + + std::tie(start, mid, end) = getStartMidEnd(); + run(*start, *mid, *end); +}; + + +std::experimental::optional readNextChar(){ return{}; } + +void run(std::experimental::optional) {} +void run(std::complex) {} + + +template +void assign_norebind(tr2::optional& optref, T& obj) +{ + if (optref) *optref = obj; + else optref.emplace(obj); +} + +template void unused(T&&) {} + +TEST(example_conceptual_model) +{ + using namespace std::experimental; + + optional oi = 0; + optional oj = 1; + optional ok = nullopt; + + oi = 1; + oj = nullopt; + ok = 0; + + unused(oi == nullopt); + unused(oj == 0); + unused(ok == 1); +}; + +TEST(example_rationale) +{ + using namespace std::experimental; + if (optional ch = readNextChar()) { + unused(ch); + // ... + } + + ////////////////////////////////// + optional opt1 = nullopt; + optional opt2 = {}; + + opt1 = nullopt; + opt2 = {}; + + if (opt1 == nullopt) {} + if (!opt2) {} + if (opt2 == optional{}) {} + + + + //////////////////////////////// + + run(nullopt); // pick the second overload + // FAILS: run({}); // ambiguous + + if (opt1 == nullopt) {} // fine + // FAILS: if (opt2 == {}) {} // ilegal + + //////////////////////////////// + assert (optional{} < optional{0}); + assert (optional{0} < optional{1}); + assert (!(optional{} < optional{}) ); + assert (!(optional{1} < optional{1})); + + assert (optional{} != optional{0}); + assert (optional{0} != optional{1}); + assert (optional{} == optional{} ); + assert (optional{0} == optional{0}); + + ///////////////////////////////// + optional o; + o = make_optional(1); // copy/move assignment + o = 1; // assignment from T + o.emplace(1); // emplacement + + //////////////////////////////////// + int isas = 0, i = 9; + optional asas = i; + assign_norebind(asas, isas); + + ///////////////////////////////////// + ////tr2::optional> ov2 = {2, 3}; + ////assert (bool(ov2)); + ////assert ((*ov2)[1] == 3); + //// + //////////////////////////////// + ////std::vector v = {1, 2, 4, 8}; + ////optional> ov = {1, 2, 4, 8}; + + ////assert (v == *ov); + //// + ////ov = {1, 2, 4, 8}; + + ////std::allocator a; + ////optional> ou { in_place, {1, 2, 4, 8}, a }; + + ////assert (ou == ov); + + ////////////////////////////// + // inconvenient syntax: + { + + tr2::optional> ov2{tr2::in_place, {2, 3}}; + + assert (bool(ov2)); + assert ((*ov2)[1] == 3); + + //////////////////////////// + + std::vector v = {1, 2, 4, 8}; + optional> ov{tr2::in_place, {1, 2, 4, 8}}; + + assert (v == *ov); + + ov.emplace({1, 2, 4, 8}); +/* + std::allocator a; + optional> ou { in_place, {1, 2, 4, 8}, a }; + + assert (ou == ov); +*/ + } + + ///////////////////////////////// + { + typedef int T; + optional> ot {in_place}; + optional> ou {in_place, nullopt}; + optional> ov {optional{}}; + + optional oi; + auto ooi = make_optional(oi); + static_assert( std::is_same>, decltype(ooi)>::value, ""); + } +}; + + +bool fun(std::string , std::experimental::optional oi = std::experimental::nullopt) +{ + return bool(oi); +} + +TEST(example_converting_ctor) +{ + using namespace std::experimental; + + assert (true == fun("dog", 2)); + assert (false == fun("dog")); + assert (false == fun("dog", nullopt)); // just to be explicit +}; + + +TEST(bad_comparison) +{ + tr2::optional oi, oj; + int i; + bool b = (oi == oj); + b = (oi >= i); + b = (oi == i); + unused(b); +}; + + +//// NOT APPLICABLE ANYMORE +////TEST(perfect_ctor) +////{ +//// //tr2::optional ois = "OS"; +//// assert (*ois == "OS"); +//// +//// // FAILS: tr2::optional oes = "OS"; +//// tr2::optional oes{"OS"}; +//// assert (oes->s == "OS"); +////}; + +TEST(value_or) +{ + tr2::optional oi = 1; + int i = oi.value_or(0); + assert (i == 1); + + oi = tr2::nullopt; + assert (oi.value_or(3) == 3); + + tr2::optional os{"AAA"}; + assert (os.value_or("BBB") == "AAA"); + os = {}; + assert (os.value_or("BBB") == "BBB"); +}; + +TEST(reset) +{ + using namespace std::experimental; + optional oi {1}; + oi.reset(); + assert (!oi); + + int i = 1; + optional oir {i}; + oir.reset(); + assert (!oir); +}; + +TEST(mixed_order) +{ + using namespace std::experimental; + + optional oN {nullopt}; + optional o0 {0}; + optional o1 {1}; + + assert ( (oN < 0)); + assert ( (oN < 1)); + assert (!(o0 < 0)); + assert ( (o0 < 1)); + assert (!(o1 < 0)); + assert (!(o1 < 1)); + + assert (!(oN >= 0)); + assert (!(oN >= 1)); + assert ( (o0 >= 0)); + assert (!(o0 >= 1)); + assert ( (o1 >= 0)); + assert ( (o1 >= 1)); + + assert (!(oN > 0)); + assert (!(oN > 1)); + assert (!(o0 > 0)); + assert (!(o0 > 1)); + assert ( (o1 > 0)); + assert (!(o1 > 1)); + + assert ( (oN <= 0)); + assert ( (oN <= 1)); + assert ( (o0 <= 0)); + assert ( (o0 <= 1)); + assert (!(o1 <= 0)); + assert ( (o1 <= 1)); + + assert ( (0 > oN)); + assert ( (1 > oN)); + assert (!(0 > o0)); + assert ( (1 > o0)); + assert (!(0 > o1)); + assert (!(1 > o1)); + + assert (!(0 <= oN)); + assert (!(1 <= oN)); + assert ( (0 <= o0)); + assert (!(1 <= o0)); + assert ( (0 <= o1)); + assert ( (1 <= o1)); + + assert (!(0 < oN)); + assert (!(1 < oN)); + assert (!(0 < o0)); + assert (!(1 < o0)); + assert ( (0 < o1)); + assert (!(1 < o1)); + + assert ( (0 >= oN)); + assert ( (1 >= oN)); + assert ( (0 >= o0)); + assert ( (1 >= o0)); + assert (!(0 >= o1)); + assert ( (1 >= o1)); +}; + +struct BadRelops +{ + int i; +}; + +constexpr bool operator<(BadRelops a, BadRelops b) { return a.i < b.i; } +constexpr bool operator>(BadRelops a, BadRelops b) { return a.i < b.i; } // intentional error! + +TEST(bad_relops) +{ + using namespace std::experimental; + BadRelops a{1}, b{2}; + assert (a < b); + assert (a > b); + + optional oa = a, ob = b; + assert (oa < ob); + assert (!(oa > ob)); + + assert (oa < b); + assert (oa > b); + + optional ra = a, rb = b; + assert (ra < rb); + assert (!(ra > rb)); + + assert (ra < b); + assert (ra > b); +}; + + +TEST(mixed_equality) +{ + using namespace std::experimental; + + assert (make_optional(0) == 0); + assert (make_optional(1) == 1); + assert (make_optional(0) != 1); + assert (make_optional(1) != 0); + + optional oN {nullopt}; + optional o0 {0}; + optional o1 {1}; + + assert (o0 == 0); + assert ( 0 == o0); + assert (o1 == 1); + assert ( 1 == o1); + assert (o1 != 0); + assert ( 0 != o1); + assert (o0 != 1); + assert ( 1 != o0); + + assert ( 1 != oN); + assert ( 0 != oN); + assert (oN != 1); + assert (oN != 0); + assert (!( 1 == oN)); + assert (!( 0 == oN)); + assert (!(oN == 1)); + assert (!(oN == 0)); + + std::string cat{"cat"}, dog{"dog"}; + optional oNil{}, oDog{"dog"}, oCat{"cat"}; + + assert (oCat == cat); + assert ( cat == oCat); + assert (oDog == dog); + assert ( dog == oDog); + assert (oDog != cat); + assert ( cat != oDog); + assert (oCat != dog); + assert ( dog != oCat); + + assert ( dog != oNil); + assert ( cat != oNil); + assert (oNil != dog); + assert (oNil != cat); + assert (!( dog == oNil)); + assert (!( cat == oNil)); + assert (!(oNil == dog)); + assert (!(oNil == cat)); +}; + +TEST(const_propagation) +{ + using namespace std::experimental; + + optional mmi{0}; + static_assert(std::is_same::value, "WTF"); + + const optional cmi{0}; + static_assert(std::is_same::value, "WTF"); + + optional mci{0}; + static_assert(std::is_same::value, "WTF"); + + optional cci{0}; + static_assert(std::is_same::value, "WTF"); +}; + + +static_assert(std::is_base_of::value, ""); + +TEST(safe_value) +{ + using namespace std::experimental; + + try { + optional ovN{}, ov1{1}; + + int& r1 = ov1.value(); + assert (r1 == 1); + + try { + ovN.value(); + assert (false); + } + catch (bad_optional_access const&) { + } + + { // ref variant + int i1 = 1; + optional orN{}, or1{i1}; + + int& r2 = or1.value(); + assert (r2 == 1); + + try { + orN.value(); + assert (false); + } + catch (bad_optional_access const&) { + } + } + } + catch(...) { + assert (false); + } +}; + +TEST(optional_ref) +{ + using namespace tr2; + // FAILS: optional orr; + // FAILS: optional on; + int i = 8; + optional ori; + assert (!ori); + ori.emplace(i); + assert (bool(ori)); + assert (*ori == 8); + assert (&*ori == &i); + *ori = 9; + assert (i == 9); + + // FAILS: int& ir = ori.value_or(i); + int ii = ori.value_or(i); + assert (ii == 9); + ii = 7; + assert (*ori == 9); + + int j = 22; + auto&& oj = make_optional(std::ref(j)); + *oj = 23; + assert (&*oj == &j); + assert (j == 23); +}; + +TEST(optional_ref_const_propagation) +{ + using namespace std::experimental; + + int i = 9; + const optional mi = i; + int& r = *mi; + optional ci = i; + static_assert(std::is_same::value, "WTF"); + static_assert(std::is_same::value, "WTF"); + + unused(r); +}; + +TEST(optional_ref_assign) +{ + using namespace std::experimental; + + int i = 9; + optional ori = i; + + int j = 1; + ori = optional{j}; + ori = {j}; + // FAILS: ori = j; + + optional orx = ori; + ori = orx; + + optional orj = j; + + assert (ori); + assert (*ori == 1); + assert (ori == orj); + assert (i == 9); + + *ori = 2; + assert (*ori == 2); + assert (ori == 2); + assert (2 == ori); + assert (ori != 3); + + assert (ori == orj); + assert (j == 2); + assert (i == 9); + + ori = {}; + assert (!ori); + assert (ori != orj); + assert (j == 2); + assert (i == 9); +}; + + +TEST(optional_ref_swap) +{ + using namespace std::experimental; + int i = 0; + int j = 1; + optional oi = i; + optional oj = j; + + assert (&*oi == &i); + assert (&*oj == &j); + + swap(oi, oj); + assert (&*oi == &j); + assert (&*oj == &i); +}; + +TEST(optional_initialization) +{ + using namespace tr2; + using std::string; + string s = "STR"; + + optional os{s}; + optional ot = s; + optional ou{"STR"}; + optional ov = string{"STR"}; + +}; + +#include + +TEST(optional_hashing) +{ + using namespace tr2; + using std::string; + + std::hash hi; + std::hash> hoi; + std::hash hs; + std::hash> hos; + + assert (hi(0) == hoi(optional{0})); + assert (hi(1) == hoi(optional{1})); + assert (hi(3198) == hoi(optional{3198})); + + assert (hs("") == hos(optional{""})); + assert (hs("0") == hos(optional{"0"})); + assert (hs("Qa1#") == hos(optional{"Qa1#"})); + + std::unordered_set> set; + assert(set.find({"Qa1#"}) == set.end()); + + set.insert({"0"}); + assert(set.find({"Qa1#"}) == set.end()); + + set.insert({"Qa1#"}); + assert(set.find({"Qa1#"}) != set.end()); +}; + + +// optional_ref_emulation +template +struct generic +{ + typedef T type; +}; + +template +struct generic +{ + typedef std::reference_wrapper type; +}; + +template +using Generic = typename generic::type; + +template +bool generic_fun() +{ + std::experimental::optional> op; + return bool(op); +} + +TEST(optional_ref_emulation) +{ + using namespace std::experimental; + optional> oi = 1; + assert (*oi == 1); + + int i = 8; + int j = 4; + optional> ori {i}; + assert (*ori == 8); + assert ((void*)&*ori != (void*)&i); // !DIFFERENT THAN optional + + *ori = j; + assert (*ori == 4); +}; + + +# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 +TEST(moved_on_value_or) +{ + using namespace tr2; + optional oo{in_place}; + + assert (oo); + assert (oo->s == sDefaultConstructed); + + Oracle o = std::move(oo).value_or( Oracle{OracleVal{}} ); + assert (oo); + assert (oo->s == sMovedFrom); + assert (o.s == sMoveConstructed); + + optional> om {in_place, 1}; + assert (om); + assert (om->moved == false); + + /*MoveAware m =*/ std::move(om).value_or( MoveAware{1} ); + assert (om); + assert (om->moved == true); + +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + { + Date d = optional{in_place, 1}.value(); + assert (d.i); // to silence compiler warning + + Date d2 = *optional{in_place, 1}; + assert (d2.i); // to silence compiler warning + } +# endif +}; +# endif + + +TEST(optional_ref_hashing) +{ + using namespace tr2; + using std::string; + + std::hash hi; + std::hash> hoi; + std::hash hs; + std::hash> hos; + + int i0 = 0; + int i1 = 1; + assert (hi(0) == hoi(optional{i0})); + assert (hi(1) == hoi(optional{i1})); + + string s{""}; + string s0{"0"}; + string sCAT{"CAT"}; + assert (hs("") == hos(optional{s})); + assert (hs("0") == hos(optional{s0})); + assert (hs("CAT") == hos(optional{sCAT})); + + std::unordered_set> set; + assert(set.find({sCAT}) == set.end()); + + set.insert({s0}); + assert(set.find({sCAT}) == set.end()); + + set.insert({sCAT}); + assert(set.find({sCAT}) != set.end()); +}; + +struct Combined +{ + int m = 0; + int n = 1; + + constexpr Combined() : m{5}, n{6} {} + constexpr Combined(int m, int n) : m{m}, n{n} {} +}; + +struct Nasty +{ + int m = 0; + int n = 1; + + constexpr Nasty() : m{5}, n{6} {} + constexpr Nasty(int m, int n) : m{m}, n{n} {} + + int operator&() { return n; } + int operator&() const { return n; } +}; + +TEST(arrow_operator) +{ + using namespace std::experimental; + + optional oc1{in_place, 1, 2}; + assert (oc1); + assert (oc1->m == 1); + assert (oc1->n == 2); + + optional on{in_place, 1, 2}; + assert (on); + assert (on->m == 1); + assert (on->n == 2); +}; + +TEST(arrow_wit_optional_ref) +{ + using namespace std::experimental; + + Combined c{1, 2}; + optional oc = c; + assert (oc); + assert (oc->m == 1); + assert (oc->n == 2); + + Nasty n{1, 2}; + Nasty m{3, 4}; + Nasty p{5, 6}; + + optional on{n}; + assert (on); + assert (on->m == 1); + assert (on->n == 2); + + on = {m}; + assert (on); + assert (on->m == 3); + assert (on->n == 4); + + on.emplace(p); + assert (on); + assert (on->m == 5); + assert (on->n == 6); + + optional om{in_place, n}; + assert (om); + assert (om->m == 1); + assert (om->n == 2); +}; + +TEST(no_dangling_reference_in_value) +{ + // this mostly tests compiler warnings + using namespace std::experimental; + optional oi {2}; + unused (oi.value()); + const optional coi {3}; + unused (coi.value()); +}; + +struct CountedObject +{ + static int _counter; + bool _throw; + CountedObject(bool b) : _throw(b) { ++_counter; } + CountedObject(CountedObject const& rhs) : _throw(rhs._throw) { if (_throw) throw int(); } + ~CountedObject() { --_counter; } +}; + +int CountedObject::_counter = 0; + +TEST(exception_safety) +{ + using namespace std::experimental; + try { + optional oo(in_place, true); // throw + optional o1(oo); + } + catch(...) + { + // + } + assert(CountedObject::_counter == 0); + + try { + optional oo(in_place, true); // throw + optional o1(std::move(oo)); // now move + } + catch(...) + { + // + } + assert(CountedObject::_counter == 0); +}; + +TEST(nested_optional) +{ + using namespace std::experimental; + + optional>> o1 {nullopt}; + assert (!o1); + + optional>> o2 {in_place, nullopt}; + assert (o2); + assert (!*o2); + + optional>> o3 (in_place, in_place, nullopt); + assert (o3); + assert (*o3); + assert (!**o3); +}; + +TEST(three_ways_of_having_value) +{ + using namespace std::experimental; + optional oN, o1 (1); + + assert (!oN); + assert (!oN.has_value()); + assert (oN == nullopt); + + assert (o1); + assert (o1.has_value()); + assert (o1 != nullopt); + + assert (bool(oN) == oN.has_value()); + assert (bool(o1) == o1.has_value()); + + int i = 1; + optional rN, r1 (i); + + assert (!rN); + assert (!rN.has_value()); + assert (rN == nullopt); + + assert (r1); + assert (r1.has_value()); + assert (r1 != nullopt); + + assert (bool(rN) == rN.has_value()); + assert (bool(r1) == r1.has_value()); +}; + +//// constexpr tests + +// these 4 classes have different noexcept signatures in move operations +struct NothrowBoth { + NothrowBoth(NothrowBoth&&) noexcept(true) {}; + void operator=(NothrowBoth&&) noexcept(true) {}; +}; +struct NothrowCtor { + NothrowCtor(NothrowCtor&&) noexcept(true) {}; + void operator=(NothrowCtor&&) noexcept(false) {}; +}; +struct NothrowAssign { + NothrowAssign(NothrowAssign&&) noexcept(false) {}; + void operator=(NothrowAssign&&) noexcept(true) {}; +}; +struct NothrowNone { + NothrowNone(NothrowNone&&) noexcept(false) {}; + void operator=(NothrowNone&&) noexcept(false) {}; +}; + +void test_noexcept() +{ + { + tr2::optional b1, b2; + static_assert(noexcept(tr2::optional{tr2::constexpr_move(b1)}), "bad noexcept!"); + static_assert(noexcept(b1 = tr2::constexpr_move(b2)), "bad noexcept!"); + } + { + tr2::optional c1, c2; + static_assert(noexcept(tr2::optional{tr2::constexpr_move(c1)}), "bad noexcept!"); + static_assert(!noexcept(c1 = tr2::constexpr_move(c2)), "bad noexcept!"); + } + { + tr2::optional a1, a2; + static_assert(!noexcept(tr2::optional{tr2::constexpr_move(a1)}), "bad noexcept!"); + static_assert(!noexcept(a1 = tr2::constexpr_move(a2)), "bad noexcept!"); + } + { + tr2::optional n1, n2; + static_assert(!noexcept(tr2::optional{tr2::constexpr_move(n1)}), "bad noexcept!"); + static_assert(!noexcept(n1 = tr2::constexpr_move(n2)), "bad noexcept!"); + } +} + + +void constexpr_test_disengaged() +{ + constexpr tr2::optional g0{}; + constexpr tr2::optional g1{tr2::nullopt}; + static_assert( !g0, "initialized!" ); + static_assert( !g1, "initialized!" ); + + static_assert( bool(g1) == bool(g0), "ne!" ); + + static_assert( g1 == g0, "ne!" ); + static_assert( !(g1 != g0), "ne!" ); + static_assert( g1 >= g0, "ne!" ); + static_assert( !(g1 > g0), "ne!" ); + static_assert( g1 <= g0, "ne!" ); + static_assert( !(g1 = tr2::nullopt, "!" ); + static_assert( !(g1 > tr2::nullopt), "!" ); + + static_assert( (tr2::nullopt == g0), "!" ); + static_assert( !(tr2::nullopt != g0), "!" ); + static_assert( (tr2::nullopt >= g0), "!" ); + static_assert( !(tr2::nullopt > g0), "!" ); + static_assert( (tr2::nullopt <= g0), "!" ); + static_assert( !(tr2::nullopt < g0), "!" ); + + static_assert( (g1 != tr2::optional(1)), "!" ); + static_assert( !(g1 == tr2::optional(1)), "!" ); + static_assert( (g1 < tr2::optional(1)), "!" ); + static_assert( (g1 <= tr2::optional(1)), "!" ); + static_assert( !(g1 > tr2::optional(1)), "!" ); + static_assert( !(g1 > tr2::optional(1)), "!" ); +} + + +constexpr tr2::optional g0{}; +constexpr tr2::optional g2{2}; +static_assert( g2, "not initialized!" ); +static_assert( *g2 == 2, "not 2!" ); +static_assert( g2 == tr2::optional(2), "not 2!" ); +static_assert( g2 != g0, "eq!" ); + +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 +static_assert( *tr2::optional{3} == 3, "WTF!" ); +static_assert( tr2::optional{3}.value() == 3, "WTF!" ); +static_assert( tr2::optional{3}.value_or(1) == 3, "WTF!" ); +static_assert( tr2::optional{}.value_or(4) == 4, "WTF!" ); +# endif + +constexpr tr2::optional gc0{tr2::in_place}; +static_assert(gc0->n == 6, "WTF!"); + +// optional refs +int gi = 0; +constexpr tr2::optional gori = gi; +constexpr tr2::optional gorn{}; +constexpr int& gri = *gori; +static_assert(gori, "WTF"); +static_assert(!gorn, "WTF"); +static_assert(gori != tr2::nullopt, "WTF"); +static_assert(gorn == tr2::nullopt, "WTF"); +static_assert(&gri == &*gori, "WTF"); + +constexpr int gci = 1; +constexpr tr2::optional gorci = gci; +constexpr tr2::optional gorcn{}; + +static_assert(gorcn < gorci, "WTF"); +static_assert(gorcn <= gorci, "WTF"); +static_assert(gorci == gorci, "WTF"); +static_assert(*gorci == 1, "WTF"); +static_assert(gorci == gci, "WTF"); + +namespace constexpr_optional_ref_and_arrow +{ + using namespace std::experimental; + constexpr Combined c{1, 2}; + constexpr optional oc = c; + static_assert(oc, "WTF!"); + static_assert(oc->m == 1, "WTF!"); + static_assert(oc->n == 2, "WTF!"); +} + +#if OPTIONAL_HAS_CONSTEXPR_INIT_LIST + +namespace InitList +{ + using namespace std::experimental; + + struct ConstInitLister + { + template + constexpr ConstInitLister(std::initializer_list il) : len (il.size()) {} + size_t len; + }; + + constexpr ConstInitLister CIL {2, 3, 4}; + static_assert(CIL.len == 3, "WTF!"); + + constexpr optional oil {in_place, {4, 5, 6, 7}}; + static_assert(oil, "WTF!"); + static_assert(oil->len == 4, "WTF!"); +} + +#endif // OPTIONAL_HAS_CONSTEXPR_INIT_LIST + +// end constexpr tests + + +#include + + +struct VEC +{ + std::vector v; + template + VEC( X&&...x) : v(std::forward(x)...) {} + + template + VEC(std::initializer_list il, X&&...x) : v(il, std::forward(x)...) {} +}; + + + +int main() { + tr2::optional oi = 1; + assert (bool(oi)); + oi.operator=({}); + assert (!oi); + + VEC v = {5, 6}; + + if (OPTIONAL_HAS_THIS_RVALUE_REFS) + std::cout << "Optional has rvalue references for *this" << std::endl; + else + std::cout << "Optional doesn't have rvalue references for *this" << std::endl; + + if (OPTIONAL_HAS_CONSTEXPR_INIT_LIST) + std::cout << "Optional has constexpr initializer_list" << std::endl; + else + std::cout << "Optional doesn't have constexpr initializer_list" << std::endl; + + if (OPTIONAL_HAS_MOVE_ACCESSORS) + std::cout << "Optional has constexpr move accessors" << std::endl; + else + std::cout << "Optional doesn't have constexpr move accessors" << std::endl; +} + diff --git a/include/tao/json/external/akrzemi1/test_type_traits.cpp b/include/tao/json/external/akrzemi1/test_type_traits.cpp new file mode 100644 index 00000000..8ec82b70 --- /dev/null +++ b/include/tao/json/external/akrzemi1/test_type_traits.cpp @@ -0,0 +1,66 @@ +// Copyright (C) 2011 - 2012 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#if (defined __clang__) + namespace std { class type_info; } +#endif + +# include "optional.hpp" + +namespace std { namespace experimental { + +struct Val +{ + Val(){} + Val( Val const & ){} + Val( Val && ) noexcept {} + + Val & operator=( Val const & ) = delete; + Val & operator=( Val && ) noexcept = delete; +}; + +struct Safe +{ + Safe(){} + Safe( Safe const & ){} + Safe( Safe && ) noexcept {} + + Safe & operator=( Safe const & ){ return *this; } + Safe & operator=( Safe && ) noexcept { return *this; } +}; + +struct Unsafe +{ + Unsafe(){} + Unsafe( Unsafe const & ){} + Unsafe( Unsafe && ){} + + Unsafe & operator=( Unsafe const & ){ return *this; } + Unsafe & operator=( Unsafe && ) { return *this; } +}; + +struct VoidNothrowBoth +{ + VoidNothrowBoth(VoidNothrowBoth&&) noexcept(true) {}; + void operator=(VoidNothrowBoth&&) noexcept(true) {}; // note void return type +}; + + +static_assert(is_nothrow_move_constructible::value, "WTF!"); +static_assert(!is_nothrow_move_constructible::value, "WTF!"); + +static_assert(is_assignable::value, "WTF!"); +static_assert(!is_assignable::value, "WTF!"); + +static_assert(is_nothrow_move_assignable::value, "WTF!"); +static_assert(!is_nothrow_move_assignable::value, "WTF!"); + +static_assert(is_nothrow_move_constructible::value, "WTF!"); +static_assert(is_nothrow_move_assignable::value, "WTF!"); + +}} // namespace std::experimental + +int main() { } diff --git a/include/tao/json/external/byte.hpp b/include/tao/json/external/byte.hpp new file mode 100644 index 00000000..c3325093 --- /dev/null +++ b/include/tao/json/external/byte.hpp @@ -0,0 +1,109 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_INCLUDE_BYTE_HPP +#define TAOCPP_INCLUDE_BYTE_HPP + +#ifndef TAOCPP_USE_STD_BYTE +#if __cplusplus >= 201703L +#define TAOCPP_USE_STD_BYTE +#endif +#endif + +#if defined( TAOCPP_USE_STD_BYTE ) +#include +#else +#include +#endif + +namespace tao +{ + +#if defined( TAOCPP_USE_STD_BYTE ) + using std::byte; + using std::to_integer; +#else + + // this is C++17's std::byte, including support functions. + // note that prior to C++17, due to the lack of the + // relaxed enum class initialization rules, + // the byte{42}-syntax does not work. + enum class byte : unsigned char + { + }; + + template< class IntType > + typename std::enable_if< std::is_integral< IntType >::value, byte& >::type + operator<<=( byte& b, IntType shift ) noexcept + { + return b = byte( static_cast< unsigned char >( b ) << shift ); + } + + template< class IntType > + constexpr typename std::enable_if< std::is_integral< IntType >::value, byte >::type + operator<<( byte b, IntType shift ) noexcept + { + return byte( static_cast< unsigned char >( b ) << shift ); + } + + template< class IntType > + typename std::enable_if< std::is_integral< IntType >::value, byte& >::type + operator>>=( byte& b, IntType shift ) noexcept + { + return b = byte( static_cast< unsigned char >( b ) >> shift ); + } + + template< class IntType > + constexpr typename std::enable_if< std::is_integral< IntType >::value, byte >::type + operator>>( byte b, IntType shift ) noexcept + { + return byte( static_cast< unsigned char >( b ) >> shift ); + } + + inline byte& operator|=( byte& l, byte r ) noexcept + { + return l = byte( static_cast< unsigned char >( l ) | static_cast< unsigned char >( r ) ); + } + + constexpr byte operator|( byte l, byte r ) noexcept + { + return byte( static_cast< unsigned char >( l ) | static_cast< unsigned char >( r ) ); + } + + inline byte& operator&=( byte& l, byte r ) noexcept + { + return l = byte( static_cast< unsigned char >( l ) & static_cast< unsigned char >( r ) ); + } + + constexpr byte operator&( byte l, byte r ) noexcept + { + return byte( static_cast< unsigned char >( l ) & static_cast< unsigned char >( r ) ); + } + + inline byte& operator^=( byte& l, byte r ) noexcept + { + return l = byte( static_cast< unsigned char >( l ) ^ static_cast< unsigned char >( r ) ); + } + + constexpr byte operator^( byte l, byte r ) noexcept + { + return byte( static_cast< unsigned char >( l ) ^ static_cast< unsigned char >( r ) ); + } + + constexpr byte operator~( byte b ) noexcept + { + return byte( ~static_cast< unsigned char >( b ) ); + } + + template< class IntType > + constexpr typename std::enable_if< std::is_integral< IntType >::value, IntType >::type + to_integer( byte b ) noexcept + { + return IntType( b ); + } + +#endif + +} // namespace tao + +#endif diff --git a/include/tao/json/external/double.hpp b/include/tao/json/external/double.hpp new file mode 100644 index 00000000..6e634bc5 --- /dev/null +++ b/include/tao/json/external/double.hpp @@ -0,0 +1,2136 @@ +// This header include/tao/json/external/double.hpp contains +// modified portions of the double-conversion library from +// https://www.github.com/google/double-conversion +// which is licensed as follows: + +// Copyright 2006-2011 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef TAOCPP_JSON_INCLUDE_EXTERNAL_DOUBLE_HPP +#define TAOCPP_JSON_INCLUDE_EXTERNAL_DOUBLE_HPP + +#include +#include +#include +#include +#include + +#include + +#ifndef ASSERT +#define ASSERT( eXPReSSioN ) ((void)0) +#endif +#ifndef UNIMPLEMENTED +#define UNIMPLEMENTED() (abort()) +#endif +#ifndef UNREACHABLE +#define UNREACHABLE() (abort()) +#endif + +// Double operations detection based on target architecture. +// Linux uses a 80bit wide floating point stack on x86. This induces double +// rounding, which in turn leads to wrong results. +// An easy way to test if the floating-point operations are correct is to +// evaluate: 89255.0/1e22. If the floating-point stack is 64 bits wide then +// the result is equal to 89255e-22. +// The best way to test this, is to create a division-function and to compare +// the output of the division with the expected result. (Inlining must be +// disabled.) +// On Linux,x86 89255e-22 != Div_double(89255.0/1e22) +#if defined(_M_X64) || defined(__x86_64__) || \ + defined(__ARMEL__) || defined(__avr32__) || \ + defined(__hppa__) || defined(__ia64__) || \ + defined(__mips__) || \ + defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \ + defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \ + defined(__sparc__) || defined(__sparc) || defined(__s390__) || \ + defined(__SH4__) || defined(__alpha__) || \ + defined(_MIPS_ARCH_MIPS32R2) || \ + defined(__AARCH64EL__) || defined(__aarch64__) +#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 +#elif defined(__mc68000__) +#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS +#elif defined(_M_IX86) || defined(__i386__) || defined(__i386) +#if defined(_WIN32) +// Windows uses a 64bit wide floating point stack. +#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 +#else +#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS +#endif // _WIN32 +#else +#error Target architecture was not detected as supported by Double-Conversion. +#endif + +#if defined(__GNUC__) +#define DOUBLE_CONVERSION_UNUSED __attribute__((unused)) +#else +#define DOUBLE_CONVERSION_UNUSED +#endif + +#if defined(_WIN32) && !defined(__MINGW32__) + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; // NOLINT +typedef unsigned short uint16_t; // NOLINT +typedef int int32_t; +typedef unsigned int uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; + +// intptr_t and friends are defined in crtdefs.h through stdio.h. + +#else + +#include + +#endif + +typedef uint16_t uc16; + +#define UINT64_2PART_C(a, b) (((static_cast(a) << 32) + 0x##b##u)) + +#ifndef GDCV8_ARRAY_SIZE +#define GDCV8_ARRAY_SIZE(a) \ + ((sizeof(a) / sizeof(*(a))) / \ + static_cast(!(sizeof(a) % sizeof(*(a))))) +#endif + +#ifndef DISALLOW_COPY_AND_ASSIGN +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&) = delete; \ + void operator=(const TypeName&) = delete +#endif + +#ifndef DISALLOW_IMPLICIT_CONSTRUCTORS +#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ + TypeName() = delete; \ + DISALLOW_COPY_AND_ASSIGN(TypeName) +#endif + +namespace json_double_conversion +{ + static const int kCharSize = sizeof( char ); + + template + static T Max(T a, T b) { + return a < b ? b : a; + } + + template + static T Min(T a, T b) { + return a < b ? a : b; + } + + inline int StrLength(const char* string) { + size_t length = strlen(string); + ASSERT(length == static_cast(static_cast(length))); + return static_cast(length); + } + + template + class Vector { + public: + Vector() : start_(NULL), length_(0) {} + Vector(T* data, int len) : start_(data), length_(len) { + ASSERT(len == 0 || (len > 0 && data != NULL)); + } + + Vector SubVector(int from, int to) { + ASSERT(to <= length_); + ASSERT(from < to); + ASSERT(0 <= from); + return Vector(start() + from, to - from); + } + + int length() const { return length_; } + + bool is_empty() const { return length_ == 0; } + + T* start() const { return start_; } + + T& operator[](int index) const { + ASSERT(0 <= index && index < length_); + return start_[index]; + } + + T& first() { return start_[0]; } + + T& last() { return start_[length_ - 1]; } + + private: + T* start_; + int length_; + }; + + template + inline Dest BitCast(const Source& source) { + DOUBLE_CONVERSION_UNUSED + typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1]; + + Dest dest; + memmove(&dest, &source, sizeof(dest)); + return dest; + } + + template + inline Dest BitCast(Source* source) { + return BitCast(reinterpret_cast(source)); + } + + class Bignum + { + public: + static const int kMaxSignificantBits = 3584; + + Bignum(); + void AssignUInt16(uint16_t value); + void AssignUInt64(uint64_t value); + void AssignBignum(const Bignum& other); + + void AssignDecimalString(Vector value); + void AssignHexString(Vector value); + + void AssignPowerUInt16(uint16_t base, int exponent); + + void AddUInt64(uint64_t operand); + void AddBignum(const Bignum& other); + void SubtractBignum(const Bignum& other); + + void Square(); + void ShiftLeft(int shift_amount); + void MultiplyByUInt32(uint32_t factor); + void MultiplyByUInt64(uint64_t factor); + void MultiplyByPowerOfTen(int exponent); + void Times10() { return MultiplyByUInt32(10); } + uint16_t DivideModuloIntBignum(const Bignum& other); + + bool ToHexString(char* buffer, int buffer_size) const; + + static int Compare(const Bignum& a, const Bignum& b); + static bool Equal(const Bignum& a, const Bignum& b) { + return Compare(a, b) == 0; + } + static bool LessEqual(const Bignum& a, const Bignum& b) { + return Compare(a, b) <= 0; + } + static bool Less(const Bignum& a, const Bignum& b) { + return Compare(a, b) < 0; + } + static int PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c); + static bool PlusEqual(const Bignum& a, const Bignum& b, const Bignum& c) { + return PlusCompare(a, b, c) == 0; + } + static bool PlusLessEqual(const Bignum& a, const Bignum& b, const Bignum& c) { + return PlusCompare(a, b, c) <= 0; + } + static bool PlusLess(const Bignum& a, const Bignum& b, const Bignum& c) { + return PlusCompare(a, b, c) < 0; + } + private: + typedef uint32_t Chunk; + typedef uint64_t DoubleChunk; + + static const int kChunkSize = sizeof(Chunk) * 8; + static const int kDoubleChunkSize = sizeof(DoubleChunk) * 8; + static const int kBigitSize = 28; + static const Chunk kBigitMask = (1 << kBigitSize) - 1; + static const int kBigitCapacity = kMaxSignificantBits / kBigitSize; + + void EnsureCapacity(int size) { + if (size > kBigitCapacity) { + UNREACHABLE(); + } + } + void Align(const Bignum& other); + void Clamp(); + bool IsClamped() const; + void Zero(); + + void BigitsShiftLeft(int shift_amount); + int BigitLength() const { return used_digits_ + exponent_; } + Chunk BigitAt(int index) const; + void SubtractTimes(const Bignum& other, int factor); + + Chunk bigits_buffer_[kBigitCapacity]; + Vector bigits_; + int used_digits_; + int exponent_; + + Bignum( const Bignum & ) = delete; + void operator= ( const Bignum & ) = delete; + }; + + inline Bignum::Bignum() + : bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) { + for (int i = 0; i < kBigitCapacity; ++i) { + bigits_[i] = 0; + } + } + + template + inline int BitSize(S value) { + (void) value; // Mark variable as used. + return 8 * sizeof(value); + } + + inline void Bignum::AssignUInt16(uint16_t value) { + ASSERT(kBigitSize >= BitSize(value)); + Zero(); + if (value == 0) return; + + EnsureCapacity(1); + bigits_[0] = value; + used_digits_ = 1; + } + + inline void Bignum::AssignUInt64(uint64_t value) { + const int kUInt64Size = 64; + + Zero(); + if (value == 0) return; + + int needed_bigits = kUInt64Size / kBigitSize + 1; + EnsureCapacity(needed_bigits); + for (int i = 0; i < needed_bigits; ++i) { + bigits_[i] = value & kBigitMask; + value = value >> kBigitSize; + } + used_digits_ = needed_bigits; + Clamp(); + } + + inline void Bignum::AssignBignum(const Bignum& other) { + exponent_ = other.exponent_; + for (int i = 0; i < other.used_digits_; ++i) { + bigits_[i] = other.bigits_[i]; + } + for (int i = other.used_digits_; i < used_digits_; ++i) { + bigits_[i] = 0; + } + used_digits_ = other.used_digits_; + } + + + inline uint64_t ReadUInt64(Vector buffer, + int from, + int digits_to_read) { + uint64_t result = 0; + for (int i = from; i < from + digits_to_read; ++i) { + int digit = buffer[i] - '0'; + ASSERT(0 <= digit && digit <= 9); + result = result * 10 + digit; + } + return result; + } + + inline void Bignum::AssignDecimalString(Vector value) { + const int kMaxUint64DecimalDigits = 19; + Zero(); + int length = value.length(); + unsigned int pos = 0; + while (length >= kMaxUint64DecimalDigits) { + uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits); + pos += kMaxUint64DecimalDigits; + length -= kMaxUint64DecimalDigits; + MultiplyByPowerOfTen(kMaxUint64DecimalDigits); + AddUInt64(digits); + } + uint64_t digits = ReadUInt64(value, pos, length); + MultiplyByPowerOfTen(length); + AddUInt64(digits); + Clamp(); + } + + inline int HexCharValue(char c) { + if ('0' <= c && c <= '9') return c - '0'; + if ('a' <= c && c <= 'f') return 10 + c - 'a'; + ASSERT('A' <= c && c <= 'F'); + return 10 + c - 'A'; + } + + inline void Bignum::AssignHexString(Vector value) { + Zero(); + int length = value.length(); + + int needed_bigits = length * 4 / kBigitSize + 1; + EnsureCapacity(needed_bigits); + int string_index = length - 1; + for (int i = 0; i < needed_bigits - 1; ++i) { + Chunk current_bigit = 0; + for (int j = 0; j < kBigitSize / 4; j++) { + current_bigit += HexCharValue(value[string_index--]) << (j * 4); + } + bigits_[i] = current_bigit; + } + used_digits_ = needed_bigits - 1; + + Chunk most_significant_bigit = 0; + for (int j = 0; j <= string_index; ++j) { + most_significant_bigit <<= 4; + most_significant_bigit += HexCharValue(value[j]); + } + if (most_significant_bigit != 0) { + bigits_[used_digits_] = most_significant_bigit; + used_digits_++; + } + Clamp(); + } + + inline void Bignum::AddUInt64(uint64_t operand) { + if (operand == 0) return; + Bignum other; + other.AssignUInt64(operand); + AddBignum(other); + } + + inline void Bignum::AddBignum(const Bignum& other) { + ASSERT(IsClamped()); + ASSERT(other.IsClamped()); + Align(other); + EnsureCapacity(1 + Max(BigitLength(), other.BigitLength()) - exponent_); + Chunk carry = 0; + int bigit_pos = other.exponent_ - exponent_; + ASSERT(bigit_pos >= 0); + for (int i = 0; i < other.used_digits_; ++i) { + Chunk sum = bigits_[bigit_pos] + other.bigits_[i] + carry; + bigits_[bigit_pos] = sum & kBigitMask; + carry = sum >> kBigitSize; + bigit_pos++; + } + while (carry != 0) { + Chunk sum = bigits_[bigit_pos] + carry; + bigits_[bigit_pos] = sum & kBigitMask; + carry = sum >> kBigitSize; + bigit_pos++; + } + used_digits_ = Max(bigit_pos, used_digits_); + ASSERT(IsClamped()); + } + + inline void Bignum::SubtractBignum(const Bignum& other) { + ASSERT(IsClamped()); + ASSERT(other.IsClamped()); + ASSERT(LessEqual(other, *this)); + Align(other); + + int offset = other.exponent_ - exponent_; + Chunk borrow = 0; + int i; + for (i = 0; i < other.used_digits_; ++i) { + ASSERT((borrow == 0) || (borrow == 1)); + Chunk difference = bigits_[i + offset] - other.bigits_[i] - borrow; + bigits_[i + offset] = difference & kBigitMask; + borrow = difference >> (kChunkSize - 1); + } + while (borrow != 0) { + Chunk difference = bigits_[i + offset] - borrow; + bigits_[i + offset] = difference & kBigitMask; + borrow = difference >> (kChunkSize - 1); + ++i; + } + Clamp(); + } + + inline void Bignum::ShiftLeft(int shift_amount) { + if (used_digits_ == 0) return; + exponent_ += shift_amount / kBigitSize; + int local_shift = shift_amount % kBigitSize; + EnsureCapacity(used_digits_ + 1); + BigitsShiftLeft(local_shift); + } + + inline void Bignum::MultiplyByUInt32(uint32_t factor) { + if (factor == 1) return; + if (factor == 0) { + Zero(); + return; + } + if (used_digits_ == 0) return; + ASSERT(kDoubleChunkSize >= kBigitSize + 32 + 1); + DoubleChunk carry = 0; + for (int i = 0; i < used_digits_; ++i) { + DoubleChunk product = static_cast(factor) * bigits_[i] + carry; + bigits_[i] = static_cast(product & kBigitMask); + carry = (product >> kBigitSize); + } + while (carry != 0) { + EnsureCapacity(used_digits_ + 1); + bigits_[used_digits_] = carry & kBigitMask; + used_digits_++; + carry >>= kBigitSize; + } + } + + inline void Bignum::MultiplyByUInt64(uint64_t factor) { + if (factor == 1) return; + if (factor == 0) { + Zero(); + return; + } + ASSERT(kBigitSize < 32); + uint64_t carry = 0; + uint64_t low = factor & 0xFFFFFFFF; + uint64_t high = factor >> 32; + for (int i = 0; i < used_digits_; ++i) { + uint64_t product_low = low * bigits_[i]; + uint64_t product_high = high * bigits_[i]; + uint64_t tmp = (carry & kBigitMask) + product_low; + bigits_[i] = tmp & kBigitMask; + carry = (carry >> kBigitSize) + (tmp >> kBigitSize) + + (product_high << (32 - kBigitSize)); + } + while (carry != 0) { + EnsureCapacity(used_digits_ + 1); + bigits_[used_digits_] = carry & kBigitMask; + used_digits_++; + carry >>= kBigitSize; + } + } + + inline void Bignum::MultiplyByPowerOfTen(int exponent) { + const uint64_t kFive27 = UINT64_2PART_C(0x6765c793, fa10079d); + const uint16_t kFive1 = 5; + const uint16_t kFive2 = kFive1 * 5; + const uint16_t kFive3 = kFive2 * 5; + const uint16_t kFive4 = kFive3 * 5; + const uint16_t kFive5 = kFive4 * 5; + const uint16_t kFive6 = kFive5 * 5; + const uint32_t kFive7 = kFive6 * 5; + const uint32_t kFive8 = kFive7 * 5; + const uint32_t kFive9 = kFive8 * 5; + const uint32_t kFive10 = kFive9 * 5; + const uint32_t kFive11 = kFive10 * 5; + const uint32_t kFive12 = kFive11 * 5; + const uint32_t kFive13 = kFive12 * 5; + const uint32_t kFive1_to_12[] = + { kFive1, kFive2, kFive3, kFive4, kFive5, kFive6, + kFive7, kFive8, kFive9, kFive10, kFive11, kFive12 }; + + ASSERT(exponent >= 0); + if (exponent == 0) return; + if (used_digits_ == 0) return; + int remaining_exponent = exponent; + while (remaining_exponent >= 27) { + MultiplyByUInt64(kFive27); + remaining_exponent -= 27; + } + while (remaining_exponent >= 13) { + MultiplyByUInt32(kFive13); + remaining_exponent -= 13; + } + if (remaining_exponent > 0) { + MultiplyByUInt32(kFive1_to_12[remaining_exponent - 1]); + } + ShiftLeft(exponent); + } + + inline void Bignum::Square() { + ASSERT(IsClamped()); + int product_length = 2 * used_digits_; + EnsureCapacity(product_length); + + if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_digits_) { + UNIMPLEMENTED(); + } + DoubleChunk accumulator = 0; + int copy_offset = used_digits_; + for (int i = 0; i < used_digits_; ++i) { + bigits_[copy_offset + i] = bigits_[i]; + } + for (int i = 0; i < used_digits_; ++i) { + int bigit_index1 = i; + int bigit_index2 = 0; + while (bigit_index1 >= 0) { + Chunk chunk1 = bigits_[copy_offset + bigit_index1]; + Chunk chunk2 = bigits_[copy_offset + bigit_index2]; + accumulator += static_cast(chunk1) * chunk2; + bigit_index1--; + bigit_index2++; + } + bigits_[i] = static_cast(accumulator) & kBigitMask; + accumulator >>= kBigitSize; + } + for (int i = used_digits_; i < product_length; ++i) { + int bigit_index1 = used_digits_ - 1; + int bigit_index2 = i - bigit_index1; + while (bigit_index2 < used_digits_) { + Chunk chunk1 = bigits_[copy_offset + bigit_index1]; + Chunk chunk2 = bigits_[copy_offset + bigit_index2]; + accumulator += static_cast(chunk1) * chunk2; + bigit_index1--; + bigit_index2++; + } + bigits_[i] = static_cast(accumulator) & kBigitMask; + accumulator >>= kBigitSize; + } + ASSERT(accumulator == 0); + used_digits_ = product_length; + exponent_ *= 2; + Clamp(); + } + + inline void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) { + ASSERT(base != 0); + ASSERT(power_exponent >= 0); + if (power_exponent == 0) { + AssignUInt16(1); + return; + } + Zero(); + int shifts = 0; + while ((base & 1) == 0) { + base >>= 1; + shifts++; + } + int bit_size = 0; + int tmp_base = base; + while (tmp_base != 0) { + tmp_base >>= 1; + bit_size++; + } + int final_size = bit_size * power_exponent; + EnsureCapacity(final_size / kBigitSize + 2); + int mask = 1; + while (power_exponent >= mask) mask <<= 1; + mask >>= 2; + uint64_t this_value = base; + bool delayed_multipliciation = false; + const uint64_t max_32bits = 0xFFFFFFFF; + while (mask != 0 && this_value <= max_32bits) { + this_value = this_value * this_value; + if ((power_exponent & mask) != 0) { + uint64_t base_bits_mask = + ~((static_cast(1) << (64 - bit_size)) - 1); + bool high_bits_zero = (this_value & base_bits_mask) == 0; + if (high_bits_zero) { + this_value *= base; + } else { + delayed_multipliciation = true; + } + } + mask >>= 1; + } + AssignUInt64(this_value); + if (delayed_multipliciation) { + MultiplyByUInt32(base); + } + while (mask != 0) { + Square(); + if ((power_exponent & mask) != 0) { + MultiplyByUInt32(base); + } + mask >>= 1; + } + ShiftLeft(shifts * power_exponent); + } + + inline uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) { + ASSERT(IsClamped()); + ASSERT(other.IsClamped()); + ASSERT(other.used_digits_ > 0); + + if (BigitLength() < other.BigitLength()) { + return 0; + } + Align(other); + + uint16_t result = 0; + + while (BigitLength() > other.BigitLength()) { + ASSERT(other.bigits_[other.used_digits_ - 1] >= ((1 << kBigitSize) / 16)); + ASSERT(bigits_[used_digits_ - 1] < 0x10000); + result += static_cast(bigits_[used_digits_ - 1]); + SubtractTimes(other, bigits_[used_digits_ - 1]); + } + ASSERT(BigitLength() == other.BigitLength()); + + Chunk this_bigit = bigits_[used_digits_ - 1]; + Chunk other_bigit = other.bigits_[other.used_digits_ - 1]; + + if (other.used_digits_ == 1) { + int quotient = this_bigit / other_bigit; + bigits_[used_digits_ - 1] = this_bigit - other_bigit * quotient; + ASSERT(quotient < 0x10000); + result += static_cast(quotient); + Clamp(); + return result; + } + int division_estimate = this_bigit / (other_bigit + 1); + ASSERT(division_estimate < 0x10000); + result += static_cast(division_estimate); + SubtractTimes(other, division_estimate); + + if (other_bigit * (division_estimate + 1) > this_bigit) { + return result; + } + while (LessEqual(other, *this)) { + SubtractBignum(other); + result++; + } + return result; + } + + template + inline int SizeInHexChars(S number) { + ASSERT(number > 0); + int result = 0; + while (number != 0) { + number >>= 4; + result++; + } + return result; + } + + inline char HexCharOfValue(int value) { + ASSERT(0 <= value && value <= 16); + if (value < 10) return static_cast(value + '0'); + return static_cast(value - 10 + 'A'); + } + + inline bool Bignum::ToHexString(char* buffer, int buffer_size) const { + ASSERT(IsClamped()); + ASSERT(kBigitSize % 4 == 0); + const int kHexCharsPerBigit = kBigitSize / 4; + + if (used_digits_ == 0) { + if (buffer_size < 2) return false; + buffer[0] = '0'; + buffer[1] = '\0'; + return true; + } + int needed_chars = (BigitLength() - 1) * kHexCharsPerBigit + + SizeInHexChars(bigits_[used_digits_ - 1]) + 1; + if (needed_chars > buffer_size) return false; + int string_index = needed_chars - 1; + buffer[string_index--] = '\0'; + for (int i = 0; i < exponent_; ++i) { + for (int j = 0; j < kHexCharsPerBigit; ++j) { + buffer[string_index--] = '0'; + } + } + for (int i = 0; i < used_digits_ - 1; ++i) { + Chunk current_bigit = bigits_[i]; + for (int j = 0; j < kHexCharsPerBigit; ++j) { + buffer[string_index--] = HexCharOfValue(current_bigit & 0xF); + current_bigit >>= 4; + } + } + Chunk most_significant_bigit = bigits_[used_digits_ - 1]; + while (most_significant_bigit != 0) { + buffer[string_index--] = HexCharOfValue(most_significant_bigit & 0xF); + most_significant_bigit >>= 4; + } + return true; + } + + inline Bignum::Chunk Bignum::BigitAt(int index) const { + if (index >= BigitLength()) return 0; + if (index < exponent_) return 0; + return bigits_[index - exponent_]; + } + + inline int Bignum::Compare(const Bignum& a, const Bignum& b) { + ASSERT(a.IsClamped()); + ASSERT(b.IsClamped()); + int bigit_length_a = a.BigitLength(); + int bigit_length_b = b.BigitLength(); + if (bigit_length_a < bigit_length_b) return -1; + if (bigit_length_a > bigit_length_b) return +1; + for (int i = bigit_length_a - 1; i >= Min(a.exponent_, b.exponent_); --i) { + Chunk bigit_a = a.BigitAt(i); + Chunk bigit_b = b.BigitAt(i); + if (bigit_a < bigit_b) return -1; + if (bigit_a > bigit_b) return +1; + } + return 0; + } + + inline int Bignum::PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c) { + ASSERT(a.IsClamped()); + ASSERT(b.IsClamped()); + ASSERT(c.IsClamped()); + if (a.BigitLength() < b.BigitLength()) { + return PlusCompare(b, a, c); + } + if (a.BigitLength() + 1 < c.BigitLength()) return -1; + if (a.BigitLength() > c.BigitLength()) return +1; + if (a.exponent_ >= b.BigitLength() && a.BigitLength() < c.BigitLength()) { + return -1; + } + Chunk borrow = 0; + int min_exponent = Min(Min(a.exponent_, b.exponent_), c.exponent_); + for (int i = c.BigitLength() - 1; i >= min_exponent; --i) { + Chunk chunk_a = a.BigitAt(i); + Chunk chunk_b = b.BigitAt(i); + Chunk chunk_c = c.BigitAt(i); + Chunk sum = chunk_a + chunk_b; + if (sum > chunk_c + borrow) { + return +1; + } else { + borrow = chunk_c + borrow - sum; + if (borrow > 1) return -1; + borrow <<= kBigitSize; + } + } + if (borrow == 0) return 0; + return -1; + } + + inline void Bignum::Clamp() { + while (used_digits_ > 0 && bigits_[used_digits_ - 1] == 0) { + used_digits_--; + } + if (used_digits_ == 0) { + exponent_ = 0; + } + } + + inline bool Bignum::IsClamped() const { + return used_digits_ == 0 || bigits_[used_digits_ - 1] != 0; + } + + inline void Bignum::Zero() { + for (int i = 0; i < used_digits_; ++i) { + bigits_[i] = 0; + } + used_digits_ = 0; + exponent_ = 0; + } + + inline void Bignum::Align(const Bignum& other) { + if (exponent_ > other.exponent_) { + int zero_digits = exponent_ - other.exponent_; + EnsureCapacity(used_digits_ + zero_digits); + for (int i = used_digits_ - 1; i >= 0; --i) { + bigits_[i + zero_digits] = bigits_[i]; + } + for (int i = 0; i < zero_digits; ++i) { + bigits_[i] = 0; + } + used_digits_ += zero_digits; + exponent_ -= zero_digits; + ASSERT(used_digits_ >= 0); + ASSERT(exponent_ >= 0); + } + } + + inline void Bignum::BigitsShiftLeft(int shift_amount) { + ASSERT(shift_amount < kBigitSize); + ASSERT(shift_amount >= 0); + Chunk carry = 0; + for (int i = 0; i < used_digits_; ++i) { + Chunk new_carry = bigits_[i] >> (kBigitSize - shift_amount); + bigits_[i] = ((bigits_[i] << shift_amount) + carry) & kBigitMask; + carry = new_carry; + } + if (carry != 0) { + bigits_[used_digits_] = carry; + used_digits_++; + } + } + + inline void Bignum::SubtractTimes(const Bignum& other, int factor) { + ASSERT(exponent_ <= other.exponent_); + if (factor < 3) { + for (int i = 0; i < factor; ++i) { + SubtractBignum(other); + } + return; + } + Chunk borrow = 0; + int exponent_diff = other.exponent_ - exponent_; + for (int i = 0; i < other.used_digits_; ++i) { + DoubleChunk product = static_cast(factor) * other.bigits_[i]; + DoubleChunk remove = borrow + product; + Chunk difference = bigits_[i + exponent_diff] - (remove & kBigitMask); + bigits_[i + exponent_diff] = difference & kBigitMask; + borrow = static_cast((difference >> (kChunkSize - 1)) + + (remove >> kBigitSize)); + } + for (int i = other.used_digits_ + exponent_diff; i < used_digits_; ++i) { + if (borrow == 0) return; + Chunk difference = bigits_[i] - borrow; + bigits_[i] = difference & kBigitMask; + borrow = difference >> (kChunkSize - 1); + } + Clamp(); + } + + class DiyFp + { + public: + static const int kSignificandSize = 64; + + DiyFp() : f_(0), e_(0) {} + DiyFp(uint64_t significand, int exponent) : f_(significand), e_(exponent) {} + + void Subtract(const DiyFp& other) { + ASSERT(e_ == other.e_); + ASSERT(f_ >= other.f_); + f_ -= other.f_; + } + + static DiyFp Minus(const DiyFp& a, const DiyFp& b) { + DiyFp result = a; + result.Subtract(b); + return result; + } + + void Multiply(const DiyFp& other) + { + const uint64_t kM32 = 0xFFFFFFFFU; + uint64_t a = f_ >> 32; + uint64_t b = f_ & kM32; + uint64_t c = other.f_ >> 32; + uint64_t d = other.f_ & kM32; + uint64_t ac = a * c; + uint64_t bc = b * c; + uint64_t ad = a * d; + uint64_t bd = b * d; + uint64_t tmp = (bd >> 32) + (ad & kM32) + (bc & kM32); + tmp += 1U << 31; + uint64_t result_f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32); + e_ += other.e_ + 64; + f_ = result_f; + } + + static DiyFp Times(const DiyFp& a, const DiyFp& b) + { + DiyFp result = a; + result.Multiply(b); + return result; + } + + void Normalize() { + ASSERT(f_ != 0); + uint64_t significand = f_; + int exponent = e_; + + const uint64_t k10MSBits = UINT64_2PART_C(0xFFC00000, 00000000); + while ((significand & k10MSBits) == 0) { + significand <<= 10; + exponent -= 10; + } + while ((significand & kUint64MSB) == 0) { + significand <<= 1; + exponent--; + } + f_ = significand; + e_ = exponent; + } + + static DiyFp Normalize(const DiyFp& a) { + DiyFp result = a; + result.Normalize(); + return result; + } + + uint64_t f() const { return f_; } + int e() const { return e_; } + + void set_f(uint64_t new_value) { f_ = new_value; } + void set_e(int new_value) { e_ = new_value; } + + private: + static const uint64_t kUint64MSB = UINT64_2PART_C(0x80000000, 00000000); + + uint64_t f_; + int e_; + }; + + static uint64_t double_to_uint64(double d) { return BitCast(d); } + static double uint64_to_double(uint64_t d64) { return BitCast(d64); } + + class Double { + public: + static const uint64_t kSignMask = UINT64_2PART_C(0x80000000, 00000000); + static const uint64_t kExponentMask = UINT64_2PART_C(0x7FF00000, 00000000); + static const uint64_t kSignificandMask = UINT64_2PART_C(0x000FFFFF, FFFFFFFF); + static const uint64_t kHiddenBit = UINT64_2PART_C(0x00100000, 00000000); + static const int kPhysicalSignificandSize = 52; + static const int kSignificandSize = 53; + + Double() : d64_(0) {} + explicit Double(double d) : d64_(double_to_uint64(d)) {} + explicit Double(uint64_t d64) : d64_(d64) {} + explicit Double(DiyFp diy_fp) + : d64_(DiyFpToUint64(diy_fp)) {} + + DiyFp AsDiyFp() const { + ASSERT(Sign() > 0); + ASSERT(!IsSpecial()); + return DiyFp(Significand(), Exponent()); + } + + DiyFp AsNormalizedDiyFp() const { + ASSERT(value() > 0.0); + uint64_t f = Significand(); + int e = Exponent(); + + while ((f & kHiddenBit) == 0) { + f <<= 1; + e--; + } + f <<= DiyFp::kSignificandSize - kSignificandSize; + e -= DiyFp::kSignificandSize - kSignificandSize; + return DiyFp(f, e); + } + + uint64_t AsUint64() const { + return d64_; + } + + double NextDouble() const { + if (d64_ == kInfinity) return Double(kInfinity).value(); + if (Sign() < 0 && Significand() == 0) { + return 0.0; + } + if (Sign() < 0) { + return Double(d64_ - 1).value(); + } else { + return Double(d64_ + 1).value(); + } + } + + double PreviousDouble() const { + if (d64_ == (kInfinity | kSignMask)) return -Double::Infinity(); + if (Sign() < 0) { + return Double(d64_ + 1).value(); + } else { + if (Significand() == 0) return -0.0; + return Double(d64_ - 1).value(); + } + } + + int Exponent() const { + if (IsDenormal()) return kDenormalExponent; + + uint64_t d64 = AsUint64(); + int biased_e = + static_cast((d64 & kExponentMask) >> kPhysicalSignificandSize); + return biased_e - kExponentBias; + } + + uint64_t Significand() const { + uint64_t d64 = AsUint64(); + uint64_t significand = d64 & kSignificandMask; + if (!IsDenormal()) { + return significand + kHiddenBit; + } else { + return significand; + } + } + + bool IsDenormal() const { + uint64_t d64 = AsUint64(); + return (d64 & kExponentMask) == 0; + } + + bool IsSpecial() const { + uint64_t d64 = AsUint64(); + return (d64 & kExponentMask) == kExponentMask; + } + + bool IsNan() const { + uint64_t d64 = AsUint64(); + return ((d64 & kExponentMask) == kExponentMask) && + ((d64 & kSignificandMask) != 0); + } + + bool IsInfinite() const { + uint64_t d64 = AsUint64(); + return ((d64 & kExponentMask) == kExponentMask) && + ((d64 & kSignificandMask) == 0); + } + + int Sign() const { + uint64_t d64 = AsUint64(); + return (d64 & kSignMask) == 0? 1: -1; + } + + DiyFp UpperBoundary() const { + ASSERT(Sign() > 0); + return DiyFp(Significand() * 2 + 1, Exponent() - 1); + } + + void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const { + ASSERT(value() > 0.0); + DiyFp v = this->AsDiyFp(); + DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1)); + DiyFp m_minus; + if (LowerBoundaryIsCloser()) { + m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2); + } else { + m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1); + } + m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e())); + m_minus.set_e(m_plus.e()); + *out_m_plus = m_plus; + *out_m_minus = m_minus; + } + + bool LowerBoundaryIsCloser() const { + bool physical_significand_is_zero = ((AsUint64() & kSignificandMask) == 0); + return physical_significand_is_zero && (Exponent() != kDenormalExponent); + } + + double value() const { return uint64_to_double(d64_); } + + static int SignificandSizeForOrderOfMagnitude(int order) { + if (order >= (kDenormalExponent + kSignificandSize)) { + return kSignificandSize; + } + if (order <= kDenormalExponent) return 0; + return order - kDenormalExponent; + } + + static double Infinity() { + return Double(kInfinity).value(); + } + + static double NaN() { + return Double(kNaN).value(); + } + + private: + static const int kExponentBias = 0x3FF + kPhysicalSignificandSize; + static const int kDenormalExponent = -kExponentBias + 1; + static const int kMaxExponent = 0x7FF - kExponentBias; + static const uint64_t kInfinity = UINT64_2PART_C(0x7FF00000, 00000000); + static const uint64_t kNaN = UINT64_2PART_C(0x7FF80000, 00000000); + + const uint64_t d64_; + + static uint64_t DiyFpToUint64(DiyFp diy_fp) { + uint64_t significand = diy_fp.f(); + int exponent = diy_fp.e(); + while (significand > kHiddenBit + kSignificandMask) { + significand >>= 1; + exponent++; + } + if (exponent >= kMaxExponent) { + return kInfinity; + } + if (exponent < kDenormalExponent) { + return 0; + } + while (exponent > kDenormalExponent && (significand & kHiddenBit) == 0) { + significand <<= 1; + exponent--; + } + uint64_t biased_exponent; + if (exponent == kDenormalExponent && (significand & kHiddenBit) == 0) { + biased_exponent = 0; + } else { + biased_exponent = static_cast(exponent + kExponentBias); + } + return (significand & kSignificandMask) | + (biased_exponent << kPhysicalSignificandSize); + } + + DISALLOW_COPY_AND_ASSIGN(Double); + }; + + struct PowersOfTenCache + { + static const int kDecimalExponentDistance = 8; + + static const int kMinDecimalExponent = -348; + static const int kMaxDecimalExponent = 340; + + static void GetCachedPowerForBinaryExponentRange(int min_exponent, + int max_exponent, + DiyFp* power, + int* decimal_exponent); + + static void GetCachedPowerForDecimalExponent(int requested_exponent, + DiyFp* power, + int* found_exponent); + }; + + struct CachedPower { + uint64_t significand; + int16_t binary_exponent; + int16_t decimal_exponent; + }; + + static const CachedPower kCachedPowers[] = { + {UINT64_2PART_C(0xfa8fd5a0, 081c0288), -1220, -348}, + {UINT64_2PART_C(0xbaaee17f, a23ebf76), -1193, -340}, + {UINT64_2PART_C(0x8b16fb20, 3055ac76), -1166, -332}, + {UINT64_2PART_C(0xcf42894a, 5dce35ea), -1140, -324}, + {UINT64_2PART_C(0x9a6bb0aa, 55653b2d), -1113, -316}, + {UINT64_2PART_C(0xe61acf03, 3d1a45df), -1087, -308}, + {UINT64_2PART_C(0xab70fe17, c79ac6ca), -1060, -300}, + {UINT64_2PART_C(0xff77b1fc, bebcdc4f), -1034, -292}, + {UINT64_2PART_C(0xbe5691ef, 416bd60c), -1007, -284}, + {UINT64_2PART_C(0x8dd01fad, 907ffc3c), -980, -276}, + {UINT64_2PART_C(0xd3515c28, 31559a83), -954, -268}, + {UINT64_2PART_C(0x9d71ac8f, ada6c9b5), -927, -260}, + {UINT64_2PART_C(0xea9c2277, 23ee8bcb), -901, -252}, + {UINT64_2PART_C(0xaecc4991, 4078536d), -874, -244}, + {UINT64_2PART_C(0x823c1279, 5db6ce57), -847, -236}, + {UINT64_2PART_C(0xc2109436, 4dfb5637), -821, -228}, + {UINT64_2PART_C(0x9096ea6f, 3848984f), -794, -220}, + {UINT64_2PART_C(0xd77485cb, 25823ac7), -768, -212}, + {UINT64_2PART_C(0xa086cfcd, 97bf97f4), -741, -204}, + {UINT64_2PART_C(0xef340a98, 172aace5), -715, -196}, + {UINT64_2PART_C(0xb23867fb, 2a35b28e), -688, -188}, + {UINT64_2PART_C(0x84c8d4df, d2c63f3b), -661, -180}, + {UINT64_2PART_C(0xc5dd4427, 1ad3cdba), -635, -172}, + {UINT64_2PART_C(0x936b9fce, bb25c996), -608, -164}, + {UINT64_2PART_C(0xdbac6c24, 7d62a584), -582, -156}, + {UINT64_2PART_C(0xa3ab6658, 0d5fdaf6), -555, -148}, + {UINT64_2PART_C(0xf3e2f893, dec3f126), -529, -140}, + {UINT64_2PART_C(0xb5b5ada8, aaff80b8), -502, -132}, + {UINT64_2PART_C(0x87625f05, 6c7c4a8b), -475, -124}, + {UINT64_2PART_C(0xc9bcff60, 34c13053), -449, -116}, + {UINT64_2PART_C(0x964e858c, 91ba2655), -422, -108}, + {UINT64_2PART_C(0xdff97724, 70297ebd), -396, -100}, + {UINT64_2PART_C(0xa6dfbd9f, b8e5b88f), -369, -92}, + {UINT64_2PART_C(0xf8a95fcf, 88747d94), -343, -84}, + {UINT64_2PART_C(0xb9447093, 8fa89bcf), -316, -76}, + {UINT64_2PART_C(0x8a08f0f8, bf0f156b), -289, -68}, + {UINT64_2PART_C(0xcdb02555, 653131b6), -263, -60}, + {UINT64_2PART_C(0x993fe2c6, d07b7fac), -236, -52}, + {UINT64_2PART_C(0xe45c10c4, 2a2b3b06), -210, -44}, + {UINT64_2PART_C(0xaa242499, 697392d3), -183, -36}, + {UINT64_2PART_C(0xfd87b5f2, 8300ca0e), -157, -28}, + {UINT64_2PART_C(0xbce50864, 92111aeb), -130, -20}, + {UINT64_2PART_C(0x8cbccc09, 6f5088cc), -103, -12}, + {UINT64_2PART_C(0xd1b71758, e219652c), -77, -4}, + {UINT64_2PART_C(0x9c400000, 00000000), -50, 4}, + {UINT64_2PART_C(0xe8d4a510, 00000000), -24, 12}, + {UINT64_2PART_C(0xad78ebc5, ac620000), 3, 20}, + {UINT64_2PART_C(0x813f3978, f8940984), 30, 28}, + {UINT64_2PART_C(0xc097ce7b, c90715b3), 56, 36}, + {UINT64_2PART_C(0x8f7e32ce, 7bea5c70), 83, 44}, + {UINT64_2PART_C(0xd5d238a4, abe98068), 109, 52}, + {UINT64_2PART_C(0x9f4f2726, 179a2245), 136, 60}, + {UINT64_2PART_C(0xed63a231, d4c4fb27), 162, 68}, + {UINT64_2PART_C(0xb0de6538, 8cc8ada8), 189, 76}, + {UINT64_2PART_C(0x83c7088e, 1aab65db), 216, 84}, + {UINT64_2PART_C(0xc45d1df9, 42711d9a), 242, 92}, + {UINT64_2PART_C(0x924d692c, a61be758), 269, 100}, + {UINT64_2PART_C(0xda01ee64, 1a708dea), 295, 108}, + {UINT64_2PART_C(0xa26da399, 9aef774a), 322, 116}, + {UINT64_2PART_C(0xf209787b, b47d6b85), 348, 124}, + {UINT64_2PART_C(0xb454e4a1, 79dd1877), 375, 132}, + {UINT64_2PART_C(0x865b8692, 5b9bc5c2), 402, 140}, + {UINT64_2PART_C(0xc83553c5, c8965d3d), 428, 148}, + {UINT64_2PART_C(0x952ab45c, fa97a0b3), 455, 156}, + {UINT64_2PART_C(0xde469fbd, 99a05fe3), 481, 164}, + {UINT64_2PART_C(0xa59bc234, db398c25), 508, 172}, + {UINT64_2PART_C(0xf6c69a72, a3989f5c), 534, 180}, + {UINT64_2PART_C(0xb7dcbf53, 54e9bece), 561, 188}, + {UINT64_2PART_C(0x88fcf317, f22241e2), 588, 196}, + {UINT64_2PART_C(0xcc20ce9b, d35c78a5), 614, 204}, + {UINT64_2PART_C(0x98165af3, 7b2153df), 641, 212}, + {UINT64_2PART_C(0xe2a0b5dc, 971f303a), 667, 220}, + {UINT64_2PART_C(0xa8d9d153, 5ce3b396), 694, 228}, + {UINT64_2PART_C(0xfb9b7cd9, a4a7443c), 720, 236}, + {UINT64_2PART_C(0xbb764c4c, a7a44410), 747, 244}, + {UINT64_2PART_C(0x8bab8eef, b6409c1a), 774, 252}, + {UINT64_2PART_C(0xd01fef10, a657842c), 800, 260}, + {UINT64_2PART_C(0x9b10a4e5, e9913129), 827, 268}, + {UINT64_2PART_C(0xe7109bfb, a19c0c9d), 853, 276}, + {UINT64_2PART_C(0xac2820d9, 623bf429), 880, 284}, + {UINT64_2PART_C(0x80444b5e, 7aa7cf85), 907, 292}, + {UINT64_2PART_C(0xbf21e440, 03acdd2d), 933, 300}, + {UINT64_2PART_C(0x8e679c2f, 5e44ff8f), 960, 308}, + {UINT64_2PART_C(0xd433179d, 9c8cb841), 986, 316}, + {UINT64_2PART_C(0x9e19db92, b4e31ba9), 1013, 324}, + {UINT64_2PART_C(0xeb96bf6e, badf77d9), 1039, 332}, + {UINT64_2PART_C(0xaf87023b, 9bf0ee6b), 1066, 340}, + }; + + static const int kCachedPowersLength = GDCV8_ARRAY_SIZE(kCachedPowers); + static const int kCachedPowersOffset = 348; + static const double kD_1_LOG2_10 = 0.30102999566398114; + + inline void PowersOfTenCache::GetCachedPowerForBinaryExponentRange( + int min_exponent, + int max_exponent, + DiyFp* power, + int* decimal_exponent) { + int kQ = DiyFp::kSignificandSize; + double k = ceil((min_exponent + kQ - 1) * kD_1_LOG2_10); + int foo = kCachedPowersOffset; + int index = + (foo + static_cast(k) - 1) / kDecimalExponentDistance + 1; + ASSERT(0 <= index && index < kCachedPowersLength); + CachedPower cached_power = kCachedPowers[index]; + ASSERT(min_exponent <= cached_power.binary_exponent); + (void) max_exponent; + ASSERT(cached_power.binary_exponent <= max_exponent); + *decimal_exponent = cached_power.decimal_exponent; + *power = DiyFp(cached_power.significand, cached_power.binary_exponent); + } + + inline void PowersOfTenCache::GetCachedPowerForDecimalExponent(int requested_exponent, + DiyFp* power, + int* found_exponent) { + ASSERT(kMinDecimalExponent <= requested_exponent); + ASSERT(requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance); + int index = + (requested_exponent + kCachedPowersOffset) / kDecimalExponentDistance; + CachedPower cached_power = kCachedPowers[index]; + *power = DiyFp(cached_power.significand, cached_power.binary_exponent); + *found_exponent = cached_power.decimal_exponent; + ASSERT(*found_exponent <= requested_exponent); + ASSERT(requested_exponent < *found_exponent + kDecimalExponentDistance); + } + + static const int kMaxExactDoubleIntegerDecimalDigits = 15; + static const int kMaxUint64DecimalDigits = 19; + + static const int kMaxDecimalPower = 309; + static const int kMinDecimalPower = -324; + + static const uint64_t kMaxUint64 = UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF); + + static const double exact_powers_of_ten[] = { + 1.0, // 10^0 + 10.0, + 100.0, + 1000.0, + 10000.0, + 100000.0, + 1000000.0, + 10000000.0, + 100000000.0, + 1000000000.0, + 10000000000.0, // 10^10 + 100000000000.0, + 1000000000000.0, + 10000000000000.0, + 100000000000000.0, + 1000000000000000.0, + 10000000000000000.0, + 100000000000000000.0, + 1000000000000000000.0, + 10000000000000000000.0, + 100000000000000000000.0, // 10^20 + 1000000000000000000000.0, + 10000000000000000000000.0 + }; + + static const int kExactPowersOfTenSize = GDCV8_ARRAY_SIZE(exact_powers_of_ten); + static const int kMaxSignificantDecimalDigits = 780; + + inline Vector TrimLeadingZeros(Vector buffer) { + for (int i = 0; i < buffer.length(); i++) { + if (buffer[i] != '0') { + return buffer.SubVector(i, buffer.length()); + } + } + return Vector(buffer.start(), 0); + } + + inline Vector TrimTrailingZeros(Vector buffer) { + for (int i = buffer.length() - 1; i >= 0; --i) { + if (buffer[i] != '0') { + return buffer.SubVector(0, i + 1); + } + } + return Vector(buffer.start(), 0); + } + + inline void CutToMaxSignificantDigits(Vector buffer, + int exponent, + char* significant_buffer, + int* significant_exponent) { + for (int i = 0; i < kMaxSignificantDecimalDigits - 1; ++i) { + significant_buffer[i] = buffer[i]; + } + ASSERT(buffer[buffer.length() - 1] != '0'); + significant_buffer[kMaxSignificantDecimalDigits - 1] = '1'; + *significant_exponent = + exponent + (buffer.length() - kMaxSignificantDecimalDigits); + } + + inline void TrimAndCut(Vector buffer, int exponent, + char* buffer_copy_space, int space_size, + Vector* trimmed, int* updated_exponent) { + Vector right_trimmed = TrimTrailingZeros(buffer); + exponent -= right_trimmed.length(); + if (right_trimmed.length() > kMaxSignificantDecimalDigits) { + (void) space_size; + ASSERT(space_size >= kMaxSignificantDecimalDigits); + CutToMaxSignificantDigits(right_trimmed, exponent, + buffer_copy_space, updated_exponent); + *trimmed = Vector(buffer_copy_space, + kMaxSignificantDecimalDigits); + } else { + *trimmed = right_trimmed; + *updated_exponent = exponent; + } + } + + inline uint64_t ReadUint64(Vector buffer, + int* number_of_read_digits) { + uint64_t result = 0; + int i = 0; + while (i < buffer.length() && result <= (kMaxUint64 / 10 - 1)) { + int digit = buffer[i++] - '0'; + ASSERT(0 <= digit && digit <= 9); + result = 10 * result + digit; + } + *number_of_read_digits = i; + return result; + } + + inline void ReadDiyFp(Vector buffer, + DiyFp* result, + int* remaining_decimals) { + int read_digits; + uint64_t significand = ReadUint64(buffer, &read_digits); + if (buffer.length() == read_digits) { + *result = DiyFp(significand, 0); + *remaining_decimals = 0; + } else { + if (buffer[read_digits] >= '5') { + significand++; + } + int exponent = 0; + *result = DiyFp(significand, exponent); + *remaining_decimals = buffer.length() - read_digits; + } + } + + inline bool DoubleStrtod(Vector trimmed, + int exponent, + double* result) { +#if !defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS) + // On x86 the floating-point stack can be 64 or 80 bits wide. If it is + // 80 bits wide (as is the case on Linux) then double-rounding occurs and the + // result is not accurate. + // We know that Windows32 uses 64 bits and is therefore accurate. + // Note that the ARM simulator is compiled for 32bits. It therefore exhibits + // the same problem. + return false; +#endif + if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) { + int read_digits; + if (exponent < 0 && -exponent < kExactPowersOfTenSize) { + *result = static_cast(ReadUint64(trimmed, &read_digits)); + ASSERT(read_digits == trimmed.length()); + *result /= exact_powers_of_ten[-exponent]; + return true; + } + if (0 <= exponent && exponent < kExactPowersOfTenSize) { + *result = static_cast(ReadUint64(trimmed, &read_digits)); + ASSERT(read_digits == trimmed.length()); + *result *= exact_powers_of_ten[exponent]; + return true; + } + int remaining_digits = + kMaxExactDoubleIntegerDecimalDigits - trimmed.length(); + if ((0 <= exponent) && + (exponent - remaining_digits < kExactPowersOfTenSize)) { + *result = static_cast(ReadUint64(trimmed, &read_digits)); + ASSERT(read_digits == trimmed.length()); + *result *= exact_powers_of_ten[remaining_digits]; + *result *= exact_powers_of_ten[exponent - remaining_digits]; + return true; + } + } + return false; + } + + inline DiyFp AdjustmentPowerOfTen(int exponent) { + ASSERT(0 < exponent); + ASSERT(exponent < PowersOfTenCache::kDecimalExponentDistance); + ASSERT(PowersOfTenCache::kDecimalExponentDistance == 8); + switch (exponent) { + case 1: return DiyFp(UINT64_2PART_C(0xa0000000, 00000000), -60); + case 2: return DiyFp(UINT64_2PART_C(0xc8000000, 00000000), -57); + case 3: return DiyFp(UINT64_2PART_C(0xfa000000, 00000000), -54); + case 4: return DiyFp(UINT64_2PART_C(0x9c400000, 00000000), -50); + case 5: return DiyFp(UINT64_2PART_C(0xc3500000, 00000000), -47); + case 6: return DiyFp(UINT64_2PART_C(0xf4240000, 00000000), -44); + case 7: return DiyFp(UINT64_2PART_C(0x98968000, 00000000), -40); + default: + UNREACHABLE(); + } + } + + inline bool DiyFpStrtod(Vector buffer, + int exponent, + double* result) { + DiyFp input; + int remaining_decimals; + ReadDiyFp(buffer, &input, &remaining_decimals); + const int kDenominatorLog = 3; + const int kDenominator = 1 << kDenominatorLog; + exponent += remaining_decimals; + uint64_t error = (remaining_decimals == 0 ? 0 : kDenominator / 2); + + int old_e = input.e(); + input.Normalize(); + error <<= old_e - input.e(); + + ASSERT(exponent <= PowersOfTenCache::kMaxDecimalExponent); + if (exponent < PowersOfTenCache::kMinDecimalExponent) { + *result = 0.0; + return true; + } + DiyFp cached_power; + int cached_decimal_exponent; + PowersOfTenCache::GetCachedPowerForDecimalExponent(exponent, + &cached_power, + &cached_decimal_exponent); + + if (cached_decimal_exponent != exponent) { + int adjustment_exponent = exponent - cached_decimal_exponent; + DiyFp adjustment_power = AdjustmentPowerOfTen(adjustment_exponent); + input.Multiply(adjustment_power); + if (kMaxUint64DecimalDigits - buffer.length() >= adjustment_exponent) { + ASSERT(DiyFp::kSignificandSize == 64); + } else { + error += kDenominator / 2; + } + } + + input.Multiply(cached_power); + int error_b = kDenominator / 2; + int error_ab = (error == 0 ? 0 : 1); + int fixed_error = kDenominator / 2; + error += error_b + error_ab + fixed_error; + + old_e = input.e(); + input.Normalize(); + error <<= old_e - input.e(); + + int order_of_magnitude = DiyFp::kSignificandSize + input.e(); + int effective_significand_size = + Double::SignificandSizeForOrderOfMagnitude(order_of_magnitude); + int precision_digits_count = + DiyFp::kSignificandSize - effective_significand_size; + if (precision_digits_count + kDenominatorLog >= DiyFp::kSignificandSize) { + int shift_amount = (precision_digits_count + kDenominatorLog) - + DiyFp::kSignificandSize + 1; + input.set_f(input.f() >> shift_amount); + input.set_e(input.e() + shift_amount); + error = (error >> shift_amount) + 1 + kDenominator; + precision_digits_count -= shift_amount; + } + ASSERT(DiyFp::kSignificandSize == 64); + ASSERT(precision_digits_count < 64); + uint64_t one64 = 1; + uint64_t precision_bits_mask = (one64 << precision_digits_count) - 1; + uint64_t precision_bits = input.f() & precision_bits_mask; + uint64_t half_way = one64 << (precision_digits_count - 1); + precision_bits *= kDenominator; + half_way *= kDenominator; + DiyFp rounded_input(input.f() >> precision_digits_count, + input.e() + precision_digits_count); + if (precision_bits >= half_way + error) { + rounded_input.set_f(rounded_input.f() + 1); + } + *result = Double(rounded_input).value(); + if (half_way - error < precision_bits && precision_bits < half_way + error) { + return false; + } else { + return true; + } + } + + inline int CompareBufferWithDiyFp(Vector buffer, + int exponent, + DiyFp diy_fp) { + ASSERT(buffer.length() + exponent <= kMaxDecimalPower + 1); + ASSERT(buffer.length() + exponent > kMinDecimalPower); + ASSERT(buffer.length() <= kMaxSignificantDecimalDigits); + ASSERT(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits); + Bignum buffer_bignum; + Bignum diy_fp_bignum; + buffer_bignum.AssignDecimalString(buffer); + diy_fp_bignum.AssignUInt64(diy_fp.f()); + if (exponent >= 0) { + buffer_bignum.MultiplyByPowerOfTen(exponent); + } else { + diy_fp_bignum.MultiplyByPowerOfTen(-exponent); + } + if (diy_fp.e() > 0) { + diy_fp_bignum.ShiftLeft(diy_fp.e()); + } else { + buffer_bignum.ShiftLeft(-diy_fp.e()); + } + return Bignum::Compare(buffer_bignum, diy_fp_bignum); + } + + inline bool ComputeGuess(Vector trimmed, int exponent, + double* guess) { + if (trimmed.length() == 0) { + *guess = 0.0; + return true; + } + if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) { + *guess = Double::Infinity(); + return true; + } + if (exponent + trimmed.length() <= kMinDecimalPower) { + *guess = 0.0; + return true; + } + + if (DoubleStrtod(trimmed, exponent, guess) || + DiyFpStrtod(trimmed, exponent, guess)) { + return true; + } + if (*guess == Double::Infinity()) { + return true; + } + return false; + } + + inline double Strtod( Vector< const char > buffer, int exponent ) + { + double guess; + if (ComputeGuess(buffer, exponent, &guess)) { + return guess; + } + DiyFp upper_boundary = Double(guess).UpperBoundary(); + int comparison = CompareBufferWithDiyFp(buffer, exponent, upper_boundary); + if (comparison < 0) { + return guess; + } else if (comparison > 0) { + return Double(guess).NextDouble(); + } else if ((Double(guess).Significand() & 1) == 0) { + return guess; + } else { + return Double(guess).NextDouble(); + } + } + + namespace + { + const int kBase10MaximalLength = 17; + const int kMaxExponentialDigits = 120; + const int kFastDtoaMaximalLength = 17; + const int kMinimalTargetExponent = -60; + const int kMaximalTargetExponent = -32; + + const unsigned int kSmallPowersOfTen[] = {0, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; + + } // + + inline void BiggestPowerTen(uint32_t number, + int number_bits, + uint32_t* power, + int* exponent_plus_one) { + ASSERT(number < (1u << (number_bits + 1))); + int exponent_plus_one_guess = ((number_bits + 1) * 1233 >> 12); + exponent_plus_one_guess++; + if (number < kSmallPowersOfTen[exponent_plus_one_guess]) { + exponent_plus_one_guess--; + } + *power = kSmallPowersOfTen[exponent_plus_one_guess]; + *exponent_plus_one = exponent_plus_one_guess; + } + + inline bool RoundWeed(Vector buffer, + int length, + uint64_t distance_too_high_w, + uint64_t unsafe_interval, + uint64_t rest, + uint64_t ten_kappa, + uint64_t unit) { + uint64_t small_distance = distance_too_high_w - unit; + uint64_t big_distance = distance_too_high_w + unit; + ASSERT(rest <= unsafe_interval); + while (rest < small_distance && + unsafe_interval - rest >= ten_kappa && + (rest + ten_kappa < small_distance || + small_distance - rest >= rest + ten_kappa - small_distance)) { + buffer[length - 1]--; + rest += ten_kappa; + } + if (rest < big_distance && + unsafe_interval - rest >= ten_kappa && + (rest + ten_kappa < big_distance || + big_distance - rest > rest + ten_kappa - big_distance)) { + return false; + } + return (2 * unit <= rest) && (rest <= unsafe_interval - 4 * unit); + } + + inline bool DigitGen(DiyFp low, + DiyFp w, + DiyFp high, + Vector buffer, + int* length, + int* kappa) { + ASSERT(low.e() == w.e() && w.e() == high.e()); + ASSERT(low.f() + 1 <= high.f() - 1); + ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent); + uint64_t unit = 1; + DiyFp too_low = DiyFp(low.f() - unit, low.e()); + DiyFp too_high = DiyFp(high.f() + unit, high.e()); + DiyFp unsafe_interval = DiyFp::Minus(too_high, too_low); + DiyFp one = DiyFp(static_cast(1) << -w.e(), w.e()); + uint32_t integrals = static_cast(too_high.f() >> -one.e()); + uint64_t fractionals = too_high.f() & (one.f() - 1); + uint32_t divisor; + int divisor_exponent_plus_one; + BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.e()), + &divisor, &divisor_exponent_plus_one); + *kappa = divisor_exponent_plus_one; + *length = 0; + while (*kappa > 0) { + int digit = integrals / divisor; + ASSERT(digit <= 9); + buffer[*length] = static_cast('0' + digit); + (*length)++; + integrals %= divisor; + (*kappa)--; + uint64_t rest = + (static_cast(integrals) << -one.e()) + fractionals; + if (rest < unsafe_interval.f()) { + return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).f(), + unsafe_interval.f(), rest, + static_cast(divisor) << -one.e(), unit); + } + divisor /= 10; + } + ASSERT(one.e() >= -60); + ASSERT(fractionals < one.f()); + ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f()); + for (;;) { + fractionals *= 10; + unit *= 10; + unsafe_interval.set_f(unsafe_interval.f() * 10); + int digit = static_cast(fractionals >> -one.e()); + ASSERT(digit <= 9); + buffer[*length] = static_cast('0' + digit); + (*length)++; + fractionals &= one.f() - 1; + (*kappa)--; + if (fractionals < unsafe_interval.f()) { + return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).f() * unit, + unsafe_interval.f(), fractionals, one.f(), unit); + } + } + } + + inline bool Grisu3( const double v, + Vector buffer, + int * length, + int * decimal_exponent ) + { + DiyFp w = Double(v).AsNormalizedDiyFp(); + DiyFp boundary_minus, boundary_plus; + Double(v).NormalizedBoundaries(&boundary_minus, &boundary_plus); + ASSERT(boundary_plus.e() == w.e()); + DiyFp ten_mk; + int mk; + int ten_mk_minimal_binary_exponent = + kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize); + int ten_mk_maximal_binary_exponent = + kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize); + PowersOfTenCache::GetCachedPowerForBinaryExponentRange(ten_mk_minimal_binary_exponent, + ten_mk_maximal_binary_exponent, + &ten_mk, &mk); + ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() + + DiyFp::kSignificandSize) && + (kMaximalTargetExponent >= w.e() + ten_mk.e() + + DiyFp::kSignificandSize)); + DiyFp scaled_w = DiyFp::Times(w, ten_mk); + ASSERT(scaled_w.e() == + boundary_plus.e() + ten_mk.e() + DiyFp::kSignificandSize); + DiyFp scaled_boundary_minus = DiyFp::Times(boundary_minus, ten_mk); + DiyFp scaled_boundary_plus = DiyFp::Times(boundary_plus, ten_mk); + int kappa; + bool result = DigitGen(scaled_boundary_minus, scaled_w, scaled_boundary_plus, + buffer, length, &kappa); + *decimal_exponent = -mk + kappa; + return result; + } + + inline bool FastDtoa( const double v, + Vector< char > buffer, + int * length, + int * decimal_point ) + { + int decimal_exponent = 0; + if ( Grisu3(v, buffer, length, &decimal_exponent) ) { + *decimal_point = *length + decimal_exponent; + buffer[*length] = '\0'; + return true; + } + return false; + } + + static int NormalizedExponent(uint64_t significand, int exponent) { + ASSERT(significand != 0); + while ((significand & Double::kHiddenBit) == 0) { + significand = significand << 1; + exponent = exponent - 1; + } + return exponent; + } + + inline int EstimatePower(int exponent) { + const double k1Log10 = 0.30102999566398114; + const int kSignificandSize = Double::kSignificandSize; + double estimate = ceil((exponent + kSignificandSize - 1) * k1Log10 - 1e-10); + return static_cast(estimate); + } + + inline void InitialScaledStartValuesPositiveExponent(uint64_t significand, int exponent, + int estimated_power, bool need_boundary_deltas, + Bignum* numerator, Bignum* denominator, + Bignum* delta_minus, Bignum* delta_plus) { + ASSERT(estimated_power >= 0); + numerator->AssignUInt64(significand); + numerator->ShiftLeft(exponent); + denominator->AssignPowerUInt16(10, estimated_power); + + if (need_boundary_deltas) { + denominator->ShiftLeft(1); + numerator->ShiftLeft(1); + delta_plus->AssignUInt16(1); + delta_plus->ShiftLeft(exponent); + delta_minus->AssignUInt16(1); + delta_minus->ShiftLeft(exponent); + } + } + + inline void InitialScaledStartValuesNegativeExponentPositivePower( + uint64_t significand, int exponent, + int estimated_power, bool need_boundary_deltas, + Bignum* numerator, Bignum* denominator, + Bignum* delta_minus, Bignum* delta_plus) { + numerator->AssignUInt64(significand); + denominator->AssignPowerUInt16(10, estimated_power); + denominator->ShiftLeft(-exponent); + + if (need_boundary_deltas) { + denominator->ShiftLeft(1); + numerator->ShiftLeft(1); + delta_plus->AssignUInt16(1); + delta_minus->AssignUInt16(1); + } + } + + inline void InitialScaledStartValuesNegativeExponentNegativePower( + uint64_t significand, int exponent, + int estimated_power, bool need_boundary_deltas, + Bignum* numerator, Bignum* denominator, + Bignum* delta_minus, Bignum* delta_plus) { + Bignum* power_ten = numerator; + power_ten->AssignPowerUInt16(10, -estimated_power); + + if (need_boundary_deltas) { + delta_plus->AssignBignum(*power_ten); + delta_minus->AssignBignum(*power_ten); + } + ASSERT(numerator == power_ten); + numerator->MultiplyByUInt64(significand); + denominator->AssignUInt16(1); + denominator->ShiftLeft(-exponent); + + if (need_boundary_deltas) { + numerator->ShiftLeft(1); + denominator->ShiftLeft(1); + } + } + + inline void InitialScaledStartValues(uint64_t significand, + int exponent, + bool lower_boundary_is_closer, + int estimated_power, + bool need_boundary_deltas, + Bignum* numerator, + Bignum* denominator, + Bignum* delta_minus, + Bignum* delta_plus) { + if (exponent >= 0) { + InitialScaledStartValuesPositiveExponent( + significand, exponent, estimated_power, need_boundary_deltas, + numerator, denominator, delta_minus, delta_plus); + } else if (estimated_power >= 0) { + InitialScaledStartValuesNegativeExponentPositivePower( + significand, exponent, estimated_power, need_boundary_deltas, + numerator, denominator, delta_minus, delta_plus); + } else { + InitialScaledStartValuesNegativeExponentNegativePower( + significand, exponent, estimated_power, need_boundary_deltas, + numerator, denominator, delta_minus, delta_plus); + } + if (need_boundary_deltas && lower_boundary_is_closer) { + denominator->ShiftLeft(1); + numerator->ShiftLeft(1); + delta_plus->ShiftLeft(1); + } + } + + inline void GenerateShortestDigits(Bignum* numerator, Bignum* denominator, + Bignum* delta_minus, Bignum* delta_plus, + bool is_even, + Vector buffer, int* length); + + inline void FixupMultiply10(int estimated_power, bool is_even, + int* decimal_point, + Bignum* numerator, Bignum* denominator, + Bignum* delta_minus, Bignum* delta_plus) { + bool in_range; + if (is_even) { + in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0; + } else { + in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0; + } + if (in_range) { + *decimal_point = estimated_power + 1; + } else { + *decimal_point = estimated_power; + numerator->Times10(); + if (Bignum::Equal(*delta_minus, *delta_plus)) { + delta_minus->Times10(); + delta_plus->AssignBignum(*delta_minus); + } else { + delta_minus->Times10(); + delta_plus->Times10(); + } + } + } + + inline void BignumDtoa(const double v, Vector buffer, int* length, int* decimal_point) { + ASSERT(v > 0); + ASSERT(!Double(v).IsSpecial()); + uint64_t significand; + int exponent; + bool lower_boundary_is_closer; + significand = Double(v).Significand(); + exponent = Double(v).Exponent(); + lower_boundary_is_closer = Double(v).LowerBoundaryIsCloser(); + const bool need_boundary_deltas = true; + + bool is_even = (significand & 1) == 0; + int normalized_exponent = NormalizedExponent(significand, exponent); + int estimated_power = EstimatePower(normalized_exponent); + + Bignum numerator; + Bignum denominator; + Bignum delta_minus; + Bignum delta_plus; + ASSERT(Bignum::kMaxSignificantBits >= 324*4); + InitialScaledStartValues(significand, exponent, lower_boundary_is_closer, + estimated_power, need_boundary_deltas, + &numerator, &denominator, + &delta_minus, &delta_plus); + FixupMultiply10(estimated_power, is_even, decimal_point, + &numerator, &denominator, + &delta_minus, &delta_plus); + GenerateShortestDigits(&numerator, &denominator, + &delta_minus, &delta_plus, + is_even, buffer, length); + buffer[*length] = '\0'; + } + + inline void GenerateShortestDigits(Bignum* numerator, Bignum* denominator, + Bignum* delta_minus, Bignum* delta_plus, + bool is_even, + Vector buffer, int* length) { + if (Bignum::Equal(*delta_minus, *delta_plus)) { + delta_plus = delta_minus; + } + *length = 0; + for (;;) { + uint16_t digit; + digit = numerator->DivideModuloIntBignum(*denominator); + ASSERT(digit <= 9); + buffer[(*length)++] = static_cast(digit + '0'); + + bool in_delta_room_minus; + bool in_delta_room_plus; + if (is_even) { + in_delta_room_minus = Bignum::LessEqual(*numerator, *delta_minus); + } else { + in_delta_room_minus = Bignum::Less(*numerator, *delta_minus); + } + if (is_even) { + in_delta_room_plus = + Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0; + } else { + in_delta_room_plus = + Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0; + } + if (!in_delta_room_minus && !in_delta_room_plus) { + numerator->Times10(); + delta_minus->Times10(); + if (delta_minus != delta_plus) { + delta_plus->Times10(); + } + } else if (in_delta_room_minus && in_delta_room_plus) { + int compare = Bignum::PlusCompare(*numerator, *numerator, *denominator); + if (compare < 0) { + } else if (compare > 0) { + ASSERT(buffer[(*length) - 1] != '9'); + buffer[(*length) - 1]++; + } else { + if ((buffer[(*length) - 1] - '0') % 2 == 0) { + } else { + ASSERT(buffer[(*length) - 1] != '9'); + buffer[(*length) - 1]++; + } + } + return; + } else if (in_delta_room_minus) { + return; + } else { + ASSERT(buffer[(*length) -1] != '9'); + buffer[(*length) - 1]++; + return; + } + } + } + + inline bool DoubleToAscii( double v, + char * buffer, + int buffer_length, + std::ostream & oss, + int * length, + int * point ) + { + if ( Double( v ).Sign() < 0 ) { + oss << '-'; + v = -v; + } + if ( v == 0.0 ) { + oss << "0.0"; + return true; + } + Vector< char > vector( buffer, buffer_length ); + + if ( ! FastDtoa(v, vector, length, point) ) { + BignumDtoa( v, vector, length, point ); + vector[ * length ] = '\0'; + } + return false; + } + + inline void CreateDecimalRepresentation(const char* decimal_digits, + int length, + int decimal_point, + int digits_after_point, + std::ostream & oss) { + if (decimal_point <= 0) { + oss << '0'; + if (digits_after_point > 0) { + oss << '.'; + for ( int i = 0; i < -decimal_point; ++i ) { + oss << '0'; + } + ASSERT(length <= digits_after_point - (-decimal_point)); + oss.write( decimal_digits, length ); + int remaining_digits = digits_after_point - (-decimal_point) - length; + for ( int i = 0; i < remaining_digits; ++i ) { + oss << '0'; + } + } + } else if (decimal_point >= length) { + oss.write( decimal_digits, length ); + for ( int i = 0; i < decimal_point - length; ++i ) { + oss << '0'; + } + if (digits_after_point > 0) { + oss << '.'; + for ( int i = 0; i < digits_after_point; ++i ) { + oss << '0'; + } + } + } else { + ASSERT(digits_after_point > 0); + oss.write( decimal_digits, decimal_point ); + oss << '.'; + ASSERT(length - decimal_point <= digits_after_point); + oss.write( decimal_digits + decimal_point, length - decimal_point ); + int remaining_digits = digits_after_point - (length - decimal_point); + for ( int i = 0; i < remaining_digits; ++i ) { + oss << '0'; + } + } + if (digits_after_point == 0) { + oss << '.'; + oss << '0'; + } + } + + inline void CreateExponentialRepresentation(const char* decimal_digits, + int length, + int exponent, + std::ostream & oss) { + ASSERT(length != 0); + oss << decimal_digits[ 0 ]; + if (length != 1) { + oss << '.'; + oss.write( decimal_digits + 1, length - 1 ); + } + oss << 'e'; + if (exponent < 0) { + oss << '-'; + exponent = -exponent; + } else { + // oss << '+'; + } + if (exponent == 0) { + oss << '0'; + return; + } + oss << exponent; + } + + inline void Dtostr( std::ostream & oss, const double value ) + { + int decimal_point; + const int kDecimalRepCapacity = kBase10MaximalLength + 1; // Plus 1 is '\0'. + char decimal_rep[ kDecimalRepCapacity ]; + int decimal_rep_length; + + if ( ! DoubleToAscii(value, decimal_rep, kDecimalRepCapacity, + oss, &decimal_rep_length, &decimal_point) ) + { + const int exponent = decimal_point - 1; + if ((-6 <= exponent) && + (exponent < 21)) { + CreateDecimalRepresentation(decimal_rep, decimal_rep_length, + decimal_point, + Max(0, decimal_rep_length - decimal_point), + oss); + } else { + CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent, + oss); + } + } + } + +} // json_double_conversion + +#endif diff --git a/include/tao/json/external/operators.hpp b/include/tao/json/external/operators.hpp new file mode 100644 index 00000000..bc40f0ba --- /dev/null +++ b/include/tao/json/external/operators.hpp @@ -0,0 +1,658 @@ +// The Art of C++ / Operators +// Copyright (c) 2013-2017 Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/operators/ + +#ifndef TAOCPP_OPERATORS_INCLUDE_OPERATORS_HPP +#define TAOCPP_OPERATORS_INCLUDE_OPERATORS_HPP + +#include + +#ifndef TAOCPP_NO_RVALUE_REFERENCE_RESULTS +#define TAOCPP_OPERATORS_BASIC_OP( name, op ) \ + template< typename T, typename U = T > \ + class name \ + { \ + friend T operator op( const T& lhs, const U& rhs ) \ + noexcept( noexcept( T( lhs ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ + { \ + T nrv( lhs ); \ + nrv op##= rhs; \ + return nrv; \ + } \ + \ + friend T operator op( const T& lhs, U&& rhs ) \ + noexcept( noexcept( T( lhs ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ + { \ + T nrv( lhs ); \ + nrv op##= std::move( rhs ); \ + return nrv; \ + } \ + \ + friend T&& operator op( T&& lhs, const U& rhs ) \ + noexcept( noexcept( lhs op##= rhs ) ) \ + { \ + lhs op##= rhs; \ + return std::move( lhs ); \ + } \ + \ + friend T&& operator op( T&& lhs, U&& rhs ) \ + noexcept( noexcept( lhs op##= std::move( rhs ) ) ) \ + { \ + lhs op##= std::move( rhs ); \ + return std::move( lhs ); \ + } \ + } +#else +#define TAOCPP_OPERATORS_BASIC_OP( name, op ) \ + template< typename T, typename U = T > \ + class name \ + { \ + friend T operator op( const T& lhs, const U& rhs ) \ + noexcept( noexcept( T( lhs ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ + { \ + T nrv( lhs ); \ + nrv op##= rhs; \ + return nrv; \ + } \ + \ + friend T operator op( const T& lhs, U&& rhs ) \ + noexcept( noexcept( T( lhs ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ + { \ + T nrv( lhs ); \ + nrv op##= std::move( rhs ); \ + return nrv; \ + } \ + \ + friend T operator op( T&& lhs, const U& rhs ) \ + noexcept( noexcept( T( std::move( lhs ) ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ + { \ + T nrv( std::move( lhs ) ); \ + nrv op##= rhs; \ + return nrv; \ + } \ + \ + friend T operator op( T&& lhs, U&& rhs ) \ + noexcept( noexcept( T( std::move( lhs ) ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ + { \ + T nrv( std::move( lhs ) ); \ + nrv op##= std::move( rhs ); \ + return nrv; \ + } \ + } +#endif + +#define TAOCPP_OPERATORS_BASIC_OP_LEFT( name, op ) \ + template< typename T, typename U > \ + class name##_left \ + { \ + friend T operator op( const U& lhs, const T& rhs ) \ + noexcept( noexcept( T( lhs ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ + { \ + T nrv( lhs ); \ + nrv op##= rhs; \ + return nrv; \ + } \ + \ + friend T operator op( const U& lhs, T&& rhs ) \ + noexcept( noexcept( T( lhs ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ + { \ + T nrv( lhs ); \ + nrv op##= std::move( rhs ); \ + return nrv; \ + } \ + \ + friend T operator op( U&& lhs, const T& rhs ) \ + noexcept( noexcept( T( std::move( lhs ) ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ + { \ + T nrv( std::move( lhs ) ); \ + nrv op##= rhs; \ + return nrv; \ + } \ + \ + friend T operator op( U&& lhs, T&& rhs ) \ + noexcept( noexcept( T( std::move( lhs ) ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ + { \ + T nrv( std::move( lhs ) ); \ + nrv op##= std::move( rhs ); \ + return nrv; \ + } \ + } + +#ifndef TAOCPP_NO_RVALUE_REFERENCE_RESULTS +#define TAOCPP_OPERATORS_BASIC_OP_COMMUTATIVE( name, op ) \ + template< typename T, typename U = T > \ + class commutative_##name \ + { \ + friend T operator op( const T& lhs, const U& rhs ) \ + noexcept( noexcept( T( lhs ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ + { \ + T nrv( lhs ); \ + nrv op##= rhs; \ + return nrv; \ + } \ + \ + friend T operator op( const T& lhs, U&& rhs ) \ + noexcept( noexcept( T( lhs ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ + { \ + T nrv( lhs ); \ + nrv op##= std::move( rhs ); \ + return nrv; \ + } \ + \ + friend T&& operator op( T&& lhs, const U& rhs ) \ + noexcept( noexcept( lhs op##= rhs ) ) \ + { \ + lhs op##= rhs; \ + return std::move( lhs ); \ + } \ + \ + friend T&& operator op( T&& lhs, U&& rhs ) \ + noexcept( noexcept( lhs op##= std::move( rhs ) ) ) \ + { \ + lhs op##= std::move( rhs ); \ + return std::move( lhs ); \ + } \ + \ + friend T operator op( const U& lhs, const T& rhs ) \ + noexcept( noexcept( T( rhs ), std::declval< T& >() op##= lhs, T( std::declval< T& >() ) ) ) \ + { \ + T nrv( rhs ); \ + nrv op##= lhs; \ + return nrv; \ + } \ + \ + friend T&& operator op( const U& lhs, T&& rhs ) \ + noexcept( noexcept( rhs op##= lhs ) ) \ + { \ + rhs op##= lhs; \ + return std::move( rhs ); \ + } \ + \ + friend T operator op( U&& lhs, const T& rhs ) \ + noexcept( noexcept( T( rhs ), std::declval< T& >() op##= std::move( lhs ) ) ) \ + { \ + T nrv( rhs ); \ + nrv op##= std::move( lhs ); \ + return nrv; \ + } \ + \ + friend T&& operator op( U&& lhs, T&& rhs ) \ + noexcept( noexcept( rhs op##= std::move( lhs ) ) ) \ + { \ + rhs op##= std::move( lhs ); \ + return std::move( rhs ); \ + } \ + }; \ + \ + template< typename T > \ + class commutative_##name< T > \ + { \ + friend T operator op( const T& lhs, const T& rhs ) \ + noexcept( noexcept( T( lhs ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ + { \ + T nrv( lhs ); \ + nrv op##= rhs; \ + return nrv; \ + } \ + \ + friend T&& operator op( const T& lhs, T&& rhs ) \ + noexcept( noexcept( rhs op##= lhs ) ) \ + { \ + rhs op##= lhs; \ + return std::move( rhs ); \ + } \ + \ + friend T&& operator op( T&& lhs, const T& rhs ) \ + noexcept( noexcept( lhs op##= rhs ) ) \ + { \ + lhs op##= rhs; \ + return std::move( lhs ); \ + } \ + \ + friend T&& operator op( T&& lhs, T&& rhs ) \ + noexcept( noexcept( lhs op##= std::move( rhs ) ) ) \ + { \ + lhs op##= std::move( rhs ); \ + return std::move( lhs ); \ + } \ + } +#else +#define TAOCPP_OPERATORS_BASIC_OP_COMMUTATIVE( name, op ) \ + template< typename T, typename U = T > \ + class commutative_##name \ + { \ + friend T operator op( const T& lhs, const U& rhs ) \ + noexcept( noexcept( T( lhs ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ + { \ + T nrv( lhs ); \ + nrv op##= rhs; \ + return nrv; \ + } \ + \ + friend T operator op( const T& lhs, U&& rhs ) \ + noexcept( noexcept( T( lhs ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ + { \ + T nrv( lhs ); \ + nrv op##= std::move( rhs ); \ + return nrv; \ + } \ + \ + friend T operator op( T&& lhs, const U& rhs ) \ + noexcept( noexcept( T( std::move( lhs ) ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ + { \ + T nrv( std::move( lhs ) ); \ + nrv op##= rhs; \ + return nrv; \ + } \ + \ + friend T operator op( T&& lhs, U&& rhs ) \ + noexcept( noexcept( T( std::move( lhs ) ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ + { \ + T nrv( std::move( lhs ) ); \ + nrv op##= std::move( rhs ); \ + return nrv; \ + } \ + \ + friend T operator op( const U& lhs, const T& rhs ) \ + noexcept( noexcept( T( rhs ), std::declval< T& >() op##= lhs, T( std::declval< T& >() ) ) ) \ + { \ + T nrv( rhs ); \ + nrv op##= lhs; \ + return nrv; \ + } \ + \ + friend T operator op( const U& lhs, T&& rhs ) \ + noexcept( noexcept( T( std::move( rhs ) ), std::declval< T& >() op##= lhs, T( std::declval< T& >() ) ) ) \ + { \ + T nrv( std::move( rhs ) ); \ + nrv op##= lhs; \ + return nrv; \ + } \ + \ + friend T operator op( U&& lhs, const T& rhs ) \ + noexcept( noexcept( T( rhs ), std::declval< T& >() op##= std::move( lhs ) ) ) \ + { \ + T nrv( rhs ); \ + nrv op##= std::move( lhs ); \ + return nrv; \ + } \ + \ + friend T operator op( U&& lhs, T&& rhs ) \ + noexcept( noexcept( T( std::move( rhs ) ), std::declval< T& >() op##= std::move( lhs ) ) ) \ + { \ + T nrv( std::move( rhs ) ); \ + nrv op##= std::move( lhs ); \ + return nrv; \ + } \ + }; \ + \ + template< typename T > \ + class commutative_##name< T > \ + { \ + friend T operator op( const T& lhs, const T& rhs ) \ + noexcept( noexcept( T( lhs ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ + { \ + T nrv( lhs ); \ + nrv op##= rhs; \ + return nrv; \ + } \ + \ + friend T operator op( const T& lhs, T&& rhs ) \ + noexcept( noexcept( T( lhs ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ + { \ + T nrv( lhs ); \ + nrv op##= std::move( rhs ); \ + return nrv; \ + } \ + \ + friend T operator op( T&& lhs, const T& rhs ) \ + noexcept( noexcept( T( std::move( lhs ) ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ + { \ + T nrv( std::move( lhs ) ); \ + nrv op##= rhs; \ + return nrv; \ + } \ + \ + friend T operator op( T&& lhs, T&& rhs ) \ + noexcept( noexcept( T( std::move( lhs ) ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ + { \ + T nrv( std::move( lhs ) ); \ + nrv op##= std::move( rhs ); \ + return nrv; \ + } \ + } +#endif + +namespace tao +{ + namespace operators + { + template< typename T, typename U = T > + class equality_comparable + { + friend bool operator!=( const T& lhs, const U& rhs ) + noexcept( noexcept( static_cast< bool >( lhs == rhs ) ) ) + { + return !static_cast< bool >( lhs == rhs ); + } + + friend bool operator==( const U& lhs, const T& rhs ) + noexcept( noexcept( static_cast< bool >( rhs == lhs ) ) ) + { + return static_cast< bool >( rhs == lhs ); + } + + friend bool operator!=( const U& lhs, const T& rhs ) + noexcept( noexcept( static_cast< bool >( rhs != lhs ) ) ) + { + return static_cast< bool >( rhs != lhs ); + } + }; + + template< typename T > + class equality_comparable< T > + { + friend bool operator!=( const T& lhs, const T& rhs ) + noexcept( noexcept( static_cast< bool >( lhs == rhs ) ) ) + { + return !static_cast< bool >( lhs == rhs ); + } + }; + + template< typename T, typename U = T > + class less_than_comparable + { + friend bool operator<=( const T& lhs, const U& rhs ) + noexcept( noexcept( static_cast< bool >( lhs > rhs ) ) ) + { + return !static_cast< bool >( lhs > rhs ); + } + + friend bool operator>=( const T& lhs, const U& rhs ) + noexcept( noexcept( static_cast< bool >( lhs < rhs ) ) ) + { + return !static_cast< bool >( lhs < rhs ); + } + + friend bool operator<( const U& lhs, const T& rhs ) + noexcept( noexcept( static_cast< bool >( rhs > lhs ) ) ) + { + return static_cast< bool >( rhs > lhs ); + } + + friend bool operator>( const U& lhs, const T& rhs ) + noexcept( noexcept( static_cast< bool >( rhs < lhs ) ) ) + { + return static_cast< bool >( rhs < lhs ); + } + + friend bool operator<=( const U& lhs, const T& rhs ) + noexcept( noexcept( static_cast< bool >( rhs >= lhs ) ) ) + { + return static_cast< bool >( rhs >= lhs ); + } + + friend bool operator>=( const U& lhs, const T& rhs ) + noexcept( noexcept( static_cast< bool >( rhs <= lhs ) ) ) + { + return static_cast< bool >( rhs <= lhs ); + } + }; + + template< typename T > + class less_than_comparable< T > + { + friend bool operator>( const T& lhs, const T& rhs ) + noexcept( noexcept( static_cast< bool >( rhs < lhs ) ) ) + { + return static_cast< bool >( rhs < lhs ); + } + + friend bool operator<=( const T& lhs, const T& rhs ) + noexcept( noexcept( static_cast< bool >( rhs < lhs ) ) ) + { + return !static_cast< bool >( rhs < lhs ); + } + + friend bool operator>=( const T& lhs, const T& rhs ) + noexcept( noexcept( static_cast< bool >( lhs < rhs ) ) ) + { + return !static_cast< bool >( lhs < rhs ); + } + }; + + template< typename T, typename U = T > + class totally_ordered + : less_than_comparable< T, U >, equality_comparable< T, U > + { + }; + + template< typename T, typename U = T > + class equivalent + { + friend bool operator==( const T& lhs, const U& rhs ) + noexcept( noexcept( static_cast< bool >( lhs < rhs ), static_cast< bool >( lhs > rhs ) ) ) + { + return !static_cast< bool >( lhs < rhs ) && !static_cast< bool >( lhs > rhs ); + } + }; + + template< typename T > + class equivalent< T > + { + friend bool operator==( const T& lhs, const T& rhs ) + noexcept( noexcept( static_cast< bool >( lhs < rhs ) ) ) + { + return !static_cast< bool >( lhs < rhs ) && !static_cast< bool >( rhs < lhs ); + } + }; + + template< typename T, typename U = T > + class partially_ordered + { + friend bool operator<=( const T& lhs, const U& rhs ) + noexcept( noexcept( static_cast< bool >( lhs < rhs ), static_cast< bool >( lhs == rhs ) ) ) + { + return static_cast< bool >( lhs < rhs ) || static_cast< bool >( lhs == rhs ); + } + + friend bool operator>=( const T& lhs, const U& rhs ) + noexcept( noexcept( static_cast< bool >( lhs > rhs ), static_cast< bool >( lhs == rhs ) ) ) + { + return static_cast< bool >( lhs > rhs ) || static_cast< bool >( lhs == rhs ); + } + + friend bool operator<( const U& lhs, const T& rhs ) + noexcept( noexcept( static_cast< bool >( rhs > lhs ) ) ) + { + return static_cast< bool >( rhs > lhs ); + } + + friend bool operator>( const U& lhs, const T& rhs ) + noexcept( noexcept( static_cast< bool >( rhs < lhs ) ) ) + { + return static_cast< bool >( rhs < lhs ); + } + + friend bool operator<=( const U& lhs, const T& rhs ) + noexcept( noexcept( static_cast< bool >( rhs >= lhs ) ) ) + { + return static_cast< bool >( rhs >= lhs ); + } + + friend bool operator>=( const U& lhs, const T& rhs ) + noexcept( noexcept( static_cast< bool >( rhs <= lhs ) ) ) + { + return static_cast< bool >( rhs <= lhs ); + } + }; + + template< typename T > + class partially_ordered< T > + { + friend bool operator>( const T& lhs, const T& rhs ) + noexcept( noexcept( static_cast< bool >( rhs < lhs ) ) ) + { + return static_cast< bool >( rhs < lhs ); + } + + friend bool operator<=( const T& lhs, const T& rhs ) + noexcept( noexcept( static_cast< bool >( lhs < rhs ), static_cast< bool >( lhs == rhs ) ) ) + { + return static_cast< bool >( lhs < rhs ) || static_cast< bool >( lhs == rhs ); + } + + friend bool operator>=( const T& lhs, const T& rhs ) + noexcept( noexcept( static_cast< bool >( rhs < lhs ), static_cast< bool >( lhs == rhs ) ) ) + { + return static_cast< bool >( rhs < lhs ) || static_cast< bool >( lhs == rhs ); + } + }; + + TAOCPP_OPERATORS_BASIC_OP( addable, + ); + TAOCPP_OPERATORS_BASIC_OP_LEFT( addable, + ); + TAOCPP_OPERATORS_BASIC_OP_COMMUTATIVE( addable, + ); + + TAOCPP_OPERATORS_BASIC_OP( subtractable, - ); + TAOCPP_OPERATORS_BASIC_OP_LEFT( subtractable, - ); + + TAOCPP_OPERATORS_BASIC_OP( multipliable, * ); + TAOCPP_OPERATORS_BASIC_OP_LEFT( multipliable, * ); + TAOCPP_OPERATORS_BASIC_OP_COMMUTATIVE( multipliable, * ); + + TAOCPP_OPERATORS_BASIC_OP( dividable, / ); + TAOCPP_OPERATORS_BASIC_OP_LEFT( dividable, / ); + + TAOCPP_OPERATORS_BASIC_OP( modable, % ); + TAOCPP_OPERATORS_BASIC_OP_LEFT( modable, % ); + + template< typename T, typename U = T > + class ring + : commutative_addable< T, U >, subtractable< T, U >, subtractable_left< T, U >, multipliable< T, U > + { + }; + + template< typename T > + class ring< T > + : commutative_addable< T >, subtractable< T >, multipliable< T > + { + }; + + template< typename T, typename U = T > + class ordered_ring + : ring< T, U >, totally_ordered< T, U > + { + }; + + template< typename T, typename U = T > + class commutative_ring + : commutative_addable< T, U >, subtractable< T, U >, subtractable_left< T, U >, commutative_multipliable< T, U > + { + }; + + template< typename T > + class commutative_ring< T > + : commutative_addable< T >, subtractable< T >, commutative_multipliable< T > + { + }; + + template< typename T, typename U = T > + class ordered_commutative_ring + : commutative_ring< T, U >, totally_ordered< T, U > + { + }; + + template< typename T, typename U = T > + class field + : commutative_ring< T, U >, dividable< T, U >, dividable_left< T, U > + { + }; + + template< typename T > + class field< T > + : commutative_ring< T >, dividable< T > + { + }; + + template< typename T, typename U = T > + class ordered_field + : field< T, U >, totally_ordered< T, U > + { + }; + + TAOCPP_OPERATORS_BASIC_OP( andable, & ); + TAOCPP_OPERATORS_BASIC_OP_LEFT( andable, & ); + TAOCPP_OPERATORS_BASIC_OP_COMMUTATIVE( andable, & ); + + TAOCPP_OPERATORS_BASIC_OP( orable, | ); + TAOCPP_OPERATORS_BASIC_OP_LEFT( orable, | ); + TAOCPP_OPERATORS_BASIC_OP_COMMUTATIVE( orable, | ); + + TAOCPP_OPERATORS_BASIC_OP( xorable, ^ ); + TAOCPP_OPERATORS_BASIC_OP_LEFT( xorable, ^ ); + TAOCPP_OPERATORS_BASIC_OP_COMMUTATIVE( xorable, ^ ); + + template< typename T, typename U = T > + class bitwise + : andable< T, U >, orable< T, U >, xorable< T, U > + { + }; + + template< typename T, typename U > + class bitwise_left + : andable_left< T, U >, orable_left< T, U >, xorable_left< T, U > + { + }; + + template< typename T, typename U = T > + class commutative_bitwise + : commutative_andable< T, U >, commutative_orable< T, U >, commutative_xorable< T, U > + { + }; + + TAOCPP_OPERATORS_BASIC_OP( left_shiftable, << ); + TAOCPP_OPERATORS_BASIC_OP( right_shiftable, >> ); + + template< typename T, typename U = T > + class shiftable + : left_shiftable< T, U >, right_shiftable< T, U > + { + }; + + template< typename T > + class incrementable + { + friend T operator++( T& arg, int ) + noexcept( noexcept( T( arg ), ++arg, T( std::declval< T >() ) ) ) + { + const T nrv( arg ); + ++arg; + return nrv; + } + }; + + template< typename T > + class decrementable + { + friend T operator--( T& arg, int ) + noexcept( noexcept( T( arg ), --arg, T( std::declval< T >() ) ) ) + { + const T nrv( arg ); + --arg; + return nrv; + } + }; + + template< typename T > + class unit_steppable + : incrementable< T >, decrementable< T > + { + }; + } +} + +#undef TAOCPP_OPERATORS_BASIC_OP +#undef TAOCPP_OPERATORS_BASIC_OP_LEFT +#undef TAOCPP_OPERATORS_BASIC_OP_COMMUTATIVE + +#endif diff --git a/include/tao/json/external/optional.hpp b/include/tao/json/external/optional.hpp new file mode 100644 index 00000000..c947c5ae --- /dev/null +++ b/include/tao/json/external/optional.hpp @@ -0,0 +1,46 @@ +// The Art of C++ +// Copyright (c) 2016-2017 Daniel Frey + +#ifndef TAOCPP_INCLUDE_OPTIONAL_HPP +#define TAOCPP_INCLUDE_OPTIONAL_HPP + +#ifndef TAOCPP_USE_STD_OPTIONAL +#if __cplusplus >= 201703L +#define TAOCPP_USE_STD_OPTIONAL +#endif +#endif + +#ifndef TAOCPP_USE_STD_OPTIONAL +#ifndef TAOCPP_USE_TS_OPTIONAL +#if( __cplusplus >= 201402L ) && ( ( __GNUC__ > 4 ) || ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 9 ) ) +#define TAOCPP_USE_TS_OPTIONAL +#endif +#endif +#endif + +#if defined( TAOCPP_USE_STD_OPTIONAL ) +#include +#elif defined( TAOCPP_USE_TS_OPTIONAL ) +#include +#else +#include "akrzemi1/optional.hpp" +#endif + +namespace tao +{ + +#if defined( TAOCPP_USE_STD_OPTIONAL ) + using std::optional; + using std::nullopt; + using std::in_place; + using std::make_optional; +#else + using std::experimental::optional; + using std::experimental::nullopt; + using std::experimental::in_place; + using std::experimental::make_optional; +#endif + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl.hpp b/include/tao/json/external/pegtl.hpp new file mode 100644 index 00000000..2855db08 --- /dev/null +++ b/include/tao/json/external/pegtl.hpp @@ -0,0 +1,31 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_PEGTL_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_PEGTL_HPP + +#include "pegtl/config.hpp" +#include "pegtl/version.hpp" + +#include "pegtl/ascii.hpp" +#include "pegtl/parse.hpp" +#include "pegtl/rules.hpp" +#include "pegtl/utf16.hpp" +#include "pegtl/utf32.hpp" +#include "pegtl/utf8.hpp" + +#include "pegtl/argv_input.hpp" +#include "pegtl/buffer_input.hpp" +#include "pegtl/cstream_input.hpp" +#include "pegtl/file_input.hpp" +#include "pegtl/istream_input.hpp" +#include "pegtl/memory_input.hpp" +#include "pegtl/read_input.hpp" +#include "pegtl/string_input.hpp" + +// The following are not included by +// default because they include . + +// #include "pegtl/analyze.hpp" + +#endif diff --git a/include/tao/json/external/pegtl/analysis/analyze_cycles.hpp b/include/tao/json/external/pegtl/analysis/analyze_cycles.hpp new file mode 100644 index 00000000..78c252e5 --- /dev/null +++ b/include/tao/json/external/pegtl/analysis/analyze_cycles.hpp @@ -0,0 +1,134 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_ANALYZE_CYCLES_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_ANALYZE_CYCLES_HPP + +#include + +#include +#include + +#include +#include + +#include "../config.hpp" + +#include "grammar_info.hpp" +#include "insert_guard.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace analysis + { + class analyze_cycles_impl + { + protected: + explicit analyze_cycles_impl( const bool verbose ) noexcept + : m_verbose( verbose ), + m_problems( 0 ) + { + } + + const bool m_verbose; + unsigned m_problems; + grammar_info m_info; + std::set< std::string > m_stack; + std::map< std::string, bool > m_cache; + std::map< std::string, bool > m_results; + + const std::map< std::string, rule_info >::const_iterator find( const std::string& name ) const noexcept + { + const auto iter = m_info.map.find( name ); + assert( iter != m_info.map.end() ); + return iter; + } + + bool work( const std::map< std::string, rule_info >::const_iterator& start, const bool accum ) + { + const auto j = m_cache.find( start->first ); + + if( j != m_cache.end() ) { + return j->second; + } + if( const auto g = make_insert_guard( m_stack, start->first ) ) { + switch( start->second.type ) { + case rule_type::ANY: { + bool a = false; + for( const auto& r : start->second.rules ) { + a = a || work( find( r ), accum || a ); + } + return m_cache[ start->first ] = true; + } + case rule_type::OPT: { + bool a = false; + for( const auto& r : start->second.rules ) { + a = a || work( find( r ), accum || a ); + } + return m_cache[ start->first ] = false; + } + case rule_type::SEQ: { + bool a = false; + for( const auto& r : start->second.rules ) { + a = a || work( find( r ), accum || a ); + } + return m_cache[ start->first ] = a; + } + case rule_type::SOR: { + bool a = true; + for( const auto& r : start->second.rules ) { + a = a && work( find( r ), accum ); + } + return m_cache[ start->first ] = a; + } + } + throw std::runtime_error( "code should be unreachable" ); // LCOV_EXCL_LINE + } + if( !accum ) { + ++m_problems; + if( m_verbose ) { + std::cout << "problem: cycle without progress detected at rule class " << start->first << std::endl; // LCOV_EXCL_LINE + } + } + return m_cache[ start->first ] = accum; + } + }; + + template< typename Grammar > + class analyze_cycles + : private analyze_cycles_impl + { + public: + explicit analyze_cycles( const bool verbose ) + : analyze_cycles_impl( verbose ) + { + Grammar::analyze_t::template insert< Grammar >( m_info ); + } + + std::size_t problems() + { + for( auto i = m_info.map.begin(); i != m_info.map.end(); ++i ) { + m_results[ i->first ] = work( i, false ); + m_cache.clear(); + } + return m_problems; + } + + template< typename Rule > + bool consumes() const noexcept + { + const auto i = m_results.find( internal::demangle< Rule >() ); + assert( i != m_results.end() ); + return i->second; + } + }; + + } // namespace analysis + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/analysis/counted.hpp b/include/tao/json/external/pegtl/analysis/counted.hpp new file mode 100644 index 00000000..f04673ea --- /dev/null +++ b/include/tao/json/external/pegtl/analysis/counted.hpp @@ -0,0 +1,29 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_COUNTED_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_COUNTED_HPP + +#include "../config.hpp" + +#include "generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace analysis + { + template< rule_type Type, unsigned Count, typename... Rules > + struct counted + : generic< ( Count != 0 ) ? Type : rule_type::OPT, Rules... > + { + }; + + } // namespace analysis + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/analysis/generic.hpp b/include/tao/json/external/pegtl/analysis/generic.hpp new file mode 100644 index 00000000..e2ebef50 --- /dev/null +++ b/include/tao/json/external/pegtl/analysis/generic.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_GENERIC_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_GENERIC_HPP + +#include "../config.hpp" + +#include "grammar_info.hpp" +#include "insert_rules.hpp" +#include "rule_type.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace analysis + { + template< rule_type Type, typename... Rules > + struct generic + { + template< typename Name > + static std::string insert( grammar_info& g ) + { + const auto r = g.insert< Name >( Type ); + if( r.second ) { + insert_rules< Rules... >::insert( g, r.first->second ); + } + return r.first->first; + } + }; + + } // namespace analysis + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/analysis/grammar_info.hpp b/include/tao/json/external/pegtl/analysis/grammar_info.hpp new file mode 100644 index 00000000..6ca96f47 --- /dev/null +++ b/include/tao/json/external/pegtl/analysis/grammar_info.hpp @@ -0,0 +1,40 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_GRAMMAR_INFO_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_GRAMMAR_INFO_HPP + +#include +#include +#include + +#include "../config.hpp" +#include "../internal/demangle.hpp" + +#include "rule_info.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace analysis + { + struct grammar_info + { + using map_t = std::map< std::string, rule_info >; + map_t map; + + template< typename Name > + std::pair< map_t::iterator, bool > insert( const rule_type type ) + { + return map.insert( map_t::value_type( internal::demangle< Name >(), rule_info( type ) ) ); + } + }; + + } // namespace analysis + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/analysis/insert_guard.hpp b/include/tao/json/external/pegtl/analysis/insert_guard.hpp new file mode 100644 index 00000000..4b558412 --- /dev/null +++ b/include/tao/json/external/pegtl/analysis/insert_guard.hpp @@ -0,0 +1,66 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_INSERT_GUARD_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_INSERT_GUARD_HPP + +#include + +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace analysis + { + template< typename C > + class insert_guard + { + public: + insert_guard( insert_guard&& other ) noexcept + : m_i( other.m_i ), + m_c( other.m_c ) + { + other.m_c = nullptr; + } + + insert_guard( C& container, const typename C::value_type& value ) + : m_i( container.insert( value ) ), + m_c( &container ) + { + } + + ~insert_guard() + { + if( m_c && m_i.second ) { + m_c->erase( m_i.first ); + } + } + + insert_guard( const insert_guard& ) = delete; + void operator=( const insert_guard& ) = delete; + + explicit operator bool() const noexcept + { + return m_i.second; + } + + private: + const std::pair< typename C::iterator, bool > m_i; + C* m_c; + }; + + template< typename C > + insert_guard< C > make_insert_guard( C& container, const typename C::value_type& value ) + { + return insert_guard< C >( container, value ); + } + + } // namespace analysis + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/analysis/insert_rules.hpp b/include/tao/json/external/pegtl/analysis/insert_rules.hpp new file mode 100644 index 00000000..f8be0728 --- /dev/null +++ b/include/tao/json/external/pegtl/analysis/insert_rules.hpp @@ -0,0 +1,45 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_INSERT_RULES_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_INSERT_RULES_HPP + +#include "../config.hpp" + +#include "grammar_info.hpp" +#include "rule_info.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace analysis + { + template< typename... > + struct insert_rules; + + template<> + struct insert_rules<> + { + static void insert( grammar_info&, rule_info& ) + { + } + }; + + template< typename Rule, typename... Rules > + struct insert_rules< Rule, Rules... > + { + static void insert( grammar_info& g, rule_info& r ) + { + r.rules.push_back( Rule::analyze_t::template insert< Rule >( g ) ); + insert_rules< Rules... >::insert( g, r ); + } + }; + + } // namespace analysis + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/analysis/rule_info.hpp b/include/tao/json/external/pegtl/analysis/rule_info.hpp new file mode 100644 index 00000000..3bff9b66 --- /dev/null +++ b/include/tao/json/external/pegtl/analysis/rule_info.hpp @@ -0,0 +1,37 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_RULE_INFO_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_RULE_INFO_HPP + +#include +#include + +#include "../config.hpp" + +#include "rule_type.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace analysis + { + struct rule_info + { + explicit rule_info( const rule_type in_type ) + : type( in_type ) + { + } + + rule_type type; + std::vector< std::string > rules; + }; + + } // namespace analysis + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/analysis/rule_type.hpp b/include/tao/json/external/pegtl/analysis/rule_type.hpp new file mode 100644 index 00000000..78efe4ca --- /dev/null +++ b/include/tao/json/external/pegtl/analysis/rule_type.hpp @@ -0,0 +1,29 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_RULE_TYPE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_RULE_TYPE_HPP + +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace analysis + { + enum class rule_type : char + { + ANY, // Consumption-on-success is always true; assumes bounded repetition of conjunction of sub-rules. + OPT, // Consumption-on-success not necessarily true; assumes bounded repetition of conjunction of sub-rules. + SEQ, // Consumption-on-success depends on consumption of (non-zero bounded repetition of) conjunction of sub-rules. + SOR // Consumption-on-success depends on consumption of (non-zero bounded repetition of) disjunction of sub-rules. + }; + + } // namespace analysis + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/analyze.hpp b/include/tao/json/external/pegtl/analyze.hpp new file mode 100644 index 00000000..4b30e0ca --- /dev/null +++ b/include/tao/json/external/pegtl/analyze.hpp @@ -0,0 +1,25 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ANALYZE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_ANALYZE_HPP + +#include "config.hpp" + +#include "analysis/analyze_cycles.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + template< typename Rule > + std::size_t analyze( const bool verbose = true ) + { + return analysis::analyze_cycles< Rule >( verbose ).problems(); + } + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/apply_mode.hpp b/include/tao/json/external/pegtl/apply_mode.hpp new file mode 100644 index 00000000..a496b0a5 --- /dev/null +++ b/include/tao/json/external/pegtl/apply_mode.hpp @@ -0,0 +1,23 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_APPLY_MODE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_APPLY_MODE_HPP + +#include "config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + enum class apply_mode : bool + { + ACTION = true, + NOTHING = false + }; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/argv_input.hpp b/include/tao/json/external/pegtl/argv_input.hpp new file mode 100644 index 00000000..ea1fe271 --- /dev/null +++ b/include/tao/json/external/pegtl/argv_input.hpp @@ -0,0 +1,52 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ARGV_INPUT_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_ARGV_INPUT_HPP + +#include +#include +#include +#include + +#include "config.hpp" +#include "eol.hpp" +#include "memory_input.hpp" +#include "tracking_mode.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + inline std::string make_argv_source( const std::size_t argn ) + { + std::ostringstream os; + os << "argv[" << argn << ']'; + return os.str(); + } + + } // namespace internal + + template< tracking_mode P = tracking_mode::IMMEDIATE, typename Eol = eol::lf_crlf > + struct argv_input + : public memory_input< P, Eol > + { + template< typename T > + argv_input( char** argv, const std::size_t argn, T&& in_source ) + : memory_input< P, Eol >( static_cast< const char* >( argv[ argn ] ), std::forward< T >( in_source ) ) + { + } + + argv_input( char** argv, const std::size_t argn ) + : argv_input( argv, argn, internal::make_argv_source( argn ) ) + { + } + }; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/ascii.hpp b/include/tao/json/external/pegtl/ascii.hpp new file mode 100644 index 00000000..ed7f194a --- /dev/null +++ b/include/tao/json/external/pegtl/ascii.hpp @@ -0,0 +1,67 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ASCII_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_ASCII_HPP + +#include "config.hpp" +#include "eol.hpp" + +#include "internal/result_on_found.hpp" +#include "internal/rules.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + inline namespace ascii + { + // clang-format off + struct alnum : internal::alnum {}; + struct alpha : internal::alpha {}; + struct any : internal::any< internal::peek_char > {}; + struct blank : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, ' ', '\t' > {}; + struct digit : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, '0', '9' > {}; + struct eolf : internal::eolf {}; + struct identifier_first : internal::identifier_first {}; + struct identifier_other : internal::identifier_other {}; + struct identifier : internal::identifier {}; + template< char... Cs > struct istring : internal::istring< Cs... > {}; + template< char... Cs > struct keyword : internal::seq< internal::string< Cs... >, internal::not_at< internal::identifier_other > > {}; + struct lower : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, 'a', 'z' > {}; + template< char... Cs > struct not_one : internal::one< internal::result_on_found::FAILURE, internal::peek_char, Cs... > {}; + template< char Lo, char Hi > struct not_range : internal::range< internal::result_on_found::FAILURE, internal::peek_char, Lo, Hi > {}; + struct nul : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, char( 0 ) > {}; + template< char... Cs > struct one : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, Cs... > {}; + struct print : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, char( 32 ), char( 126 ) > {}; + template< char Lo, char Hi > struct range : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, Lo, Hi > {}; + template< char... Cs > struct ranges : internal::ranges< internal::peek_char, Cs... > {}; + struct seven : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, char( 0 ), char( 127 ) > {}; + struct shebang : internal::if_must< internal::string< '#', '!' >, internal::until< internal::eolf > > {}; + struct space : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, ' ', '\n', '\r', '\t', '\v', '\f' > {}; + template< char... Cs > struct string : internal::string< Cs... > {}; + template< char C > struct two : internal::string< C, C > {}; + struct upper : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, 'A', 'Z' > {}; + struct xdigit : internal::ranges< internal::peek_char, '0', '9', 'a', 'f', 'A', 'F' > {}; + // clang-format on + + template<> + struct keyword<> + { + template< typename Input > + static bool match( Input& ) noexcept + { + static_assert( sizeof( Input ) == 0, "empty keywords not allowed" ); + return false; + } + }; + + } // namespace ascii + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#include "internal/pegtl_string.hpp" + +#endif diff --git a/include/tao/json/external/pegtl/buffer_input.hpp b/include/tao/json/external/pegtl/buffer_input.hpp new file mode 100644 index 00000000..d92d22b0 --- /dev/null +++ b/include/tao/json/external/pegtl/buffer_input.hpp @@ -0,0 +1,179 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_BUFFER_INPUT_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_BUFFER_INPUT_HPP + +#include +#include +#include +#include + +#include "config.hpp" +#include "eol.hpp" +#include "memory_input.hpp" +#include "position.hpp" +#include "tracking_mode.hpp" + +#include "internal/action_input.hpp" +#include "internal/bump_impl.hpp" +#include "internal/iterator.hpp" +#include "internal/marker.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + template< typename Reader, typename Eol = eol::lf_crlf, typename Source = std::string > + class buffer_input + { + public: + static constexpr tracking_mode tracking_mode_v = tracking_mode::IMMEDIATE; + using reader_t = Reader; + + using eol_t = Eol; + using source_t = Source; + + using iterator_t = internal::iterator; + + using action_t = internal::action_input< buffer_input >; + + template< typename T, typename... As > + buffer_input( T&& in_source, const std::size_t maximum, As&&... as ) + : m_reader( std::forward< As >( as )... ), + m_maximum( maximum ), + m_buffer( new char[ maximum ] ), + m_current( m_buffer.get() ), + m_end( m_buffer.get() ), + m_source( std::forward< T >( in_source ) ) + { + } + + buffer_input( const buffer_input& ) = delete; + void operator=( const buffer_input& ) = delete; + + bool empty() + { + require( 1 ); + return m_current.data == m_end; + } + + std::size_t size( const std::size_t amount ) + { + require( amount ); + return std::size_t( m_end - m_current.data ); + } + + const char* current() const noexcept + { + return m_current.data; + } + + const char* end( const std::size_t amount ) + { + require( amount ); + return m_end; + } + + std::size_t byte() const noexcept + { + return m_current.byte; + } + + std::size_t line() const noexcept + { + return m_current.line; + } + + std::size_t byte_in_line() const noexcept + { + return m_current.byte_in_line; + } + + const Source& source() const noexcept + { + return m_source; + } + + char peek_char( const std::size_t offset = 0 ) const noexcept + { + return m_current.data[ offset ]; + } + + unsigned char peek_byte( const std::size_t offset = 0 ) const noexcept + { + return static_cast< unsigned char >( peek_char( offset ) ); + } + + void bump( const std::size_t in_count = 1 ) noexcept + { + internal::bump( m_current, in_count, Eol::ch ); + } + + void bump_in_this_line( const std::size_t in_count = 1 ) noexcept + { + internal::bump_in_this_line( m_current, in_count ); + } + + void bump_to_next_line( const std::size_t in_count = 1 ) noexcept + { + internal::bump_to_next_line( m_current, in_count ); + } + + void discard() noexcept + { + const auto s = m_end - m_current.data; + std::memmove( m_buffer.get(), m_current.data, s ); + m_current.data = m_buffer.get(); + m_end = m_buffer.get() + s; + } + + void require( const std::size_t amount ) + { + if( m_current.data + amount > m_end ) { + if( m_current.data + amount <= m_buffer.get() + m_maximum ) { + if( const auto r = m_reader( const_cast< char* >( m_end ), amount - std::size_t( m_end - m_current.data ) ) ) { + m_end += r; + } + else { + m_maximum = 0; + } + } + } + } + + template< rewind_mode M > + internal::marker< iterator_t, M > mark() noexcept + { + return internal::marker< iterator_t, M >( m_current ); + } + + TAOCPP_JSON_PEGTL_NAMESPACE::position position( const iterator_t& it ) const + { + return TAOCPP_JSON_PEGTL_NAMESPACE::position( it, m_source ); + } + + TAOCPP_JSON_PEGTL_NAMESPACE::position position() const + { + return position( m_current ); + } + + const iterator_t& iterator() const noexcept + { + return m_current; + } + + private: + Reader m_reader; + std::size_t m_maximum; + std::unique_ptr< char[] > m_buffer; + iterator_t m_current; + const char* m_end; + const Source m_source; + }; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/config.hpp b/include/tao/json/external/pegtl/config.hpp new file mode 100644 index 00000000..f2f0e4d4 --- /dev/null +++ b/include/tao/json/external/pegtl/config.hpp @@ -0,0 +1,15 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONFIG_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_CONFIG_HPP + +#ifndef TAOCPP_JSON_PEGTL_NAMESPACE +#define TAOCPP_JSON_PEGTL_NAMESPACE json_pegtl +#endif + +// Enable some improvements to the readability of +// demangled type names under some circumstances. +// #define TAOCPP_JSON_PEGTL_PRETTY_DEMANGLE + +#endif diff --git a/include/tao/json/external/pegtl/contrib/abnf.hpp b/include/tao/json/external/pegtl/contrib/abnf.hpp new file mode 100644 index 00000000..5c1d36e9 --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/abnf.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_ABNF_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_ABNF_HPP + +#include "../config.hpp" +#include "../internal/rules.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace abnf + { + // Core ABNF rules according to RFC 5234, Appendix B + + // clang-format off + struct ALPHA : internal::ranges< internal::peek_char, 'a', 'z', 'A', 'Z' > {}; + struct BIT : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, '0', '1' > {}; + struct CHAR : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, char( 1 ), char( 127 ) > {}; + struct CR : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, '\r' > {}; + struct CRLF : internal::string< '\r', '\n' > {}; + struct CTL : internal::ranges< internal::peek_char, char( 0 ), char( 31 ), char( 127 ) > {}; + struct DIGIT : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, '0', '9' > {}; + struct DQUOTE : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, '"' > {}; + struct HEXDIG : internal::ranges< internal::peek_char, '0', '9', 'a', 'f', 'A', 'F' > {}; + struct HTAB : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, '\t' > {}; + struct LF : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, '\n' > {}; + struct LWSP : internal::star< internal::sor< internal::string< '\r', '\n' >, internal::one< internal::result_on_found::SUCCESS, internal::peek_char, ' ', '\t' > >, internal::one< internal::result_on_found::SUCCESS, internal::peek_char, ' ', '\t' > > {}; + struct OCTET : internal::any< internal::peek_char > {}; + struct SP : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, ' ' > {}; + struct VCHAR : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, char( 33 ), char( 126 ) > {}; + struct WSP : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, ' ', '\t' > {}; + // clang-format on + + } // namespace abnf + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/contrib/alphabet.hpp b/include/tao/json/external/pegtl/contrib/alphabet.hpp new file mode 100644 index 00000000..738db535 --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/alphabet.hpp @@ -0,0 +1,75 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_ALPHABET_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_ALPHABET_HPP + +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + inline namespace alphabet + { + static const int a = 'a'; + static const int b = 'b'; + static const int c = 'c'; + static const int d = 'd'; + static const int e = 'e'; + static const int f = 'f'; + static const int g = 'g'; + static const int h = 'h'; + static const int i = 'i'; + static const int j = 'j'; + static const int k = 'k'; + static const int l = 'l'; + static const int m = 'm'; + static const int n = 'n'; + static const int o = 'o'; + static const int p = 'p'; + static const int q = 'q'; + static const int r = 'r'; + static const int s = 's'; + static const int t = 't'; + static const int u = 'u'; + static const int v = 'v'; + static const int w = 'w'; + static const int x = 'x'; + static const int y = 'y'; + static const int z = 'z'; + + static const int A = 'A'; + static const int B = 'B'; + static const int C = 'C'; + static const int D = 'D'; + static const int E = 'E'; + static const int F = 'F'; + static const int G = 'G'; + static const int H = 'H'; + static const int I = 'I'; + static const int J = 'J'; + static const int K = 'K'; + static const int L = 'L'; + static const int M = 'M'; + static const int N = 'N'; + static const int O = 'O'; + static const int P = 'P'; + static const int Q = 'Q'; + static const int R = 'R'; + static const int S = 'S'; + static const int T = 'T'; + static const int U = 'U'; + static const int V = 'V'; + static const int W = 'W'; + static const int X = 'X'; + static const int Y = 'Y'; + static const int Z = 'Z'; + + } // namespace alphabet + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/contrib/changes.hpp b/include/tao/json/external/pegtl/contrib/changes.hpp new file mode 100644 index 00000000..24649139 --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/changes.hpp @@ -0,0 +1,86 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_CHANGES_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_CHANGES_HPP + +#include + +#include "../config.hpp" +#include "../normal.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct dummy_disabled_state + { + template< typename... Ts > + void success( Ts&&... ) const noexcept + { + } + }; + + template< apply_mode A, typename State > + using state_disable_helper = typename std::conditional< A == apply_mode::ACTION, State, dummy_disabled_state >::type; + + } // namespace internal + + template< typename Rule, typename State, template< typename... > class Base = normal > + struct change_state + : public Base< Rule > + { + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + internal::state_disable_helper< A, State > s; + + if( Base< Rule >::template match< A, M, Action, Control >( in, s ) ) { + s.success( st... ); + return true; + } + return false; + } + }; + + template< typename Rule, template< typename... > class Action, template< typename... > class Base = normal > + struct change_action + : public Base< Rule > + { + template< apply_mode A, + rewind_mode M, + template< typename... > class, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + return Base< Rule >::template match< A, M, Action, Control >( in, st... ); + } + }; + + template< template< typename... > class Action, template< typename... > class Base > + struct change_both_helper + { + template< typename T > + using change_action = change_action< T, Action, Base >; + }; + + template< typename Rule, typename State, template< typename... > class Action, template< typename... > class Base = normal > + struct change_state_and_action + : public change_state< Rule, State, change_both_helper< Action, Base >::template change_action > + { + }; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/contrib/counter.hpp b/include/tao/json/external/pegtl/contrib/counter.hpp new file mode 100644 index 00000000..6aab2746 --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/counter.hpp @@ -0,0 +1,58 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_COUNTER_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_COUNTER_HPP + +#include +#include + +#include "../config.hpp" +#include "../normal.hpp" + +#include "../internal/demangle.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + struct counter_data + { + unsigned start = 0; + unsigned success = 0; + unsigned failure = 0; + }; + + struct counter_state + { + std::map< std::string, counter_data > counts; + }; + + template< typename Rule > + struct counter + : normal< Rule > + { + template< typename Input > + static void start( const Input&, counter_state& ts ) + { + ++ts.counts[ internal::demangle< Rule >() ].start; + } + + template< typename Input > + static void success( const Input&, counter_state& ts ) + { + ++ts.counts[ internal::demangle< Rule >() ].success; + } + + template< typename Input > + static void failure( const Input&, counter_state& ts ) + { + ++ts.counts[ internal::demangle< Rule >() ].failure; + } + }; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/contrib/http.hpp b/include/tao/json/external/pegtl/contrib/http.hpp new file mode 100644 index 00000000..63268b97 --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/http.hpp @@ -0,0 +1,152 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_HTTP_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_HTTP_HPP + +#include "../ascii.hpp" +#include "../config.hpp" +#include "../rules.hpp" +#include "../utf8.hpp" +#include "abnf.hpp" +#include "uri.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace http + { + // HTTP 1.1 grammar according to RFC 7230. + + // This grammar is a direct PEG translation of the original HTTP grammar. + // It should be considered experimental -- in case of any issues, in particular + // missing rules for attached actions, please contact the developers. + + using namespace abnf; + + using OWS = star< WSP >; // optional whitespace + using RWS = plus< WSP >; // required whitespace + using BWS = OWS; // "bad" whitespace + + // cppcheck-suppress constStatement + using obs_text = not_range< 0x00, 0x7F >; + using obs_fold = seq< CRLF, plus< WSP > >; + + // clang-format off + struct tchar : sor< ALPHA, DIGIT, one< '!', '#', '$', '%', '&', '\'', '*', '+', '-', '.', '^', '_', '`', '|', '~' > > {}; + struct token : plus< tchar > {}; + + struct field_name : token {}; + + struct field_vchar : sor< VCHAR, obs_text > {}; + struct field_content : list< field_vchar, plus< WSP > > {}; + struct field_value : star< sor< field_content, obs_fold > > {}; + + struct header_field : seq< field_name, one< ':' >, OWS, field_value, OWS > {}; + + struct method : token {}; + + struct absolute_path : plus< one< '/' >, uri::segment > {}; + + struct origin_form : seq< absolute_path, uri::opt_query > {}; + struct absolute_form : uri::absolute_URI {}; + struct authority_form : uri::authority {}; + struct asterisk_form : one< '*' > {}; + + struct request_target : sor< origin_form, absolute_form, authority_form, asterisk_form > {}; + + struct status_code : rep< 3, DIGIT > {}; + struct reason_phrase : star< sor< VCHAR, obs_text, WSP > > {}; + + struct HTTP_version : if_must< TAOCPP_JSON_PEGTL_STRING( "HTTP/" ), DIGIT, one< '.' >, DIGIT > {}; + + struct request_line : if_must< method, SP, request_target, SP, HTTP_version, CRLF > {}; + struct status_line : if_must< HTTP_version, SP, status_code, SP, reason_phrase, CRLF > {}; + struct start_line : sor< status_line, request_line > {}; + + struct message_body : star< OCTET > {}; + struct HTTP_message : seq< start_line, star< header_field, CRLF >, CRLF, opt< message_body > > {}; + + struct Content_Length : plus< DIGIT > {}; + + struct uri_host : uri::host {}; + struct port : uri::port {}; + + struct Host : seq< uri_host, opt< one< ':' >, port > > {}; + + // PEG are different from CFGs! (this replaces ctext and qdtext) + using text = sor< HTAB, range< 0x20, 0x7E >, obs_text >; + + struct quoted_pair : if_must< one< '\\' >, sor< VCHAR, obs_text, WSP > > {}; + struct quoted_string : if_must< DQUOTE, until< DQUOTE, sor< quoted_pair, text > > > {}; + + struct transfer_parameter : seq< token, BWS, one< '=' >, BWS, sor< token, quoted_string > > {}; + struct transfer_extension : seq< token, star< OWS, one< ';' >, OWS, transfer_parameter > > {}; + struct transfer_coding : sor< TAOCPP_JSON_PEGTL_ISTRING( "chunked" ), + TAOCPP_JSON_PEGTL_ISTRING( "compress" ), + TAOCPP_JSON_PEGTL_ISTRING( "deflate" ), + TAOCPP_JSON_PEGTL_ISTRING( "gzip" ), + transfer_extension > {}; + + struct rank : sor< seq< one< '0' >, opt< one< '.' >, rep_opt< 3, DIGIT > > >, + seq< one< '1' >, opt< one< '.' >, rep_opt< 3, one< '0' > > > > > {}; + + struct t_ranking : seq< OWS, one< ';' >, OWS, one< 'q', 'Q' >, one< '=' >, rank > {}; + struct t_codings : sor< TAOCPP_JSON_PEGTL_ISTRING( "trailers" ), seq< transfer_coding, opt< t_ranking > > > {}; + + struct TE : opt< sor< one< ',' >, t_codings >, star< OWS, one< ',' >, opt< OWS, t_codings > > > {}; + + template< typename T > + using make_comma_list = seq< star< one< ',' >, OWS >, T, star< OWS, one< ',' >, opt< OWS, T > > >; + + struct connection_option : token {}; + struct Connection : make_comma_list< connection_option > {}; + + struct Trailer : make_comma_list< field_name > {}; + + struct Transfer_Encoding : make_comma_list< transfer_coding > {}; + + struct protocol_name : token {}; + struct protocol_version : token {}; + struct protocol : seq< protocol_name, opt< one< '/' >, protocol_version > > {}; + struct Upgrade : make_comma_list< protocol > {}; + + struct pseudonym : token {}; + + struct received_protocol : seq< opt< protocol_name, one< '/' > >, protocol_version > {}; + struct received_by : sor< seq< uri_host, opt< one< ':' >, port > >, pseudonym > {}; + + struct comment : if_must< one< '(' >, until< one< ')' >, sor< comment, quoted_pair, text > > > {}; + + struct Via : make_comma_list< seq< received_protocol, RWS, received_by, opt< RWS, comment > > > {}; + + struct http_URI : if_must< TAOCPP_JSON_PEGTL_ISTRING( "http://" ), uri::authority, uri::path_abempty, uri::opt_query, uri::opt_fragment > {}; + struct https_URI : if_must< TAOCPP_JSON_PEGTL_ISTRING( "https://" ), uri::authority, uri::path_abempty, uri::opt_query, uri::opt_fragment > {}; + + struct partial_URI : seq< uri::relative_part, uri::opt_query > {}; + + struct chunk_size : plus< HEXDIG > {}; + + struct chunk_ext_name : token {}; + struct chunk_ext_val : sor< quoted_string, token > {}; + struct chunk_ext : star< if_must< one< ';' >, chunk_ext_name, if_must< one< '=' >, chunk_ext_val > > > {}; + + struct chunk_data : until< at< CRLF >, OCTET > {}; + + struct chunk : seq< chunk_size, opt< chunk_ext >, CRLF, chunk_data, CRLF > {}; + + struct last_chunk : seq< plus< one< '0' > >, opt< chunk_ext >, CRLF > {}; + + struct trailer_part : star< header_field, CRLF > {}; + + struct chunked_body : seq< until< last_chunk, chunk >, trailer_part, CRLF > {}; + // clang-format on + + } // namespace http + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/contrib/json.hpp b/include/tao/json/external/pegtl/contrib/json.hpp new file mode 100644 index 00000000..352c3f70 --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/json.hpp @@ -0,0 +1,98 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_JSON_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_JSON_HPP + +#include "../ascii.hpp" +#include "../config.hpp" +#include "../rules.hpp" +#include "../utf8.hpp" + +#include "abnf.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace json + { + // JSON grammar according to RFC 7159 (for UTF-8 encoded JSON only). + + // clang-format off + struct ws : one< ' ', '\t', '\n', '\r' > {}; + + template< typename R, typename P = ws > + struct padr : internal::seq< R, internal::star< P > > {}; + + struct begin_array : padr< one< '[' > > {}; + struct begin_object : padr< one< '{' > > {}; + struct end_array : one< ']' > {}; + struct end_object : one< '}' > {}; + struct name_separator : pad< one< ':' >, ws > {}; + struct value_separator : padr< one< ',' > > {}; + + struct false_ : TAOCPP_JSON_PEGTL_STRING( "false" ) {}; + struct null : TAOCPP_JSON_PEGTL_STRING( "null" ) {}; + struct true_ : TAOCPP_JSON_PEGTL_STRING( "true" ) {}; + + struct digits : plus< abnf::DIGIT > {}; + struct exp : seq< one< 'e', 'E' >, opt< one< '-', '+'> >, must< digits > > {}; + struct frac : if_must< one< '.' >, digits > {}; + struct int_ : sor< one< '0' >, digits > {}; + struct number : seq< opt< one< '-' > >, int_, opt< frac >, opt< exp > > {}; + + struct xdigit : abnf::HEXDIG {}; + struct unicode : list< seq< one< 'u' >, rep< 4, must< xdigit > > >, one< '\\' > > {}; + struct escaped_char : one< '"', '\\', '/', 'b', 'f', 'n', 'r', 't' > {}; + struct escaped : sor< escaped_char, unicode > {}; + struct unescaped : utf8::range< 0x20, 0x10FFFF > {}; + struct char_ : if_then_else< one< '\\' >, must< escaped >, unescaped > {}; + + struct string_content : until< at< one< '"' > >, must< char_ > > {}; + struct string : seq< one< '"' >, must< string_content >, any > + { + using content = string_content; + }; + + struct key_content : until< at< one< '"' > >, must< char_ > > {}; + struct key : seq< one< '"' >, must< key_content >, any > + { + using content = key_content; + }; + + struct value; + + struct array_element; + struct array_content : opt< list_must< array_element, value_separator > > {}; + struct array : seq< begin_array, array_content, must< end_array > > + { + using begin = begin_array; + using end = end_array; + using element = array_element; + using content = array_content; + }; + + struct member : if_must< key, name_separator, value > {}; + struct object_content : opt< list_must< member, value_separator > > {}; + struct object : seq< begin_object, object_content, must< end_object > > + { + using begin = begin_object; + using end = end_object; + using element = member; + using content = object_content; + }; + + struct value : padr< sor< string, number, object, array, false_, true_, null > > {}; + struct array_element : seq< value > {}; + + struct text : seq< star< ws >, value > {}; + // clang-format on + + } // namespace json + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/contrib/parse_tree.hpp b/include/tao/json/external/pegtl/contrib/parse_tree.hpp new file mode 100644 index 00000000..ac654852 --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/parse_tree.hpp @@ -0,0 +1,183 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_PARSE_TREE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_PARSE_TREE_HPP + +#include +#include +#include +#include +#include + +#include "../config.hpp" +#include "../normal.hpp" + +#include "../internal/iterator.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace parse_tree + { + struct node + { + std::vector< std::unique_ptr< node > > children; + const std::type_info* id = nullptr; + internal::iterator begin; + internal::iterator end; + }; + + class state + { + private: + std::vector< std::unique_ptr< node > > stack; + + public: + state() + { + emplace_back(); + } + + const node& root() const noexcept + { + return *stack.front(); + } + + std::unique_ptr< node >& back() noexcept + { + return stack.back(); + } + + void pop_back() noexcept + { + return stack.pop_back(); + } + + void emplace_back() + { + stack.emplace_back( std::unique_ptr< node >( new node ) ); + } + }; + + } // namespace parse_tree + + namespace internal + { + template< template< typename > class S, template< typename > class C > + struct parse_tree + { + template< typename Rule, bool = S< Rule >::value, bool = C< Rule >::value > + struct builder; + }; + + template< template< typename > class S, template< typename > class C > + template< typename Rule > + struct parse_tree< S, C >::builder< Rule, false, false > + : normal< Rule > + { + }; + + template< template< typename > class S, template< typename > class C > + template< typename Rule > + struct parse_tree< S, C >::builder< Rule, true, true > + : normal< Rule > + { + static_assert( sizeof( Rule ) == 0, "error: both S::value and C::value are true" ); + }; + + template< template< typename > class S, template< typename > class C > + template< typename Rule > + struct parse_tree< S, C >::builder< Rule, true, false > + : normal< Rule > + { + template< typename Input > + static void start( const Input& in, TAOCPP_JSON_PEGTL_NAMESPACE::parse_tree::state& s ) + { + s.emplace_back(); + s.back()->begin = in.iterator(); + } + + template< typename Input > + static void success( const Input&, TAOCPP_JSON_PEGTL_NAMESPACE::parse_tree::state& s ) + { + auto n = std::move( s.back() ); + n->id = &typeid( Rule ); + s.pop_back(); + s.back()->children.emplace_back( std::move( n ) ); + } + + template< typename Input > + static void failure( const Input&, TAOCPP_JSON_PEGTL_NAMESPACE::parse_tree::state& s ) + { + s.pop_back(); + } + }; + + template< template< typename > class S, template< typename > class C > + template< typename Rule > + struct parse_tree< S, C >::builder< Rule, false, true > + : normal< Rule > + { + template< typename Input > + static void start( const Input& in, TAOCPP_JSON_PEGTL_NAMESPACE::parse_tree::state& s ) + { + s.emplace_back(); + s.back()->begin = in.iterator(); + } + + template< typename Input > + static void success( const Input& in, TAOCPP_JSON_PEGTL_NAMESPACE::parse_tree::state& s ) + { + auto n = std::move( s.back() ); + n->id = &typeid( Rule ); + n->end = in.iterator(); + s.pop_back(); + s.back()->children.emplace_back( std::move( n ) ); + } + + template< typename Input > + static void failure( const Input&, TAOCPP_JSON_PEGTL_NAMESPACE::parse_tree::state& s ) + { + s.pop_back(); + } + }; + + template< typename > + struct default_store_simple : std::false_type + { + }; + + template< typename > + struct default_store_content : std::true_type + { + }; + + } // namespace internal + + namespace parse_tree + { + template< typename Rule > + struct builder + : internal::parse_tree< internal::default_store_simple, internal::default_store_content >::builder< Rule > + { + }; + + template< template< typename > class S, template< typename > class C > + struct make_builder + { + template< typename Rule > + struct type + : internal::parse_tree< S, C >::template builder< Rule > + { + }; + }; + + } // namespace parse_tree + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/contrib/raw_string.hpp b/include/tao/json/external/pegtl/contrib/raw_string.hpp new file mode 100644 index 00000000..842f7d91 --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/raw_string.hpp @@ -0,0 +1,247 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_RAW_STRING_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_RAW_STRING_HPP + +#include "../apply_mode.hpp" +#include "../config.hpp" +#include "../nothing.hpp" +#include "../rewind_mode.hpp" + +#include "../internal/iterator.hpp" +#include "../internal/must.hpp" +#include "../internal/skip_control.hpp" +#include "../internal/state.hpp" +#include "../internal/until.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< char Open, char Marker, char Close, typename... Contents > + struct raw_string_tag; + + template< bool use_apply_void, bool use_apply0_void, typename Tag > + struct raw_string_state_apply; + + template< typename Tag > + struct raw_string_state_apply< false, false, Tag > + { + template< template< typename... > class, + template< typename... > class, + typename State, + typename Input, + typename... States > + static void success( const State&, const Input&, States&&... ) + { + } + }; + + template< typename Tag > + struct raw_string_state_apply< true, false, Tag > + { + template< template< typename... > class Action, + template< typename... > class Control, + typename State, + typename Input, + typename... States > + static void success( const State& s, const Input& in, States&&... st ) + { + Control< Tag >::template apply< Action >( s.iter, in, st... ); + } + }; + + template< typename Tag > + struct raw_string_state_apply< false, true, Tag > + { + template< template< typename... > class Action, + template< typename... > class Control, + typename State, + typename Input, + typename... States > + static void success( const State&, const Input& in, States&&... st ) + { + Control< Tag >::template apply0< Action >( in, st... ); + } + }; + + template< typename Tag, typename Iterator > + struct raw_string_state + { + template< typename Input, typename... States > + raw_string_state( const Input&, States&&... ) + { + } + + template< apply_mode A, + rewind_mode, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + void success( Input& in, States&&... st ) const + { + constexpr char use_action = ( A == apply_mode::ACTION ) && ( !is_nothing< Action, Tag >::value ); + constexpr char use_apply_void = use_action && internal::has_apply< Action< Tag >, void, typename Input::action_t, States... >::value; + constexpr char use_apply_bool = use_action && internal::has_apply< Action< Tag >, bool, typename Input::action_t, States... >::value; + constexpr char use_apply0_void = use_action && internal::has_apply0< Action< Tag >, void, States... >::value; + constexpr char use_apply0_bool = use_action && internal::has_apply0< Action< Tag >, bool, States... >::value; + static_assert( use_apply_void + use_apply_bool + use_apply0_void + use_apply0_bool < 2, "more than one apply or apply0 defined" ); + static_assert( !use_action || use_apply_bool || use_apply_void || use_apply0_bool || use_apply0_void, "actions not disabled but no apply or apply0 found" ); + static_assert( use_apply_bool + use_apply0_bool == 0, "actions with bool result not supported in raw_string" ); + raw_string_state_apply< use_apply_void, use_apply0_void, Tag >::template success< Action, Control >( *this, in, st... ); + in.bump_in_this_line( marker_size ); + } + + raw_string_state( const raw_string_state& ) = delete; + void operator=( const raw_string_state& ) = delete; + + Iterator iter; + std::size_t marker_size = 0; + }; + + template< char Open, char Marker > + struct raw_string_open + { + using analyze_t = analysis::generic< analysis::rule_type::ANY >; + + template< apply_mode A, + rewind_mode, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename State > + static bool match( Input& in, State& ls ) + { + if( in.empty() || ( in.peek_char( 0 ) != Open ) ) { + return false; + } + for( std::size_t i = 1; i < in.size( i + 1 ); ++i ) { + switch( const auto c = in.peek_char( i ) ) { + case Open: + ls.marker_size = i + 1; + in.bump( ls.marker_size ); + eol::match( in ); + ls.iter = in.iterator(); + return true; + case Marker: + break; + default: + return false; + } + } + return false; + } + }; + + template< char Open, char Marker > + struct skip_control< raw_string_open< Open, Marker > > : std::true_type + { + }; + + template< char Marker, char Close > + struct at_raw_string_close + { + using analyze_t = analysis::generic< analysis::rule_type::ANY >; + + template< apply_mode A, + rewind_mode, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename State > + static bool match( Input& in, const State& ls ) + { + if( in.size( ls.marker_size ) < ls.marker_size ) { + return false; + } + if( in.peek_char( 0 ) != Close ) { + return false; + } + if( in.peek_char( ls.marker_size - 1 ) != Close ) { + return false; + } + for( std::size_t i = 0; i < ls.marker_size - 2; ++i ) { + if( in.peek_char( i + 1 ) != Marker ) { + return false; + } + } + return true; + } + }; + + template< char Marker, char Close > + struct skip_control< at_raw_string_close< Marker, Close > > : std::true_type + { + }; + + } // namespace internal + + // raw_string matches Lua-style long literals. + // + // The following description was taken from the Lua documentation + // (see http://www.lua.org/docs.html): + // + // - An "opening long bracket of level n" is defined as an opening square + // bracket followed by n equal signs followed by another opening square + // bracket. So, an opening long bracket of level 0 is written as `[[`, + // an opening long bracket of level 1 is written as `[=[`, and so on. + // - A "closing long bracket" is defined similarly; for instance, a closing + // long bracket of level 4 is written as `]====]`. + // - A "long literal" starts with an opening long bracket of any level and + // ends at the first closing long bracket of the same level. It can + // contain any text except a closing bracket of the same level. + // - Literals in this bracketed form can run for several lines, do not + // interpret any escape sequences, and ignore long brackets of any other + // level. + // - For convenience, when the opening long bracket is immediately followed + // by a newline, the newline is not included in the string. + // + // Note that unlike Lua's long literal, a raw_string is customizable to use + // other characters than `[`, `=` and `]` for matching. Also note that Lua + // introduced newline-specific replacements in Lua 5.2, which we do not + // support on the grammar level. + + template< char Open, char Marker, char Close, typename... Contents > + struct raw_string + { + // This is used as a tag to bind an action to the content. + using content = internal::raw_string_tag< Open, Marker, Close, Contents... >; + + // This is used internally. + using open = internal::raw_string_open< Open, Marker >; + + // This is used for error-reporting when a raw string is not closed properly. + using close = internal::until< internal::at_raw_string_close< Marker, Close >, Contents... >; + + using analyze_t = analysis::generic< analysis::rule_type::SEQ, open, internal::must< close > >; + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + using Iterator = typename Input::iterator_t; + internal::raw_string_state< content, Iterator > s( const_cast< const Input& >( in ), st... ); + + if( Control< internal::seq< open, internal::must< close > > >::template match< A, M, Action, Control >( in, s ) ) { + s.template success< A, M, Action, Control >( in, st... ); + return true; + } + return false; + } + }; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/contrib/rep_one_min_max.hpp b/include/tao/json/external/pegtl/contrib/rep_one_min_max.hpp new file mode 100644 index 00000000..a88d66ea --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/rep_one_min_max.hpp @@ -0,0 +1,72 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_REP_ONE_MIN_MAX_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_REP_ONE_MIN_MAX_HPP + +#include + +#include "../config.hpp" + +#include "../analysis/counted.hpp" + +#include "../internal/bump_help.hpp" +#include "../internal/skip_control.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< unsigned Min, unsigned Max, char C > + struct rep_one_min_max + { + using analyze_t = analysis::counted< analysis::rule_type::ANY, Min >; + + static_assert( Min <= Max, "invalid rep_one_min_max rule (maximum number of repetitions smaller than minimum)" ); + + template< typename Input > + static bool match( Input& in ) + { + const auto size = in.size( Max + 1 ); + if( size < Min ) { + return false; + } + std::size_t i = 0; + while( ( i < size ) && ( in.peek_char( i ) == C ) ) { + ++i; + } + if( ( Min <= i ) && ( i <= Max ) ) { + bump_help< result_on_found::SUCCESS, Input, char, C >( in, i ); + return true; + } + return false; + } + }; + + template< unsigned Min, unsigned Max, char C > + struct skip_control< rep_one_min_max< Min, Max, C > > : std::true_type + { + }; + + } // namespace internal + + inline namespace ascii + { + template< unsigned Min, unsigned Max, char C > + struct rep_one_min_max : internal::rep_one_min_max< Min, Max, C > + { + }; + + struct ellipsis : internal::rep_one_min_max< 3, 3, '.' > + { + }; + + } // namespace ascii + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/contrib/to_string.hpp b/include/tao/json/external/pegtl/contrib/to_string.hpp new file mode 100644 index 00000000..4472713b --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/to_string.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_TO_STRING_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_TO_STRING_HPP + +#include + +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename > + struct to_string; + + template< template< char... > class X, char... Cs > + struct to_string< X< Cs... > > + { + static std::string get() + { + const char s[] = { Cs..., 0 }; + return std::string( s, sizeof...( Cs ) ); + } + }; + + } // namespace internal + + template< typename T > + std::string to_string() + { + return internal::to_string< T >::get(); + } + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/contrib/tracer.hpp b/include/tao/json/external/pegtl/contrib/tracer.hpp new file mode 100644 index 00000000..24558470 --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/tracer.hpp @@ -0,0 +1,111 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_TRACER_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_TRACER_HPP + +#include +#include +#include +#include +#include + +#include "../config.hpp" +#include "../normal.hpp" + +#include "../internal/demangle.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + struct trace_state + { + unsigned rule = 0; + unsigned line = 0; + std::vector< unsigned > stack; + }; + + template< typename Rule > + struct tracer + : normal< Rule > + { + template< typename Input, typename... States > + static void start( const Input& in, States&&... ) + { + std::cerr << in.position() << " start " << internal::demangle< Rule >() << std::endl; + } + + template< typename Input > + static void start( const Input& in, trace_state& ts ) + { + std::cerr << std::setw( 6 ) << ++ts.line << " " << std::setw( 6 ) << ++ts.rule << " " << in.position() << " start " << internal::demangle< Rule >() << std::endl; + ts.stack.push_back( ts.rule ); + } + + template< typename Input, typename... States > + static void success( const Input& in, States&&... ) + { + std::cerr << in.position() << " success " << internal::demangle< Rule >() << std::endl; + } + + template< typename Input > + static void success( const Input& in, trace_state& ts ) + { + assert( !ts.stack.empty() ); + std::cerr << std::setw( 6 ) << ++ts.line << " " << std::setw( 6 ) << ts.stack.back() << " " << in.position() << " success " << internal::demangle< Rule >() << std::endl; + ts.stack.pop_back(); + } + + template< typename Input, typename... States > + static void failure( const Input& in, States&&... ) + { + std::cerr << in.position() << " failure " << internal::demangle< Rule >() << std::endl; + } + + template< typename Input > + static void failure( const Input& in, trace_state& ts ) + { + assert( !ts.stack.empty() ); + std::cerr << std::setw( 6 ) << ++ts.line << " " << std::setw( 6 ) << ts.stack.back() << " " << in.position() << " failure " << internal::demangle< Rule >() << std::endl; + ts.stack.pop_back(); + } + + template< template< typename... > class Action, typename Input, typename... States > + static void apply0( const Input&, States&&... st ) + { + std::cerr << "apply0 " << internal::demangle< Action< Rule > >() << std::endl; + Action< Rule >::apply0( st... ); + } + + template< template< typename... > class Action, typename Input > + static void apply0( const Input&, trace_state& ts ) + { + std::cerr << std::setw( 6 ) << ++ts.line << " " << internal::demangle< Action< Rule > >() << "::apply0()" << std::endl; + Action< Rule >::apply0( ts ); + } + + template< template< typename... > class Action, typename Iterator, typename Input, typename... States > + static void apply( const Iterator& begin, const Input& in, States&&... st ) + { + std::cerr << "apply " << internal::demangle< Action< Rule > >() << std::endl; + using action_t = typename Input::action_t; + const action_t action_input( begin, in ); + Action< Rule >::apply( action_input, st... ); + } + + template< template< typename... > class Action, typename Iterator, typename Input > + static void apply( const Iterator& begin, const Input& in, trace_state& ts ) + { + std::cerr << std::setw( 6 ) << ++ts.line << " " << internal::demangle< Action< Rule > >() << "::apply()" << std::endl; + using action_t = typename Input::action_t; + const action_t action_input( begin, in ); + Action< Rule >::apply( action_input, ts ); + } + }; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/contrib/unescape.hpp b/include/tao/json/external/pegtl/contrib/unescape.hpp new file mode 100644 index 00000000..ff86c6f3 --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/unescape.hpp @@ -0,0 +1,203 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_UNESCAPE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_UNESCAPE_HPP + +#include +#include + +#include "../ascii.hpp" +#include "../config.hpp" +#include "../parse_error.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace unescape + { + struct state + { + std::string unescaped; + }; + + // Utility functions for the unescape actions. + + inline bool utf8_append_utf32( std::string& string, const unsigned utf32 ) + { + if( utf32 <= 0x7f ) { + string += char( utf32 & 0xff ); + return true; + } + if( utf32 <= 0x7ff ) { + char tmp[] = { char( ( ( utf32 & 0x7c0 ) >> 6 ) | 0xc0 ), + char( ( ( utf32 & 0x03f ) ) | 0x80 ) }; + string.append( tmp, sizeof( tmp ) ); + return true; + } + if( utf32 <= 0xffff ) { + char tmp[] = { char( ( ( utf32 & 0xf000 ) >> 12 ) | 0xe0 ), + char( ( ( utf32 & 0x0fc0 ) >> 6 ) | 0x80 ), + char( ( ( utf32 & 0x003f ) ) | 0x80 ) }; + string.append( tmp, sizeof( tmp ) ); + return true; + } + if( utf32 <= 0x10ffff ) { + char tmp[] = { char( ( ( utf32 & 0x1c0000 ) >> 18 ) | 0xf0 ), + char( ( ( utf32 & 0x03f000 ) >> 12 ) | 0x80 ), + char( ( ( utf32 & 0x000fc0 ) >> 6 ) | 0x80 ), + char( ( ( utf32 & 0x00003f ) ) | 0x80 ) }; + string.append( tmp, sizeof( tmp ) ); + return true; + } + return false; + } + + // This function MUST only be called for characters matching tao::TAOCPP_JSON_PEGTL_NAMESPACE::ascii::xdigit! + template< typename I > + I unhex_char( const char c ) + { + switch( c ) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return I( c - '0' ); + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + return I( c - 'a' + 10 ); + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + return I( c - 'A' + 10 ); + } + throw std::runtime_error( "invalid character in unhex" ); // LCOV_EXCL_LINE + } + + template< typename I > + I unhex_string( const char* begin, const char* const end ) + { + I r = 0; + while( begin != end ) { + r <<= 4; + r += unhex_char< I >( *begin++ ); + } + return r; + } + + // Actions for common unescape situations. + + struct append_all + { + template< typename Input, typename State > + static void apply( const Input& in, State& st ) + { + st.unescaped.append( in.begin(), in.size() ); + } + }; + + // This action MUST be called for a character matching T which MUST be tao::TAOCPP_JSON_PEGTL_NAMESPACE::one< ... >. + template< typename T, char... Rs > + struct unescape_c + { + template< typename Input, typename State > + static void apply( const Input& in, State& st ) + { + assert( in.size() == 1 ); + st.unescaped += apply_one( *in.begin(), static_cast< const T* >( nullptr ) ); + } + + template< char... Qs > + static char apply_one( const char c, const one< Qs... >* ) + { + static_assert( sizeof...( Qs ) == sizeof...( Rs ), "size mismatch between escaped characters and their mappings" ); + return apply_two( c, { Qs... }, { Rs... } ); + } + + static char apply_two( const char c, const std::initializer_list< char >& q, const std::initializer_list< char >& r ) + { + for( std::size_t i = 0; i < q.size(); ++i ) { + if( *( q.begin() + i ) == c ) { + return *( r.begin() + i ); + } + } + throw std::runtime_error( "invalid character in unescape" ); // LCOV_EXCL_LINE + } + }; + + // See src/example/pegtl/unescape.cpp for why the following two actions + // skip the first input character. They also MUST be called + // with non-empty matched inputs! + + struct unescape_u + { + template< typename Input, typename State > + static void apply( const Input& in, State& st ) + { + assert( !in.empty() ); // First character MUST be present, usually 'u' or 'U'. + if( !utf8_append_utf32( st.unescaped, unhex_string< unsigned >( in.begin() + 1, in.end() ) ) ) { + throw parse_error( "invalid escaped unicode code point", in ); + } + } + }; + + struct unescape_x + { + template< typename Input, typename State > + static void apply( const Input& in, State& st ) + { + assert( !in.empty() ); // First character MUST be present, usually 'x'. + st.unescaped += unhex_string< char >( in.begin() + 1, in.end() ); + } + }; + + // The unescape_j action is similar to unescape_u, however unlike + // unescape_u it + // (a) assumes exactly 4 hexdigits per escape sequence, + // (b) accepts multiple consecutive escaped 16-bit values. + // When applied to more than one escape sequence, unescape_j + // translates UTF-16 surrogate pairs in the input into a single + // UTF-8 sequence in st.unescaped, as required for JSON by RFC 7159. + + struct unescape_j + { + template< typename Input, typename State > + static void apply( const Input& in, State& st ) + { + assert( ( ( in.size() + 1 ) % 6 ) == 0 ); // Expects multiple "\\u1234", starting with the first "u". + for( const char* b = in.begin() + 1; b < in.end(); b += 6 ) { + const auto c = unhex_string< unsigned >( b, b + 4 ); + if( ( 0xd800 <= c ) && ( c <= 0xdbff ) && ( b + 6 < in.end() ) ) { + const auto d = unhex_string< unsigned >( b + 6, b + 10 ); + if( ( 0xdc00 <= d ) && ( d <= 0xdfff ) ) { + b += 6; + utf8_append_utf32( st.unescaped, ( ( ( c & 0x03ff ) << 10 ) | ( d & 0x03ff ) ) + 0x10000 ); + continue; + } + } + utf8_append_utf32( st.unescaped, c ); + } + } + }; + + } // namespace unescape + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/contrib/uri.hpp b/include/tao/json/external/pegtl/contrib/uri.hpp new file mode 100644 index 00000000..31e1cde5 --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/uri.hpp @@ -0,0 +1,116 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_URI_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_URI_HPP + +#include "../ascii.hpp" +#include "../config.hpp" +#include "../rules.hpp" +#include "../utf8.hpp" + +#include "abnf.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace uri + { + // URI grammar according to RFC 3986. + + // This grammar is a direct PEG translation of the original URI grammar. + // It should be considered experimental -- in case of any issues, in particular + // missing rules for attached actions, please contact the developers. + + // Note that this grammar has multiple top-level rules. + + using namespace abnf; + + using dot = one< '.' >; + using colon = one< ':' >; + + // clang-format off + struct dec_octet : sor< one< '0' >, + rep_min_max< 1, 2, DIGIT >, + seq< one< '1' >, DIGIT, DIGIT >, + seq< one< '2' >, range< '0', '4' >, DIGIT >, + seq< string< '2', '5' >, range< '0', '5' > > > {}; + + struct IPv4address : seq< dec_octet, dot, dec_octet, dot, dec_octet, dot, dec_octet > {}; + + struct h16 : rep_min_max< 1, 4, HEXDIG > {}; + struct ls32 : sor< seq< h16, colon, h16 >, IPv4address > {}; + + struct dcolon : two< ':' > {}; + + struct IPv6address : sor< seq< rep< 6, h16, colon >, ls32 >, + seq< dcolon, rep< 5, h16, colon >, ls32 >, + seq< opt< h16 >, dcolon, rep< 4, h16, colon >, ls32 >, + seq< opt< h16, opt< colon, h16 > >, dcolon, rep< 3, h16, colon >, ls32 >, + seq< opt< h16, rep_opt< 2, colon, h16 > >, dcolon, rep< 2, h16, colon >, ls32 >, + seq< opt< h16, rep_opt< 3, colon, h16 > >, dcolon, h16, colon, ls32 >, + seq< opt< h16, rep_opt< 4, colon, h16 > >, dcolon, ls32 >, + seq< opt< h16, rep_opt< 5, colon, h16 > >, dcolon, h16 >, + seq< opt< h16, rep_opt< 6, colon, h16 > >, dcolon > > {}; + + struct gen_delims : one< ':', '/', '?', '#', '[', ']', '@' > {}; + struct sub_delims : one< '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=' > {}; + + struct unreserved : sor< ALPHA, DIGIT, one< '-', '.', '_', '~' > > {}; + struct reserved : sor< gen_delims, sub_delims > {}; + + struct IPvFuture : if_must< one< 'v' >, plus< HEXDIG >, dot, plus< sor< unreserved, sub_delims, colon > > > {}; + + struct IP_literal : if_must< one< '[' >, sor< IPvFuture, IPv6address >, one< ']' > > {}; + + struct pct_encoded : if_must< one< '%' >, HEXDIG, HEXDIG > {}; + struct pchar : sor< unreserved, pct_encoded, sub_delims, one< ':', '@' > > {}; + + struct query : star< sor< pchar, one< '/', '?' > > > {}; + struct fragment : star< sor< pchar, one< '/', '?' > > > {}; + + struct segment : star< pchar > {}; + struct segment_nz : plus< pchar > {}; + struct segment_nz_nc : plus< sor< unreserved, pct_encoded, sub_delims, one< '@' > > > {}; // non-zero-length segment without any colon ":" + + struct path_abempty : star< one< '/' >, segment > {}; + struct path_absolute : seq< one< '/' >, opt< segment_nz, star< one< '/' >, segment > > > {}; + struct path_noscheme : seq< segment_nz_nc, star< one< '/' >, segment > > {}; + struct path_rootless : seq< segment_nz, star< one< '/' >, segment > > {}; + struct path_empty : success {}; + + struct path : sor< path_noscheme, // begins with a non-colon segment + path_rootless, // begins with a segment + path_absolute, // begins with "/" but not "//" + path_abempty > {}; // begins with "/" or is empty + + struct reg_name : star< sor< unreserved, pct_encoded, sub_delims > > {}; + + struct port : star< DIGIT > {}; + struct host : sor< IP_literal, IPv4address, reg_name > {}; + struct userinfo : star< sor< unreserved, pct_encoded, sub_delims, colon > > {}; + struct authority : seq< opt< userinfo, one< '@' > >, host, opt< colon, port > > {}; + + struct scheme : seq< ALPHA, star< sor< ALPHA, DIGIT, one< '+', '-', '.' > > > > {}; + + using dslash = two< '/' >; + using opt_query = opt< if_must< one< '?' >, query > >; + using opt_fragment = opt< if_must< one< '#' >, fragment > >; + + struct hier_part : sor< if_must< dslash, authority, path_abempty >, path_rootless, path_absolute, path_empty > {}; + struct relative_part : sor< if_must< dslash, authority, path_abempty >, path_noscheme, path_absolute, path_empty > {}; + struct relative_ref : seq< relative_part, opt_query, opt_fragment > {}; + + struct URI : seq< scheme, one< ':' >, hier_part, opt_query, opt_fragment > {}; + struct URI_reference : sor< URI, relative_ref > {}; + struct absolute_URI : seq< scheme, one< ':' >, hier_part, opt_query > {}; + // clang-format on + + } // namespace uri + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/cstream_input.hpp b/include/tao/json/external/pegtl/cstream_input.hpp new file mode 100644 index 00000000..a2852ddc --- /dev/null +++ b/include/tao/json/external/pegtl/cstream_input.hpp @@ -0,0 +1,34 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CSTREAM_INPUT_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_CSTREAM_INPUT_HPP + +#include + +#include "buffer_input.hpp" +#include "config.hpp" +#include "eol.hpp" + +#include "internal/cstream_reader.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + template< typename Eol = eol::lf_crlf > + struct cstream_input + : buffer_input< internal::cstream_reader, Eol > + { + template< typename T > + cstream_input( std::FILE* in_stream, const std::size_t in_maximum, T&& in_source ) + : buffer_input< internal::cstream_reader, Eol >( std::forward< T >( in_source ), in_maximum, in_stream ) + { + } + }; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/eol.hpp b/include/tao/json/external/pegtl/eol.hpp new file mode 100644 index 00000000..efc1fc6a --- /dev/null +++ b/include/tao/json/external/pegtl/eol.hpp @@ -0,0 +1,54 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_EOL_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_EOL_HPP + +#include +#include + +#include "config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + using eol_pair = std::pair< bool, std::size_t >; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#include "internal/cr_crlf_eol.hpp" +#include "internal/cr_eol.hpp" +#include "internal/crlf_eol.hpp" +#include "internal/lf_crlf_eol.hpp" +#include "internal/lf_eol.hpp" + +#include "internal/eol.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + inline namespace ascii + { + // this is both a rule and a pseudo-namespace for eol::cr, ... + struct eol : internal::eol + { + // clang-format off + struct cr : internal::cr_eol {}; + struct cr_crlf : internal::cr_crlf_eol {}; + struct crlf : internal::crlf_eol {}; + struct lf : internal::lf_eol {}; + struct lf_crlf : internal::lf_crlf_eol {}; + // clang-format on + }; + + } // namespace ascii + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/file_input.hpp b/include/tao/json/external/pegtl/file_input.hpp new file mode 100644 index 00000000..de8f32d7 --- /dev/null +++ b/include/tao/json/external/pegtl/file_input.hpp @@ -0,0 +1,37 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_FILE_INPUT_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_FILE_INPUT_HPP + +#include "config.hpp" +#include "eol.hpp" +#include "tracking_mode.hpp" + +#if defined( __unix__ ) || ( defined( __APPLE__ ) && defined( __MACH__ ) ) +#include // Required for _POSIX_MAPPED_FILES +#endif + +#if defined( _POSIX_MAPPED_FILES ) +#include "mmap_input.hpp" +#else +#include "read_input.hpp" +#endif + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { +#if defined( _POSIX_MAPPED_FILES ) + template< tracking_mode P = tracking_mode::IMMEDIATE, typename Eol = eol::lf_crlf > + using file_input = mmap_input< P, Eol >; +#else + template< tracking_mode P = tracking_mode::IMMEDIATE, typename Eol = eol::lf_crlf > + using file_input = read_input< P, Eol >; +#endif + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/input_error.hpp b/include/tao/json/external/pegtl/input_error.hpp new file mode 100644 index 00000000..9c56a3d3 --- /dev/null +++ b/include/tao/json/external/pegtl/input_error.hpp @@ -0,0 +1,41 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INPUT_ERROR_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INPUT_ERROR_HPP + +#include +#include +#include + +#include "config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + struct input_error + : std::runtime_error + { + input_error( const std::string& message, const int in_errorno ) + : std::runtime_error( message ), + errorno( in_errorno ) + { + } + + int errorno; + }; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#define TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( MESSAGE ) \ + do { \ + const int errorno = errno; \ + std::ostringstream oss; \ + oss << "pegtl: " << MESSAGE << " errno " << errorno; \ + throw tao::TAOCPP_JSON_PEGTL_NAMESPACE::input_error( oss.str(), errorno ); \ + } while( false ) + +#endif diff --git a/include/tao/json/external/pegtl/internal/action.hpp b/include/tao/json/external/pegtl/internal/action.hpp new file mode 100644 index 00000000..d93599e4 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/action.hpp @@ -0,0 +1,52 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ACTION_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ACTION_HPP + +#include "../config.hpp" + +#include "duseltronik.hpp" +#include "seq.hpp" +#include "skip_control.hpp" + +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< template< typename... > class Action, typename... Rules > + struct action + { + using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rules... >; + + template< apply_mode A, + rewind_mode M, + template< typename... > class, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + return duseltronik< seq< Rules... >, A, M, Action, Control >::match( in, st... ); + } + }; + + template< template< typename... > class Action, typename... Rules > + struct skip_control< action< Action, Rules... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/action_input.hpp b/include/tao/json/external/pegtl/internal/action_input.hpp new file mode 100644 index 00000000..589cf216 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/action_input.hpp @@ -0,0 +1,108 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ACTION_INPUT_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ACTION_INPUT_HPP + +#include +#include + +#include "iterator.hpp" + +#include "../config.hpp" +#include "../position.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + inline const char* begin_c_ptr( const char* p ) noexcept + { + return p; + } + + inline const char* begin_c_ptr( const iterator& it ) noexcept + { + return it.data; + } + + template< typename Input > + class action_input + { + public: + using input_t = Input; + using iterator_t = typename Input::iterator_t; + + action_input( const iterator_t& in_begin, const Input& in_input ) noexcept + : m_begin( in_begin ), + m_input( in_input ) + { + } + + action_input( const action_input& ) = delete; + action_input& operator=( const action_input& ) = delete; + + const iterator_t& iterator() const noexcept + { + return m_begin; + } + + const Input& input() const noexcept + { + return m_input; + } + + const char* begin() const noexcept + { + return begin_c_ptr( iterator() ); + } + + const char* end() const noexcept + { + return input().current(); + } + + bool empty() const noexcept + { + return begin() == end(); + } + + std::size_t size() const noexcept + { + return std::size_t( end() - begin() ); + } + + std::string string() const + { + return std::string( begin(), end() ); + } + + char peek_char( const std::size_t offset = 0 ) const noexcept + { + return begin()[ offset ]; + } + + unsigned char peek_byte( const std::size_t offset = 0 ) const noexcept + { + return static_cast< unsigned char >( peek_char( offset ) ); + } + + TAOCPP_JSON_PEGTL_NAMESPACE::position position() const noexcept + { + return input().position( iterator() ); // NOTE: Not efficient with LAZY inputs. + } + + protected: + const iterator_t m_begin; + const Input& m_input; + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/alnum.hpp b/include/tao/json/external/pegtl/internal/alnum.hpp new file mode 100644 index 00000000..c8d0738d --- /dev/null +++ b/include/tao/json/external/pegtl/internal/alnum.hpp @@ -0,0 +1,26 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ALNUM_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ALNUM_HPP + +#include "../config.hpp" + +#include "peek_char.hpp" +#include "ranges.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + using alnum = ranges< peek_char, 'a', 'z', 'A', 'Z', '0', '9' >; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/alpha.hpp b/include/tao/json/external/pegtl/internal/alpha.hpp new file mode 100644 index 00000000..a12b8021 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/alpha.hpp @@ -0,0 +1,26 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ALPHA_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ALPHA_HPP + +#include "../config.hpp" + +#include "peek_char.hpp" +#include "ranges.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + using alpha = ranges< peek_char, 'a', 'z', 'A', 'Z' >; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/any.hpp b/include/tao/json/external/pegtl/internal/any.hpp new file mode 100644 index 00000000..8f44b78b --- /dev/null +++ b/include/tao/json/external/pegtl/internal/any.hpp @@ -0,0 +1,68 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ANY_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ANY_HPP + +#include "../config.hpp" + +#include "peek_char.hpp" +#include "skip_control.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename Peek > + struct any; + + template<> + struct any< peek_char > + { + using analyze_t = analysis::generic< analysis::rule_type::ANY >; + + template< typename Input > + static bool match( Input& in ) + { + if( !in.empty() ) { + in.bump(); + return true; + } + return false; + } + }; + + template< typename Peek > + struct any + { + using analyze_t = analysis::generic< analysis::rule_type::ANY >; + + template< typename Input > + static bool match( Input& in ) + { + if( !in.empty() ) { + if( const auto t = Peek::peek( in ) ) { + in.bump( t.size ); + return true; + } + } + return false; + } + }; + + template< typename Peek > + struct skip_control< any< Peek > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/apply.hpp b/include/tao/json/external/pegtl/internal/apply.hpp new file mode 100644 index 00000000..d23c2dc9 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/apply.hpp @@ -0,0 +1,79 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_APPLY_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_APPLY_HPP + +#include "../config.hpp" + +#include "skip_control.hpp" +#include "trivial.hpp" + +#include "../analysis/counted.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< apply_mode A, typename... Actions > + struct apply_impl; + + template< typename... Actions > + struct apply_impl< apply_mode::ACTION, Actions... > + { + template< typename Input, typename... States > + static bool match( Input& in, States&&... st ) + { + using action_t = typename Input::action_t; + const action_t i2( in.iterator(), in ); // No data -- range is from begin to begin. +#ifdef __cpp_fold_expressions + ( Actions::apply( i2, st... ), ... ); +#else + using swallow = bool[]; + (void)swallow{ ( Actions::apply( i2, st... ), true )..., true }; +#endif + return true; + } + }; + + template< typename... Actions > + struct apply_impl< apply_mode::NOTHING, Actions... > + { + template< typename Input, typename... States > + static bool match( Input&, States&&... ) + { + return true; + } + }; + + template< typename... Actions > + struct apply + { + using analyze_t = analysis::counted< analysis::rule_type::ANY, 0 >; + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + return apply_impl< A, Actions... >::match( in, st... ); + } + }; + + template< typename... Actions > + struct skip_control< apply< Actions... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/apply0.hpp b/include/tao/json/external/pegtl/internal/apply0.hpp new file mode 100644 index 00000000..c85c7532 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/apply0.hpp @@ -0,0 +1,77 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_APPLY0_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_APPLY0_HPP + +#include "../config.hpp" + +#include "skip_control.hpp" +#include "trivial.hpp" + +#include "../analysis/counted.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< apply_mode A, typename... Actions > + struct apply0_impl; + + template< typename... Actions > + struct apply0_impl< apply_mode::ACTION, Actions... > + { + template< typename... States > + static bool match( States&&... st ) + { +#ifdef __cpp_fold_expressions + ( Actions::apply0( st... ), ... ); +#else + using swallow = bool[]; + (void)swallow{ ( Actions::apply0( st... ), true )..., true }; +#endif + return true; + } + }; + + template< typename... Actions > + struct apply0_impl< apply_mode::NOTHING, Actions... > + { + template< typename... States > + static bool match( States&&... ) + { + return true; + } + }; + + template< typename... Actions > + struct apply0 + { + using analyze_t = analysis::counted< analysis::rule_type::ANY, 0 >; + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input&, States&&... st ) + { + return apply0_impl< A, Actions... >::match( st... ); + } + }; + + template< typename... Actions > + struct skip_control< apply0< Actions... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/at.hpp b/include/tao/json/external/pegtl/internal/at.hpp new file mode 100644 index 00000000..ecf49384 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/at.hpp @@ -0,0 +1,62 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_AT_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_AT_HPP + +#include "../config.hpp" + +#include "rule_conjunction.hpp" +#include "skip_control.hpp" +#include "trivial.hpp" + +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename... Rules > + struct at; + + template<> + struct at<> + : trivial< true > + { + }; + + template< typename... Rules > + struct at + { + using analyze_t = analysis::generic< analysis::rule_type::OPT, Rules... >; + + template< apply_mode, + rewind_mode, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + const auto m = in.template mark< rewind_mode::REQUIRED >(); + return rule_conjunction< Rules... >::template match< apply_mode::NOTHING, rewind_mode::ACTIVE, Action, Control >( in, st... ); + } + }; + + template< typename... Rules > + struct skip_control< at< Rules... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/bof.hpp b/include/tao/json/external/pegtl/internal/bof.hpp new file mode 100644 index 00000000..0dc54ea4 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/bof.hpp @@ -0,0 +1,41 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BOF_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BOF_HPP + +#include "../config.hpp" + +#include "skip_control.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct bof + { + using analyze_t = analysis::generic< analysis::rule_type::OPT >; + + template< typename Input > + static bool match( Input& in ) noexcept + { + return in.byte() == 0; + } + }; + + template<> + struct skip_control< bof > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/bol.hpp b/include/tao/json/external/pegtl/internal/bol.hpp new file mode 100644 index 00000000..fa60d229 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/bol.hpp @@ -0,0 +1,41 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BOL_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BOL_HPP + +#include "../config.hpp" + +#include "skip_control.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct bol + { + using analyze_t = analysis::generic< analysis::rule_type::OPT >; + + template< typename Input > + static bool match( Input& in ) noexcept + { + return in.byte_in_line() == 0; + } + }; + + template<> + struct skip_control< bol > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/bump_help.hpp b/include/tao/json/external/pegtl/internal/bump_help.hpp new file mode 100644 index 00000000..2e3fe922 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/bump_help.hpp @@ -0,0 +1,64 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BUMP_UTIL_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BUMP_UTIL_HPP + +#include +#include + +#include "../config.hpp" + +#include "result_on_found.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< bool > + struct bump_impl; + + template<> + struct bump_impl< true > + { + template< typename Input > + static void bump( Input& in, const std::size_t count ) noexcept + { + in.bump( count ); + } + }; + + template<> + struct bump_impl< false > + { + template< typename Input > + static void bump( Input& in, const std::size_t count ) noexcept + { + in.bump_in_this_line( count ); + } + }; + + template< bool... > + struct bool_list + { + }; + + template< bool... Bs > + using bool_and = std::is_same< bool_list< Bs..., true >, bool_list< true, Bs... > >; + + template< result_on_found R, typename Input, typename Char, Char... Cs > + void bump_help( Input& in, const std::size_t count ) noexcept + { + using eol_t = typename Input::eol_t; + bump_impl< bool_and< ( Cs != eol_t::ch )... >::value != bool( R ) >::bump( in, count ); + } + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/bump_impl.hpp b/include/tao/json/external/pegtl/internal/bump_impl.hpp new file mode 100644 index 00000000..85e45c0d --- /dev/null +++ b/include/tao/json/external/pegtl/internal/bump_impl.hpp @@ -0,0 +1,53 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BUMP_IMPL_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BUMP_IMPL_HPP + +#include "../config.hpp" + +#include "iterator.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + inline void bump( iterator& iter, const std::size_t count, const int ch ) noexcept + { + for( std::size_t i = 0; i < count; ++i ) { + if( iter.data[ i ] == ch ) { + ++iter.line; + iter.byte_in_line = 0; + } + else { + ++iter.byte_in_line; + } + } + iter.byte += count; + iter.data += count; + } + + inline void bump_in_this_line( iterator& iter, const std::size_t count ) noexcept + { + iter.data += count; + iter.byte += count; + iter.byte_in_line += count; + } + + inline void bump_to_next_line( iterator& iter, const std::size_t count ) noexcept + { + ++iter.line; + iter.byte += count; + iter.byte_in_line = 0; + iter.data += count; + } + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/bytes.hpp b/include/tao/json/external/pegtl/internal/bytes.hpp new file mode 100644 index 00000000..e1b1dac0 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/bytes.hpp @@ -0,0 +1,46 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BYTES_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BYTES_HPP + +#include "../config.hpp" + +#include "skip_control.hpp" + +#include "../analysis/counted.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< unsigned Num > + struct bytes + { + using analyze_t = analysis::counted< analysis::rule_type::ANY, Num >; + + template< typename Input > + static bool match( Input& in ) + { + if( in.size( Num ) >= Num ) { + in.bump( Num ); + return true; + } + return false; + } + }; + + template< unsigned Num > + struct skip_control< bytes< Num > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/control.hpp b/include/tao/json/external/pegtl/internal/control.hpp new file mode 100644 index 00000000..ee104de7 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/control.hpp @@ -0,0 +1,52 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CONTROL_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CONTROL_HPP + +#include "../config.hpp" + +#include "duseltronik.hpp" +#include "seq.hpp" +#include "skip_control.hpp" + +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< template< typename... > class Control, typename... Rules > + struct control + { + using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rules... >; + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + return duseltronik< seq< Rules... >, A, M, Action, Control >::match( in, st... ); + } + }; + + template< template< typename... > class Control, typename... Rules > + struct skip_control< control< Control, Rules... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/cr_crlf_eol.hpp b/include/tao/json/external/pegtl/internal/cr_crlf_eol.hpp new file mode 100644 index 00000000..428a30a2 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/cr_crlf_eol.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CR_CRLF_EOL_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CR_CRLF_EOL_HPP + +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct cr_crlf_eol + { + static constexpr int ch = '\r'; + + template< typename Input > + static eol_pair match( Input& in ) + { + eol_pair p = { false, in.size( 2 ) }; + if( p.second ) { + if( in.peek_char() == '\r' ) { + in.bump_to_next_line( 1 + ( ( p.second > 1 ) && ( in.peek_char( 1 ) == '\n' ) ) ); + p.first = true; + } + } + return p; + } + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/cr_eol.hpp b/include/tao/json/external/pegtl/internal/cr_eol.hpp new file mode 100644 index 00000000..18396fac --- /dev/null +++ b/include/tao/json/external/pegtl/internal/cr_eol.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CR_EOL_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CR_EOL_HPP + +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct cr_eol + { + static constexpr int ch = '\r'; + + template< typename Input > + static eol_pair match( Input& in ) + { + eol_pair p = { false, in.size( 1 ) }; + if( p.second ) { + if( in.peek_char() == '\r' ) { + in.bump_to_next_line(); + p.first = true; + } + } + return p; + } + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/crlf_eol.hpp b/include/tao/json/external/pegtl/internal/crlf_eol.hpp new file mode 100644 index 00000000..3b010ff4 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/crlf_eol.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CRLF_EOL_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CRLF_EOL_HPP + +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct crlf_eol + { + static constexpr int ch = '\n'; + + template< typename Input > + static eol_pair match( Input& in ) + { + eol_pair p = { false, in.size( 2 ) }; + if( p.second > 1 ) { + if( ( in.peek_char() == '\r' ) && ( in.peek_char( 1 ) == '\n' ) ) { + in.bump_to_next_line( 2 ); + p.first = true; + } + } + return p; + } + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/cstream_reader.hpp b/include/tao/json/external/pegtl/internal/cstream_reader.hpp new file mode 100644 index 00000000..6e350049 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/cstream_reader.hpp @@ -0,0 +1,48 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CSTREAM_READER_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CSTREAM_READER_HPP + +#include +#include + +#include "../config.hpp" +#include "../input_error.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct cstream_reader + { + explicit cstream_reader( std::FILE* s ) noexcept + : m_cstream( s ) + { + } + + std::size_t operator()( char* buffer, const std::size_t length ) + { + if( const auto r = std::fread( buffer, 1, length, m_cstream ) ) { + return r; + } + if( std::feof( m_cstream ) != 0 ) { + return 0; + } + // Please contact us if you know how to provoke the following exception. + // The example on cppreference.com doesn't work, at least not on macOS. + TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "error in fread() from cstream" ); // LCOV_EXCL_LINE + } + + std::FILE* m_cstream; + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/cstring_reader.hpp b/include/tao/json/external/pegtl/internal/cstring_reader.hpp new file mode 100644 index 00000000..584ab766 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/cstring_reader.hpp @@ -0,0 +1,49 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CSTRING_READER_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CSTRING_READER_HPP + +#include +#include + +#include "../config.hpp" +#include "../input_error.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct cstring_reader + { + explicit cstring_reader( const char* zero_terminated ) noexcept + : m_cstring( zero_terminated ) + { + assert( m_cstring ); + } + + std::size_t operator()( char* buffer, const std::size_t length ) noexcept + { + std::size_t i = 0; + char c; + + while( ( i < length ) && ( ( c = m_cstring[ i ] ) != 0 ) ) { + *buffer++ = c; + ++i; + } + m_cstring += i; + return i; + } + + const char* m_cstring; + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/demangle.hpp b/include/tao/json/external/pegtl/internal/demangle.hpp new file mode 100644 index 00000000..6358487b --- /dev/null +++ b/include/tao/json/external/pegtl/internal/demangle.hpp @@ -0,0 +1,44 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DEMANGLE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DEMANGLE_HPP + +#include +#include + +#include "../config.hpp" + +#if defined( __GLIBCXX__ ) +#include "demangle_cxxabi.hpp" +#elif defined( __has_include ) +// clang-format off +#if __has_include( ) +// clang-format on +#include "demangle_cxxabi.hpp" +#else +#include "demangle_nop.hpp" +#endif +#else +#include "demangle_nop.hpp" +#endif + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename T > + std::string demangle() + { + return demangle( typeid( T ).name() ); + } + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/demangle_cxxabi.hpp b/include/tao/json/external/pegtl/internal/demangle_cxxabi.hpp new file mode 100644 index 00000000..d5708e55 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/demangle_cxxabi.hpp @@ -0,0 +1,41 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DEMANGLE_CXXABI_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DEMANGLE_CXXABI_HPP + +#include +#include +#include +#include + +#include "../config.hpp" + +#include "demangle_sanitise.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + inline std::string demangle( const char* symbol ) + { + const std::unique_ptr< char, decltype( &std::free ) > demangled( abi::__cxa_demangle( symbol, nullptr, nullptr, nullptr ), &std::free ); + if( !demangled ) { + return symbol; + } + std::string result( demangled.get() ); +#ifdef TAOCPP_JSON_PEGTL_PRETTY_DEMANGLE + demangle_sanitise_chars( result ); // LCOV_EXCL_LINE +#endif + return result; + } + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/demangle_nop.hpp b/include/tao/json/external/pegtl/internal/demangle_nop.hpp new file mode 100644 index 00000000..00f1fe89 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/demangle_nop.hpp @@ -0,0 +1,28 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DEMANGLE_NOP_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DEMANGLE_NOP_HPP + +#include + +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + inline std::string demangle( const char* symbol ) + { + return symbol; + } + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/demangle_sanitise.hpp b/include/tao/json/external/pegtl/internal/demangle_sanitise.hpp new file mode 100644 index 00000000..30b27534 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/demangle_sanitise.hpp @@ -0,0 +1,48 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DEMANGLE_SANITISE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DEMANGLE_SANITISE_HPP + +#include + +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + inline void demangle_sanitise_chars( std::string& s ) + { + std::string::size_type p; + while( ( p = s.find( "(char)" ) ) != std::string::npos ) { + int c = 0; + std::string::size_type q; + for( q = p + 6; ( q < s.size() ) && ( s[ q ] >= '0' ) && ( s[ q ] <= '9' ); ++q ) { + c *= 10; + c += s[ q ] - '0'; + } + if( c == '\'' ) { + s.replace( p, q - p, "'\\''" ); + } + else if( c == '\\' ) { + s.replace( p, q - p, "'\\\\'" ); + } + else if( ( c < 32 ) || ( c > 126 ) ) { + s.replace( p, 6, std::string() ); + } + else { + s.replace( p, q - p, std::string( 1, '\'' ) + char( c ) + '\'' ); + } + } + } + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/disable.hpp b/include/tao/json/external/pegtl/internal/disable.hpp new file mode 100644 index 00000000..8ddcf6ec --- /dev/null +++ b/include/tao/json/external/pegtl/internal/disable.hpp @@ -0,0 +1,52 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DISABLE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DISABLE_HPP + +#include "../config.hpp" + +#include "duseltronik.hpp" +#include "seq.hpp" +#include "skip_control.hpp" + +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename... Rules > + struct disable + { + using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rules... >; + + template< apply_mode, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + return duseltronik< seq< Rules... >, apply_mode::NOTHING, M, Action, Control >::match( in, st... ); + } + }; + + template< typename... Rules > + struct skip_control< disable< Rules... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/discard.hpp b/include/tao/json/external/pegtl/internal/discard.hpp new file mode 100644 index 00000000..9069ed67 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/discard.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DISCARD_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DISCARD_HPP + +#include "../config.hpp" + +#include "skip_control.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct discard + { + using analyze_t = analysis::generic< analysis::rule_type::OPT >; + + template< typename Input > + static bool match( Input& in ) + { + in.discard(); + return true; + } + }; + + template<> + struct skip_control< discard > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/dusel_mode.hpp b/include/tao/json/external/pegtl/internal/dusel_mode.hpp new file mode 100644 index 00000000..a30aba5a --- /dev/null +++ b/include/tao/json/external/pegtl/internal/dusel_mode.hpp @@ -0,0 +1,27 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DUSEL_MODE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DUSEL_MODE_HPP + +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + enum class dusel_mode : char + { + NOTHING = 0, + CONTROL = 1, + CONTROL_AND_APPLY_VOID = 2, + CONTROL_AND_APPLY_BOOL = 3, + CONTROL_AND_APPLY0_VOID = 4, + CONTROL_AND_APPLY0_BOOL = 5 + }; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/duseltronik.hpp b/include/tao/json/external/pegtl/internal/duseltronik.hpp new file mode 100644 index 00000000..48d8e291 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/duseltronik.hpp @@ -0,0 +1,167 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DUSELTRONIK_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DUSELTRONIK_HPP + +#include "../apply_mode.hpp" +#include "../config.hpp" +#include "../rewind_mode.hpp" + +#include "dusel_mode.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + dusel_mode = dusel_mode::NOTHING > + struct duseltronik; + + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control > + struct duseltronik< Rule, A, M, Action, Control, dusel_mode::NOTHING > + { + template< typename Input, typename... States > + static auto match( Input& in, States&&... st ) -> decltype( Rule::template match< A, M, Action, Control >( in, st... ), true ) + { + return Rule::template match< A, M, Action, Control >( in, st... ); + } + + // NOTE: The additional "int = 0" is a work-around for missing expression SFINAE in VS2015. + + template< typename Input, typename... States, int = 0 > + static auto match( Input& in, States&&... ) -> decltype( Rule::match( in ), true ) + { + return Rule::match( in ); + } + }; + + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control > + struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL > + { + template< typename Input, typename... States > + static bool match( Input& in, States&&... st ) + { + Control< Rule >::start( const_cast< const Input& >( in ), st... ); + + if( duseltronik< Rule, A, M, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) { + Control< Rule >::success( const_cast< const Input& >( in ), st... ); + return true; + } + Control< Rule >::failure( const_cast< const Input& >( in ), st... ); + return false; + } + }; + + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control > + struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY_VOID > + { + template< typename Input, typename... States > + static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< rewind_mode::REQUIRED >(); + + Control< Rule >::start( const_cast< const Input& >( in ), st... ); + + if( duseltronik< Rule, A, rewind_mode::ACTIVE, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) { + Control< Rule >::template apply< Action >( m.iterator(), const_cast< const Input& >( in ), st... ); + Control< Rule >::success( const_cast< const Input& >( in ), st... ); + return m( true ); + } + Control< Rule >::failure( const_cast< const Input& >( in ), st... ); + return false; + } + }; + + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control > + struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY_BOOL > + { + template< typename Input, typename... States > + static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< rewind_mode::REQUIRED >(); + + Control< Rule >::start( const_cast< const Input& >( in ), st... ); + + if( duseltronik< Rule, A, rewind_mode::ACTIVE, Action, Control, dusel_mode::NOTHING >::match( in, st... ) && Control< Rule >::template apply< Action >( m.iterator(), const_cast< const Input& >( in ), st... ) ) { + Control< Rule >::success( const_cast< const Input& >( in ), st... ); + return m( true ); + } + return false; + } + }; + + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control > + struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY0_VOID > + { + template< typename Input, typename... States > + static bool match( Input& in, States&&... st ) + { + Control< Rule >::start( const_cast< const Input& >( in ), st... ); + + if( duseltronik< Rule, A, M, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) { + Control< Rule >::template apply0< Action >( const_cast< const Input& >( in ), st... ); + Control< Rule >::success( const_cast< const Input& >( in ), st... ); + return true; + } + Control< Rule >::failure( const_cast< const Input& >( in ), st... ); + return false; + } + }; + + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control > + struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY0_BOOL > + { + template< typename Input, typename... States > + static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< rewind_mode::REQUIRED >(); + + Control< Rule >::start( const_cast< const Input& >( in ), st... ); + + if( duseltronik< Rule, A, rewind_mode::ACTIVE, Action, Control, dusel_mode::NOTHING >::match( in, st... ) && Control< Rule >::template apply0< Action >( const_cast< const Input& >( in ), st... ) ) { + Control< Rule >::success( const_cast< const Input& >( in ), st... ); + return m( true ); + } + Control< Rule >::failure( const_cast< const Input& >( in ), st... ); + return false; + } + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/enable.hpp b/include/tao/json/external/pegtl/internal/enable.hpp new file mode 100644 index 00000000..c4fd0012 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/enable.hpp @@ -0,0 +1,52 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ENABLE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ENABLE_HPP + +#include "../config.hpp" + +#include "duseltronik.hpp" +#include "seq.hpp" +#include "skip_control.hpp" + +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename... Rules > + struct enable + { + using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rules... >; + + template< apply_mode, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + return duseltronik< seq< Rules... >, apply_mode::ACTION, M, Action, Control >::match( in, st... ); + } + }; + + template< typename... Rules > + struct skip_control< enable< Rules... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/eof.hpp b/include/tao/json/external/pegtl/internal/eof.hpp new file mode 100644 index 00000000..97ab487b --- /dev/null +++ b/include/tao/json/external/pegtl/internal/eof.hpp @@ -0,0 +1,41 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_EOF_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_EOF_HPP + +#include "../config.hpp" + +#include "skip_control.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct eof + { + using analyze_t = analysis::generic< analysis::rule_type::OPT >; + + template< typename Input > + static bool match( Input& in ) + { + return in.empty(); + } + }; + + template<> + struct skip_control< eof > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/eol.hpp b/include/tao/json/external/pegtl/internal/eol.hpp new file mode 100644 index 00000000..b603edf0 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/eol.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_EOL_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_EOL_HPP + +#include "../config.hpp" + +#include "skip_control.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct eol + { + using analyze_t = analysis::generic< analysis::rule_type::ANY >; + + template< typename Input > + static bool match( Input& in ) + { + using eol_t = typename Input::eol_t; + return eol_t::match( in ).first; + } + }; + + template<> + struct skip_control< eol > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/eolf.hpp b/include/tao/json/external/pegtl/internal/eolf.hpp new file mode 100644 index 00000000..1e7cf99d --- /dev/null +++ b/include/tao/json/external/pegtl/internal/eolf.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_EOLF_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_EOLF_HPP + +#include "../config.hpp" + +#include "skip_control.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct eolf + { + using analyze_t = analysis::generic< analysis::rule_type::OPT >; + + template< typename Input > + static bool match( Input& in ) + { + using eol_t = typename Input::eol_t; + const auto p = eol_t::match( in ); + return p.first || ( !p.second ); + } + }; + + template<> + struct skip_control< eolf > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/file_mapper.hpp b/include/tao/json/external/pegtl/internal/file_mapper.hpp new file mode 100644 index 00000000..96dc37fc --- /dev/null +++ b/include/tao/json/external/pegtl/internal/file_mapper.hpp @@ -0,0 +1,91 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_FILE_MAPPER_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_FILE_MAPPER_HPP + +#include +#include + +#include "../config.hpp" + +#include "file_opener.hpp" + +#include "../input_error.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + class file_mapper + { + public: + explicit file_mapper( const char* filename ) + : file_mapper( file_opener( filename ) ) + { + } + + explicit file_mapper( const file_opener& reader ) + : m_size( reader.size() ), + m_data( static_cast< const char* >(::mmap( nullptr, m_size, PROT_READ, MAP_PRIVATE, reader.m_fd, 0 ) ) ) + { + if( m_size && ( intptr_t( m_data ) == -1 ) ) { + TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "unable to mmap() file " << reader.m_source << " descriptor " << reader.m_fd ); + } + } + + ~file_mapper() noexcept + { + ::munmap( const_cast< char* >( m_data ), m_size ); // Legacy C interface requires pointer-to-mutable but does not write through the pointer. + } + + file_mapper( const file_mapper& ) = delete; + void operator=( const file_mapper& ) = delete; + + bool empty() const noexcept + { + return m_size == 0; + } + + std::size_t size() const noexcept + { + return m_size; + } + + using iterator = const char*; + using const_iterator = const char*; + + iterator data() const noexcept + { + return m_data; + } + + iterator begin() const noexcept + { + return m_data; + } + + iterator end() const noexcept + { + return m_data + m_size; + } + + std::string string() const + { + return std::string( m_data, m_size ); + } + + private: + const std::size_t m_size; + const char* const m_data; + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/file_opener.hpp b/include/tao/json/external/pegtl/internal/file_opener.hpp new file mode 100644 index 00000000..8a65b9de --- /dev/null +++ b/include/tao/json/external/pegtl/internal/file_opener.hpp @@ -0,0 +1,70 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_FILE_OPENER_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_FILE_OPENER_HPP + +#include +#include +#include +#include + +#include + +#include "../config.hpp" +#include "../input_error.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct file_opener + { + explicit file_opener( const char* filename ) + : m_source( filename ), + m_fd( open() ) + { + } + + ~file_opener() noexcept + { + ::close( m_fd ); + } + + file_opener( const file_opener& ) = delete; + void operator=( const file_opener& ) = delete; + + std::size_t size() const + { + struct stat st; + errno = 0; + if(::fstat( m_fd, &st ) < 0 ) { + TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "unable to fstat() file " << m_source << " descriptor " << m_fd ); + } + return std::size_t( st.st_size ); + } + + const char* const m_source; + const int m_fd; + + private: + int open() const + { + errno = 0; + const int fd = ::open( m_source, O_RDONLY ); + if( fd >= 0 ) { + return fd; + } + TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "unable to open() file " << m_source << " for reading" ); + } + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/file_reader.hpp b/include/tao/json/external/pegtl/internal/file_reader.hpp new file mode 100644 index 00000000..d2e25277 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/file_reader.hpp @@ -0,0 +1,96 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_FILE_READER_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_FILE_READER_HPP + +#include +#include +#include +#include + +#include "../config.hpp" +#include "../input_error.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct file_close + { + void operator()( FILE* f ) const + { + std::fclose( f ); + } + }; + + class file_reader + { + public: + explicit file_reader( const char* filename ) + : m_source( filename ), + m_file( open() ) + { + } + + file_reader( const file_reader& ) = delete; + void operator=( const file_reader& ) = delete; + + std::size_t size() const + { + errno = 0; + if( std::fseek( m_file.get(), 0, SEEK_END ) != 0 ) { + TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "unable to fseek() to end of file " << m_source ); // LCOV_EXCL_LINE + } + errno = 0; + const auto s = std::ftell( m_file.get() ); + if( s < 0 ) { + TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "unable to ftell() file size of file " << m_source ); // LCOV_EXCL_LINE + } + errno = 0; + if( std::fseek( m_file.get(), 0, SEEK_SET ) != 0 ) { + TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "unable to fseek() to beginning of file " << m_source ); // LCOV_EXCL_LINE + } + return std::size_t( s ); + } + + std::string read() const + { + std::string nrv; + nrv.resize( size() ); + errno = 0; + if( ( nrv.size() != 0 ) && ( std::fread( &nrv[ 0 ], nrv.size(), 1, m_file.get() ) != 1 ) ) { + TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "unable to fread() file " << m_source << " size " << nrv.size() ); // LCOV_EXCL_LINE + } + return nrv; + } + + private: + const char* const m_source; + const std::unique_ptr< std::FILE, file_close > m_file; + + std::FILE* open() const + { + errno = 0; +#if defined( _MSC_VER ) + std::FILE* file; + if(::fopen_s( &file, m_source, "rb" ) == 0 ) +#else + if( auto* file = std::fopen( m_source, "rb" ) ) +#endif + { + return file; + } + TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "unable to fopen() file " << m_source << " for reading" ); + } + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/has_apply.hpp b/include/tao/json/external/pegtl/internal/has_apply.hpp new file mode 100644 index 00000000..47bc99af --- /dev/null +++ b/include/tao/json/external/pegtl/internal/has_apply.hpp @@ -0,0 +1,33 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_HAS_APPLY_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_HAS_APPLY_HPP + +#include + +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename, typename, typename... > + struct has_apply : std::false_type + { + }; + + template< typename A, typename... S > + struct has_apply< A, decltype( A::apply( std::declval< S >()... ) ), S... > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/has_apply0.hpp b/include/tao/json/external/pegtl/internal/has_apply0.hpp new file mode 100644 index 00000000..35a15eae --- /dev/null +++ b/include/tao/json/external/pegtl/internal/has_apply0.hpp @@ -0,0 +1,33 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_HAS_APPLY0_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_HAS_APPLY0_HPP + +#include + +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename, typename, typename... > + struct has_apply0 : std::false_type + { + }; + + template< typename A, typename... S > + struct has_apply0< A, decltype( A::apply0( std::declval< S >()... ) ), S... > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/identifier.hpp b/include/tao/json/external/pegtl/internal/identifier.hpp new file mode 100644 index 00000000..8eed3a40 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/identifier.hpp @@ -0,0 +1,30 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IDENTIFIER_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IDENTIFIER_HPP + +#include "../config.hpp" + +#include "peek_char.hpp" +#include "ranges.hpp" +#include "seq.hpp" +#include "star.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + using identifier_first = ranges< peek_char, 'a', 'z', 'A', 'Z', '_' >; + using identifier_other = ranges< peek_char, 'a', 'z', 'A', 'Z', '0', '9', '_' >; + using identifier = seq< identifier_first, star< identifier_other > >; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/if_apply.hpp b/include/tao/json/external/pegtl/internal/if_apply.hpp new file mode 100644 index 00000000..bbfbdde3 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/if_apply.hpp @@ -0,0 +1,90 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IF_APPLY_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IF_APPLY_HPP + +#include "../config.hpp" + +#include "skip_control.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< apply_mode A, typename Rule, typename... Actions > + struct if_apply_impl; + + template< typename Rule, typename... Actions > + struct if_apply_impl< apply_mode::ACTION, Rule, Actions... > + { + template< rewind_mode, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + using action_t = typename Input::action_t; + + auto m = in.template mark< rewind_mode::REQUIRED >(); + + if( Control< Rule >::template match< apply_mode::ACTION, rewind_mode::ACTIVE, Action, Control >( in, st... ) ) { + const action_t i2( m.iterator(), in ); +#ifdef __cpp_fold_expressions + ( Actions::apply( i2, st... ), ... ); +#else + using swallow = bool[]; + (void)swallow{ ( Actions::apply( i2, st... ), true )..., true }; +#endif + return m( true ); + } + return false; + } + }; + + template< typename Rule, typename... Actions > + struct if_apply_impl< apply_mode::NOTHING, Rule, Actions... > + { + template< rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + return Control< Rule >::template match< apply_mode::NOTHING, M, Action, Control >( in, st... ); + } + }; + + template< typename Rule, typename... Actions > + struct if_apply + { + using analyze_t = typename Rule::analyze_t; + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + return if_apply_impl< A, Rule, Actions... >::template match< M, Action, Control >( in, st... ); + } + }; + + template< typename Rule, typename... Actions > + struct skip_control< if_apply< Rule, Actions... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/if_must.hpp b/include/tao/json/external/pegtl/internal/if_must.hpp new file mode 100644 index 00000000..bf5d0839 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/if_must.hpp @@ -0,0 +1,27 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IF_MUST_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IF_MUST_HPP + +#include "../config.hpp" + +#include "must.hpp" +#include "seq.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename Cond, typename... Thens > + using if_must = seq< Cond, must< Thens... > >; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/if_must_else.hpp b/include/tao/json/external/pegtl/internal/if_must_else.hpp new file mode 100644 index 00000000..f3433de6 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/if_must_else.hpp @@ -0,0 +1,27 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IF_MUST_ELSE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IF_MUST_ELSE_HPP + +#include "../config.hpp" + +#include "if_then_else.hpp" +#include "must.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename Cond, typename Then, typename Else > + using if_must_else = if_then_else< Cond, must< Then >, must< Else > >; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/if_then_else.hpp b/include/tao/json/external/pegtl/internal/if_then_else.hpp new file mode 100644 index 00000000..4f5dfa19 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/if_then_else.hpp @@ -0,0 +1,59 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IF_THEN_ELSE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IF_THEN_ELSE_HPP + +#include "../config.hpp" + +#include "not_at.hpp" +#include "seq.hpp" +#include "skip_control.hpp" +#include "sor.hpp" + +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename Cond, typename Then, typename Else > + struct if_then_else + { + using analyze_t = analysis::generic< analysis::rule_type::SOR, seq< Cond, Then >, seq< not_at< Cond >, Else > >; + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< M >(); + using m_t = decltype( m ); + + if( Control< Cond >::template match< A, rewind_mode::REQUIRED, Action, Control >( in, st... ) ) { + return m( Control< Then >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) ); + } + return m( Control< Else >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) ); + } + }; + + template< typename Cond, typename Then, typename Else > + struct skip_control< if_then_else< Cond, Then, Else > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/input_pair.hpp b/include/tao/json/external/pegtl/internal/input_pair.hpp new file mode 100644 index 00000000..36fe50d7 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/input_pair.hpp @@ -0,0 +1,35 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_INPUT_PAIR_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_INPUT_PAIR_HPP + +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename Data > + struct input_pair + { + Data data; + unsigned char size; + + using data_t = Data; + + explicit operator bool() const noexcept + { + return size > 0; + } + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/integer_sequence.hpp b/include/tao/json/external/pegtl/internal/integer_sequence.hpp new file mode 100644 index 00000000..6ed887f4 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/integer_sequence.hpp @@ -0,0 +1,86 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_INTEGER_SEQUENCE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_INTEGER_SEQUENCE_HPP + +#include +#include +#include + +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename T, T... Ns > + struct integer_sequence + { + using value_type = T; + + static constexpr std::size_t size() noexcept + { + return sizeof...( Ns ); + } + }; + + template< std::size_t... Ns > + using index_sequence = integer_sequence< std::size_t, Ns... >; + + template< bool V, bool E > + struct generate_sequence; + + template<> + struct generate_sequence< false, true > + { + template< typename T, T M, T N, std::size_t S, T... Ns > + using f = integer_sequence< T, Ns... >; + }; + + template<> + struct generate_sequence< true, true > + { + template< typename T, T M, T N, std::size_t S, T... Ns > + using f = integer_sequence< T, Ns..., S >; + }; + + template<> + struct generate_sequence< false, false > + { + template< typename T, T M, T N, std::size_t S, T... Ns > + using f = typename generate_sequence< ( N & ( M / 2 ) ) != 0, ( M / 2 ) == 0 >::template f< T, M / 2, N, 2 * S, Ns..., ( Ns + S )... >; + }; + + template<> + struct generate_sequence< true, false > + { + template< typename T, T M, T N, std::size_t S, T... Ns > + using f = typename generate_sequence< ( N & ( M / 2 ) ) != 0, ( M / 2 ) == 0 >::template f< T, M / 2, N, 2 * S + 1, Ns..., ( Ns + S )..., 2 * S >; + }; + + template< typename T, T N > + struct memoize_sequence + { + static_assert( N < T( 1 << 20 ), "N too large" ); + using type = typename generate_sequence< false, false >::template f< T, ( N < T( 1 << 1 ) ) ? T( 1 << 1 ) : ( N < T( 1 << 2 ) ) ? T( 1 << 2 ) : ( N < T( 1 << 3 ) ) ? T( 1 << 3 ) : ( N < T( 1 << 4 ) ) ? T( 1 << 4 ) : ( N < T( 1 << 5 ) ) ? T( 1 << 5 ) : ( N < T( 1 << 6 ) ) ? T( 1 << 6 ) : ( N < T( 1 << 7 ) ) ? T( 1 << 7 ) : ( N < T( 1 << 8 ) ) ? T( 1 << 8 ) : ( N < T( 1 << 9 ) ) ? T( 1 << 9 ) : ( N < T( 1 << 10 ) ) ? T( 1 << 10 ) : T( 1 << 20 ), N, 0 >; + }; + + template< typename T, T N > + using make_integer_sequence = typename memoize_sequence< T, N >::type; + + template< std::size_t N > + using make_index_sequence = make_integer_sequence< std::size_t, N >; + + template< typename... Ts > + using index_sequence_for = make_index_sequence< sizeof...( Ts ) >; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/istream_reader.hpp b/include/tao/json/external/pegtl/internal/istream_reader.hpp new file mode 100644 index 00000000..55ec31b2 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/istream_reader.hpp @@ -0,0 +1,47 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ISTREAM_READER_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ISTREAM_READER_HPP + +#include + +#include "../config.hpp" +#include "../input_error.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct istream_reader + { + explicit istream_reader( std::istream& s ) noexcept + : m_istream( s ) + { + } + + std::size_t operator()( char* buffer, const std::size_t length ) + { + m_istream.read( buffer, std::streamsize( length ) ); + + if( const auto r = m_istream.gcount() ) { + return std::size_t( r ); + } + if( m_istream.eof() ) { + return 0; + } + TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "error in istream.read()" ); + } + + std::istream& m_istream; + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/istring.hpp b/include/tao/json/external/pegtl/internal/istring.hpp new file mode 100644 index 00000000..d0d33407 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/istring.hpp @@ -0,0 +1,107 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ISTRING_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ISTRING_HPP + +#include + +#include "../config.hpp" + +#include "bump_help.hpp" +#include "result_on_found.hpp" +#include "skip_control.hpp" +#include "trivial.hpp" + +#include "../analysis/counted.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< char C > + using is_alpha = std::integral_constant< bool, ( ( 'a' <= C ) && ( C <= 'z' ) ) || ( ( 'A' <= C ) && ( C <= 'Z' ) ) >; + + template< char C, bool A = is_alpha< C >::value > + struct ichar_equal; + + template< char C > + struct ichar_equal< C, true > + { + static bool match( const char c ) noexcept + { + return ( C | 0x20 ) == ( c | 0x20 ); + } + }; + + template< char C > + struct ichar_equal< C, false > + { + static bool match( const char c ) noexcept + { + return c == C; + } + }; + + template< char... Cs > + struct istring_equal; + + template<> + struct istring_equal<> + { + static bool match( const char* ) noexcept + { + return true; + } + }; + + template< char C, char... Cs > + struct istring_equal< C, Cs... > + { + static bool match( const char* r ) noexcept + { + return ichar_equal< C >::match( *r ) && istring_equal< Cs... >::match( r + 1 ); + } + }; + + template< char... Cs > + struct istring; + + template<> + struct istring<> + : trivial< true > + { + }; + + template< char... Cs > + struct istring + { + using analyze_t = analysis::counted< analysis::rule_type::ANY, sizeof...( Cs ) >; + + template< typename Input > + static bool match( Input& in ) + { + if( in.size( sizeof...( Cs ) ) >= sizeof...( Cs ) ) { + if( istring_equal< Cs... >::match( in.current() ) ) { + bump_help< result_on_found::SUCCESS, Input, char, Cs... >( in, sizeof...( Cs ) ); + return true; + } + } + return false; + } + }; + + template< char... Cs > + struct skip_control< istring< Cs... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/iterator.hpp b/include/tao/json/external/pegtl/internal/iterator.hpp new file mode 100644 index 00000000..70de7d4d --- /dev/null +++ b/include/tao/json/external/pegtl/internal/iterator.hpp @@ -0,0 +1,53 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ITERATOR_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ITERATOR_HPP + +#include + +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct iterator + { + iterator() noexcept = default; + + explicit iterator( const char* in_data ) noexcept + : data( in_data ), + byte( 0 ), + line( 1 ), + byte_in_line( 0 ) + { + } + + iterator( const char* in_data, const std::size_t in_byte, const std::size_t in_line, const std::size_t in_byte_in_line ) noexcept + : data( in_data ), + byte( in_byte ), + line( in_line ), + byte_in_line( in_byte_in_line ) + { + } + + iterator( const iterator& ) = default; + iterator& operator=( const iterator& ) = default; + + const char* data = nullptr; + + std::size_t byte; + std::size_t line; + std::size_t byte_in_line; + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/lf_crlf_eol.hpp b/include/tao/json/external/pegtl/internal/lf_crlf_eol.hpp new file mode 100644 index 00000000..a3089b96 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/lf_crlf_eol.hpp @@ -0,0 +1,44 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LF_CRLF_EOL_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LF_CRLF_EOL_HPP + +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct lf_crlf_eol + { + static constexpr int ch = '\n'; + + template< typename Input > + static eol_pair match( Input& in ) + { + eol_pair p = { false, in.size( 2 ) }; + if( p.second ) { + const auto a = in.peek_char(); + if( a == '\n' ) { + in.bump_to_next_line(); + p.first = true; + } + else if( ( a == '\r' ) && ( p.second > 1 ) && ( in.peek_char( 1 ) == '\n' ) ) { + in.bump_to_next_line( 2 ); + p.first = true; + } + } + return p; + } + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/lf_eol.hpp b/include/tao/json/external/pegtl/internal/lf_eol.hpp new file mode 100644 index 00000000..00485c70 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/lf_eol.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LF_EOL_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LF_EOL_HPP + +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct lf_eol + { + static constexpr int ch = '\n'; + + template< typename Input > + static eol_pair match( Input& in ) + { + eol_pair p = { false, in.size( 1 ) }; + if( p.second ) { + if( in.peek_char() == '\n' ) { + in.bump_to_next_line(); + p.first = true; + } + } + return p; + } + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/list.hpp b/include/tao/json/external/pegtl/internal/list.hpp new file mode 100644 index 00000000..fddbc640 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/list.hpp @@ -0,0 +1,27 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LIST_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LIST_HPP + +#include "../config.hpp" + +#include "seq.hpp" +#include "star.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename Rule, typename Sep > + using list = seq< Rule, star< Sep, Rule > >; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/list_must.hpp b/include/tao/json/external/pegtl/internal/list_must.hpp new file mode 100644 index 00000000..c0f9123f --- /dev/null +++ b/include/tao/json/external/pegtl/internal/list_must.hpp @@ -0,0 +1,28 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LIST_MUST_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LIST_MUST_HPP + +#include "../config.hpp" + +#include "must.hpp" +#include "seq.hpp" +#include "star.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename Rule, typename Sep > + using list_must = seq< Rule, star< Sep, must< Rule > > >; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/list_tail.hpp b/include/tao/json/external/pegtl/internal/list_tail.hpp new file mode 100644 index 00000000..9576c8cb --- /dev/null +++ b/include/tao/json/external/pegtl/internal/list_tail.hpp @@ -0,0 +1,28 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LIST_TAIL_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LIST_TAIL_HPP + +#include "../config.hpp" + +#include "list.hpp" +#include "opt.hpp" +#include "seq.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename Rule, typename Sep > + using list_tail = seq< list< Rule, Sep >, opt< Sep > >; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/list_tail_pad.hpp b/include/tao/json/external/pegtl/internal/list_tail_pad.hpp new file mode 100644 index 00000000..9d456d83 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/list_tail_pad.hpp @@ -0,0 +1,30 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LIST_TAIL_PAD_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LIST_TAIL_PAD_HPP + +#include "../config.hpp" + +#include "list.hpp" +#include "opt.hpp" +#include "pad.hpp" +#include "seq.hpp" +#include "star.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename Rule, typename Sep, typename Pad > + using list_tail_pad = seq< list< Rule, pad< Sep, Pad > >, opt< star< Pad >, Sep > >; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/marker.hpp b/include/tao/json/external/pegtl/internal/marker.hpp new file mode 100644 index 00000000..b6252448 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/marker.hpp @@ -0,0 +1,93 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_MARKER_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_MARKER_HPP + +#include "../config.hpp" +#include "../rewind_mode.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename Iterator, rewind_mode M > + class marker + { + public: + static constexpr rewind_mode next_rewind_mode = M; + + explicit marker( const Iterator& ) noexcept + { + } + + marker( marker&& ) noexcept + { + } + + marker( const marker& ) = delete; + void operator=( const marker& ) = delete; + + bool operator()( const bool result ) const noexcept + { + return result; + } + }; + + template< typename Iterator > + class marker< Iterator, rewind_mode::REQUIRED > + { + public: + static constexpr rewind_mode next_rewind_mode = rewind_mode::ACTIVE; + + explicit marker( Iterator& i ) noexcept + : m_saved( i ), + m_input( &i ) + { + } + + marker( marker&& i ) noexcept + : m_saved( i.m_saved ), + m_input( i.m_input ) + { + i.m_input = nullptr; + } + + ~marker() noexcept + { + if( m_input != nullptr ) { + ( *m_input ) = m_saved; + } + } + + marker( const marker& ) = delete; + void operator=( const marker& ) = delete; + + bool operator()( const bool result ) noexcept + { + if( result ) { + m_input = nullptr; + return true; + } + return false; + } + + const Iterator& iterator() const noexcept + { + return m_saved; + } + + private: + const Iterator m_saved; + Iterator* m_input; + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/minus.hpp b/include/tao/json/external/pegtl/internal/minus.hpp new file mode 100644 index 00000000..e4dab285 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/minus.hpp @@ -0,0 +1,69 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_MINUS_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_MINUS_HPP + +#include "../config.hpp" + +#include "skip_control.hpp" + +#include "../apply_mode.hpp" +#include "../memory_input.hpp" +#include "../rewind_mode.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + inline const char* source_pointer( const char* source ) noexcept + { + return source; + } + + inline const char* source_pointer( const std::string& source ) noexcept + { + return source.c_str(); + } + + template< typename R, typename S > + struct minus + { + using analyze_t = typename R::analyze_t; // NOTE: S is currently ignored for analyze(). + + template< apply_mode A, + rewind_mode, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< rewind_mode::REQUIRED >(); + + if( !Control< R >::template match< A, rewind_mode::ACTIVE, Action, Control >( in, st... ) ) { + return false; + } + memory_input< tracking_mode::LAZY, typename Input::eol_t, const char* > i2( m.iterator(), in.current(), source_pointer( in.source() ) ); + + if( !Control< S >::template match< apply_mode::NOTHING, rewind_mode::ACTIVE, Action, Control >( i2, st... ) ) { + return m( true ); + } + return m( !i2.empty() ); + } + }; + + template< typename R, typename S > + struct skip_control< minus< R, S > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/must.hpp b/include/tao/json/external/pegtl/internal/must.hpp new file mode 100644 index 00000000..f3742eab --- /dev/null +++ b/include/tao/json/external/pegtl/internal/must.hpp @@ -0,0 +1,79 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_MUST_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_MUST_HPP + +#include "../config.hpp" + +#include "raise.hpp" +#include "rule_conjunction.hpp" +#include "skip_control.hpp" + +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + // The general case applies must<> to each of the + // rules in the 'Rules' parameter pack individually. + + template< typename... Rules > + struct must + { + using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rules... >; + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + return rule_conjunction< must< Rules >... >::template match< A, M, Action, Control >( in, st... ); + } + }; + + // While in theory the implementation for a single rule could + // be simplified to must< Rule > = sor< Rule, raise< Rule > >, this + // would result in some unnecessary run-time overhead. + + template< typename Rule > + struct must< Rule > + { + using analyze_t = typename Rule::analyze_t; + + template< apply_mode A, + rewind_mode, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + if( !Control< Rule >::template match< A, rewind_mode::DONTCARE, Action, Control >( in, st... ) ) { + raise< Rule >::template match< A, rewind_mode::DONTCARE, Action, Control >( in, st... ); + } + return true; + } + }; + + template< typename... Rules > + struct skip_control< must< Rules... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/not_at.hpp b/include/tao/json/external/pegtl/internal/not_at.hpp new file mode 100644 index 00000000..40c0caff --- /dev/null +++ b/include/tao/json/external/pegtl/internal/not_at.hpp @@ -0,0 +1,62 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_NOT_AT_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_NOT_AT_HPP + +#include "../config.hpp" + +#include "rule_conjunction.hpp" +#include "skip_control.hpp" +#include "trivial.hpp" + +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename... Rules > + struct not_at; + + template<> + struct not_at<> + : trivial< false > + { + }; + + template< typename... Rules > + struct not_at + { + using analyze_t = analysis::generic< analysis::rule_type::OPT, Rules... >; + + template< apply_mode, + rewind_mode, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + const auto m = in.template mark< rewind_mode::REQUIRED >(); + return !rule_conjunction< Rules... >::template match< apply_mode::NOTHING, rewind_mode::ACTIVE, Action, Control >( in, st... ); + } + }; + + template< typename... Rules > + struct skip_control< not_at< Rules... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/one.hpp b/include/tao/json/external/pegtl/internal/one.hpp new file mode 100644 index 00000000..b3b4c3d2 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/one.hpp @@ -0,0 +1,81 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ONE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ONE_HPP + +#include +#include + +#include "../config.hpp" + +#include "bump_help.hpp" +#include "result_on_found.hpp" +#include "skip_control.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename Char > + bool contains( const Char c, const std::initializer_list< Char >& l ) noexcept + { + return std::find( l.begin(), l.end(), c ) != l.end(); + } + + template< result_on_found R, typename Peek, typename Peek::data_t... Cs > + struct one + { + using analyze_t = analysis::generic< analysis::rule_type::ANY >; + + template< typename Input > + static bool match( Input& in ) + { + if( !in.empty() ) { + if( const auto t = Peek::peek( in ) ) { + if( contains( t.data, { Cs... } ) == bool( R ) ) { + bump_help< R, Input, typename Peek::data_t, Cs... >( in, t.size ); + return true; + } + } + } + return false; + } + }; + + template< result_on_found R, typename Peek, typename Peek::data_t C > + struct one< R, Peek, C > + { + using analyze_t = analysis::generic< analysis::rule_type::ANY >; + + template< typename Input > + static bool match( Input& in ) + { + if( !in.empty() ) { + if( const auto t = Peek::peek( in ) ) { + if( ( t.data == C ) == bool( R ) ) { + bump_help< R, Input, typename Peek::data_t, C >( in, t.size ); + return true; + } + } + } + return false; + } + }; + + template< result_on_found R, typename Peek, typename Peek::data_t... Cs > + struct skip_control< one< R, Peek, Cs... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/opt.hpp b/include/tao/json/external/pegtl/internal/opt.hpp new file mode 100644 index 00000000..42d66f56 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/opt.hpp @@ -0,0 +1,67 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_OPT_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_OPT_HPP + +#include + +#include "../config.hpp" + +#include "duseltronik.hpp" +#include "seq.hpp" +#include "skip_control.hpp" +#include "trivial.hpp" + +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename... Rules > + struct opt; + + template<> + struct opt<> + : trivial< true > + { + }; + + template< typename... Rules > + struct opt + { + using analyze_t = analysis::generic< analysis::rule_type::OPT, Rules... >; + + template< apply_mode A, + rewind_mode, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + if( !in.empty() ) { + duseltronik< seq< Rules... >, A, rewind_mode::REQUIRED, Action, Control >::match( in, st... ); + } + return true; + } + }; + + template< typename... Rules > + struct skip_control< opt< Rules... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/pad.hpp b/include/tao/json/external/pegtl/internal/pad.hpp new file mode 100644 index 00000000..d5f9b9c8 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/pad.hpp @@ -0,0 +1,27 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PAD_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PAD_HPP + +#include "../config.hpp" + +#include "seq.hpp" +#include "star.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename Rule, typename Pad1, typename Pad2 = Pad1 > + using pad = seq< star< Pad1 >, Rule, star< Pad2 > >; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/pad_opt.hpp b/include/tao/json/external/pegtl/internal/pad_opt.hpp new file mode 100644 index 00000000..bf125ce1 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/pad_opt.hpp @@ -0,0 +1,28 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PAD_OPT_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PAD_OPT_HPP + +#include "../config.hpp" + +#include "opt.hpp" +#include "seq.hpp" +#include "star.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename Rule, typename Pad > + using pad_opt = seq< star< Pad >, opt< Rule, star< Pad > > >; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/peek_char.hpp b/include/tao/json/external/pegtl/internal/peek_char.hpp new file mode 100644 index 00000000..348c6645 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/peek_char.hpp @@ -0,0 +1,37 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PEEK_CHAR_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PEEK_CHAR_HPP + +#include + +#include "../config.hpp" + +#include "input_pair.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct peek_char + { + using data_t = char; + using pair_t = input_pair< char >; + + template< typename Input > + static pair_t peek( Input& in, const std::size_t o = 0 ) + { + return { in.peek_char( o ), 1 }; + } + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/peek_utf16.hpp b/include/tao/json/external/pegtl/internal/peek_utf16.hpp new file mode 100644 index 00000000..bcfa7c3a --- /dev/null +++ b/include/tao/json/external/pegtl/internal/peek_utf16.hpp @@ -0,0 +1,54 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PEEK_UTF16_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PEEK_UTF16_HPP + +#include + +#include "../config.hpp" + +#include "input_pair.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct peek_utf16 + { + using data_t = char32_t; + using pair_t = input_pair< char32_t >; + + using short_t = std::make_unsigned< char16_t >::type; + + static_assert( sizeof( short_t ) == 2, "expected size 2 for 16bit value" ); + static_assert( sizeof( char16_t ) == 2, "expected size 2 for 16bit value" ); + + template< typename Input > + static pair_t peek( Input& in ) + { + const std::size_t s = in.size( 4 ); + if( s >= 2 ) { + const char32_t t = *reinterpret_cast< const short_t* >( in.current() ); + if( ( t < 0xd800 ) || ( t > 0xdbff ) || ( s < 4 ) ) { + return { t, 2 }; + } + const char32_t u = *reinterpret_cast< const short_t* >( in.current() + 2 ); + if( ( u < 0xdc00 ) || ( u > 0xdfff ) ) { + return { t, 2 }; + } + return { ( ( ( t & 0x03ff ) << 10 ) | ( u & 0x03ff ) ) + 0x10000, 4 }; + } + return { 0, 0 }; + } + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/peek_utf32.hpp b/include/tao/json/external/pegtl/internal/peek_utf32.hpp new file mode 100644 index 00000000..cfcac3dc --- /dev/null +++ b/include/tao/json/external/pegtl/internal/peek_utf32.hpp @@ -0,0 +1,46 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PEEK_UTF32_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PEEK_UTF32_HPP + +#include + +#include "../config.hpp" + +#include "input_pair.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct peek_utf32 + { + using data_t = char32_t; + using pair_t = input_pair< char32_t >; + + static_assert( sizeof( char32_t ) == 4, "expected size 4 for 32bit value" ); + + template< typename Input > + static pair_t peek( Input& in ) + { + const std::size_t s = in.size( 4 ); + if( s >= 4 ) { + const char32_t t = *reinterpret_cast< const char32_t* >( in.current() ); + if( ( 0 <= t ) && ( t <= 0x10ffff ) ) { + return { t, 4 }; + } + } + return { 0, 0 }; + } + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/peek_utf8.hpp b/include/tao/json/external/pegtl/internal/peek_utf8.hpp new file mode 100644 index 00000000..831288f1 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/peek_utf8.hpp @@ -0,0 +1,88 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PEEK_UTF8_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PEEK_UTF8_HPP + +#include "../config.hpp" + +#include "input_pair.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct peek_utf8 + { + using data_t = char32_t; + using pair_t = input_pair< char32_t >; + + template< typename Input > + static pair_t peek( Input& in ) + { + char32_t c0 = in.peek_byte(); + + if( ( c0 & 0x80 ) == 0 ) { + return { c0, 1 }; + } + if( ( c0 & 0xE0 ) == 0xC0 ) { + if( in.size( 2 ) >= 2 ) { + const char32_t c1 = in.peek_byte( 1 ); + if( ( c1 & 0xC0 ) == 0x80 ) { + c0 &= 0x1F; + c0 <<= 6; + c0 |= ( c1 & 0x3F ); + if( c0 >= 0x80 ) { + return { c0, 2 }; + } + } + } + } + else if( ( c0 & 0xF0 ) == 0xE0 ) { + if( in.size( 3 ) >= 3 ) { + const char32_t c1 = in.peek_byte( 1 ); + const char32_t c2 = in.peek_byte( 2 ); + if( ( ( c1 & 0xC0 ) == 0x80 ) && ( ( c2 & 0xC0 ) == 0x80 ) ) { + c0 &= 0x0F; + c0 <<= 6; + c0 |= ( c1 & 0x3F ); + c0 <<= 6; + c0 |= ( c2 & 0x3F ); + if( c0 >= 0x800 ) { + return { c0, 3 }; + } + } + } + } + else if( ( c0 & 0xF8 ) == 0xF0 ) { + if( in.size( 4 ) >= 4 ) { + const char32_t c1 = in.peek_byte( 1 ); + const char32_t c2 = in.peek_byte( 2 ); + const char32_t c3 = in.peek_byte( 3 ); + if( ( ( c1 & 0xC0 ) == 0x80 ) && ( ( c2 & 0xC0 ) == 0x80 ) && ( ( c3 & 0xC0 ) == 0x80 ) ) { + c0 &= 0x07; + c0 <<= 6; + c0 |= ( c1 & 0x3F ); + c0 <<= 6; + c0 |= ( c2 & 0x3F ); + c0 <<= 6; + c0 |= ( c3 & 0x3F ); + if( c0 >= 0x10000 && c0 <= 0x10FFFF ) { + return { c0, 4 }; + } + } + } + } + return { 0, 0 }; + } + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/pegtl_string.hpp b/include/tao/json/external/pegtl/internal/pegtl_string.hpp new file mode 100644 index 00000000..1e9b48ff --- /dev/null +++ b/include/tao/json/external/pegtl/internal/pegtl_string.hpp @@ -0,0 +1,98 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_TAOCPP_JSON_PEGTL_STRING_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_TAOCPP_JSON_PEGTL_STRING_HPP + +#include +#include + +#include "../ascii.hpp" +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + // Inspired by https://github.com/irrequietus/typestring + // Rewritten and reduced to what is needed for the PEGTL + // and to work with Visual Studio 2015. + + namespace internal + { + template< typename, typename, typename, typename, typename, typename, typename, typename > + struct string_join; + + template< template< char... > class S, char... C0s, char... C1s, char... C2s, char... C3s, char... C4s, char... C5s, char... C6s, char... C7s > + struct string_join< S< C0s... >, S< C1s... >, S< C2s... >, S< C3s... >, S< C4s... >, S< C5s... >, S< C6s... >, S< C7s... > > + { + using type = S< C0s..., C1s..., C2s..., C3s..., C4s..., C5s..., C6s..., C7s... >; + }; + + template< template< char... > class S, char, bool > + struct string_at + { + using type = S<>; + }; + + template< template< char... > class S, char C > + struct string_at< S, C, true > + { + using type = S< C >; + }; + + template< typename T, std::size_t S > + struct string_max_length + { + static_assert( S <= 512, "String longer than 512 (excluding terminating \\0)!" ); + using type = T; + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#define TAOCPP_JSON_PEGTL_INTERNAL_EMPTY() +#define TAOCPP_JSON_PEGTL_INTERNAL_DEFER( X ) X TAOCPP_JSON_PEGTL_INTERNAL_EMPTY() +#define TAOCPP_JSON_PEGTL_INTERNAL_EXPAND( ... ) __VA_ARGS__ + +#define TAOCPP_JSON_PEGTL_INTERNAL_STRING_AT( S, x, n ) \ + tao::TAOCPP_JSON_PEGTL_NAMESPACE::internal::string_at< S, ( 0##n < sizeof( x ) ) ? x[ 0##n ] : 0, ( 0##n < sizeof( x ) - 1 ) >::type + +#define TAOCPP_JSON_PEGTL_INTERNAL_JOIN_8( M, S, x, n ) \ + tao::TAOCPP_JSON_PEGTL_NAMESPACE::internal::string_join< TAOCPP_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##0 ), \ + TAOCPP_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##1 ), \ + TAOCPP_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##2 ), \ + TAOCPP_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##3 ), \ + TAOCPP_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##4 ), \ + TAOCPP_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##5 ), \ + TAOCPP_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##6 ), \ + TAOCPP_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##7 ) >::type + +#define TAOCPP_JSON_PEGTL_INTERNAL_STRING_8( S, x, n ) \ + TAOCPP_JSON_PEGTL_INTERNAL_JOIN_8( TAOCPP_JSON_PEGTL_INTERNAL_STRING_AT, S, x, n ) + +#define TAOCPP_JSON_PEGTL_INTERNAL_STRING_64( S, x, n ) \ + TAOCPP_JSON_PEGTL_INTERNAL_JOIN_8( TAOCPP_JSON_PEGTL_INTERNAL_STRING_8, S, x, n ) + +#define TAOCPP_JSON_PEGTL_INTERNAL_STRING_512( S, x, n ) \ + TAOCPP_JSON_PEGTL_INTERNAL_JOIN_8( TAOCPP_JSON_PEGTL_INTERNAL_STRING_64, S, x, n ) + +#define TAOCPP_JSON_PEGTL_INTERNAL_STRING( S, x ) \ + TAOCPP_JSON_PEGTL_INTERNAL_EXPAND( \ + TAOCPP_JSON_PEGTL_INTERNAL_EXPAND( \ + TAOCPP_JSON_PEGTL_INTERNAL_EXPAND( \ + tao::TAOCPP_JSON_PEGTL_NAMESPACE::internal::string_max_length< TAOCPP_JSON_PEGTL_INTERNAL_STRING_512( S, x, ), sizeof( x ) - 1 >::type ) ) ) + +#define TAOCPP_JSON_PEGTL_STRING( x ) \ + TAOCPP_JSON_PEGTL_INTERNAL_STRING( tao::TAOCPP_JSON_PEGTL_NAMESPACE::ascii::string, x ) + +#define TAOCPP_JSON_PEGTL_ISTRING( x ) \ + TAOCPP_JSON_PEGTL_INTERNAL_STRING( tao::TAOCPP_JSON_PEGTL_NAMESPACE::ascii::istring, x ) + +#define TAOCPP_JSON_PEGTL_KEYWORD( x ) \ + TAOCPP_JSON_PEGTL_INTERNAL_STRING( tao::TAOCPP_JSON_PEGTL_NAMESPACE::ascii::keyword, x ) + +#endif diff --git a/include/tao/json/external/pegtl/internal/plus.hpp b/include/tao/json/external/pegtl/internal/plus.hpp new file mode 100644 index 00000000..03a87c81 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/plus.hpp @@ -0,0 +1,61 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PLUS_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PLUS_HPP + +#include + +#include "../config.hpp" + +#include "duseltronik.hpp" +#include "opt.hpp" +#include "seq.hpp" +#include "skip_control.hpp" +#include "star.hpp" + +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + // While plus<> could easily be implemented with + // seq< Rule, Rules ..., star< Rule, Rules ... > > we + // provide an explicit implementation to optimise away + // the otherwise created input mark. + + template< typename Rule, typename... Rules > + struct plus + { + using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rule, Rules..., opt< plus > >; + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + return duseltronik< seq< Rule, Rules... >, A, M, Action, Control >::match( in, st... ) && duseltronik< star< Rule, Rules... >, A, M, Action, Control >::match( in, st... ); + } + }; + + template< typename Rule, typename... Rules > + struct skip_control< plus< Rule, Rules... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/raise.hpp b/include/tao/json/external/pegtl/internal/raise.hpp new file mode 100644 index 00000000..c1eb87ed --- /dev/null +++ b/include/tao/json/external/pegtl/internal/raise.hpp @@ -0,0 +1,57 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RAISE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RAISE_HPP + +#include +#include + +#include "../config.hpp" + +#include "skip_control.hpp" + +#include "../analysis/generic.hpp" +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename T > + struct raise + { + using analyze_t = analysis::generic< analysis::rule_type::ANY >; + + template< apply_mode, + rewind_mode, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + Control< T >::raise( const_cast< const Input& >( in ), st... ); +#if defined( _MSC_VER ) + __assume( false ); // LCOV_EXCL_LINE +#else + std::abort(); // LCOV_EXCL_LINE +#endif + } + }; + + template< typename T > + struct skip_control< raise< T > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/range.hpp b/include/tao/json/external/pegtl/internal/range.hpp new file mode 100644 index 00000000..e88c90de --- /dev/null +++ b/include/tao/json/external/pegtl/internal/range.hpp @@ -0,0 +1,60 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RANGE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RANGE_HPP + +#include "../config.hpp" + +#include "bump_help.hpp" +#include "result_on_found.hpp" +#include "skip_control.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< result_on_found R, typename Peek, typename Peek::data_t Lo, typename Peek::data_t Hi > + struct range + { + using analyze_t = analysis::generic< analysis::rule_type::ANY >; + + template< int Eol > + struct can_match_eol + { + static constexpr bool value = ( ( ( Lo <= Eol ) && ( Eol <= Hi ) ) == bool( R ) ); + }; + + template< typename Input > + static bool match( Input& in ) + { + using eol_t = typename Input::eol_t; + + if( !in.empty() ) { + if( const auto t = Peek::peek( in ) ) { + if( ( ( Lo <= t.data ) && ( t.data <= Hi ) ) == bool( R ) ) { + bump_impl< can_match_eol< eol_t::ch >::value >::bump( in, t.size ); + return true; + } + } + } + return false; + } + }; + + template< result_on_found R, typename Peek, typename Peek::data_t Lo, typename Peek::data_t Hi > + struct skip_control< range< R, Peek, Lo, Hi > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/ranges.hpp b/include/tao/json/external/pegtl/internal/ranges.hpp new file mode 100644 index 00000000..40dcc4b7 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/ranges.hpp @@ -0,0 +1,102 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RANGES_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RANGES_HPP + +#include "../config.hpp" + +#include "bump_help.hpp" +#include "range.hpp" +#include "skip_control.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< int Eol, typename Char, Char... Cs > + struct ranges_impl; + + template< int Eol, typename Char > + struct ranges_impl< Eol, Char > + { + static constexpr bool can_match_eol = false; + + static bool match( const Char ) noexcept + { + return false; + } + }; + + template< int Eol, typename Char, Char Eq > + struct ranges_impl< Eol, Char, Eq > + { + static constexpr bool can_match_eol = ( Eq == Eol ); + + static bool match( const Char c ) noexcept + { + return c == Eq; + } + }; + + template< int Eol, typename Char, Char Lo, Char Hi, Char... Cs > + struct ranges_impl< Eol, Char, Lo, Hi, Cs... > + { + static constexpr bool can_match_eol = ( ( ( Lo <= Eol ) && ( Eol <= Hi ) ) || ranges_impl< Eol, Char, Cs... >::can_match_eol ); + + static bool match( const Char c ) noexcept + { + return ( ( Lo <= c ) && ( c <= Hi ) ) || ranges_impl< Eol, Char, Cs... >::match( c ); + } + }; + + template< typename Peek, typename Peek::data_t... Cs > + struct ranges + { + using analyze_t = analysis::generic< analysis::rule_type::ANY >; + + template< int Eol > + struct can_match_eol + { + static constexpr bool value = ranges_impl< Eol, typename Peek::data_t, Cs... >::can_match_eol; + }; + + template< typename Input > + static bool match( Input& in ) + { + using eol_t = typename Input::eol_t; + + if( !in.empty() ) { + if( const auto t = Peek::peek( in ) ) { + if( ranges_impl< eol_t::ch, typename Peek::data_t, Cs... >::match( t.data ) ) { + bump_impl< can_match_eol< eol_t::ch >::value >::bump( in, t.size ); + return true; + } + } + } + return false; + } + }; + + template< typename Peek, typename Peek::data_t Lo, typename Peek::data_t Hi > + struct ranges< Peek, Lo, Hi > + : range< result_on_found::SUCCESS, Peek, Lo, Hi > + { + }; + + template< typename Peek, typename Peek::data_t... Cs > + struct skip_control< ranges< Peek, Cs... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/rep.hpp b/include/tao/json/external/pegtl/internal/rep.hpp new file mode 100644 index 00000000..255de231 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/rep.hpp @@ -0,0 +1,75 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REP_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REP_HPP + +#include "../config.hpp" + +#include "rule_conjunction.hpp" +#include "skip_control.hpp" +#include "trivial.hpp" + +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/counted.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< unsigned Num, typename... Rules > + struct rep; + + template< unsigned Num > + struct rep< Num > + : trivial< true > + { + }; + + template< typename Rule, typename... Rules > + struct rep< 0, Rule, Rules... > + : trivial< true > + { + }; + + template< unsigned Num, typename... Rules > + struct rep + { + using analyze_t = analysis::counted< analysis::rule_type::SEQ, Num, Rules... >; + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< M >(); + using m_t = decltype( m ); + + for( unsigned i = 0; i != Num; ++i ) { + if( !rule_conjunction< Rules... >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) ) { + return false; + } + } + return m( true ); + } + }; + + template< unsigned Num, typename... Rules > + struct skip_control< rep< Num, Rules... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/rep_min.hpp b/include/tao/json/external/pegtl/internal/rep_min.hpp new file mode 100644 index 00000000..04ede5be --- /dev/null +++ b/include/tao/json/external/pegtl/internal/rep_min.hpp @@ -0,0 +1,28 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REP_MIN_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REP_MIN_HPP + +#include "../config.hpp" + +#include "rep.hpp" +#include "seq.hpp" +#include "star.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< unsigned Min, typename Rule, typename... Rules > + using rep_min = seq< rep< Min, Rule, Rules... >, star< Rule, Rules... > >; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/rep_min_max.hpp b/include/tao/json/external/pegtl/internal/rep_min_max.hpp new file mode 100644 index 00000000..343df844 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/rep_min_max.hpp @@ -0,0 +1,88 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REP_MIN_MAX_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REP_MIN_MAX_HPP + +#include + +#include "../config.hpp" + +#include "duseltronik.hpp" +#include "not_at.hpp" +#include "rule_conjunction.hpp" +#include "seq.hpp" +#include "skip_control.hpp" +#include "trivial.hpp" + +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/counted.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< unsigned Min, unsigned Max, typename... Rules > + struct rep_min_max; + + template< unsigned Min, unsigned Max > + struct rep_min_max< Min, Max > + : trivial< false > + { + static_assert( Min <= Max, "invalid rep_min_max rule (maximum number of repetitions smaller than minimum)" ); + }; + + template< typename Rule, typename... Rules > + struct rep_min_max< 0, 0, Rule, Rules... > + : not_at< Rule, Rules... > + { + }; + + template< unsigned Min, unsigned Max, typename... Rules > + struct rep_min_max + { + using analyze_t = analysis::counted< analysis::rule_type::SEQ, Min, Rules... >; + + static_assert( Min <= Max, "invalid rep_min_max rule (maximum number of repetitions smaller than minimum)" ); + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< M >(); + using m_t = decltype( m ); + + for( unsigned i = 0; i != Min; ++i ) { + if( !rule_conjunction< Rules... >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) ) { + return false; + } + } + for( unsigned i = Min; i != Max; ++i ) { + if( !duseltronik< seq< Rules... >, A, rewind_mode::REQUIRED, Action, Control >::match( in, st... ) ) { + return m( true ); + } + } + return m( duseltronik< not_at< Rules... >, A, m_t::next_rewind_mode, Action, Control >::match( in, st... ) ); // NOTE that not_at<> will always rewind. + } + }; + + template< unsigned Min, unsigned Max, typename... Rules > + struct skip_control< rep_min_max< Min, Max, Rules... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/rep_opt.hpp b/include/tao/json/external/pegtl/internal/rep_opt.hpp new file mode 100644 index 00000000..00e31a27 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/rep_opt.hpp @@ -0,0 +1,54 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REP_OPT_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REP_OPT_HPP + +#include "../config.hpp" + +#include "duseltronik.hpp" +#include "seq.hpp" +#include "skip_control.hpp" + +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< unsigned Max, typename... Rules > + struct rep_opt + { + using analyze_t = analysis::generic< analysis::rule_type::OPT, Rules... >; + + template< apply_mode A, + rewind_mode, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + for( unsigned i = 0; ( i != Max ) && duseltronik< seq< Rules... >, A, rewind_mode::REQUIRED, Action, Control >::match( in, st... ); ++i ) { + } + return true; + } + }; + + template< unsigned Max, typename... Rules > + struct skip_control< rep_opt< Max, Rules... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/require.hpp b/include/tao/json/external/pegtl/internal/require.hpp new file mode 100644 index 00000000..9c2b696b --- /dev/null +++ b/include/tao/json/external/pegtl/internal/require.hpp @@ -0,0 +1,52 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REQUIRE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REQUIRE_HPP + +#include "../config.hpp" + +#include "skip_control.hpp" +#include "trivial.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< unsigned Amount > + struct require; + + template<> + struct require< 0 > + : trivial< true > + { + }; + + template< unsigned Amount > + struct require + { + using analyze_t = analysis::generic< analysis::rule_type::OPT >; + + template< typename Input > + static bool match( Input& in ) + { + return in.size( Amount ) >= Amount; + } + }; + + template< unsigned Amount > + struct skip_control< require< Amount > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/result_on_found.hpp b/include/tao/json/external/pegtl/internal/result_on_found.hpp new file mode 100644 index 00000000..cc2fe927 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/result_on_found.hpp @@ -0,0 +1,27 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RESULT_ON_FOUND_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RESULT_ON_FOUND_HPP + +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + enum class result_on_found : bool + { + SUCCESS = true, + FAILURE = false + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/rule_conjunction.hpp b/include/tao/json/external/pegtl/internal/rule_conjunction.hpp new file mode 100644 index 00000000..d1e0cda2 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/rule_conjunction.hpp @@ -0,0 +1,63 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RULE_CONJUNCTION_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RULE_CONJUNCTION_HPP + +#include "../apply_mode.hpp" +#include "../config.hpp" +#include "../rewind_mode.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename... Rules > + struct rule_conjunction; + + template<> + struct rule_conjunction<> + { + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input&, States&&... ) + { + return true; + } + }; + + template< typename... Rules > + struct rule_conjunction + { + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { +#ifdef __cpp_fold_expressions + return ( Control< Rules >::template match< A, M, Action, Control >( in, st... ) && ... ); +#else + bool result = true; + using swallow = bool[]; + (void)swallow{ result = result && Control< Rules >::template match< A, M, Action, Control >( in, st... )... }; + return result; +#endif + } + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/rules.hpp b/include/tao/json/external/pegtl/internal/rules.hpp new file mode 100644 index 00000000..7fa41c9f --- /dev/null +++ b/include/tao/json/external/pegtl/internal/rules.hpp @@ -0,0 +1,61 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RULES_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RULES_HPP + +#include "action.hpp" +#include "alnum.hpp" +#include "alpha.hpp" +#include "any.hpp" +#include "apply.hpp" +#include "apply0.hpp" +#include "at.hpp" +#include "bof.hpp" +#include "bol.hpp" +#include "bytes.hpp" +#include "control.hpp" +#include "disable.hpp" +#include "discard.hpp" +#include "enable.hpp" +#include "eof.hpp" +#include "eol.hpp" +#include "eolf.hpp" +#include "identifier.hpp" +#include "if_apply.hpp" +#include "if_must.hpp" +#include "if_must_else.hpp" +#include "if_then_else.hpp" +#include "istring.hpp" +#include "list.hpp" +#include "list_must.hpp" +#include "list_tail.hpp" +#include "list_tail_pad.hpp" +#include "minus.hpp" +#include "must.hpp" +#include "not_at.hpp" +#include "one.hpp" +#include "opt.hpp" +#include "pad.hpp" +#include "pad_opt.hpp" +#include "plus.hpp" +#include "raise.hpp" +#include "range.hpp" +#include "ranges.hpp" +#include "rep.hpp" +#include "rep_min.hpp" +#include "rep_min_max.hpp" +#include "rep_opt.hpp" +#include "require.hpp" +#include "seq.hpp" +#include "skip_control.hpp" +#include "sor.hpp" +#include "star.hpp" +#include "star_must.hpp" +#include "state.hpp" +#include "string.hpp" +#include "trivial.hpp" +#include "try_catch_type.hpp" +#include "until.hpp" + +#endif diff --git a/include/tao/json/external/pegtl/internal/seq.hpp b/include/tao/json/external/pegtl/internal/seq.hpp new file mode 100644 index 00000000..142d4109 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/seq.hpp @@ -0,0 +1,80 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_SEQ_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_SEQ_HPP + +#include "../config.hpp" + +#include "rule_conjunction.hpp" +#include "skip_control.hpp" +#include "trivial.hpp" + +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename... Rules > + struct seq; + + template<> + struct seq<> + : trivial< true > + { + }; + + template< typename Rule > + struct seq< Rule > + { + using analyze_t = typename Rule::analyze_t; + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + return Control< Rule >::template match< A, M, Action, Control >( in, st... ); + } + }; + + template< typename... Rules > + struct seq + { + using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rules... >; + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< M >(); + using m_t = decltype( m ); + return m( rule_conjunction< Rules... >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) ); + } + }; + + template< typename... Rules > + struct skip_control< seq< Rules... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/skip_control.hpp b/include/tao/json/external/pegtl/internal/skip_control.hpp new file mode 100644 index 00000000..4c1f71fb --- /dev/null +++ b/include/tao/json/external/pegtl/internal/skip_control.hpp @@ -0,0 +1,35 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_SKIP_CONTROL_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_SKIP_CONTROL_HPP + +#include + +#include "../config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + // This class is a simple tagging mechanism. + // By default, skip_control< Rule >::value + // is 'false'. Each internal (!) rule that should + // be hidden from the control and action class' + // callbacks simply specializes skip_control<> + // to return 'true' for the above expression. + + template< typename Rule > + struct skip_control : std::false_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/sor.hpp b/include/tao/json/external/pegtl/internal/sor.hpp new file mode 100644 index 00000000..684107f1 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/sor.hpp @@ -0,0 +1,74 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_SOR_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_SOR_HPP + +#include "../config.hpp" + +#include "skip_control.hpp" + +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/generic.hpp" + +#include "integer_sequence.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename... Rules > + struct sor; + + template<> + struct sor<> + : trivial< false > + { + }; + + template< typename... Rules > + struct sor + : sor< index_sequence_for< Rules... >, Rules... > + { + }; + + template< std::size_t... Indices, typename... Rules > + struct sor< index_sequence< Indices... >, Rules... > + { + using analyze_t = analysis::generic< analysis::rule_type::SOR, Rules... >; + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { +#ifdef __cpp_fold_expressions + return ( Control< Rules >::template match < A, ( Indices == ( sizeof...( Rules ) - 1 ) ) ? M : rewind_mode::REQUIRED, Action, Control > ( in, st... ) || ... ); +#else + bool result = false; + using swallow = bool[]; + (void)swallow{ result = result || Control< Rules >::template match < A, ( Indices == ( sizeof...( Rules ) - 1 ) ) ? M : rewind_mode::REQUIRED, Action, Control > ( in, st... )... }; + return result; +#endif + } + }; + + template< typename... Rules > + struct skip_control< sor< Rules... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/star.hpp b/include/tao/json/external/pegtl/internal/star.hpp new file mode 100644 index 00000000..da771cee --- /dev/null +++ b/include/tao/json/external/pegtl/internal/star.hpp @@ -0,0 +1,56 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_STAR_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_STAR_HPP + +#include + +#include "../config.hpp" + +#include "duseltronik.hpp" +#include "seq.hpp" +#include "skip_control.hpp" + +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename Rule, typename... Rules > + struct star + { + using analyze_t = analysis::generic< analysis::rule_type::OPT, Rule, Rules..., star >; + + template< apply_mode A, + rewind_mode, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + while( duseltronik< seq< Rule, Rules... >, A, rewind_mode::REQUIRED, Action, Control >::match( in, st... ) ) { + } + return true; + } + }; + + template< typename Rule, typename... Rules > + struct skip_control< star< Rule, Rules... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/star_must.hpp b/include/tao/json/external/pegtl/internal/star_must.hpp new file mode 100644 index 00000000..19584b98 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/star_must.hpp @@ -0,0 +1,27 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_STAR_MUST_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_STAR_MUST_HPP + +#include "../config.hpp" + +#include "if_must.hpp" +#include "star.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename Cond, typename... Rules > + using star_must = star< if_must< Cond, Rules... > >; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/state.hpp b/include/tao/json/external/pegtl/internal/state.hpp new file mode 100644 index 00000000..92bfd3b9 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/state.hpp @@ -0,0 +1,83 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_STATE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_STATE_HPP + +#include "../config.hpp" + +#include "duseltronik.hpp" +#include "seq.hpp" +#include "skip_control.hpp" + +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename State, typename... Rules > + struct state + { + using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rules... >; + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static auto success( State& s, const Input& in, States&&... st ) -> decltype( s.template success< A, M, Action, Control >( in, st... ), void() ) + { + s.template success< A, M, Action, Control >( in, st... ); + } + + // NOTE: The additional "int = 0" is a work-around for missing expression SFINAE in VS2015. + + template< apply_mode, + rewind_mode, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States, + int = 0 > + static auto success( State& s, const Input& in, States&&... st ) -> decltype( s.success( in, st... ), void() ) + { + s.success( in, st... ); + } + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + State s( const_cast< const Input& >( in ), st... ); + + if( duseltronik< seq< Rules... >, A, M, Action, Control >::match( in, s ) ) { + success< A, M, Action, Control >( s, in, st... ); + return true; + } + return false; + } + }; + + template< typename State, typename... Rules > + struct skip_control< state< State, Rules... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/string.hpp b/include/tao/json/external/pegtl/internal/string.hpp new file mode 100644 index 00000000..3ca15f04 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/string.hpp @@ -0,0 +1,68 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_STRING_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_STRING_HPP + +#include +#include + +#include "../config.hpp" + +#include "bump_help.hpp" +#include "result_on_found.hpp" +#include "skip_control.hpp" +#include "trivial.hpp" + +#include "../analysis/counted.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + inline bool unsafe_equals( const char* s, const std::initializer_list< char >& l ) noexcept + { + return std::memcmp( s, &*l.begin(), l.size() ) == 0; + } + + template< char... Cs > + struct string; + + template<> + struct string<> + : trivial< true > + { + }; + + template< char... Cs > + struct string + { + using analyze_t = analysis::counted< analysis::rule_type::ANY, sizeof...( Cs ) >; + + template< typename Input > + static bool match( Input& in ) + { + if( in.size( sizeof...( Cs ) ) >= sizeof...( Cs ) ) { + if( unsafe_equals( in.current(), { Cs... } ) ) { + bump_help< result_on_found::SUCCESS, Input, char, Cs... >( in, sizeof...( Cs ) ); + return true; + } + } + return false; + } + }; + + template< char... Cs > + struct skip_control< string< Cs... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/trivial.hpp b/include/tao/json/external/pegtl/internal/trivial.hpp new file mode 100644 index 00000000..3e4de6e3 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/trivial.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_TRIVIAL_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_TRIVIAL_HPP + +#include "../config.hpp" + +#include "skip_control.hpp" + +#include "../analysis/counted.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< bool Result > + struct trivial + { + using analyze_t = analysis::counted< analysis::rule_type::ANY, unsigned( !Result ) >; + + template< typename Input > + static bool match( Input& ) noexcept + { + return Result; + } + }; + + template< bool Result > + struct skip_control< trivial< Result > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/try_catch_type.hpp b/include/tao/json/external/pegtl/internal/try_catch_type.hpp new file mode 100644 index 00000000..c04e094e --- /dev/null +++ b/include/tao/json/external/pegtl/internal/try_catch_type.hpp @@ -0,0 +1,72 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_TRY_CATCH_TYPE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_TRY_CATCH_TYPE_HPP + +#include + +#include "../config.hpp" + +#include "duseltronik.hpp" +#include "seq.hpp" +#include "skip_control.hpp" +#include "trivial.hpp" + +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename Exception, typename... Rules > + struct try_catch_type; + + template< typename Exception > + struct try_catch_type< Exception > + : trivial< true > + { + }; + + template< typename Exception, typename... Rules > + struct try_catch_type + { + using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rules... >; + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< M >(); + using m_t = decltype( m ); + + try { + return m( duseltronik< seq< Rules... >, A, m_t::next_rewind_mode, Action, Control >::match( in, st... ) ); + } + catch( const Exception& ) { + return false; + } + } + }; + + template< typename Exception, typename... Rules > + struct skip_control< try_catch_type< Exception, Rules... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/internal/until.hpp b/include/tao/json/external/pegtl/internal/until.hpp new file mode 100644 index 00000000..e2563d34 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/until.hpp @@ -0,0 +1,91 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_UNTIL_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_UNTIL_HPP + +#include "../config.hpp" + +#include "bytes.hpp" +#include "eof.hpp" +#include "not_at.hpp" +#include "rule_conjunction.hpp" +#include "skip_control.hpp" +#include "star.hpp" + +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/generic.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< typename Cond, typename... Rules > + struct until; + + template< typename Cond > + struct until< Cond > + { + using analyze_t = analysis::generic< analysis::rule_type::SEQ, star< not_at< Cond >, not_at< eof >, bytes< 1 > >, Cond >; + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< M >(); + + while( !Control< Cond >::template match< A, rewind_mode::REQUIRED, Action, Control >( in, st... ) ) { + if( in.empty() ) { + return false; + } + in.bump(); + } + return m( true ); + } + }; + + template< typename Cond, typename... Rules > + struct until + { + using analyze_t = analysis::generic< analysis::rule_type::SEQ, star< not_at< Cond >, not_at< eof >, Rules... >, Cond >; + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< M >(); + using m_t = decltype( m ); + + while( !Control< Cond >::template match< A, rewind_mode::REQUIRED, Action, Control >( in, st... ) ) { + if( in.empty() || ( !rule_conjunction< Rules... >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) ) ) { + return false; + } + } + return m( true ); + } + }; + + template< typename Cond, typename... Rules > + struct skip_control< until< Cond, Rules... > > : std::true_type + { + }; + + } // namespace internal + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/istream_input.hpp b/include/tao/json/external/pegtl/istream_input.hpp new file mode 100644 index 00000000..745603c7 --- /dev/null +++ b/include/tao/json/external/pegtl/istream_input.hpp @@ -0,0 +1,34 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ISTREAM_INPUT_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_ISTREAM_INPUT_HPP + +#include + +#include "buffer_input.hpp" +#include "config.hpp" +#include "eol.hpp" + +#include "internal/istream_reader.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + template< typename Eol = eol::lf_crlf > + struct istream_input + : buffer_input< internal::istream_reader, Eol > + { + template< typename T > + istream_input( std::istream& in_stream, const std::size_t in_maximum, T&& in_source ) + : buffer_input< internal::istream_reader, Eol >( std::forward< T >( in_source ), in_maximum, in_stream ) + { + } + }; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/memory_input.hpp b/include/tao/json/external/pegtl/memory_input.hpp new file mode 100644 index 00000000..d16f572f --- /dev/null +++ b/include/tao/json/external/pegtl/memory_input.hpp @@ -0,0 +1,285 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_MEMORY_INPUT_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_MEMORY_INPUT_HPP + +#include +#include +#include +#include +#include + +#include "config.hpp" +#include "eol.hpp" +#include "position.hpp" +#include "tracking_mode.hpp" + +#include "internal/action_input.hpp" +#include "internal/bump_impl.hpp" +#include "internal/iterator.hpp" +#include "internal/marker.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + template< tracking_mode, typename Eol, typename Source > + class memory_input_base; + + template< typename Eol, typename Source > + class memory_input_base< tracking_mode::IMMEDIATE, Eol, Source > + { + public: + using iterator_t = internal::iterator; + + template< typename T > + memory_input_base( const iterator_t& in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value ) + : m_current( in_begin ), + m_end( in_end ), + m_source( std::forward< T >( in_source ) ) + { + } + + template< typename T > + memory_input_base( const char* in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value ) + : m_current( in_begin ), + m_end( in_end ), + m_source( std::forward< T >( in_source ) ) + { + } + + memory_input_base( const memory_input_base& ) = delete; + memory_input_base operator=( const memory_input_base& ) = delete; + + const char* current() const noexcept + { + return m_current.data; + } + + const char* end( const std::size_t = 0 ) const noexcept + { + return m_end; + } + + std::size_t byte() const noexcept + { + return m_current.byte; + } + + std::size_t line() const noexcept + { + return m_current.line; + } + + std::size_t byte_in_line() const noexcept + { + return m_current.byte_in_line; + } + + void bump( const std::size_t in_count = 1 ) noexcept + { + internal::bump( m_current, in_count, Eol::ch ); + } + + void bump_in_this_line( const std::size_t in_count = 1 ) noexcept + { + internal::bump_in_this_line( m_current, in_count ); + } + + void bump_to_next_line( const std::size_t in_count = 1 ) noexcept + { + internal::bump_to_next_line( m_current, in_count ); + } + + TAOCPP_JSON_PEGTL_NAMESPACE::position position( const iterator_t& it ) const + { + return TAOCPP_JSON_PEGTL_NAMESPACE::position( it, m_source ); + } + + protected: + iterator_t m_current; + const char* const m_end; + const Source m_source; + }; + + template< typename Eol, typename Source > + class memory_input_base< tracking_mode::LAZY, Eol, Source > + { + public: + using iterator_t = const char*; + + template< typename T > + memory_input_base( const internal::iterator& in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value ) + : m_begin( in_begin ), + m_current( in_begin.data ), + m_end( in_end ), + m_source( std::forward< T >( in_source ) ) + { + } + + template< typename T > + memory_input_base( const char* in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value ) + : m_begin( in_begin ), + m_current( in_begin ), + m_end( in_end ), + m_source( std::forward< T >( in_source ) ) + { + } + + memory_input_base( const memory_input_base& ) = delete; + memory_input_base operator=( const memory_input_base& ) = delete; + + const char* current() const noexcept + { + return m_current; + } + + const char* end( const std::size_t = 0 ) const noexcept + { + return m_end; + } + + std::size_t byte() const noexcept + { + return std::size_t( current() - m_begin.data ); + } + + void bump( const std::size_t in_count = 1 ) noexcept + { + m_current += in_count; + } + + void bump_in_this_line( const std::size_t in_count = 1 ) noexcept + { + m_current += in_count; + } + + void bump_to_next_line( const std::size_t in_count = 1 ) noexcept + { + m_current += in_count; + } + + TAOCPP_JSON_PEGTL_NAMESPACE::position position( const iterator_t it ) const + { + internal::iterator c( m_begin ); + internal::bump( c, std::size_t( it - m_begin.data ), Eol::ch ); + return TAOCPP_JSON_PEGTL_NAMESPACE::position( c, m_source ); + } + + protected: + const internal::iterator m_begin; + iterator_t m_current; + const char* const m_end; + const Source m_source; + }; + + } // namespace internal + + template< tracking_mode P = tracking_mode::IMMEDIATE, typename Eol = eol::lf_crlf, typename Source = std::string > + class memory_input + : public internal::memory_input_base< P, Eol, Source > + { + public: + static constexpr tracking_mode tracking_mode_v = P; + + using eol_t = Eol; + using source_t = Source; + + using typename internal::memory_input_base< P, Eol, Source >::iterator_t; + + using action_t = internal::action_input< memory_input >; + + using internal::memory_input_base< P, Eol, Source >::memory_input_base; + + template< typename T > + memory_input( const char* in_begin, const std::size_t in_size, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value ) + : memory_input( in_begin, in_begin + in_size, std::forward< T >( in_source ) ) + { + } + + template< typename T > + memory_input( const std::string& in_string, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value ) + : memory_input( in_string.data(), in_string.size(), std::forward< T >( in_source ) ) + { + } + + template< typename T > + memory_input( const char* in_begin, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value ) + : memory_input( in_begin, std::strlen( in_begin ), std::forward< T >( in_source ) ) + { + } + + template< typename T > + memory_input( const char* in_begin, const char* in_end, T&& in_source, const std::size_t in_byte, const std::size_t in_line, const std::size_t in_byte_in_line ) noexcept( std::is_nothrow_constructible< Source, T&& >::value ) + : memory_input( { in_begin, in_byte, in_line, in_byte_in_line }, in_end, std::forward< T >( in_source ) ) + { + } + + memory_input( const memory_input& ) = delete; + memory_input operator=( const memory_input& ) = delete; + + const Source& source() const noexcept + { + return this->m_source; + } + + bool empty() const noexcept + { + return this->current() == this->end(); + } + + std::size_t size( const std::size_t = 0 ) const noexcept + { + return std::size_t( this->end() - this->current() ); + } + + char peek_char( const std::size_t offset = 0 ) const noexcept + { + return this->current()[ offset ]; + } + + unsigned char peek_byte( const std::size_t offset = 0 ) const noexcept + { + return static_cast< unsigned char >( peek_char( offset ) ); + } + + iterator_t& iterator() noexcept + { + return this->m_current; + } + + const iterator_t& iterator() const noexcept + { + return this->m_current; + } + + using internal::memory_input_base< P, Eol, Source >::position; + + TAOCPP_JSON_PEGTL_NAMESPACE::position position() const + { + return position( iterator() ); + } + + void discard() const noexcept + { + } + + void require( const std::size_t ) const noexcept + { + } + + template< rewind_mode M > + internal::marker< iterator_t, M > mark() noexcept + { + return internal::marker< iterator_t, M >( iterator() ); + } + }; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/mmap_input.hpp b/include/tao/json/external/pegtl/mmap_input.hpp new file mode 100644 index 00000000..25dc9c85 --- /dev/null +++ b/include/tao/json/external/pegtl/mmap_input.hpp @@ -0,0 +1,55 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_MMAP_INPUT_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_MMAP_INPUT_HPP + +#include +#include + +#include "config.hpp" +#include "eol.hpp" +#include "memory_input.hpp" +#include "tracking_mode.hpp" + +#include "internal/file_mapper.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct mmap_holder + { + const std::string filename; + const file_mapper data; + + template< typename T > + mmap_holder( T&& in_filename ) + : filename( std::forward< T >( in_filename ) ), + data( filename.c_str() ) + { + } + }; + + } // namespace internal + + template< tracking_mode P = tracking_mode::IMMEDIATE, typename Eol = eol::lf_crlf > + struct mmap_input + : private internal::mmap_holder, + public memory_input< P, Eol, const char* > + { + template< typename T > + explicit mmap_input( T&& in_filename ) + : internal::mmap_holder( std::forward< T >( in_filename ) ), + memory_input< P, Eol, const char* >( data.begin(), data.end(), filename.c_str() ) + { + } + }; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/normal.hpp b/include/tao/json/external/pegtl/normal.hpp new file mode 100644 index 00000000..2209d93f --- /dev/null +++ b/include/tao/json/external/pegtl/normal.hpp @@ -0,0 +1,89 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_NORMAL_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_NORMAL_HPP + +#include + +#include "apply_mode.hpp" +#include "config.hpp" +#include "nothing.hpp" +#include "parse_error.hpp" +#include "rewind_mode.hpp" + +#include "internal/demangle.hpp" +#include "internal/dusel_mode.hpp" +#include "internal/duseltronik.hpp" +#include "internal/has_apply.hpp" +#include "internal/has_apply0.hpp" +#include "internal/skip_control.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + template< typename Rule > + struct normal + { + template< typename Input, typename... States > + static void start( const Input&, States&&... ) noexcept + { + } + + template< typename Input, typename... States > + static void success( const Input&, States&&... ) noexcept + { + } + + template< typename Input, typename... States > + static void failure( const Input&, States&&... ) noexcept + { + } + + template< typename Input, typename... States > + static void raise( const Input& in, States&&... ) + { + throw parse_error( "parse error matching " + internal::demangle< Rule >(), in ); + } + + template< template< typename... > class Action, typename Input, typename... States > + static auto apply0( const Input&, States&&... st ) -> decltype( Action< Rule >::apply0( st... ) ) + { + return Action< Rule >::apply0( st... ); + } + + template< template< typename... > class Action, typename Iterator, typename Input, typename... States > + static auto apply( const Iterator& begin, const Input& in, States&&... st ) -> decltype( Action< Rule >::apply( std::declval< typename Input::action_t >(), st... ) ) + { + using action_t = typename Input::action_t; + const action_t action_input( begin, in ); + return Action< Rule >::apply( action_input, st... ); + } + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + constexpr char use_control = !internal::skip_control< Rule >::value; + constexpr char use_action = use_control && ( A == apply_mode::ACTION ) && ( !is_nothing< Action, Rule >::value ); + constexpr char use_apply_void = use_action && internal::has_apply< Action< Rule >, void, typename Input::action_t, States... >::value; + constexpr char use_apply_bool = use_action && internal::has_apply< Action< Rule >, bool, typename Input::action_t, States... >::value; + constexpr char use_apply0_void = use_action && internal::has_apply0< Action< Rule >, void, States... >::value; + constexpr char use_apply0_bool = use_action && internal::has_apply0< Action< Rule >, bool, States... >::value; + static_assert( use_apply_void + use_apply_bool + use_apply0_void + use_apply0_bool < 2, "more than one apply or apply0 defined" ); + static_assert( !use_action || use_apply_bool || use_apply_void || use_apply0_bool || use_apply0_void, "actions not disabled but no apply or apply0 found" ); + constexpr dusel_mode mode = static_cast< dusel_mode >( use_control + use_apply_void + 2 * use_apply_bool + 3 * use_apply0_void + 4 * use_apply0_bool ); + return internal::duseltronik< Rule, A, M, Action, Control, mode >::match( in, st... ); + } + }; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/nothing.hpp b/include/tao/json/external/pegtl/nothing.hpp new file mode 100644 index 00000000..61aee1d8 --- /dev/null +++ b/include/tao/json/external/pegtl/nothing.hpp @@ -0,0 +1,27 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_NOTHING_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_NOTHING_HPP + +#include + +#include "config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + template< typename Rule > + struct nothing + { + }; + + template< template< typename... > class Action, typename Rule > + using is_nothing = std::is_base_of< nothing< Rule >, Action< Rule > >; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/parse.hpp b/include/tao/json/external/pegtl/parse.hpp new file mode 100644 index 00000000..b1f7d0b5 --- /dev/null +++ b/include/tao/json/external/pegtl/parse.hpp @@ -0,0 +1,53 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_PARSE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_PARSE_HPP + +#include "apply_mode.hpp" +#include "config.hpp" +#include "normal.hpp" +#include "nothing.hpp" +#include "parse_error.hpp" +#include "rewind_mode.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + template< typename Rule, + template< typename... > class Action = nothing, + template< typename... > class Control = normal, + apply_mode A = apply_mode::ACTION, + rewind_mode M = rewind_mode::REQUIRED, + typename Input, + typename... States > + bool parse( Input&& in, States&&... st ) + { + return Control< Rule >::template match< A, M, Action, Control >( in, st... ); + } + + template< typename Rule, + template< typename... > class Action = nothing, + template< typename... > class Control = normal, + apply_mode A = apply_mode::ACTION, + rewind_mode M = rewind_mode::REQUIRED, + typename Outer, + typename Input, + typename... States > + bool parse_nested( const Outer& oi, Input&& in, States&&... st ) + { + try { + return parse< Rule, Action, Control, A, M >( in, st... ); + } + catch( parse_error& e ) { + e.positions.push_back( oi.position() ); + throw; + } + } + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/parse_error.hpp b/include/tao/json/external/pegtl/parse_error.hpp new file mode 100644 index 00000000..eee75c00 --- /dev/null +++ b/include/tao/json/external/pegtl/parse_error.hpp @@ -0,0 +1,45 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_PARSE_ERROR_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_PARSE_ERROR_HPP + +#include +#include + +#include "config.hpp" +#include "position.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + struct parse_error + : public std::runtime_error + { + parse_error( const std::string& msg, std::vector< position >&& in_positions ) + : std::runtime_error( msg ), + positions( std::move( in_positions ) ) + { + } + + template< typename Input > + parse_error( const std::string& msg, const Input& in ) + : parse_error( msg, in.position() ) + { + } + + parse_error( const std::string& msg, const position& pos ) + : std::runtime_error( to_string( pos ) + ": " + msg ), + positions( 1, pos ) + { + } + + std::vector< position > positions; + }; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/position.hpp b/include/tao/json/external/pegtl/position.hpp new file mode 100644 index 00000000..72ac1e33 --- /dev/null +++ b/include/tao/json/external/pegtl/position.hpp @@ -0,0 +1,54 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_POSITION_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_POSITION_HPP + +#include +#include +#include +#include +#include + +#include "config.hpp" + +#include "internal/iterator.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + struct position + { + template< typename T > + position( const internal::iterator& in_iter, T&& in_source ) + : byte( in_iter.byte ), + line( in_iter.line ), + byte_in_line( in_iter.byte_in_line ), + source( std::forward< T >( in_source ) ) + { + } + + std::size_t byte; + std::size_t line; + std::size_t byte_in_line; + std::string source; + }; + + inline std::ostream& operator<<( std::ostream& o, const position& p ) + { + return o << p.source << ':' << p.line << ':' << p.byte_in_line << '(' << p.byte << ')'; + } + + inline std::string to_string( const position& p ) + { + std::ostringstream o; + o << p; + return o.str(); + } + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/read_input.hpp b/include/tao/json/external/pegtl/read_input.hpp new file mode 100644 index 00000000..bc6b4fe8 --- /dev/null +++ b/include/tao/json/external/pegtl/read_input.hpp @@ -0,0 +1,52 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_READ_INPUT_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_READ_INPUT_HPP + +#include + +#include "config.hpp" +#include "eol.hpp" +#include "string_input.hpp" +#include "tracking_mode.hpp" + +#include "internal/file_reader.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct filename_holder + { + const std::string filename; + + template< typename T > + explicit filename_holder( T&& in_filename ) + : filename( std::forward< T >( in_filename ) ) + { + } + }; + + } // namespace internal + + template< tracking_mode P = tracking_mode::IMMEDIATE, typename Eol = eol::lf_crlf > + struct read_input + : private internal::filename_holder, + public string_input< P, Eol, const char* > + { + template< typename T > + explicit read_input( T&& in_filename ) + : internal::filename_holder( std::forward< T >( in_filename ) ), + string_input< P, Eol, const char* >( internal::file_reader( filename.c_str() ).read(), filename.c_str() ) + { + } + }; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/rewind_mode.hpp b/include/tao/json/external/pegtl/rewind_mode.hpp new file mode 100644 index 00000000..96cd4f58 --- /dev/null +++ b/include/tao/json/external/pegtl/rewind_mode.hpp @@ -0,0 +1,24 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_REWIND_MODE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_REWIND_MODE_HPP + +#include "config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + enum class rewind_mode : char + { + ACTIVE, + REQUIRED, + DONTCARE + }; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/rules.hpp b/include/tao/json/external/pegtl/rules.hpp new file mode 100644 index 00000000..210524cd --- /dev/null +++ b/include/tao/json/external/pegtl/rules.hpp @@ -0,0 +1,69 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_RULES_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_RULES_HPP + +#include "config.hpp" +#include "parse_error.hpp" + +#include "internal/rules.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + // clang-format off + template< typename... Actions > struct apply : internal::apply< Actions... > {}; + template< typename... Actions > struct apply0 : internal::apply0< Actions... > {}; + template< template< typename... > class Action, typename... Rules > struct action : internal::action< Action, Rules... > {}; + template< typename... Rules > struct at : internal::at< Rules... > {}; + struct bof : internal::bof {}; + struct bol : internal::bol {}; + template< unsigned Num > struct bytes : internal::bytes< Num > {}; + template< template< typename... > class Control, typename... Rules > struct control : internal::control< Control, Rules... > {}; + template< typename... Rules > struct disable : internal::disable< Rules... > {}; + struct discard : internal::discard {}; + template< typename... Rules > struct enable : internal::enable< Rules... > {}; + struct eof : internal::eof {}; + struct failure : internal::trivial< false > {}; + template< typename Rule, typename... Actions > struct if_apply : internal::if_apply< Rule, Actions... > {}; + template< typename Cond, typename... Thens > struct if_must : internal::if_must< Cond, Thens... > {}; + template< typename Cond, typename Then, typename Else > struct if_must_else : internal::if_must_else< Cond, Then, Else > {}; + template< typename Cond, typename Then, typename Else > struct if_then_else : internal::if_then_else< Cond, Then, Else > {}; + template< typename Rule, typename Sep, typename Pad = void > struct list : internal::list< Rule, internal::pad< Sep, Pad > > {}; + template< typename Rule, typename Sep > struct list< Rule, Sep, void > : internal::list< Rule, Sep > {}; + template< typename Rule, typename Sep, typename Pad = void > struct list_must : internal::list_must< Rule, internal::pad< Sep, Pad > > {}; + template< typename Rule, typename Sep > struct list_must< Rule, Sep, void > : internal::list_must< Rule, Sep > {}; + template< typename Rule, typename Sep, typename Pad = void > struct list_tail : internal::list_tail_pad< Rule, Sep, Pad > {}; + template< typename Rule, typename Sep > struct list_tail< Rule, Sep, void > : internal::list_tail< Rule, Sep > {}; + template< typename M, typename S > struct minus : internal::minus< M, S > {}; + template< typename... Rules > struct must : internal::must< Rules... > {}; + template< typename... Rules > struct not_at : internal::not_at< Rules... > {}; + template< typename... Rules > struct opt : internal::opt< Rules... > {}; + template< typename Rule, typename Pad1, typename Pad2 = Pad1 > struct pad : internal::pad< Rule, Pad1, Pad2 > {}; + template< typename Rule, typename Pad > struct pad_opt : internal::pad_opt< Rule, Pad > {}; + template< typename Rule, typename... Rules > struct plus : internal::plus< Rule, Rules... > {}; + template< typename Exception > struct raise : internal::raise< Exception > {}; + template< unsigned Num, typename... Rules > struct rep : internal::rep< Num, Rules... > {}; + template< unsigned Max, typename... Rules > struct rep_max : internal::rep_min_max< 0, Max, Rules... > {}; + template< unsigned Min, typename Rule, typename... Rules > struct rep_min : internal::rep_min< Min, Rule, Rules... > {}; + template< unsigned Min, unsigned Max, typename... Rules > struct rep_min_max : internal::rep_min_max< Min, Max, Rules... > {}; + template< unsigned Max, typename... Rules > struct rep_opt : internal::rep_opt< Max, Rules... > {}; + template< unsigned Amount > struct require : internal::require< Amount > {}; + template< typename... Rules > struct seq : internal::seq< Rules... > {}; + template< typename... Rules > struct sor : internal::sor< Rules... > {}; + template< typename Rule, typename... Rules > struct star : internal::star< Rule, Rules... > {}; + template< typename Cond, typename... Rules > struct star_must : internal::star_must< Cond, Rules... > {}; + template< typename State, typename... Rules > struct state : internal::state< State, Rules... > {}; + struct success : internal::trivial< true > {}; + template< typename... Rules > struct try_catch : internal::try_catch_type< parse_error, Rules... > {}; + template< typename Exception, typename... Rules > struct try_catch_type : internal::try_catch_type< Exception, Rules... > {}; + template< typename Cond, typename... Rules > struct until : internal::until< Cond, Rules... > {}; + // clang-format on + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/string_input.hpp b/include/tao/json/external/pegtl/string_input.hpp new file mode 100644 index 00000000..831e91d3 --- /dev/null +++ b/include/tao/json/external/pegtl/string_input.hpp @@ -0,0 +1,51 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_STRING_INPUT_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_STRING_INPUT_HPP + +#include +#include + +#include "config.hpp" +#include "eol.hpp" +#include "memory_input.hpp" +#include "tracking_mode.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace internal + { + struct string_holder + { + const std::string data; + + template< typename T > + explicit string_holder( T&& in_data ) + : data( std::forward< T >( in_data ) ) + { + } + }; + + } // namespace internal + + template< tracking_mode P = tracking_mode::IMMEDIATE, typename Eol = eol::lf_crlf, typename Source = std::string > + struct string_input + : private internal::string_holder, + public memory_input< P, Eol, Source > + { + template< typename T, typename... Ts > + explicit string_input( T&& in_data, Ts&&... ts ) + : internal::string_holder( std::forward< T >( in_data ) ), + memory_input< P, Eol, Source >( data.data(), data.size(), std::forward< Ts >( ts )... ) + { + } + }; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/tracking_mode.hpp b/include/tao/json/external/pegtl/tracking_mode.hpp new file mode 100644 index 00000000..eea30426 --- /dev/null +++ b/include/tao/json/external/pegtl/tracking_mode.hpp @@ -0,0 +1,23 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_TRACKING_MODE_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_TRACKING_MODE_HPP + +#include "config.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + enum class tracking_mode : bool + { + IMMEDIATE, + LAZY + }; + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/utf16.hpp b/include/tao/json/external/pegtl/utf16.hpp new file mode 100644 index 00000000..da03f2eb --- /dev/null +++ b/include/tao/json/external/pegtl/utf16.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_UTF16_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_UTF16_HPP + +#include "config.hpp" + +#include "internal/peek_utf16.hpp" +#include "internal/result_on_found.hpp" +#include "internal/rules.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace utf16 + { + // clang-format off + struct any : internal::any< internal::peek_utf16 > {}; + struct bom : internal::one< internal::result_on_found::SUCCESS, internal::peek_utf16, 0xfeff > {}; + template< char32_t... Cs > struct not_one : internal::one< internal::result_on_found::FAILURE, internal::peek_utf16, Cs... > {}; + template< char32_t Lo, char32_t Hi > struct not_range : internal::range< internal::result_on_found::FAILURE, internal::peek_utf16, Lo, Hi > {}; + template< char32_t... Cs > struct one : internal::one< internal::result_on_found::SUCCESS, internal::peek_utf16, Cs... > {}; + template< char32_t Lo, char32_t Hi > struct range : internal::range< internal::result_on_found::SUCCESS, internal::peek_utf16, Lo, Hi > {}; + template< char32_t... Cs > struct ranges : internal::ranges< internal::peek_utf16, Cs... > {}; + template< char32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::SUCCESS, internal::peek_utf16, Cs >... > {}; + // clang-format on + + } // namespace utf16 + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/utf32.hpp b/include/tao/json/external/pegtl/utf32.hpp new file mode 100644 index 00000000..3029d6aa --- /dev/null +++ b/include/tao/json/external/pegtl/utf32.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_UTF32_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_UTF32_HPP + +#include "config.hpp" + +#include "internal/peek_utf32.hpp" +#include "internal/result_on_found.hpp" +#include "internal/rules.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace utf32 + { + // clang-format off + struct any : internal::any< internal::peek_utf32 > {}; + struct bom : internal::one< internal::result_on_found::SUCCESS, internal::peek_utf32, 0xfeff > {}; + template< char32_t... Cs > struct not_one : internal::one< internal::result_on_found::FAILURE, internal::peek_utf32, Cs... > {}; + template< char32_t Lo, char32_t Hi > struct not_range : internal::range< internal::result_on_found::FAILURE, internal::peek_utf32, Lo, Hi > {}; + template< char32_t... Cs > struct one : internal::one< internal::result_on_found::SUCCESS, internal::peek_utf32, Cs... > {}; + template< char32_t Lo, char32_t Hi > struct range : internal::range< internal::result_on_found::SUCCESS, internal::peek_utf32, Lo, Hi > {}; + template< char32_t... Cs > struct ranges : internal::ranges< internal::peek_utf32, Cs... > {}; + template< char32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::SUCCESS, internal::peek_utf32, Cs >... > {}; + // clang-format on + + } // namespace utf32 + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/utf8.hpp b/include/tao/json/external/pegtl/utf8.hpp new file mode 100644 index 00000000..5f91e3ca --- /dev/null +++ b/include/tao/json/external/pegtl/utf8.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_UTF8_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_UTF8_HPP + +#include "config.hpp" + +#include "internal/peek_utf8.hpp" +#include "internal/result_on_found.hpp" +#include "internal/rules.hpp" + +namespace tao +{ + namespace TAOCPP_JSON_PEGTL_NAMESPACE + { + namespace utf8 + { + // clang-format off + struct any : internal::any< internal::peek_utf8 > {}; + struct bom : internal::one< internal::result_on_found::SUCCESS, internal::peek_utf8, 0xfeff > {}; + template< char32_t... Cs > struct not_one : internal::one< internal::result_on_found::FAILURE, internal::peek_utf8, Cs... > {}; + template< char32_t Lo, char32_t Hi > struct not_range : internal::range< internal::result_on_found::FAILURE, internal::peek_utf8, Lo, Hi > {}; + template< char32_t... Cs > struct one : internal::one< internal::result_on_found::SUCCESS, internal::peek_utf8, Cs... > {}; + template< char32_t Lo, char32_t Hi > struct range : internal::range< internal::result_on_found::SUCCESS, internal::peek_utf8, Lo, Hi > {}; + template< char32_t... Cs > struct ranges : internal::ranges< internal::peek_utf8, Cs... > {}; + template< char32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::SUCCESS, internal::peek_utf8, Cs >... > {}; + // clang-format on + + } // namespace utf8 + + } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + +} // namespace tao + +#endif diff --git a/include/tao/json/external/pegtl/version.hpp b/include/tao/json/external/pegtl/version.hpp new file mode 100644 index 00000000..a269f4c3 --- /dev/null +++ b/include/tao/json/external/pegtl/version.hpp @@ -0,0 +1,13 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAOCPP_JSON_PEGTL_INCLUDE_VERSION_HPP +#define TAOCPP_JSON_PEGTL_INCLUDE_VERSION_HPP + +#define TAOCPP_JSON_PEGTL_VERSION "2.2.0" + +#define TAOCPP_JSON_PEGTL_VERSION_MAJOR 2 +#define TAOCPP_JSON_PEGTL_VERSION_MINOR 2 +#define TAOCPP_JSON_PEGTL_VERSION_PATCH 0 + +#endif diff --git a/include/tao/json/external/string_view.hpp b/include/tao/json/external/string_view.hpp new file mode 100644 index 00000000..13ac077a --- /dev/null +++ b/include/tao/json/external/string_view.hpp @@ -0,0 +1,565 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_INCLUDE_STRING_VIEW_HPP +#define TAOCPP_INCLUDE_STRING_VIEW_HPP + +#ifndef TAOCPP_USE_STD_STRING_VIEW +#if __cplusplus >= 201703L +#define TAOCPP_USE_STD_STRING_VIEW +#endif +#endif + +#ifndef TAOCPP_USE_STD_STRING_VIEW +#ifndef TAOCPP_USE_TS_STRING_VIEW +#if( __cplusplus >= 201402L ) && ( ( __GNUC__ > 4 ) || ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 9 ) ) +#define TAOCPP_USE_TS_STRING_VIEW +#endif +#endif +#endif + +#if defined( TAOCPP_USE_STD_STRING_VIEW ) +#include +#elif defined( TAOCPP_USE_TS_STRING_VIEW ) +#include +#else +#include "../internal/identity.hpp" +#include +#include +#include +#include +#include +#endif + +namespace tao +{ + +#if defined( TAOCPP_USE_STD_STRING_VIEW ) + using std::basic_string_view; +#elif defined( TAOCPP_USE_TS_STRING_VIEW ) + using std::experimental::basic_string_view; +#else + + // this is C++17's std::string_view + // * based on N4659, except: + // * additional ctor for basic_string to compensate for missing basic_string::operator basic_string_view + // * additional noexcept specifiers have been added in a few places + // * dropped some constexpr specifiers which are not possible in C++11 + // * user-defined literals have suffix '_sv' instead of 'sv' + // * inefficient implementation of operator<< + // * no std::hash-specializations + // * implementations of find-methods is based on N3921 + template< class charT, class traits = std::char_traits< charT > > + class basic_string_view + { + public: + // types + using traits_type = traits; + using value_type = charT; + using pointer = value_type*; + using const_pointer = const value_type*; + using reference = value_type&; + using const_reference = const value_type&; + using const_iterator = const value_type*; + using iterator = const_iterator; + using const_reverse_iterator = std::reverse_iterator< const_iterator >; + using reverse_iterator = const_reverse_iterator; + using size_type = size_t; + using difference_type = ptrdiff_t; + + static constexpr size_type npos = size_type( -1 ); + + // 24.4.2.1, construction and assignment + constexpr basic_string_view() noexcept + : data_( nullptr ), size_( 0 ) + { + } + + constexpr basic_string_view( const charT* str ) // TODO: noexcept? + : data_( str ), size_( traits::length( str ) ) + { + } + + constexpr basic_string_view( const charT* str, size_type len ) noexcept + : data_( str ), size_( len ) + { + } + + // this is a work-around for missing operator basic_string_view in std::string + constexpr basic_string_view( const std::basic_string< charT, traits >& str ) noexcept + : data_( str.data() ), size_( str.size() ) + { + } + + constexpr basic_string_view( const basic_string_view& ) noexcept = default; + /*constexpr*/ basic_string_view& operator=( const basic_string_view& ) noexcept = default; + + // 24.4.2.2, iterator support + constexpr const_iterator begin() const noexcept + { + return data_; + } + + constexpr const_iterator end() const noexcept + { + return begin() + size(); + } + + constexpr const_iterator cbegin() const noexcept + { + return begin(); + } + + constexpr const_iterator cend() const noexcept + { + return begin() + size(); + } + + constexpr const_reverse_iterator rbegin() const noexcept + { + return const_reverse_iterator( end() ); + } + + constexpr const_reverse_iterator rend() const noexcept + { + return const_reverse_iterator( begin() ); + } + + constexpr const_reverse_iterator crbegin() const noexcept + { + return const_reverse_iterator( end() ); + } + + constexpr const_reverse_iterator crend() const noexcept + { + return const_reverse_iterator( begin() ); + } + + // 24.4.2.3, capacity + constexpr size_type size() const noexcept + { + return size_; + } + + constexpr size_type length() const noexcept + { + return size_; + } + + constexpr size_type max_size() const noexcept + { + return npos - 1; + } + + constexpr bool empty() const noexcept + { + return size_ == 0; + } + + // 24.4.2.4, element access + constexpr const_reference operator[]( size_type pos ) const noexcept + { + return data_[ pos ]; + } + + constexpr const_reference at( size_type pos ) const + { + return ( pos >= size() ) ? throw std::out_of_range( "index out of range in tao::basic_string_view::at" ) : data_[ pos ]; + } + + constexpr const_reference front() const noexcept + { + return data_[ 0 ]; + } + + constexpr const_reference back() const noexcept + { + return data_[ size() - 1 ]; + } + + constexpr const_pointer data() const noexcept + { + return data_; + } + + // 24.4.2.5, modifiers + /*constexpr*/ void remove_prefix( size_type n ) noexcept + { + data_ += n; + size_ -= n; + } + + /*constexpr*/ void remove_suffix( size_type n ) noexcept + { + size_ -= n; + } + + /*constexpr*/ void swap( basic_string_view& s ) noexcept + { + std::swap( data_, s.data_ ); + std::swap( size_, s.size_ ); + } + + // 24.4.2.6, string operations + size_type copy( charT* s, size_type n, size_type pos = 0 ) const + { + if( pos > size() ) { + throw std::out_of_range( "index out of range in tao::basic_string_view::copy" ); + } + const size_type rlen = std::min( n, size() - pos ); + traits::copy( s, data() + pos, rlen ); + return rlen; + } + + constexpr basic_string_view substr( size_type pos = 0, size_type n = npos ) const + { + return ( pos > size() ) ? throw std::out_of_range( "index out of range in tao::basic_string_view::substr" ) : basic_string_view( data() + pos, std::min( n, size() - pos ) ); + } + + /*constexpr*/ int compare( basic_string_view s ) const noexcept + { + const size_type rlen = std::min( size(), s.size() ); + const int result = traits::compare( data(), s.data(), rlen ); + if( result == 0 && size() != s.size() ) { + return ( size() < s.size() ) ? -1 : 1; + } + return result; + } + + constexpr int compare( size_type pos1, size_type n1, basic_string_view s ) const + { + return substr( pos1, n1 ).compare( s ); + } + + constexpr int compare( size_type pos1, size_type n1, basic_string_view s, size_type pos2, size_type n2 ) const + { + return substr( pos1, n1 ).compare( s.substr( pos2, n2 ) ); + } + + constexpr int compare( const charT* s ) const + { + return compare( basic_string_view( s ) ); + } + + constexpr int compare( size_type pos1, size_type n1, const charT* s ) const + { + return substr( pos1, n1 ).compare( basic_string_view( s ) ); + } + + constexpr int compare( size_type pos1, size_type n1, const charT* s, size_type n2 ) const + { + return substr( pos1, n1 ).compare( basic_string_view( s, n2 ) ); + } + + /*constexpr*/ size_type find( basic_string_view s, size_type pos = 0 ) const noexcept + { + if( pos > size() - s.size() ) { + return npos; + } + const auto iter = std::search( begin() + pos, end(), s.begin(), s.end() ); + return iter == end() ? npos : iter - begin(); + } + + constexpr size_type find( charT c, size_type pos = 0 ) const noexcept + { + return find( basic_string_view( &c, 1 ), pos ); + } + + constexpr size_type find( const charT* s, size_type pos, size_type n ) const noexcept + { + return find( basic_string_view( s, n ), pos ); + } + + constexpr size_type find( const charT* s, size_type pos = 0 ) const + { + return find( basic_string_view( s ), pos ); + } + + /*constexpr*/ size_type rfind( basic_string_view s, size_type pos = npos ) const noexcept + { + if( pos > size() - s.size() ) { + return npos; + } + const auto iter = std::find_end( begin() + pos, end(), s.begin(), s.end() ); + return iter == end() ? npos : iter - begin(); + } + + constexpr size_type rfind( charT c, size_type pos = npos ) const noexcept + { + return rfind( basic_string_view( &c, 1 ), pos ); + } + + constexpr size_type rfind( const charT* s, size_type pos, size_type n ) const noexcept + { + return rfind( basic_string_view( s, n ), pos ); + } + + constexpr size_type rfind( const charT* s, size_type pos = npos ) const + { + return rfind( basic_string_view( s ), pos ); + } + + /*constexpr*/ size_type find_first_of( basic_string_view s, size_type pos = 0 ) const noexcept + { + if( pos > size() - 1 ) { + return npos; + } + const auto iter = std::find_first_of( begin() + pos, end(), s.begin(), s.end() ); + return iter == end() ? npos : iter - begin(); + } + + constexpr size_type find_first_of( charT c, size_type pos = 0 ) const noexcept + { + return find_first_of( basic_string_view( &c, 1 ), pos ); + } + + constexpr size_type find_first_of( const charT* s, size_type pos, size_type n ) const noexcept + { + return find_first_of( basic_string_view( s, n ), pos ); + } + + constexpr size_type find_first_of( const charT* s, size_type pos = 0 ) const + { + return find_first_of( basic_string_view( s ), pos ); + } + + /*constexpr*/ size_type find_last_of( basic_string_view s, size_type pos = npos ) const noexcept + { + if( pos > size() - 1 ) { + return npos; + } + const auto iter = std::find_first_of( rbegin() + pos, rend(), s.begin(), s.end() ); + return iter == rend() ? npos : iter.base() - 1 - begin(); + } + + constexpr size_type find_last_of( charT c, size_type pos = npos ) const noexcept + { + return find_last_of( basic_string_view( &c, 1 ), pos ); + } + + constexpr size_type find_last_of( const charT* s, size_type pos, size_type n ) const noexcept + { + return find_last_of( basic_string_view( s, n ), pos ); + } + + constexpr size_type find_last_of( const charT* s, size_type pos = npos ) const + { + return find_last_of( basic_string_view( s ), pos ); + } + + /*constexpr*/ size_type find_first_not_of( basic_string_view s, size_type pos = 0 ) const noexcept + { + if( pos > size() - 1 ) { + return npos; + } + const auto iter = std::find_if( begin() + pos, end(), [&]( char c ) { + return std::find( s.begin(), s.end(), c ) == s.end(); + } ); + return iter == end() ? npos : iter - begin(); + } + + constexpr size_type find_first_not_of( charT c, size_type pos = 0 ) const noexcept + { + return find_first_not_of( basic_string_view( &c, 1 ), pos ); + } + + constexpr size_type find_first_not_of( const charT* s, size_type pos, size_type n ) const noexcept + { + return find_first_not_of( basic_string_view( s, n ), pos ); + } + + constexpr size_type find_first_not_of( const charT* s, size_type pos = 0 ) const + { + return find_first_not_of( basic_string_view( s ), pos ); + } + + /*constexpr*/ size_type find_last_not_of( basic_string_view s, size_type pos = npos ) const noexcept + { + if( pos > size() - 1 ) { + return npos; + } + const auto iter = std::find_if( rbegin() + pos, rend(), [&]( char c ) { + return std::find( s.begin(), s.end(), c ) == s.end(); + } ); + return iter == rend() ? npos : iter.base() - 1 - begin(); + } + + constexpr size_type find_last_not_of( charT c, size_type pos = npos ) const noexcept + { + return find_last_not_of( basic_string_view( &c, 1 ), pos ); + } + + constexpr size_type find_last_not_of( const charT* s, size_type pos, size_type n ) const noexcept + { + return find_first_not_of( basic_string_view( s, n ), pos ); + } + + constexpr size_type find_last_not_of( const charT* s, size_type pos = npos ) const + { + return find_last_not_of( basic_string_view( s ), pos ); + } + + private: + const_pointer data_; + size_type size_; + }; + + // 24.4.3, non-member comparison functions + template< class charT, class traits > + constexpr bool operator==( basic_string_view< charT, traits > x, basic_string_view< charT, traits > y ) noexcept + { + return x.compare( y ) == 0; + } + + template< class charT, class traits > + constexpr bool operator==( basic_string_view< charT, traits > x, internal::identity< basic_string_view< charT, traits > > y ) noexcept + { + return x.compare( y ) == 0; + } + + template< class charT, class traits > + constexpr bool operator==( internal::identity< basic_string_view< charT, traits > > x, basic_string_view< charT, traits > y ) noexcept + { + return x.compare( y ) == 0; + } + + template< class charT, class traits > + constexpr bool operator!=( basic_string_view< charT, traits > x, basic_string_view< charT, traits > y ) noexcept + { + return x.compare( y ) != 0; + } + + template< class charT, class traits > + constexpr bool operator!=( basic_string_view< charT, traits > x, internal::identity< basic_string_view< charT, traits > > y ) noexcept + { + return x.compare( y ) != 0; + } + + template< class charT, class traits > + constexpr bool operator!=( internal::identity< basic_string_view< charT, traits > > x, basic_string_view< charT, traits > y ) noexcept + { + return x.compare( y ) != 0; + } + + template< class charT, class traits > + constexpr bool operator<( basic_string_view< charT, traits > x, basic_string_view< charT, traits > y ) noexcept + { + return x.compare( y ) < 0; + } + + template< class charT, class traits > + constexpr bool operator<( basic_string_view< charT, traits > x, internal::identity< basic_string_view< charT, traits > > y ) noexcept + { + return x.compare( y ) < 0; + } + + template< class charT, class traits > + constexpr bool operator<( internal::identity< basic_string_view< charT, traits > > x, basic_string_view< charT, traits > y ) noexcept + { + return x.compare( y ) < 0; + } + + template< class charT, class traits > + constexpr bool operator>( basic_string_view< charT, traits > x, basic_string_view< charT, traits > y ) noexcept + { + return x.compare( y ) > 0; + } + + template< class charT, class traits > + constexpr bool operator>( basic_string_view< charT, traits > x, internal::identity< basic_string_view< charT, traits > > y ) noexcept + { + return x.compare( y ) > 0; + } + + template< class charT, class traits > + constexpr bool operator>( internal::identity< basic_string_view< charT, traits > > x, basic_string_view< charT, traits > y ) noexcept + { + return x.compare( y ) > 0; + } + + template< class charT, class traits > + constexpr bool operator<=( basic_string_view< charT, traits > x, basic_string_view< charT, traits > y ) noexcept + { + return x.compare( y ) <= 0; + } + + template< class charT, class traits > + constexpr bool operator<=( basic_string_view< charT, traits > x, internal::identity< basic_string_view< charT, traits > > y ) noexcept + { + return x.compare( y ) <= 0; + } + + template< class charT, class traits > + constexpr bool operator<=( internal::identity< basic_string_view< charT, traits > > x, basic_string_view< charT, traits > y ) noexcept + { + return x.compare( y ) <= 0; + } + + template< class charT, class traits > + constexpr bool operator>=( basic_string_view< charT, traits > x, basic_string_view< charT, traits > y ) noexcept + { + return x.compare( y ) >= 0; + } + + template< class charT, class traits > + constexpr bool operator>=( basic_string_view< charT, traits > x, internal::identity< basic_string_view< charT, traits > > y ) noexcept + { + return x.compare( y ) >= 0; + } + + template< class charT, class traits > + constexpr bool operator>=( internal::identity< basic_string_view< charT, traits > > x, basic_string_view< charT, traits > y ) noexcept + { + return x.compare( y ) >= 0; + } + + // 24.4.4, inserters and extractors + template< class charT, class traits > + std::basic_ostream< charT, traits >& operator<<( std::basic_ostream< charT, traits >& os, basic_string_view< charT, traits > str ) + { + // TODO: This is easy, but also inefficient. + return os << std::string( str.begin(), str.end() ); + } + +// TODO: 24.4.5, hash support + +#endif + + using string_view = basic_string_view< char >; + using u16string_view = basic_string_view< char16_t >; + using u32string_view = basic_string_view< char32_t >; + using wstring_view = basic_string_view< wchar_t >; + + inline namespace literals + { + inline namespace string_view_literals + { + // 24.4.6, suffix for basic_string_view literals + // NOTE: We are not the real STL, we use '_sv' instead of 'sv' as the suffix + constexpr string_view operator"" _sv( const char* str, size_t len ) noexcept + { + return string_view( str, len ); + } + + constexpr u16string_view operator"" _sv( const char16_t* str, size_t len ) noexcept + { + return u16string_view( str, len ); + } + + constexpr u32string_view operator"" _sv( const char32_t* str, size_t len ) noexcept + { + return u32string_view( str, len ); + } + + constexpr wstring_view operator"" _sv( const wchar_t* str, size_t len ) noexcept + { + return wstring_view( str, len ); + } + + } // namespace string_view_literals + + } // namespace literals + +} // namespace tao + +#endif diff --git a/include/tao/json/from_stream.hpp b/include/tao/json/from_stream.hpp new file mode 100644 index 00000000..5372ca3e --- /dev/null +++ b/include/tao/json/from_stream.hpp @@ -0,0 +1,49 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_FROM_STREAM_HPP +#define TAOCPP_JSON_INCLUDE_FROM_STREAM_HPP + +#include +#include +#include + +#include "events/from_stream.hpp" +#include "events/to_value.hpp" +#include "events/transformer.hpp" + +namespace tao +{ + namespace json + { + template< template< typename... > class Traits, template< typename... > class... Transformers > + basic_value< Traits > basic_from_stream( std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) + { + events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; + events::from_stream( consumer, stream, source, maximum_buffer_size ); + return std::move( consumer.value ); + } + + template< template< typename... > class Traits, template< typename... > class... Transformers > + basic_value< Traits > basic_from_stream( std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) + { + return basic_from_stream< Traits, Transformers... >( stream, source.c_str(), maximum_buffer_size ); + } + + template< template< typename... > class... Transformers > + value from_stream( std::istream& stream, const char* source, const std::size_t maximum_buffer_size = 4000 ) + { + return basic_from_stream< traits, Transformers... >( stream, source, maximum_buffer_size ); + } + + template< template< typename... > class... Transformers > + value from_stream( std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) + { + return basic_from_stream< traits, Transformers... >( stream, source.c_str(), maximum_buffer_size ); + } + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/from_string.hpp b/include/tao/json/from_string.hpp new file mode 100644 index 00000000..43193fa6 --- /dev/null +++ b/include/tao/json/from_string.hpp @@ -0,0 +1,45 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_FROM_STRING_HPP +#define TAOCPP_JSON_INCLUDE_FROM_STRING_HPP + +#include +#include + +#include "events/from_string.hpp" +#include "events/to_value.hpp" +#include "events/transformer.hpp" + +namespace tao +{ + namespace json + { + template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > + basic_value< Traits > basic_from_string( Ts&&... ts ) + { + events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; + events::from_string( consumer, std::forward< Ts >( ts )... ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers, typename... Ts > + value from_string( Ts&&... ts ) + { + return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); + } + + inline namespace literals + { + inline value operator"" _json( const char* data, const std::size_t size ) + { + return json::from_string( data, size, "literal" ); + } + + } // namespace literals + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/action.hpp b/include/tao/json/internal/action.hpp new file mode 100644 index 00000000..059e7c36 --- /dev/null +++ b/include/tao/json/internal/action.hpp @@ -0,0 +1,242 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_ACTION_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_ACTION_HPP + +#include "../external/pegtl/nothing.hpp" + +#include "errors.hpp" +#include "grammar.hpp" + +#include "number_state.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + template< typename Rule > + struct action + : json_pegtl::nothing< Rule > + { + }; + + template<> + struct action< rules::null > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.null(); + } + }; + + template<> + struct action< rules::true_ > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.boolean( true ); + } + }; + + template<> + struct action< rules::false_ > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.boolean( false ); + } + }; + + template<> + struct action< rules::array::begin > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.begin_array(); + } + }; + + template<> + struct action< rules::array::element > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.element(); + } + }; + + template<> + struct action< rules::array::end > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.end_array(); + } + }; + + template<> + struct action< rules::object::begin > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.begin_object(); + } + }; + + template<> + struct action< rules::object::element > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.member(); + } + }; + + template<> + struct action< rules::object::end > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.end_object(); + } + }; + + template<> + struct action< rules::zero< false > > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.number( std::uint64_t( 0 ) ); + } + }; + + template<> + struct action< rules::zero< true > > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.number( std::int64_t( 0 ) ); + } + }; + + template<> + struct action< rules::esign > + { + template< typename Input, bool NEG > + static void apply( const Input& in, number_state< NEG >& result ) + { + result.eneg = ( in.peek_char() == '-' ); + } + }; + + template<> + struct action< rules::idigits > + { + template< typename Input, bool NEG > + static void apply( const Input& in, number_state< NEG >& result ) + { + const auto s = in.size(); + + if( s == 1 && in.peek_char() == '0' ) { + return; + } + + if( s > ( 1 << 20 ) ) { + throw std::runtime_error( "JSON number with 1 megabyte digits" ); + } + + const auto c = std::min( s, max_mantissa_digits ); + std::memcpy( result.mantissa, in.begin(), c ); + result.exponent10 += static_cast< typename number_state< NEG >::exponent10_t >( s - c ); + result.msize = static_cast< typename number_state< NEG >::msize_t >( c ); + + for( std::size_t i = c; i < s; ++i ) { + if( in.peek_char( i ) != '0' ) { + result.drop = true; + return; + } + } + } + }; + + template<> + struct action< rules::fdigits > + { + template< typename Input, bool NEG > + static void apply( const Input& in, number_state< NEG >& result ) + { + result.isfp = true; + + const auto* b = in.begin(); + const auto* e = in.end(); + + while( ( e > b ) && ( e[ -1 ] == '0' ) ) { + --e; + } + if( !result.msize ) { + while( ( b < e ) && ( b[ 0 ] == '0' ) ) { + ++b; + --result.exponent10; + } + } + const auto c = std::min( std::size_t( e - b ), max_mantissa_digits - result.msize ); + std::memcpy( result.mantissa + result.msize, b, c ); + result.exponent10 -= static_cast< typename number_state< NEG >::exponent10_t >( c ); + result.msize += static_cast< typename number_state< NEG >::msize_t >( c ); + + for( const auto* r = b + c; r < e; ++r ) { + if( *r != '0' ) { + result.drop = true; + return; + } + } + } + }; + + template<> + struct action< rules::edigits > + { + template< typename Input, bool NEG > + static void apply( const Input& in, number_state< NEG >& result ) + { + result.isfp = true; + + const char* b = in.begin(); + + while( ( b < in.end() ) && ( b[ 0 ] == '0' ) ) { + ++b; + } + if( ( in.end() - b ) > 9 ) { + throw std::runtime_error( "JSON exponent has more than 9 significant digits" ); + } + int exponent10 = 0; + + while( b < in.end() ) { + exponent10 = ( exponent10 * 10 ) + ( b[ 0 ] - '0' ); + ++b; + } + result.exponent10 += ( result.eneg ? -exponent10 : exponent10 ); + } + }; + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/base64.hpp b/include/tao/json/internal/base64.hpp new file mode 100644 index 00000000..f4403f00 --- /dev/null +++ b/include/tao/json/internal/base64.hpp @@ -0,0 +1,63 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_BASE64_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_BASE64_HPP + +#include +#include + +namespace tao +{ + namespace json + { + namespace internal + { + template< typename T > + std::string base64( const T& v ) + { + static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + std::string s; + s.reserve( ( v.size() + 2 ) / 3 * 4 ); + + unsigned cycle = 0; + unsigned encode = 0; + for( const auto c : v ) { + encode <<= 8; + encode += static_cast< unsigned char >( c ); + s += table[ ( encode >> ( ++cycle * 2 ) ) & 0x3f ]; + if( cycle == 3 ) { + cycle = 0; + s += table[ encode & 0x3f ]; + } + } + + switch( cycle ) { + case 0: + break; + + case 1: + s += table[ ( encode << 4 ) & 0x3f ]; + s += "=="; + break; + + case 2: + s += table[ ( encode << 2 ) & 0x3f ]; + s += '='; + break; + + default: + assert( !"code should be unreachable" ); // LCOV_EXCL_LINE + } + + return s; + } + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/base64url.hpp b/include/tao/json/internal/base64url.hpp new file mode 100644 index 00000000..725e8bf6 --- /dev/null +++ b/include/tao/json/internal/base64url.hpp @@ -0,0 +1,61 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_BASE64URL_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_BASE64URL_HPP + +#include +#include + +namespace tao +{ + namespace json + { + namespace internal + { + template< typename T > + inline std::string base64url( const T& v ) + { + static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + + std::string s; + s.reserve( ( v.size() + 2 ) / 3 * 4 ); + + unsigned cycle = 0; + unsigned encode = 0; + for( const auto c : v ) { + encode <<= 8; + encode += static_cast< unsigned char >( c ); + s += table[ ( encode >> ( ++cycle * 2 ) ) & 0x3f ]; + if( cycle == 3 ) { + cycle = 0; + s += table[ encode & 0x3f ]; + } + } + + switch( cycle ) { + case 0: + break; + + case 1: + s += table[ ( encode << 4 ) & 0x3f ]; + break; + + case 2: + s += table[ ( encode << 2 ) & 0x3f ]; + break; + + default: + assert( !"code should be unreachable" ); // LCOV_EXCL_LINE + } + + return s; + } + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/control.hpp b/include/tao/json/internal/control.hpp new file mode 100644 index 00000000..8fbbe8fe --- /dev/null +++ b/include/tao/json/internal/control.hpp @@ -0,0 +1,53 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_CONTROL_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_CONTROL_HPP + +#include "../external/pegtl/contrib/changes.hpp" + +#include "errors.hpp" + +#include "unescape_action.hpp" + +#include "key_state.hpp" +#include "number_state.hpp" +#include "string_state.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + template< typename Rule > + struct control + : errors< Rule > + { + }; + + template< bool NEG > + struct control< rules::number< NEG > > + : json_pegtl::change_state< rules::number< NEG >, number_state< NEG >, errors > + { + }; + + template<> + struct control< rules::string::content > + : json_pegtl::change_state_and_action< rules::string::content, string_state, unescape_action, errors > + { + }; + + template<> + struct control< rules::key::content > + : json_pegtl::change_state_and_action< rules::key::content, key_state, unescape_action, errors > + { + }; + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/endian.hpp b/include/tao/json/internal/endian.hpp new file mode 100644 index 00000000..72709865 --- /dev/null +++ b/include/tao/json/internal/endian.hpp @@ -0,0 +1,70 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_ENDIAN_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_ENDIAN_HPP + +#include +#include + +// TODO: Where to put this header? + +#if defined( _WIN32 ) && !defined( __MINGW32__ ) +#include "endian_win.hpp" +#else +#include "endian_gcc.hpp" +#endif + +namespace tao +{ + namespace json + { + namespace internal + { + template< typename N > + N h_to_be( const N n ) noexcept + { + return N( to_and_from_be< sizeof( N ) >::convert( n ) ); + } + + template< typename N > + N be_to_h( const N n ) noexcept + { + return h_to_be( n ); + } + + template< typename N > + N be_to_h( const void* p ) noexcept + { + N n; + std::memcpy( &n, p, sizeof( n ) ); + return internal::be_to_h( n ); + } + + template< typename N > + N h_to_le( const N n ) noexcept + { + return N( to_and_from_le< sizeof( N ) >::convert( n ) ); + } + + template< typename N > + N le_to_h( const N n ) noexcept + { + return h_to_le( n ); + } + + template< typename N > + N le_to_h( const void* p ) noexcept + { + N n; + std::memcpy( &n, p, sizeof( n ) ); + return internal::le_to_h( n ); + } + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/endian_gcc.hpp b/include/tao/json/internal/endian_gcc.hpp new file mode 100644 index 00000000..63ae3bfd --- /dev/null +++ b/include/tao/json/internal/endian_gcc.hpp @@ -0,0 +1,202 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_ENDIAN_GCC_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_ENDIAN_GCC_HPP + +namespace tao +{ + namespace json + { + namespace internal + { +#if not defined( __BYTE_ORDER__ ) +#error TODO -- what? +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + + template< unsigned S > + struct to_and_from_be + { + template< typename T > + static T convert( const T n ) noexcept + { + return n; + } + }; + + template< unsigned S > + struct to_and_from_le; + + template<> + struct to_and_from_le< 1 > + { + static std::uint8_t convert( const std::uint8_t n ) noexcept + { + return n; + } + + static std::int8_t convert( const std::int8_t n ) noexcept + { + return n; + } + }; + + template<> + struct to_and_from_le< 2 > + { + static std::int16_t convert( const std::int16_t n ) noexcept + { + return __builtin_bswap16( n ); + } + + static std::uint16_t convert( const std::uint16_t n ) noexcept + { + return __builtin_bswap16( n ); + } + }; + + template<> + struct to_and_from_le< 4 > + { + static float convert( float n ) noexcept + { + std::uint32_t u; + std::memcpy( &u, &n, 4 ); + u = convert( u ); + std::memcpy( &n, &u, 4 ); + return n; + } + + static std::int32_t convert( const std::int32_t n ) noexcept + { + return __builtin_bswap32( n ); + } + + static std::uint32_t convert( const std::uint32_t n ) noexcept + { + return __builtin_bswap32( n ); + } + }; + + template<> + struct to_and_from_le< 8 > + { + static double convert( double n ) noexcept + { + std::uint64_t u; + std::memcpy( &u, &n, 8 ); + u = convert( u ); + std::memcpy( &n, &u, 8 ); + return n; + } + + static std::int64_t convert( const std::int64_t n ) noexcept + { + return __builtin_bswap64( n ); + } + + static std::uint64_t convert( const std::uint64_t n ) noexcept + { + return __builtin_bswap64( n ); + } + }; + +#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + + template< unsigned S > + struct to_and_from_le + { + template< typename T > + static T convert( const T n ) noexcept + { + return n; + } + }; + + template< unsigned S > + struct to_and_from_be; + + template<> + struct to_and_from_be< 1 > + { + static std::int8_t convert( const std::int8_t n ) noexcept + { + return n; + } + + static std::uint8_t convert( const std::uint8_t n ) noexcept + { + return n; + } + }; + + template<> + struct to_and_from_be< 2 > + { + static std::int16_t convert( const std::int16_t n ) noexcept + { + return __builtin_bswap16( n ); + } + + static std::uint16_t convert( const std::uint16_t n ) noexcept + { + return __builtin_bswap16( n ); + } + }; + + template<> + struct to_and_from_be< 4 > + { + static float convert( float n ) noexcept + { + std::uint32_t u; + std::memcpy( &u, &n, 4 ); + u = convert( u ); + std::memcpy( &n, &u, 4 ); + return n; + } + + static std::int32_t convert( const std::int32_t n ) noexcept + { + return __builtin_bswap32( n ); + } + + static std::uint32_t convert( const std::uint32_t n ) noexcept + { + return __builtin_bswap32( n ); + } + }; + + template<> + struct to_and_from_be< 8 > + { + static double convert( double n ) noexcept + { + std::uint64_t u; + std::memcpy( &u, &n, 8 ); + u = convert( u ); + std::memcpy( &n, &u, 8 ); + return n; + } + + static std::uint64_t convert( const std::uint64_t n ) noexcept + { + return __builtin_bswap64( n ); + } + + static std::int64_t convert( const std::int64_t n ) noexcept + { + return __builtin_bswap64( n ); + } + }; + +#else +#error Unknown host byte order! +#endif + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/endian_win.hpp b/include/tao/json/internal/endian_win.hpp new file mode 100644 index 00000000..38bc9932 --- /dev/null +++ b/include/tao/json/internal/endian_win.hpp @@ -0,0 +1,91 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_ENDIAN_WIN_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_ENDIAN_WIN_HPP + +#include +#include + +#include // TODO: Or is intrin.h the 'more correct' header for the _byteswap_foo() functions? + +namespace tao +{ + namespace json + { + namespace internal + { + template< unsigned S > + struct to_and_from_le + { + template< typename T > + static T convert( const T t ) noexcept + { + return t; + } + }; + + template< unsigned S > + struct to_and_from_be; + + template<> + struct to_and_from_be< 1 > + { + static std::uint8_t convert( const std::uint8_t n ) noexcept + { + return n; + } + }; + + template<> + struct to_and_from_be< 2 > + { + static std::uint16_t convert( const std::uint16_t n ) noexcept + { + return _byteswap_ushort( n ); + } + }; + + template<> + struct to_and_from_be< 4 > + { + static float convert( float n ) noexcept + { + std::uint32_t u; + std::memcpy( &u, &n, 4 ); + u = convert( u ); + std::memcpy( &n, &u, 4 ); + return n; + } + + static std::uint32_t convert( const std::uint32_t n ) noexcept + { + return _byteswap_ulong( n ); + } + }; + + template<> + struct to_and_from_be< 8 > + { + static double convert( double n ) noexcept + { + std::uint64_t u; + std::memcpy( &u, &n, 8 ); + u = convert( u ); + std::memcpy( &n, &u, 8 ); + return n; + } + + static std::uint64_t convert( const std::uint64_t n ) noexcept + { + return _byteswap_uint64( n ); + } + }; + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/errors.hpp b/include/tao/json/internal/errors.hpp new file mode 100644 index 00000000..1d795ad0 --- /dev/null +++ b/include/tao/json/internal/errors.hpp @@ -0,0 +1,98 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_ERRORS_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_ERRORS_HPP + +#include + +#include "../external/pegtl/normal.hpp" +#include "../external/pegtl/parse_error.hpp" + +#include "grammar.hpp" + +#if defined( _MSC_VER ) +#define WEAK_PREFIX __declspec( selectany ) +#define WEAK_SUFFIX +#else +#define WEAK_PREFIX +#define WEAK_SUFFIX __attribute__( ( weak ) ) +#endif + +namespace tao +{ + namespace json + { + namespace internal + { + template< typename Rule > + struct errors + : json_pegtl::normal< Rule > + { + static const std::string error_message; + + template< typename Input, typename... States > + static void raise( const Input& in, States&&... ) + { + throw json_pegtl::parse_error( error_message, in ); + } + + template< template< typename... > class Action, typename Input, typename... States > + static void apply0( const Input& in, States&&... st ) + { + try { + Action< Rule >::apply0( st... ); + } + catch( const json_pegtl::parse_error& ) { + throw; + } + catch( const std::exception& e ) { + throw json_pegtl::parse_error( e.what(), in ); + } + } + + template< template< typename... > class Action, typename Iterator, typename Input, typename... States > + static void apply( const Iterator& begin, const Input& in, States&&... st ) + { + try { + using action_t = typename Input::action_t; + const action_t action_input( begin, in ); + Action< Rule >::apply( action_input, st... ); + } + catch( const json_pegtl::parse_error& ) { + throw; + } + catch( const std::exception& e ) { + throw json_pegtl::parse_error( e.what(), in ); + } + } + }; + + // clang-format off + template<> WEAK_PREFIX const std::string errors< rules::text >::error_message WEAK_SUFFIX = "no valid JSON"; + + template<> WEAK_PREFIX const std::string errors< rules::end_array >::error_message WEAK_SUFFIX = "incomplete array, expected ']'"; + template<> WEAK_PREFIX const std::string errors< rules::end_object >::error_message WEAK_SUFFIX = "incomplete object, expected '}'"; + template<> WEAK_PREFIX const std::string errors< rules::member >::error_message WEAK_SUFFIX = "expected member"; + template<> WEAK_PREFIX const std::string errors< rules::name_separator >::error_message WEAK_SUFFIX = "expected ':'"; + template<> WEAK_PREFIX const std::string errors< rules::array_element >::error_message WEAK_SUFFIX = "expected value"; + template<> WEAK_PREFIX const std::string errors< rules::value >::error_message WEAK_SUFFIX = "expected value"; + + template<> WEAK_PREFIX const std::string errors< rules::edigits >::error_message WEAK_SUFFIX = "expected at least one exponent digit"; + template<> WEAK_PREFIX const std::string errors< rules::fdigits >::error_message WEAK_SUFFIX = "expected at least one fraction digit"; + template<> WEAK_PREFIX const std::string errors< rules::xdigit >::error_message WEAK_SUFFIX = "incomplete universal character name"; + template<> WEAK_PREFIX const std::string errors< rules::escaped >::error_message WEAK_SUFFIX = "unknown escape sequence"; + template<> WEAK_PREFIX const std::string errors< rules::chars >::error_message WEAK_SUFFIX = "invalid character in string"; + template<> WEAK_PREFIX const std::string errors< rules::string::content >::error_message WEAK_SUFFIX = "unterminated string"; + template<> WEAK_PREFIX const std::string errors< rules::key::content >::error_message WEAK_SUFFIX = "unterminated key"; + + template<> WEAK_PREFIX const std::string errors< json_pegtl::eof >::error_message WEAK_SUFFIX = "unexpected character after JSON value"; + // clang-format on + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/escape.hpp b/include/tao/json/internal/escape.hpp new file mode 100644 index 00000000..6e254740 --- /dev/null +++ b/include/tao/json/internal/escape.hpp @@ -0,0 +1,77 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_ESCAPE_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_ESCAPE_HPP + +#include + +#include "../external/string_view.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + inline void escape( std::ostream& os, const tao::string_view s ) + { + static const char* h = "0123456789abcdef"; + + const char* p = s.data(); + const char* l = p; + const char* const e = s.data() + s.size(); + while( p != e ) { + const unsigned char c = *p; + if( c == '\\' ) { + os.write( l, p - l ); + l = ++p; + os << "\\\\"; + } + else if( c == '"' ) { + os.write( l, p - l ); + l = ++p; + os << "\\\""; + } + else if( c < 32 ) { + os.write( l, p - l ); + l = ++p; + switch( c ) { + case '\b': + os << "\\b"; + break; + case '\f': + os << "\\f"; + break; + case '\n': + os << "\\n"; + break; + case '\r': + os << "\\r"; + break; + case '\t': + os << "\\t"; + break; + default: + os << "\\u00" << h[ ( c & 0xf0 ) >> 4 ] << h[ c & 0x0f ]; + } + } + else if( c == 127 ) { + os.write( l, p - l ); + l = ++p; + os << "\\u007f"; + } + else { + ++p; + } + } + os.write( l, p - l ); + } + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/get_by_enum.hpp b/include/tao/json/internal/get_by_enum.hpp new file mode 100644 index 00000000..49758d77 --- /dev/null +++ b/include/tao/json/internal/get_by_enum.hpp @@ -0,0 +1,172 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_GET_BY_ENUM_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_GET_BY_ENUM_HPP + +#include + +#include "../type.hpp" + +#include "value_union.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + template< type > + struct get_by_enum; + + template<> + struct get_by_enum< type::NULL_ > + { + template< typename T > + static null_t get( const value_union< T >& ) noexcept + { + return null; + } + }; + + template<> + struct get_by_enum< type::BOOLEAN > + { + template< typename T > + static bool get( const value_union< T >& u ) noexcept + { + return u.b; + } + }; + + template<> + struct get_by_enum< type::SIGNED > + { + template< typename T > + static std::int64_t get( const value_union< T >& u ) noexcept + { + return u.i; + } + }; + + template<> + struct get_by_enum< type::UNSIGNED > + { + template< typename T > + static std::uint64_t get( const value_union< T >& u ) noexcept + { + return u.u; + } + }; + + template<> + struct get_by_enum< type::DOUBLE > + { + template< typename T > + static double get( const value_union< T >& u ) noexcept + { + return u.d; + } + }; + + template<> + struct get_by_enum< type::STRING > + { + template< typename T > + static std::string& get( value_union< T >& u ) noexcept + { + return u.s; + } + + template< typename T > + static const std::string& get( const value_union< T >& u ) noexcept + { + return u.s; + } + }; + + template<> + struct get_by_enum< type::STRING_VIEW > + { + template< typename T > + static tao::string_view get( const value_union< T >& u ) noexcept + { + return u.sv; + } + }; + + template<> + struct get_by_enum< type::BINARY > + { + template< typename T > + static std::vector< tao::byte >& get( value_union< T >& u ) noexcept + { + return u.x; + } + + template< typename T > + static const std::vector< tao::byte >& get( const value_union< T >& u ) noexcept + { + return u.x; + } + }; + + template<> + struct get_by_enum< type::BINARY_VIEW > + { + template< typename T > + static tao::byte_view get( const value_union< T >& u ) noexcept + { + return u.xv; + } + }; + + template<> + struct get_by_enum< type::ARRAY > + { + template< typename T > + static std::vector< T >& get( value_union< T >& u ) noexcept + { + return u.a; + } + + template< typename T > + static const std::vector< T >& get( const value_union< T >& u ) noexcept + { + return u.a; + } + }; + + template<> + struct get_by_enum< type::OBJECT > + { + template< typename T > + static std::map< std::string, T >& get( value_union< T >& u ) noexcept + { + return u.o; + } + + template< typename T > + static const std::map< std::string, T >& get( const value_union< T >& u ) noexcept + { + return u.o; + } + }; + + template<> + struct get_by_enum< type::RAW_PTR > + { + template< typename T > + static const T* get( const value_union< T >& u ) noexcept + { + return u.p; + } + }; + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/grammar.hpp b/include/tao/json/internal/grammar.hpp new file mode 100644 index 00000000..193e2339 --- /dev/null +++ b/include/tao/json/internal/grammar.hpp @@ -0,0 +1,238 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_GRAMMAR_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_GRAMMAR_HPP + +#include "../external/pegtl.hpp" +#include "../external/pegtl/contrib/abnf.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + // clang-format off + namespace rules + { + using namespace json_pegtl; + + struct ws : one< ' ', '\t', '\n', '\r' > {}; + + template< typename R, typename P = ws > + using padr = json_pegtl::internal::seq< R, json_pegtl::internal::star< P > >; + + struct begin_array : padr< one< '[' > > {}; + struct begin_object : padr< one< '{' > > {}; + struct end_array : one< ']' > {}; + struct end_object : one< '}' > {}; + struct name_separator : pad< one< ':' >, ws > {}; + struct value_separator : padr< one< ',' > > {}; + struct element_separator : padr< one< ',' > > {}; + + struct false_ : TAOCPP_JSON_PEGTL_STRING( "false" ) {}; + struct null : TAOCPP_JSON_PEGTL_STRING( "null" ) {}; + struct true_ : TAOCPP_JSON_PEGTL_STRING( "true" ) {}; + + struct digits : plus< abnf::DIGIT > {}; + + struct esign : one< '-', '+' > {}; + + struct edigits : digits {}; + struct fdigits : digits {}; + struct idigits : digits {}; + + struct exp : seq< one< 'e', 'E' >, opt< esign >, must< edigits > > {}; + struct frac : if_must< one< '.' >, fdigits > {}; + + template< bool NEG > + struct number : seq< idigits, opt< frac >, opt< exp > > {}; + + struct xdigit : abnf::HEXDIG {}; + struct escaped_unicode : list< seq< one< 'u' >, rep< 4, must< xdigit > > >, one< '\\' > > {}; + + struct escaped_char : one< '"', '\\', '/', 'b', 'f', 'n', 'r', 't' > {}; + struct escaped : sor< escaped_char, escaped_unicode > {}; + + struct unescaped + { + using analyze_t = json_pegtl::analysis::generic< json_pegtl::analysis::rule_type::ANY >; + + template< typename Input > + static bool match( Input& in ) + { + bool result = false; + + while( !in.empty() ) { + if( const auto t = json_pegtl::internal::peek_utf8::peek( in ) ) { + if( ( 0x20 <= t.data ) && ( t.data <= 0x10ffff ) && ( t.data != '\\' ) && ( t.data != '"' ) ) { + in.bump_in_this_line( t.size ); + result = true; + continue; + } + } + return result; + } + throw json_pegtl::parse_error( "invalid character in string", in ); + } + }; + + struct chars : if_then_else< one< '\\' >, must< escaped >, unescaped > {}; + + struct string_content : until< at< one< '"' > >, must< chars > > {}; + struct string : seq< one< '"' >, must< string_content >, any > + { + using content = string_content; + }; + + struct key_content : string_content {}; + struct key : seq< one< '"' >, must< key_content >, any > + { + using content = key_content; + }; + + struct value; + + struct array_element; + struct array_content : opt< list_must< array_element, element_separator > > {}; + struct array : seq< begin_array, array_content, must< end_array > > + { + using begin = begin_array; + using end = end_array; + using element = array_element; + using content = array_content; + }; + + struct member : if_must< key, name_separator, value > {}; + struct object_content : opt< list_must< member, value_separator > > {}; + struct object : seq< begin_object, object_content, must< end_object > > + { + using begin = begin_object; + using end = end_object; + using element = member; + using content = object_content; + }; + + template< bool NEG > + struct zero {}; + + struct sor_value + { + using analyze_t = json_pegtl::analysis::generic< json_pegtl::analysis::rule_type::SOR, string, number< false >, object, array, false_, true_, null >; + + template< bool NEG, + apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match_zero( Input& in, States&&... st ) + { + if( in.size( 2 ) > 1 ) { + switch( in.peek_char( 1 ) ) { + case '.': + case 'e': + case 'E': + return Control< number< NEG > >::template match< A, M, Action, Control >( in, st... ); + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + throw json_pegtl::parse_error( "invalid leading zero", in ); + } + } + in.bump_in_this_line(); + Control< zero< NEG > >::template apply0< Action >( in, st... ); + return true; + } + + template< bool NEG, + apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match_number( Input& in, States&&... st ) + { + if( in.peek_char() == '0' ) { + if( !match_zero< NEG, A, rewind_mode::DONTCARE, Action, Control >( in, st... ) ) { + throw json_pegtl::parse_error( "incomplete number", in ); + } + return true; + } + else { + return Control< number< NEG > >::template match< A, M, Action, Control >( in, st... ); + } + } + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match_impl( Input& in, States&&... st ) + { + switch( in.peek_char() ) { + case '"': return Control< string >::template match< A, M, Action, Control >( in, st... ); + case '{': return Control< object >::template match< A, M, Action, Control >( in, st... ); + case '[': return Control< array >::template match< A, M, Action, Control >( in, st... ); + case 'n': return Control< null >::template match< A, M, Action, Control >( in, st... ); + case 't': return Control< true_ >::template match< A, M, Action, Control >( in, st... ); + case 'f': return Control< false_ >::template match< A, M, Action, Control >( in, st... ); + + case '-': + in.bump_in_this_line(); + if( in.empty() || !match_number< true, A, rewind_mode::DONTCARE, Action, Control >( in, st... ) ) { + throw json_pegtl::parse_error( "incomplete number", in ); + } + return true; + + default: + return match_number< false, A, M, Action, Control >( in, st... ); + } + } + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + if( in.size( 2 ) && match_impl< A, M, Action, Control >( in, st... ) ) { + in.discard(); + return true; + } + return false; + } + }; + + struct value : padr< sor_value > {}; + struct array_element : value {}; + + struct text : seq< star< ws >, value > {}; + + } // namespace rules + + struct grammar : json_pegtl::must< rules::text, json_pegtl::eof > {}; + // clang-format on + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/hexdump.hpp b/include/tao/json/internal/hexdump.hpp new file mode 100644 index 00000000..3634ece4 --- /dev/null +++ b/include/tao/json/internal/hexdump.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_HEXDUMP_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_HEXDUMP_HPP + +#include + +namespace tao +{ + namespace json + { + namespace internal + { + template< typename T > + void hexdump( std::ostream& os, const T& v ) + { + static const char h[] = "0123456789ABCDEF"; + for( const auto b : v ) { + os.put( h[ static_cast< unsigned char >( b ) >> 4 ] ); + os.put( h[ static_cast< unsigned char >( b ) & 0xF ] ); + } + } + + template< typename T > + std::string hexdump( const T& v ) + { + std::ostringstream os; + internal::hexdump( os, v ); + return os.str(); + } + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/identity.hpp b/include/tao/json/internal/identity.hpp new file mode 100644 index 00000000..20e7f614 --- /dev/null +++ b/include/tao/json/internal/identity.hpp @@ -0,0 +1,20 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_INCLUDE_INTERNAL_IDENTITY_HPP +#define TAOCPP_INCLUDE_INTERNAL_IDENTITY_HPP + +#include + +namespace tao +{ + namespace internal + { + template< typename T > + using identity = typename std::decay< T >::type; + + } // namespace internal + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/jaxn/action.hpp b/include/tao/json/internal/jaxn/action.hpp new file mode 100644 index 00000000..4ad31cb2 --- /dev/null +++ b/include/tao/json/internal/jaxn/action.hpp @@ -0,0 +1,335 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_ACTION_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_ACTION_HPP + +#include "../../external/pegtl/nothing.hpp" +#include "../../external/string_view.hpp" + +#include "errors.hpp" +#include "grammar.hpp" + +#include "../number_state.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + namespace jaxn + { + template< typename Rule > + struct action + : json_pegtl::nothing< Rule > + { + }; + + template<> + struct action< rules::null > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.null(); + } + }; + + template<> + struct action< rules::true_ > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.boolean( true ); + } + }; + + template<> + struct action< rules::false_ > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.boolean( false ); + } + }; + + template<> + struct action< rules::identifier > + { + template< typename Input, typename Consumer > + static void apply( const Input& in, Consumer& consumer ) + { + consumer.key( tao::string_view( in.begin(), in.size() ) ); + } + }; + + template< bool NEG > + struct action< rules::hexnum< NEG > > + { + static char unhex( const char c ) + { + if( ( '0' <= c ) && ( c <= '9' ) ) { + return c - '0'; + } + if( ( 'a' <= c ) && ( c <= 'f' ) ) { + return c - 'a' + 10; + } + if( ( 'A' <= c ) && ( c <= 'F' ) ) { + return c - 'A' + 10; + } + // LCOV_EXCL_START + assert( false ); + return false; + // LCOV_EXCL_STOP + } + + template< typename Input, typename Consumer > + static void apply( const Input& in, Consumer& consumer ) + { + std::uint64_t value = 0; + for( char c : in ) { + if( value & 0xF000000000000000 ) { + throw std::runtime_error( "JAXN hexadecimal number too large" ); + } + value <<= 4; + value += unhex( c ); + } + if( NEG ) { + if( value < 9223372036854775808ull ) { + consumer.number( -static_cast< std::int64_t >( value ) ); + } + else if( value == 9223372036854775808ull ) { + consumer.number( static_cast< std::int64_t >( -9223372036854775807ll - 1 ) ); + } + else { + throw std::runtime_error( "JAXN hexadecimal number too large to negate" ); + } + } + else { + consumer.number( value ); + } + } + }; + + template<> + struct action< rules::array::begin > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.begin_array(); + } + }; + + template<> + struct action< rules::array::element > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.element(); + } + }; + + template<> + struct action< rules::array::end > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.end_array(); + } + }; + + template<> + struct action< rules::object::begin > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.begin_object(); + } + }; + + template<> + struct action< rules::object::element > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.member(); + } + }; + + template<> + struct action< rules::object::end > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.end_object(); + } + }; + + template<> + struct action< rules::zero< false > > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.number( std::uint64_t( 0 ) ); + } + }; + + template<> + struct action< rules::zero< true > > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.number( std::int64_t( 0 ) ); + } + }; + + template<> + struct action< rules::nan > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.number( NAN ); + } + }; + + template<> + struct action< rules::infinity< false > > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.number( INFINITY ); + } + }; + + template<> + struct action< rules::infinity< true > > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.number( -INFINITY ); + } + }; + + template<> + struct action< rules::esign > + { + template< typename Input, bool NEG > + static void apply( const Input& in, number_state< NEG >& result ) + { + result.eneg = ( in.peek_char() == '-' ); + } + }; + + template<> + struct action< rules::idigits > + { + template< typename Input, bool NEG > + static void apply( const Input& in, number_state< NEG >& result ) + { + const auto s = in.size(); + + if( s == 1 && in.peek_char() == '0' ) { + return; + } + + if( s > ( 1 << 20 ) ) { + throw std::runtime_error( "JSON number with 1 megabyte digits" ); + } + + const auto c = std::min( s, max_mantissa_digits ); + std::memcpy( result.mantissa, in.begin(), c ); + result.exponent10 += static_cast< typename number_state< NEG >::exponent10_t >( s - c ); + result.msize = static_cast< typename number_state< NEG >::msize_t >( c ); + + for( std::size_t i = c; i < s; ++i ) { + if( in.peek_char( i ) != '0' ) { + result.drop = true; + return; + } + } + } + }; + + template<> + struct action< rules::fdigits > + { + template< typename Input, bool NEG > + static void apply( const Input& in, number_state< NEG >& result ) + { + result.isfp = true; + + const auto* b = in.begin(); + const auto* e = in.end(); + + while( ( e > b ) && ( e[ -1 ] == '0' ) ) { + --e; + } + if( !result.msize ) { + while( ( b < e ) && ( b[ 0 ] == '0' ) ) { + ++b; + --result.exponent10; + } + } + const auto c = std::min( std::size_t( e - b ), max_mantissa_digits - result.msize ); + std::memcpy( result.mantissa + result.msize, b, c ); + result.exponent10 -= static_cast< typename number_state< NEG >::exponent10_t >( c ); + result.msize += static_cast< typename number_state< NEG >::msize_t >( c ); + + for( const auto* r = b + c; r < e; ++r ) { + if( *r != '0' ) { + result.drop = true; + return; + } + } + } + }; + + template<> + struct action< rules::edigits > + { + template< typename Input, bool NEG > + static void apply( const Input& in, number_state< NEG >& result ) + { + result.isfp = true; + + const char* b = in.begin(); + + while( ( b < in.end() ) && ( b[ 0 ] == '0' ) ) { + ++b; + } + if( ( in.end() - b ) > 9 ) { + throw std::runtime_error( "JSON exponent has more than 9 significant digits" ); + } + int exponent10 = 0; + + while( b < in.end() ) { + exponent10 = ( exponent10 * 10 ) + ( b[ 0 ] - '0' ); + ++b; + } + result.exponent10 += ( result.eneg ? -exponent10 : exponent10 ); + } + }; + + } // namespace jaxn + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/jaxn/binary_state.hpp b/include/tao/json/internal/jaxn/binary_state.hpp new file mode 100644 index 00000000..f5776bfa --- /dev/null +++ b/include/tao/json/internal/jaxn/binary_state.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_BINARY_STATE_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_BINARY_STATE_HPP + +#include +#include + +#include "../../external/byte.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + namespace jaxn + { + struct binary_state + { + binary_state() = default; + binary_state( const binary_state& ) = delete; + void operator=( const binary_state& ) = delete; + + template< typename Consumer > + void success( Consumer& consumer ) + { + consumer.binary( std::move( value ) ); + } + + std::vector< tao::byte > value; + }; + + } // namespace jaxn + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/jaxn/bunescape_action.hpp b/include/tao/json/internal/jaxn/bunescape_action.hpp new file mode 100644 index 00000000..45cbbeac --- /dev/null +++ b/include/tao/json/internal/jaxn/bunescape_action.hpp @@ -0,0 +1,123 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_BUNESCAPE_ACTION_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_BUNESCAPE_ACTION_HPP + +#include "../../external/pegtl/contrib/unescape.hpp" +#include "../../external/pegtl/nothing.hpp" + +#include "grammar.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + namespace jaxn + { + template< typename Rule > + struct bunescape_action : json_pegtl::nothing< Rule > + { + }; + + template<> + struct bunescape_action< rules::bescaped_char > + { + template< typename Input, typename State > + static void apply( const Input& in, State& st ) + { + switch( *in.begin() ) { + case '"': + st.value.push_back( tao::byte( '"' ) ); + break; + + case '\'': + st.value.push_back( tao::byte( '\'' ) ); + break; + + case '\\': + st.value.push_back( tao::byte( '\\' ) ); + break; + + case '/': + st.value.push_back( tao::byte( '/' ) ); + break; + + case 'b': + st.value.push_back( tao::byte( '\b' ) ); + break; + + case 'f': + st.value.push_back( tao::byte( '\f' ) ); + break; + + case 'n': + st.value.push_back( tao::byte( '\n' ) ); + break; + + case 'r': + st.value.push_back( tao::byte( '\r' ) ); + break; + + case 't': + st.value.push_back( tao::byte( '\t' ) ); + break; + + case 'v': + st.value.push_back( tao::byte( '\v' ) ); + break; + + case '0': + st.value.push_back( tao::byte( '\0' ) ); + break; + + default: + throw std::runtime_error( "invalid character in unescape" ); // LCOV_EXCL_LINE + } + } + }; + + template<> + struct bunescape_action< rules::bescaped_hexcode > + { + template< typename Input, typename State > + static void apply( const Input& in, State& st ) + { + assert( !in.empty() ); // First character MUST be present, usually 'x'. + st.value.push_back( static_cast< tao::byte >( json_pegtl::unescape::unhex_string< char >( in.begin() + 1, in.end() ) ) ); + } + }; + + template< char D > + struct bunescape_action< rules::bunescaped< D > > + { + template< typename Input, typename State > + static void apply( const Input& in, State& st ) + { + const auto begin = reinterpret_cast< const tao::byte* >( in.begin() ); + const auto end = begin + in.size(); + st.value.insert( st.value.end(), begin, end ); + } + }; + + template<> + struct bunescape_action< rules::bbyte > + { + template< typename Input, typename State > + static void apply( const Input& in, State& st ) + { + st.value.push_back( static_cast< tao::byte >( json_pegtl::unescape::unhex_string< char >( in.begin(), in.end() ) ) ); + } + }; + + } // namespace jaxn + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/jaxn/control.hpp b/include/tao/json/internal/jaxn/control.hpp new file mode 100644 index 00000000..a36128a7 --- /dev/null +++ b/include/tao/json/internal/jaxn/control.hpp @@ -0,0 +1,64 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_CONTROL_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_CONTROL_HPP + +#include "../../external/pegtl/contrib/changes.hpp" + +#include "binary_state.hpp" +#include "bunescape_action.hpp" +#include "errors.hpp" +#include "unescape_action.hpp" + +#include "../key_state.hpp" +#include "../number_state.hpp" +#include "../string_state.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + namespace jaxn + { + template< typename Rule > + struct control + : errors< Rule > + { + }; + + template< bool NEG > + struct control< rules::number< NEG > > + : json_pegtl::change_state< rules::number< NEG >, number_state< NEG >, errors > + { + }; + + template<> + struct control< rules::string > + : json_pegtl::change_state_and_action< rules::string, string_state, unescape_action, errors > + { + }; + + template<> + struct control< rules::key > + : json_pegtl::change_state_and_action< rules::key, key_state, unescape_action, errors > + { + }; + + template<> + struct control< rules::binary > + : json_pegtl::change_state_and_action< rules::binary, binary_state, bunescape_action, errors > + { + }; + + } // namespace jaxn + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/jaxn/errors.hpp b/include/tao/json/internal/jaxn/errors.hpp new file mode 100644 index 00000000..b8c8b3f6 --- /dev/null +++ b/include/tao/json/internal/jaxn/errors.hpp @@ -0,0 +1,121 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_ERRORS_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_ERRORS_HPP + +#include + +#include "../../external/pegtl/normal.hpp" +#include "../../external/pegtl/parse_error.hpp" + +#include "grammar.hpp" + +#if defined( _MSC_VER ) +#define WEAK_PREFIX __declspec( selectany ) +#define WEAK_SUFFIX +#else +#define WEAK_PREFIX +#define WEAK_SUFFIX __attribute__( ( weak ) ) +#endif + +namespace tao +{ + namespace json + { + namespace internal + { + namespace jaxn + { + template< typename Rule > + struct errors + : json_pegtl::normal< Rule > + { + static const std::string error_message; + + template< typename Input, typename... States > + static void raise( const Input& in, States&&... ) + { + throw json_pegtl::parse_error( error_message, in ); + } + + template< template< typename... > class Action, typename Input, typename... States > + static void apply0( const Input& in, States&&... st ) + { + try { + Action< Rule >::apply0( st... ); + } + catch( const json_pegtl::parse_error& ) { + throw; + } + catch( const std::exception& e ) { + throw json_pegtl::parse_error( e.what(), in ); + } + } + + template< template< typename... > class Action, typename Iterator, typename Input, typename... States > + static void apply( const Iterator& begin, const Input& in, States&&... st ) + { + try { + using action_t = typename Input::action_t; + const action_t action_input( begin, in ); + Action< Rule >::apply( action_input, st... ); + } + catch( const json_pegtl::parse_error& ) { + throw; + } + catch( const std::exception& e ) { + throw json_pegtl::parse_error( e.what(), in ); + } + } + }; + + // clang-format off + template<> WEAK_PREFIX const std::string errors< rules::text >::error_message WEAK_SUFFIX = "no valid JAXN"; + + template<> WEAK_PREFIX const std::string errors< rules::comment >::error_message WEAK_SUFFIX = "expected '*' or '/'"; + template<> WEAK_PREFIX const std::string errors< rules::line_comment_char >::error_message WEAK_SUFFIX = "invalid character in line comment"; + template<> WEAK_PREFIX const std::string errors< rules::block_comment_char >::error_message WEAK_SUFFIX = "invalid character in block comment"; + template<> WEAK_PREFIX const std::string errors< rules::end_block_comment >::error_message WEAK_SUFFIX = "unterminated multi-line comment"; + + template<> WEAK_PREFIX const std::string errors< rules::end_array >::error_message WEAK_SUFFIX = "incomplete array, expected value or ']'"; + template<> WEAK_PREFIX const std::string errors< rules::end_object >::error_message WEAK_SUFFIX = "incomplete object, expected key or '}'"; + template<> WEAK_PREFIX const std::string errors< rules::name_separator >::error_message WEAK_SUFFIX = "expected ':'"; + template<> WEAK_PREFIX const std::string errors< rules::value >::error_message WEAK_SUFFIX = "expected value"; + + template<> WEAK_PREFIX const std::string errors< rules::edigits >::error_message WEAK_SUFFIX = "expected at least one exponent digit"; + template<> WEAK_PREFIX const std::string errors< rules::fdigits >::error_message WEAK_SUFFIX = "expected at least one fraction digit"; + template<> WEAK_PREFIX const std::string errors< rules::nan >::error_message WEAK_SUFFIX = "invalid numeric literal"; + template<> WEAK_PREFIX const std::string errors< rules::infinity< false > >::error_message WEAK_SUFFIX = "invalid numeric literal"; + template<> WEAK_PREFIX const std::string errors< rules::infinity< true > >::error_message WEAK_SUFFIX = "invalid numeric literal"; + template<> WEAK_PREFIX const std::string errors< rules::hexnum< false > >::error_message WEAK_SUFFIX = "expected at least one hexadecimal digit"; + template<> WEAK_PREFIX const std::string errors< rules::hexnum< true > >::error_message WEAK_SUFFIX = "expected at least one hexadecimal digit"; + + template<> WEAK_PREFIX const std::string errors< rules::xdigit >::error_message WEAK_SUFFIX = "incomplete universal character name"; + template<> WEAK_PREFIX const std::string errors< rules::escaped >::error_message WEAK_SUFFIX = "unknown escape sequence in string"; + template<> WEAK_PREFIX const std::string errors< rules::chars< '"' > >::error_message WEAK_SUFFIX = "invalid character in string"; + template<> WEAK_PREFIX const std::string errors< rules::chars< '\'' > >::error_message WEAK_SUFFIX = "invalid character in string"; + template<> WEAK_PREFIX const std::string errors< rules::qstring_content< '"' > >::error_message WEAK_SUFFIX = "unterminated string"; + template<> WEAK_PREFIX const std::string errors< rules::qstring_content< '\'' > >::error_message WEAK_SUFFIX = "unterminated string"; + template<> WEAK_PREFIX const std::string errors< rules::string_fragment >::error_message WEAK_SUFFIX = "expected string"; + + template<> WEAK_PREFIX const std::string errors< rules::bescaped >::error_message WEAK_SUFFIX = "unknown escape sequence in binary string"; + template<> WEAK_PREFIX const std::string errors< rules::bchars< '"' > >::error_message WEAK_SUFFIX = "invalid character in binary string"; + template<> WEAK_PREFIX const std::string errors< rules::bchars< '\'' > >::error_message WEAK_SUFFIX = "invalid character in binary string"; + template<> WEAK_PREFIX const std::string errors< rules::bqstring_content< '"' > >::error_message WEAK_SUFFIX = "unterminated binary string"; + template<> WEAK_PREFIX const std::string errors< rules::bqstring_content< '\'' > >::error_message WEAK_SUFFIX = "unterminated binary string"; + template<> WEAK_PREFIX const std::string errors< rules::bvalue >::error_message WEAK_SUFFIX = "expected binary"; + template<> WEAK_PREFIX const std::string errors< rules::bpart >::error_message WEAK_SUFFIX = "expected a pair of hexadecimal digits"; + + template<> WEAK_PREFIX const std::string errors< json_pegtl::eof >::error_message WEAK_SUFFIX = "unexpected character after JAXN value"; + // clang-format on + + } // namespace jaxn + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/jaxn/grammar.hpp b/include/tao/json/internal/jaxn/grammar.hpp new file mode 100644 index 00000000..88ef5c42 --- /dev/null +++ b/include/tao/json/internal/jaxn/grammar.hpp @@ -0,0 +1,357 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_GRAMMAR_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_GRAMMAR_HPP + +#include "../../external/pegtl.hpp" +#include "../../external/pegtl/contrib/abnf.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + namespace jaxn + { + // clang-format off + namespace rules + { + using namespace json_pegtl; + + struct line_comment_char : sor< one< '\t' >, utf8::range< 0x20, 0x10FFFF > > {}; + struct line_comment : seq< one< '/' >, until< eolf, must< line_comment_char > > > {}; + + struct block_comment_char : sor< one< '\t' >, utf8::range< 0x20, 0x10FFFF >, eol > {}; + struct end_block_comment : until< json_pegtl::string< '*', '/' >, must< block_comment_char > > {}; + struct block_comment : if_must< one< '*' >, end_block_comment > {}; + + struct comment : sor< line_comment, block_comment > {}; + + struct ws : sor< one< ' ', '\t', '\n', '\r' >, seq< one< '#' >, until< eolf > >, if_must< one< '/' >, comment > > {}; + + template< typename R, typename P = ws > + using padr = json_pegtl::internal::seq< R, json_pegtl::internal::star< P > >; + + struct begin_array : padr< one< '[' > > {}; + struct begin_object : padr< one< '{' > > {}; + struct end_array : one< ']' > {}; + struct end_object : one< '}' > {}; + struct name_separator : pad< one< ':' >, ws > {}; + struct value_separator : padr< one< ',' > > {}; + struct element_separator : padr< one< ',' > > {}; + struct value_concat : pad< one< '+' >, ws > {}; + + struct false_ : TAOCPP_JSON_PEGTL_STRING( "false" ) {}; + struct null : TAOCPP_JSON_PEGTL_STRING( "null" ) {}; + struct true_ : TAOCPP_JSON_PEGTL_STRING( "true" ) {}; + + struct nan : TAOCPP_JSON_PEGTL_STRING( "NaN" ) {}; + + template< bool NEG > + struct infinity : TAOCPP_JSON_PEGTL_STRING( "Infinity" ) {}; + + template< bool NEG > + struct hexnum : plus< abnf::HEXDIG > {}; + + struct digits : plus< abnf::DIGIT > {}; + + struct esign : one< '-', '+' > {}; + + struct edigits : digits {}; + struct fdigits : digits {}; + struct idigits : digits {}; + + struct exp : seq< one< 'e', 'E' >, opt< esign >, must< edigits > > {}; + struct frac0 : seq< one< '.' >, opt< fdigits > > {}; + struct frac1 : if_must< one< '.' >, fdigits > {}; + + template< bool NEG > + struct number : seq< sor< seq< idigits, opt< frac0 > >, frac1 >, opt< exp > > {}; + + struct xdigit : abnf::HEXDIG {}; + struct escaped_unicode_code_point_content : seq< one< '{' >, plus< xdigit > > {}; + struct escaped_unicode_code_point : seq< one< 'u' >, escaped_unicode_code_point_content, one< '}' > > {}; + struct escaped_unicode : list< seq< one< 'u' >, rep< 4, xdigit > >, one< '\\' > > {}; + + struct escaped_char : one< '"', '\'', '\\', '/', 'b', 'f', 'n', 'r', 't', 'v', '0' > {}; + struct escaped : sor< escaped_char, escaped_unicode_code_point, escaped_unicode > {}; + + template< char D > + struct unescaped + { + using analyze_t = json_pegtl::analysis::generic< json_pegtl::analysis::rule_type::ANY >; + + template< typename Input > + static bool match( Input& in ) + { + bool result = false; + + while( !in.empty() ) { + if( const auto t = json_pegtl::internal::peek_utf8::peek( in ) ) { + if( ( 0x20 <= t.data ) && ( t.data <= 0x10FFFF ) && ( t.data != '\\' ) && ( t.data != D ) ) { + in.bump_in_this_line( t.size ); + result = true; + continue; + } + } + return result; + } + throw json_pegtl::parse_error( "invalid character in string", in ); + } + }; + + template< char D > + struct chars : if_then_else< one< '\\' >, must< escaped >, unescaped< D > > {}; + + template< char D > + struct qstring_content : until< at< one< D > >, must< chars< D > > > {}; + + template< char D > + struct qstring : seq< one< D >, must< qstring_content< D > >, any > {}; + + struct string_fragment : sor< qstring< '"' >, qstring< '\'' > > {}; + + struct string : list_must< string_fragment, value_concat > {}; + + struct binary_prefix : one< '$' > {}; + + struct bescaped_hexcode : seq< one< 'x' >, rep< 2, must< xdigit > > > {}; + + struct bescaped_char : one< '"', '\'', '\\', '/', 'b', 'f', 'n', 'r', 't', 'v', '0' > {}; + struct bescaped : sor< bescaped_char, bescaped_hexcode > {}; + + template< char D > + struct bunescaped + { + using analyze_t = json_pegtl::analysis::generic< json_pegtl::analysis::rule_type::ANY >; + + template< typename Input > + static bool match( Input& in ) + { + bool result = false; + + while( !in.empty() ) { + const auto t = in.peek_char(); + if( ( 0x20 <= t ) && ( t <= 0x7E ) && ( t != '\\' ) && ( t != D ) ) { + in.bump_in_this_line( 1 ); + result = true; + continue; + } + return result; + } + throw json_pegtl::parse_error( "invalid character in binary string", in ); + } + }; + + template< char D > + struct bchars : if_then_else< one< '\\' >, must< bescaped >, bunescaped< D > > {}; + + template< char D > + struct bqstring_content : until< at< one< D > >, must< bchars< D > > > {}; + + template< char D > + struct bqstring : seq< one< D >, must< bqstring_content< D > >, any > {}; + + struct bstring : sor< bqstring< '"' >, bqstring< '\'' > > {}; + + struct bbyte : rep< 2, abnf::HEXDIG > {}; + + struct bpart : plus< bbyte > {}; + + struct bdirect : list_must< bpart, one< '.' > > {}; + + struct bvalue : seq< binary_prefix, opt< sor< bstring, bdirect > > > {}; + + struct binary : list_must< bvalue, value_concat > {}; + + struct value; + + struct array_element; + struct array_content : opt< list_tail< array_element, element_separator > > {}; + struct array : seq< begin_array, array_content, must< end_array > > + { + using begin = begin_array; + using end = end_array; + using element = array_element; + using content = array_content; + }; + + struct key : string {}; + + struct identifier_first : ranges< 'a', 'z', 'A', 'Z', '_', '_', '$' > {}; + struct identifier_other : ranges< 'a', 'z', 'A', 'Z', '0', '9', '_', '_', '$' > {}; + struct identifier : seq< identifier_first, star< identifier_other > > {}; + + struct mkey : sor< key, identifier > {}; + struct member : if_must< mkey, name_separator, value > {}; + struct object_content : opt< list_tail< member, value_separator > > {}; + struct object : seq< begin_object, object_content, must< end_object > > + { + using begin = begin_object; + using end = end_object; + using element = member; + using content = object_content; + }; + + template< bool NEG > + struct zero {}; + + struct sor_value + { + using analyze_t = json_pegtl::analysis::generic< json_pegtl::analysis::rule_type::SOR, string, number< false >, object, array, false_, true_, null >; + + template< typename Rule, + apply_mode A, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match_must( Input& in, States&&... st ) + { + return Control< must< Rule > >::template match< A, rewind_mode::DONTCARE, Action, Control >( in, st... ); + } + + template< bool NEG, + apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match_zero( Input& in, States&&... st ) + { + if( in.size( 2 ) > 1 ) { + switch( in.peek_char( 1 ) ) { + case '.': + case 'e': + case 'E': + return Control< number< NEG > >::template match< A, M, Action, Control >( in, st... ); + + case 'x': + case 'X': + in.bump_in_this_line( 2 ); + return Control< must< hexnum< NEG > > >::template match< A, M, Action, Control >( in, st... ); + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + throw json_pegtl::parse_error( "invalid leading zero", in ); + } + } + in.bump_in_this_line(); + Control< zero< NEG > >::template apply0< Action >( in, st... ); + return true; + } + + template< bool NEG, + apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match_number( Input& in, States&&... st ) + { + switch( in.peek_char() ) { + case 'N': + return Control< must< nan > >::template match< A, M, Action, Control >( in, st... ); + + case 'I': + return Control< must< infinity< NEG > > >::template match< A, M, Action, Control >( in, st... ); + + case '0': + if( !match_zero< NEG, A, rewind_mode::DONTCARE, Action, Control >( in, st... ) ) { + throw json_pegtl::parse_error( "incomplete number", in ); + } + return true; + + default: + return Control< number< NEG > >::template match< A, M, Action, Control >( in, st... ); + } + } + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match_impl( Input& in, States&&... st ) + { + switch( in.peek_char() ) { + case '{': return Control< object >::template match< A, M, Action, Control >( in, st... ); + case '[': return Control< array >::template match< A, M, Action, Control >( in, st... ); + case 'n': return Control< null >::template match< A, M, Action, Control >( in, st... ); + case 't': return Control< true_ >::template match< A, M, Action, Control >( in, st... ); + case 'f': return Control< false_ >::template match< A, M, Action, Control >( in, st... ); + + case '"': + case '\'': + return Control< string >::template match< A, M, Action, Control >( in, st... ); + + case '$': + return Control< binary >::template match< A, M, Action, Control >( in, st... ); + + case '+': + in.bump_in_this_line(); + if( in.empty() || !match_number< false, A, rewind_mode::DONTCARE, Action, Control >( in, st... ) ) { + throw json_pegtl::parse_error( "incomplete number", in ); + } + return true; + + case '-': + in.bump_in_this_line(); + if( in.empty() || !match_number< true, A, rewind_mode::DONTCARE, Action, Control >( in, st... ) ) { + throw json_pegtl::parse_error( "incomplete number", in ); + } + return true; + + default: + return match_number< false, A, M, Action, Control >( in, st... ); + } + } + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + static bool match( Input& in, States&&... st ) + { + if( in.size( 2 ) && match_impl< A, M, Action, Control >( in, st... ) ) { + in.discard(); + return true; + } + return false; + } + }; + + struct value : padr< sor_value > {}; + struct array_element : value {}; + + struct text : seq< star< ws >, value > {}; + + } // namespace rules + + struct grammar : json_pegtl::must< rules::text, json_pegtl::eof > {}; + // clang-format on + + } // namespace jaxn + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/jaxn/unescape_action.hpp b/include/tao/json/internal/jaxn/unescape_action.hpp new file mode 100644 index 00000000..401e3172 --- /dev/null +++ b/include/tao/json/internal/jaxn/unescape_action.hpp @@ -0,0 +1,38 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_UNESCAPE_ACTION_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_UNESCAPE_ACTION_HPP + +#include "../../external/pegtl/contrib/unescape.hpp" +#include "../../external/pegtl/nothing.hpp" + +#include "grammar.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + namespace jaxn + { + // clang-format off + template< typename Rule > struct unescape_action : json_pegtl::nothing< Rule > {}; + + template<> struct unescape_action< rules::escaped_char > : json_pegtl::unescape::unescape_c< rules::escaped_char, '"', '\'', '\\', '/', '\b', '\f', '\n', '\r', '\t', '\v', '\0' > {}; + template<> struct unescape_action< rules::escaped_unicode > : json_pegtl::unescape::unescape_j {}; + template<> struct unescape_action< rules::escaped_unicode_code_point_content > : json_pegtl::unescape::unescape_u {}; + + template< char D > struct unescape_action< rules::unescaped< D > > : json_pegtl::unescape::append_all {}; + // clang-format on + + } // namespace jaxn + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/key_state.hpp b/include/tao/json/internal/key_state.hpp new file mode 100644 index 00000000..ca2b7131 --- /dev/null +++ b/include/tao/json/internal/key_state.hpp @@ -0,0 +1,37 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_KEY_STATE_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_KEY_STATE_HPP + +#include +#include + +namespace tao +{ + namespace json + { + namespace internal + { + struct key_state + { + key_state() = default; + key_state( const key_state& ) = delete; + void operator=( const key_state& ) = delete; + + template< typename Consumer > + void success( Consumer& consumer ) + { + consumer.key( std::move( unescaped ) ); + } + + std::string unescaped; + }; + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/number_state.hpp b/include/tao/json/internal/number_state.hpp new file mode 100644 index 00000000..844f2ee8 --- /dev/null +++ b/include/tao/json/internal/number_state.hpp @@ -0,0 +1,86 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_NUMBER_STATE_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_NUMBER_STATE_HPP + +#include +#include +#include +#include +#include + +#include "../external/double.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + static const std::size_t max_mantissa_digits = 772; + + template< bool NEG > + struct number_state + { + using exponent10_t = int32_t; + using msize_t = uint16_t; + + number_state() + { + } + + number_state( const number_state& ) = delete; + void operator=( const number_state& ) = delete; + + exponent10_t exponent10 = 0; + msize_t msize = 0; // Excluding sign. + bool isfp = false; + bool eneg = false; + bool drop = false; + char mantissa[ max_mantissa_digits + 1 ]; + + template< typename Consumer > + void success( Consumer& consumer ) + { + if( !isfp && msize <= 20 ) { + mantissa[ msize ] = 0; + char* p; + errno = 0; + const std::uint64_t ull = std::strtoull( mantissa, &p, 10 ); + if( ( errno != ERANGE ) && ( p == mantissa + msize ) ) { + if( NEG ) { + if( ull < 9223372036854775808ull ) { + consumer.number( -static_cast< std::int64_t >( ull ) ); + return; + } + else if( ull == 9223372036854775808ull ) { + consumer.number( static_cast< std::int64_t >( -9223372036854775807ll - 1 ) ); + return; + } + } + else { + consumer.number( ull ); + return; + } + } + } + if( drop ) { + mantissa[ msize++ ] = '1'; + --exponent10; + } + const auto d = json_double_conversion::Strtod( json_double_conversion::Vector< const char >( mantissa, msize ), exponent10 ); + if( !std::isfinite( d ) ) { + throw std::runtime_error( "invalid double value" ); + } + consumer.number( NEG ? -d : d ); + } + }; + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/sha256.hpp b/include/tao/json/internal/sha256.hpp new file mode 100644 index 00000000..2920ffca --- /dev/null +++ b/include/tao/json/internal/sha256.hpp @@ -0,0 +1,218 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_SHA256_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_SHA256_HPP + +// Implements RFC 6234, SHA-256 + +#include +#include +#include +#include + +#define DBL_INT_ADD( a, b, c ) \ + if( a > 0xffffffff - ( c ) ) \ + ++b; \ + a += c; + +// RFC 6234, 3.d; see also http://stackoverflow.com/a/4209604/2073257 +#define ROR( x, N ) ( ( x >> N ) | ( x << ( 32 - N ) ) ) + +// RFC 6234, 5.1 +#define CH( x, y, z ) ( ( x & y ) ^ ( ~x & z ) ) +#define MAJ( x, y, z ) ( ( x & y ) ^ ( x & z ) ^ ( y & z ) ) +#define BSIG0( x ) ( ROR( x, 2 ) ^ ROR( x, 13 ) ^ ROR( x, 22 ) ) +#define BSIG1( x ) ( ROR( x, 6 ) ^ ROR( x, 11 ) ^ ROR( x, 25 ) ) +#define SSIG0( x ) ( ROR( x, 7 ) ^ ROR( x, 18 ) ^ ( x >> 3 ) ) +#define SSIG1( x ) ( ROR( x, 17 ) ^ ROR( x, 19 ) ^ ( x >> 10 ) ) + +namespace tao +{ + namespace json + { + namespace internal + { + // RFC 6234, 5.1 + // clang-format off + static std::uint32_t K[ 64 ] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + }; + // clang-format on + + class sha256 + { + private: + unsigned char M[ 64 ]; + std::size_t size; + + std::uint32_t H[ 8 ]; + + // RFC 6234, 6.2 + void process() noexcept + { + std::uint32_t W[ 64 ]; + + // step 1 + for( std::size_t t = 0, i = 0; t != 16; ++t, i += 4 ) { + W[ t ] = ( M[ i ] << 24 ) | ( M[ i + 1 ] << 16 ) | ( M[ i + 2 ] << 8 ) | ( M[ i + 3 ] ); + } + for( std::size_t t = 16; t != 64; ++t ) { + W[ t ] = SSIG1( W[ t - 2 ] ) + W[ t - 7 ] + SSIG0( W[ t - 15 ] ) + W[ t - 16 ]; + } + + // step 2 + std::uint32_t a, b, c, d, e, f, g, h; + a = H[ 0 ]; + b = H[ 1 ]; + c = H[ 2 ]; + d = H[ 3 ]; + e = H[ 4 ]; + f = H[ 5 ]; + g = H[ 6 ]; + h = H[ 7 ]; + + // step 3 + for( std::size_t t = 0; t != 64; ++t ) { + const std::uint32_t T1 = h + BSIG1( e ) + CH( e, f, g ) + K[ t ] + W[ t ]; + const std::uint32_t T2 = BSIG0( a ) + MAJ( a, b, c ); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + // step 4 + H[ 0 ] += a; + H[ 1 ] += b; + H[ 2 ] += c; + H[ 3 ] += d; + H[ 4 ] += e; + H[ 5 ] += f; + H[ 6 ] += g; + H[ 7 ] += h; + } + + public: + sha256() noexcept + { + reset(); + } + + sha256( const sha256& ) = delete; + void operator=( const sha256& ) = delete; + + void reset() noexcept + { + size = 0; + + // RFC 6234, 6.1 + H[ 0 ] = 0x6a09e667; + H[ 1 ] = 0xbb67ae85; + H[ 2 ] = 0x3c6ef372; + H[ 3 ] = 0xa54ff53a; + H[ 4 ] = 0x510e527f; + H[ 5 ] = 0x9b05688c; + H[ 6 ] = 0x1f83d9ab; + H[ 7 ] = 0x5be0cd19; + } + + void feed( const unsigned char c ) noexcept + { + M[ size++ % 64 ] = c; + if( ( size % 64 ) == 0 ) { + process(); + } + } + + void feed( const void* p, std::size_t s ) noexcept + { + const unsigned char* q = static_cast< const unsigned char* >( p ); + while( s-- ) { + feed( *q++ ); + } + } + + void feed( const std::string& v ) noexcept + { + feed( v.data(), v.size() ); + } + + // RFC 6234, 4.1 + void store_unsafe( unsigned char* buffer ) noexcept + { + std::size_t i = size % 64; + if( i < 56 ) { + M[ i++ ] = 0x80; + while( i < 56 ) { + M[ i++ ] = 0x00; + } + } + else { + M[ i++ ] = 0x80; + while( i < 64 ) { + M[ i++ ] = 0x00; + } + process(); + std::memset( M, 0, 56 ); + } + + size *= 8; + + M[ 63 ] = size; + M[ 62 ] = size >> 8; + M[ 61 ] = size >> 16; + M[ 60 ] = size >> 24; + M[ 59 ] = size >> 32; + M[ 58 ] = size >> 40; + M[ 57 ] = size >> 48; + M[ 56 ] = size >> 56; + + process(); + + for( std::size_t j = 0; j < 4; ++j ) { + buffer[ j ] = ( H[ 0 ] >> ( 24 - j * 8 ) ) & 0xff; + buffer[ j + 4 ] = ( H[ 1 ] >> ( 24 - j * 8 ) ) & 0xff; + buffer[ j + 8 ] = ( H[ 2 ] >> ( 24 - j * 8 ) ) & 0xff; + buffer[ j + 12 ] = ( H[ 3 ] >> ( 24 - j * 8 ) ) & 0xff; + buffer[ j + 16 ] = ( H[ 4 ] >> ( 24 - j * 8 ) ) & 0xff; + buffer[ j + 20 ] = ( H[ 5 ] >> ( 24 - j * 8 ) ) & 0xff; + buffer[ j + 24 ] = ( H[ 6 ] >> ( 24 - j * 8 ) ) & 0xff; + buffer[ j + 28 ] = ( H[ 7 ] >> ( 24 - j * 8 ) ) & 0xff; + } + } + + std::string get() + { + unsigned char result[ 32 ]; + store_unsafe( result ); + return std::string( reinterpret_cast< const char* >( result ), 32 ); + } + }; + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/string_state.hpp b/include/tao/json/internal/string_state.hpp new file mode 100644 index 00000000..f7156627 --- /dev/null +++ b/include/tao/json/internal/string_state.hpp @@ -0,0 +1,37 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_STRING_STATE_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_STRING_STATE_HPP + +#include +#include + +namespace tao +{ + namespace json + { + namespace internal + { + struct string_state + { + string_state() = default; + string_state( const string_state& ) = delete; + void operator=( const string_state& ) = delete; + + template< typename Consumer > + void success( Consumer& consumer ) + { + consumer.string( std::move( unescaped ) ); + } + + std::string unescaped; + }; + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/throw.hpp b/include/tao/json/internal/throw.hpp new file mode 100644 index 00000000..c4caf5a7 --- /dev/null +++ b/include/tao/json/internal/throw.hpp @@ -0,0 +1,24 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_THROW_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_THROW_HPP + +#include +#include + +#include "../type.hpp" + +#define TAOCPP_JSON_THROW_TYPE_ERROR( TyPe ) \ + do { \ + throw std::logic_error( std::string( "invalid json type '" ) + to_string( TyPe ) + '\'' ); \ + } while( false ) + +#define TAOCPP_JSON_CHECK_TYPE_ERROR( HaVe, NeeD ) \ + do { \ + if( ( HaVe ) != ( NeeD ) ) { \ + TAOCPP_JSON_THROW_TYPE_ERROR( HaVe ); \ + } \ + } while( false ) + +#endif diff --git a/include/tao/json/internal/unescape_action.hpp b/include/tao/json/internal/unescape_action.hpp new file mode 100644 index 00000000..1f32f5cf --- /dev/null +++ b/include/tao/json/internal/unescape_action.hpp @@ -0,0 +1,32 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_UNESCAPE_ACTION_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_UNESCAPE_ACTION_HPP + +#include "../external/pegtl/contrib/unescape.hpp" +#include "../external/pegtl/nothing.hpp" + +#include "grammar.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + // clang-format off + template< typename Rule > struct unescape_action : json_pegtl::nothing< Rule > {}; + + template<> struct unescape_action< rules::escaped_unicode > : json_pegtl::unescape::unescape_j {}; + template<> struct unescape_action< rules::escaped_char > : json_pegtl::unescape::unescape_c< rules::escaped_char, '"', '\\', '/', '\b', '\f', '\n', '\r', '\t' > {}; + template<> struct unescape_action< rules::unescaped > : json_pegtl::unescape::append_all {}; + // clang-format on + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/uri_fragment.hpp b/include/tao/json/internal/uri_fragment.hpp new file mode 100644 index 00000000..a42b825c --- /dev/null +++ b/include/tao/json/internal/uri_fragment.hpp @@ -0,0 +1,188 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_URI_FRAGMENT_HPP +#define TAOCPP_JSON_INCLUDE_URI_FRAGMENT_HPP + +#include "../pointer.hpp" + +#include + +namespace tao +{ + namespace json + { + namespace internal + { + // clang-format off + const bool allowed_uri_fragment_characters[] = { + false, false, false, false, false, false, false, false, // 0 + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, // 16 + false, false, false, false, false, false, false, false, + false, true, false, false, true, false, true, true, // 32 + true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, // 48 + true, true, true, true, false, true, false, true, + true, true, true, true, true, true, true, true, // 64 + true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, // 80 + true, true, true, false, false, false, false, true, + false, true, true, true, true, true, true, true, // 96 + true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, // 112 + true, true, true, false, false, false, true, false, + false, false, false, false, false, false, false, false, // 128 + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false + }; + // clang-format on + + inline char xdigit_value( const char c ) + { + // clang-format off + switch ( c ) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + case 'a': case 'A': return 10; + case 'b': case 'B': return 11; + case 'c': case 'C': return 12; + case 'd': case 'D': return 13; + case 'e': case 'E': return 14; + case 'f': case 'F': return 15; + } + // clang-format on + throw std::invalid_argument( "invalid URI Fragment escape sequence, '%' must be followed by two hexadecimal digits" ); + } + + inline pointer uri_fragment_to_pointer( const std::string& v ) + { + pointer result; + if( v.empty() || v[ 0 ] != '#' ) { + throw std::invalid_argument( "invalid URI Fragment value, must begin with '#'" ); + } + if( v.size() > 1 ) { + const char* p = v.data() + 1; + const char* const e = v.data() + v.size(); + if( *p++ != '/' ) { + throw std::invalid_argument( "invalid JSON Pointer value, must be empty or begin with '/'" ); + } + std::string token; + while( p != e ) { + const char c = *p++; + switch( c ) { + // clang-format off + case '!': case '$': case '&': case '\'': case '(': case ')': case '*': case '+': case ',': case '-': case '.': + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': + case ':': case ';': case '=': case '?': case '@': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': + case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': + case '_': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': + case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': + // clang-format on + token += c; + continue; + + case '%': + if( p != e ) { + const char h1 = xdigit_value( *p++ ); + if( p != e ) { + const char h2 = xdigit_value( *p++ ); + token += h1 * 16 + h2; + continue; + } + } + throw std::invalid_argument( "invalid URI Fragment escape sequence, '%' must be followed by two hexadecimal digits" ); + + case '~': + if( p != e ) { + switch( *p++ ) { + case '0': + token += '~'; + continue; + case '1': + token += '/'; + continue; + } + } + throw std::invalid_argument( "invalid JSON Pointer escape sequence, '~' must be followed by '0' or '1'" ); + + case '/': + result += std::move( token ); + token.clear(); + continue; + + default: + throw std::invalid_argument( "invalid URI Fragment character" ); + } + } + result += std::move( token ); + } + return result; + } + + inline std::string tokens_to_uri_fragment( std::vector< token >::const_iterator it, const std::vector< token >::const_iterator& end ) + { + static const char* hex = "0123456789ABCDEF"; + + std::string result = "#"; + while( it != end ) { + result += '/'; + for( const unsigned char c : it->key() ) { + switch( c ) { + case '~': + result += "~0"; + break; + case '/': + result += "~1"; + break; + default: + if( allowed_uri_fragment_characters[ c ] ) { + result += c; + } + else { + result += '%'; + result += hex[ c >> 4 ]; + result += hex[ c & 15 ]; + } + } + } + ++it; + } + return result; + } + + inline std::string to_uri_fragment( const pointer& p ) + { + return tokens_to_uri_fragment( p.begin(), p.end() ); + } + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/internal/value_union.hpp b/include/tao/json/internal/value_union.hpp new file mode 100644 index 00000000..f8ff94a0 --- /dev/null +++ b/include/tao/json/internal/value_union.hpp @@ -0,0 +1,62 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_VALUE_UNION_HPP +#define TAOCPP_JSON_INCLUDE_INTERNAL_VALUE_UNION_HPP + +#include +#include +#include +#include + +#include "../byte_view.hpp" + +#include "../external/byte.hpp" +#include "../external/string_view.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + template< typename T > + union value_union + { + value_union() noexcept + { + } + + value_union( const value_union& ) = delete; + void operator=( const value_union& ) = delete; + + ~value_union() noexcept + { + } + + bool b; + + std::int64_t i; + std::uint64_t u; + double d; + + std::string s; + tao::string_view sv; + + std::vector< tao::byte > x; + tao::byte_view xv; + + std::vector< T > a; + + std::map< std::string, T > o; + + const T* p; + }; + + } // namespace internal + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/jaxn.hpp b/include/tao/json/jaxn.hpp new file mode 100644 index 00000000..2a7fc9c7 --- /dev/null +++ b/include/tao/json/jaxn.hpp @@ -0,0 +1,14 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_JAXN_HPP +#define TAOCPP_JSON_INCLUDE_JAXN_HPP + +#include "../json.hpp" + +#include "jaxn/from_stream.hpp" +#include "jaxn/from_string.hpp" +#include "jaxn/to_stream.hpp" +#include "jaxn/to_string.hpp" + +#endif diff --git a/include/tao/json/jaxn/from_stream.hpp b/include/tao/json/jaxn/from_stream.hpp new file mode 100644 index 00000000..32888ff9 --- /dev/null +++ b/include/tao/json/jaxn/from_stream.hpp @@ -0,0 +1,54 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_JAXN_FROM_STREAM_HPP +#define TAOCPP_JSON_INCLUDE_JAXN_FROM_STREAM_HPP + +#include +#include +#include + +#include "../events/to_stream.hpp" +#include "../events/transformer.hpp" + +#include "../events/jaxn/from_stream.hpp" + +namespace tao +{ + namespace json + { + namespace jaxn + { + template< template< typename... > class Traits, template< typename... > class... Transformers > + basic_value< Traits > basic_from_stream( std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) + { + events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; + events::jaxn::from_stream( consumer, stream, source, maximum_buffer_size ); + return std::move( consumer.value ); + } + + template< template< typename... > class Traits, template< typename... > class... Transformers > + basic_value< Traits > basic_from_stream( std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) + { + return basic_from_stream< Traits, Transformers... >( stream, source.c_str(), maximum_buffer_size ); + } + + template< template< typename... > class... Transformers > + value from_stream( std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) + { + return basic_from_stream< traits, Transformers... >( stream, source, maximum_buffer_size ); + } + + template< template< typename... > class... Transformers > + value from_stream( std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) + { + return basic_from_stream< traits, Transformers... >( stream, source.c_str(), maximum_buffer_size ); + } + + } // namespace jaxn + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/jaxn/from_string.hpp b/include/tao/json/jaxn/from_string.hpp new file mode 100644 index 00000000..7d2f2c5d --- /dev/null +++ b/include/tao/json/jaxn/from_string.hpp @@ -0,0 +1,50 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_JAXN_FROM_STRING_HPP +#define TAOCPP_JSON_INCLUDE_JAXN_FROM_STRING_HPP + +#include +#include + +#include "../events/to_value.hpp" +#include "../events/transformer.hpp" + +#include "../events/jaxn/from_string.hpp" + +namespace tao +{ + namespace json + { + namespace jaxn + { + template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > + basic_value< Traits > basic_from_string( Ts&&... ts ) + { + events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; + events::jaxn::from_string( consumer, std::forward< Ts >( ts )... ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers, typename... Ts > + value from_string( Ts&&... ts ) + { + return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); + } + + inline namespace literals + { + inline value operator"" _jaxn( const char* data, const std::size_t size ) + { + return jaxn::from_string( data, size, "literal" ); + } + + } // namespace literals + + } // namespace jaxn + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/jaxn/is_identifier.hpp b/include/tao/json/jaxn/is_identifier.hpp new file mode 100644 index 00000000..e8c15656 --- /dev/null +++ b/include/tao/json/jaxn/is_identifier.hpp @@ -0,0 +1,35 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_JAXN_IS_IDENTIFIER_HPP +#define TAOCPP_JSON_INCLUDE_JAXN_IS_IDENTIFIER_HPP + +#include +#include + +namespace tao +{ + namespace json + { + namespace jaxn + { + inline bool is_identifier( const tao::string_view v ) noexcept + { + if( v.empty() || std::isdigit( v[ 0 ] ) ) { + return false; + } + for( const auto c : v ) { + if( !std::isalnum( c ) && c != '_' ) { + return false; + } + } + return true; + } + + } // namespace jaxn + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/jaxn/parse_file.hpp b/include/tao/json/jaxn/parse_file.hpp new file mode 100644 index 00000000..d2c82834 --- /dev/null +++ b/include/tao/json/jaxn/parse_file.hpp @@ -0,0 +1,41 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_JAXN_PARSE_FILE_HPP +#define TAOCPP_JSON_INCLUDE_JAXN_PARSE_FILE_HPP + +#include +#include + +#include "../events/to_value.hpp" +#include "../events/transformer.hpp" + +#include "../events/jaxn/parse_file.hpp" + +namespace tao +{ + namespace json + { + namespace jaxn + { + template< template< typename... > class Traits, template< typename... > class... Transformers > + basic_value< Traits > basic_parse_file( const std::string& filename ) + { + events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; + events::jaxn::parse_file( consumer, filename ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers > + value parse_file( const std::string& filename ) + { + return basic_parse_file< traits, Transformers... >( filename ); + } + + } // namespace jaxn + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/jaxn/to_stream.hpp b/include/tao/json/jaxn/to_stream.hpp new file mode 100644 index 00000000..5bd4d19f --- /dev/null +++ b/include/tao/json/jaxn/to_stream.hpp @@ -0,0 +1,44 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_JAXN_TO_STREAM_HPP +#define TAOCPP_JSON_INCLUDE_JAXN_TO_STREAM_HPP + +#include +#include + +#include "../value.hpp" + +#include "../events/from_value.hpp" +#include "../events/transformer.hpp" + +#include "../events/jaxn/to_pretty_stream.hpp" +#include "../events/jaxn/to_stream.hpp" + +namespace tao +{ + namespace json + { + namespace jaxn + { + template< template< typename... > class... Transformers, template< typename... > class Traits > + void to_stream( std::ostream& os, const basic_value< Traits >& v ) + { + events::transformer< events::jaxn::to_stream, Transformers... > consumer( os ); + events::from_value( consumer, v ); + } + + template< template< typename... > class... Transformers, template< typename... > class Traits > + void to_stream( std::ostream& os, const basic_value< Traits >& v, const std::size_t indent ) + { + events::transformer< events::jaxn::to_pretty_stream, Transformers... > consumer( os, indent ); + events::from_value( consumer, v ); + } + + } // namespace jaxn + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/jaxn/to_string.hpp b/include/tao/json/jaxn/to_string.hpp new file mode 100644 index 00000000..bff574b3 --- /dev/null +++ b/include/tao/json/jaxn/to_string.hpp @@ -0,0 +1,41 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_JAXN_TO_STRING_HPP +#define TAOCPP_JSON_INCLUDE_JAXN_TO_STRING_HPP + +#include + +#include "../value.hpp" + +#include "to_stream.hpp" + +namespace tao +{ + namespace json + { + namespace jaxn + { + template< template< typename... > class... Transformers, template< typename... > class Traits > + std::string to_string( const basic_value< Traits >& v ) + { + std::ostringstream o; + jaxn::to_stream< Transformers... >( o, v ); + return o.str(); + } + + template< template< typename... > class... Transformers, template< typename... > class Traits > + std::string to_string( const basic_value< Traits >& v, const unsigned indent ) + { + std::ostringstream o; + jaxn::to_stream< Transformers... >( o, v, indent ); + return o.str(); + } + + } // namespace jaxn + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/msgpack.hpp b/include/tao/json/msgpack.hpp new file mode 100644 index 00000000..4a6fbf94 --- /dev/null +++ b/include/tao/json/msgpack.hpp @@ -0,0 +1,13 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_MSGPACK_HPP +#define TAOCPP_JSON_INCLUDE_MSGPACK_HPP + +#include "../json.hpp" + +#include "msgpack/from_string.hpp" +#include "msgpack/to_stream.hpp" +#include "msgpack/to_string.hpp" + +#endif diff --git a/include/tao/json/msgpack/from_string.hpp b/include/tao/json/msgpack/from_string.hpp new file mode 100644 index 00000000..6416b4a9 --- /dev/null +++ b/include/tao/json/msgpack/from_string.hpp @@ -0,0 +1,40 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_MSGPACK_FROM_STRING_HPP +#define TAOCPP_JSON_INCLUDE_MSGPACK_FROM_STRING_HPP + +#include + +#include "../events/to_value.hpp" +#include "../events/transformer.hpp" + +#include "../events/msgpack/from_string.hpp" + +namespace tao +{ + namespace json + { + namespace msgpack + { + template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > + basic_value< Traits > basic_from_string( Ts&&... ts ) + { + events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; + events::msgpack::from_string( consumer, std::forward< Ts >( ts )... ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers, typename... Ts > + value from_string( Ts&&... ts ) + { + return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); + } + + } // namespace msgpack + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/msgpack/to_stream.hpp b/include/tao/json/msgpack/to_stream.hpp new file mode 100644 index 00000000..dd16fb1e --- /dev/null +++ b/include/tao/json/msgpack/to_stream.hpp @@ -0,0 +1,35 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_MSGPACK_TO_STREAM_HPP +#define TAOCPP_JSON_INCLUDE_MSGPACK_TO_STREAM_HPP + +#include + +#include "../value.hpp" + +#include "../events/from_value.hpp" +#include "../events/transformer.hpp" + +#include "../events/msgpack/to_stream.hpp" + +namespace tao +{ + namespace json + { + namespace msgpack + { + template< template< typename... > class... Transformers, template< typename... > class Traits > + void to_stream( std::ostream& os, const basic_value< Traits >& v ) + { + events::transformer< events::msgpack::to_stream, Transformers... > consumer( os ); + events::from_value( consumer, v ); + } + + } // namespace msgpack + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/msgpack/to_string.hpp b/include/tao/json/msgpack/to_string.hpp new file mode 100644 index 00000000..feed0c2a --- /dev/null +++ b/include/tao/json/msgpack/to_string.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_MSGPACK_TO_STRING_HPP +#define TAOCPP_JSON_INCLUDE_MSGPACK_TO_STRING_HPP + +#include + +#include "../value.hpp" + +#include "../events/from_value.hpp" +#include "../events/transformer.hpp" + +#include "../events/msgpack/to_string.hpp" + +namespace tao +{ + namespace json + { + namespace msgpack + { + template< template< typename... > class... Transformers, template< typename... > class Traits > + std::string to_string( const basic_value< Traits >& v ) + { + events::transformer< events::msgpack::to_string, Transformers... > consumer; + events::from_value( consumer, v ); + return consumer.value(); + } + + } // namespace msgpack + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/pair.hpp b/include/tao/json/pair.hpp new file mode 100644 index 00000000..45e90647 --- /dev/null +++ b/include/tao/json/pair.hpp @@ -0,0 +1,66 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_PAIR_HPP +#define TAOCPP_JSON_INCLUDE_PAIR_HPP + +#include +#include +#include + +namespace tao +{ + namespace json + { + template< template< typename... > class Traits > + class basic_value; + + template< template< typename... > class Traits > + struct pair + { + mutable std::string key; + mutable basic_value< Traits > value; + + template< typename U > + pair( U&& v ) + : key( Traits< typename std::decay< U >::type >::default_key ), + value( std::forward< U >( v ) ) + { + } + + pair( std::string&& k, basic_value< Traits >&& v ) + : key( std::move( k ) ), value( std::move( v ) ) + { + } + + pair( std::string&& k, const basic_value< Traits >& v ) + : key( std::move( k ) ), value( v ) + { + } + + pair( const std::string& k, basic_value< Traits >&& v ) + : key( k ), value( std::move( v ) ) + { + } + + pair( const std::string& k, const basic_value< Traits >& v ) + : key( k ), value( v ) + { + } + + pair( const char* k, basic_value< Traits >&& v ) + : key( k ), value( std::move( v ) ) + { + } + + pair( const char* k, const basic_value< Traits >& v ) + : key( k ), value( v ) + { + } + }; + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/parse_file.hpp b/include/tao/json/parse_file.hpp new file mode 100644 index 00000000..01985390 --- /dev/null +++ b/include/tao/json/parse_file.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_PARSE_FILE_HPP +#define TAOCPP_JSON_INCLUDE_PARSE_FILE_HPP + +#include +#include + +#include "events/parse_file.hpp" +#include "events/to_value.hpp" +#include "events/transformer.hpp" + +namespace tao +{ + namespace json + { + template< template< typename... > class Traits, template< typename... > class... Transformers > + basic_value< Traits > basic_parse_file( const std::string& filename ) + { + events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; + events::parse_file( consumer, filename ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers > + value parse_file( const std::string& filename ) + { + return basic_parse_file< traits, Transformers... >( filename ); + } + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/patch.hpp b/include/tao/json/patch.hpp new file mode 100644 index 00000000..08483643 --- /dev/null +++ b/include/tao/json/patch.hpp @@ -0,0 +1,109 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_PATCH_HPP +#define TAOCPP_JSON_INCLUDE_PATCH_HPP + +#include +#include + +#include "pointer.hpp" +#include "value.hpp" + +namespace tao +{ + namespace json + { + template< template< typename... > class Traits > + void patch_inplace( basic_value< Traits >& v, const basic_value< Traits >& patch ) + { + for( const auto& entry : patch.get_array() ) { + const auto& op = entry.at( "op" ).get_string(); + const auto& path = entry.at( "path" ).get_string(); + const pointer path_pointer( path ); + if( op == "test" ) { + if( v.at( path_pointer ) != entry.at( "value" ) ) { + throw std::runtime_error( "test failed for: " + path ); + } + } + else if( op == "remove" ) { + v.erase( path_pointer ); + } + else if( op == "add" ) { + v.insert( path_pointer, entry.at( "value" ) ); + } + else if( op == "replace" ) { + v.at( path_pointer ) = entry.at( "value" ); + } + else if( op == "move" ) { + const pointer from( entry.at( "from" ).get_string() ); + auto t = std::move( v.at( from ) ); + v.erase( from ); + v.insert( path_pointer, std::move( t ) ); + } + else if( op == "copy" ) { + const pointer from( entry.at( "from" ).get_string() ); + v.insert( path_pointer, v.at( from ) ); + } + else { + throw std::runtime_error( "unknown patch operation: '" + op + '\'' ); + } + } + } + + template< template< typename... > class Traits > + void patch_inplace( basic_value< Traits >& v, basic_value< Traits >&& patch ) + { + for( const auto& entry : patch.get_array() ) { + const auto& op = entry.at( "op" ).get_string(); + const auto& path = entry.at( "path" ).get_string(); + const pointer path_pointer( path ); + if( op == "test" ) { + if( v.at( path_pointer ) != entry.at( "value" ) ) { + throw std::runtime_error( "test failed for: " + path ); + } + } + else if( op == "remove" ) { + v.erase( path_pointer ); + } + else if( op == "add" ) { + v.insert( path_pointer, std::move( entry.at( "value" ) ) ); + } + else if( op == "replace" ) { + v.at( path_pointer ) = std::move( entry.at( "value" ) ); + } + else if( op == "move" ) { + const pointer from( entry.at( "from" ).get_string() ); + auto t = std::move( v.at( from ) ); + v.erase( from ); + v.insert( path_pointer, std::move( t ) ); + } + else if( op == "copy" ) { + const pointer from( entry.at( "from" ).get_string() ); + v.insert( path_pointer, v.at( from ) ); + } + else { + throw std::runtime_error( "unknown patch operation: '" + op + '\'' ); + } + } + } + + template< template< typename... > class Traits > + basic_value< Traits > patch( basic_value< Traits > v, const basic_value< Traits >& patch ) + { + patch_inplace( v, patch ); + return v; + } + + template< template< typename... > class Traits > + basic_value< Traits > patch( basic_value< Traits > v, basic_value< Traits >&& patch ) + { + patch_inplace( v, std::move( patch ) ); + return v; + } + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/pointer.hpp b/include/tao/json/pointer.hpp new file mode 100644 index 00000000..8ff08257 --- /dev/null +++ b/include/tao/json/pointer.hpp @@ -0,0 +1,307 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_POINTER_HPP +#define TAOCPP_JSON_INCLUDE_POINTER_HPP + +#include +#include +#include +#include +#include + +#include "type.hpp" + +#include "external/operators.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + std::size_t token_to_index( const std::string& key ); + + } // namespace internal + + // RFC 6901 + class token + { + private: + std::size_t m_index; + std::string m_key; + + public: + explicit token( const std::string& in_key ) + : m_index( internal::token_to_index( in_key ) ), + m_key( in_key ) + { + } + + explicit token( std::string&& in_key ) + : m_index( internal::token_to_index( in_key ) ), + m_key( std::move( in_key ) ) + { + } + + token( const token& ) = default; + token( token&& v ) noexcept + : m_index( v.m_index ), + m_key( std::move( v.m_key ) ) + { + } + + token& operator=( const token& ) = default; + token& operator=( token&& v ) noexcept + { + m_index = v.m_index; + m_key = std::move( v.m_key ); + return *this; + } + + const std::string& key() const + { + return m_key; + } + + std::size_t index() const + { + if( m_index == std::string::npos ) { + throw std::invalid_argument( "unable to resolve JSON Pointer, invalid token for array access '" + m_key + '\'' ); + } + return m_index; + } + + friend bool operator==( const token& lhs, const token& rhs ) + { + return lhs.m_key == rhs.m_key; + } + + friend bool operator<( const token& lhs, const token& rhs ) + { + return lhs.m_key < rhs.m_key; + } + }; + + class pointer + : operators::totally_ordered< pointer > + { + private: + std::vector< token > m_tokens; + + static std::vector< token > parse( const std::string& v ) + { + std::vector< token > result; + if( !v.empty() ) { + const char* p = v.data(); + const char* const e = p + v.size(); + if( *p++ != '/' ) { + throw std::invalid_argument( "invalid JSON Pointer value, must be empty or begin with '/'" ); + } + std::string token; + while( p != e ) { + const char c = *p++; + switch( c ) { + case '~': + if( p != e ) { + switch( *p++ ) { + case '0': + token += '~'; + continue; + case '1': + token += '/'; + continue; + } + } + throw std::invalid_argument( "invalid JSON Pointer escape sequence, '~' must be followed by '0' or '1'" ); + + case '/': + result.emplace_back( std::move( token ) ); + token.clear(); + continue; + + default: + token += c; + } + } + result.emplace_back( std::move( token ) ); + } + return result; + } + + public: + pointer() = default; + + pointer( const pointer& ) = default; + + pointer( pointer&& p ) noexcept + : m_tokens( std::move( p.m_tokens ) ) + { + } + + explicit pointer( const std::string& v ) + : m_tokens( parse( v ) ) + { + } + + pointer& operator=( const pointer& ) = default; + + pointer& operator=( pointer&& p ) noexcept + { + m_tokens = std::move( p.m_tokens ); + return *this; + } + + pointer& operator=( const std::string& v ) + { + m_tokens = parse( v ); + return *this; + } + + explicit operator bool() const noexcept + { + return !m_tokens.empty(); + } + + std::vector< token >::const_iterator begin() const noexcept + { + return m_tokens.begin(); + } + + std::vector< token >::const_iterator end() const noexcept + { + return m_tokens.end(); + } + + void push_back( const std::string& v ) + { + m_tokens.push_back( token( v ) ); + } + + void push_back( std::string&& v ) + { + m_tokens.push_back( token( std::move( v ) ) ); + } + + pointer& operator+=( const std::string& v ) + { + push_back( v ); + return *this; + } + + pointer& operator+=( std::string&& v ) + { + push_back( std::move( v ) ); + return *this; + } + + friend bool operator==( const pointer& lhs, const pointer& rhs ) noexcept + { + return lhs.m_tokens == rhs.m_tokens; + } + + friend bool operator<( const pointer& lhs, const pointer& rhs ) noexcept + { + return lhs.m_tokens < rhs.m_tokens; + } + }; + + inline pointer operator+( const pointer& p, const std::string& v ) + { + pointer nrv( p ); + nrv += v; + return nrv; + } + + inline pointer operator+( const pointer& p, std::string&& v ) + { + pointer nrv( p ); + nrv += std::move( v ); + return nrv; + } + + namespace internal + { + inline std::size_t token_to_index( const std::string& key ) + { + if( !key.empty() && key.size() <= 20 ) { + if( key == "0" ) { + return 0; + } + else if( ( key[ 0 ] != '0' ) && ( key.find_first_not_of( "0123456789" ) == std::string::npos ) ) { + if( key.size() < 20 || key < "18446744073709551616" ) { + return std::stoull( key ); + } + } + } + return std::string::npos; + } + + inline std::string tokens_to_string( std::vector< token >::const_iterator it, const std::vector< token >::const_iterator& end ) + { + std::string result; + while( it != end ) { + result += '/'; + for( const char c : it->key() ) { + switch( c ) { + case '~': + result += "~0"; + break; + case '/': + result += "~1"; + break; + default: + result += c; + } + } + ++it; + } + return result; + } + + inline std::string to_string( const pointer& p ) + { + return tokens_to_string( p.begin(), p.end() ); + } + + inline std::runtime_error invalid_type( const std::vector< token >::const_iterator& begin, const std::vector< token >::const_iterator& end ) + { + return std::runtime_error( "unable to resolve JSON Pointer '" + tokens_to_string( begin, end ) + "' -- value type is neither 'object' nor 'array'" ); + } + + template< typename T > + T& pointer_at( T* v, const std::vector< token >::const_iterator& begin, const std::vector< token >::const_iterator& end ) + { + auto it = begin; + while( it != end ) { + switch( v->type() ) { + case type::ARRAY: + v = &v->at( it->index() ); + break; + case type::OBJECT: + v = &v->at( it->key() ); + break; + default: + throw invalid_type( begin, std::next( it ) ); + } + ++it; + } + return *v; + } + + } // namespace internal + + inline namespace literals + { + inline pointer operator"" _json_pointer( const char* data, const std::size_t size ) + { + return pointer( { data, size } ); + } + + } // namespace literals + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/reference.hpp b/include/tao/json/reference.hpp new file mode 100644 index 00000000..2301d6e6 --- /dev/null +++ b/include/tao/json/reference.hpp @@ -0,0 +1,122 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_REFERENCE_HPP +#define TAOCPP_JSON_INCLUDE_REFERENCE_HPP + +#include "internal/uri_fragment.hpp" + +#include "pointer.hpp" +#include "value.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + // JSON Reference, see draft ("work in progress") RFC at + // https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03 + + // NOTE: Currently, only URI fragments are supported. + // Remote references are ignored, i.e., left untouched. + + // JSON References are replaced with a RAW_PTR, + // which might lead to infinite loops if you try + // to traverse the value. Make sure you understand + // the consequences and handle the resulting value + // accordingly! + + // Self-references will throw an exception, as well as + // references into JSON Reference additional members + // (which shall be ignored as per the specification). + + template< template< typename... > class Traits > + void resolve_references( basic_value< Traits >& r, basic_value< Traits >& v ) + { + switch( v.type() ) { + case type::UNINITIALIZED: + return; + case type::DISCARDED: + throw std::logic_error( "attempt to use a discarded value" ); + case type::DESTROYED: + throw std::logic_error( "attempt to use a destroyed value" ); + case type::NULL_: + case type::BOOLEAN: + case type::SIGNED: + case type::UNSIGNED: + case type::DOUBLE: + case type::STRING: + case type::STRING_VIEW: + case type::BINARY: + case type::BINARY_VIEW: + return; + case type::ARRAY: + for( auto& e : v.unsafe_get_array() ) { + resolve_references( r, e ); + } + return; + case type::OBJECT: + for( auto& e : v.unsafe_get_object() ) { + resolve_references( r, e.second ); + } + if( const auto* ref = v.find( "$ref" ) ) { + ref = ref->skip_raw_ptr(); + // TODO: support is_string_view + if( ref->is_string() ) { + const std::string& s = ref->unsafe_get_string(); + if( !s.empty() && s[ 0 ] == '#' ) { + const pointer ptr = internal::uri_fragment_to_pointer( s ); + const auto* p = &r; + auto it = ptr.begin(); + while( it != ptr.end() ) { + switch( p->type() ) { + case type::ARRAY: + p = p->at( it->index() ).skip_raw_ptr(); + break; + case type::OBJECT: + if( const auto* t = p->find( "$ref" ) ) { + if( t->is_string() ) { + throw std::runtime_error( "invalid JSON Reference: referencing additional data members is invalid" ); + } + } + p = p->at( it->key() ).skip_raw_ptr(); + break; + default: + throw invalid_type( ptr.begin(), std::next( it ) ); + } + ++it; + } + if( p == &v ) { + throw std::runtime_error( "JSON Reference: invalid self reference" ); + } + v.assign_raw_ptr( p ); + resolve_references( r, v ); + return; + } + else { + // Ignore remote references for now... + // throw std::runtime_error( "JSON Reference: unsupported or invalid URI: " + s ); + } + } + } + return; + case type::RAW_PTR: + return; + } + throw std::logic_error( "invalid value for tao::json::type" ); // LCOV_EXCL_LINE + } + + } // namespace internal + + template< template< typename... > class Traits > + void resolve_references( basic_value< Traits >& r ) + { + internal::resolve_references( r, r ); + } + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/schema.hpp b/include/tao/json/schema.hpp new file mode 100644 index 00000000..1e7118a2 --- /dev/null +++ b/include/tao/json/schema.hpp @@ -0,0 +1,1786 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_SCHEMA_HPP +#define TAOCPP_JSON_INCLUDE_SCHEMA_HPP + +#include "events/compare.hpp" +#include "events/from_value.hpp" +#include "events/hash.hpp" +#include "pointer.hpp" +#include "reference.hpp" +#include "value.hpp" + +#include "external/pegtl/contrib/uri.hpp" +#include "external/pegtl/parse.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace tao +{ + namespace json + { + namespace internal + { + // TODO: Check if these grammars are correct. + struct local_part_label + : json_pegtl::plus< json_pegtl::sor< json_pegtl::alnum, json_pegtl::one< '!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', '=', '?', '^', '_', '`', '{', '|', '}', '~' > > > + { + }; + + struct local_part + : json_pegtl::list_must< local_part_label, json_pegtl::one< '.' > > + { + }; + + struct hostname_label + : json_pegtl::seq< json_pegtl::alnum, json_pegtl::rep_max< 62, json_pegtl::ranges< 'a', 'z', 'A', 'Z', '0', '9', '-' > > > + { + }; + + struct hostname + : json_pegtl::list_must< hostname_label, json_pegtl::one< '.' > > + { + }; + + struct email + : json_pegtl::seq< local_part, json_pegtl::one< '@' >, hostname > + { + }; + + template< typename Rule > + bool parse( const tao::string_view v ) + { + json_pegtl::memory_input<> in( v.data(), v.size(), "" ); + return json_pegtl::parse< json_pegtl::seq< Rule, json_pegtl::eof > >( in ); + } + + inline bool parse_date_time( const tao::string_view v ) + { + static std::regex re( "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:[0-5]\\d:[0-5]\\d(\\.\\d+)?(Z|[+-]\\d{2}:[0-5]\\d)$" ); + if( !std::regex_search( v.begin(), v.end(), re ) ) { + return false; + } + + const unsigned year = ( v[ 0 ] - '0' ) * 1000 + ( v[ 1 ] - '0' ) * 100 + ( v[ 2 ] - '0' ) * 10 + ( v[ 3 ] - '0' ); + const unsigned month = ( v[ 5 ] - '0' ) * 10 + ( v[ 6 ] - '0' ); + const unsigned day = ( v[ 8 ] - '0' ) * 10 + ( v[ 9 ] - '0' ); + + if( month == 0 || month > 12 ) { + return false; + } + if( day == 0 || day > 31 ) { + return false; + } + if( month == 2 ) { + const bool is_leap_year = ( year % 4 == 0 ) && ( year % 100 != 0 || year % 400 == 0 ); + if( day > ( is_leap_year ? 29 : 28 ) ) { + return false; + } + } + else if( day == 31 ) { + switch( month ) { + case 4: + case 6: + case 9: + case 11: + return false; + } + } + + const unsigned hour = ( v[ 11 ] - '0' ) * 10 + ( v[ 12 ] - '0' ); + if( hour >= 24 ) { + return false; + } + + if( *v.rbegin() != 'Z' ) { + const auto s = v.size(); + const unsigned tz_hour = ( v[ s - 5 ] - '0' ) * 10 + ( v[ s - 4 ] - '0' ); + if( tz_hour >= 24 ) { + return false; + } + } + + return true; + } + + enum schema_flags + { + NONE = 0, + + HAS_TYPE = 1 << 0, + NULL_ = 1 << 1, + BOOLEAN = 1 << 2, + INTEGER = 1 << 3, + NUMBER = 1 << 4, + STRING = 1 << 5, + ARRAY = 1 << 6, + OBJECT = 1 << 7, + + HAS_ENUM = 1 << 8, + + HAS_MULTIPLE_OF_UNSIGNED = 1 << 9, + HAS_MULTIPLE_OF_DOUBLE = 1 << 10, + HAS_MULTIPLE_OF = 3 << 9, + + HAS_MAXIMUM_SIGNED = 1 << 11, + HAS_MAXIMUM_UNSIGNED = 1 << 12, + HAS_MAXIMUM_DOUBLE = 3 << 11, + HAS_MAXIMUM = 3 << 11, + EXCLUSIVE_MAXIMUM = 1 << 13, + + HAS_MINIMUM_SIGNED = 1 << 14, + HAS_MINIMUM_UNSIGNED = 1 << 15, + HAS_MINIMUM_DOUBLE = 3 << 14, + HAS_MINIMUM = 3 << 14, + EXCLUSIVE_MINIMUM = 1 << 16, + + HAS_MAX_LENGTH = 1 << 17, + HAS_MIN_LENGTH = 1 << 18, + + HAS_MAX_ITEMS = 1 << 19, + HAS_MIN_ITEMS = 1 << 20, + HAS_UNIQUE_ITEMS = 1 << 21, + + HAS_MAX_PROPERTIES = 1 << 22, + HAS_MIN_PROPERTIES = 1 << 23, + NO_ADDITIONAL_PROPERTIES = 1 << 24, + HAS_DEPENDENCIES = 1 << 25 + }; + + enum class schema_format + { + NONE, + DATE_TIME, + EMAIL, + HOSTNAME, + IPV4, + IPV6, + URI + }; + + inline constexpr schema_flags operator|( const schema_flags lhs, const schema_flags rhs ) noexcept + { + return static_cast< schema_flags >( static_cast< std::underlying_type< schema_flags >::type >( lhs ) | static_cast< std::underlying_type< schema_flags >::type >( rhs ) ); + } + + union schema_limit + { + std::int64_t i; + std::uint64_t u; + double d; + }; + + template< template< typename... > class Traits > + class schema_container; + + template< template< typename... > class Traits > + struct schema_node + { + const schema_container< Traits >* m_container; + const basic_value< Traits >* m_value; + const basic_value< Traits >* m_all_of = nullptr; + const basic_value< Traits >* m_any_of = nullptr; + const basic_value< Traits >* m_one_of = nullptr; + const basic_value< Traits >* m_not = nullptr; + const basic_value< Traits >* m_items = nullptr; + const basic_value< Traits >* m_additional_items = nullptr; + const basic_value< Traits >* m_properties = nullptr; + const basic_value< Traits >* m_additional_properties = nullptr; + + std::map< std::string, std::set< std::string > > m_property_dependencies; + std::map< std::string, const basic_value< Traits >* > m_schema_dependencies; + + std::vector< std::pair< std::regex, const basic_value< Traits >* > > m_pattern_properties; + + std::set< const basic_value< Traits >* > m_referenced_pointers; + + // number + schema_limit m_multiple_of; + schema_limit m_maximum; + schema_limit m_minimum; + + // string + std::uint64_t m_max_length; + std::uint64_t m_min_length; + std::unique_ptr< std::regex > m_pattern; + + // array + std::uint64_t m_max_items; + std::uint64_t m_min_items; + + // object + std::uint64_t m_max_properties; + std::uint64_t m_min_properties; + std::set< std::string > m_required; + + schema_flags m_flags = schema_flags::NONE; + schema_format m_format = schema_format::NONE; + + void add_type( const schema_flags v ) + { + if( ( m_flags & v ) != 0 ) { + throw std::runtime_error( "invalid JSON Schema: duplicate primitive type" ); + } + m_flags = m_flags | v; + } + + void add_type( const std::string& v ) + { + if( !v.empty() ) { + switch( v[ 0 ] ) { + case 'n': + if( v == "number" ) { + return add_type( NUMBER ); + } + else if( v == "null" ) { + return add_type( NULL_ ); + } + break; + case 'b': + if( v == "boolean" ) { + return add_type( BOOLEAN ); + } + break; + case 'i': + if( v == "integer" ) { + return add_type( INTEGER ); + } + break; + case 's': + if( v == "string" ) { + return add_type( STRING ); + } + break; + case 'a': + if( v == "array" ) { + return add_type( ARRAY ); + } + break; + case 'o': + if( v == "object" ) { + return add_type( OBJECT ); + } + break; + } + } + throw std::runtime_error( "invalid JSON Schema: invalid primitive type '" + v + '\'' ); + } + + const basic_value< Traits >* find( const char* s ) const + { + const auto* p = m_value->unsafe_find( s ); + if( p != nullptr ) { + p = p->skip_raw_ptr(); + } + return p; + } + + schema_node( const schema_container< Traits >* c, const basic_value< Traits >& v ) + : m_container( c ), + m_value( &v ) + { + // general + if( !m_value->is_object() ) { + throw std::runtime_error( "invalid JSON Schema: a schema must be of type 'object'" ); + } + + // title + if( const auto* p = find( "title" ) ) { + if( !p->is_string() ) { + throw std::runtime_error( "invalid JSON Schema: \"title\" must be of type 'string'" ); + } + } + + // description + if( const auto* p = find( "description" ) ) { + if( !p->is_string() ) { + throw std::runtime_error( "invalid JSON Schema: \"description\" must be of type 'string'" ); + } + } + + // type + if( const auto* p = find( "type" ) ) { + switch( p->type() ) { + case type::STRING: + add_type( p->unsafe_get_string() ); + break; + case type::ARRAY: + for( const auto& e : p->unsafe_get_array() ) { + if( !e.is_string() ) { + throw std::runtime_error( "invalid JSON Schema: elements in array \"type\" must be of type 'string'" ); + } + add_type( e.unsafe_get_string() ); + } + break; + default: + throw std::runtime_error( "invalid JSON Schema: \"type\" must be of type 'string' or 'array'" ); + } + m_flags = m_flags | HAS_TYPE; + } + + // enum + if( const auto* p = find( "enum" ) ) { + if( !p->is_array() ) { + throw std::runtime_error( "invalid JSON Schema: \"enum\" must be of type 'array'" ); + } + m_flags = m_flags | HAS_ENUM; + } + + // allOf + if( const auto* p = find( "allOf" ) ) { + if( !p->is_array() ) { + throw std::runtime_error( "invalid JSON Schema: \"allOf\" must be of type 'array'" ); + } + if( p->empty() ) { + throw std::runtime_error( "invalid JSON Schema: \"allOf\" must have at least one element" ); + } + for( const auto& e : p->unsafe_get_array() ) { + m_referenced_pointers.insert( e.skip_raw_ptr() ); + } + m_all_of = p; + } + + // anyOf + if( const auto* p = find( "anyOf" ) ) { + if( !p->is_array() ) { + throw std::runtime_error( "invalid JSON Schema: \"anyOf\" must be of type 'array'" ); + } + if( p->empty() ) { + throw std::runtime_error( "invalid JSON Schema: \"anyOf\" must have at least one element" ); + } + for( const auto& e : p->unsafe_get_array() ) { + m_referenced_pointers.insert( e.skip_raw_ptr() ); + } + m_any_of = p; + } + + // oneOf + if( const auto* p = find( "oneOf" ) ) { + if( !p->is_array() ) { + throw std::runtime_error( "invalid JSON Schema: \"oneOf\" must be of type 'array'" ); + } + if( p->empty() ) { + throw std::runtime_error( "invalid JSON Schema: \"oneOf\" must have at least one element" ); + } + for( const auto& e : p->unsafe_get_array() ) { + m_referenced_pointers.insert( e.skip_raw_ptr() ); + } + m_one_of = p; + } + + // not + if( const auto* p = find( "not" ) ) { + m_referenced_pointers.insert( p ); + m_not = p; + } + + // definitions + if( const auto* p = find( "definitions" ) ) { + if( !p->is_object() ) { + throw std::runtime_error( "invalid JSON Schema: \"definitions\" must be of type 'object'" ); + } + for( const auto& e : p->unsafe_get_object() ) { + m_referenced_pointers.insert( e.second.skip_raw_ptr() ); + } + } + + // multipleOf + if( const auto* p = find( "multipleOf" ) ) { + switch( p->type() ) { + case type::SIGNED: { + const auto i = p->unsafe_get_signed(); + if( i <= 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"multipleOf\" must be strictly greater than zero" ); + } + m_multiple_of.u = i; + m_flags = m_flags | HAS_MULTIPLE_OF_UNSIGNED; + } break; + case type::UNSIGNED: { + const auto u = p->unsafe_get_unsigned(); + if( u == 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"multipleOf\" must be strictly greater than zero" ); + } + m_multiple_of.u = u; + m_flags = m_flags | HAS_MULTIPLE_OF_UNSIGNED; + } break; + case type::DOUBLE: { + const auto d = p->unsafe_get_double(); + if( d <= 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"multipleOf\" must be strictly greater than zero" ); + } + m_multiple_of.d = d; + m_flags = m_flags | HAS_MULTIPLE_OF_DOUBLE; + } break; + default: + throw std::runtime_error( "invalid JSON Schema: \"multipleOf\" must be of type 'number'" ); + } + } + + // maximum + if( const auto* p = find( "maximum" ) ) { + switch( p->type() ) { + case type::SIGNED: + m_maximum.i = p->unsafe_get_signed(); + m_flags = m_flags | HAS_MAXIMUM_SIGNED; + break; + case type::UNSIGNED: + m_maximum.u = p->unsafe_get_unsigned(); + m_flags = m_flags | HAS_MAXIMUM_UNSIGNED; + break; + case type::DOUBLE: + m_maximum.d = p->unsafe_get_double(); + m_flags = m_flags | HAS_MAXIMUM_DOUBLE; + break; + default: + throw std::runtime_error( "invalid JSON Schema: \"maximum\" must be of type 'number'" ); + } + } + + // exclusiveMaximum + if( const auto* p = find( "exclusiveMaximum" ) ) { + if( !p->is_boolean() ) { + throw std::runtime_error( "invalid JSON Schema: \"exclusiveMaximum\" must be of type 'boolean'" ); + } + if( ( m_flags & HAS_MAXIMUM ) == 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"exclusiveMaximum\" requires presence of \"maximum\"" ); + } + if( p->get_boolean() ) { + m_flags = m_flags | EXCLUSIVE_MAXIMUM; + } + } + + // minimum + if( const auto* p = find( "minimum" ) ) { + switch( p->type() ) { + case type::SIGNED: + m_minimum.i = p->unsafe_get_signed(); + m_flags = m_flags | HAS_MINIMUM_SIGNED; + break; + case type::UNSIGNED: + m_minimum.u = p->unsafe_get_unsigned(); + m_flags = m_flags | HAS_MINIMUM_UNSIGNED; + break; + case type::DOUBLE: + m_minimum.d = p->unsafe_get_double(); + m_flags = m_flags | HAS_MINIMUM_DOUBLE; + break; + default: + throw std::runtime_error( "invalid JSON Schema: \"minimum\" must be of type 'number'" ); + } + } + + // exclusiveMinimum + if( const auto* p = find( "exclusiveMinimum" ) ) { + if( !p->is_boolean() ) { + throw std::runtime_error( "invalid JSON Schema: \"exclusiveMinimum\" must be of type 'boolean'" ); + } + if( ( m_flags & HAS_MINIMUM ) == 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"exclusiveMinimum\" requires presence of \"minimum\"" ); + } + if( p->get_boolean() ) { + m_flags = m_flags | EXCLUSIVE_MINIMUM; + } + } + + // maxLength + if( const auto* p = find( "maxLength" ) ) { + switch( p->type() ) { + case type::SIGNED: { + const auto i = p->unsafe_get_signed(); + if( i < 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"maxLength\" must be greater than or equal to zero" ); + } + m_max_length = i; + m_flags = m_flags | HAS_MAX_LENGTH; + } break; + case type::UNSIGNED: + m_max_length = p->unsafe_get_unsigned(); + m_flags = m_flags | HAS_MAX_LENGTH; + break; + default: + throw std::runtime_error( "invalid JSON Schema: \"maxLength\" must be of type 'integer'" ); + } + } + + // minLength + if( const auto* p = find( "minLength" ) ) { + switch( p->type() ) { + case type::SIGNED: { + const auto i = p->unsafe_get_signed(); + if( i < 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"minLength\" must be greater than or equal to zero" ); + } + if( i > 0 ) { + m_min_length = i; + m_flags = m_flags | HAS_MIN_LENGTH; + } + } break; + case type::UNSIGNED: { + const auto u = p->unsafe_get_unsigned(); + if( u > 0 ) { + m_min_length = u; + m_flags = m_flags | HAS_MIN_LENGTH; + } + } break; + default: + throw std::runtime_error( "invalid JSON Schema: \"minLength\" must be of type 'integer'" ); + } + } + + // pattern + if( const auto* p = find( "pattern" ) ) { + if( !p->is_string() ) { + throw std::runtime_error( "invalid JSON Schema: \"pattern\" must be of type 'string'" ); + } + try { + m_pattern.reset( new std::regex( p->unsafe_get_string() ) ); + } + catch( const std::regex_error& e ) { + throw std::runtime_error( "invalid JSON Schema: \"pattern\" must be a regular expression: " + std::string( e.what() ) ); + } + } + + // format + // TODO: offer an option to disable "format" support? + if( const auto* p = find( "format" ) ) { + if( !p->is_string() ) { + throw std::runtime_error( "invalid JSON Schema: \"format\" must be of type 'string'" ); + } + const auto& s = p->unsafe_get_string(); + if( s == "date-time" ) { + m_format = schema_format::DATE_TIME; + } + else if( s == "email" ) { + m_format = schema_format::EMAIL; + } + else if( s == "hostname" ) { + m_format = schema_format::HOSTNAME; + } + else if( s == "ipv4" ) { + m_format = schema_format::IPV4; + } + else if( s == "ipv6" ) { + m_format = schema_format::IPV6; + } + else if( s == "uri" ) { + m_format = schema_format::URI; + } + // unknown "format" values are ignored + } + + // items + if( const auto* p = find( "items" ) ) { + if( p->is_array() ) { + for( const auto& e : p->unsafe_get_array() ) { + m_referenced_pointers.insert( e.skip_raw_ptr() ); + } + } + else if( p->is_object() ) { + m_referenced_pointers.insert( p ); + } + else { + throw std::runtime_error( "invalid JSON Schema: \"items\" must be of type 'object' or 'array'" ); + } + m_items = p; + } + + // additionalItems + if( const auto* p = find( "additionalItems" ) ) { + if( p->is_object() ) { + m_referenced_pointers.insert( p ); + } + else if( !p->is_boolean() ) { + throw std::runtime_error( "invalid JSON Schema: \"additionalItems\" must be of type 'boolean' or 'object'" ); + } + m_additional_items = p; + } + + // maxItems + if( const auto* p = find( "maxItems" ) ) { + switch( p->type() ) { + case type::SIGNED: { + const auto i = p->unsafe_get_signed(); + if( i < 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"maxItems\" must be greater than or equal to zero" ); + } + m_max_items = i; + m_flags = m_flags | HAS_MAX_ITEMS; + } break; + case type::UNSIGNED: + m_max_items = p->unsafe_get_unsigned(); + m_flags = m_flags | HAS_MAX_ITEMS; + break; + default: + throw std::runtime_error( "invalid JSON Schema: \"maxItems\" must be of type 'integer'" ); + } + } + + // minItems + if( const auto* p = find( "minItems" ) ) { + switch( p->type() ) { + case type::SIGNED: { + const auto i = p->unsafe_get_signed(); + if( i < 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"minItems\" must be greater than or equal to zero" ); + } + m_min_items = i; + m_flags = m_flags | HAS_MIN_ITEMS; + } break; + case type::UNSIGNED: + m_min_items = p->unsafe_get_unsigned(); + m_flags = m_flags | HAS_MIN_ITEMS; + break; + default: + throw std::runtime_error( "invalid JSON Schema: \"minItems\" must be of type 'integer'" ); + } + } + + // uniqueItems + if( const auto* p = find( "uniqueItems" ) ) { + if( p->get_boolean() ) { + m_flags = m_flags | HAS_UNIQUE_ITEMS; + } + } + + // maxProperties + if( const auto* p = find( "maxProperties" ) ) { + switch( p->type() ) { + case type::SIGNED: { + const auto i = p->unsafe_get_signed(); + if( i < 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"maxProperties\" must be greater than or equal to zero" ); + } + m_max_properties = i; + m_flags = m_flags | HAS_MAX_PROPERTIES; + } break; + case type::UNSIGNED: + m_max_properties = p->unsafe_get_unsigned(); + m_flags = m_flags | HAS_MAX_PROPERTIES; + break; + default: + throw std::runtime_error( "invalid JSON Schema: \"maxProperties\" must be of type 'integer'" ); + } + } + + // minProperties + if( const auto* p = find( "minProperties" ) ) { + switch( p->type() ) { + case type::SIGNED: { + const auto i = p->unsafe_get_signed(); + if( i < 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"minProperties\" must be greater than or equal to zero" ); + } + m_min_properties = i; + m_flags = m_flags | HAS_MIN_PROPERTIES; + } break; + case type::UNSIGNED: + m_min_properties = p->unsafe_get_unsigned(); + m_flags = m_flags | HAS_MIN_PROPERTIES; + break; + default: + throw std::runtime_error( "invalid JSON Schema: \"minProperties\" must be of type 'integer'" ); + } + } + + // required + if( const auto* p = find( "required" ) ) { + if( !p->is_array() ) { + throw std::runtime_error( "invalid JSON Schema: \"required\" must be of type 'array'" ); + } + if( p->empty() ) { + throw std::runtime_error( "invalid JSON Schema: \"required\" must have at least one element" ); + } + for( const auto& e : p->unsafe_get_array() ) { + if( !m_required.insert( e.get_string() ).second ) { + throw std::runtime_error( "invalid JSON Schema: duplicate required key" ); + } + } + } + + // properties + if( const auto* p = find( "properties" ) ) { + if( !p->is_object() ) { + throw std::runtime_error( "invalid JSON Schema: \"properties\" must be of type 'object'" ); + } + for( const auto& e : p->unsafe_get_object() ) { + m_referenced_pointers.insert( e.second.skip_raw_ptr() ); + } + m_properties = p; + } + + // patternProperties + if( const auto* p = find( "patternProperties" ) ) { + if( !p->is_object() ) { + throw std::runtime_error( "invalid JSON Schema: \"patternProperties\" must be of type 'object'" ); + } + for( const auto& e : p->unsafe_get_object() ) { + try { + m_pattern_properties.emplace_back( std::regex( e.first ), e.second.skip_raw_ptr() ); + } + catch( const std::regex_error& ex ) { + throw std::runtime_error( "invalid JSON Schema: keys in object \"patternProperties\" must be regular expressions: " + std::string( ex.what() ) ); + } + m_referenced_pointers.insert( e.second.skip_raw_ptr() ); + } + } + + // additionalProperties + if( const auto* p = find( "additionalProperties" ) ) { + const type t = p->type(); + if( t == type::OBJECT ) { + m_referenced_pointers.insert( p ); + } + else if( t != type::BOOLEAN ) { + throw std::runtime_error( "invalid JSON Schema: \"additionalProperties\" must be of type 'boolean' or 'object'" ); + } + m_additional_properties = p; + } + + // dependencies + if( const auto* p = find( "dependencies" ) ) { + if( !p->is_object() ) { + throw std::runtime_error( "invalid JSON Schema: \"dependencies\" must be of type 'object'" ); + } + for( const auto& e : p->unsafe_get_object() ) { + const auto* p2 = e.second.skip_raw_ptr(); + if( p2->is_object() ) { + m_schema_dependencies.emplace( e.first, p2 ); + m_referenced_pointers.insert( p2 ); + } + else if( p2->is_array() ) { + if( p2->empty() ) { + throw std::runtime_error( "invalid JSON Schema: values in object \"dependencies\" of type 'array' must have at least one element" ); + } + std::set< std::string > s; + for( const auto& r : p2->unsafe_get_array() ) { + if( !r.is_string() ) { + throw std::runtime_error( "invalid JSON Schema: values in object \"dependencies\" of type 'array' must contain elements of type 'string'" ); + } + if( !s.emplace( r.unsafe_get_string() ).second ) { + throw std::runtime_error( "invalid JSON Schema: values in object \"dependencies\" of type 'array' must contain unique elements of type 'string'" ); + } + } + m_property_dependencies.emplace( e.first, std::move( s ) ); + } + else { + throw std::runtime_error( "invalid JSON Schema: values in object \"dependencies\" must be of type 'object' or 'array'" ); + } + } + if( !p->empty() ) { + m_flags = m_flags | HAS_DEPENDENCIES; + } + } + + // default + if( const auto* p = find( "default" ) ) { + // TODO: the value should validate against the JSON Schema itself + } + } + + schema_node( const schema_node& ) = delete; + schema_node( schema_node&& ) = delete; + + void operator=( const schema_node& ) = delete; + void operator=( schema_node&& ) = delete; + + const std::set< const basic_value< Traits >* >& referenced_pointers() const noexcept + { + return m_referenced_pointers; + } + }; + + template< template< typename... > class Traits > + class schema_consumer + { + private: + const std::shared_ptr< const schema_container< Traits > > m_container; + const schema_node< Traits >* const m_node; + + std::vector< std::unique_ptr< events_compare< Traits > > > m_enum; + std::unique_ptr< events::hash > m_hash; + std::set< std::string > m_unique; + std::set< std::string > m_keys; + std::vector< std::size_t > m_count; + std::vector< std::unique_ptr< schema_consumer > > m_properties; + std::vector< std::unique_ptr< schema_consumer > > m_all_of; + std::vector< std::unique_ptr< schema_consumer > > m_any_of; + std::vector< std::unique_ptr< schema_consumer > > m_one_of; + std::map< std::string, std::unique_ptr< schema_consumer > > m_schema_dependencies; + std::unique_ptr< schema_consumer > m_not; + std::unique_ptr< schema_consumer > m_item; + bool m_match = true; + + void validate_type( const schema_flags t ) + { + if( !m_count.empty() ) { + return; + } + if( ( m_node->m_flags & HAS_TYPE ) == 0 ) { + return; + } + if( ( m_node->m_flags & t ) == 0 ) { + m_match = false; + } + } + + // note: lambda returns true if validation failure detected + template< typename F > + void validate_enum( F&& f ) + { + assert( m_match ); + if( m_node->m_flags & HAS_ENUM ) { + m_enum.erase( std::remove_if( m_enum.begin(), m_enum.end(), [&]( const std::unique_ptr< events_compare< Traits > >& p ) { return f( *p ); } ), m_enum.end() ); + if( m_enum.empty() ) { + m_match = false; + } + } + } + + template< typename F > + void validate_item( F&& f ) + { + if( m_item ) { + if( f( m_item ) ) { + m_match = false; + } + } + } + + template< typename F > + void validate_properties( F&& f ) + { + for( auto& p : m_properties ) { + if( f( p ) ) { + m_match = false; + break; + } + } + } + + template< typename F > + void validate_schema_dependencies( F&& f ) + { + auto it = m_schema_dependencies.begin(); + while( it != m_schema_dependencies.end() ) { + if( f( it->second ) ) { + it = m_schema_dependencies.erase( it ); + } + else { + ++it; + } + } + } + + template< typename F > + void validate_all_of( F&& f ) + { + for( auto& p : m_all_of ) { + if( f( p ) ) { + m_match = false; + break; + } + } + } + + template< typename F > + void validate_any_of( F&& f ) + { + if( !m_any_of.empty() ) { + m_any_of.erase( std::remove_if( m_any_of.begin(), m_any_of.end(), f ), m_any_of.end() ); + if( m_any_of.empty() ) { + m_match = false; + } + } + } + + template< typename F > + void validate_one_of( F&& f ) + { + if( !m_one_of.empty() ) { + m_one_of.erase( std::remove_if( m_one_of.begin(), m_one_of.end(), f ), m_one_of.end() ); + if( m_one_of.empty() ) { + m_match = false; + } + } + } + + template< typename F > + void validate_not( F&& f ) + { + if( m_not ) { + if( f( m_not ) ) { + m_not.reset(); + } + } + } + + // note: lambda returns true if validation failure detected + template< typename F > + void validate_collections( F&& f ) + { + assert( m_match ); + const auto f2 = [&]( const std::unique_ptr< schema_consumer >& p ) { return f( *p ); }; + if( m_match ) + validate_item( f2 ); + if( m_match ) + validate_properties( f2 ); + if( m_match ) + validate_all_of( f2 ); + if( m_match ) + validate_any_of( f2 ); + if( m_match ) + validate_one_of( f2 ); + if( m_match ) + validate_not( f2 ); + if( m_match ) + validate_schema_dependencies( f2 ); + } + + static bool is_multiple_of( const double v, const double d ) + { + const auto r = std::fmod( v, d ); + if( std::fabs( r ) < std::numeric_limits< double >::epsilon() ) { + return true; + } + if( std::fabs( r - d ) < std::numeric_limits< double >::epsilon() ) { + return true; + } + return false; + } + + void validate_multiple_of( const std::int64_t v ) + { + switch( m_node->m_flags & HAS_MULTIPLE_OF ) { + case HAS_MULTIPLE_OF_UNSIGNED: + if( v < 0 ) { + if( ( -v % m_node->m_multiple_of.u ) != 0 ) { + m_match = false; + } + } + else { + if( ( v % m_node->m_multiple_of.u ) != 0 ) { + m_match = false; + } + } + break; + case HAS_MULTIPLE_OF_DOUBLE: + if( !is_multiple_of( v, m_node->m_multiple_of.d ) ) { + m_match = false; + } + break; + } + } + + void validate_multiple_of( const std::uint64_t v ) + { + switch( m_node->m_flags & HAS_MULTIPLE_OF ) { + case HAS_MULTIPLE_OF_UNSIGNED: + if( ( v % m_node->m_multiple_of.u ) != 0 ) { + m_match = false; + } + break; + case HAS_MULTIPLE_OF_DOUBLE: + if( !is_multiple_of( v, m_node->m_multiple_of.d ) ) { + m_match = false; + } + break; + } + } + + void validate_multiple_of( const double v ) + { + switch( m_node->m_flags & HAS_MULTIPLE_OF ) { + case HAS_MULTIPLE_OF_UNSIGNED: + if( !is_multiple_of( v, m_node->m_multiple_of.u ) ) { + m_match = false; + } + break; + case HAS_MULTIPLE_OF_DOUBLE: + if( !is_multiple_of( v, m_node->m_multiple_of.d ) ) { + m_match = false; + } + break; + } + } + + void validate_number( const std::int64_t v ) + { + validate_multiple_of( v ); + switch( m_node->m_flags & ( HAS_MAXIMUM | EXCLUSIVE_MAXIMUM ) ) { + case HAS_MAXIMUM_SIGNED: + if( v > m_node->m_maximum.i ) { + m_match = false; + } + break; + case HAS_MAXIMUM_SIGNED | EXCLUSIVE_MAXIMUM: + if( v >= m_node->m_maximum.i ) { + m_match = false; + } + break; + case HAS_MAXIMUM_UNSIGNED: + if( v >= 0 && static_cast< std::uint64_t >( v ) > m_node->m_maximum.u ) { + m_match = false; + } + break; + case HAS_MAXIMUM_UNSIGNED | EXCLUSIVE_MAXIMUM: + if( v >= 0 && static_cast< std::uint64_t >( v ) >= m_node->m_maximum.u ) { + m_match = false; + } + break; + case HAS_MAXIMUM_DOUBLE: + if( v > m_node->m_maximum.d ) { + m_match = false; + } + break; + case HAS_MAXIMUM_DOUBLE | EXCLUSIVE_MAXIMUM: + if( v >= m_node->m_maximum.d ) { + m_match = false; + } + break; + } + switch( m_node->m_flags & ( HAS_MINIMUM | EXCLUSIVE_MINIMUM ) ) { + case HAS_MINIMUM_SIGNED: + if( v < m_node->m_minimum.i ) { + m_match = false; + } + break; + case HAS_MINIMUM_SIGNED | EXCLUSIVE_MINIMUM: + if( v <= m_node->m_minimum.i ) { + m_match = false; + } + break; + case HAS_MINIMUM_UNSIGNED: + if( v < 0 || static_cast< std::uint64_t >( v ) < m_node->m_minimum.u ) { + m_match = false; + } + break; + case HAS_MINIMUM_UNSIGNED | EXCLUSIVE_MINIMUM: + if( v < 0 || static_cast< std::uint64_t >( v ) <= m_node->m_minimum.u ) { + m_match = false; + } + break; + case HAS_MINIMUM_DOUBLE: + if( v < m_node->m_minimum.d ) { + m_match = false; + } + break; + case HAS_MINIMUM_DOUBLE | EXCLUSIVE_MINIMUM: + if( v <= m_node->m_minimum.d ) { + m_match = false; + } + break; + } + } + + void validate_number( const std::uint64_t v ) + { + validate_multiple_of( v ); + switch( m_node->m_flags & ( HAS_MAXIMUM | EXCLUSIVE_MAXIMUM ) ) { + case HAS_MAXIMUM_SIGNED: + if( m_node->m_maximum.i < 0 || v > static_cast< std::uint64_t >( m_node->m_maximum.i ) ) { + m_match = false; + } + break; + case HAS_MAXIMUM_SIGNED | EXCLUSIVE_MAXIMUM: + if( m_node->m_maximum.i < 0 || v >= static_cast< std::uint64_t >( m_node->m_maximum.i ) ) { + m_match = false; + } + break; + case HAS_MAXIMUM_UNSIGNED: + if( v > m_node->m_maximum.u ) { + m_match = false; + } + break; + case HAS_MAXIMUM_UNSIGNED | EXCLUSIVE_MAXIMUM: + if( v >= m_node->m_maximum.u ) { + m_match = false; + } + break; + case HAS_MAXIMUM_DOUBLE: + if( v > m_node->m_maximum.d ) { + m_match = false; + } + break; + case HAS_MAXIMUM_DOUBLE | EXCLUSIVE_MAXIMUM: + if( v >= m_node->m_maximum.d ) { + m_match = false; + } + break; + } + switch( m_node->m_flags & ( HAS_MINIMUM | EXCLUSIVE_MINIMUM ) ) { + case HAS_MINIMUM_SIGNED: + if( m_node->m_minimum.i >= 0 && v < static_cast< std::uint64_t >( m_node->m_minimum.i ) ) { + m_match = false; + } + break; + case HAS_MINIMUM_SIGNED | EXCLUSIVE_MINIMUM: + if( m_node->m_minimum.i >= 0 && v <= static_cast< std::uint64_t >( m_node->m_minimum.i ) ) { + m_match = false; + } + break; + case HAS_MINIMUM_UNSIGNED: + if( v < m_node->m_minimum.u ) { + m_match = false; + } + break; + case HAS_MINIMUM_UNSIGNED | EXCLUSIVE_MINIMUM: + if( v <= m_node->m_minimum.u ) { + m_match = false; + } + break; + case HAS_MINIMUM_DOUBLE: + if( v < m_node->m_minimum.d ) { + m_match = false; + } + break; + case HAS_MINIMUM_DOUBLE | EXCLUSIVE_MINIMUM: + if( v <= m_node->m_minimum.d ) { + m_match = false; + } + break; + } + } + + void validate_number( const double v ) + { + validate_multiple_of( v ); + switch( m_node->m_flags & ( HAS_MAXIMUM | EXCLUSIVE_MAXIMUM ) ) { + case HAS_MAXIMUM_SIGNED: + if( v > m_node->m_maximum.i ) { + m_match = false; + } + break; + case HAS_MAXIMUM_SIGNED | EXCLUSIVE_MAXIMUM: + if( v >= m_node->m_maximum.i ) { + m_match = false; + } + break; + case HAS_MAXIMUM_UNSIGNED: + if( v > m_node->m_maximum.u ) { + m_match = false; + } + break; + case HAS_MAXIMUM_UNSIGNED | EXCLUSIVE_MAXIMUM: + if( v >= m_node->m_maximum.u ) { + m_match = false; + } + break; + case HAS_MAXIMUM_DOUBLE: + if( v > m_node->m_maximum.d ) { + m_match = false; + } + break; + case HAS_MAXIMUM_DOUBLE | EXCLUSIVE_MAXIMUM: + if( v >= m_node->m_maximum.d ) { + m_match = false; + } + break; + } + switch( m_node->m_flags & ( HAS_MINIMUM | EXCLUSIVE_MINIMUM ) ) { + case HAS_MINIMUM_SIGNED: + if( v < m_node->m_minimum.i ) { + m_match = false; + } + break; + case HAS_MINIMUM_SIGNED | EXCLUSIVE_MINIMUM: + if( v <= m_node->m_minimum.i ) { + m_match = false; + } + break; + case HAS_MINIMUM_UNSIGNED: + if( v < m_node->m_minimum.u ) { + m_match = false; + } + break; + case HAS_MINIMUM_UNSIGNED | EXCLUSIVE_MINIMUM: + if( v <= m_node->m_minimum.u ) { + m_match = false; + } + break; + case HAS_MINIMUM_DOUBLE: + if( v < m_node->m_minimum.d ) { + m_match = false; + } + break; + case HAS_MINIMUM_DOUBLE | EXCLUSIVE_MINIMUM: + if( v <= m_node->m_minimum.d ) { + m_match = false; + } + break; + } + } + + void validate_string( const tao::string_view v ) + { + if( m_node->m_flags & HAS_MAX_LENGTH && v.size() > m_node->m_max_length ) { + m_match = false; + } + if( m_node->m_flags & HAS_MIN_LENGTH && v.size() < m_node->m_min_length ) { + m_match = false; + } + if( m_match && m_node->m_pattern ) { + if( !std::regex_search( v.begin(), v.end(), *m_node->m_pattern ) ) { + m_match = false; + } + } + if( m_match && m_node->m_format != schema_format::NONE ) { + switch( m_node->m_format ) { + case schema_format::DATE_TIME: + if( !internal::parse_date_time( v ) ) { + m_match = false; + } + break; + case schema_format::EMAIL: + if( ( v.size() > 255 ) || !internal::parse< internal::email >( v ) ) { + m_match = false; + } + break; + case schema_format::HOSTNAME: + if( ( v.size() > 255 ) || !internal::parse< internal::hostname >( v ) ) { + m_match = false; + } + break; + case schema_format::IPV4: + if( !internal::parse< json_pegtl::uri::IPv4address >( v ) ) { + m_match = false; + } + break; + case schema_format::IPV6: + if( !internal::parse< json_pegtl::uri::IPv6address >( v ) ) { + m_match = false; + } + break; + case schema_format::URI: + // TODO: What rule exactly should we apply here?? JSON Schema is not exactly the best spec I've ever read... + if( !internal::parse< json_pegtl::uri::URI >( v ) ) { + m_match = false; + } + break; + case schema_format::NONE:; + } + } + } + + void validate_elements( const std::size_t v ) + { + if( m_node->m_flags & HAS_MAX_ITEMS && v > m_node->m_max_items ) { + m_match = false; + } + if( m_node->m_flags & HAS_MIN_ITEMS && v < m_node->m_min_items ) { + m_match = false; + } + } + + void validate_members( const std::size_t v ) + { + if( m_node->m_flags & HAS_MAX_PROPERTIES && v > m_node->m_max_properties ) { + m_match = false; + } + if( m_node->m_flags & HAS_MIN_PROPERTIES && v < m_node->m_min_properties ) { + m_match = false; + } + } + + public: + schema_consumer( const std::shared_ptr< const schema_container< Traits > >& c, const schema_node< Traits >& n ) + : m_container( c ), + m_node( &n ) + { + if( m_node->m_flags & HAS_ENUM ) { + const auto& a = m_node->m_value->unsafe_at( "enum" ).unsafe_get_array(); + m_enum.reserve( a.size() ); + for( const auto& e : a ) { + m_enum.emplace_back( new events_compare< Traits >() ); + m_enum.back()->push( &e ); + } + } + if( const auto* p = m_node->m_all_of ) { + for( const auto& e : p->unsafe_get_array() ) { + m_all_of.push_back( m_container->consumer( e.skip_raw_ptr() ) ); + } + } + if( const auto* p = m_node->m_any_of ) { + for( const auto& e : p->unsafe_get_array() ) { + m_any_of.push_back( m_container->consumer( e.skip_raw_ptr() ) ); + } + } + if( const auto* p = m_node->m_one_of ) { + for( const auto& e : p->unsafe_get_array() ) { + m_one_of.push_back( m_container->consumer( e.skip_raw_ptr() ) ); + } + } + if( const auto* p = m_node->m_not ) { + m_not = m_container->consumer( p ); + } + for( const auto& e : m_node->m_schema_dependencies ) { + m_schema_dependencies.emplace( e.first, m_container->consumer( e.second ) ); + } + } + + schema_consumer( const schema_consumer& ) = delete; + schema_consumer( schema_consumer&& ) = delete; + + void operator=( const schema_consumer& ) = delete; + void operator=( schema_consumer&& ) = delete; + + bool finalize() + { + if( m_match && !m_all_of.empty() ) { + for( auto& e : m_all_of ) { + if( !e->finalize() ) { + m_match = false; + break; + } + } + } + if( m_match && !m_any_of.empty() ) { + m_any_of.erase( std::remove_if( m_any_of.begin(), m_any_of.end(), []( const std::unique_ptr< schema_consumer >& c ) { return !c->finalize(); } ), m_any_of.end() ); + if( m_any_of.empty() ) { + m_match = false; + } + } + if( m_match && !m_one_of.empty() ) { + m_one_of.erase( std::remove_if( m_one_of.begin(), m_one_of.end(), []( const std::unique_ptr< schema_consumer >& c ) { return !c->finalize(); } ), m_one_of.end() ); + if( m_one_of.size() != 1 ) { + m_match = false; + } + } + if( m_match && m_not && m_not->finalize() ) { + m_match = false; + } + if( m_match && m_node->m_flags & HAS_DEPENDENCIES ) { + for( const auto& e : m_node->m_schema_dependencies ) { + if( m_keys.count( e.first ) != 0 ) { + const auto it = m_schema_dependencies.find( e.first ); + if( it == m_schema_dependencies.end() ) { + m_match = false; + break; + } + if( !it->second->finalize() ) { + m_match = false; + break; + } + } + } + } + return m_match; + } + + bool match() const noexcept + { + return m_match; + } + + void null() + { + if( m_match ) + validate_type( NULL_ ); + if( m_match ) + validate_enum( []( events_compare< Traits >& c ) { c.null(); return ! c.match(); } ); + if( m_match ) + validate_collections( []( schema_consumer& c ) { c.null(); return ! c.match(); } ); + if( m_match && m_hash ) + m_hash->null(); + } + + void boolean( const bool v ) + { + if( m_match ) + validate_type( BOOLEAN ); + if( m_match ) + validate_enum( [=]( events_compare< Traits >& c ) { c.boolean( v ); return ! c.match(); } ); + if( m_match ) + validate_collections( [=]( schema_consumer& c ) { c.boolean( v ); return ! c.match(); } ); + if( m_match && m_hash ) + m_hash->boolean( v ); + } + + void number( const std::int64_t v ) + { + if( m_match ) + validate_type( INTEGER | NUMBER ); + if( m_match ) + validate_enum( [=]( events_compare< Traits >& c ) { c.number( v ); return ! c.match(); } ); + if( m_match ) + validate_collections( [=]( schema_consumer& c ) { c.number( v ); return ! c.match(); } ); + if( m_match && m_count.empty() ) + validate_number( v ); + if( m_match && m_hash ) + m_hash->number( v ); + } + + void number( const std::uint64_t v ) + { + if( m_match ) + validate_type( INTEGER | NUMBER ); + if( m_match ) + validate_enum( [=]( events_compare< Traits >& c ) { c.number( v ); return ! c.match(); } ); + if( m_match ) + validate_collections( [=]( schema_consumer& c ) { c.number( v ); return ! c.match(); } ); + if( m_match && m_count.empty() ) + validate_number( v ); + if( m_match && m_hash ) + m_hash->number( v ); + } + + void number( const double v ) + { + if( m_match ) + validate_type( NUMBER ); + if( m_match ) + validate_enum( [=]( events_compare< Traits >& c ) { c.number( v ); return ! c.match(); } ); + if( m_match ) + validate_collections( [=]( schema_consumer& c ) { c.number( v ); return ! c.match(); } ); + if( m_match && m_count.empty() ) + validate_number( v ); + if( m_match && m_hash ) + m_hash->number( v ); + } + + void string( const tao::string_view v ) + { + if( m_match ) + validate_type( STRING ); + if( m_match ) + validate_enum( [&]( events_compare< Traits >& c ) { c.string( v ); return ! c.match(); } ); + if( m_match ) + validate_collections( [&]( schema_consumer& c ) { c.string( v ); return ! c.match(); } ); + if( m_match && m_count.empty() ) + validate_string( v ); + if( m_match && m_hash ) + m_hash->string( v ); + } + + void binary( const tao::byte_view ) + { + // TODO: What? + } + + void begin_array( const std::size_t = 0 ) + { + if( m_match ) + validate_type( ARRAY ); + if( m_match ) + validate_enum( []( events_compare< Traits >& c ) { c.begin_array(); return ! c.match(); } ); + if( m_match ) + validate_collections( []( schema_consumer& c ) { c.begin_array(); return ! c.match(); } ); + if( m_match ) { + if( m_hash ) { + m_hash->begin_array(); + } + else if( m_count.empty() && ( ( m_node->m_flags & HAS_UNIQUE_ITEMS ) != 0 ) ) { + m_hash.reset( new events::hash ); + } + } + if( m_match && m_count.empty() ) { + if( const auto* p = m_node->m_items ) { + if( p->is_object() ) { + m_item = m_container->consumer( p ); + } + else { + const auto& a = p->unsafe_get_array(); + if( !a.empty() ) { + m_item = m_container->consumer( a[ 0 ].skip_raw_ptr() ); + } + } + } + if( !m_item ) { + if( const auto* p = m_node->m_additional_items ) { + if( p->is_object() ) { + m_item = m_container->consumer( p ); + } + } + } + } + m_count.push_back( 0 ); + } + + void element() + { + if( m_match ) + validate_enum( []( events_compare< Traits >& c ) { c.element(); return ! c.match(); } ); + if( m_match && m_item ) { + if( m_count.size() == 1 ) { + if( !m_item->finalize() ) { + m_match = false; + } + m_item.reset(); + } + } + if( m_match ) + validate_collections( []( schema_consumer& c ) { c.element(); return ! c.match(); } ); + if( m_match && m_hash ) { + if( m_count.size() == 1 ) { + if( !m_unique.emplace( m_hash->value() ).second ) { + m_match = false; + } + m_hash->reset(); + } + else { + m_hash->element(); + } + } + const auto next = ++m_count.back(); + if( m_match && ( m_count.size() == 1 ) ) { + if( const auto* p = m_node->m_items ) { + if( p->is_object() ) { + m_item = m_container->consumer( p ); + } + else { + const auto& a = p->unsafe_get_array(); + if( next < a.size() ) { + m_item = m_container->consumer( a[ next ].skip_raw_ptr() ); + } + } + } + if( !m_item ) { + if( const auto* p = m_node->m_additional_items ) { + if( p->is_object() ) { + m_item = m_container->consumer( p ); + } + } + } + } + } + + void end_array( const std::size_t = 0 ) + { + if( m_match ) + validate_enum( []( events_compare< Traits >& c ) { c.end_array(); return ! c.match(); } ); + if( m_match && m_item && ( m_count.size() == 1 ) ) { + if( !m_item->finalize() ) { + m_match = false; + } + m_item.reset(); + } + if( m_match && ( m_count.size() == 1 ) ) { + if( m_node->m_items && m_node->m_items->is_array() ) { + if( m_node->m_additional_items && m_node->m_additional_items->is_boolean() ) { + if( !m_node->m_additional_items->get_boolean() ) { + if( m_count.back() > m_node->m_items->unsafe_get_array().size() ) { + m_match = false; + } + } + } + } + } + if( m_match ) + validate_collections( []( schema_consumer& c ) { c.end_array(); return ! c.match(); } ); + if( m_match && m_hash ) + m_hash->end_array(); + if( m_match && ( m_count.size() == 1 ) ) + validate_elements( m_count.back() ); + m_count.pop_back(); + } + + void begin_object( const std::size_t = 0 ) + { + if( m_match ) + validate_type( OBJECT ); + if( m_match ) + validate_enum( []( events_compare< Traits >& c ) { c.begin_object(); return ! c.match(); } ); + if( m_match ) + validate_collections( []( schema_consumer& c ) { c.begin_object(); return ! c.match(); } ); + if( m_match && m_hash ) + m_hash->begin_object(); + m_count.push_back( 0 ); + } + + void key( const std::string& v ) + { + if( m_match ) + validate_enum( [&]( events_compare< Traits >& c ) { c.key( v ); return ! c.match(); } ); + if( m_match ) + validate_collections( [&]( schema_consumer& c ) { c.key( v ); return ! c.match(); } ); + if( m_match && m_hash ) + m_hash->key( v ); + if( m_match && ( m_count.size() == 1 ) && ( m_node->m_flags & HAS_DEPENDENCIES || !m_node->m_required.empty() ) ) { + if( !m_keys.insert( v ).second ) { + // duplicate keys immediately invalidate! + // TODO: throw? + m_match = false; + } + } + if( m_match && m_properties.empty() && ( m_count.size() == 1 ) ) { + if( const auto* p = m_node->m_properties ) { + const auto& o = p->unsafe_get_object(); + const auto it = o.find( v ); + if( it != o.end() ) { + m_properties.push_back( m_container->consumer( it->second.skip_raw_ptr() ) ); + } + } + for( const auto& e : m_node->m_pattern_properties ) { + if( std::regex_search( v, e.first ) ) { + m_properties.push_back( m_container->consumer( e.second ) ); + } + } + if( m_properties.empty() ) { + if( const auto* p = m_node->m_additional_properties ) { + if( p->is_boolean() ) { + if( !p->unsafe_get_boolean() ) { + m_match = false; + } + } + else { + m_properties.push_back( m_container->consumer( p ) ); + } + } + } + } + } + + void member() + { + if( m_match ) + validate_enum( []( events_compare< Traits >& c ) { c.member(); return ! c.match(); } ); + if( m_match && !m_properties.empty() && ( m_count.size() == 1 ) ) { + for( auto& e : m_properties ) { + if( !e->finalize() ) { + m_match = false; + break; + } + } + m_properties.clear(); + } + if( m_match ) + validate_collections( []( schema_consumer& c ) { c.member(); return ! c.match(); } ); + if( m_match && m_hash ) + m_hash->member(); + ++m_count.back(); + } + + void end_object( const std::size_t = 0 ) + { + if( m_match ) + validate_enum( []( events_compare< Traits >& c ) { c.end_object(); return ! c.match(); } ); + if( m_match ) + validate_collections( []( schema_consumer& c ) { c.end_object(); return ! c.match(); } ); + if( m_match && m_hash ) + m_hash->end_object(); + if( m_match && ( m_count.size() == 1 ) ) + validate_members( m_count.back() ); + if( m_match && ( m_count.size() == 1 ) && !m_node->m_required.empty() ) { + if( !std::includes( m_keys.begin(), m_keys.end(), m_node->m_required.begin(), m_node->m_required.end() ) ) { + m_match = false; + } + } + if( m_match && ( m_count.size() == 1 ) && m_node->m_flags & HAS_DEPENDENCIES ) { + for( const auto& e : m_node->m_property_dependencies ) { + if( m_keys.count( e.first ) != 0 ) { + if( !std::includes( m_keys.begin(), m_keys.end(), e.second.begin(), e.second.end() ) ) { + m_match = false; + break; + } + } + } + } + m_count.pop_back(); + } + }; + + template< template< typename... > class Traits > + class schema_container + : public std::enable_shared_from_this< schema_container< Traits > > + { + private: + basic_value< Traits > m_value; + + using nodes_t = std::map< const basic_value< Traits >*, std::unique_ptr< schema_node< Traits > > >; + nodes_t m_nodes; + + void make_node( const basic_value< Traits >* p ) + { + m_nodes.emplace( p, std::unique_ptr< schema_node< Traits > >( new schema_node< Traits >( this, *p ) ) ); + } + + public: + explicit schema_container( const basic_value< Traits >& v ) + : m_value( *v.skip_raw_ptr() ) + { + resolve_references( m_value ); + make_node( &m_value ); + while( true ) { + std::set< const basic_value< Traits >* > required; + for( const auto& e : m_nodes ) { + auto s = e.second->referenced_pointers(); + required.insert( s.begin(), s.end() ); + } + for( const auto& e : m_nodes ) { + required.erase( e.first ); + } + if( required.empty() ) { + break; + } + for( const auto& e : required ) { + make_node( e ); + } + } + } + + std::unique_ptr< schema_consumer< Traits > > consumer( const basic_value< Traits >* p ) const + { + const auto it = m_nodes.find( p ); + if( it == m_nodes.end() ) { + throw std::logic_error( "invalid node ptr, no schema registered" ); + } + return std::unique_ptr< schema_consumer< Traits > >( new schema_consumer< Traits >( this->shared_from_this(), *it->second ) ); + } + + std::unique_ptr< schema_consumer< Traits > > consumer() const + { + return consumer( &m_value ); + } + }; + + } // namespace internal + + template< template< typename... > class Traits > + class basic_schema + { + private: + const std::shared_ptr< const internal::schema_container< Traits > > m_container; + + public: + explicit basic_schema( const basic_value< Traits >& v ) + : m_container( std::make_shared< internal::schema_container< Traits > >( v ) ) + { + } + + std::unique_ptr< internal::schema_consumer< Traits > > consumer() const + { + return m_container->consumer(); + } + + bool validate( const basic_value< Traits >& v ) const + { + // TODO: Value validation should be implemented independently, + // as it could be more efficient than Events validation! + const auto c = consumer(); + events::from_value( *c, v ); + return c->finalize(); + } + }; + + using schema = basic_schema< traits >; + + template< template< typename... > class Traits > + basic_schema< Traits > make_schema( const basic_value< Traits >& v ) + { + return basic_schema< Traits >( v ); + } + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/self_contained.hpp b/include/tao/json/self_contained.hpp new file mode 100644 index 00000000..993d21d7 --- /dev/null +++ b/include/tao/json/self_contained.hpp @@ -0,0 +1,137 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_SELF_CONTAINED_HPP +#define TAOCPP_JSON_INCLUDE_SELF_CONTAINED_HPP + +#include "value.hpp" + +namespace tao +{ + namespace json + { + // recursively checks for the existence if RAW_PTR nodes, + // STRING_VIEW or BINARY_VIEW, + // returns true is no such nodes were found. + template< template< typename... > class Traits > + bool is_self_contained( const basic_value< Traits >& v ) noexcept + { + switch( v.type() ) { + case type::UNINITIALIZED: + return true; + + // LCOV_EXCL_START + case type::DISCARDED: + assert( v.type() != type::DISCARDED ); + return false; + + case type::DESTROYED: + assert( v.type() != type::DESTROYED ); + return false; + // LCOV_EXCL_STOP + + case type::NULL_: + case type::BOOLEAN: + case type::SIGNED: + case type::UNSIGNED: + case type::DOUBLE: + case type::STRING: + case type::BINARY: + return true; + + case type::STRING_VIEW: + case type::BINARY_VIEW: + return false; + + case type::ARRAY: + for( auto& e : v.unsafe_get_array() ) { + if( !is_self_contained( e ) ) { + return false; + } + } + return true; + + case type::OBJECT: + for( auto& e : v.unsafe_get_object() ) { + if( !is_self_contained( e.second ) ) { + return false; + } + } + return true; + + case type::RAW_PTR: + return false; + } + // LCOV_EXCL_START + assert( false ); + return false; + // LCOV_EXCL_STOP + } + + // removes all RAW_PTR nodes, recursively, by copying their pointed-to content + // or replacing a nullptr RAW_PTR node with a null node. + // replaces STRING_VIEW and BINARY_VIEW with copies. + template< template< typename... > class Traits > + void make_self_contained( basic_value< Traits >& v ) + { + switch( v.type() ) { + case type::UNINITIALIZED: + return; + + case type::DISCARDED: + throw std::logic_error( "attempt to use a discarded value" ); + + case type::DESTROYED: + throw std::logic_error( "attempt to use a destroyed value" ); + + case type::NULL_: + case type::BOOLEAN: + case type::SIGNED: + case type::UNSIGNED: + case type::DOUBLE: + case type::STRING: + case type::BINARY: + return; + + case type::STRING_VIEW: { + const auto sv = v.unsafe_get_string_view(); + v.unsafe_emplace_string( sv.data(), sv.size() ); + return; + } + + case type::BINARY_VIEW: { + const auto xv = v.unsafe_get_binary_view(); + v.unsafe_emplace_binary( xv.begin(), xv.end() ); + return; + } + + case type::ARRAY: + for( auto& e : v.unsafe_get_array() ) { + make_self_contained( e ); + } + return; + + case type::OBJECT: + for( auto& e : v.unsafe_get_object() ) { + make_self_contained( e.second ); + } + return; + + case type::RAW_PTR: + if( const auto* p = v.unsafe_get_raw_ptr() ) { + v = *p; + make_self_contained( v ); + } + else { + v.unsafe_assign_null(); + } + return; + } + throw std::logic_error( "invalid value for tao::json::type" ); // LCOV_EXCL_LINE + } + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/single.hpp b/include/tao/json/single.hpp new file mode 100644 index 00000000..d3e681ca --- /dev/null +++ b/include/tao/json/single.hpp @@ -0,0 +1,49 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_SINGLE_HPP +#define TAOCPP_JSON_INCLUDE_SINGLE_HPP + +#include + +#include "pair.hpp" + +namespace tao +{ + namespace json + { + template< template< typename... > class Traits > + class basic_value; + + template< template< typename... > class Traits > + struct single + { + mutable basic_value< Traits > value; + + template< typename U > + single( U&& v ) + : value( std::forward< U >( v ) ) + { + } + + single( std::initializer_list< pair< Traits > >&& l ) + : value( std::move( l ) ) + { + } + + single( const std::initializer_list< pair< Traits > >& l ) + : value( l ) + { + } + + single( std::initializer_list< pair< Traits > >& l ) + : value( l ) + { + } + }; + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/stream.hpp b/include/tao/json/stream.hpp new file mode 100644 index 00000000..493f06ef --- /dev/null +++ b/include/tao/json/stream.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_STREAM_HPP +#define TAOCPP_JSON_INCLUDE_STREAM_HPP + +#include +#include + +#include "to_stream.hpp" +#include "value.hpp" + +namespace tao +{ + namespace json + { + // Use ostream << std::setw( n ) for pretty-printing with indent n. + + template< template< typename... > class Traits > + std::ostream& operator<<( std::ostream& o, const basic_value< Traits >& v ) + { + const auto w = o.width(); + + o.width( 0 ); + + if( w > 0 ) { + json::to_stream( o, v, w ); + } + else { + json::to_stream( o, v ); + } + return o; + } + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/to_stream.hpp b/include/tao/json/to_stream.hpp new file mode 100644 index 00000000..3255635f --- /dev/null +++ b/include/tao/json/to_stream.hpp @@ -0,0 +1,38 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_TO_STREAM_HPP +#define TAOCPP_JSON_INCLUDE_TO_STREAM_HPP + +#include +#include + +#include "events/from_value.hpp" +#include "events/to_pretty_stream.hpp" +#include "events/to_stream.hpp" +#include "events/transformer.hpp" +#include "value.hpp" + +namespace tao +{ + namespace json + { + template< template< typename... > class... Transformers, template< typename... > class Traits > + void to_stream( std::ostream& os, const basic_value< Traits >& v ) + { + events::transformer< events::to_stream, Transformers... > consumer( os ); + events::from_value( consumer, v ); + } + + template< template< typename... > class... Transformers, template< typename... > class Traits > + void to_stream( std::ostream& os, const basic_value< Traits >& v, const std::size_t indent ) + { + events::transformer< events::to_pretty_stream, Transformers... > consumer( os, indent ); + events::from_value( consumer, v ); + } + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/to_string.hpp b/include/tao/json/to_string.hpp new file mode 100644 index 00000000..3d4e123d --- /dev/null +++ b/include/tao/json/to_string.hpp @@ -0,0 +1,27 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_TO_STRING_HPP +#define TAOCPP_JSON_INCLUDE_TO_STRING_HPP + +#include + +#include "to_stream.hpp" + +namespace tao +{ + namespace json + { + template< template< typename... > class... Transformers, typename... Ts > + std::string to_string( Ts&&... ts ) + { + std::ostringstream o; + json::to_stream< Transformers... >( o, std::forward< Ts >( ts )... ); + return o.str(); + } + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/traits.hpp b/include/tao/json/traits.hpp new file mode 100644 index 00000000..b7492d7a --- /dev/null +++ b/include/tao/json/traits.hpp @@ -0,0 +1,1091 @@ +// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_TRAITS_HPP +#define TAOCPP_JSON_INCLUDE_TRAITS_HPP + +#include + +#include +#include +#include + +#include "byte_view.hpp" +#include "type.hpp" + +#include "internal/throw.hpp" + +#include "external/byte.hpp" +#include "external/optional.hpp" +#include "external/string_view.hpp" + +namespace tao +{ + namespace json + { + template< template< typename... > class Traits > + class basic_value; + + // note: traits< ... >::assign() is always called with needs_discard(v) == false + + template< typename T, typename = void > + struct traits; + + template<> + struct traits< null_t > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, null_t ) noexcept + { + v.unsafe_assign_null(); + } + + template< template< typename... > class Traits > + static bool equal( const basic_value< Traits >& lhs, null_t ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + return p->is_null(); + } + else { + return true; + } + } + + template< template< typename... > class Traits > + static bool less_than( const basic_value< Traits >& lhs, null_t ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + return p->type() < type::NULL_; + } + else { + return false; + } + } + + template< template< typename... > class Traits > + static bool greater_than( const basic_value< Traits >& lhs, null_t ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + return p->type() > type::NULL_; + } + else { + return false; + } + } + }; + + template<> + struct traits< bool > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const bool b ) noexcept + { + v.unsafe_assign_bool( b ); + } + + template< template< typename... > class Traits > + static void extract( const basic_value< Traits >& v, bool& b ) + { + b = v.get_boolean(); + } + + template< template< typename... > class Traits > + static bool equal( const basic_value< Traits >& lhs, const bool rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + return p->is_boolean() && ( p->unsafe_get_boolean() == rhs ); + } + else { + return false; + } + } + + template< template< typename... > class Traits > + static bool less_than( const basic_value< Traits >& lhs, const bool rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + return ( p->type() < type::BOOLEAN ) || ( p->is_boolean() && ( p->unsafe_get_boolean() < rhs ) ); + } + else { + return type::NULL_ < type::BOOLEAN; + } + } + + template< template< typename... > class Traits > + static bool greater_than( const basic_value< Traits >& lhs, const bool rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + return ( p->type() > type::BOOLEAN ) || ( p->is_boolean() && ( p->unsafe_get_boolean() > rhs ) ); + } + else { + return type::NULL_ > type::BOOLEAN; + } + } + }; + + namespace internal + { + template< typename T > + struct number_trait + { + template< template< typename... > class Traits > + static void extract( const basic_value< Traits >& v, T& i ) + { + switch( v.type() ) { + case type::SIGNED: + i = v.unsafe_get_signed(); + break; + case type::UNSIGNED: + i = v.unsafe_get_unsigned(); + break; + case type::DOUBLE: + i = v.unsafe_get_double(); + break; + default: + TAOCPP_JSON_THROW_TYPE_ERROR( v.type() ); + } + } + }; + + template< typename T > + struct signed_trait + : number_trait< T > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const T i ) noexcept + { + v.unsafe_assign_signed( i ); + } + + template< template< typename... > class Traits > + static bool equal( const basic_value< Traits >& lhs, const T rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::SIGNED: + return p->unsafe_get_signed() == rhs; + case type::UNSIGNED: + return ( rhs >= 0 ) && ( p->unsafe_get_unsigned() == static_cast< std::uint64_t >( rhs ) ); + case type::DOUBLE: + return p->unsafe_get_double() == rhs; + default: + return false; + } + } + else { + return false; + } + } + + template< template< typename... > class Traits > + static bool less_than( const basic_value< Traits >& lhs, const T rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::SIGNED: + return p->unsafe_get_signed() < rhs; + case type::UNSIGNED: + return ( rhs >= 0 ) && ( p->unsafe_get_unsigned() < static_cast< std::uint64_t >( rhs ) ); + case type::DOUBLE: + return p->unsafe_get_double() < rhs; + default: + return p->type() < type::SIGNED; + } + } + else { + return type::NULL_ < type::SIGNED; + } + } + + template< template< typename... > class Traits > + static bool greater_than( const basic_value< Traits >& lhs, const T rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::SIGNED: + return p->unsafe_get_signed() > rhs; + case type::UNSIGNED: + return ( rhs < 0 ) || ( p->unsafe_get_unsigned() > static_cast< std::uint64_t >( rhs ) ); + case type::DOUBLE: + return p->unsafe_get_double() > rhs; + default: + return p->type() > type::SIGNED; + } + } + else { + return type::NULL_ > type::SIGNED; + } + } + }; + + template< typename T > + struct unsigned_trait + : number_trait< T > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const T i ) noexcept + { + v.unsafe_assign_unsigned( i ); + } + + template< template< typename... > class Traits > + static bool equal( const basic_value< Traits >& lhs, const T rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::SIGNED: { + const auto v = p->unsafe_get_signed(); + return ( v >= 0 ) && ( static_cast< std::uint64_t >( v ) == rhs ); + } + case type::UNSIGNED: + return p->unsafe_get_unsigned() == rhs; + case type::DOUBLE: + return p->unsafe_get_double() == rhs; + default: + return false; + } + } + else { + return false; + } + } + + template< template< typename... > class Traits > + static bool less_than( const basic_value< Traits >& lhs, const T rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::SIGNED: { + const auto v = p->unsafe_get_signed(); + return ( v < 0 ) || ( static_cast< std::uint64_t >( v ) < rhs ); + } + case type::UNSIGNED: + return p->unsafe_get_unsigned() < rhs; + case type::DOUBLE: + return p->unsafe_get_double() < rhs; + default: + return p->type() < type::UNSIGNED; + } + } + else { + return type::NULL_ < type::UNSIGNED; + } + } + + template< template< typename... > class Traits > + static bool greater_than( const basic_value< Traits >& lhs, const T rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::SIGNED: { + const auto v = p->unsafe_get_signed(); + return ( v >= 0 ) && ( static_cast< std::uint64_t >( v ) > rhs ); + } + case type::UNSIGNED: + return p->unsafe_get_unsigned() > rhs; + case type::DOUBLE: + return p->unsafe_get_double() > rhs; + default: + return p->type() > type::UNSIGNED; + } + } + else { + return type::NULL_ > type::UNSIGNED; + } + } + }; + + template< typename T > + struct float_trait + : number_trait< T > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const T f ) noexcept + { + v.unsafe_assign_double( f ); + } + + template< template< typename... > class Traits > + static bool equal( const basic_value< Traits >& lhs, const T rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::SIGNED: + return p->unsafe_get_signed() == rhs; + case type::UNSIGNED: + return p->unsafe_get_unsigned() == rhs; + case type::DOUBLE: + return p->unsafe_get_double() == rhs; + default: + return false; + } + } + else { + return false; + } + } + + template< template< typename... > class Traits > + static bool less_than( const basic_value< Traits >& lhs, const T rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::SIGNED: + return p->unsafe_get_signed() < rhs; + case type::UNSIGNED: + return p->unsafe_get_unsigned() < rhs; + case type::DOUBLE: + return p->unsafe_get_double() < rhs; + default: + return p->type() < type::DOUBLE; + } + } + else { + return type::NULL_ < type::DOUBLE; + } + } + + template< template< typename... > class Traits > + static bool greater_than( const basic_value< Traits >& lhs, const T rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::SIGNED: + return p->unsafe_get_signed() > rhs; + case type::UNSIGNED: + return p->unsafe_get_unsigned() > rhs; + case type::DOUBLE: + return p->unsafe_get_double() > rhs; + default: + return p->type() > type::DOUBLE; + } + } + else { + return type::NULL_ > type::DOUBLE; + } + } + }; + } + + // clang-format off + template<> struct traits< signed char > : internal::signed_trait< signed char > {}; + template<> struct traits< signed short > : internal::signed_trait< signed short > {}; + template<> struct traits< signed int > : internal::signed_trait< signed int > {}; + template<> struct traits< signed long > : internal::signed_trait< signed long > {}; + template<> struct traits< signed long long > : internal::signed_trait< signed long long > {}; + + template<> struct traits< unsigned char > : internal::unsigned_trait< unsigned char > {}; + template<> struct traits< unsigned short > : internal::unsigned_trait< unsigned short > {}; + template<> struct traits< unsigned int > : internal::unsigned_trait< unsigned int > {}; + template<> struct traits< unsigned long > : internal::unsigned_trait< unsigned long > {}; + template<> struct traits< unsigned long long > : internal::unsigned_trait< unsigned long long > {}; + + template<> struct traits< float > : internal::float_trait< float > {}; + template<> struct traits< double > : internal::float_trait< double > {}; + // clang-format on + + template<> + struct traits< empty_binary_t > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, empty_binary_t ) noexcept + { + v.unsafe_emplace_binary(); + } + + template< template< typename... > class Traits > + static bool equal( const basic_value< Traits >& lhs, empty_binary_t ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::BINARY: + return p->unsafe_get_binary().empty(); + case type::BINARY_VIEW: + return p->unsafe_get_binary_view().empty(); + default: + return false; + } + } + else { + return false; + } + } + + template< template< typename... > class Traits > + static bool less_than( const basic_value< Traits >& lhs, empty_binary_t ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::BINARY: + case type::BINARY_VIEW: + return false; + default: + return p->type() < type::BINARY; + } + } + else { + return type::NULL_ < type::BINARY; + } + } + + template< template< typename... > class Traits > + static bool greater_than( const basic_value< Traits >& lhs, empty_binary_t ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::BINARY: + return !p->unsafe_get_binary().empty(); + case type::BINARY_VIEW: + return !p->unsafe_get_binary_view().empty(); + default: + return p->type() > type::BINARY; + } + } + else { + return type::NULL_ > type::BINARY; + } + } + }; + + template<> + struct traits< empty_array_t > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, empty_array_t ) noexcept + { + v.unsafe_emplace_array(); + } + + template< template< typename... > class Traits > + static bool equal( const basic_value< Traits >& lhs, empty_array_t ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + return p->is_array() && p->unsafe_get_array().empty(); + } + else { + return false; + } + } + + template< template< typename... > class Traits > + static bool less_than( const basic_value< Traits >& lhs, empty_array_t ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + return p->type() < type::ARRAY; + } + else { + return type::NULL_ < type::ARRAY; + } + } + + template< template< typename... > class Traits > + static bool greater_than( const basic_value< Traits >& lhs, empty_array_t ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + return ( p->type() > type::ARRAY ) || ( p->is_array() && !p->unsafe_get_array().empty() ); + } + else { + return type::NULL_ > type::ARRAY; + } + } + }; + + template<> + struct traits< empty_object_t > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, empty_object_t ) noexcept + { + v.unsafe_emplace_object(); + } + + template< template< typename... > class Traits > + static bool equal( const basic_value< Traits >& lhs, empty_object_t ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + return p->is_object() && p->unsafe_get_object().empty(); + } + else { + return false; + } + } + + template< template< typename... > class Traits > + static bool less_than( const basic_value< Traits >& lhs, empty_object_t ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + return p->type() < type::OBJECT; + } + else { + return type::NULL_ < type::OBJECT; + } + } + + template< template< typename... > class Traits > + static bool greater_than( const basic_value< Traits >& lhs, empty_object_t ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + return ( p->type() > type::OBJECT ) || ( p->is_object() && !p->unsafe_get_object().empty() ); + } + else { + return type::NULL_ > type::OBJECT; + } + } + }; + + template<> + struct traits< std::string > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const std::string& s ) + { + v.unsafe_assign_string( s ); + } + + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, std::string&& s ) noexcept + { + v.unsafe_assign_string( std::move( s ) ); + } + + template< template< typename... > class Traits > + static void extract( const basic_value< Traits >& v, std::string& s ) + { + switch( v.type() ) { + case type::STRING: + s = v.unsafe_get_string(); + break; + case type::STRING_VIEW: { + const auto sv = v.unsafe_get_string_view(); + s.assign( sv.data(), sv.size() ); + break; + } + default: + TAOCPP_JSON_THROW_TYPE_ERROR( v.type() ); + } + } + + template< template< typename... > class Traits > + static bool equal( const basic_value< Traits >& lhs, const std::string& rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::STRING: + return p->unsafe_get_string() == rhs; + case type::STRING_VIEW: + return p->unsafe_get_string_view() == rhs; + default: + return false; + } + } + else { + return false; + } + } + + template< template< typename... > class Traits > + static bool less_than( const basic_value< Traits >& lhs, const std::string& rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::STRING: + return p->unsafe_get_string() < rhs; + case type::STRING_VIEW: + return p->unsafe_get_string_view() < rhs; + default: + return p->type() < type::STRING; + } + } + else { + return type::NULL_ < type::STRING; + } + } + + template< template< typename... > class Traits > + static bool greater_than( const basic_value< Traits >& lhs, const std::string& rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::STRING: + return p->unsafe_get_string() > rhs; + case type::STRING_VIEW: + return p->unsafe_get_string_view() > rhs; + default: + return p->type() > type::STRING; + } + } + else { + return type::NULL_ > type::STRING; + } + } + }; + + template<> + struct traits< tao::string_view > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const tao::string_view sv ) + { + v.unsafe_emplace_string( sv.data(), sv.size() ); + } + + template< template< typename... > class Traits > + static tao::string_view as( const basic_value< Traits >& v ) + { + switch( v.type() ) { + case type::STRING: + return v.unsafe_get_string(); + case type::STRING_VIEW: + return v.unsafe_get_string_view(); + default: + TAOCPP_JSON_THROW_TYPE_ERROR( v.type() ); + } + } + + template< template< typename... > class Traits > + static bool equal( const basic_value< Traits >& lhs, const tao::string_view rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::STRING: + return p->unsafe_get_string() == rhs; + case type::STRING_VIEW: + return p->unsafe_get_string_view() == rhs; + default: + return false; + } + } + else { + return false; + } + } + + template< template< typename... > class Traits > + static bool less_than( const basic_value< Traits >& lhs, const tao::string_view rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::STRING: + return p->unsafe_get_string() < rhs; + case type::STRING_VIEW: + return p->unsafe_get_string_view() < rhs; + default: + return p->type() < type::STRING; + } + } + else { + return type::NULL_ < type::STRING; + } + } + + template< template< typename... > class Traits > + static bool greater_than( const basic_value< Traits >& lhs, const tao::string_view rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::STRING: + return p->unsafe_get_string() > rhs; + case type::STRING_VIEW: + return p->unsafe_get_string_view() > rhs; + default: + return p->type() > type::STRING; + } + } + else { + return type::NULL_ > type::STRING; + } + } + }; + + template<> + struct traits< const char* > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const char* s ) + { + v.unsafe_emplace_string( s ); + } + + template< template< typename... > class Traits > + static const char* as( const basic_value< Traits >& v ) + { + return v.get_string().c_str(); + } + + template< template< typename... > class Traits > + static bool equal( const basic_value< Traits >& lhs, const char* rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::STRING: + return p->unsafe_get_string() == rhs; + case type::STRING_VIEW: + return p->unsafe_get_string_view() == rhs; + default: + return false; + } + } + else { + return false; + } + } + + template< template< typename... > class Traits > + static bool less_than( const basic_value< Traits >& lhs, const char* rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::STRING: + return p->unsafe_get_string() < rhs; + case type::STRING_VIEW: + return p->unsafe_get_string_view() < rhs; + default: + return p->type() < type::STRING; + } + } + else { + return type::NULL_ < type::STRING; + } + } + + template< template< typename... > class Traits > + static bool greater_than( const basic_value< Traits >& lhs, const char* rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::STRING: + return p->unsafe_get_string() > rhs; + case type::STRING_VIEW: + return p->unsafe_get_string_view() > rhs; + default: + return p->type() > type::STRING; + } + } + else { + return type::NULL_ > type::STRING; + } + } + }; + + template<> + struct traits< const std::string& > + { + template< template< typename... > class Traits > + static const std::string& as( const basic_value< Traits >& v ) + { + return v.get_string(); + } + }; + + template<> + struct traits< std::vector< tao::byte > > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const std::vector< tao::byte >& x ) + { + v.unsafe_assign_binary( x ); + } + + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, std::vector< tao::byte >&& x ) noexcept + { + v.unsafe_assign_binary( std::move( x ) ); + } + + template< template< typename... > class Traits > + static void extract( const basic_value< Traits >& v, std::vector< tao::byte >& x ) + { + switch( v.type() ) { + case type::BINARY: + x = v.unsafe_get_binary(); + break; + case type::BINARY_VIEW: { + const auto xv = v.unsafe_get_binary_view(); + x.assign( xv.begin(), xv.end() ); + break; + } + default: + TAOCPP_JSON_THROW_TYPE_ERROR( v.type() ); + } + } + + template< template< typename... > class Traits > + static bool equal( const basic_value< Traits >& lhs, const std::vector< tao::byte >& rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::BINARY: + return p->unsafe_get_binary() == rhs; + case type::BINARY_VIEW: + return p->unsafe_get_binary_view() == rhs; + default: + return false; + } + } + else { + return false; + } + } + + template< template< typename... > class Traits > + static bool less_than( const basic_value< Traits >& lhs, const std::vector< tao::byte >& rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::BINARY: + return p->unsafe_get_binary() < rhs; + case type::BINARY_VIEW: + return p->unsafe_get_binary_view() < rhs; + default: + return p->type() < type::BINARY; + } + } + else { + return type::NULL_ < type::BINARY; + } + } + + template< template< typename... > class Traits > + static bool greater_than( const basic_value< Traits >& lhs, const std::vector< tao::byte >& rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::BINARY: + return p->unsafe_get_binary() > rhs; + case type::BINARY_VIEW: + return p->unsafe_get_binary_view() > rhs; + default: + return p->type() > type::BINARY; + } + } + else { + return type::NULL_ > type::BINARY; + } + } + }; + + template<> + struct traits< tao::byte_view > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const tao::byte_view xv ) noexcept + { + v.unsafe_emplace_binary( xv.begin(), xv.end() ); + } + + template< template< typename... > class Traits > + static tao::byte_view as( const basic_value< Traits >& v ) + { + switch( v.type() ) { + case type::BINARY: + return v.unsafe_get_binary(); + case type::BINARY_VIEW: + return v.unsafe_get_binary_view(); + default: + TAOCPP_JSON_THROW_TYPE_ERROR( v.type() ); + } + } + + template< template< typename... > class Traits > + static bool equal( const basic_value< Traits >& lhs, const tao::byte_view rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::BINARY: + return p->unsafe_get_binary() == rhs; + case type::BINARY_VIEW: + return p->unsafe_get_binary_view() == rhs; + default: + return false; + } + } + else { + return false; + } + } + + template< template< typename... > class Traits > + static bool less_than( const basic_value< Traits >& lhs, const tao::byte_view rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::BINARY: + return p->unsafe_get_binary() < rhs; + case type::BINARY_VIEW: + return p->unsafe_get_binary_view() < rhs; + default: + return p->type() < type::BINARY; + } + } + else { + return type::NULL_ < type::BINARY; + } + } + + template< template< typename... > class Traits > + static bool greater_than( const basic_value< Traits >& lhs, const tao::byte_view rhs ) noexcept + { + if( const auto* p = lhs.skip_raw_ptr() ) { + switch( p->type() ) { + case type::BINARY: + return p->unsafe_get_binary() > rhs; + case type::BINARY_VIEW: + return p->unsafe_get_binary_view() > rhs; + default: + return p->type() > type::BINARY; + } + } + else { + return type::NULL_ > type::BINARY; + } + } + }; + + template<> + struct traits< const std::vector< tao::byte >& > + { + template< template< typename... > class Traits > + static const std::vector< tao::byte >& as( const basic_value< Traits >& v ) + { + return v.get_binary(); + } + }; + + template< template< typename... > class Traits > + struct traits< std::vector< basic_value< Traits > > > + { + static void assign( basic_value< Traits >& v, const std::vector< basic_value< Traits > >& a ) + { + v.unsafe_assign_array( a ); + } + + static void assign( basic_value< Traits >& v, std::vector< basic_value< Traits > >&& a ) noexcept + { + v.unsafe_assign_array( std::move( a ) ); + } + }; + + template< template< typename... > class Traits > + struct traits< std::map< std::string, basic_value< Traits > > > + { + static void assign( basic_value< Traits >& v, const std::map< std::string, basic_value< Traits > >& o ) + { + v.unsafe_assign_object( std::move( o ) ); + } + + static void assign( basic_value< Traits >& v, std::map< std::string, basic_value< Traits > >&& o ) noexcept + { + v.unsafe_assign_object( std::move( o ) ); + } + }; + + template< template< typename... > class Traits > + struct traits< const basic_value< Traits >* > + { + static void assign( basic_value< Traits >& v, const basic_value< Traits >* p ) noexcept + { + v.unsafe_assign_raw_ptr( p ); + } + + template< template< typename... > class TraitsL > + static bool equal( const basic_value< TraitsL >& lhs, const basic_value< Traits >* rhs ) noexcept + { + return rhs ? ( lhs == *rhs ) : ( lhs == null ); + } + + template< template< typename... > class TraitsL > + static bool less_than( const basic_value< TraitsL >& lhs, const basic_value< Traits >* rhs ) noexcept + { + return rhs ? ( lhs < *rhs ) : ( lhs < null ); + } + + template< template< typename... > class TraitsL > + static bool greater_than( const basic_value< TraitsL >& lhs, const basic_value< Traits >* rhs ) noexcept + { + return rhs ? ( lhs > *rhs ) : ( lhs > null ); + } + }; + + template< template< typename... > class Traits > + struct traits< basic_value< Traits >* > + : traits< const basic_value< Traits >* > + { + }; + + template<> + struct traits< std::nullptr_t > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, std::nullptr_t ) noexcept + { + v.unsafe_assign_raw_ptr( nullptr ); + } + + template< template< typename... > class Traits > + static bool equal( const basic_value< Traits >& lhs, std::nullptr_t ) noexcept + { + return lhs == null; + } + + template< template< typename... > class Traits > + static bool less_than( const basic_value< Traits >& lhs, std::nullptr_t ) noexcept + { + return lhs < null; + } + + template< template< typename... > class Traits > + static bool greater_than( const basic_value< Traits >& lhs, std::nullptr_t ) noexcept + { + return lhs > null; + } + }; + + template< typename T > + struct traits< tao::optional< T > > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const tao::optional< T >& o ) + { + if( o ) { + v = *o; + } + else { + v.unsafe_assign_null(); + } + } + + template< template< typename... > class Traits > + static void extract( const basic_value< Traits >& v, tao::optional< T >& o ) + { + if( v.is_null() ) { + o = tao::nullopt; + } + else { + o = v.template as< T >(); + } + } + + template< template< typename... > class Traits > + static bool equal( const basic_value< Traits >& lhs, const tao::optional< T >& rhs ) noexcept + { + return rhs ? ( lhs == *rhs ) : ( lhs == null ); + } + + template< template< typename... > class Traits > + static bool less_than( const basic_value< Traits >& lhs, const tao::optional< T >& rhs ) noexcept + { + return rhs ? ( lhs < *rhs ) : ( lhs < null ); + } + + template< template< typename... > class Traits > + static bool greater_than( const basic_value< Traits >& lhs, const tao::optional< T >& rhs ) noexcept + { + return rhs ? ( lhs > *rhs ) : ( lhs > null ); + } + }; + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/type.hpp b/include/tao/json/type.hpp new file mode 100644 index 00000000..98998d14 --- /dev/null +++ b/include/tao/json/type.hpp @@ -0,0 +1,121 @@ +// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_TYPE_HPP +#define TAOCPP_JSON_INCLUDE_TYPE_HPP + +#include + +namespace tao +{ + namespace json + { + enum class type : std::uint8_t + { + UNINITIALIZED, + DISCARDED, + DESTROYED, + NULL_, + BOOLEAN, + SIGNED, + UNSIGNED, + DOUBLE, + STRING, + STRING_VIEW, + BINARY, + BINARY_VIEW, + ARRAY, + OBJECT, + RAW_PTR + }; + + inline bool needs_discard( const type t ) + { + switch( t ) { + case type::STRING: + case type::STRING_VIEW: + case type::BINARY: + case type::BINARY_VIEW: + case type::ARRAY: + case type::OBJECT: + return true; + default: + return false; + } + } + + inline const char* to_string( const type t ) + { + switch( t ) { + case type::UNINITIALIZED: + return "uninitialized"; + case type::DISCARDED: + return "discarded"; + case type::DESTROYED: + return "destroyed"; + case type::NULL_: + return "null"; + case type::BOOLEAN: + return "boolean"; + case type::SIGNED: + return "signed"; + case type::UNSIGNED: + return "unsigned"; + case type::DOUBLE: + return "double"; + case type::STRING: + return "string"; + case type::STRING_VIEW: + return "string_view"; + case type::BINARY: + return "binary"; + case type::BINARY_VIEW: + return "binary_view"; + case type::ARRAY: + return "array"; + case type::OBJECT: + return "object"; + case type::RAW_PTR: + return "raw_ptr"; + } + return "unknown"; + } + + struct null_t + { + constexpr explicit null_t( int ) + { + } + }; + + struct empty_binary_t + { + constexpr explicit empty_binary_t( int ) + { + } + }; + + struct empty_array_t + { + constexpr explicit empty_array_t( int ) + { + } + }; + + struct empty_object_t + { + constexpr explicit empty_object_t( int ) + { + } + }; + + constexpr null_t null{ 0 }; + constexpr empty_binary_t empty_binary{ 0 }; + constexpr empty_array_t empty_array{ 0 }; + constexpr empty_object_t empty_object{ 0 }; + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/ubjson.hpp b/include/tao/json/ubjson.hpp new file mode 100644 index 00000000..89df4793 --- /dev/null +++ b/include/tao/json/ubjson.hpp @@ -0,0 +1,13 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_UBJSON_HPP +#define TAOCPP_JSON_INCLUDE_UBJSON_HPP + +#include "../json.hpp" + +#include "ubjson/from_string.hpp" +#include "ubjson/to_stream.hpp" +#include "ubjson/to_string.hpp" + +#endif diff --git a/include/tao/json/ubjson/from_string.hpp b/include/tao/json/ubjson/from_string.hpp new file mode 100644 index 00000000..49287610 --- /dev/null +++ b/include/tao/json/ubjson/from_string.hpp @@ -0,0 +1,40 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_UBJSON_FROM_STRING_HPP +#define TAOCPP_JSON_INCLUDE_UBJSON_FROM_STRING_HPP + +#include + +#include "../events/to_value.hpp" +#include "../events/transformer.hpp" + +#include "../events/ubjson/from_string.hpp" + +namespace tao +{ + namespace json + { + namespace ubjson + { + template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > + basic_value< Traits > basic_from_string( Ts&&... ts ) + { + events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; + events::ubjson::from_string( consumer, std::forward< Ts >( ts )... ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers, typename... Ts > + value from_string( Ts&&... ts ) + { + return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); + } + + } // namespace ubjson + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/ubjson/to_stream.hpp b/include/tao/json/ubjson/to_stream.hpp new file mode 100644 index 00000000..31c14317 --- /dev/null +++ b/include/tao/json/ubjson/to_stream.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_UBJSON_TO_STREAM_HPP +#define TAOCPP_JSON_INCLUDE_UBJSON_TO_STREAM_HPP + +#include + +#include "../value.hpp" + +#include "../events/from_value.hpp" +#include "../events/non_finite_to_null.hpp" +#include "../events/transformer.hpp" + +#include "../events/ubjson/to_stream.hpp" + +namespace tao +{ + namespace json + { + namespace ubjson + { + template< template< typename... > class... Transformers, template< typename... > class Traits > + void to_stream( std::ostream& os, const basic_value< Traits >& v ) + { + events::transformer< events::ubjson::to_stream, Transformers..., events::non_finite_to_null > consumer( os ); + events::from_value( consumer, v ); + } + + } // namespace ubjson + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/ubjson/to_string.hpp b/include/tao/json/ubjson/to_string.hpp new file mode 100644 index 00000000..cd6680a0 --- /dev/null +++ b/include/tao/json/ubjson/to_string.hpp @@ -0,0 +1,37 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_UBJSON_TO_STRING_HPP +#define TAOCPP_JSON_INCLUDE_UBJSON_TO_STRING_HPP + +#include + +#include "../value.hpp" + +#include "../events/from_value.hpp" +#include "../events/non_finite_to_null.hpp" +#include "../events/transformer.hpp" + +#include "../events/ubjson/to_string.hpp" + +namespace tao +{ + namespace json + { + namespace ubjson + { + template< template< typename... > class... Transformers, template< typename... > class Traits > + std::string to_string( const basic_value< Traits >& v ) + { + events::transformer< events::ubjson::to_string, Transformers..., events::non_finite_to_null > consumer; + events::from_value( consumer, v ); + return consumer.value(); + } + + } // namespace ubjson + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/tao/json/value.hpp b/include/tao/json/value.hpp new file mode 100644 index 00000000..afb6bd3b --- /dev/null +++ b/include/tao/json/value.hpp @@ -0,0 +1,1905 @@ +// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAOCPP_JSON_INCLUDE_VALUE_HPP +#define TAOCPP_JSON_INCLUDE_VALUE_HPP + +#include +#include +#include +#include +#include +#include + +#include "external/byte.hpp" +#include "external/string_view.hpp" + +#include "internal/get_by_enum.hpp" +#include "internal/identity.hpp" +#include "internal/throw.hpp" +#include "internal/value_union.hpp" + +#include "byte_view.hpp" +#include "pair.hpp" +#include "pointer.hpp" +#include "single.hpp" +#include "traits.hpp" +#include "type.hpp" + +namespace tao +{ + namespace json + { + namespace internal + { + template< typename, typename, typename = void > + struct has_as : std::false_type + { + }; + + template< typename T, typename V > + struct has_as< T, V, decltype( T::as( std::declval< const V& >() ), void() ) > : std::true_type + { + }; + + // required work-around for GCC 6 + inline void rethrow() + { + throw; + } + + } // namespace internal + + template< template< typename... > class Traits > + class basic_value + { + public: + using binary_t = std::vector< tao::byte >; + using array_t = std::vector< basic_value >; + using object_t = std::map< std::string, basic_value >; + + basic_value() noexcept = default; + + basic_value( const basic_value& r ) + : m_type( r.m_type ) + { + try { + embed( r ); + } + catch( ... ) { + this->~basic_value(); + throw; + } + } + + basic_value( basic_value&& r ) noexcept + : m_type( r.m_type ) + { + seize( std::move( r ) ); + } + + basic_value( null_t ) noexcept + { + unsafe_assign_null(); + } + + basic_value( empty_binary_t ) noexcept + { + unsafe_emplace_binary(); + } + + basic_value( empty_array_t ) noexcept + { + unsafe_emplace_array(); + } + + basic_value( empty_object_t ) noexcept + { + unsafe_emplace_object(); + } + + template< typename T, typename = typename std::enable_if< !std::is_convertible< T&&, const basic_value& >::value >::type > + basic_value( T&& v ) noexcept( noexcept( Traits< typename std::decay< T >::type >::assign( std::declval< basic_value& >(), std::forward< T >( v ) ) ) ) + { + try { + using D = typename std::decay< T >::type; + Traits< D >::assign( *this, std::forward< T >( v ) ); + } + catch( ... ) { + this->~basic_value(); + internal::rethrow(); + } + } + + basic_value( std::initializer_list< pair< Traits > >&& l ) + { + try { + unsafe_assign( std::move( l ) ); + } + catch( ... ) { + this->~basic_value(); + throw; + } + } + + basic_value( const std::initializer_list< pair< Traits > >& l ) + { + try { + unsafe_assign( l ); + } + catch( ... ) { + this->~basic_value(); + throw; + } + } + + basic_value( std::initializer_list< pair< Traits > >& l ) + : basic_value( static_cast< const std::initializer_list< pair< Traits > >& >( l ) ) + { + } + + ~basic_value() noexcept + { + unsafe_discard(); + assert( ( const_cast< volatile json::type& >( m_type ) = json::type::DESTROYED, true ) ); + } + + static basic_value array( std::initializer_list< single< Traits > >&& l ) + { + basic_value v; + v.append( std::move( l ) ); + return v; + } + + static basic_value array( const std::initializer_list< single< Traits > >& l ) + { + basic_value v; + v.append( l ); + return v; + } + + basic_value& operator=( basic_value v ) noexcept + { + unsafe_discard(); + m_type = v.m_type; + seize( std::move( v ) ); + return *this; + } + + basic_value& operator=( null_t ) noexcept + { + unsafe_discard(); + unsafe_assign_null(); + return *this; + } + + basic_value& operator=( empty_binary_t ) noexcept + { + unsafe_discard(); + unsafe_emplace_binary(); + return *this; + } + + basic_value& operator=( empty_array_t ) noexcept + { + unsafe_discard(); + unsafe_emplace_array(); + return *this; + } + + basic_value& operator=( empty_object_t ) noexcept + { + unsafe_discard(); + unsafe_emplace_object(); + return *this; + } + + void swap( basic_value& r ) noexcept + { + basic_value t( std::move( r ) ); + r = std::move( *this ); + ( *this ) = ( std::move( t ) ); + } + + json::type type() const noexcept + { + return m_type; + } + + explicit operator bool() const noexcept + { + assert( m_type != json::type::DISCARDED ); + assert( m_type != json::type::DESTROYED ); + return m_type != json::type::UNINITIALIZED; + } + + bool is_null() const noexcept + { + return m_type == json::type::NULL_; + } + + bool is_boolean() const noexcept + { + return m_type == json::type::BOOLEAN; + } + + bool is_signed() const noexcept + { + return m_type == json::type::SIGNED; + } + + bool is_unsigned() const noexcept + { + return m_type == json::type::UNSIGNED; + } + + bool is_integer() const noexcept + { + return is_signed() || is_unsigned(); + } + + bool is_double() const noexcept + { + return m_type == json::type::DOUBLE; + } + + bool is_number() const noexcept + { + return is_integer() || is_double(); + } + + bool is_string() const noexcept + { + return m_type == json::type::STRING; + } + + bool is_string_view() const noexcept + { + return m_type == json::type::STRING_VIEW; + } + + bool is_string_type() const noexcept + { + return is_string() || is_string_view(); + } + + bool is_binary() const noexcept + { + return m_type == json::type::BINARY; + } + + bool is_binary_view() const noexcept + { + return m_type == json::type::BINARY_VIEW; + } + + bool is_binary_type() const noexcept + { + return is_binary() || is_binary_view(); + } + + bool is_array() const noexcept + { + return m_type == json::type::ARRAY; + } + + bool is_object() const noexcept + { + return m_type == json::type::OBJECT; + } + + bool is_raw_ptr() const noexcept + { + return m_type == json::type::RAW_PTR; + } + + // The unsafe_get_*() accessor functions MUST NOT be + // called when the type of the value is not the one + // corresponding to the type of the accessor! + + bool unsafe_get_boolean() const noexcept + { + return m_union.b; + } + + std::int64_t unsafe_get_signed() const noexcept + { + return m_union.i; + } + + std::uint64_t unsafe_get_unsigned() const noexcept + { + return m_union.u; + } + + double unsafe_get_double() const noexcept + { + return m_union.d; + } + + std::string& unsafe_get_string() noexcept + { + return m_union.s; + } + + const std::string& unsafe_get_string() const noexcept + { + return m_union.s; + } + + tao::string_view unsafe_get_string_view() const noexcept + { + return m_union.sv; + } + + binary_t& unsafe_get_binary() noexcept + { + return m_union.x; + } + + const binary_t& unsafe_get_binary() const noexcept + { + return m_union.x; + } + + tao::byte_view unsafe_get_binary_view() const noexcept + { + return m_union.xv; + } + + array_t& unsafe_get_array() noexcept + { + return m_union.a; + } + + const array_t& unsafe_get_array() const noexcept + { + return m_union.a; + } + + object_t& unsafe_get_object() noexcept + { + return m_union.o; + } + + const object_t& unsafe_get_object() const noexcept + { + return m_union.o; + } + + const basic_value* unsafe_get_raw_ptr() const noexcept + { + return m_union.p; + } + + template< json::type E > + decltype( internal::get_by_enum< E >::get( std::declval< internal::value_union< basic_value >& >() ) ) unsafe_get() noexcept + { + return internal::get_by_enum< E >::get( m_union ); + } + + template< json::type E > + decltype( internal::get_by_enum< E >::get( std::declval< const internal::value_union< basic_value >& >() ) ) unsafe_get() const noexcept + { + return internal::get_by_enum< E >::get( m_union ); + } + + bool get_boolean() const + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::BOOLEAN ); + return unsafe_get_boolean(); + } + + std::int64_t get_signed() const + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::SIGNED ); + return unsafe_get_signed(); + } + + std::uint64_t get_unsigned() const + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::UNSIGNED ); + return unsafe_get_unsigned(); + } + + double get_double() const + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::DOUBLE ); + return unsafe_get_double(); + } + + std::string& get_string() + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::STRING ); + return unsafe_get_string(); + } + + const std::string& get_string() const + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::STRING ); + return unsafe_get_string(); + } + + tao::string_view get_string_view() const + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::STRING_VIEW ); + return unsafe_get_string_view(); + } + + binary_t& get_binary() + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::BINARY ); + return unsafe_get_binary(); + } + + const binary_t& get_binary() const + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::BINARY ); + return unsafe_get_binary(); + } + + tao::byte_view get_binary_view() const + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::BINARY_VIEW ); + return unsafe_get_binary_view(); + } + + array_t& get_array() + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::ARRAY ); + return unsafe_get_array(); + } + + const array_t& get_array() const + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::ARRAY ); + return unsafe_get_array(); + } + + object_t& get_object() + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::OBJECT ); + return unsafe_get_object(); + } + + const object_t& get_object() const + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::OBJECT ); + return unsafe_get_object(); + } + + const basic_value* get_raw_ptr() const + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::RAW_PTR ); + return unsafe_get_raw_ptr(); + } + + template< json::type E > + decltype( internal::get_by_enum< E >::get( std::declval< internal::value_union< basic_value >& >() ) ) get() + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, E ); + return internal::get_by_enum< E >::get( m_union ); + } + + template< json::type E > + decltype( internal::get_by_enum< E >::get( std::declval< const internal::value_union< basic_value >& >() ) ) get() const + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, E ); + return internal::get_by_enum< E >::get( m_union ); + } + + void unsafe_assign_null() noexcept + { + m_type = json::type::NULL_; + } + + void unsafe_assign_bool( const bool b ) noexcept + { + m_union.b = b; + m_type = json::type::BOOLEAN; + } + + void unsafe_assign_signed( const std::int64_t i ) noexcept + { + m_union.i = i; + m_type = json::type::SIGNED; + } + + void unsafe_assign_unsigned( const std::uint64_t u ) noexcept + { + m_union.u = u; + m_type = json::type::UNSIGNED; + } + + void unsafe_assign_double( const double d ) noexcept + { + m_union.d = d; + m_type = json::type::DOUBLE; + } + + template< typename... Ts > + void unsafe_emplace_string( Ts&&... ts ) noexcept( noexcept( std::string( std::forward< Ts >( ts )... ) ) ) + { + new( &m_union.s ) std::string( std::forward< Ts >( ts )... ); + m_type = json::type::STRING; + } + + void unsafe_assign_string( const std::string& s ) + { + unsafe_emplace_string( s ); + } + + void unsafe_assign_string( std::string&& s ) noexcept + { + unsafe_emplace_string( std::move( s ) ); + } + + void unsafe_assign_string_view( const tao::string_view sv ) noexcept + { + m_union.sv = sv; + m_type = json::type::STRING_VIEW; + } + + template< typename... Ts > + void unsafe_emplace_binary( Ts&&... ts ) noexcept( noexcept( binary_t( std::forward< Ts >( ts )... ) ) ) + { + new( &m_union.x ) binary_t( std::forward< Ts >( ts )... ); + m_type = json::type::BINARY; + } + + void unsafe_assign_binary( const binary_t& x ) + { + unsafe_emplace_binary( x ); + } + + void unsafe_assign_binary( binary_t&& x ) noexcept + { + unsafe_emplace_binary( std::move( x ) ); + } + + void unsafe_assign_binary_view( const tao::byte_view xv ) noexcept + { + m_union.xv = xv; + m_type = json::type::BINARY_VIEW; + } + + template< typename... Ts > + void unsafe_emplace_array( Ts&&... ts ) noexcept( noexcept( array_t( std::forward< Ts >( ts )... ) ) ) + { + new( &m_union.a ) array_t( std::forward< Ts >( ts )... ); + m_type = json::type::ARRAY; + } + + void unsafe_assign_array( const array_t& a ) + { + unsafe_emplace_array( a ); + } + + void unsafe_assign_array( array_t&& a ) noexcept + { + unsafe_emplace_array( std::move( a ) ); + } + + void unsafe_push_back( const basic_value& v ) + { + m_union.a.push_back( v ); + } + + void unsafe_push_back( basic_value&& v ) + { + m_union.a.push_back( std::move( v ) ); + } + + template< typename... Args > + auto unsafe_emplace_back( Args&&... args ) -> decltype( std::declval< array_t >().emplace_back( std::forward< Args >( args )... ) ) + { + return m_union.a.emplace_back( std::forward< Args >( args )... ); + } + + template< typename... Ts > + void unsafe_emplace_object( Ts&&... ts ) noexcept( noexcept( object_t( std::forward< Ts >( ts )... ) ) ) + { + new( &m_union.o ) object_t( std::forward< Ts >( ts )... ); + m_type = json::type::OBJECT; + } + + void unsafe_assign_object( const object_t& o ) + { + unsafe_emplace_object( o ); + } + + void unsafe_assign_object( object_t&& o ) noexcept + { + unsafe_emplace_object( std::move( o ) ); + } + + template< typename... Args > + std::pair< typename object_t::iterator, bool > unsafe_emplace( Args&&... args ) + { + return m_union.o.emplace( std::forward< Args >( args )... ); + } + + void unsafe_assign_raw_ptr( const basic_value* p ) noexcept + { + m_union.p = p; + m_type = json::type::RAW_PTR; + } + + template< typename T > + void unsafe_assign( T&& v ) noexcept( noexcept( Traits< typename std::decay< T >::type >::assign( std::declval< basic_value& >(), std::forward< T >( v ) ) ) ) + { + using D = typename std::decay< T >::type; + Traits< D >::assign( *this, std::forward< T >( v ) ); + } + + void unsafe_assign( std::initializer_list< pair< Traits > >&& l ) + { + unsafe_emplace_object(); + for( auto& e : l ) { + const auto r = unsafe_emplace( std::move( e.key ), std::move( e.value ) ); + if( !r.second ) { + throw std::runtime_error( "duplicate JSON object key: " + r.first->first ); + } + } + } + + void unsafe_assign( const std::initializer_list< pair< Traits > >& l ) + { + unsafe_emplace_object(); + for( const auto& e : l ) { + const auto r = unsafe_emplace( e.key, e.value ); + if( !r.second ) { + throw std::runtime_error( "duplicate JSON object key: " + r.first->first ); + } + } + } + + void unsafe_assign( std::initializer_list< pair< Traits > >& l ) + { + unsafe_assign( static_cast< const std::initializer_list< pair< Traits > >& >( l ) ); + } + + void assign_null() noexcept + { + unsafe_discard(); + unsafe_assign_null(); + } + + void assign_bool( const bool b ) noexcept + { + unsafe_discard(); + unsafe_assign_bool( b ); + } + + void assign_signed( const std::int64_t i ) noexcept + { + unsafe_discard(); + unsafe_assign_signed( i ); + } + + void assign_unsigned( const std::uint64_t u ) noexcept + { + unsafe_discard(); + unsafe_assign_unsigned( u ); + } + + void assign_double( const double d ) noexcept + { + unsafe_discard(); + unsafe_assign_double( d ); + } + + template< typename... Ts > + void emplace_string( Ts&&... ts ) noexcept( noexcept( unsafe_emplace_string( std::forward< Ts >( ts )... ) ) ) + { + discard(); + unsafe_emplace_string( std::forward< Ts >( ts )... ); + } + + void assign_string( const std::string& s ) + { + discard(); + unsafe_assign_string( s ); + } + + void assign_string( std::string&& s ) noexcept + { + unsafe_discard(); + unsafe_assign_string( std::move( s ) ); + } + + void assign_string_view( const tao::string_view sv ) noexcept + { + unsafe_discard(); + unsafe_assign_string_view( sv ); + } + + template< typename... Ts > + void emplace_binary( Ts&&... ts ) noexcept( noexcept( unsafe_emplace_binary( std::forward< Ts >( ts )... ) ) ) + { + discard(); + unsafe_emplace_binary( std::forward< Ts >( ts )... ); + } + + void assign_binary( const binary_t& v ) + { + discard(); + unsafe_assign_binary( v ); + } + + void assign_binary( binary_t&& v ) noexcept + { + unsafe_discard(); + unsafe_assign_binary( std::move( v ) ); + } + + void assign_binary_view( const tao::byte_view xv ) noexcept + { + unsafe_discard(); + unsafe_assign_binary_view( xv ); + } + + template< typename... Ts > + void emplace_array( Ts&&... ts ) noexcept( noexcept( unsafe_emplace_array( std::forward< Ts >( ts )... ) ) ) + { + discard(); + unsafe_emplace_array( std::forward< Ts >( ts )... ); + } + + void assign_array( const array_t& v ) + { + discard(); + unsafe_assign_array( v ); + } + + void assign_array( array_t&& v ) noexcept + { + unsafe_discard(); + unsafe_assign_array( std::move( v ) ); + } + + void prepare_array() + { + switch( m_type ) { + case json::type::UNINITIALIZED: + case json::type::DISCARDED: + unsafe_emplace_array(); + case json::type::ARRAY: + break; + default: + TAOCPP_JSON_THROW_TYPE_ERROR( m_type ); + } + } + + void push_back( const basic_value& v ) + { + prepare_array(); + unsafe_push_back( v ); + } + + void push_back( basic_value&& v ) + { + prepare_array(); + unsafe_push_back( std::move( v ) ); + } + + template< typename... Args > + void emplace_back( Args&&... args ) + { + prepare_array(); + unsafe_emplace_back( std::forward< Args... >( args )... ); + } + + void append( std::initializer_list< single< Traits > >&& l ) + { + prepare_array(); + auto& v = unsafe_get_array(); + v.reserve( v.size() + l.size() ); + for( auto& e : l ) { + unsafe_push_back( std::move( e.value ) ); + } + } + + void append( const std::initializer_list< single< Traits > >& l ) + { + prepare_array(); + auto& v = unsafe_get_array(); + v.reserve( v.size() + l.size() ); + for( const auto& e : l ) { + unsafe_push_back( e.value ); + } + } + + template< typename... Ts > + void emplace_object( Ts&&... ts ) noexcept( noexcept( unsafe_emplace_object( std::forward< Ts >( ts )... ) ) ) + { + discard(); + unsafe_emplace_object( std::forward< Ts >( ts )... ); + } + + void assign_object( const object_t& o ) + { + discard(); + unsafe_assign_object( o ); + } + + void assign_object( object_t&& o ) noexcept + { + unsafe_discard(); + unsafe_assign_object( std::move( o ) ); + } + + void prepare_object() + { + switch( m_type ) { + case json::type::UNINITIALIZED: + case json::type::DISCARDED: + unsafe_emplace_object(); + case json::type::OBJECT: + break; + default: + TAOCPP_JSON_THROW_TYPE_ERROR( m_type ); + } + } + + template< typename... Args > + std::pair< typename object_t::iterator, bool > emplace( Args&&... args ) + { + prepare_object(); + return unsafe_emplace( std::forward< Args >( args )... ); + } + + void insert( std::initializer_list< pair< Traits > >&& l ) + { + prepare_object(); + for( auto& e : l ) { + const auto r = unsafe_emplace( std::move( e.key ), std::move( e.value ) ); + if( !r.second ) { + throw std::runtime_error( "duplicate JSON object key: " + r.first->first ); + } + } + } + + void insert( const std::initializer_list< pair< Traits > >& l ) + { + prepare_object(); + for( const auto& e : l ) { + const auto r = unsafe_emplace( e.key, e.value ); + if( !r.second ) { + throw std::runtime_error( "duplicate JSON object key: " + r.first->first ); + } + } + } + + void assign_raw_ptr( const basic_value* p ) noexcept + { + unsafe_discard(); + unsafe_assign_raw_ptr( p ); + } + + const basic_value* skip_raw_ptr() const noexcept + { + const basic_value* p = this; + while( p && p->is_raw_ptr() ) { + p = p->unsafe_get_raw_ptr(); + } + return p; + } + + basic_value* unsafe_find( const std::string& key ) noexcept + { + const auto it = m_union.o.find( key ); + return ( it != m_union.o.end() ) ? ( &it->second ) : nullptr; + } + + template< typename T > + basic_value* unsafe_find( const T& key ) noexcept + { + const auto it = m_union.o.find( key ); + return ( it != m_union.o.end() ) ? ( &it->second ) : nullptr; + } + + const basic_value* unsafe_find( const std::string& key ) const noexcept + { + const auto it = m_union.o.find( key ); + return ( it != m_union.o.end() ) ? ( &it->second ) : nullptr; + } + + template< typename T > + const basic_value* unsafe_find( const T& key ) const noexcept + { + const auto it = m_union.o.find( key ); + return ( it != m_union.o.end() ) ? ( &it->second ) : nullptr; + } + + basic_value* find( const std::string& key ) + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::OBJECT ); + return unsafe_find( key ); + } + + template< typename T > + basic_value* find( const T& key ) + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::OBJECT ); + return unsafe_find( key ); + } + + const basic_value* find( const std::string& key ) const + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::OBJECT ); + return unsafe_find( key ); + } + + template< typename T > + const basic_value* find( const T& key ) const + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::OBJECT ); + return unsafe_find( key ); + } + + basic_value& unsafe_at( const std::size_t index ) noexcept + { + return m_union.a[ index ]; + } + + const basic_value& unsafe_at( const std::size_t index ) const noexcept + { + return m_union.a[ index ]; + } + + basic_value& unsafe_at( const std::string& key ) noexcept + { + return m_union.o.find( key )->second; + } + + const basic_value& unsafe_at( const std::string& key ) const noexcept + { + return m_union.o.find( key )->second; + } + + basic_value& at( const std::size_t index ) + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::ARRAY ); + return m_union.a.at( index ); + } + + const basic_value& at( const std::size_t index ) const + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::ARRAY ); + return m_union.a.at( index ); + } + + basic_value& at( const std::string& key ) + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::OBJECT ); + return m_union.o.at( key ); + } + + const basic_value& at( const std::string& key ) const + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::OBJECT ); + return m_union.o.at( key ); + } + + basic_value& at( const pointer& k ) + { + return internal::pointer_at( this, k.begin(), k.end() ); + } + + const basic_value& at( const pointer& k ) const + { + return internal::pointer_at( this, k.begin(), k.end() ); + } + + basic_value& operator[]( const std::size_t index ) noexcept + { + assert( m_type == json::type::ARRAY ); + return m_union.a[ index ]; + } + + const basic_value& operator[]( const std::size_t index ) const noexcept + { + assert( m_type == json::type::ARRAY ); + return m_union.a[ index ]; + } + + basic_value& operator[]( const std::string& key ) + { + prepare_object(); + return m_union.o[ key ]; + } + + basic_value& operator[]( std::string&& key ) + { + prepare_object(); + return m_union.o[ std::move( key ) ]; + } + + basic_value& operator[]( const pointer& k ) + { + if( !k ) { + return *this; + } + const auto b = k.begin(); + const auto e = std::prev( k.end() ); + basic_value& v = internal::pointer_at( this, b, e ); + switch( v.m_type ) { + case json::type::ARRAY: { + if( e->key() == "-" ) { + basic_value d; + d.unsafe_assign_null(); + v.unsafe_emplace_back( std::move( d ) ); + return v.m_union.a.back(); + } + return v.at( e->index() ); + } break; + case json::type::OBJECT: { + const auto& key = e->key(); + const auto it = v.m_union.o.find( key ); + if( it == v.m_union.o.end() ) { + basic_value d; + d.unsafe_assign_null(); + const auto r = v.unsafe_emplace( key, std::move( d ) ); + assert( r.second ); + return r.first->second; + } + return it->second; + } break; + default: + throw internal::invalid_type( b, std::next( e ) ); + } + } + + template< typename T > + void extract( T& v ) const + { + Traits< typename std::decay< T >::type >::extract( *this, v ); + } + + template< typename T > + typename std::enable_if< internal::has_as< Traits< T >, basic_value >::value, T >::type as() const + { + return Traits< T >::as( *this ); + } + + template< typename T > + typename std::enable_if< !internal::has_as< Traits< T >, basic_value >::value, T >::type as() const + { + T nrv; + this->extract( nrv ); + return nrv; + } + + template< typename T > + tao::optional< T > optional() const + { + if( is_null() ) { + return tao::nullopt; + } + else { + return as< T >(); + } + } + + template< typename T, typename K > + tao::optional< T > optional( const K& key ) const + { + if( const auto* p = find( key ) ) { + return tao::nullopt; + } + else { + return p->template as< T >(); + } + } + + template< typename T > + tao::optional< T > optional( const std::string& key ) const + { + return optional< T, std::string >( key ); + } + + void erase( const std::size_t index ) + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::ARRAY ); + auto& a = m_union.a; + if( index >= a.size() ) { + throw std::out_of_range( "JSON array index out of bounds" ); + } + a.erase( a.begin() + index ); + } + + void erase( const std::string& key ) + { + TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::OBJECT ); + if( m_union.o.erase( key ) == 0 ) { + throw std::out_of_range( "JSON object key not found: " + key ); + } + } + + void erase( const pointer& k ) + { + if( !k ) { + throw std::runtime_error( "invalid root JSON Pointer for erase" ); + } + const auto b = k.begin(); + const auto e = std::prev( k.end() ); + basic_value& v = internal::pointer_at( this, b, e ); + switch( v.m_type ) { + case json::type::ARRAY: + v.erase( e->index() ); + break; + case json::type::OBJECT: + v.erase( e->key() ); + break; + default: + throw internal::invalid_type( b, std::next( e ) ); + } + } + + basic_value& insert( const pointer& k, basic_value value ) + { + if( !k ) { + *this = std::move( value ); + return *this; + } + const auto b = k.begin(); + const auto e = std::prev( k.end() ); + basic_value& v = internal::pointer_at( this, b, e ); + switch( v.m_type ) { + case json::type::ARRAY: { + if( e->key() == "-" ) { + v.unsafe_emplace_back( std::move( value ) ); + return v.m_union.a.back(); + } + const auto i = e->index(); + if( i >= v.m_union.a.size() ) { + throw std::out_of_range( "invalid JSON Pointer '" + internal::tokens_to_string( b, std::next( e ) ) + "' -- array index out of bounds" ); + } + v.m_union.a.insert( v.m_union.a.begin() + i, std::move( value ) ); + return v.m_union.a.at( i ); + } break; + case json::type::OBJECT: { + const auto& key = e->key(); + const auto it = v.m_union.o.find( key ); + if( it == v.m_union.o.end() ) { + const auto r = v.unsafe_emplace( key, std::move( value ) ); + assert( r.second ); + return r.first->second; + } + it->second = std::move( value ); + return it->second; + } break; + default: + throw internal::invalid_type( b, std::next( e ) ); + } + } + + bool empty() const noexcept + { + switch( m_type ) { + case json::type::UNINITIALIZED: + return true; + + // LCOV_EXCL_START + case json::type::DISCARDED: + assert( m_type != json::type::DISCARDED ); + return true; + + case json::type::DESTROYED: + assert( m_type != json::type::DESTROYED ); + return true; + // LCOV_EXCL_STOP + + case json::type::NULL_: + case json::type::BOOLEAN: + case json::type::SIGNED: + case json::type::UNSIGNED: + case json::type::DOUBLE: + return false; + + case json::type::STRING: + return m_union.s.empty(); + + case json::type::STRING_VIEW: + return m_union.sv.empty(); + + case json::type::BINARY: + return m_union.x.empty(); + + case json::type::BINARY_VIEW: + return m_union.xv.empty(); + + case json::type::ARRAY: + return m_union.a.empty(); + + case json::type::OBJECT: + return m_union.o.empty(); + + case json::type::RAW_PTR: + return !m_union.p; + } + // LCOV_EXCL_START + assert( false ); + return false; + // LCOV_EXCL_STOP + } + + void unsafe_discard() noexcept + { + assert( m_type != json::type::DESTROYED ); + + switch( m_type ) { + case json::type::UNINITIALIZED: + case json::type::DISCARDED: + case json::type::DESTROYED: + case json::type::NULL_: + case json::type::BOOLEAN: + case json::type::SIGNED: + case json::type::UNSIGNED: + case json::type::DOUBLE: + case json::type::RAW_PTR: + return; + + case json::type::STRING: + m_union.s.~basic_string(); + return; + + case json::type::STRING_VIEW: + m_union.sv.~string_view(); + return; + + case json::type::BINARY: + m_union.x.~vector(); + return; + + case json::type::BINARY_VIEW: + m_union.xv.~byte_view(); + return; + + case json::type::ARRAY: + m_union.a.~vector(); + return; + + case json::type::OBJECT: + m_union.o.~map(); + return; + } + assert( false ); // LCOV_EXCL_LINE + } + + void discard() noexcept + { + unsafe_discard(); + m_type = json::type::DISCARDED; + } + + void reset() noexcept + { + unsafe_discard(); + m_type = json::type::UNINITIALIZED; + } + + private: + void seize( basic_value&& r ) noexcept + { + assert( m_type != json::type::DESTROYED ); + + switch( r.m_type ) { + case json::type::UNINITIALIZED: + assert( ( r.m_type = json::type::DISCARDED, true ) ); + return; + + // LCOV_EXCL_START + case json::type::DISCARDED: + assert( r.m_type != json::type::DISCARDED ); + return; + + case json::type::DESTROYED: + assert( r.m_type != json::type::DESTROYED ); + return; + // LCOV_EXCL_STOP + + case json::type::NULL_: + assert( ( r.m_type = json::type::DISCARDED, true ) ); + return; + + case json::type::BOOLEAN: + m_union.b = r.m_union.b; + assert( ( r.m_type = json::type::DISCARDED, true ) ); + return; + + case json::type::SIGNED: + m_union.i = r.m_union.i; + assert( ( r.m_type = json::type::DISCARDED, true ) ); + return; + + case json::type::UNSIGNED: + m_union.u = r.m_union.u; + assert( ( r.m_type = json::type::DISCARDED, true ) ); + return; + + case json::type::DOUBLE: + m_union.d = r.m_union.d; + assert( ( r.m_type = json::type::DISCARDED, true ) ); + return; + + case json::type::STRING: + new( &m_union.s ) std::string( std::move( r.m_union.s ) ); + assert( ( r.discard(), true ) ); + return; + + case json::type::STRING_VIEW: + new( &m_union.sv ) tao::string_view( r.m_union.sv ); + assert( ( r.m_type = json::type::DISCARDED, true ) ); + return; + + case json::type::BINARY: + new( &m_union.x ) binary_t( std::move( r.m_union.x ) ); + assert( ( r.discard(), true ) ); + return; + + case json::type::BINARY_VIEW: + new( &m_union.xv ) tao::byte_view( r.m_union.xv ); + assert( ( r.m_type = json::type::DISCARDED, true ) ); + return; + + case json::type::ARRAY: + new( &m_union.a ) array_t( std::move( r.m_union.a ) ); + assert( ( r.discard(), true ) ); + return; + + case json::type::OBJECT: + new( &m_union.o ) object_t( std::move( r.m_union.o ) ); + assert( ( r.discard(), true ) ); + return; + + case json::type::RAW_PTR: + m_union.p = r.m_union.p; + assert( ( r.m_type = json::type::DISCARDED, true ) ); + return; + } + assert( false ); // LCOV_EXCL_LINE + } + + void embed( const basic_value& r ) + { + assert( m_type != json::type::DESTROYED ); + + switch( r.m_type ) { + case json::type::UNINITIALIZED: + return; + + case json::type::DISCARDED: + throw std::logic_error( "attempt to use a discarded value" ); + + case json::type::DESTROYED: + throw std::logic_error( "attempt to use a destroyed value" ); + + case json::type::NULL_: + return; + + case json::type::BOOLEAN: + m_union.b = r.m_union.b; + return; + + case json::type::SIGNED: + m_union.i = r.m_union.i; + return; + + case json::type::UNSIGNED: + m_union.u = r.m_union.u; + return; + + case json::type::DOUBLE: + m_union.d = r.m_union.d; + return; + + case json::type::STRING: + new( &m_union.s ) std::string( r.m_union.s ); + return; + + case json::type::STRING_VIEW: + new( &m_union.sv ) tao::string_view( r.m_union.sv ); + return; + + case json::type::BINARY: + new( &m_union.x ) binary_t( r.m_union.x ); + return; + + case json::type::BINARY_VIEW: + new( &m_union.xv ) tao::byte_view( r.m_union.xv ); + return; + + case json::type::ARRAY: + new( &m_union.a ) array_t( r.m_union.a ); + return; + + case json::type::OBJECT: + new( &m_union.o ) object_t( r.m_union.o ); + return; + + case json::type::RAW_PTR: + m_union.p = r.m_union.p; + return; + } + assert( false ); // LCOV_EXCL_LINE + } + + protected: + json::type m_type = json::type::UNINITIALIZED; + internal::value_union< basic_value > m_union; + }; + + template< template< typename... > class TraitsL, template< typename... > class TraitsR > + bool operator==( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept + { + if( rhs.is_raw_ptr() ) { + if( const auto* p = rhs.skip_raw_ptr() ) { + return lhs == *p; + } + else { + if( const auto* q = lhs.skip_raw_ptr() ) { + return q->is_null(); + } + else { + return true; + } + } + } + + if( lhs.type() != rhs.type() ) { + switch( lhs.type() ) { + case type::RAW_PTR: + if( const auto* p = lhs.skip_raw_ptr() ) { + return *p == rhs; + } + return rhs.is_null(); + + case type::SIGNED: + if( rhs.type() == type::UNSIGNED ) { + const auto v = lhs.unsafe_get_signed(); + return ( v >= 0 ) && ( static_cast< std::uint64_t >( v ) == rhs.unsafe_get_unsigned() ); + } + if( rhs.type() == type::DOUBLE ) { + return lhs.unsafe_get_signed() == rhs.unsafe_get_double(); + } + break; + + case type::UNSIGNED: + if( rhs.type() == type::SIGNED ) { + const auto v = rhs.unsafe_get_signed(); + return ( v >= 0 ) && ( lhs.unsafe_get_unsigned() == static_cast< std::uint64_t >( v ) ); + } + if( rhs.type() == type::DOUBLE ) { + return lhs.unsafe_get_unsigned() == rhs.unsafe_get_double(); + } + break; + + case type::DOUBLE: + if( rhs.type() == type::SIGNED ) { + return lhs.unsafe_get_double() == rhs.unsafe_get_signed(); + } + if( rhs.type() == type::UNSIGNED ) { + return lhs.unsafe_get_double() == rhs.unsafe_get_unsigned(); + } + break; + + case type::STRING: + if( rhs.type() == type::STRING_VIEW ) { + return lhs.unsafe_get_string() == rhs.unsafe_get_string_view(); + } + break; + + case type::STRING_VIEW: + if( rhs.type() == type::STRING ) { + return lhs.unsafe_get_string_view() == rhs.unsafe_get_string(); + } + break; + + case type::BINARY: + if( rhs.type() == type::BINARY_VIEW ) { + return lhs.unsafe_get_binary() == rhs.unsafe_get_binary_view(); + } + break; + + case type::BINARY_VIEW: + if( rhs.type() == type::BINARY ) { + return lhs.unsafe_get_binary_view() == rhs.unsafe_get_binary(); + } + break; + + case type::DISCARDED: + case type::DESTROYED: + assert( false ); + break; + + default: + break; + } + assert( rhs.type() != type::DISCARDED ); + assert( rhs.type() != type::DESTROYED ); + return false; + } + + switch( lhs.type() ) { + case type::UNINITIALIZED: + return true; + + // LCOV_EXCL_START + case type::DISCARDED: + assert( lhs.type() != type::DISCARDED ); + break; + + case type::DESTROYED: + assert( lhs.type() != type::DESTROYED ); + break; + // LCOV_EXCL_STOP + + case type::NULL_: + return true; + + case type::BOOLEAN: + return lhs.unsafe_get_boolean() == rhs.unsafe_get_boolean(); + + case type::SIGNED: + return lhs.unsafe_get_signed() == rhs.unsafe_get_signed(); + + case type::UNSIGNED: + return lhs.unsafe_get_unsigned() == rhs.unsafe_get_unsigned(); + + case type::DOUBLE: + return lhs.unsafe_get_double() == rhs.unsafe_get_double(); + + case type::STRING: + return lhs.unsafe_get_string() == rhs.unsafe_get_string(); + + case type::STRING_VIEW: + return lhs.unsafe_get_string_view() == rhs.unsafe_get_string_view(); + + case type::BINARY: + return lhs.unsafe_get_binary() == rhs.unsafe_get_binary(); + + case type::BINARY_VIEW: + return lhs.unsafe_get_binary_view() == rhs.unsafe_get_binary_view(); + + case type::ARRAY: + return lhs.unsafe_get_array() == rhs.unsafe_get_array(); + + case type::OBJECT: + return lhs.unsafe_get_object() == rhs.unsafe_get_object(); + + case type::RAW_PTR: + assert( false ); + break; // LCOV_EXCL_LINE + } + // LCOV_EXCL_START + assert( false ); + return false; + // LCOV_EXCL_STOP + } + + template< template< typename... > class Traits > + bool operator==( const basic_value< Traits >& lhs, tao::internal::identity< basic_value< Traits > > rhs ) noexcept + { + return lhs == rhs; + } + + template< template< typename... > class Traits > + bool operator==( tao::internal::identity< basic_value< Traits > > lhs, const basic_value< Traits >& rhs ) noexcept + { + return lhs == rhs; + } + + template< template< typename... > class Traits, typename T, typename = decltype( Traits< typename std::decay< T >::type >::equal( std::declval< const basic_value< Traits >& >(), std::declval< const T& >() ) ) > + bool operator==( const basic_value< Traits >& lhs, const T& rhs ) noexcept + { + using D = typename std::decay< T >::type; + static_assert( noexcept( Traits< D >::equal( lhs, rhs ) ), "equal must be noexcept" ); + return Traits< D >::equal( lhs, rhs ); + } + + template< typename T, template< typename... > class Traits, typename = decltype( Traits< typename std::decay< T >::type >::equal( std::declval< const basic_value< Traits >& >(), std::declval< const T& >() ) ) > + bool operator==( const T& lhs, const basic_value< Traits >& rhs ) noexcept + { + using D = typename std::decay< T >::type; + static_assert( noexcept( Traits< D >::equal( rhs, lhs ) ), "equal must be noexcept" ); + return Traits< D >::equal( rhs, lhs ); + } + + template< template< typename... > class TraitsL, template< typename... > class TraitsR > + bool operator!=( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept + { + return !( lhs == rhs ); + } + + template< template< typename... > class Traits, typename T > + bool operator!=( const basic_value< Traits >& lhs, const T& rhs ) noexcept + { + return !( lhs == rhs ); + } + + template< typename T, template< typename... > class Traits > + bool operator!=( const T& lhs, const basic_value< Traits >& rhs ) noexcept + { + return !( lhs == rhs ); + } + + template< template< typename... > class TraitsL, template< typename... > class TraitsR > + bool operator<( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept + { + if( rhs.is_raw_ptr() ) { + if( const auto* p = rhs.skip_raw_ptr() ) { + return lhs < *p; + } + else { + if( const auto* q = lhs.skip_raw_ptr() ) { + return q->type() < type::NULL_; + } + else { + return false; + } + } + } + + if( lhs.type() != rhs.type() ) { + switch( lhs.type() ) { + case type::RAW_PTR: + if( const auto* p = lhs.skip_raw_ptr() ) { + return *p < rhs; + } + return type::NULL_ < rhs.type(); + + case type::SIGNED: + if( rhs.type() == type::UNSIGNED ) { + const auto v = lhs.unsafe_get_signed(); + return ( v < 0 ) || ( static_cast< std::uint64_t >( v ) < rhs.unsafe_get_unsigned() ); + } + if( rhs.type() == type::DOUBLE ) { + return lhs.unsafe_get_signed() < rhs.unsafe_get_double(); + } + break; + + case type::UNSIGNED: + if( rhs.type() == type::SIGNED ) { + const auto v = rhs.unsafe_get_signed(); + return ( v >= 0 ) && ( lhs.unsafe_get_unsigned() < static_cast< std::uint64_t >( v ) ); + } + if( rhs.type() == type::DOUBLE ) { + return lhs.unsafe_get_unsigned() < rhs.unsafe_get_double(); + } + break; + + case type::DOUBLE: + if( rhs.type() == type::SIGNED ) { + return lhs.unsafe_get_double() < rhs.unsafe_get_signed(); + } + if( rhs.type() == type::UNSIGNED ) { + return lhs.unsafe_get_double() < rhs.unsafe_get_unsigned(); + } + break; + + case type::STRING: + if( rhs.type() == type::STRING_VIEW ) { + return lhs.unsafe_get_string() < rhs.unsafe_get_string_view(); + } + break; + + case type::STRING_VIEW: + if( rhs.type() == type::STRING ) { + return lhs.unsafe_get_string_view() < rhs.unsafe_get_string(); + } + break; + + case type::BINARY: + if( rhs.type() == type::BINARY_VIEW ) { + return lhs.unsafe_get_binary() < rhs.unsafe_get_binary_view(); + } + break; + + case type::BINARY_VIEW: + if( rhs.type() == type::BINARY ) { + return lhs.unsafe_get_binary_view() < rhs.unsafe_get_binary(); + } + break; + + case type::DISCARDED: + case type::DESTROYED: + assert( false ); + break; + + default: + break; + } + assert( rhs.type() != type::DISCARDED ); + assert( rhs.type() != type::DESTROYED ); + return lhs.type() < rhs.type(); + } + + switch( lhs.type() ) { + case type::UNINITIALIZED: + return false; + + // LCOV_EXCL_START + case type::DISCARDED: + assert( lhs.type() != type::DISCARDED ); + break; + + case type::DESTROYED: + assert( lhs.type() != type::DESTROYED ); + break; + // LCOV_EXCL_STOP + + case type::NULL_: + return false; + + case type::BOOLEAN: + return lhs.unsafe_get_boolean() < rhs.unsafe_get_boolean(); + + case type::SIGNED: + return lhs.unsafe_get_signed() < rhs.unsafe_get_signed(); + + case type::UNSIGNED: + return lhs.unsafe_get_unsigned() < rhs.unsafe_get_unsigned(); + + case type::DOUBLE: + return lhs.unsafe_get_double() < rhs.unsafe_get_double(); + + case type::STRING: + return lhs.unsafe_get_string() < rhs.unsafe_get_string(); + + case type::STRING_VIEW: + return lhs.unsafe_get_string_view() < rhs.unsafe_get_string_view(); + + case type::BINARY: + return lhs.unsafe_get_binary() < rhs.unsafe_get_binary(); + + case type::BINARY_VIEW: + return lhs.unsafe_get_binary_view() < rhs.unsafe_get_binary_view(); + + case type::ARRAY: + return lhs.unsafe_get_array() < rhs.unsafe_get_array(); + + case type::OBJECT: + return lhs.unsafe_get_object() < rhs.unsafe_get_object(); + + case type::RAW_PTR: + break; // LCOV_EXCL_LINE + } + // LCOV_EXCL_START + assert( false ); + return false; + // LCOV_EXCL_STOP + } + + template< template< typename... > class Traits > + bool operator<( const basic_value< Traits >& lhs, tao::internal::identity< basic_value< Traits > > rhs ) noexcept + { + return lhs < rhs; + } + + template< template< typename... > class Traits > + bool operator<( const tao::internal::identity< basic_value< Traits > > lhs, const basic_value< Traits >& rhs ) noexcept + { + return lhs < rhs; + } + + template< template< typename... > class Traits, typename T, typename = decltype( Traits< typename std::decay< T >::type >::less_than( std::declval< const basic_value< Traits >& >(), std::declval< const T& >() ) ) > + bool operator<( const basic_value< Traits >& lhs, const T& rhs ) noexcept + { + using D = typename std::decay< T >::type; + static_assert( noexcept( Traits< D >::less_than( lhs, rhs ) ), "less_than must be noexcept" ); + return Traits< D >::less_than( lhs, rhs ); + } + + template< typename T, template< typename... > class Traits, typename = decltype( Traits< typename std::decay< T >::type >::greater_than( std::declval< const basic_value< Traits >& >(), std::declval< const T& >() ) ) > + bool operator<( const T& lhs, const basic_value< Traits >& rhs ) noexcept + { + using D = typename std::decay< T >::type; + static_assert( noexcept( Traits< D >::greater_than( rhs, lhs ) ), "less_than must be noexcept" ); + return Traits< D >::greater_than( rhs, lhs ); + } + + template< template< typename... > class TraitsL, template< typename... > class TraitsR > + bool operator>( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept + { + return rhs < lhs; + } + + template< template< typename... > class Traits > + bool operator>( const basic_value< Traits >& lhs, tao::internal::identity< basic_value< Traits > > rhs ) noexcept + { + return rhs < lhs; + } + + template< template< typename... > class Traits > + bool operator>( tao::internal::identity< basic_value< Traits > > lhs, const basic_value< Traits >& rhs ) noexcept + { + return rhs < lhs; + } + + template< template< typename... > class Traits, typename T, typename = decltype( Traits< typename std::decay< T >::type >::greater_than( std::declval< const basic_value< Traits >& >(), std::declval< const T& >() ) ) > + bool operator>( const basic_value< Traits >& lhs, const T& rhs ) noexcept + { + using D = typename std::decay< T >::type; + static_assert( noexcept( Traits< D >::greater_than( lhs, rhs ) ), "less_than must be noexcept" ); + return Traits< D >::greater_than( lhs, rhs ); + } + + template< typename T, template< typename... > class Traits, typename = decltype( Traits< typename std::decay< T >::type >::less_than( std::declval< const basic_value< Traits >& >(), std::declval< const T& >() ) ) > + bool operator>( const T& lhs, const basic_value< Traits >& rhs ) noexcept + { + using D = typename std::decay< T >::type; + static_assert( noexcept( Traits< D >::less_than( rhs, lhs ) ), "less_than must be noexcept" ); + return Traits< D >::less_than( rhs, lhs ); + } + + template< template< typename... > class TraitsL, template< typename... > class TraitsR > + bool operator<=( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept + { + return !( lhs > rhs ); + } + + template< template< typename... > class Traits, typename T > + bool operator<=( const basic_value< Traits >& lhs, const T& rhs ) noexcept + { + return !( lhs > rhs ); + } + + template< typename T, template< typename... > class Traits > + bool operator<=( const T& lhs, const basic_value< Traits >& rhs ) noexcept + { + return !( lhs > rhs ); + } + + template< template< typename... > class TraitsL, template< typename... > class TraitsR > + bool operator>=( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept + { + return !( lhs < rhs ); + } + + template< template< typename... > class Traits, typename T > + bool operator>=( const basic_value< Traits >& lhs, const T& rhs ) noexcept + { + return !( lhs < rhs ); + } + + template< typename T, template< typename... > class Traits > + bool operator>=( const T& lhs, const basic_value< Traits >& rhs ) noexcept + { + return !( lhs < rhs ); + } + + template< template< typename... > class Traits > + basic_value< Traits >& operator+=( basic_value< Traits >& v, std::initializer_list< pair< Traits > >&& l ) + { + v.insert( std::move( l ) ); + return v; + } + + template< template< typename... > class Traits > + basic_value< Traits >& operator+=( basic_value< Traits >& v, const std::initializer_list< pair< Traits > >& l ) + { + v.insert( l ); + return v; + } + + template< template< typename... > class Traits > + basic_value< Traits >& operator-=( basic_value< Traits >& v, std::initializer_list< std::string > l ) + { + auto& o = v.get_object(); + for( const auto& k : l ) { + if( o.erase( k ) == 0 ) { + throw std::runtime_error( "JSON object key not found: " + k ); + } + } + return v; + } + + using value = basic_value< traits >; + + } // namespace json + +} // namespace tao + +#endif diff --git a/include/velocypack/Json.h b/include/velocypack/Json.h new file mode 100644 index 00000000..0811a586 --- /dev/null +++ b/include/velocypack/Json.h @@ -0,0 +1,263 @@ +// Author: Dr. Colin Hirsch + +#ifndef ARANGODB_VELOCYPACK_JSON_H +#define ARANGODB_VELOCYPACK_JSON_H + +#include +#include + +#include "tao/json.hpp" + +#include "velocypack/Builder.h" +#include "velocypack/Iterator.h" +#include "velocypack/Options.h" +#include "velocypack/Slice.h" +#include "velocypack/Value.h" +#include "velocypack/ValueType.h" + +namespace arangodb +{ + namespace velocypack + { + // Class that consumes taocpp/json Events, i.e. + // implements the standard taocpp/json Events + // API, and feeds them into a Builder. + + class EventsToBuilder + { + private: + std::string m_key; + bool m_member = false; + + void add( const Value& v ) + { + if ( m_member ) { + builder->add( m_key, v ); + m_member = false; + } + else { + builder->add( v ); + } + } + + void add( const ValuePair& v ) + { + if ( m_member ) { + builder->add( m_key, v ); + m_member = false; + } + else { + builder->add( v ); + } + } + + public: + std::shared_ptr< Builder > builder; + + EventsToBuilder() + : builder( std::make_shared< Builder >() ) + { + } + + EventsToBuilder( std::shared_ptr< Builder > && builder ) + : builder( std::move( builder ) ) + { + } + + EventsToBuilder( const std::shared_ptr< Builder > & builder ) + : builder( builder ) + { + } + + void null() + { + add( Value( ValueType::Null ) ); + } + + void boolean( const bool v ) + { + add( Value( v ) ); + } + + void number( const std::int64_t v ) + { + add( Value( v ) ); + } + + void number( const std::uint64_t v ) + { + add( Value( v ) ); + } + + void number( const double v ) + { + add( Value( v ) ); + } + + void string( const tao::string_view v ) + { + add( ValuePair( reinterpret_cast< const uint8_t* >( v.data() ), v.size(), ValueType::String ) ); + } + + void binary( const tao::byte_view v ) + { + add( ValuePair( reinterpret_cast< const uint8_t* >( v.data() ), v.size(), ValueType::Binary ) ); + } + + void begin_array( const std::size_t = 0 ) + { + add( Value( ValueType::Array ) ); + } + + void element() + { + } + + void end_array( const std::size_t = 0 ) + { + builder->close(); + } + + void begin_object( const std::size_t = 0 ) + { + add( Value( ValueType::Object ) ); + } + + void key( const std::string& v ) + { + m_key = v; + m_member = true; + } + + void key( std::string&& v ) + { + m_key = std::move( v ); + m_member = true; + } + + void member() + { + } + + void end_object( const std::size_t = 0 ) + { + builder->close(); + } + }; + + // Function that produces taocpp/json Events from + // a given Slice (or Builder); the consumer must + // implement the taocpp/json Events API methods. + + template< typename Consumer > + void sliceToEvents( Consumer& consumer, const Slice& slice ) + { + switch( slice.type() ) { + case ValueType::None: + case ValueType::Illegal: + // TOOD: Decide what to do; for now fall through. + case ValueType::Null: + consumer.null(); + break; + case ValueType::Bool: + consumer.boolean( slice.getBool() ); + break; + case ValueType::Array: { + const auto size = slice.length(); + consumer.begin_array( size ); + for ( const auto& s : ArrayIterator( slice ) ) { + sliceToEvents( consumer, s ); + consumer.element(); + } + consumer.end_array( size ); + } break; + case ValueType::Object: { + const auto size = slice.length(); + consumer.begin_object( size ); + for ( const auto& s : ObjectIterator( slice ) ) { + ValueLength size; + const char * data = s.key.getString( size ); + consumer.key( tao::string_view( data, size ) ); + sliceToEvents( consumer, s.value ); + consumer.member(); + } + consumer.end_object( size ); + } break; + case ValueType::Double: + consumer.number( slice.getDouble() ); + break; + case ValueType::UTCDate: + // TODO: Implement when taocpp/json datetime support is finished. + break; + case ValueType::External: + // TODO: What? + break; + case ValueType::MinKey: + case ValueType::MaxKey: + // TODO: What? + break; + case ValueType::Int: + consumer.number( slice.getInt() ); + break; + case ValueType::UInt: + consumer.number( slice.getUInt() ); + break; + case ValueType::SmallInt: + consumer.number( slice.getSmallInt() ); + break; + case ValueType::String: { + ValueLength size; + const char * data = slice.getString( size ); + consumer.string( tao::string_view( data, size ) ); + } break; + case ValueType::Binary: { + ValueLength size; + const auto * data = slice.getBinary( size ); + consumer.binary( tao::byte_view( reinterpret_cast< const tao::byte* >( data ), size ) ); + } break; + case ValueType::BCD: + // TODO: Convert to other number format or string? + break; + case ValueType::Custom: + // TODO: What? + break; + } + } + + template< typename Consumer > + void builderToEvents( Consumer& consumer, const Builder& builder ) + { + sliceToEvents( consumer, Slice( builder.start() ) ); + } + + inline void builderToJsonStream( std::ostream& stream, const Builder& builder ) + { + tao::json::events::to_stream events( stream ); + builderToEvents( events, builder ); + } + + inline void builderToPrettyJsonStream( std::ostream& stream, const Builder& builder, const std::size_t indent = 3 ) + { + tao::json::events::to_pretty_stream events( stream, indent ); + builderToEvents( events, builder ); + } + + inline std::string builderToJsonString( const Builder& builder ) + { + std::ostringstream stream; + builderToJsonStream( stream, builder ); + return stream.str(); + } + + inline std::string builderToPrettyJsonString( const Builder& builder, const std::size_t indent = 3 ) + { + std::ostringstream stream; + builderToPrettyJsonStream( stream, builder, indent ); + return stream.str(); + } + + } // velocypack + +} // namespace arangodb + +#endif diff --git a/include/velocypack/Parser.h b/include/velocypack/Parser.h index 65335cff..679e65a1 100644 --- a/include/velocypack/Parser.h +++ b/include/velocypack/Parser.h @@ -29,61 +29,22 @@ #include #include +#include +#include #include "velocypack/velocypack-common.h" -#include "velocypack/Builder.h" +#include "velocypack/Json.h" #include "velocypack/Exception.h" -#include "velocypack/Options.h" -#include "velocypack/Value.h" -#include "velocypack/ValueType.h" namespace arangodb { namespace velocypack { -class Parser { - // This class can parse JSON very rapidly, but only from contiguous - // blocks of memory. It builds the result using the Builder. - - struct ParsedNumber { - ParsedNumber() : intValue(0), doubleValue(0.0), isInteger(true) {} - - void addDigit(int i) { - if (isInteger) { - // check if adding another digit to the int will make it overflow - if (intValue < 1844674407370955161ULL || - (intValue == 1844674407370955161ULL && (i - '0') <= 5)) { - // int won't overflow - intValue = intValue * 10 + (i - '0'); - return; - } - // int would overflow - doubleValue = static_cast(intValue); - isInteger = false; - } - - doubleValue = doubleValue * 10.0 + (i - '0'); - if (std::isnan(doubleValue) || !std::isfinite(doubleValue)) { - throw Exception(Exception::NumberOutOfRange); - } - } - - double asDouble() const { - if (isInteger) { - return static_cast(intValue); - } - return doubleValue; - } + // Parser class with the same interface as before + // the integration of taocpp/json. - uint64_t intValue; - double doubleValue; - bool isInteger; - }; +class Parser { - std::shared_ptr _b; - uint8_t const* _start; - size_t _size; - size_t _pos; - int _nesting; + EventsToBuilder _e; public: Options const* options; @@ -95,18 +56,17 @@ class Parser { ~Parser() = default; explicit Parser(Options const* options = &Options::Defaults) - : _start(nullptr), _size(0), _pos(0), _nesting(0), options(options) { + : options(options) { if (options == nullptr) { throw Exception(Exception::InternalError, "Options cannot be a nullptr"); } - _b.reset(new Builder()); - _b->options = options; + _e.builder->options = options; } explicit Parser(std::shared_ptr& builder, Options const* options = &Options::Defaults) - : _b(builder), _start(nullptr), _size(0), _pos(0), _nesting(0), - options(options) { + : _e(builder), + options(options) { if (options == nullptr) { throw Exception(Exception::InternalError, "Options cannot be a nullptr"); } @@ -115,15 +75,14 @@ class Parser { // This method produces a parser that does not own the builder explicit Parser(Builder& builder, Options const* options = &Options::Defaults) - : _start(nullptr), _size(0), _pos(0), _nesting(0), - options(options) { + : _e( std::shared_ptr< Builder >( &builder, BuilderNonDeleter() ) ), + options(options) { if (options == nullptr) { throw Exception(Exception::InternalError, "Options cannot be a nullptr"); } - _b.reset(&builder, BuilderNonDeleter()); } - Builder const& builder() const { return *_b; } + Builder const& builder() const { return *_e.builder; } static std::shared_ptr fromJson( std::string const& json, @@ -132,7 +91,7 @@ class Parser { parser.parse(json); return parser.steal(); } - + static std::shared_ptr fromJson( char const* start, size_t size, Options const* options = &Options::Defaults) { @@ -150,150 +109,25 @@ class Parser { } ValueLength parse(std::string const& json, bool multi = false) { - return parse(reinterpret_cast(json.c_str()), json.size(), - multi); - } - - ValueLength parse(char const* start, size_t size, bool multi = false) { - return parse(reinterpret_cast(start), size, multi); - } - - ValueLength parse(uint8_t const* start, size_t size, bool multi = false) { - _start = start; - _size = size; - _pos = 0; - if (options->clearBuilderBeforeParse) { - _b->clear(); - } - return parseInternal(multi); + return parse(json.data(), json.size(),multi); } - // We probably want a parse from stream at some stage... - // Not with this high-performance two-pass approach. :-( + ValueLength parse(void const* json, const ValueLength size, const bool multi = false ); std::shared_ptr steal() { // Parser object is broken after a steal() - std::shared_ptr res(_b); - _b.reset(); - return res; + return std::move( _e.builder ); } // Beware, only valid as long as you do not parse more, use steal // to move the data out! - uint8_t const* start() { return _b->start(); } + uint8_t const* start() { return _e.builder->start(); } // Returns the position at the time when the just reported error // occurred, only use when handling an exception. - size_t errorPos() const { return _pos > 0 ? _pos - 1 : _pos; } - - void clear() { _b->clear(); } - - private: - inline int peek() const { - if (_pos >= _size) { - return -1; - } - return static_cast(_start[_pos]); - } - - inline int consume() { - if (_pos >= _size) { - return -1; - } - return static_cast(_start[_pos++]); - } - - inline void unconsume() { --_pos; } - - inline void reset() { _pos = 0; } - - ValueLength parseInternal(bool multi); - - inline bool isWhiteSpace(uint8_t i) const noexcept { - return (i == ' ' || i == '\t' || i == '\n' || i == '\r'); - } - - // skips over all following whitespace tokens but does not consume the - // byte following the whitespace - int skipWhiteSpace(char const*); - - void parseTrue() { - // Called, when main mode has just seen a 't', need to see "rue" next - if (consume() != 'r' || consume() != 'u' || consume() != 'e') { - throw Exception(Exception::ParseError, "Expecting 'true'"); - } - _b->addTrue(); - } - - void parseFalse() { - // Called, when main mode has just seen a 'f', need to see "alse" next - if (consume() != 'a' || consume() != 'l' || consume() != 's' || - consume() != 'e') { - throw Exception(Exception::ParseError, "Expecting 'false'"); - } - _b->addFalse(); - } - - void parseNull() { - // Called, when main mode has just seen a 'n', need to see "ull" next - if (consume() != 'u' || consume() != 'l' || consume() != 'l') { - throw Exception(Exception::ParseError, "Expecting 'null'"); - } - _b->addNull(); - } - - void scanDigits(ParsedNumber& value) { - while (true) { - int i = consume(); - if (i < 0) { - return; - } - if (i < '0' || i > '9') { - unconsume(); - return; - } - value.addDigit(i); - } - } - - double scanDigitsFractional() { - double pot = 0.1; - double x = 0.0; - while (true) { - int i = consume(); - if (i < 0) { - return x; - } - if (i < '0' || i > '9') { - unconsume(); - return x; - } - x = x + pot * (i - '0'); - pot /= 10.0; - } - } - - inline int getOneOrThrow(char const* msg) { - int i = consume(); - if (i < 0) { - throw Exception(Exception::ParseError, msg); - } - return i; - } - - inline void increaseNesting() { ++_nesting; } - - inline void decreaseNesting() { --_nesting; } - - void parseNumber(); - - void parseString(); - - void parseArray(); - - void parseObject(); + size_t errorPos() const { return 0; } // TODO! - void parseJson(); + void clear() { _e.builder->clear(); } }; } // namespace arangodb::velocypack diff --git a/src/Parser.cpp b/src/Parser.cpp index 5d9fd765..1aaf914d 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -26,590 +26,32 @@ #include "velocypack/velocypack-common.h" #include "velocypack/Parser.h" -#include "asm-functions.h" #include -using namespace arangodb::velocypack; - -// The following function does the actual parse. It gets bytes -// via peek, consume and reset appends the result to the Builder -// in *_b. Errors are reported via an exception. -// Behind the scenes it runs two parses, one to collect sizes and -// check for parse errors (scan phase) and then one to actually -// build the result (build phase). - -ValueLength Parser::parseInternal(bool multi) { - // skip over optional BOM - if (_size >= 3 && _start[0] == 0xef && _start[1] == 0xbb && - _start[2] == 0xbf) { - // found UTF-8 BOM. simply skip over it - _pos += 3; - } - - ValueLength nr = 0; - do { - bool haveReported = false; - if (!_b->_stack.empty()) { - ValueLength const tos = _b->_stack.back(); - if (_b->_start[tos] == 0x0b || _b->_start[tos] == 0x14) { - if (! _b->_keyWritten) { - throw Exception(Exception::BuilderKeyMustBeString); - } - else { - _b->_keyWritten = false; - } - } - else { - _b->reportAdd(); - haveReported = true; - } - } - try { - parseJson(); - } - catch (...) { - if (haveReported) { - _b->cleanupAdd(); - } - throw; - } - nr++; - while (_pos < _size && isWhiteSpace(_start[_pos])) { - ++_pos; - } - if (!multi && _pos != _size) { - consume(); // to get error reporting right. return value intentionally not checked - throw Exception(Exception::ParseError, "Expecting EOF"); - } - } while (multi && _pos < _size); - return nr; -} - -// skips over all following whitespace tokens but does not consume the -// byte following the whitespace -int Parser::skipWhiteSpace(char const* err) { - if (_pos >= _size) { - throw Exception(Exception::ParseError, err); - } - uint8_t c = _start[_pos]; - if (!isWhiteSpace(c)) { - return c; - } - if (c == ' ') { - if (_pos + 1 >= _size) { - _pos++; - throw Exception(Exception::ParseError, err); - } - c = _start[_pos + 1]; - if (!isWhiteSpace(c)) { - _pos++; - return c; - } - } - size_t remaining = _size - _pos; - if (remaining >= 16) { - size_t count = JSONSkipWhiteSpace(_start + _pos, remaining - 15); - _pos += count; - } - do { - if (!isWhiteSpace(_start[_pos])) { - return static_cast(_start[_pos]); - } - _pos++; - } while (_pos < _size); - throw Exception(Exception::ParseError, err); -} - -// parses a number value -void Parser::parseNumber() { - size_t startPos = _pos; - ParsedNumber numberValue; - bool negative = false; - int i = consume(); - // We know that a character is coming, and it's a number if it - // starts with '-' or a digit. otherwise it's invalid - if (i == '-') { - i = getOneOrThrow("Incomplete number"); - negative = true; - } - if (i < '0' || i > '9') { - throw Exception(Exception::ParseError, "Expecting digit"); - } - - if (i != '0') { - unconsume(); - scanDigits(numberValue); - } - i = consume(); - if (i < 0 || (i != '.' && i != 'e' && i != 'E')) { - if (i >= 0) { - unconsume(); - } - if (!numberValue.isInteger) { - if (negative) { - _b->addDouble(-numberValue.doubleValue); - } else { - _b->addDouble(numberValue.doubleValue); - } - } else if (negative) { - if (numberValue.intValue <= static_cast(INT64_MAX)) { - _b->addInt(-static_cast(numberValue.intValue)); - } else if (numberValue.intValue == toUInt64(INT64_MIN)) { - _b->addInt(INT64_MIN); - } else { - _b->addDouble(-static_cast(numberValue.intValue)); - } - } else { - _b->addUInt(numberValue.intValue); - } - return; - } - - double fractionalPart; - if (i == '.') { - // fraction. skip over '.' - i = getOneOrThrow("Incomplete number"); - if (i < '0' || i > '9') { - throw Exception(Exception::ParseError, "Incomplete number"); - } - unconsume(); - fractionalPart = scanDigitsFractional(); - if (negative) { - fractionalPart = -numberValue.asDouble() - fractionalPart; - } else { - fractionalPart = numberValue.asDouble() + fractionalPart; - } - i = consume(); - if (i < 0) { - _b->addDouble(fractionalPart); - return; - } - } else { - if (negative) { - fractionalPart = -numberValue.asDouble(); - } else { - fractionalPart = numberValue.asDouble(); - } - } - if (i != 'e' && i != 'E') { - unconsume(); - // use conventional atof() conversion here, to avoid precision loss - // when interpreting and multiplying the single digits of the input stream - // _b->addDouble(fractionalPart); - _b->addDouble(atof(reinterpret_cast(_start) + startPos)); - return; - } - i = getOneOrThrow("Incomplete number"); - negative = false; - if (i == '+' || i == '-') { - negative = (i == '-'); - i = getOneOrThrow("Incomplete number"); - } - if (i < '0' || i > '9') { - throw Exception(Exception::ParseError, "Incomplete number"); - } - unconsume(); - ParsedNumber exponent; - scanDigits(exponent); - if (negative) { - fractionalPart *= pow(10, -exponent.asDouble()); - } else { - fractionalPart *= pow(10, exponent.asDouble()); - } - if (std::isnan(fractionalPart) || !std::isfinite(fractionalPart)) { - throw Exception(Exception::NumberOutOfRange); - } - // use conventional atof() conversion here, to avoid precision loss - // when interpreting and multiplying the single digits of the input stream - // _b->addDouble(fractionalPart); - _b->addDouble(atof(reinterpret_cast(_start) + startPos)); -} - -void Parser::parseString() { - // When we get here, we have seen a " character and now want to - // find the end of the string and parse the string value to its - // VPack representation. We assume that the string is short and - // insert 8 bytes for the length as soon as we reach 127 bytes - // in the VPack representation. - - // copy builder pointer into local variable - // this avoids accessing the shared pointer repeatedly, which has - // a small but non-negligible cost - Builder* builder = _b.get(); - VELOCYPACK_ASSERT(builder != nullptr); - - ValueLength const base = builder->_pos; - builder->reserveSpace(1); - builder->_start[builder->_pos++] = 0x40; // correct this later - - bool large = false; // set to true when we reach 128 bytes - uint32_t highSurrogate = 0; // non-zero if high-surrogate was seen - - while (true) { - size_t remainder = _size - _pos; - if (remainder >= 16) { - builder->reserveSpace(remainder); - size_t count; - // Note that the SSE4.2 accelerated string copying functions might - // peek up to 15 bytes over the given end, because they use 128bit - // registers. Therefore, we have to subtract 15 from remainder - // to be on the safe side. Further bytes will be processed below. - if (options->validateUtf8Strings) { - count = JSONStringCopyCheckUtf8(builder->_start + builder->_pos, _start + _pos, - remainder - 15); - } else { - count = JSONStringCopy(builder->_start + builder->_pos, _start + _pos, - remainder - 15); - } - _pos += count; - builder->_pos += count; - } - int i = getOneOrThrow("Unfinished string"); - if (!large && builder->_pos - (base + 1) > 126) { - large = true; - builder->reserveSpace(8); - ValueLength len = builder->_pos - (base + 1); - memmove(builder->_start + base + 9, builder->_start + base + 1, checkOverflow(len)); - builder->_pos += 8; - } - switch (i) { - case '"': - ValueLength len; - if (!large) { - len = builder->_pos - (base + 1); - builder->_start[base] = 0x40 + static_cast(len); - // String is ready - } else { - len = builder->_pos - (base + 9); - builder->_start[base] = 0xbf; - for (ValueLength i = 1; i <= 8; i++) { - builder->_start[base + i] = len & 0xff; - len >>= 8; - } - } - return; - case '\\': - // Handle cases or throw error - i = consume(); - if (i < 0) { - throw Exception(Exception::ParseError, "Invalid escape sequence"); - } - switch (i) { - case '"': - case '/': - case '\\': - builder->reserveSpace(1); - builder->_start[builder->_pos++] = static_cast(i); - highSurrogate = 0; - break; - case 'b': - builder->reserveSpace(1); - builder->_start[builder->_pos++] = '\b'; - highSurrogate = 0; - break; - case 'f': - builder->reserveSpace(1); - builder->_start[builder->_pos++] = '\f'; - highSurrogate = 0; - break; - case 'n': - builder->reserveSpace(1); - builder->_start[builder->_pos++] = '\n'; - highSurrogate = 0; - break; - case 'r': - builder->reserveSpace(1); - builder->_start[builder->_pos++] = '\r'; - highSurrogate = 0; - break; - case 't': - builder->reserveSpace(1); - builder->_start[builder->_pos++] = '\t'; - highSurrogate = 0; - break; - case 'u': { - uint32_t v = 0; - for (int j = 0; j < 4; j++) { - i = consume(); - if (i < 0) { - throw Exception(Exception::ParseError, - "Unfinished \\uXXXX escape sequence"); - } - if (i >= '0' && i <= '9') { - v = (v << 4) + i - '0'; - } else if (i >= 'a' && i <= 'f') { - v = (v << 4) + i - 'a' + 10; - } else if (i >= 'A' && i <= 'F') { - v = (v << 4) + i - 'A' + 10; - } else { - throw Exception(Exception::ParseError, - "Illegal \\uXXXX escape sequence"); - } - } - if (v < 0x80) { - builder->reserveSpace(1); - builder->_start[builder->_pos++] = static_cast(v); - highSurrogate = 0; - } else if (v < 0x800) { - builder->reserveSpace(2); - builder->_start[builder->_pos++] = 0xc0 + (v >> 6); - builder->_start[builder->_pos++] = 0x80 + (v & 0x3f); - highSurrogate = 0; - } else if (v >= 0xdc00 && v < 0xe000 && highSurrogate != 0) { - // Low surrogate, put the two together: - v = 0x10000 + ((highSurrogate - 0xd800) << 10) + v - 0xdc00; - builder->_pos -= 3; - builder->reserveSpace(4); - builder->_start[builder->_pos++] = 0xf0 + (v >> 18); - builder->_start[builder->_pos++] = 0x80 + ((v >> 12) & 0x3f); - builder->_start[builder->_pos++] = 0x80 + ((v >> 6) & 0x3f); - builder->_start[builder->_pos++] = 0x80 + (v & 0x3f); - highSurrogate = 0; - } else { - if (v >= 0xd800 && v < 0xdc00) { - // High surrogate: - highSurrogate = v; - } else { - highSurrogate = 0; - } - builder->reserveSpace(3); - builder->_start[builder->_pos++] = 0xe0 + (v >> 12); - builder->_start[builder->_pos++] = 0x80 + ((v >> 6) & 0x3f); - builder->_start[builder->_pos++] = 0x80 + (v & 0x3f); - } - break; - } - default: - throw Exception(Exception::ParseError, "Invalid escape sequence"); - } - break; - default: - if ((i & 0x80) == 0) { - // non-UTF-8 sequence - if (i < 0x20) { - // control character - throw Exception(Exception::UnexpectedControlCharacter); - } - highSurrogate = 0; - builder->reserveSpace(1); - builder->_start[builder->_pos++] = static_cast(i); - } else { - if (!options->validateUtf8Strings) { - highSurrogate = 0; - builder->reserveSpace(1); - builder->_start[builder->_pos++] = static_cast(i); - } else { - // multi-byte UTF-8 sequence! - int follow = 0; - if ((i & 0xe0) == 0x80) { - throw Exception(Exception::InvalidUtf8Sequence); - } else if ((i & 0xe0) == 0xc0) { - // two-byte sequence - follow = 1; - } else if ((i & 0xf0) == 0xe0) { - // three-byte sequence - follow = 2; - } else if ((i & 0xf8) == 0xf0) { - // four-byte sequence - follow = 3; - } else { - throw Exception(Exception::InvalidUtf8Sequence); - } - - // validate follow up characters - builder->reserveSpace(1 + follow); - builder->_start[builder->_pos++] = static_cast(i); - for (int j = 0; j < follow; ++j) { - i = getOneOrThrow("scanString: truncated UTF-8 sequence"); - if ((i & 0xc0) != 0x80) { - throw Exception(Exception::InvalidUtf8Sequence); - } - builder->_start[builder->_pos++] = static_cast(i); - } - highSurrogate = 0; - } - } - break; - } - } -} - -void Parser::parseArray() { - // copy builder pointer into local variable - // this avoids accessing the shared pointer repeatedly, which has - // a small but non-negligible cost - Builder* builder = _b.get(); - VELOCYPACK_ASSERT(builder != nullptr); - - builder->addArray(); - - int i = skipWhiteSpace("Expecting item or ']'"); - if (i == ']') { - // empty array - ++_pos; // the closing ']' - builder->close(); - return; - } - - increaseNesting(); - - while (true) { - // parse array element itself - builder->reportAdd(); - parseJson(); - i = skipWhiteSpace("Expecting ',' or ']'"); - if (i == ']') { - // end of array - ++_pos; // the closing ']' - builder->close(); - decreaseNesting(); - return; - } - // skip over ',' - if (i != ',') { - throw Exception(Exception::ParseError, "Expecting ',' or ']'"); - } - ++_pos; // the ',' - } - - // should never get here - VELOCYPACK_ASSERT(false); -} - -void Parser::parseObject() { - // copy builder pointer into local variable - // this avoids accessing the shared pointer repeatedly, which has - // a small but non-negligible cost - Builder* builder = _b.get(); - VELOCYPACK_ASSERT(builder != nullptr); - - builder->addObject(); - - int i = skipWhiteSpace("Expecting item or '}'"); - if (i == '}') { - // empty object - consume(); // the closing '}'. return value intentionally not checked - - if (_nesting != 0 || !options->keepTopLevelOpen) { - // only close if we've not been asked to keep top level open - builder->close(); - } - return; - } - - increaseNesting(); - - while (true) { - // always expecting a string attribute name here - if (i != '"') { - throw Exception(Exception::ParseError, "Expecting '\"' or '}'"); - } - // get past the initial '"' - ++_pos; - - builder->reportAdd(); - bool excludeAttribute = false; - auto const lastPos = builder->_pos; - if (options->attributeExcludeHandler == nullptr) { - parseString(); - } else { - parseString(); - if (options->attributeExcludeHandler->shouldExclude( - Slice(builder->_start + lastPos), _nesting)) { - excludeAttribute = true; - } - } - - if (!excludeAttribute && options->attributeTranslator != nullptr) { - // check if a translation for the attribute name exists - Slice key(builder->_start + lastPos); - - if (key.isString()) { - ValueLength keyLength; - char const* p = key.getString(keyLength); - uint8_t const* translated = - options->attributeTranslator->translate(p, keyLength); - - if (translated != nullptr) { - // found translation... now reset position to old key position - // and simply overwrite the existing key with the numeric translation - // id - builder->_pos = lastPos; - builder->addUInt(Slice(translated).getUInt()); - } - } - } - - i = skipWhiteSpace("Expecting ':'"); - // always expecting the ':' here - if (i != ':') { - throw Exception(Exception::ParseError, "Expecting ':'"); - } - ++_pos; // skip over the colon - - parseJson(); - - if (excludeAttribute) { - builder->removeLast(); - } - - i = skipWhiteSpace("Expecting ',' or '}'"); - if (i == '}') { - // end of object - ++_pos; // the closing '}' - if (_nesting != 1 || !options->keepTopLevelOpen) { - // only close if we've not been asked to keep top level open - builder->close(); - } - decreaseNesting(); - return; - } - if (i != ',') { - throw Exception(Exception::ParseError, "Expecting ',' or '}'"); - } - // skip over ',' - ++_pos; // the ',' - i = skipWhiteSpace("Expecting '\"' or '}'"); - } - - // should never get here - VELOCYPACK_ASSERT(false); -} - -void Parser::parseJson() { - skipWhiteSpace("Expecting item"); // return value intentionally not checked - - int i = consume(); - if (i < 0) { - return; - } - switch (i) { - case '{': - parseObject(); // this consumes the closing '}' or throws - break; - case '[': - parseArray(); // this consumes the closing ']' or throws - break; - case 't': - parseTrue(); // this consumes "rue" or throws - break; - case 'f': - parseFalse(); // this consumes "alse" or throws - break; - case 'n': - parseNull(); // this consumes "ull" or throws - break; - case '"': - parseString(); - break; - default: { - // everything else must be a number or is invalid... - // this includes '-' and '0' to '9'. scanNumber() will - // throw if the input is non-numeric - unconsume(); - parseNumber(); // this consumes the number or throws - break; - } - } -} +namespace arangodb +{ + namespace velocypack + { + ValueLength Parser::parse( const void * json, const ValueLength size, const bool multi) { + if (options->clearBuilderBeforeParse) { + _e.builder->clear(); + } + tao::json_pegtl::memory_input< tao::json_pegtl::tracking_mode::LAZY, tao::json_pegtl::eol::lf_crlf, const char* > in( reinterpret_cast< const char * >( json ), size, __PRETTY_FUNCTION__ ); + if ( multi ) { + ValueLength nr = 0; + do { + const auto * const t = in.current(); + tao::json_pegtl::parse< tao::json_pegtl::must< tao::json::internal::rules::text >, tao::json::internal::action, tao::json::internal::control >( in, _e ); + nr += in.current() - t; + } while ( !in.empty() ); + return nr; + } + const auto * const t = in.current(); + tao::json_pegtl::parse< tao::json::internal::grammar, tao::json::internal::action, tao::json::internal::control >( in, _e ); + return in.current() - t; + } + + } // velocypack + +} // arangodb From 8bfac4b47f80c23323cf37a12f5a5fbf5bb139d3 Mon Sep 17 00:00:00 2001 From: Jan Christoph Uhde Date: Fri, 14 Feb 2020 12:16:36 +0100 Subject: [PATCH 2/7] Move the TaoCpp Parser to a new file. --- include/velocypack/Parser.h | 247 ++++++++++++-- include/velocypack/TaoParser.h | 136 ++++++++ src/Parser.cpp | 570 +++++++++++++++++++++++++++++++-- src/TaoParser.cpp | 57 ++++ 4 files changed, 956 insertions(+), 54 deletions(-) create mode 100644 include/velocypack/TaoParser.h create mode 100644 src/TaoParser.cpp diff --git a/include/velocypack/Parser.h b/include/velocypack/Parser.h index 679e65a1..748f9e02 100644 --- a/include/velocypack/Parser.h +++ b/include/velocypack/Parser.h @@ -29,22 +29,60 @@ #include #include -#include -#include #include "velocypack/velocypack-common.h" -#include "velocypack/Json.h" +#include "velocypack/Builder.h" #include "velocypack/Exception.h" +#include "velocypack/Options.h" namespace arangodb { namespace velocypack { - // Parser class with the same interface as before - // the integration of taocpp/json. - class Parser { + // This class can parse JSON very rapidly, but only from contiguous + // blocks of memory. It builds the result using the Builder. + + struct ParsedNumber { + ParsedNumber() : intValue(0), doubleValue(0.0), isInteger(true) {} + + void addDigit(int i) { + if (isInteger) { + // check if adding another digit to the int will make it overflow + if (intValue < 1844674407370955161ULL || + (intValue == 1844674407370955161ULL && (i - '0') <= 5)) { + // int won't overflow + intValue = intValue * 10 + (i - '0'); + return; + } + // int would overflow + doubleValue = static_cast(intValue); + isInteger = false; + } + + doubleValue = doubleValue * 10.0 + (i - '0'); + if (std::isnan(doubleValue) || !std::isfinite(doubleValue)) { + throw Exception(Exception::NumberOutOfRange); + } + } + + double asDouble() const { + if (isInteger) { + return static_cast(intValue); + } + return doubleValue; + } - EventsToBuilder _e; + uint64_t intValue; + double doubleValue; + bool isInteger; + }; + + std::shared_ptr _builder; + Builder* _builderPtr; + uint8_t const* _start; + std::size_t _size; + std::size_t _pos; + int _nesting; public: Options const* options; @@ -54,20 +92,42 @@ class Parser { Parser& operator=(Parser const&) = delete; Parser& operator=(Parser&&) = delete; ~Parser() = default; + + Parser() + : _start(nullptr), + _size(0), + _pos(0), + _nesting(0), + options(&Options::Defaults) { + _builder.reset(new Builder()); + _builderPtr = _builder.get(); + _builderPtr->options = &Options::Defaults; + } - explicit Parser(Options const* options = &Options::Defaults) - : options(options) { - if (options == nullptr) { + explicit Parser(Options const* options) + : _start(nullptr), + _size(0), + _pos(0), + _nesting(0), + options(options) { + if (VELOCYPACK_UNLIKELY(options == nullptr)) { throw Exception(Exception::InternalError, "Options cannot be a nullptr"); } - _e.builder->options = options; + _builder.reset(new Builder()); + _builderPtr = _builder.get(); + _builderPtr->options = options; } - explicit Parser(std::shared_ptr& builder, + explicit Parser(std::shared_ptr const& builder, Options const* options = &Options::Defaults) - : _e(builder), - options(options) { - if (options == nullptr) { + : _builder(builder), + _builderPtr(_builder.get()), + _start(nullptr), + _size(0), + _pos(0), + _nesting(0), + options(options) { + if (VELOCYPACK_UNLIKELY(options == nullptr)) { throw Exception(Exception::InternalError, "Options cannot be a nullptr"); } } @@ -75,14 +135,19 @@ class Parser { // This method produces a parser that does not own the builder explicit Parser(Builder& builder, Options const* options = &Options::Defaults) - : _e( std::shared_ptr< Builder >( &builder, BuilderNonDeleter() ) ), - options(options) { - if (options == nullptr) { + : _start(nullptr), + _size(0), + _pos(0), + _nesting(0), + options(options) { + if (VELOCYPACK_UNLIKELY(options == nullptr)) { throw Exception(Exception::InternalError, "Options cannot be a nullptr"); } + _builder.reset(&builder, BuilderNonDeleter()); + _builderPtr = _builder.get(); } - Builder const& builder() const { return *_e.builder; } + Builder const& builder() const { return *_builderPtr; } static std::shared_ptr fromJson( std::string const& json, @@ -91,9 +156,9 @@ class Parser { parser.parse(json); return parser.steal(); } - + static std::shared_ptr fromJson( - char const* start, size_t size, + char const* start, std::size_t size, Options const* options = &Options::Defaults) { Parser parser(options); parser.parse(start, size); @@ -101,7 +166,7 @@ class Parser { } static std::shared_ptr fromJson( - uint8_t const* start, size_t size, + uint8_t const* start, std::size_t size, Options const* options = &Options::Defaults) { Parser parser(options); parser.parse(start, size); @@ -109,25 +174,151 @@ class Parser { } ValueLength parse(std::string const& json, bool multi = false) { - return parse(json.data(), json.size(),multi); + return parse(reinterpret_cast(json.data()), json.size(), + multi); + } + + ValueLength parse(char const* start, std::size_t size, bool multi = false) { + return parse(reinterpret_cast(start), size, multi); + } + + ValueLength parse(uint8_t const* start, std::size_t size, bool multi = false) { + _start = start; + _size = size; + _pos = 0; + if (options->clearBuilderBeforeParse) { + _builder->clear(); + } + return parseInternal(multi); } - ValueLength parse(void const* json, const ValueLength size, const bool multi = false ); + // We probably want a parse from stream at some stage... + // Not with this high-performance two-pass approach. :-( std::shared_ptr steal() { // Parser object is broken after a steal() - return std::move( _e.builder ); + std::shared_ptr res(_builder); + _builder.reset(); + _builderPtr = nullptr; + return res; } // Beware, only valid as long as you do not parse more, use steal // to move the data out! - uint8_t const* start() { return _e.builder->start(); } + uint8_t const* start() { return _builderPtr->start(); } // Returns the position at the time when the just reported error // occurred, only use when handling an exception. - size_t errorPos() const { return 0; } // TODO! + std::size_t errorPos() const { return _pos > 0 ? _pos - 1 : _pos; } + + void clear() { _builderPtr->clear(); } + + private: + inline int peek() const { + if (_pos >= _size) { + return -1; + } + return static_cast(_start[_pos]); + } + + inline int consume() { + if (_pos >= _size) { + return -1; + } + return static_cast(_start[_pos++]); + } + + inline void unconsume() { --_pos; } + + inline void reset() { _pos = 0; } + + ValueLength parseInternal(bool multi); + + inline bool isWhiteSpace(uint8_t i) const noexcept { + return (i == ' ' || i == '\t' || i == '\n' || i == '\r'); + } + + // skips over all following whitespace tokens but does not consume the + // byte following the whitespace + int skipWhiteSpace(char const*); + + void parseTrue() { + // Called, when main mode has just seen a 't', need to see "rue" next + if (consume() != 'r' || consume() != 'u' || consume() != 'e') { + throw Exception(Exception::ParseError, "Expecting 'true'"); + } + _builderPtr->addTrue(); + } + + void parseFalse() { + // Called, when main mode has just seen a 'f', need to see "alse" next + if (consume() != 'a' || consume() != 'l' || consume() != 's' || + consume() != 'e') { + throw Exception(Exception::ParseError, "Expecting 'false'"); + } + _builderPtr->addFalse(); + } + + void parseNull() { + // Called, when main mode has just seen a 'n', need to see "ull" next + if (consume() != 'u' || consume() != 'l' || consume() != 'l') { + throw Exception(Exception::ParseError, "Expecting 'null'"); + } + _builderPtr->addNull(); + } + + void scanDigits(ParsedNumber& value) { + while (true) { + int i = consume(); + if (i < 0) { + return; + } + if (i < '0' || i > '9') { + unconsume(); + return; + } + value.addDigit(i); + } + } + + double scanDigitsFractional() { + double pot = 0.1; + double x = 0.0; + while (true) { + int i = consume(); + if (i < 0) { + return x; + } + if (i < '0' || i > '9') { + unconsume(); + return x; + } + x = x + pot * (i - '0'); + pot /= 10.0; + } + } + + inline int getOneOrThrow(char const* msg) { + int i = consume(); + if (i < 0) { + throw Exception(Exception::ParseError, msg); + } + return i; + } + + inline void increaseNesting() { ++_nesting; } + + inline void decreaseNesting() { --_nesting; } + + void parseNumber(); + + void parseString(); + + void parseArray(); + + void parseObject(); - void clear() { _e.builder->clear(); } + void parseJson(); }; } // namespace arangodb::velocypack diff --git a/include/velocypack/TaoParser.h b/include/velocypack/TaoParser.h new file mode 100644 index 00000000..679e65a1 --- /dev/null +++ b/include/velocypack/TaoParser.h @@ -0,0 +1,136 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief Library to build up VPack documents. +/// +/// DISCLAIMER +/// +/// Copyright 2015 ArangoDB GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is ArangoDB GmbH, Cologne, Germany +/// +/// @author Max Neunhoeffer +/// @author Jan Steemann +/// @author Copyright 2015, ArangoDB GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#ifndef VELOCYPACK_PARSER_H +#define VELOCYPACK_PARSER_H 1 + +#include +#include +#include +#include + +#include "velocypack/velocypack-common.h" +#include "velocypack/Json.h" +#include "velocypack/Exception.h" + +namespace arangodb { +namespace velocypack { + + // Parser class with the same interface as before + // the integration of taocpp/json. + +class Parser { + + EventsToBuilder _e; + + public: + Options const* options; + + Parser(Parser const&) = delete; + Parser(Parser&&) = delete; + Parser& operator=(Parser const&) = delete; + Parser& operator=(Parser&&) = delete; + ~Parser() = default; + + explicit Parser(Options const* options = &Options::Defaults) + : options(options) { + if (options == nullptr) { + throw Exception(Exception::InternalError, "Options cannot be a nullptr"); + } + _e.builder->options = options; + } + + explicit Parser(std::shared_ptr& builder, + Options const* options = &Options::Defaults) + : _e(builder), + options(options) { + if (options == nullptr) { + throw Exception(Exception::InternalError, "Options cannot be a nullptr"); + } + } + + // This method produces a parser that does not own the builder + explicit Parser(Builder& builder, + Options const* options = &Options::Defaults) + : _e( std::shared_ptr< Builder >( &builder, BuilderNonDeleter() ) ), + options(options) { + if (options == nullptr) { + throw Exception(Exception::InternalError, "Options cannot be a nullptr"); + } + } + + Builder const& builder() const { return *_e.builder; } + + static std::shared_ptr fromJson( + std::string const& json, + Options const* options = &Options::Defaults) { + Parser parser(options); + parser.parse(json); + return parser.steal(); + } + + static std::shared_ptr fromJson( + char const* start, size_t size, + Options const* options = &Options::Defaults) { + Parser parser(options); + parser.parse(start, size); + return parser.steal(); + } + + static std::shared_ptr fromJson( + uint8_t const* start, size_t size, + Options const* options = &Options::Defaults) { + Parser parser(options); + parser.parse(start, size); + return parser.steal(); + } + + ValueLength parse(std::string const& json, bool multi = false) { + return parse(json.data(), json.size(),multi); + } + + ValueLength parse(void const* json, const ValueLength size, const bool multi = false ); + + std::shared_ptr steal() { + // Parser object is broken after a steal() + return std::move( _e.builder ); + } + + // Beware, only valid as long as you do not parse more, use steal + // to move the data out! + uint8_t const* start() { return _e.builder->start(); } + + // Returns the position at the time when the just reported error + // occurred, only use when handling an exception. + size_t errorPos() const { return 0; } // TODO! + + void clear() { _e.builder->clear(); } +}; + +} // namespace arangodb::velocypack +} // namespace arangodb + +#endif diff --git a/src/Parser.cpp b/src/Parser.cpp index 1aaf914d..89633c66 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -26,32 +26,550 @@ #include "velocypack/velocypack-common.h" #include "velocypack/Parser.h" +#include "velocypack/Value.h" +#include "velocypack/ValueType.h" +#include "asm-functions.h" #include -namespace arangodb -{ - namespace velocypack - { - ValueLength Parser::parse( const void * json, const ValueLength size, const bool multi) { - if (options->clearBuilderBeforeParse) { - _e.builder->clear(); - } - tao::json_pegtl::memory_input< tao::json_pegtl::tracking_mode::LAZY, tao::json_pegtl::eol::lf_crlf, const char* > in( reinterpret_cast< const char * >( json ), size, __PRETTY_FUNCTION__ ); - if ( multi ) { - ValueLength nr = 0; - do { - const auto * const t = in.current(); - tao::json_pegtl::parse< tao::json_pegtl::must< tao::json::internal::rules::text >, tao::json::internal::action, tao::json::internal::control >( in, _e ); - nr += in.current() - t; - } while ( !in.empty() ); - return nr; - } - const auto * const t = in.current(); - tao::json_pegtl::parse< tao::json::internal::grammar, tao::json::internal::action, tao::json::internal::control >( in, _e ); - return in.current() - t; - } - - } // velocypack - -} // arangodb +using namespace arangodb::velocypack; + +// The following function does the actual parse. It gets bytes +// via peek, consume and reset appends the result to the Builder +// in *_builderPtr. Errors are reported via an exception. +// Behind the scenes it runs two parses, one to collect sizes and +// check for parse errors (scan phase) and then one to actually +// build the result (build phase). + +ValueLength Parser::parseInternal(bool multi) { + // skip over optional BOM + if (_size >= 3 && _start[0] == 0xef && _start[1] == 0xbb && + _start[2] == 0xbf) { + // found UTF-8 BOM. simply skip over it + _pos += 3; + } + + ValueLength nr = 0; + do { + bool haveReported = false; + if (!_builderPtr->_stack.empty()) { + ValueLength const tos = _builderPtr->_stack.back(); + if (_builderPtr->_start[tos] == 0x0b || _builderPtr->_start[tos] == 0x14) { + if (!_builderPtr->_keyWritten) { + throw Exception(Exception::BuilderKeyMustBeString); + } + else { + _builderPtr->_keyWritten = false; + } + } + else { + _builderPtr->reportAdd(); + haveReported = true; + } + } + try { + parseJson(); + } + catch (...) { + if (haveReported) { + _builderPtr->cleanupAdd(); + } + throw; + } + nr++; + while (_pos < _size && isWhiteSpace(_start[_pos])) { + ++_pos; + } + if (!multi && _pos != _size) { + consume(); // to get error reporting right. return value intentionally not checked + throw Exception(Exception::ParseError, "Expecting EOF"); + } + } while (multi && _pos < _size); + return nr; +} + +// skips over all following whitespace tokens but does not consume the +// byte following the whitespace +int Parser::skipWhiteSpace(char const* err) { + if (VELOCYPACK_UNLIKELY(_pos >= _size)) { + throw Exception(Exception::ParseError, err); + } + uint8_t c = _start[_pos]; + if (!isWhiteSpace(c)) { + return c; + } + if (c == ' ') { + if (_pos + 1 >= _size) { + _pos++; + throw Exception(Exception::ParseError, err); + } + c = _start[_pos + 1]; + if (!isWhiteSpace(c)) { + _pos++; + return c; + } + } + std::size_t remaining = _size - _pos; + if (remaining >= 16) { + std::size_t count = JSONSkipWhiteSpace(_start + _pos, remaining - 15); + _pos += count; + } + do { + if (!isWhiteSpace(_start[_pos])) { + return static_cast(_start[_pos]); + } + _pos++; + } while (_pos < _size); + throw Exception(Exception::ParseError, err); +} + +// parses a number value +void Parser::parseNumber() { + std::size_t startPos = _pos; + ParsedNumber numberValue; + bool negative = false; + int i = consume(); + // We know that a character is coming, and it's a number if it + // starts with '-' or a digit. otherwise it's invalid + if (i == '-') { + i = getOneOrThrow("Incomplete number"); + negative = true; + } + if (i < '0' || i > '9') { + throw Exception(Exception::ParseError, "Expecting digit"); + } + + if (i != '0') { + unconsume(); + scanDigits(numberValue); + } + i = consume(); + if (i < 0 || (i != '.' && i != 'e' && i != 'E')) { + if (i >= 0) { + unconsume(); + } + if (!numberValue.isInteger) { + if (negative) { + _builderPtr->addDouble(-numberValue.doubleValue); + } else { + _builderPtr->addDouble(numberValue.doubleValue); + } + } else if (negative) { + if (numberValue.intValue <= static_cast(INT64_MAX)) { + _builderPtr->addInt(-static_cast(numberValue.intValue)); + } else if (numberValue.intValue == toUInt64(INT64_MIN)) { + _builderPtr->addInt(INT64_MIN); + } else { + _builderPtr->addDouble(-static_cast(numberValue.intValue)); + } + } else { + _builderPtr->addUInt(numberValue.intValue); + } + return; + } + + double fractionalPart; + if (i == '.') { + // fraction. skip over '.' + i = getOneOrThrow("Incomplete number"); + if (i < '0' || i > '9') { + throw Exception(Exception::ParseError, "Incomplete number"); + } + unconsume(); + fractionalPart = scanDigitsFractional(); + if (negative) { + fractionalPart = -numberValue.asDouble() - fractionalPart; + } else { + fractionalPart = numberValue.asDouble() + fractionalPart; + } + i = consume(); + if (i < 0) { + _builderPtr->addDouble(fractionalPart); + return; + } + } else { + if (negative) { + fractionalPart = -numberValue.asDouble(); + } else { + fractionalPart = numberValue.asDouble(); + } + } + if (i != 'e' && i != 'E') { + unconsume(); + // use conventional atof() conversion here, to avoid precision loss + // when interpreting and multiplying the single digits of the input stream + // _builderPtr->addDouble(fractionalPart); + _builderPtr->addDouble(atof(reinterpret_cast(_start) + startPos)); + return; + } + i = getOneOrThrow("Incomplete number"); + negative = false; + if (i == '+' || i == '-') { + negative = (i == '-'); + i = getOneOrThrow("Incomplete number"); + } + if (i < '0' || i > '9') { + throw Exception(Exception::ParseError, "Incomplete number"); + } + unconsume(); + ParsedNumber exponent; + scanDigits(exponent); + if (negative) { + fractionalPart *= pow(10, -exponent.asDouble()); + } else { + fractionalPart *= pow(10, exponent.asDouble()); + } + if (std::isnan(fractionalPart) || !std::isfinite(fractionalPart)) { + throw Exception(Exception::NumberOutOfRange); + } + // use conventional atof() conversion here, to avoid precision loss + // when interpreting and multiplying the single digits of the input stream + // _builderPtr->addDouble(fractionalPart); + _builderPtr->addDouble(atof(reinterpret_cast(_start) + startPos)); +} + +void Parser::parseString() { + // When we get here, we have seen a " character and now want to + // find the end of the string and parse the string value to its + // VPack representation. We assume that the string is short and + // insert 8 bytes for the length as soon as we reach 127 bytes + // in the VPack representation. + ValueLength const base = _builderPtr->_pos; + _builderPtr->appendByte(0x40); // correct this later + + bool large = false; // set to true when we reach 128 bytes + uint32_t highSurrogate = 0; // non-zero if high-surrogate was seen + + while (true) { + std::size_t remainder = _size - _pos; + if (remainder >= 16) { + _builderPtr->reserve(remainder); + std::size_t count; + // Note that the SSE4.2 accelerated string copying functions might + // peek up to 15 bytes over the given end, because they use 128bit + // registers. Therefore, we have to subtract 15 from remainder + // to be on the safe side. Further bytes will be processed below. + if (options->validateUtf8Strings) { + count = JSONStringCopyCheckUtf8(_builderPtr->_start + _builderPtr->_pos, _start + _pos, + remainder - 15); + } else { + count = JSONStringCopy(_builderPtr->_start + _builderPtr->_pos, _start + _pos, + remainder - 15); + } + _pos += count; + _builderPtr->advance(count); + } + int i = getOneOrThrow("Unfinished string"); + if (!large && _builderPtr->_pos - (base + 1) > 126) { + large = true; + _builderPtr->reserve(8); + ValueLength len = _builderPtr->_pos - (base + 1); + memmove(_builderPtr->_start + base + 9, _builderPtr->_start + base + 1, checkOverflow(len)); + _builderPtr->advance(8); + } + switch (i) { + case '"': + ValueLength len; + if (!large) { + len = _builderPtr->_pos - (base + 1); + _builderPtr->_start[base] = 0x40 + static_cast(len); + // String is ready + } else { + len = _builderPtr->_pos - (base + 9); + _builderPtr->_start[base] = 0xbf; + for (ValueLength i = 1; i <= 8; i++) { + _builderPtr->_start[base + i] = len & 0xff; + len >>= 8; + } + } + return; + case '\\': + // Handle cases or throw error + i = consume(); + if (VELOCYPACK_UNLIKELY(i < 0)) { + throw Exception(Exception::ParseError, "Invalid escape sequence"); + } + switch (i) { + case '"': + case '/': + case '\\': + _builderPtr->appendByte(static_cast(i)); + highSurrogate = 0; + break; + case 'b': + _builderPtr->appendByte('\b'); + highSurrogate = 0; + break; + case 'f': + _builderPtr->appendByte('\f'); + highSurrogate = 0; + break; + case 'n': + _builderPtr->appendByte('\n'); + highSurrogate = 0; + break; + case 'r': + _builderPtr->appendByte('\r'); + highSurrogate = 0; + break; + case 't': + _builderPtr->appendByte('\t'); + highSurrogate = 0; + break; + case 'u': { + uint32_t v = 0; + for (int j = 0; j < 4; j++) { + i = consume(); + if (i < 0) { + throw Exception(Exception::ParseError, + "Unfinished \\uXXXX escape sequence"); + } + if (i >= '0' && i <= '9') { + v = (v << 4) + i - '0'; + } else if (i >= 'a' && i <= 'f') { + v = (v << 4) + i - 'a' + 10; + } else if (i >= 'A' && i <= 'F') { + v = (v << 4) + i - 'A' + 10; + } else { + throw Exception(Exception::ParseError, + "Illegal \\uXXXX escape sequence"); + } + } + if (v < 0x80) { + _builderPtr->appendByte(static_cast(v)); + highSurrogate = 0; + } else if (v < 0x800) { + _builderPtr->reserve(2); + _builderPtr->appendByteUnchecked(0xc0 + (v >> 6)); + _builderPtr->appendByteUnchecked(0x80 + (v & 0x3f)); + highSurrogate = 0; + } else if (v >= 0xdc00 && v < 0xe000 && highSurrogate != 0) { + // Low surrogate, put the two together: + v = 0x10000 + ((highSurrogate - 0xd800) << 10) + v - 0xdc00; + _builderPtr->rollback(3); + _builderPtr->reserve(4); + _builderPtr->appendByteUnchecked(0xf0 + (v >> 18)); + _builderPtr->appendByteUnchecked(0x80 + ((v >> 12) & 0x3f)); + _builderPtr->appendByteUnchecked(0x80 + ((v >> 6) & 0x3f)); + _builderPtr->appendByteUnchecked(0x80 + (v & 0x3f)); + highSurrogate = 0; + } else { + if (v >= 0xd800 && v < 0xdc00) { + // High surrogate: + highSurrogate = v; + } else { + highSurrogate = 0; + } + _builderPtr->reserve(3); + _builderPtr->appendByteUnchecked(0xe0 + (v >> 12)); + _builderPtr->appendByteUnchecked(0x80 + ((v >> 6) & 0x3f)); + _builderPtr->appendByteUnchecked(0x80 + (v & 0x3f)); + } + break; + } + default: + throw Exception(Exception::ParseError, "Invalid escape sequence"); + } + break; + default: + if ((i & 0x80) == 0) { + // non-UTF-8 sequence + if (VELOCYPACK_UNLIKELY(i < 0x20)) { + // control character + throw Exception(Exception::UnexpectedControlCharacter); + } + highSurrogate = 0; + _builderPtr->appendByte(static_cast(i)); + } else { + if (!options->validateUtf8Strings) { + highSurrogate = 0; + _builderPtr->appendByte(static_cast(i)); + } else { + // multi-byte UTF-8 sequence! + int follow = 0; + if ((i & 0xe0) == 0x80) { + throw Exception(Exception::InvalidUtf8Sequence); + } else if ((i & 0xe0) == 0xc0) { + // two-byte sequence + follow = 1; + } else if ((i & 0xf0) == 0xe0) { + // three-byte sequence + follow = 2; + } else if ((i & 0xf8) == 0xf0) { + // four-byte sequence + follow = 3; + } else { + throw Exception(Exception::InvalidUtf8Sequence); + } + + // validate follow up characters + _builderPtr->reserve(1 + follow); + _builderPtr->appendByteUnchecked(static_cast(i)); + for (int j = 0; j < follow; ++j) { + i = getOneOrThrow("scanString: truncated UTF-8 sequence"); + if ((i & 0xc0) != 0x80) { + throw Exception(Exception::InvalidUtf8Sequence); + } + _builderPtr->appendByteUnchecked(static_cast(i)); + } + highSurrogate = 0; + } + } + break; + } + } +} + +void Parser::parseArray() { + _builderPtr->addArray(); + + int i = skipWhiteSpace("Expecting item or ']'"); + if (i == ']') { + // empty array + ++_pos; // the closing ']' + _builderPtr->close(); + return; + } + + increaseNesting(); + + while (true) { + // parse array element itself + _builderPtr->reportAdd(); + parseJson(); + i = skipWhiteSpace("Expecting ',' or ']'"); + if (i == ']') { + // end of array + ++_pos; // the closing ']' + _builderPtr->close(); + decreaseNesting(); + return; + } + // skip over ',' + if (VELOCYPACK_UNLIKELY(i != ',')) { + throw Exception(Exception::ParseError, "Expecting ',' or ']'"); + } + ++_pos; // the ',' + } + + // should never get here + VELOCYPACK_ASSERT(false); +} + +void Parser::parseObject() { + _builderPtr->addObject(); + + int i = skipWhiteSpace("Expecting item or '}'"); + if (i == '}') { + // empty object + consume(); // the closing '}'. return value intentionally not checked + + if (_nesting != 0 || !options->keepTopLevelOpen) { + // only close if we've not been asked to keep top level open + _builderPtr->close(); + } + return; + } + + increaseNesting(); + + while (true) { + // always expecting a string attribute name here + if (VELOCYPACK_UNLIKELY(i != '"')) { + throw Exception(Exception::ParseError, "Expecting '\"' or '}'"); + } + // get past the initial '"' + ++_pos; + + _builderPtr->reportAdd(); + auto const lastPos = _builderPtr->_pos; + parseString(); + + if (options->attributeTranslator != nullptr) { + // check if a translation for the attribute name exists + Slice key(_builderPtr->_start + lastPos); + + if (key.isString()) { + ValueLength keyLength; + char const* p = key.getString(keyLength); + uint8_t const* translated = + options->attributeTranslator->translate(p, keyLength); + + if (translated != nullptr) { + // found translation... now reset position to old key position + // and simply overwrite the existing key with the numeric translation + // id + _builderPtr->resetTo(lastPos); + _builderPtr->addUInt(Slice(translated).getUInt()); + } + } + } + + i = skipWhiteSpace("Expecting ':'"); + // always expecting the ':' here + if (VELOCYPACK_UNLIKELY(i != ':')) { + throw Exception(Exception::ParseError, "Expecting ':'"); + } + ++_pos; // skip over the colon + + parseJson(); + + i = skipWhiteSpace("Expecting ',' or '}'"); + if (i == '}') { + // end of object + ++_pos; // the closing '}' + if (_nesting != 1 || !options->keepTopLevelOpen) { + // only close if we've not been asked to keep top level open + _builderPtr->close(); + } + decreaseNesting(); + return; + } + if (VELOCYPACK_UNLIKELY(i != ',')) { + throw Exception(Exception::ParseError, "Expecting ',' or '}'"); + } + // skip over ',' + ++_pos; // the ',' + i = skipWhiteSpace("Expecting '\"' or '}'"); + } + + // should never get here + VELOCYPACK_ASSERT(false); +} + +void Parser::parseJson() { + skipWhiteSpace("Expecting item"); // return value intentionally not checked + + int i = consume(); + if (i < 0) { + return; + } + switch (i) { + case '{': + parseObject(); // this consumes the closing '}' or throws + break; + case '[': + parseArray(); // this consumes the closing ']' or throws + break; + case 't': + parseTrue(); // this consumes "rue" or throws + break; + case 'f': + parseFalse(); // this consumes "alse" or throws + break; + case 'n': + parseNull(); // this consumes "ull" or throws + break; + case '"': + parseString(); + break; + default: { + // everything else must be a number or is invalid... + // this includes '-' and '0' to '9'. scanNumber() will + // throw if the input is non-numeric + unconsume(); + parseNumber(); // this consumes the number or throws + break; + } + } +} diff --git a/src/TaoParser.cpp b/src/TaoParser.cpp new file mode 100644 index 00000000..1aaf914d --- /dev/null +++ b/src/TaoParser.cpp @@ -0,0 +1,57 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief Library to build up VPack documents. +/// +/// DISCLAIMER +/// +/// Copyright 2015 ArangoDB GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is ArangoDB GmbH, Cologne, Germany +/// +/// @author Max Neunhoeffer +/// @author Jan Steemann +/// @author Copyright 2015, ArangoDB GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#include "velocypack/velocypack-common.h" +#include "velocypack/Parser.h" + +#include + +namespace arangodb +{ + namespace velocypack + { + ValueLength Parser::parse( const void * json, const ValueLength size, const bool multi) { + if (options->clearBuilderBeforeParse) { + _e.builder->clear(); + } + tao::json_pegtl::memory_input< tao::json_pegtl::tracking_mode::LAZY, tao::json_pegtl::eol::lf_crlf, const char* > in( reinterpret_cast< const char * >( json ), size, __PRETTY_FUNCTION__ ); + if ( multi ) { + ValueLength nr = 0; + do { + const auto * const t = in.current(); + tao::json_pegtl::parse< tao::json_pegtl::must< tao::json::internal::rules::text >, tao::json::internal::action, tao::json::internal::control >( in, _e ); + nr += in.current() - t; + } while ( !in.empty() ); + return nr; + } + const auto * const t = in.current(); + tao::json_pegtl::parse< tao::json::internal::grammar, tao::json::internal::action, tao::json::internal::control >( in, _e ); + return in.current() - t; + } + + } // velocypack + +} // arangodb From bf446e28b136eb9b915bf653d2d0d301933b0a86 Mon Sep 17 00:00:00 2001 From: Jan Christoph Uhde Date: Fri, 14 Feb 2020 12:22:55 +0100 Subject: [PATCH 3/7] Make the project build. --- CMakeLists.txt | 1 + include/velocypack/TaoParser.h | 31 +++++++++++++++---------------- src/TaoParser.cpp | 7 +++---- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 82ea636f..ea801917 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,7 @@ set(VELOCY_SOURCE src/Iterator.cpp src/Options.cpp src/Parser.cpp + src/TaoParser.cpp src/Serializable.cpp src/Slice.cpp src/SliceStaticData.cpp diff --git a/include/velocypack/TaoParser.h b/include/velocypack/TaoParser.h index 679e65a1..89f73756 100644 --- a/include/velocypack/TaoParser.h +++ b/include/velocypack/TaoParser.h @@ -19,13 +19,12 @@ /// /// Copyright holder is ArangoDB GmbH, Cologne, Germany /// -/// @author Max Neunhoeffer -/// @author Jan Steemann +/// @author Colin Hirsch /// @author Copyright 2015, ArangoDB GmbH, Cologne, Germany //////////////////////////////////////////////////////////////////////////////// -#ifndef VELOCYPACK_PARSER_H -#define VELOCYPACK_PARSER_H 1 +#ifndef VELOCYPACK_TAOPARSER_H +#define VELOCYPACK_TAOPARSER_H 1 #include #include @@ -42,20 +41,20 @@ namespace velocypack { // Parser class with the same interface as before // the integration of taocpp/json. -class Parser { +class TaoParser { EventsToBuilder _e; public: Options const* options; - Parser(Parser const&) = delete; - Parser(Parser&&) = delete; - Parser& operator=(Parser const&) = delete; - Parser& operator=(Parser&&) = delete; - ~Parser() = default; + TaoParser(TaoParser const&) = delete; + TaoParser(TaoParser&&) = delete; + TaoParser& operator=(TaoParser const&) = delete; + TaoParser& operator=(TaoParser&&) = delete; + ~TaoParser() = default; - explicit Parser(Options const* options = &Options::Defaults) + explicit TaoParser(Options const* options = &Options::Defaults) : options(options) { if (options == nullptr) { throw Exception(Exception::InternalError, "Options cannot be a nullptr"); @@ -63,7 +62,7 @@ class Parser { _e.builder->options = options; } - explicit Parser(std::shared_ptr& builder, + explicit TaoParser(std::shared_ptr& builder, Options const* options = &Options::Defaults) : _e(builder), options(options) { @@ -73,7 +72,7 @@ class Parser { } // This method produces a parser that does not own the builder - explicit Parser(Builder& builder, + explicit TaoParser(Builder& builder, Options const* options = &Options::Defaults) : _e( std::shared_ptr< Builder >( &builder, BuilderNonDeleter() ) ), options(options) { @@ -87,7 +86,7 @@ class Parser { static std::shared_ptr fromJson( std::string const& json, Options const* options = &Options::Defaults) { - Parser parser(options); + TaoParser parser(options); parser.parse(json); return parser.steal(); } @@ -95,7 +94,7 @@ class Parser { static std::shared_ptr fromJson( char const* start, size_t size, Options const* options = &Options::Defaults) { - Parser parser(options); + TaoParser parser(options); parser.parse(start, size); return parser.steal(); } @@ -103,7 +102,7 @@ class Parser { static std::shared_ptr fromJson( uint8_t const* start, size_t size, Options const* options = &Options::Defaults) { - Parser parser(options); + TaoParser parser(options); parser.parse(start, size); return parser.steal(); } diff --git a/src/TaoParser.cpp b/src/TaoParser.cpp index 1aaf914d..947f68f0 100644 --- a/src/TaoParser.cpp +++ b/src/TaoParser.cpp @@ -19,13 +19,12 @@ /// /// Copyright holder is ArangoDB GmbH, Cologne, Germany /// -/// @author Max Neunhoeffer -/// @author Jan Steemann +/// @author Colin Hirsch /// @author Copyright 2015, ArangoDB GmbH, Cologne, Germany //////////////////////////////////////////////////////////////////////////////// #include "velocypack/velocypack-common.h" -#include "velocypack/Parser.h" +#include "velocypack/TaoParser.h" #include @@ -33,7 +32,7 @@ namespace arangodb { namespace velocypack { - ValueLength Parser::parse( const void * json, const ValueLength size, const bool multi) { + ValueLength TaoParser::parse( const void * json, const ValueLength size, const bool multi) { if (options->clearBuilderBeforeParse) { _e.builder->clear(); } From 503ce3dd53b936ca51606234cedd51a789e6e9af Mon Sep 17 00:00:00 2001 From: Jan Christoph Uhde Date: Fri, 14 Feb 2020 12:57:23 +0100 Subject: [PATCH 4/7] Update taocpp json lib. --- include/tao/json.hpp | 71 +- include/tao/json/basic_value.hpp | 941 ++++++++ include/tao/json/binary.hpp | 149 +- include/tao/json/binary_view.hpp | 31 + include/tao/json/binding.hpp | 71 + include/tao/json/binding/constant.hpp | 232 ++ include/tao/json/binding/element.hpp | 182 ++ include/tao/json/binding/factory.hpp | 250 +++ .../tao/json/binding/for_nothing_value.hpp | 17 + include/tao/json/binding/for_unknown_key.hpp | 17 + include/tao/json/binding/inherit.hpp | 14 + include/tao/json/binding/internal/array.hpp | 103 + include/tao/json/binding/internal/inherit.hpp | 45 + include/tao/json/binding/internal/object.hpp | 267 +++ .../tao/json/binding/internal/type_key.hpp | 54 + include/tao/json/binding/member.hpp | 32 + include/tao/json/binding/member_kind.hpp | 17 + include/tao/json/binding/versions.hpp | 127 ++ include/tao/json/byte_view.hpp | 445 ---- include/tao/json/cbor.hpp | 11 +- include/tao/json/cbor/consume_file.hpp | 34 + include/tao/json/cbor/consume_string.hpp | 32 + include/tao/json/cbor/events/from_file.hpp | 27 + include/tao/json/cbor/events/from_input.hpp | 43 + include/tao/json/cbor/events/from_string.hpp | 37 + include/tao/json/cbor/events/to_stream.hpp | 161 ++ include/tao/json/cbor/events/to_string.hpp | 31 + include/tao/json/cbor/from_file.hpp | 33 + include/tao/json/cbor/from_input.hpp | 33 + include/tao/json/cbor/from_string.hpp | 46 +- include/tao/json/cbor/internal/grammar.hpp | 417 ++++ include/tao/json/cbor/internal/major.hpp | 28 + include/tao/json/cbor/parts_parser.hpp | 392 ++++ include/tao/json/cbor/to_stream.hpp | 30 +- include/tao/json/cbor/to_string.hpp | 32 +- include/tao/json/consume.hpp | 43 + include/tao/json/consume_file.hpp | 33 + include/tao/json/consume_string.hpp | 31 + include/tao/json/contrib/array_traits.hpp | 43 + include/tao/json/contrib/deque_traits.hpp | 41 + include/tao/json/contrib/diff.hpp | 106 + include/tao/json/contrib/get.hpp | 152 ++ .../json/contrib/internal/array_traits.hpp | 92 + .../json/contrib/internal/indirect_traits.hpp | 69 + .../json/contrib/internal/object_traits.hpp | 105 + .../tao/json/contrib/internal/type_traits.hpp | 36 + include/tao/json/contrib/list_traits.hpp | 41 + include/tao/json/contrib/map_traits.hpp | 43 + include/tao/json/contrib/multimap_traits.hpp | 43 + include/tao/json/contrib/multiset_traits.hpp | 41 + include/tao/json/contrib/pair_traits.hpp | 21 + include/tao/json/contrib/patch.hpp | 105 + include/tao/json/contrib/pointer_traits.hpp | 59 + include/tao/json/contrib/position.hpp | 166 ++ include/tao/json/contrib/reference.hpp | 115 + include/tao/json/contrib/schema.hpp | 1851 ++++++++++++++++ include/tao/json/contrib/set_traits.hpp | 41 + .../tao/json/contrib/shared_ptr_traits.hpp | 90 + include/tao/json/contrib/traits.hpp | 121 ++ include/tao/json/contrib/tuple_traits.hpp | 51 + .../tao/json/contrib/unique_ptr_traits.hpp | 89 + .../tao/json/contrib/unordered_map_traits.hpp | 43 + .../tao/json/contrib/unordered_set_traits.hpp | 41 + .../tao/json/contrib/vector_bool_traits.hpp | 45 + include/tao/json/contrib/vector_traits.hpp | 51 + include/tao/json/events.hpp | 47 + include/tao/json/events/apply.hpp | 26 +- include/tao/json/events/binary_to_base64.hpp | 38 +- .../tao/json/events/binary_to_base64url.hpp | 38 +- .../tao/json/events/binary_to_exception.hpp | 38 +- include/tao/json/events/binary_to_hex.hpp | 38 +- include/tao/json/events/cbor/from_string.hpp | 47 - include/tao/json/events/cbor/grammar.hpp | 444 ---- include/tao/json/events/cbor/major.hpp | 40 - include/tao/json/events/cbor/to_stream.hpp | 166 -- include/tao/json/events/cbor/to_string.hpp | 43 - include/tao/json/events/compare.hpp | 374 ++-- include/tao/json/events/debug.hpp | 264 ++- include/tao/json/events/discard.hpp | 95 +- include/tao/json/events/from_file.hpp | 28 + include/tao/json/events/from_input.hpp | 45 + include/tao/json/events/from_stream.hpp | 44 +- include/tao/json/events/from_string.hpp | 67 +- include/tao/json/events/from_value.hpp | 360 ++-- include/tao/json/events/hash.hpp | 280 ++- .../json/events/invalid_string_to_binary.hpp | 50 + .../events/invalid_string_to_exception.hpp | 49 + .../tao/json/events/invalid_string_to_hex.hpp | 48 + include/tao/json/events/jaxn/from_stream.hpp | 45 - include/tao/json/events/jaxn/from_string.hpp | 51 - include/tao/json/events/jaxn/parse_file.hpp | 40 - .../tao/json/events/jaxn/to_pretty_stream.hpp | 76 - include/tao/json/events/jaxn/to_stream.hpp | 75 - .../events/key_camel_case_to_snake_case.hpp | 101 +- .../events/key_snake_case_to_camel_case.hpp | 93 +- .../tao/json/events/limit_nesting_depth.hpp | 82 + include/tao/json/events/limit_value_count.hpp | 46 + .../tao/json/events/msgpack/from_string.hpp | 46 - include/tao/json/events/msgpack/grammar.hpp | 261 --- include/tao/json/events/msgpack/to_stream.hpp | 218 -- include/tao/json/events/msgpack/to_string.hpp | 44 - .../json/events/non_finite_to_exception.hpp | 46 +- .../tao/json/events/non_finite_to_null.hpp | 50 +- .../tao/json/events/non_finite_to_string.hpp | 64 +- include/tao/json/events/parse_file.hpp | 36 - include/tao/json/events/prefer_signed.hpp | 50 +- include/tao/json/events/prefer_unsigned.hpp | 50 +- include/tao/json/events/produce.hpp | 22 + include/tao/json/events/ref.hpp | 211 +- include/tao/json/events/statistics.hpp | 112 + include/tao/json/events/tee.hpp | 733 +++---- include/tao/json/events/to_pretty_stream.hpp | 304 +-- include/tao/json/events/to_stream.hpp | 253 ++- include/tao/json/events/to_string.hpp | 45 +- include/tao/json/events/to_value.hpp | 259 ++- include/tao/json/events/transformer.hpp | 79 +- .../tao/json/events/ubjson/from_string.hpp | 47 - include/tao/json/events/ubjson/grammar.hpp | 279 --- include/tao/json/events/ubjson/to_stream.hpp | 188 -- include/tao/json/events/ubjson/to_string.hpp | 44 - .../tao/json/events/validate_event_order.hpp | 726 ++++--- include/tao/json/events/validate_keys.hpp | 81 +- include/tao/json/events/virtual_base.hpp | 192 ++ include/tao/json/events/virtual_ref.hpp | 170 ++ .../tao/json/external/akrzemi1/CMakeLists.txt | 46 - include/tao/json/external/akrzemi1/LICENSE | 23 - .../json/external/akrzemi1/LICENSE_1_0.txt | 23 - include/tao/json/external/akrzemi1/README.md | 39 - .../tao/json/external/akrzemi1/copyright.txt | 10 - .../tao/json/external/akrzemi1/optional.hpp | 1052 --------- .../json/external/akrzemi1/test_optional.cpp | 1520 ------------- .../external/akrzemi1/test_type_traits.cpp | 66 - include/tao/json/external/byte.hpp | 109 - include/tao/json/external/double.hpp | 1221 ++--------- include/tao/json/external/itoa.hpp | 149 ++ include/tao/json/external/operators.hpp | 658 ------ include/tao/json/external/optional.hpp | 46 - include/tao/json/external/pegtl.hpp | 32 +- .../pegtl/analysis/analyze_cycles.hpp | 193 +- .../json/external/pegtl/analysis/counted.hpp | 28 +- .../json/external/pegtl/analysis/generic.hpp | 42 +- .../external/pegtl/analysis/grammar_info.hpp | 36 +- .../external/pegtl/analysis/insert_guard.hpp | 79 +- .../external/pegtl/analysis/insert_rules.hpp | 42 +- .../external/pegtl/analysis/rule_info.hpp | 32 +- .../external/pegtl/analysis/rule_type.hpp | 30 +- include/tao/json/external/pegtl/analyze.hpp | 22 +- .../tao/json/external/pegtl/apply_mode.hpp | 22 +- .../tao/json/external/pegtl/argv_input.hpp | 59 +- include/tao/json/external/pegtl/ascii.hpp | 96 +- .../tao/json/external/pegtl/buffer_input.hpp | 281 +-- .../tao/json/external/pegtl/change_action.hpp | 38 + .../pegtl/change_action_and_state.hpp | 53 + .../pegtl/change_action_and_states.hpp | 62 + .../json/external/pegtl/change_control.hpp | 36 + .../tao/json/external/pegtl/change_state.hpp | 50 + .../tao/json/external/pegtl/change_states.hpp | 61 + include/tao/json/external/pegtl/config.hpp | 14 +- .../tao/json/external/pegtl/contrib/abnf.hpp | 60 +- .../json/external/pegtl/contrib/alphabet.hpp | 122 +- .../json/external/pegtl/contrib/changes.hpp | 86 - .../json/external/pegtl/contrib/counter.hpp | 76 +- .../tao/json/external/pegtl/contrib/http.hpp | 295 ++- .../external/pegtl/contrib/icu/internal.hpp | 68 + .../json/external/pegtl/contrib/icu/utf16.hpp | 200 ++ .../json/external/pegtl/contrib/icu/utf32.hpp | 200 ++ .../json/external/pegtl/contrib/icu/utf8.hpp | 105 + .../json/external/pegtl/contrib/if_then.hpp | 55 + .../json/external/pegtl/contrib/integer.hpp | 446 ++++ .../tao/json/external/pegtl/contrib/json.hpp | 162 +- .../external/pegtl/contrib/json_pointer.hpp | 33 + .../external/pegtl/contrib/parse_tree.hpp | 636 ++++-- .../pegtl/contrib/parse_tree_to_dot.hpp | 104 + .../external/pegtl/contrib/raw_string.hpp | 374 ++-- .../pegtl/contrib/remove_first_state.hpp | 86 + .../pegtl/contrib/rep_one_min_max.hpp | 80 +- .../external/pegtl/contrib/rep_string.hpp | 44 + .../json/external/pegtl/contrib/to_string.hpp | 48 +- .../json/external/pegtl/contrib/tracer.hpp | 143 +- .../json/external/pegtl/contrib/unescape.hpp | 348 ++- .../tao/json/external/pegtl/contrib/uri.hpp | 148 +- .../tao/json/external/pegtl/cstream_input.hpp | 31 +- .../json/external/pegtl/disable_action.hpp | 35 + .../tao/json/external/pegtl/discard_input.hpp | 37 + .../pegtl/discard_input_on_failure.hpp | 39 + .../pegtl/discard_input_on_success.hpp | 39 + .../tao/json/external/pegtl/enable_action.hpp | 35 + include/tao/json/external/pegtl/eol.hpp | 57 +- include/tao/json/external/pegtl/eol_pair.hpp | 18 + .../tao/json/external/pegtl/file_input.hpp | 33 +- .../tao/json/external/pegtl/input_error.hpp | 41 - .../json/external/pegtl/internal/action.hpp | 58 +- .../external/pegtl/internal/action_input.hpp | 177 +- .../json/external/pegtl/internal/alnum.hpp | 20 +- .../json/external/pegtl/internal/alpha.hpp | 20 +- .../external/pegtl/internal/always_false.hpp | 21 + .../tao/json/external/pegtl/internal/any.hpp | 88 +- .../json/external/pegtl/internal/apply.hpp | 98 +- .../json/external/pegtl/internal/apply0.hpp | 93 +- .../external/pegtl/internal/apply0_single.hpp | 34 + .../external/pegtl/internal/apply_single.hpp | 34 + .../tao/json/external/pegtl/internal/at.hpp | 79 +- .../tao/json/external/pegtl/internal/bof.hpp | 40 +- .../tao/json/external/pegtl/internal/bol.hpp | 40 +- .../tao/json/external/pegtl/internal/bump.hpp | 45 + .../external/pegtl/internal/bump_help.hpp | 65 +- .../external/pegtl/internal/bump_impl.hpp | 53 - .../json/external/pegtl/internal/bytes.hpp | 54 +- .../json/external/pegtl/internal/control.hpp | 58 +- .../external/pegtl/internal/cr_crlf_eol.hpp | 47 +- .../json/external/pegtl/internal/cr_eol.hpp | 47 +- .../json/external/pegtl/internal/crlf_eol.hpp | 47 +- .../pegtl/internal/cstream_reader.hpp | 71 +- .../pegtl/internal/cstring_reader.hpp | 63 +- .../json/external/pegtl/internal/demangle.hpp | 152 +- .../pegtl/internal/demangle_cxxabi.hpp | 41 - .../external/pegtl/internal/demangle_nop.hpp | 28 - .../pegtl/internal/demangle_sanitise.hpp | 48 - .../json/external/pegtl/internal/disable.hpp | 58 +- .../json/external/pegtl/internal/discard.hpp | 43 +- .../external/pegtl/internal/dusel_mode.hpp | 30 +- .../external/pegtl/internal/duseltronik.hpp | 314 +-- .../json/external/pegtl/internal/enable.hpp | 58 +- .../json/external/pegtl/internal/endian.hpp | 62 + .../external/pegtl/internal/endian_gcc.hpp | 206 ++ .../external/pegtl/internal/endian_win.hpp | 106 + .../tao/json/external/pegtl/internal/eof.hpp | 40 +- .../tao/json/external/pegtl/internal/eol.hpp | 41 +- .../tao/json/external/pegtl/internal/eolf.hpp | 43 +- .../external/pegtl/internal/file_mapper.hpp | 91 - .../pegtl/internal/file_mapper_posix.hpp | 83 + .../pegtl/internal/file_mapper_win32.hpp | 219 ++ .../external/pegtl/internal/file_opener.hpp | 94 +- .../external/pegtl/internal/file_reader.hpp | 162 +- .../external/pegtl/internal/has_apply.hpp | 34 +- .../external/pegtl/internal/has_apply0.hpp | 34 +- .../external/pegtl/internal/has_match.hpp | 56 + .../external/pegtl/internal/identifier.hpp | 24 +- .../json/external/pegtl/internal/if_apply.hpp | 117 +- .../json/external/pegtl/internal/if_must.hpp | 51 +- .../external/pegtl/internal/if_must_else.hpp | 22 +- .../external/pegtl/internal/if_then_else.hpp | 70 +- .../external/pegtl/internal/input_pair.hpp | 40 +- .../pegtl/internal/integer_sequence.hpp | 86 - .../pegtl/internal/istream_reader.hpp | 63 +- .../json/external/pegtl/internal/istring.hpp | 127 +- .../json/external/pegtl/internal/iterator.hpp | 65 +- .../external/pegtl/internal/lf_crlf_eol.hpp | 57 +- .../json/external/pegtl/internal/lf_eol.hpp | 47 +- .../tao/json/external/pegtl/internal/list.hpp | 22 +- .../external/pegtl/internal/list_must.hpp | 22 +- .../external/pegtl/internal/list_tail.hpp | 22 +- .../external/pegtl/internal/list_tail_pad.hpp | 22 +- .../json/external/pegtl/internal/marker.hpp | 153 +- .../json/external/pegtl/internal/minus.hpp | 69 - .../external/pegtl/internal/missing_apply.hpp | 25 + .../pegtl/internal/missing_apply0.hpp | 23 + .../tao/json/external/pegtl/internal/must.hpp | 107 +- .../json/external/pegtl/internal/not_at.hpp | 79 +- .../tao/json/external/pegtl/internal/one.hpp | 83 +- .../tao/json/external/pegtl/internal/opt.hpp | 76 +- .../tao/json/external/pegtl/internal/pad.hpp | 22 +- .../json/external/pegtl/internal/pad_opt.hpp | 22 +- .../external/pegtl/internal/peek_char.hpp | 37 +- .../pegtl/internal/peek_mask_uint.hpp | 54 + .../pegtl/internal/peek_mask_uint8.hpp | 34 + .../external/pegtl/internal/peek_uint.hpp | 45 + .../external/pegtl/internal/peek_uint8.hpp | 33 + .../external/pegtl/internal/peek_utf16.hpp | 80 +- .../external/pegtl/internal/peek_utf32.hpp | 61 +- .../external/pegtl/internal/peek_utf8.hpp | 134 +- .../external/pegtl/internal/pegtl_string.hpp | 162 +- .../tao/json/external/pegtl/internal/plus.hpp | 68 +- .../json/external/pegtl/internal/raise.hpp | 64 +- .../json/external/pegtl/internal/range.hpp | 71 +- .../json/external/pegtl/internal/ranges.hpp | 143 +- .../external/pegtl/internal/read_uint.hpp | 77 + .../json/external/pegtl/internal/rematch.hpp | 69 + .../tao/json/external/pegtl/internal/rep.hpp | 95 +- .../json/external/pegtl/internal/rep_min.hpp | 22 +- .../external/pegtl/internal/rep_min_max.hpp | 115 +- .../json/external/pegtl/internal/rep_opt.hpp | 62 +- .../json/external/pegtl/internal/require.hpp | 58 +- .../pegtl/internal/result_on_found.hpp | 26 +- .../pegtl/internal/rule_conjunction.hpp | 63 - .../json/external/pegtl/internal/rules.hpp | 8 +- .../tao/json/external/pegtl/internal/seq.hpp | 111 +- .../external/pegtl/internal/skip_control.hpp | 36 +- .../tao/json/external/pegtl/internal/sor.hpp | 94 +- .../tao/json/external/pegtl/internal/star.hpp | 63 +- .../external/pegtl/internal/star_must.hpp | 22 +- .../json/external/pegtl/internal/state.hpp | 94 +- .../json/external/pegtl/internal/string.hpp | 74 +- .../json/external/pegtl/internal/trivial.hpp | 42 +- .../pegtl/internal/try_catch_type.hpp | 92 +- .../json/external/pegtl/internal/until.hpp | 121 +- .../tao/json/external/pegtl/istream_input.hpp | 31 +- include/tao/json/external/pegtl/match.hpp | 73 + .../tao/json/external/pegtl/memory_input.hpp | 504 +++-- .../tao/json/external/pegtl/mmap_input.hpp | 88 +- include/tao/json/external/pegtl/normal.hpp | 126 +- include/tao/json/external/pegtl/nothing.hpp | 25 +- include/tao/json/external/pegtl/parse.hpp | 72 +- .../tao/json/external/pegtl/parse_error.hpp | 86 +- include/tao/json/external/pegtl/position.hpp | 79 +- .../tao/json/external/pegtl/read_input.hpp | 78 +- .../tao/json/external/pegtl/require_apply.hpp | 16 + .../json/external/pegtl/require_apply0.hpp | 16 + .../tao/json/external/pegtl/rewind_mode.hpp | 24 +- include/tao/json/external/pegtl/rules.hpp | 112 +- .../tao/json/external/pegtl/string_input.hpp | 71 +- .../tao/json/external/pegtl/tracking_mode.hpp | 22 +- include/tao/json/external/pegtl/uint16.hpp | 62 + include/tao/json/external/pegtl/uint32.hpp | 62 + include/tao/json/external/pegtl/uint64.hpp | 63 + include/tao/json/external/pegtl/uint8.hpp | 36 + include/tao/json/external/pegtl/utf16.hpp | 59 +- include/tao/json/external/pegtl/utf32.hpp | 59 +- include/tao/json/external/pegtl/utf8.hpp | 40 +- include/tao/json/external/pegtl/version.hpp | 14 +- include/tao/json/external/ryu.hpp | 1216 +++++++++++ include/tao/json/external/string_view.hpp | 565 ----- include/tao/json/forward.hpp | 44 + include/tao/json/from_file.hpp | 32 + include/tao/json/from_input.hpp | 32 + include/tao/json/from_stream.hpp | 64 +- include/tao/json/from_string.hpp | 48 +- include/tao/json/internal/action.hpp | 476 ++-- include/tao/json/internal/base64.hpp | 94 +- include/tao/json/internal/base64url.hpp | 90 +- include/tao/json/internal/control.hpp | 53 - include/tao/json/internal/endian.hpp | 86 +- include/tao/json/internal/endian_gcc.hpp | 364 ++-- include/tao/json/internal/endian_win.hpp | 168 +- include/tao/json/internal/errors.hpp | 151 +- include/tao/json/internal/escape.hpp | 124 +- include/tao/json/internal/format.hpp | 59 + include/tao/json/internal/get_by_enum.hpp | 172 -- include/tao/json/internal/grammar.hpp | 397 ++-- include/tao/json/internal/hexdump.hpp | 50 +- include/tao/json/internal/identity.hpp | 20 +- include/tao/json/internal/jaxn/action.hpp | 335 --- .../tao/json/internal/jaxn/binary_state.hpp | 43 - .../json/internal/jaxn/bunescape_action.hpp | 123 -- include/tao/json/internal/jaxn/control.hpp | 64 - include/tao/json/internal/jaxn/errors.hpp | 121 -- include/tao/json/internal/jaxn/grammar.hpp | 357 --- .../json/internal/jaxn/unescape_action.hpp | 38 - include/tao/json/internal/key_state.hpp | 37 - include/tao/json/internal/number_state.hpp | 118 +- include/tao/json/internal/number_traits.hpp | 267 +++ include/tao/json/internal/pair.hpp | 42 + include/tao/json/internal/parse_util.hpp | 112 + include/tao/json/internal/sha256.hpp | 376 ++-- include/tao/json/internal/single.hpp | 40 + include/tao/json/internal/string_state.hpp | 37 - include/tao/json/internal/string_t.hpp | 35 + include/tao/json/internal/throw.hpp | 24 - include/tao/json/internal/type_traits.hpp | 113 + include/tao/json/internal/unescape_action.hpp | 30 +- include/tao/json/internal/uri_fragment.hpp | 328 ++- include/tao/json/internal/value_union.hpp | 62 - include/tao/json/jaxn.hpp | 11 +- include/tao/json/jaxn/consume_file.hpp | 34 + include/tao/json/jaxn/consume_string.hpp | 32 + include/tao/json/jaxn/events/from_file.hpp | 28 + include/tao/json/jaxn/events/from_input.hpp | 45 + include/tao/json/jaxn/events/from_stream.hpp | 33 + include/tao/json/jaxn/events/from_string.hpp | 39 + .../tao/json/jaxn/events/to_pretty_stream.hpp | 69 + include/tao/json/jaxn/events/to_stream.hpp | 67 + include/tao/json/jaxn/events/to_string.hpp | 33 + include/tao/json/jaxn/from_file.hpp | 33 + include/tao/json/jaxn/from_input.hpp | 33 + include/tao/json/jaxn/from_stream.hpp | 74 +- include/tao/json/jaxn/from_string.hpp | 62 +- include/tao/json/jaxn/internal/action.hpp | 355 +++ .../json/jaxn/internal/bunescape_action.hpp | 114 + include/tao/json/jaxn/internal/errors.hpp | 108 + include/tao/json/jaxn/internal/grammar.hpp | 375 ++++ include/tao/json/jaxn/internal/integer.hpp | 256 +++ .../json/jaxn/internal/unescape_action.hpp | 28 + include/tao/json/jaxn/is_identifier.hpp | 40 +- include/tao/json/jaxn/parse_file.hpp | 41 - include/tao/json/jaxn/parts_parser.hpp | 263 +++ include/tao/json/jaxn/to_stream.hpp | 48 +- include/tao/json/jaxn/to_string.hpp | 48 +- include/tao/json/message_extension.hpp | 49 + include/tao/json/msgpack.hpp | 11 +- include/tao/json/msgpack/consume_file.hpp | 34 + include/tao/json/msgpack/consume_string.hpp | 32 + include/tao/json/msgpack/events/from_file.hpp | 27 + .../tao/json/msgpack/events/from_input.hpp | 43 + .../tao/json/msgpack/events/from_string.hpp | 37 + include/tao/json/msgpack/events/to_stream.hpp | 214 ++ include/tao/json/msgpack/events/to_string.hpp | 31 + include/tao/json/msgpack/from_file.hpp | 33 + include/tao/json/msgpack/from_input.hpp | 33 + include/tao/json/msgpack/from_string.hpp | 46 +- include/tao/json/msgpack/internal/format.hpp | 57 + include/tao/json/msgpack/internal/grammar.hpp | 249 +++ include/tao/json/msgpack/parts_parser.hpp | 311 +++ include/tao/json/msgpack/to_stream.hpp | 30 +- include/tao/json/msgpack/to_string.hpp | 32 +- include/tao/json/operators.hpp | 494 +++++ include/tao/json/pair.hpp | 66 - include/tao/json/parse_file.hpp | 36 - include/tao/json/parts_parser.hpp | 306 +++ include/tao/json/patch.hpp | 109 - include/tao/json/pointer.hpp | 577 +++-- include/tao/json/produce.hpp | 61 + include/tao/json/reference.hpp | 122 -- include/tao/json/schema.hpp | 1786 ---------------- include/tao/json/self_contained.hpp | 236 +- include/tao/json/single.hpp | 49 - include/tao/json/span.hpp | 568 +++++ include/tao/json/stream.hpp | 45 +- include/tao/json/to_stream.hpp | 48 +- include/tao/json/to_string.hpp | 26 +- include/tao/json/traits.hpp | 1738 +++++++-------- include/tao/json/type.hpp | 209 +- include/tao/json/ubjson.hpp | 11 +- include/tao/json/ubjson/consume_file.hpp | 34 + include/tao/json/ubjson/consume_string.hpp | 32 + include/tao/json/ubjson/events/from_file.hpp | 27 + include/tao/json/ubjson/events/from_input.hpp | 43 + .../tao/json/ubjson/events/from_string.hpp | 37 + include/tao/json/ubjson/events/to_stream.hpp | 174 ++ include/tao/json/ubjson/events/to_string.hpp | 31 + include/tao/json/ubjson/from_file.hpp | 33 + include/tao/json/ubjson/from_input.hpp | 33 + include/tao/json/ubjson/from_string.hpp | 46 +- include/tao/json/ubjson/internal/grammar.hpp | 413 ++++ include/tao/json/ubjson/internal/marker.hpp | 46 + include/tao/json/ubjson/parts_parser.hpp | 393 ++++ include/tao/json/ubjson/to_stream.hpp | 30 +- include/tao/json/ubjson/to_string.hpp | 32 +- include/tao/json/utf8.hpp | 57 + include/tao/json/value.hpp | 1905 +---------------- 439 files changed, 30917 insertions(+), 25242 deletions(-) create mode 100644 include/tao/json/basic_value.hpp create mode 100644 include/tao/json/binary_view.hpp create mode 100644 include/tao/json/binding.hpp create mode 100644 include/tao/json/binding/constant.hpp create mode 100644 include/tao/json/binding/element.hpp create mode 100644 include/tao/json/binding/factory.hpp create mode 100644 include/tao/json/binding/for_nothing_value.hpp create mode 100644 include/tao/json/binding/for_unknown_key.hpp create mode 100644 include/tao/json/binding/inherit.hpp create mode 100644 include/tao/json/binding/internal/array.hpp create mode 100644 include/tao/json/binding/internal/inherit.hpp create mode 100644 include/tao/json/binding/internal/object.hpp create mode 100644 include/tao/json/binding/internal/type_key.hpp create mode 100644 include/tao/json/binding/member.hpp create mode 100644 include/tao/json/binding/member_kind.hpp create mode 100644 include/tao/json/binding/versions.hpp delete mode 100644 include/tao/json/byte_view.hpp create mode 100644 include/tao/json/cbor/consume_file.hpp create mode 100644 include/tao/json/cbor/consume_string.hpp create mode 100644 include/tao/json/cbor/events/from_file.hpp create mode 100644 include/tao/json/cbor/events/from_input.hpp create mode 100644 include/tao/json/cbor/events/from_string.hpp create mode 100644 include/tao/json/cbor/events/to_stream.hpp create mode 100644 include/tao/json/cbor/events/to_string.hpp create mode 100644 include/tao/json/cbor/from_file.hpp create mode 100644 include/tao/json/cbor/from_input.hpp create mode 100644 include/tao/json/cbor/internal/grammar.hpp create mode 100644 include/tao/json/cbor/internal/major.hpp create mode 100644 include/tao/json/cbor/parts_parser.hpp create mode 100644 include/tao/json/consume.hpp create mode 100644 include/tao/json/consume_file.hpp create mode 100644 include/tao/json/consume_string.hpp create mode 100644 include/tao/json/contrib/array_traits.hpp create mode 100644 include/tao/json/contrib/deque_traits.hpp create mode 100644 include/tao/json/contrib/diff.hpp create mode 100644 include/tao/json/contrib/get.hpp create mode 100644 include/tao/json/contrib/internal/array_traits.hpp create mode 100644 include/tao/json/contrib/internal/indirect_traits.hpp create mode 100644 include/tao/json/contrib/internal/object_traits.hpp create mode 100644 include/tao/json/contrib/internal/type_traits.hpp create mode 100644 include/tao/json/contrib/list_traits.hpp create mode 100644 include/tao/json/contrib/map_traits.hpp create mode 100644 include/tao/json/contrib/multimap_traits.hpp create mode 100644 include/tao/json/contrib/multiset_traits.hpp create mode 100644 include/tao/json/contrib/pair_traits.hpp create mode 100644 include/tao/json/contrib/patch.hpp create mode 100644 include/tao/json/contrib/pointer_traits.hpp create mode 100644 include/tao/json/contrib/position.hpp create mode 100644 include/tao/json/contrib/reference.hpp create mode 100644 include/tao/json/contrib/schema.hpp create mode 100644 include/tao/json/contrib/set_traits.hpp create mode 100644 include/tao/json/contrib/shared_ptr_traits.hpp create mode 100644 include/tao/json/contrib/traits.hpp create mode 100644 include/tao/json/contrib/tuple_traits.hpp create mode 100644 include/tao/json/contrib/unique_ptr_traits.hpp create mode 100644 include/tao/json/contrib/unordered_map_traits.hpp create mode 100644 include/tao/json/contrib/unordered_set_traits.hpp create mode 100644 include/tao/json/contrib/vector_bool_traits.hpp create mode 100644 include/tao/json/contrib/vector_traits.hpp create mode 100644 include/tao/json/events.hpp delete mode 100644 include/tao/json/events/cbor/from_string.hpp delete mode 100644 include/tao/json/events/cbor/grammar.hpp delete mode 100644 include/tao/json/events/cbor/major.hpp delete mode 100644 include/tao/json/events/cbor/to_stream.hpp delete mode 100644 include/tao/json/events/cbor/to_string.hpp create mode 100644 include/tao/json/events/from_file.hpp create mode 100644 include/tao/json/events/from_input.hpp create mode 100644 include/tao/json/events/invalid_string_to_binary.hpp create mode 100644 include/tao/json/events/invalid_string_to_exception.hpp create mode 100644 include/tao/json/events/invalid_string_to_hex.hpp delete mode 100644 include/tao/json/events/jaxn/from_stream.hpp delete mode 100644 include/tao/json/events/jaxn/from_string.hpp delete mode 100644 include/tao/json/events/jaxn/parse_file.hpp delete mode 100644 include/tao/json/events/jaxn/to_pretty_stream.hpp delete mode 100644 include/tao/json/events/jaxn/to_stream.hpp create mode 100644 include/tao/json/events/limit_nesting_depth.hpp create mode 100644 include/tao/json/events/limit_value_count.hpp delete mode 100644 include/tao/json/events/msgpack/from_string.hpp delete mode 100644 include/tao/json/events/msgpack/grammar.hpp delete mode 100644 include/tao/json/events/msgpack/to_stream.hpp delete mode 100644 include/tao/json/events/msgpack/to_string.hpp delete mode 100644 include/tao/json/events/parse_file.hpp create mode 100644 include/tao/json/events/produce.hpp create mode 100644 include/tao/json/events/statistics.hpp delete mode 100644 include/tao/json/events/ubjson/from_string.hpp delete mode 100644 include/tao/json/events/ubjson/grammar.hpp delete mode 100644 include/tao/json/events/ubjson/to_stream.hpp delete mode 100644 include/tao/json/events/ubjson/to_string.hpp create mode 100644 include/tao/json/events/virtual_base.hpp create mode 100644 include/tao/json/events/virtual_ref.hpp delete mode 100644 include/tao/json/external/akrzemi1/CMakeLists.txt delete mode 100644 include/tao/json/external/akrzemi1/LICENSE delete mode 100644 include/tao/json/external/akrzemi1/LICENSE_1_0.txt delete mode 100644 include/tao/json/external/akrzemi1/README.md delete mode 100644 include/tao/json/external/akrzemi1/copyright.txt delete mode 100644 include/tao/json/external/akrzemi1/optional.hpp delete mode 100644 include/tao/json/external/akrzemi1/test_optional.cpp delete mode 100644 include/tao/json/external/akrzemi1/test_type_traits.cpp delete mode 100644 include/tao/json/external/byte.hpp create mode 100644 include/tao/json/external/itoa.hpp delete mode 100644 include/tao/json/external/operators.hpp delete mode 100644 include/tao/json/external/optional.hpp create mode 100644 include/tao/json/external/pegtl/change_action.hpp create mode 100644 include/tao/json/external/pegtl/change_action_and_state.hpp create mode 100644 include/tao/json/external/pegtl/change_action_and_states.hpp create mode 100644 include/tao/json/external/pegtl/change_control.hpp create mode 100644 include/tao/json/external/pegtl/change_state.hpp create mode 100644 include/tao/json/external/pegtl/change_states.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/changes.hpp create mode 100644 include/tao/json/external/pegtl/contrib/icu/internal.hpp create mode 100644 include/tao/json/external/pegtl/contrib/icu/utf16.hpp create mode 100644 include/tao/json/external/pegtl/contrib/icu/utf32.hpp create mode 100644 include/tao/json/external/pegtl/contrib/icu/utf8.hpp create mode 100644 include/tao/json/external/pegtl/contrib/if_then.hpp create mode 100644 include/tao/json/external/pegtl/contrib/integer.hpp create mode 100644 include/tao/json/external/pegtl/contrib/json_pointer.hpp create mode 100644 include/tao/json/external/pegtl/contrib/parse_tree_to_dot.hpp create mode 100644 include/tao/json/external/pegtl/contrib/remove_first_state.hpp create mode 100644 include/tao/json/external/pegtl/contrib/rep_string.hpp create mode 100644 include/tao/json/external/pegtl/disable_action.hpp create mode 100644 include/tao/json/external/pegtl/discard_input.hpp create mode 100644 include/tao/json/external/pegtl/discard_input_on_failure.hpp create mode 100644 include/tao/json/external/pegtl/discard_input_on_success.hpp create mode 100644 include/tao/json/external/pegtl/enable_action.hpp create mode 100644 include/tao/json/external/pegtl/eol_pair.hpp delete mode 100644 include/tao/json/external/pegtl/input_error.hpp create mode 100644 include/tao/json/external/pegtl/internal/always_false.hpp create mode 100644 include/tao/json/external/pegtl/internal/apply0_single.hpp create mode 100644 include/tao/json/external/pegtl/internal/apply_single.hpp create mode 100644 include/tao/json/external/pegtl/internal/bump.hpp delete mode 100644 include/tao/json/external/pegtl/internal/bump_impl.hpp delete mode 100644 include/tao/json/external/pegtl/internal/demangle_cxxabi.hpp delete mode 100644 include/tao/json/external/pegtl/internal/demangle_nop.hpp delete mode 100644 include/tao/json/external/pegtl/internal/demangle_sanitise.hpp create mode 100644 include/tao/json/external/pegtl/internal/endian.hpp create mode 100644 include/tao/json/external/pegtl/internal/endian_gcc.hpp create mode 100644 include/tao/json/external/pegtl/internal/endian_win.hpp delete mode 100644 include/tao/json/external/pegtl/internal/file_mapper.hpp create mode 100644 include/tao/json/external/pegtl/internal/file_mapper_posix.hpp create mode 100644 include/tao/json/external/pegtl/internal/file_mapper_win32.hpp create mode 100644 include/tao/json/external/pegtl/internal/has_match.hpp delete mode 100644 include/tao/json/external/pegtl/internal/integer_sequence.hpp delete mode 100644 include/tao/json/external/pegtl/internal/minus.hpp create mode 100644 include/tao/json/external/pegtl/internal/missing_apply.hpp create mode 100644 include/tao/json/external/pegtl/internal/missing_apply0.hpp create mode 100644 include/tao/json/external/pegtl/internal/peek_mask_uint.hpp create mode 100644 include/tao/json/external/pegtl/internal/peek_mask_uint8.hpp create mode 100644 include/tao/json/external/pegtl/internal/peek_uint.hpp create mode 100644 include/tao/json/external/pegtl/internal/peek_uint8.hpp create mode 100644 include/tao/json/external/pegtl/internal/read_uint.hpp create mode 100644 include/tao/json/external/pegtl/internal/rematch.hpp delete mode 100644 include/tao/json/external/pegtl/internal/rule_conjunction.hpp create mode 100644 include/tao/json/external/pegtl/match.hpp create mode 100644 include/tao/json/external/pegtl/require_apply.hpp create mode 100644 include/tao/json/external/pegtl/require_apply0.hpp create mode 100644 include/tao/json/external/pegtl/uint16.hpp create mode 100644 include/tao/json/external/pegtl/uint32.hpp create mode 100644 include/tao/json/external/pegtl/uint64.hpp create mode 100644 include/tao/json/external/pegtl/uint8.hpp create mode 100644 include/tao/json/external/ryu.hpp delete mode 100644 include/tao/json/external/string_view.hpp create mode 100644 include/tao/json/forward.hpp create mode 100644 include/tao/json/from_file.hpp create mode 100644 include/tao/json/from_input.hpp delete mode 100644 include/tao/json/internal/control.hpp create mode 100644 include/tao/json/internal/format.hpp delete mode 100644 include/tao/json/internal/get_by_enum.hpp delete mode 100644 include/tao/json/internal/jaxn/action.hpp delete mode 100644 include/tao/json/internal/jaxn/binary_state.hpp delete mode 100644 include/tao/json/internal/jaxn/bunescape_action.hpp delete mode 100644 include/tao/json/internal/jaxn/control.hpp delete mode 100644 include/tao/json/internal/jaxn/errors.hpp delete mode 100644 include/tao/json/internal/jaxn/grammar.hpp delete mode 100644 include/tao/json/internal/jaxn/unescape_action.hpp delete mode 100644 include/tao/json/internal/key_state.hpp create mode 100644 include/tao/json/internal/number_traits.hpp create mode 100644 include/tao/json/internal/pair.hpp create mode 100644 include/tao/json/internal/parse_util.hpp create mode 100644 include/tao/json/internal/single.hpp delete mode 100644 include/tao/json/internal/string_state.hpp create mode 100644 include/tao/json/internal/string_t.hpp delete mode 100644 include/tao/json/internal/throw.hpp create mode 100644 include/tao/json/internal/type_traits.hpp delete mode 100644 include/tao/json/internal/value_union.hpp create mode 100644 include/tao/json/jaxn/consume_file.hpp create mode 100644 include/tao/json/jaxn/consume_string.hpp create mode 100644 include/tao/json/jaxn/events/from_file.hpp create mode 100644 include/tao/json/jaxn/events/from_input.hpp create mode 100644 include/tao/json/jaxn/events/from_stream.hpp create mode 100644 include/tao/json/jaxn/events/from_string.hpp create mode 100644 include/tao/json/jaxn/events/to_pretty_stream.hpp create mode 100644 include/tao/json/jaxn/events/to_stream.hpp create mode 100644 include/tao/json/jaxn/events/to_string.hpp create mode 100644 include/tao/json/jaxn/from_file.hpp create mode 100644 include/tao/json/jaxn/from_input.hpp create mode 100644 include/tao/json/jaxn/internal/action.hpp create mode 100644 include/tao/json/jaxn/internal/bunescape_action.hpp create mode 100644 include/tao/json/jaxn/internal/errors.hpp create mode 100644 include/tao/json/jaxn/internal/grammar.hpp create mode 100644 include/tao/json/jaxn/internal/integer.hpp create mode 100644 include/tao/json/jaxn/internal/unescape_action.hpp delete mode 100644 include/tao/json/jaxn/parse_file.hpp create mode 100644 include/tao/json/jaxn/parts_parser.hpp create mode 100644 include/tao/json/message_extension.hpp create mode 100644 include/tao/json/msgpack/consume_file.hpp create mode 100644 include/tao/json/msgpack/consume_string.hpp create mode 100644 include/tao/json/msgpack/events/from_file.hpp create mode 100644 include/tao/json/msgpack/events/from_input.hpp create mode 100644 include/tao/json/msgpack/events/from_string.hpp create mode 100644 include/tao/json/msgpack/events/to_stream.hpp create mode 100644 include/tao/json/msgpack/events/to_string.hpp create mode 100644 include/tao/json/msgpack/from_file.hpp create mode 100644 include/tao/json/msgpack/from_input.hpp create mode 100644 include/tao/json/msgpack/internal/format.hpp create mode 100644 include/tao/json/msgpack/internal/grammar.hpp create mode 100644 include/tao/json/msgpack/parts_parser.hpp create mode 100644 include/tao/json/operators.hpp delete mode 100644 include/tao/json/pair.hpp delete mode 100644 include/tao/json/parse_file.hpp create mode 100644 include/tao/json/parts_parser.hpp delete mode 100644 include/tao/json/patch.hpp create mode 100644 include/tao/json/produce.hpp delete mode 100644 include/tao/json/reference.hpp delete mode 100644 include/tao/json/schema.hpp delete mode 100644 include/tao/json/single.hpp create mode 100644 include/tao/json/span.hpp create mode 100644 include/tao/json/ubjson/consume_file.hpp create mode 100644 include/tao/json/ubjson/consume_string.hpp create mode 100644 include/tao/json/ubjson/events/from_file.hpp create mode 100644 include/tao/json/ubjson/events/from_input.hpp create mode 100644 include/tao/json/ubjson/events/from_string.hpp create mode 100644 include/tao/json/ubjson/events/to_stream.hpp create mode 100644 include/tao/json/ubjson/events/to_string.hpp create mode 100644 include/tao/json/ubjson/from_file.hpp create mode 100644 include/tao/json/ubjson/from_input.hpp create mode 100644 include/tao/json/ubjson/internal/grammar.hpp create mode 100644 include/tao/json/ubjson/internal/marker.hpp create mode 100644 include/tao/json/ubjson/parts_parser.hpp create mode 100644 include/tao/json/utf8.hpp diff --git a/include/tao/json.hpp b/include/tao/json.hpp index ca505a46..716c976e 100644 --- a/include/tao/json.hpp +++ b/include/tao/json.hpp @@ -1,70 +1,45 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_JSON_HPP -#define TAOCPP_JSON_INCLUDE_JSON_HPP +#ifndef TAO_JSON_HPP +#define TAO_JSON_HPP -// JSON Value +// Value Class #include "json/value.hpp" -// Events producers -#include "json/events/from_stream.hpp" -#include "json/events/from_string.hpp" -#include "json/events/from_value.hpp" -#include "json/events/parse_file.hpp" - -// Events consumers -#include "json/events/to_pretty_stream.hpp" -#include "json/events/to_stream.hpp" -#include "json/events/to_string.hpp" -#include "json/events/to_value.hpp" - -// Events transformer -#include "json/events/binary_to_base64.hpp" -#include "json/events/binary_to_base64url.hpp" -#include "json/events/binary_to_exception.hpp" -#include "json/events/binary_to_hex.hpp" -#include "json/events/key_camel_case_to_snake_case.hpp" -#include "json/events/key_snake_case_to_camel_case.hpp" -#include "json/events/non_finite_to_exception.hpp" -#include "json/events/non_finite_to_null.hpp" -#include "json/events/non_finite_to_string.hpp" -#include "json/events/prefer_signed.hpp" -#include "json/events/prefer_unsigned.hpp" - -// Events other -#include "json/events/debug.hpp" -#include "json/events/discard.hpp" -#include "json/events/hash.hpp" -#include "json/events/tee.hpp" -#include "json/events/validate_event_order.hpp" -#include "json/events/validate_keys.hpp" - -// Value producers +// Value Reading +#include "json/from_file.hpp" +#include "json/from_input.hpp" #include "json/from_stream.hpp" #include "json/from_string.hpp" -#include "json/parse_file.hpp" +#include "json/parts_parser.hpp" -// Value writers +// Value Writing #include "json/stream.hpp" // operator<< #include "json/to_stream.hpp" #include "json/to_string.hpp" -// Value support -#include "json/patch.hpp" +// Value Support +#include "json/operators.hpp" #include "json/self_contained.hpp" -//#include "json/diff.hpp" -#include "json/schema.hpp" -// Relaxed JSON -#include "json/jaxn.hpp" +// Custom Types +#include "json/binding.hpp" +#include "json/consume.hpp" +#include "json/consume_file.hpp" +#include "json/consume_string.hpp" +#include "json/produce.hpp" -// Binary literals +// Binary Literals #include "json/binary.hpp" -// Binary formats +// Other Formats #include "json/cbor.hpp" +#include "json/jaxn.hpp" #include "json/msgpack.hpp" #include "json/ubjson.hpp" +// Events Implementations +#include "json/events.hpp" + #endif diff --git a/include/tao/json/basic_value.hpp b/include/tao/json/basic_value.hpp new file mode 100644 index 00000000..612bc903 --- /dev/null +++ b/include/tao/json/basic_value.hpp @@ -0,0 +1,941 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_BASIC_VALUE_HPP +#define TAO_JSON_BASIC_VALUE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "events/virtual_base.hpp" + +#include "internal/escape.hpp" +#include "internal/format.hpp" +#include "internal/identity.hpp" +#include "internal/pair.hpp" +#include "internal/single.hpp" +#include "internal/type_traits.hpp" + +#include "binary.hpp" +#include "binary_view.hpp" +#include "forward.hpp" +#include "message_extension.hpp" +#include "pointer.hpp" +#include "type.hpp" + +namespace tao::json +{ + template< template< typename... > class Traits > + class basic_value + : public Traits< void >::template public_base< basic_value< Traits > > + { + public: + using public_base_t = typename Traits< void >::template public_base< basic_value< Traits > >; + + static_assert( std::is_nothrow_destructible_v< public_base_t > ); + + using array_t = std::vector< basic_value >; + using object_t = std::map< std::string, basic_value, std::less<> >; + + private: + using variant_t = std::variant< uninitialized_t, + null_t, + bool, + std::int64_t, + std::uint64_t, + double, + std::string, + std::string_view, + tao::binary, + tao::binary_view, + array_t, + object_t, + const basic_value*, + internal::opaque_ptr_t >; + + static_assert( std::is_nothrow_destructible_v< variant_t > ); + + variant_t m_variant; + + public: + basic_value() = default; + + basic_value( const basic_value& r ) = default; + basic_value( basic_value&& r ) = default; + +#if( __cplusplus > 201703L ) + + template< typename T, + typename D = std::decay_t< T >, + typename = decltype( Traits< D >::assign( std::declval< basic_value& >(), std::declval< T&& >() ) ) > + explicit( !internal::enable_implicit_constructor< Traits, D > ) basic_value( T&& v, public_base_t b = public_base_t() ) noexcept( noexcept( Traits< D >::assign( std::declval< basic_value& >(), std::forward< T >( v ) ) ) && std::is_nothrow_move_assignable_v< public_base_t > ) + : public_base_t( std::move( b ) ) + { + Traits< D >::assign( *this, std::forward< T >( v ) ); + } + +#else + + template< typename T, + typename D = std::decay_t< T >, + typename = std::enable_if_t< internal::enable_implicit_constructor< Traits, D > >, + typename = decltype( Traits< D >::assign( std::declval< basic_value& >(), std::declval< T&& >() ) ) > + basic_value( T&& v, public_base_t b = public_base_t() ) noexcept( noexcept( Traits< D >::assign( std::declval< basic_value& >(), std::forward< T >( v ) ) ) && std::is_nothrow_move_assignable_v< public_base_t > ) + : public_base_t( std::move( b ) ) + { + Traits< D >::assign( *this, std::forward< T >( v ) ); + } + + template< typename T, + typename D = std::decay_t< T >, + typename = std::enable_if_t< !internal::enable_implicit_constructor< Traits, D > >, + typename = decltype( Traits< D >::assign( std::declval< basic_value& >(), std::declval< T&& >() ) ), + int = 0 > + explicit basic_value( T&& v, public_base_t b = public_base_t() ) noexcept( noexcept( Traits< D >::assign( std::declval< basic_value& >(), std::forward< T >( v ) ) ) && std::is_nothrow_move_assignable_v< public_base_t > ) + : public_base_t( std::move( b ) ) + { + Traits< D >::assign( *this, std::forward< T >( v ) ); + } + +#endif + + basic_value( std::initializer_list< internal::pair< Traits > >&& l, public_base_t b = public_base_t() ) + : public_base_t( std::move( b ) ) + { + assign( std::move( l ) ); + } + + basic_value( const std::initializer_list< internal::pair< Traits > >& l, public_base_t b = public_base_t() ) + : public_base_t( std::move( b ) ) + { + assign( l ); + } + + basic_value( std::initializer_list< internal::pair< Traits > >& l, public_base_t b = public_base_t() ) + : basic_value( static_cast< const std::initializer_list< internal::pair< Traits > >& >( l ), std::move( b ) ) + {} + + ~basic_value() = default; + + [[nodiscard]] static basic_value array( std::initializer_list< internal::single< Traits > >&& l, public_base_t b = public_base_t() ) + { + basic_value v( uninitialized, std::move( b ) ); + v.append( std::move( l ) ); + return v; + } + + [[nodiscard]] static basic_value array( const std::initializer_list< internal::single< Traits > >& l, public_base_t b = public_base_t() ) + { + basic_value v( uninitialized, std::move( b ) ); + v.append( l ); + return v; + } + + [[nodiscard]] static basic_value object( std::initializer_list< internal::pair< Traits > >&& l, public_base_t b = public_base_t() ) + { + basic_value v( uninitialized, std::move( b ) ); + v.insert( std::move( l ) ); + return v; + } + + [[nodiscard]] static basic_value object( const std::initializer_list< internal::pair< Traits > >& l, public_base_t b = public_base_t() ) + { + basic_value v( uninitialized, std::move( b ) ); + v.insert( l ); + return v; + } + + basic_value& operator=( basic_value v ) noexcept( std::is_nothrow_move_assignable_v< variant_t >&& std::is_nothrow_move_assignable_v< public_base_t > ) + { + m_variant = std::move( v.m_variant ); + public_base_t::operator=( static_cast< public_base_t&& >( v ) ); + return *this; + } + + [[nodiscard]] public_base_t& public_base() noexcept + { + return static_cast< public_base_t& >( *this ); + } + + [[nodiscard]] const public_base_t& public_base() const noexcept + { + return static_cast< const public_base_t& >( *this ); + } + + [[nodiscard]] json::type type() const noexcept + { + return static_cast< json::type >( m_variant.index() ); + } + + [[nodiscard]] explicit operator bool() const noexcept + { + return !is_uninitialized(); + } + + [[nodiscard]] bool is_uninitialized() const noexcept + { + return std::holds_alternative< uninitialized_t >( m_variant ); + } + + [[nodiscard]] bool is_null() const noexcept + { + return std::holds_alternative< null_t >( m_variant ); + } + + [[nodiscard]] bool is_boolean() const noexcept + { + return std::holds_alternative< bool >( m_variant ); + } + + [[nodiscard]] bool is_signed() const noexcept + { + return std::holds_alternative< std::int64_t >( m_variant ); + } + + [[nodiscard]] bool is_unsigned() const noexcept + { + return std::holds_alternative< std::uint64_t >( m_variant ); + } + + [[nodiscard]] bool is_integer() const noexcept + { + return is_signed() || is_unsigned(); + } + + [[nodiscard]] bool is_double() const noexcept + { + return std::holds_alternative< double >( m_variant ); + } + + [[nodiscard]] bool is_number() const noexcept + { + return is_integer() || is_double(); + } + + [[nodiscard]] bool is_string() const noexcept + { + return std::holds_alternative< std::string >( m_variant ); + } + + [[nodiscard]] bool is_string_view() const noexcept + { + return std::holds_alternative< std::string_view >( m_variant ); + } + + [[nodiscard]] bool is_string_type() const noexcept + { + return is_string() || is_string_view(); + } + + [[nodiscard]] bool is_binary() const noexcept + { + return std::holds_alternative< binary >( m_variant ); + } + + [[nodiscard]] bool is_binary_view() const noexcept + { + return std::holds_alternative< tao::binary_view >( m_variant ); + } + + [[nodiscard]] bool is_binary_type() const noexcept + { + return is_binary() || is_binary_view(); + } + + [[nodiscard]] bool is_array() const noexcept + { + return std::holds_alternative< array_t >( m_variant ); + } + + [[nodiscard]] bool is_object() const noexcept + { + return std::holds_alternative< object_t >( m_variant ); + } + + [[nodiscard]] bool is_value_ptr() const noexcept + { + return std::holds_alternative< const basic_value* >( m_variant ); + } + + [[nodiscard]] bool is_opaque_ptr() const noexcept + { + return std::holds_alternative< internal::opaque_ptr_t >( m_variant ); + } + + [[nodiscard]] bool get_boolean() const + { + return std::get< bool >( m_variant ); + } + + [[nodiscard]] std::int64_t get_signed() const + { + return std::get< std::int64_t >( m_variant ); + } + + [[nodiscard]] std::uint64_t get_unsigned() const + { + return std::get< std::uint64_t >( m_variant ); + } + + [[nodiscard]] double get_double() const + { + return std::get< double >( m_variant ); + } + + [[nodiscard]] std::string& get_string() + { + return std::get< std::string >( m_variant ); + } + + [[nodiscard]] const std::string& get_string() const + { + return std::get< std::string >( m_variant ); + } + + [[nodiscard]] std::string_view get_string_view() const + { + return std::get< std::string_view >( m_variant ); + } + + [[nodiscard]] std::string_view get_string_type() const + { + return is_string() ? get_string() : get_string_view(); + } + + [[nodiscard]] binary& get_binary() + { + return std::get< binary >( m_variant ); + } + + [[nodiscard]] const binary& get_binary() const + { + return std::get< binary >( m_variant ); + } + + [[nodiscard]] tao::binary_view get_binary_view() const + { + return std::get< tao::binary_view >( m_variant ); + } + + [[nodiscard]] tao::binary_view get_binary_type() const + { + return is_binary() ? get_binary() : get_binary_view(); + } + + [[nodiscard]] array_t& get_array() + { + return std::get< array_t >( m_variant ); + } + + [[nodiscard]] const array_t& get_array() const + { + return std::get< array_t >( m_variant ); + } + + [[nodiscard]] object_t& get_object() + { + return std::get< object_t >( m_variant ); + } + + [[nodiscard]] const object_t& get_object() const + { + return std::get< object_t >( m_variant ); + } + + [[nodiscard]] const basic_value* get_value_ptr() const + { + return std::get< const basic_value* >( m_variant ); + } + + [[nodiscard]] internal::opaque_ptr_t get_opaque_ptr() const + { + return std::get< internal::opaque_ptr_t >( m_variant ); + } + + private: + void throw_duplicate_key_exception( const std::string_view k ) const + { + throw std::runtime_error( internal::format( "duplicate JSON object key \"", internal::escape( k ), '"', json::message_extension( *this ) ) ); + } + + void throw_index_out_of_bound_exception( const std::size_t i ) const + { + throw std::out_of_range( internal::format( "JSON array index '", i, "' out of bound '", get_array().size(), '\'', json::message_extension( *this ) ) ); + } + + void throw_key_not_found_exception( const std::string_view k ) const + { + throw std::out_of_range( internal::format( "JSON object key \"", internal::escape( k ), "\" not found", json::message_extension( *this ) ) ); + } + + public: + void set_uninitialized() noexcept + { + m_variant = uninitialized; + } + + void set_null() noexcept + { + m_variant = null; + } + + void set_boolean( const bool b ) noexcept + { + m_variant = b; + } + + void set_signed( const std::int64_t i ) noexcept + { + m_variant = i; + } + + void set_unsigned( const std::uint64_t u ) noexcept + { + m_variant = u; + } + + void set_double( const double d ) noexcept + { + m_variant = d; + } + + template< typename... Ts > + std::string& emplace_string( Ts&&... ts ) noexcept( noexcept( std::string( std::forward< Ts >( ts )... ) ) ) + { + return m_variant.template emplace< std::string >( std::forward< Ts >( ts )... ); + } + + void set_string( const std::string& s ) + { + m_variant = s; + } + + void set_string( std::string&& s ) noexcept + { + m_variant = std::move( s ); + } + + void set_string_view( const std::string_view sv ) noexcept + { + m_variant = sv; + } + + template< typename... Ts > + binary& emplace_binary( Ts&&... ts ) noexcept( noexcept( binary( std::forward< Ts >( ts )... ) ) ) + { + return m_variant.template emplace< binary >( std::forward< Ts >( ts )... ); + } + + void set_binary( const binary& x ) + { + m_variant = x; + } + + void set_binary( binary&& x ) noexcept + { + m_variant = std::move( x ); + } + + void set_binary_view( const tao::binary_view xv ) noexcept + { + m_variant = xv; + } + + template< typename... Ts > + array_t& emplace_array( Ts&&... ts ) noexcept( noexcept( array_t( std::forward< Ts >( ts )... ) ) ) + { + return m_variant.template emplace< array_t >( std::forward< Ts >( ts )... ); + } + + void set_array( const array_t& a ) + { + m_variant = a; + } + + void set_array( array_t&& a ) noexcept( std::is_nothrow_move_assignable_v< array_t > ) + { + m_variant = std::move( a ); + } + + array_t& prepare_array() + { + return is_uninitialized() ? emplace_array() : get_array(); + } + + void push_back( const basic_value& v ) + { + prepare_array().push_back( v ); + } + + void push_back( basic_value&& v ) + { + prepare_array().push_back( std::move( v ) ); + } + + template< typename... Ts > + basic_value& emplace_back( Ts&&... ts ) + { + return prepare_array().emplace_back( std::forward< Ts >( ts )... ); + } + + template< typename... Ts > + object_t& emplace_object( Ts&&... ts ) noexcept( noexcept( object_t( std::forward< Ts >( ts )... ) ) ) + { + return m_variant.template emplace< object_t >( std::forward< Ts >( ts )... ); + } + + void set_object( const object_t& o ) + { + m_variant = o; + } + + void set_object( object_t&& o ) noexcept( std::is_nothrow_move_assignable_v< object_t > ) + { + m_variant = std::move( o ); + } + + object_t& prepare_object() + { + return is_uninitialized() ? emplace_object() : get_object(); + } + + template< typename... Ts > + auto try_emplace( Ts&&... ts ) + { + auto r = prepare_object().try_emplace( std::forward< Ts >( ts )... ); + if( !r.second ) { + throw_duplicate_key_exception( r.first->first ); + } + return r; + } + + auto insert( typename object_t::value_type&& t ) + { + return prepare_object().emplace( std::move( t ) ); + } + + auto insert( const typename object_t::value_type& t ) + { + return prepare_object().emplace( t ); + } + + void set_value_ptr( const basic_value* p ) noexcept + { + assert( p ); + m_variant = p; + } + + template< typename T > + void set_opaque_ptr( const T* data, const producer_t producer ) noexcept + { + assert( data ); + assert( producer ); + m_variant = internal::opaque_ptr_t{ data, producer }; + } + + template< typename T > + void set_opaque_ptr( const T* data ) noexcept + { + set_opaque_ptr( data, &basic_value::produce_from_opaque_ptr< T > ); + } + + template< typename T > + void assign( T&& v ) noexcept( noexcept( Traits< std::decay_t< T > >::assign( std::declval< basic_value& >(), std::forward< T >( v ) ) ) ) + { + Traits< std::decay_t< T > >::assign( *this, std::forward< T >( v ) ); + } + + template< typename T > + void assign( T&& v, public_base_t b ) noexcept( noexcept( Traits< std::decay_t< T > >::assign( std::declval< basic_value& >(), std::forward< T >( v ) ) ) && std::is_nothrow_move_assignable_v< public_base_t > ) + { + Traits< std::decay_t< T > >::assign( *this, std::forward< T >( v ) ); + public_base() = std::move( b ); + } + + void assign( std::initializer_list< internal::pair< Traits > >&& l ) + { + emplace_object(); + for( auto& e : l ) { + try_emplace( std::move( e.key ), std::move( e.value ) ); + } + } + + void assign( const std::initializer_list< internal::pair< Traits > >& l ) + { + emplace_object(); + for( const auto& e : l ) { + try_emplace( e.key, e.value ); + } + } + + void assign( std::initializer_list< internal::pair< Traits > >& l ) + { + assign( static_cast< const std::initializer_list< internal::pair< Traits > >& >( l ) ); + } + + void append( std::initializer_list< internal::single< Traits > >&& l ) + { + auto& v = prepare_array(); + v.reserve( v.size() + l.size() ); + for( auto& e : l ) { + v.push_back( std::move( e.value ) ); + } + } + + void append( const std::initializer_list< internal::single< Traits > >& l ) + { + auto& v = prepare_array(); + v.reserve( v.size() + l.size() ); + for( const auto& e : l ) { + v.push_back( e.value ); + } + } + + void insert( std::initializer_list< internal::pair< Traits > >&& l ) + { + prepare_object(); + for( auto& e : l ) { + try_emplace( std::move( e.key ), std::move( e.value ) ); + } + } + + void insert( const std::initializer_list< internal::pair< Traits > >& l ) + { + prepare_object(); + for( const auto& e : l ) { + try_emplace( e.key, e.value ); + } + } + + [[nodiscard]] const basic_value& skip_value_ptr() const noexcept + { + const basic_value* p = this; + while( p->is_value_ptr() ) { + p = p->get_value_ptr(); + assert( p ); + } + return *p; + } + + [[nodiscard]] basic_value* find( const std::size_t index ) + { + auto& a = get_array(); + return ( index < a.size() ) ? ( a.data() + index ) : nullptr; + } + + [[nodiscard]] const basic_value* find( const std::size_t index ) const + { + const auto& a = get_array(); + return ( index < a.size() ) ? ( a.data() + index ) : nullptr; + } + + template< typename Key > + [[nodiscard]] std::enable_if_t< !std::is_convertible_v< Key, std::size_t > && !std::is_convertible_v< Key, pointer >, basic_value* > find( Key&& key ) + { + auto& o = get_object(); + const auto it = o.find( std::forward< Key >( key ) ); + return ( it != o.end() ) ? ( &it->second ) : nullptr; + } + + template< typename Key > + [[nodiscard]] std::enable_if_t< !std::is_convertible_v< Key, std::size_t > && !std::is_convertible_v< Key, pointer >, const basic_value* > find( Key&& key ) const + { + const auto& o = get_object(); + const auto it = o.find( std::forward< Key >( key ) ); + return ( it != o.end() ) ? ( &it->second ) : nullptr; + } + + [[nodiscard]] basic_value* find( const pointer& k ) + { + return internal::pointer_find( this, k.begin(), k.end() ); + } + + [[nodiscard]] const basic_value* find( const pointer& k ) const + { + return internal::pointer_find( this, k.begin(), k.end() ); + } + + [[nodiscard]] basic_value& at( const std::size_t index ) + { + auto& a = get_array(); + if( index >= a.size() ) { + throw_index_out_of_bound_exception( index ); + } + return a[ index ]; + } + + [[nodiscard]] const basic_value& at( const std::size_t index ) const + { + const auto& a = get_array(); + if( index >= a.size() ) { + throw_index_out_of_bound_exception( index ); + } + return a[ index ]; + } + + template< typename Key > + [[nodiscard]] std::enable_if_t< !std::is_convertible_v< Key, std::size_t > && !std::is_convertible_v< Key, pointer >, basic_value& > at( const Key& key ) + { + auto& o = get_object(); + const auto it = o.find( key ); + if( it == o.end() ) { + throw_key_not_found_exception( key ); + } + return it->second; + } + + template< typename Key > + [[nodiscard]] std::enable_if_t< !std::is_convertible_v< Key, std::size_t > && !std::is_convertible_v< Key, pointer >, const basic_value& > at( const Key& key ) const + { + const auto& o = get_object(); + const auto it = o.find( key ); + if( it == o.end() ) { + throw_key_not_found_exception( key ); + } + return it->second; + } + + [[nodiscard]] basic_value& at( const pointer& k ) + { + return internal::pointer_at( this, k.begin(), k.end() ); + } + + [[nodiscard]] const basic_value& at( const pointer& k ) const + { + return internal::pointer_at( this, k.begin(), k.end() ); + } + + [[nodiscard]] basic_value& operator[]( const std::size_t index ) + { + return get_array()[ index ]; + } + + [[nodiscard]] const basic_value& operator[]( const std::size_t index ) const + { + return get_array()[ index ]; + } + + template< typename Key > + [[nodiscard]] std::enable_if_t< !std::is_convertible_v< Key, std::size_t > && !std::is_convertible_v< Key, pointer >, basic_value& > operator[]( Key&& key ) + { + return prepare_object()[ std::forward< Key >( key ) ]; + } + + [[nodiscard]] basic_value& operator[]( const pointer& k ) + { + if( k.empty() ) { + return *this; + } + const auto b = k.begin(); + const auto e = std::prev( k.end() ); + basic_value& v = internal::pointer_at( this, b, e ); + if( v.is_object() ) { + return v.get_object()[ e->key() ]; + } + if( v.is_array() ) { + if( e->key() == "-" ) { + v.emplace_back( null ); + return v.get_array().back(); + } + return v.at( e->index() ); + } + throw internal::invalid_type( b, std::next( e ) ); + } + + template< typename T > + [[nodiscard]] std::enable_if_t< internal::has_as< Traits< T >, basic_value >, T > as() const + { + return Traits< T >::as( *this ); + } + + template< typename T > + [[nodiscard]] std::enable_if_t< !internal::has_as< Traits< T >, basic_value > && internal::has_as_type< Traits, T, basic_value >, T > as() const + { + return Traits< T >::template as_type< Traits, T >( *this ); + } + + template< typename T > + [[nodiscard]] std::enable_if_t< !internal::has_as< Traits< T >, basic_value > && !internal::has_as_type< Traits, T, basic_value > && internal::has_to< Traits< T >, basic_value, T >, T > as() const + { + T v; // TODO: Should is_default_constructible< T > be part of the enable_if, static_assert()ed here, or this line allowed to error? + Traits< T >::to( *this, v ); + return v; + } + + template< typename T > + std::enable_if_t< !internal::has_as< Traits< T >, basic_value > && !internal::has_as_type< Traits, T, basic_value > && !internal::has_to< Traits< T >, basic_value, T > > as() const = delete; + + template< typename T, typename K > + [[nodiscard]] T as( const K& key ) const + { + return this->at( key ).template as< T >(); + } + + // TODO: Incorporate has_as_type in the following functions (and throughout the library) (if we decide keep it)! + + template< typename T, typename... With > + [[nodiscard]] std::enable_if_t< internal::has_as< Traits< T >, basic_value, With... >, T > as_with( With&&... with ) const + { + return Traits< T >::as( *this, with... ); + } + + template< typename T, typename... With > + [[nodiscard]] std::enable_if_t< !internal::has_as< Traits< T >, basic_value, With... > && internal::has_to< Traits< T >, basic_value, T, With... >, T > as_with( With&&... with ) const + { + T v; // TODO: Should is_default_constructible< T > be part of the enable_if, static_assert()ed here, or this line allowed to error? + Traits< T >::to( *this, v, with... ); + return v; + } + + template< typename T, typename... With > + std::enable_if_t< !internal::has_as< Traits< T >, basic_value, With... > && !internal::has_to< Traits< T >, basic_value, T, With... >, T > as_with( With&&... with ) const = delete; + + template< typename T > + std::enable_if_t< internal::has_to< Traits< T >, basic_value, T > > to( T& v ) const + { + Traits< std::decay_t< T > >::to( *this, v ); + } + + template< typename T > + std::enable_if_t< !internal::has_to< Traits< T >, basic_value, T > && internal::has_as< Traits< T >, basic_value > > to( T& v ) const + { + v = Traits< std::decay_t< T > >::as( *this ); + } + + template< typename T > + std::enable_if_t< !internal::has_to< Traits< T >, basic_value, T > && !internal::has_as< Traits< T >, basic_value > > to( T& v ) const = delete; + + template< typename T, typename K > + void to( T& v, const K& key ) + { + this->at( key ).to( v ); + } + + template< typename T, typename... With > + std::enable_if_t< internal::has_to< Traits< T >, basic_value, T, With... > > to_with( T& v, With&&... with ) const + { + Traits< std::decay_t< T > >::to( *this, v, with... ); + } + + template< typename T, typename... With > + std::enable_if_t< !internal::has_to< Traits< T >, basic_value, T, With... > && internal::has_as< Traits< T >, basic_value, With... > > to_with( T& v, With&&... with ) const + { + v = Traits< std::decay_t< T > >::as( *this, with... ); + } + + template< typename T, typename... With > + std::enable_if_t< !internal::has_to< Traits< T >, basic_value, T, With... > && !internal::has_as< Traits< T >, basic_value, With... > > to_with( T& v, With&&... with ) const = delete; + + template< typename T > + [[nodiscard]] std::optional< T > optional() const + { + if( is_null() ) { + return std::nullopt; + } + return as< T >(); + } + + template< typename T, typename K > + [[nodiscard]] std::optional< T > optional( const K& key ) const + { + if( const auto* p = find( key ) ) { + return p->template as< T >(); + } + return std::nullopt; + } + + void erase( const std::size_t index ) + { + auto& a = get_array(); + if( index >= a.size() ) { + throw_index_out_of_bound_exception( index ); + } + a.erase( a.begin() + index ); + } + + template< typename Key > + std::enable_if_t< !std::is_convertible_v< Key, std::size_t > && !std::is_convertible_v< Key, pointer > > erase( const Key& key ) + { + if( get_object().erase( key ) == 0 ) { + throw_key_not_found_exception( key ); + } + } + + void erase( const pointer& k ) + { + if( !k ) { + throw std::runtime_error( internal::format( "invalid root JSON Pointer for erase", json::message_extension( *this ) ) ); + } + const auto b = k.begin(); + const auto e = std::prev( k.end() ); + basic_value& v = internal::pointer_at( this, b, e ); + if( v.is_object() ) { + v.erase( e->key() ); + } + else if( v.is_array() ) { + v.erase( e->index() ); + } + else { + throw internal::invalid_type( b, std::next( e ) ); + } + } + + basic_value& insert( const pointer& k, basic_value in ) + { + if( !k ) { + *this = std::move( in ); + return *this; + } + const auto b = k.begin(); + const auto e = std::prev( k.end() ); + basic_value& v = internal::pointer_at( this, b, e ); + if( v.is_object() ) { + return v.get_object().insert_or_assign( e->key(), std::move( in ) ).first->second; + } + if( v.is_array() ) { + auto& a = v.get_array(); + if( e->key() == "-" ) { + v.emplace_back( std::move( in ) ); + return a.back(); + } + const auto i = e->index(); + if( i >= a.size() ) { + throw std::out_of_range( internal::format( "invalid JSON Pointer \"", internal::tokens_to_string( b, std::next( e ) ), "\", array index '", i, "' out of bound '", a.size(), '\'', json::message_extension( *this ) ) ); + } + a.insert( a.begin() + i, std::move( in ) ); + return a.at( i ); + } + throw internal::invalid_type( b, std::next( e ) ); + } + + variant_t& variant() noexcept + { + return m_variant; + } + + const variant_t& variant() const noexcept + { + return m_variant; + } + + private: + template< typename T > + static void produce_from_opaque_ptr( events::virtual_base& consumer, const void* raw ) + { + Traits< T >::template produce< Traits >( consumer, *static_cast< const T* >( raw ) ); + } + }; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/binary.hpp b/include/tao/json/binary.hpp index cd66a6d9..c762fdf7 100644 --- a/include/tao/json/binary.hpp +++ b/include/tao/json/binary.hpp @@ -1,100 +1,103 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_BINARY_HPP -#define TAOCPP_JSON_INCLUDE_BINARY_HPP +#ifndef TAO_JSON_BINARY_HPP +#define TAO_JSON_BINARY_HPP +#include #include -#include "external/byte.hpp" +#include "external/pegtl/internal/always_false.hpp" namespace tao { - namespace json + using binary = std::vector< std::byte >; + +} // namespace tao + +namespace tao::json +{ + namespace internal { - namespace internal + [[nodiscard]] constexpr char unhex_char( const char c ) noexcept { - constexpr char unhex_char( const char c ) noexcept - { - return ( c < 'A' ) ? ( c - '0' ) : ( ( c < 'a' ) ? ( c - 'A' + 10 ) : ( c - 'a' + 10 ) ); - } + return static_cast< char >( ( c < 'A' ) ? ( c - '0' ) : ( ( c < 'a' ) ? ( c - 'A' + 10 ) : ( c - 'a' + 10 ) ) ); + } - template< typename V, V... > - struct vlist; + template< typename V, V... > + struct vlist; - template< typename T, typename L, char... Cs > - struct unhex_helper; - - template< typename T, typename V, V... Vs > - struct unhex_helper< T, vlist< V, Vs... > > - { - static constexpr T unhex() - { - return T{ Vs... }; - } - }; - - template< typename T, typename V, V... Vs, char C > - struct unhex_helper< T, vlist< V, Vs... >, C > - : unhex_helper< T, vlist< V > > - { - static_assert( sizeof( T ) == 0, "digits must occur in pairs" ); - }; + template< typename T, typename L, char... Cs > + struct unhex_helper; - template< typename T, typename V, V... Vs, char C1, char... Cs > - struct unhex_helper< T, vlist< V, Vs... >, '\'', C1, Cs... > - : unhex_helper< T, vlist< V, Vs... >, C1, Cs... > + template< typename T, typename V, V... Vs > + struct unhex_helper< T, vlist< V, Vs... > > + { + [[nodiscard]] static constexpr T unhex() { - }; + return T{ Vs... }; + } + }; - template< typename T, typename V, V... Vs, char C0, char... Cs > - struct unhex_helper< T, vlist< V, Vs... >, C0, '\'', Cs... > - : unhex_helper< T, vlist< V > > - { - static_assert( sizeof( T ) == 0, "digit separator only allowed between pairs of digits" ); - }; + template< typename T, typename V, V... Vs, char C > + struct unhex_helper< T, vlist< V, Vs... >, C > + : unhex_helper< T, vlist< V > > + { + static_assert( pegtl::internal::always_false< T >::value, "digits must occur in pairs" ); + }; - template< typename T, typename V, V... Vs, char C0, char C1, char... Cs > - struct unhex_helper< T, vlist< V, Vs... >, C0, C1, Cs... > - : unhex_helper< T, vlist< V, Vs..., V( ( unhex_char( C0 ) << 4 ) + unhex_char( C1 ) ) >, Cs... > - { - }; + template< typename T, typename V, V... Vs, char C1, char... Cs > + struct unhex_helper< T, vlist< V, Vs... >, '\'', C1, Cs... > + : unhex_helper< T, vlist< V, Vs... >, C1, Cs... > + { + }; - template< typename T, typename V, char C > - constexpr T unhex() - { - static_assert( sizeof( T ) == 0, "not a hex literal" ); - return T{}; - } + template< typename T, typename V, V... Vs, char C0, char... Cs > + struct unhex_helper< T, vlist< V, Vs... >, C0, '\'', Cs... > + : unhex_helper< T, vlist< V > > + { + static_assert( pegtl::internal::always_false< T >::value, "digit separator only allowed between pairs of digits" ); + }; - template< typename T, typename V, char C0, char C1, char... Cs > - constexpr T unhex() - { - static_assert( C0 == '0', "not a hex literal" ); - static_assert( C1 == 'x' || C1 == 'X', "not a hex literal" ); - return unhex_helper< T, vlist< V >, Cs... >::unhex(); - } + template< typename T, typename V, V... Vs, char C0, char C1, char... Cs > + struct unhex_helper< T, vlist< V, Vs... >, C0, C1, Cs... > + : unhex_helper< T, vlist< V, Vs..., V( ( unhex_char( C0 ) << 4 ) + unhex_char( C1 ) ) >, Cs... > + { + }; - template< typename T, char... Cs > - constexpr T unhex() - { - return unhex< T, typename T::value_type, Cs... >(); - } + template< typename T, typename V, char C > + [[nodiscard]] constexpr T unhex() + { + static_assert( pegtl::internal::always_false< T >::value, "not a hex literal" ); + return T{}; + } - } // namespace internal + template< typename T, typename V, char C0, char C1, char... Cs > + [[nodiscard]] constexpr T unhex() + { + static_assert( C0 == '0', "not a hex literal" ); + static_assert( C1 == 'x' || C1 == 'X', "not a hex literal" ); + return unhex_helper< T, vlist< V >, Cs... >::unhex(); + } - inline namespace literals + template< typename T, char... Cs > + [[nodiscard]] constexpr T unhex() { - template< char... Cs > - std::vector< tao::byte > operator"" _binary() - { - return internal::unhex< std::vector< tao::byte >, Cs... >(); - } + return unhex< T, typename T::value_type, Cs... >(); + } - } // namespace literals + } // namespace internal - } // namespace json + inline namespace literals + { + template< char... Cs > + [[nodiscard]] std::vector< std::byte > operator"" _binary() + { + return internal::unhex< std::vector< std::byte >, Cs... >(); + } -} // namespace tao + } // namespace literals + +} // namespace tao::json #endif diff --git a/include/tao/json/binary_view.hpp b/include/tao/json/binary_view.hpp new file mode 100644 index 00000000..9014b2e2 --- /dev/null +++ b/include/tao/json/binary_view.hpp @@ -0,0 +1,31 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_BINARY_VIEW_HPP +#define TAO_JSON_BINARY_VIEW_HPP + +#include "span.hpp" + +#include + +namespace tao +{ + using binary_view = span< const std::byte >; + + namespace internal + { + [[nodiscard]] inline bool binary_equal( const binary_view lhs, const binary_view rhs ) noexcept + { + return std::equal( lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend() ); + } + + [[nodiscard]] inline bool binary_less( const binary_view lhs, const binary_view rhs ) noexcept + { + return std::lexicographical_compare( lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend() ); + } + + } // namespace internal + +} // namespace tao + +#endif diff --git a/include/tao/json/binding.hpp b/include/tao/json/binding.hpp new file mode 100644 index 00000000..7c0f861b --- /dev/null +++ b/include/tao/json/binding.hpp @@ -0,0 +1,71 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_BINDING_HPP +#define TAO_JSON_BINDING_HPP + +#include "binding/constant.hpp" +#include "binding/element.hpp" +#include "binding/factory.hpp" +#include "binding/for_nothing_value.hpp" +#include "binding/for_unknown_key.hpp" +#include "binding/inherit.hpp" +#include "binding/member.hpp" +#include "binding/versions.hpp" + +#include "binding/internal/array.hpp" +#include "binding/internal/inherit.hpp" +#include "binding/internal/object.hpp" + +namespace tao::json::binding +{ + namespace internal + { + template< typename... As > + struct make_array + { + using list = json::internal::merge_type_lists< internal::inherit_elements< As >... >; + using type = internal::array< list >; + }; + + } // namespace internal + + template< typename... As > + using array = typename internal::make_array< As... >::type; + + template< for_unknown_key E, for_nothing_value N, typename... As > + using basic_object = internal::basic_object< E, N, json::internal::merge_type_lists< internal::inherit_members< As >... > >; + + template< typename... As > + using object = basic_object< for_unknown_key::fail, for_nothing_value::encode, As... >; + +} // namespace tao::json::binding + +#define TAO_JSON_BIND_ELEMENT( ... ) tao::json::binding::element< __VA_ARGS__ > + +#define TAO_JSON_BIND_ELEMENT_BOOL( VaLue ) tao::json::binding::element_b< VaLue > +#define TAO_JSON_BIND_ELEMENT_SIGNED( VaLue ) tao::json::binding::element_i< VaLue > +#define TAO_JSON_BIND_ELEMENT_UNSIGNED( VaLue ) tao::json::binding::element_u< VaLue > +#define TAO_JSON_BIND_ELEMENT_STRING( VaLue ) tao::json::binding::element_s< TAO_JSON_STRING_T( VaLue ) > + +#define TAO_JSON_BIND_REQUIRED( KeY, ... ) tao::json::binding::member< tao::json::binding::member_kind::required, TAO_JSON_STRING_T( KeY ), __VA_ARGS__ > +#define TAO_JSON_BIND_OPTIONAL( KeY, ... ) tao::json::binding::member< tao::json::binding::member_kind::optional, TAO_JSON_STRING_T( KeY ), __VA_ARGS__ > + +#define TAO_JSON_BIND_REQUIRED_BOOL( KeY, VaLue ) tao::json::binding::member_b< tao::json::binding::member_kind::required, TAO_JSON_STRING_T( KeY ), VaLue > +#define TAO_JSON_BIND_REQUIRED_SIGNED( KeY, VaLue ) tao::json::binding::member_i< tao::json::binding::member_kind::required, TAO_JSON_STRING_T( KeY ), VaLue > +#define TAO_JSON_BIND_REQUIRED_UNSIGNED( KeY, VaLue ) tao::json::binding::member_u< tao::json::binding::member_kind::required, TAO_JSON_STRING_T( KeY ), VaLue > +#define TAO_JSON_BIND_REQUIRED_STRING( KeY, VaLue ) tao::json::binding::member_s< tao::json::binding::member_kind::required, TAO_JSON_STRING_T( KeY ), TAO_JSON_STRING_T( VaLue ) > + +#define TAO_JSON_BIND_OPTIONAL_BOOL( KeY, VaLue ) tao::json::binding::member_b< tao::json::binding::member_kind::optional, TAO_JSON_STRING_T( KeY ), VaLue > +#define TAO_JSON_BIND_OPTIONAL_SIGNED( KeY, VaLue ) tao::json::binding::member_i< tao::json::binding::member_kind::optional, TAO_JSON_STRING_T( KeY ), VaLue > +#define TAO_JSON_BIND_OPTIONAL_UNSIGNED( KeY, VaLue ) tao::json::binding::member_u< tao::json::binding::member_kind::optional, TAO_JSON_STRING_T( KeY ), VaLue > +#define TAO_JSON_BIND_OPTIONAL_STRING( KeY, VaLue ) tao::json::binding::member_s< tao::json::binding::member_kind::optional, TAO_JSON_STRING_T( KeY ), TAO_JSON_STRING_T( VaLue ) > + +#define TAO_JSON_BIND_REQUIRED1( ... ) tao::json::binding::member< tao::json::binding::member_kind::required, tao::json::binding::internal::use_default_key, __VA_ARGS__ > +#define TAO_JSON_BIND_OPTIONAL1( ... ) tao::json::binding::member< tao::json::binding::member_kind::optional, tao::json::binding::internal::use_default_key, __VA_ARGS__ > + +#define TAO_JSON_FACTORY_BIND( KeY, ... ) tao::json::binding::internal::factory_temp< TAO_JSON_STRING_T( KeY ), __VA_ARGS__ > + +#define TAO_JSON_FACTORY_BIND1( ... ) tao::json::binding::internal::factory_temp< tao::json::binding::internal::use_default_key, __VA_ARGS__ > + +#endif diff --git a/include/tao/json/binding/constant.hpp b/include/tao/json/binding/constant.hpp new file mode 100644 index 00000000..193de3f0 --- /dev/null +++ b/include/tao/json/binding/constant.hpp @@ -0,0 +1,232 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_BINDING_CONSTANT_HPP +#define TAO_JSON_BINDING_CONSTANT_HPP + +#include +#include + +#include "../external/pegtl/internal/pegtl_string.hpp" +#include "../internal/escape.hpp" +#include "../internal/format.hpp" +#include "../internal/string_t.hpp" +#include "../message_extension.hpp" + +#include "element.hpp" +#include "member_kind.hpp" + +#include "internal/type_key.hpp" + +namespace tao::json::binding +{ + template< bool V > + struct element_b + { + using value_t = bool; + + template< typename C > + [[nodiscard]] static bool read( const C& /*unused*/ ) + { + return V; + } + + template< template< typename... > class Traits, typename C > + static void to( const basic_value< Traits >& v, C& /*unused*/ ) + { + const auto t = v.template as< bool >(); + if( t != V ) { + throw std::runtime_error( json::internal::format( "boolean mismatch, expected '", V, "' parsed '", t, '\'', json::message_extension( v ) ) ); + } + } + + template< template< typename... > class Traits = traits, typename Consumer, typename C > + static void produce( Consumer& consumer, const C& /*unused*/ ) + { + consumer.boolean( V ); + } + + template< template< typename... > class Traits = traits, typename Producer, typename C > + static void consume( Producer& parser, C& /*unused*/ ) + { + const auto t = parser.boolean(); + if( t != V ) { + parser.throw_parse_error( json::internal::format( "boolean mismatch, expected '", V, "' parsed '", t, '\'' ) ); + } + } + }; + + template< std::int64_t V > + struct element_i + { + using value_t = std::int64_t; + + template< typename C > + [[nodiscard]] static std::int64_t read( const C& /*unused*/ ) + { + return V; + } + + template< template< typename... > class Traits, typename C > + static void to( const basic_value< Traits >& v, C& /*unused*/ ) + { + const auto t = v.template as< std::int64_t >(); + if( t != V ) { + throw std::runtime_error( json::internal::format( "signed integer mismatch, expected '", V, "' parsed '", t, '\'', json::message_extension( v ) ) ); + } + } + + template< template< typename... > class Traits = traits, typename Consumer, typename C > + static void produce( Consumer& consumer, const C& /*unused*/ ) + { + consumer.number( V ); + } + + template< template< typename... > class Traits = traits, typename Producer, typename C > + static void consume( Producer& parser, C& /*unused*/ ) + { + const auto t = parser.number_signed(); + if( t != V ) { + parser.throw_parse_error( json::internal::format( "signed integer mismatch, expected '", V, "' parsed '", t, '\'' ) ); + } + } + }; + + template< std::uint64_t V > + struct element_u + { + using value_t = std::uint64_t; + + template< typename C > + [[nodiscard]] static std::uint64_t read( const C& /*unused*/ ) + { + return V; + } + + template< template< typename... > class Traits, typename C > + static void to( const basic_value< Traits >& v, C& /*unused*/ ) + { + const auto t = v.template as< std::uint64_t >(); + if( t != V ) { + throw std::runtime_error( json::internal::format( "unsigned integer mismatch, expected '", V, "' parsed '", t, '\'', json::message_extension( v ) ) ); + } + } + + template< template< typename... > class Traits = traits, typename Consumer, typename C > + static void produce( Consumer& consumer, const C& /*unused*/ ) + { + consumer.number( V ); + } + + template< template< typename... > class Traits = traits, typename Producer, typename C > + static void consume( Producer& parser, C& /*unused*/ ) + { + const auto t = parser.number_unsigned(); + if( t != V ) { + parser.throw_parse_error( json::internal::format( "unsigned integer mismatch, expected '", V, "' parsed '", t, '\'' ) ); + } + } + }; + + template< typename S > + struct element_s; + + template< char... Cs > + struct element_s< json::internal::string_t< Cs... > > + { + using value_t = std::string; // TODO: Or std::string_view? Something else? Nothing? + + using string = json::internal::string_t< Cs... >; + + template< typename C > + [[nodiscard]] static std::string_view read( const C& /*unused*/ ) + { + return string::as_string_view(); + } + + template< template< typename... > class Traits, typename C > + static void to( const basic_value< Traits >& v, C& /*unused*/ ) + { + const auto sc = string::as_string_view(); + const auto sv = v.template as< std::string_view >(); + if( sv != sc ) { + throw std::runtime_error( json::internal::format( "string mismatch, expected \"", json::internal::escape( sc ), "\" parsed \"", json::internal::escape( sv ), '"', json::message_extension( v ) ) ); + } + } + + template< template< typename... > class Traits = traits, typename Consumer, typename T > + static void produce( Consumer& consumer, const T& /*unused*/ ) + { + consumer.string( string::as_string_view() ); + } + + template< template< typename... > class Traits = traits, typename Producer, typename T > + static void consume( Producer& parser, T& /*unused*/ ) + { + const auto sc = string::as_string_view(); + const auto ss = parser.string(); + if( ss != sc ) { + parser.throw_parse_error( json::internal::format( "string mismatch, expected \"", json::internal::escape( sc ), "\" parsed \"", json::internal::escape( ss ), '"' ) ); + } + } + }; + + template< member_kind R, typename K, bool B > + struct member_b + : element_b< B >, + internal::type_key< K, void > + { + static constexpr member_kind kind = R; + + template< template< typename... > class Traits, typename T > + [[nodiscard]] static bool is_nothing( const T& /*unused*/ ) + { + return false; + } + }; + + template< member_kind R, typename K, std::int64_t V > + struct member_i + : element_i< V >, + internal::type_key< K, void > + { + static constexpr member_kind kind = R; + + template< template< typename... > class Traits, typename T > + [[nodiscard]] static bool is_nothing( const T& /*unused*/ ) + { + return false; + } + }; + + template< member_kind R, typename K, std::uint64_t V > + struct member_u + : element_u< V >, + internal::type_key< K, void > + { + static constexpr member_kind kind = R; + + template< template< typename... > class Traits, typename T > + [[nodiscard]] static bool is_nothing( const T& /*unused*/ ) + { + return false; + } + }; + + template< member_kind R, typename K, typename S > + struct member_s + : element_s< S >, + internal::type_key< K, void > + { + static constexpr member_kind kind = R; + + template< template< typename... > class Traits, typename T > + [[nodiscard]] static bool is_nothing( const T& /*unused*/ ) + { + return false; + } + }; + +} // namespace tao::json::binding + +#endif diff --git a/include/tao/json/binding/element.hpp b/include/tao/json/binding/element.hpp new file mode 100644 index 00000000..7fc0b5cf --- /dev/null +++ b/include/tao/json/binding/element.hpp @@ -0,0 +1,182 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_BINDING_ELEMENT_HPP +#define TAO_JSON_BINDING_ELEMENT_HPP + +#include + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "../events/produce.hpp" + +namespace tao::json::binding +{ + namespace internal + { + template< typename T, T, typename = void > + struct element; + + template< typename C, typename T, T C::*P > + struct element< T C::*, P, std::enable_if_t< std::is_member_object_pointer_v< T C::* > > > + { + using class_t = C; + using value_t = T; + + using internal_t = std::decay_t< decltype( std::declval< C >().*P ) >; + + [[nodiscard]] static const auto& read( const C& v ) + { + return v.*P; + } + + template< typename W > + static void write( C& v, W&& w ) + { + v.*P = std::forward< W >( w ); + } + + template< template< typename... > class Traits > + static void to( const basic_value< Traits >& v, C& x ) + { + v.to( x.*P ); + } + + template< template< typename... > class Traits = traits, typename Producer > + static void consume( Producer& parser, C& v ) + { + json::consume< Traits >( parser, v.*P ); + } + + template< template< typename... > class Traits = traits, typename Consumer > + static void produce( Consumer& consumer, const C& v ) + { + events::produce< Traits >( consumer, v.*P ); + } + }; + + template< typename C, typename T, T C::*P > + struct element< T C::*, P, std::enable_if_t< std::is_member_function_pointer_v< T C::* > > > + { + using class_t = C; + using value_t = T; + + using internal_t = std::decay_t< decltype( ( std::declval< const C >().*P )() ) >; + + [[nodiscard]] static decltype( auto ) read( const C& v ) + { + return ( v.*P )(); + } + + template< template< typename... > class Traits = traits, typename Consumer > + static void produce( Consumer& consumer, const C& v ) + { + events::produce< Traits >( consumer, ( v.*P )() ); + } + }; + + template< typename C, typename T, T ( *P )( const C& ) > + struct element< T ( * )( const C& ), P > + { + using class_t = C; + using value_t = T; + + [[nodiscard]] static decltype( auto ) read( const C& v ) + { + return P( v ); + } + + template< template< typename... > class Traits = traits, typename Consumer > + static void produce( Consumer& consumer, const C& v ) + { + events::produce< Traits >( consumer, P( v ) ); + } + }; + + template< typename CT, CT CP, typename T, T P > + struct element2; + + template< typename A, typename CR, CR ( *CP )( const A& ) noexcept, typename R, R ( *P )( A& ) noexcept > + struct element2< CR ( * )( const A& ) noexcept, CP, R ( * )( A& ) noexcept, P > + { + using class_t = A; + using value_t = std::decay_t< R >; + + [[nodiscard]] static decltype( auto ) read( const A& v ) noexcept + { + return CP( v ); + } + + template< typename W > + static void write( A& v, W&& w ) + { + P( v ) = std::forward< W >( w ); + } + + template< template< typename... > class Traits > + static void to( const basic_value< Traits >& v, A& x ) + { + v.to( P( x ) ); + } + + template< template< typename... > class Traits = traits, typename Producer > + static void consume( Producer& parser, A& v ) + { + json::consume< Traits >( parser, P( v ) ); + } + + template< template< typename... > class Traits = traits, typename Consumer > + static void produce( Consumer& consumer, const A& v ) + { + events::produce< Traits >( consumer, CP( v ) ); + } + }; + + template< typename A, typename CR, CR ( *CP )( const A& ) noexcept, typename R, void ( *P )( A&, R&& ) noexcept > + struct element2< CR ( * )( const A& ) noexcept, CP, void ( * )( A&, R&& ) noexcept, P > + { + using class_t = A; + using value_t = std::decay_t< R >; + + [[nodiscard]] static decltype( auto ) read( const A& v ) noexcept + { + return CP( v ); + } + + template< typename W > + static void write( A& v, W&& w ) + { + P( v, std::forward< W >( w ) ); + } + + template< template< typename... > class Traits > + static void to( const basic_value< Traits >& v, A& x ) + { + P( x, v.template as< std::decay_t< R > >() ); + } + + template< template< typename... > class Traits = traits, typename Producer > + static void consume( Producer& parser, A& v ) + { + P( v, json::consume< Traits >( parser ) ); + } + + template< template< typename... > class Traits = traits, typename Consumer > + static void produce( Consumer& consumer, const A& v ) + { + events::produce< Traits >( consumer, CP( v ) ); + } + }; + + } // namespace internal + + template< auto P > + using element = internal::element< decltype( P ), P >; + + template< auto CP, auto P > + using element2 = internal::element2< decltype( CP ), CP, decltype( P ), P >; + +} // namespace tao::json::binding + +#endif diff --git a/include/tao/json/binding/factory.hpp b/include/tao/json/binding/factory.hpp new file mode 100644 index 00000000..28362f18 --- /dev/null +++ b/include/tao/json/binding/factory.hpp @@ -0,0 +1,250 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_BINDING_FACTORY_HPP +#define TAO_JSON_BINDING_FACTORY_HPP + +#include +#include +#include +#include +#include + +#include "../forward.hpp" + +#include "../basic_value.hpp" +#include "../external/pegtl/internal/pegtl_string.hpp" +#include "../internal/escape.hpp" +#include "../internal/format.hpp" +#include "../internal/string_t.hpp" + +#include "internal/type_key.hpp" + +namespace tao::json::binding +{ + namespace internal + { + template< typename... Ts > + void list_all_types( std::ostream& oss, const std::map< std::string, Ts... >& m ) + { + for( const auto& i : m ) { + json::internal::format_to( oss, " \"", i.first, '\"' ); + } + } + + template< typename... Ts > + void list_all_types( std::ostream& oss, const std::map< const std::type_info*, Ts... >& m ) + { + for( const auto& i : m ) { + json::internal::format_to( oss, ' ', i.first->name() ); + } + } + + template< typename K, typename T, typename Base, template< typename... > class Pointer > + struct factory_type + : type_key< K, T > + { + [[nodiscard]] static const std::type_info* type() + { + return &typeid( T ); + } + + template< template< typename... > class Traits, typename... With > + [[nodiscard]] static Pointer< Base > as( const basic_value< Traits >& v, With&... with ) + { + using R = typename Traits< Pointer< T > >::template with_base< Base >; + return R::as( v, with... ); + } + + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const Pointer< Base >& p ) + { + using R = typename Traits< Pointer< T > >::template with_base< Base >; + R::assign( v, p ); + } + + template< template< typename... > class Traits, typename Producer > + [[nodiscard]] static Pointer< Base > consume( Producer& parser ) + { + using R = typename Traits< Pointer< T > >::template with_base< Base >; + return R::template consume< Traits >( parser ); + } + + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, const Pointer< Base >& p ) + { + using R = typename Traits< Pointer< T > >::template with_base< Base >; + R::template produce< Traits >( c, p ); + } + }; + + template< typename K, typename T > + struct factory_temp + { + template< typename Base, template< typename... > class Pointer > + using bind = factory_type< K, T, Base, Pointer >; + }; + + template< template< typename... > class Traits, template< typename... > class Pointer, typename Base, typename... With > + using as_func_t = Pointer< Base > ( * )( const basic_value< Traits >&, With&... ); + + } // namespace internal + + template< typename... Ts > + struct factory + { + template< typename F > + struct entry1 + { + explicit entry1( F c ) + : function( c ) + {} + + F function; + }; + + template< typename F > + struct entry2 + { + entry2( F c, std::string&& n ) + : function( c ), + name( std::move( n ) ) + {} + + F function; + std::string name; + }; + + template< typename V, template< typename... > class Traits, template< typename... > class Pointer, typename Base, typename... With > + static void emplace_as( std::map< std::string, entry1< internal::as_func_t< Traits, Pointer, Base, With... > >, std::less<> >& m ) + { + using W = typename V::template bind< Base, Pointer >; + m.try_emplace( W::template key< Traits >(), entry1< internal::as_func_t< Traits, Pointer, Base, With... > >( &W::template as< Traits, With... > ) ); + } + + template< template< typename... > class Traits, template< typename... > class Pointer, typename Base, typename... With > + static void to( const basic_value< Traits >& v, Pointer< Base >& r, With&... with ) + { + static const std::map< std::string, entry1< internal::as_func_t< Traits, Pointer, Base, With... > >, std::less<> > m = []() { + std::map< std::string, entry1< internal::as_func_t< Traits, Pointer, Base, With... > >, std::less<> > t; + ( emplace_as< Ts >( t ), ... ); + assert( t.size() == sizeof...( Ts ) ); + return t; + }(); + + const auto& a = v.get_object(); + if( a.size() != 1 ) { + throw std::runtime_error( json::internal::format( "polymorphic factory requires object of size one for base class ", pegtl::internal::demangle< Base >(), json::message_extension( v ) ) ); + } + const auto b = a.begin(); + const auto i = m.find( b->first ); + if( i == m.end() ) { + std::ostringstream oss; + json::internal::format_to( oss, "unknown factory type \"", json::internal::escape( b->first ), "\" -- known are" ); + internal::list_all_types( oss, m ); + json::internal::format_to( oss, " for base class ", pegtl::internal::demangle< Base >(), json::message_extension( v ) ); + throw std::runtime_error( oss.str() ); + } + r = i->second.function( b->second, with... ); + } + + template< typename V, template< typename... > class Traits, template< typename... > class Pointer, typename Base, typename F > + static void emplace_assign( std::map< const std::type_info*, entry2< F >, json::internal::type_info_less >& m ) + { + using W = typename V::template bind< Base, Pointer >; + m.try_emplace( W::type(), entry2< F >( &W::template assign< Traits >, W::template key< Traits >() ) ); + } + + template< template< typename... > class Traits, template< typename... > class Pointer, typename Base > + static void assign( basic_value< Traits >& v, const Pointer< Base >& p ) + { + using F = void ( * )( basic_value< Traits >&, const Pointer< Base >& ); + static const std::map< const std::type_info*, entry2< F >, json::internal::type_info_less > m = []() { + std::map< const std::type_info*, entry2< F >, json::internal::type_info_less > t; + ( emplace_assign< Ts, Traits, Pointer, Base >( t ), ... ); + assert( t.size() == sizeof...( Ts ) ); + return t; + }(); + + const auto i = m.find( &typeid( *p ) ); + if( i == m.end() ) { + std::ostringstream oss; + json::internal::format_to( oss, "unknown factory type ", pegtl::internal::demangle< decltype( *p ) >(), " -- known are" ); + internal::list_all_types( oss, m ); + json::internal::format_to( oss, " for base class ", pegtl::internal::demangle< Base >() ); + throw std::runtime_error( oss.str() ); + } + i->second.function( v, p ); + v = { + { i->second.name, std::move( v ) } + }; + } + + template< typename V, template< typename... > class Traits, template< typename... > class Pointer, typename Base, typename Producer, typename F > + static void emplace_consume( std::map< std::string, entry1< F >, std::less<> >& m ) + { + using W = typename V::template bind< Base, Pointer >; + m.try_emplace( W::template key< Traits >(), entry1< F >( &W::template consume< Traits, Producer > ) ); + } + + template< template< typename... > class Traits, template< typename... > class Pointer, typename Base, typename Producer > + static void consume( Producer& parser, Pointer< Base >& r ) + { + using F = Pointer< Base > ( * )( Producer& ); + static const std::map< std::string, entry1< F >, std::less<> > m = []() { + std::map< std::string, entry1< F >, std::less<> > t; + ( emplace_consume< Ts, Traits, Pointer, Base, Producer >( t ), ... ); + return t; + }(); + + auto s = parser.begin_object(); + const auto k = parser.key(); + const auto i = m.find( k ); + if( i == m.end() ) { + std::ostringstream oss; + json::internal::format_to( oss, "unknown factory type \"", json::internal::escape( k ), "\" -- known are" ); + internal::list_all_types( oss, m ); + json::internal::format_to( oss, " for base class ", pegtl::internal::demangle< Base >() ); + throw std::runtime_error( oss.str() ); + } + r = i->second.function( parser ); + parser.end_object( s ); + } + + template< typename V, template< typename... > class Traits, template< typename... > class Pointer, typename Base, typename Consumer, typename F > + static void emplace_produce( std::map< const std::type_info*, entry2< F >, json::internal::type_info_less >& m ) + { + using W = typename V::template bind< Base, Pointer >; + m.try_emplace( W::type(), entry2< F >( &W::template produce< Traits, Consumer >, W::template key< Traits >() ) ); + } + + template< template< typename... > class Traits, template< typename... > class Pointer, typename Base, typename Consumer > + static void produce( Consumer& consumer, const Pointer< Base >& p ) + { + using F = void ( * )( Consumer&, const Pointer< Base >& ); + static const std::map< const std::type_info*, entry2< F >, json::internal::type_info_less > m = []() { + std::map< const std::type_info*, entry2< F >, json::internal::type_info_less > t; + ( emplace_produce< Ts, Traits, Pointer, Base, Consumer >( t ), ... ); + assert( t.size() == sizeof...( Ts ) ); + return t; + }(); + + const auto i = m.find( &typeid( *p ) ); + if( i == m.end() ) { + std::ostringstream oss; + json::internal::format_to( oss, "unknown factory type ", pegtl::internal::demangle< decltype( *p ) >(), " -- known are" ); + internal::list_all_types( oss, m ); + json::internal::format_to( oss, " for base class ", pegtl::internal::demangle< Base >() ); + throw std::runtime_error( oss.str() ); + } + consumer.begin_object( 1 ); + consumer.key( i->second.name ); + i->second.function( consumer, p ); + consumer.member(); + consumer.end_object( 1 ); + } + }; + +} // namespace tao::json::binding + +#endif diff --git a/include/tao/json/binding/for_nothing_value.hpp b/include/tao/json/binding/for_nothing_value.hpp new file mode 100644 index 00000000..6fbae902 --- /dev/null +++ b/include/tao/json/binding/for_nothing_value.hpp @@ -0,0 +1,17 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_BINDING_FOR_NOTHING_VALUE_HPP +#define TAO_JSON_BINDING_FOR_NOTHING_VALUE_HPP + +namespace tao::json::binding +{ + enum class for_nothing_value : bool + { + encode, + suppress + }; + +} // namespace tao::json::binding + +#endif diff --git a/include/tao/json/binding/for_unknown_key.hpp b/include/tao/json/binding/for_unknown_key.hpp new file mode 100644 index 00000000..07e1e2ed --- /dev/null +++ b/include/tao/json/binding/for_unknown_key.hpp @@ -0,0 +1,17 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_BINDING_FOR_UNKNOWN_KEY_HPP +#define TAO_JSON_BINDING_FOR_UNKNOWN_KEY_HPP + +namespace tao::json::binding +{ + enum class for_unknown_key : bool + { + fail, + skip + }; + +} // namespace tao::json::binding + +#endif diff --git a/include/tao/json/binding/inherit.hpp b/include/tao/json/binding/inherit.hpp new file mode 100644 index 00000000..ea6ddcdd --- /dev/null +++ b/include/tao/json/binding/inherit.hpp @@ -0,0 +1,14 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_BINDING_INHERIT_HPP +#define TAO_JSON_BINDING_INHERIT_HPP + +namespace tao::json::binding +{ + template< typename T > + struct inherit; + +} // namespace tao::json::binding + +#endif diff --git a/include/tao/json/binding/internal/array.hpp b/include/tao/json/binding/internal/array.hpp new file mode 100644 index 00000000..72896dcb --- /dev/null +++ b/include/tao/json/binding/internal/array.hpp @@ -0,0 +1,103 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_BINDING_INTERNAL_ARRAY_HPP +#define TAO_JSON_BINDING_INTERNAL_ARRAY_HPP + +#include +#include + +#include "../../basic_value.hpp" +#include "../../forward.hpp" + +#include "../../internal/format.hpp" +#include "../../internal/type_traits.hpp" + +namespace tao::json::binding::internal +{ + template< typename T, typename L = std::make_index_sequence< T::size > > + struct array; + + template< typename... As, std::size_t... Is > + struct array< json::internal::type_list< As... >, std::index_sequence< Is... > > + { + using elements = json::internal::type_list< As... >; + + template< template< typename... > class Traits, typename C > + static const std::vector< basic_value< Traits > >& get_array_impl( const basic_value< Traits >& v ) + { + const auto& a = v.get_array(); + if( a.size() != sizeof...( As ) ) { + throw std::runtime_error( json::internal::format( "array size mismatch for type ", pegtl::internal::demangle< C >(), " -- expected ", sizeof...( As ), " received ", a.size(), json::message_extension( v ) ) ); + } + return a; + } + + template< template< typename... > class Traits, typename C > + static std::enable_if_t< std::is_constructible_v< C, typename As::value_t... >, C > as_type( const basic_value< Traits >& v ) + { + const auto& a = get_array_impl< Traits, C >( v ); + return C( a[ Is ].template as< typename As::value_t >()... ); + } + + template< template< typename... > class Traits, typename C > + static void to( const basic_value< Traits >& v, C& x ) // TODO: std::enable_if_t< WHAT?, void > + { + const auto& a = get_array_impl< Traits, C >( v ); + ( As::to( a[ Is ], x ), ... ); + } + + template< template< typename... > class Traits, typename C > + static void assign( basic_value< Traits >& v, const C& x ) + { + v.emplace_array(); + ( v.emplace_back( As::read( x ) ), ... ); + } + + template< typename A, template< typename... > class Traits = traits, typename Producer, typename C, typename State > + static void consume_element( Producer& parser, C& x, State& s ) + { + parser.element( s ); + A::template consume< Traits >( parser, x ); + } + + template< template< typename... > class Traits = traits, typename Producer, typename C > + static void consume( Producer& parser, C& x ) + { + auto s = parser.begin_array(); + ( consume_element< As, Traits >( parser, x, s ), ... ); + parser.end_array( s ); + } + + template< typename A, template< typename... > class Traits, typename Consumer, typename C > + static void produce_element( Consumer& consumer, const C& x ) + { + A::template produce< Traits >( consumer, x ); + consumer.element(); + } + + template< template< typename... > class Traits = traits, typename Consumer, typename C > + static void produce( Consumer& consumer, const C& x ) + { + consumer.begin_array( sizeof...( As ) ); + ( produce_element< As, Traits >( consumer, x ), ... ); + consumer.end_array( sizeof...( As ) ); + } + + template< template< typename... > class Traits, typename C > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const C& rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + if( p.is_array() ) { + const auto& a = p.get_array(); + if( a.size() == sizeof...( As ) ) { + return ( ( a[ Is ] == As::read( rhs ) ) && ... ); + } + } + return false; + } + }; + +} // namespace tao::json::binding::internal + +#endif diff --git a/include/tao/json/binding/internal/inherit.hpp b/include/tao/json/binding/internal/inherit.hpp new file mode 100644 index 00000000..09bfc0a8 --- /dev/null +++ b/include/tao/json/binding/internal/inherit.hpp @@ -0,0 +1,45 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_BINDING_INTERNAL_INHERIT_HPP +#define TAO_JSON_BINDING_INTERNAL_INHERIT_HPP + +#include "../../internal/type_traits.hpp" + +#include "../inherit.hpp" + +namespace tao::json::binding::internal +{ + template< typename T > + struct inherit_elements_t + { + using list = json::internal::type_list< T >; + }; + + template< typename T > + struct inherit_elements_t< inherit< T > > + { + using list = typename T::elements; + }; + + template< typename T > + using inherit_elements = typename inherit_elements_t< T >::list; + + template< typename T > + struct inherit_members_t + { + using list = json::internal::type_list< T >; + }; + + template< typename T > + struct inherit_members_t< inherit< T > > + { + using list = typename T::members; + }; + + template< typename T > + using inherit_members = typename inherit_members_t< T >::list; + +} // namespace tao::json::binding::internal + +#endif diff --git a/include/tao/json/binding/internal/object.hpp b/include/tao/json/binding/internal/object.hpp new file mode 100644 index 00000000..733784bb --- /dev/null +++ b/include/tao/json/binding/internal/object.hpp @@ -0,0 +1,267 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_BINDING_INTERNAL_OBJECT_HPP +#define TAO_JSON_BINDING_INTERNAL_OBJECT_HPP + +#include +#include +#include +#include +#include +#include + +#include "../for_nothing_value.hpp" +#include "../for_unknown_key.hpp" +#include "../member_kind.hpp" + +#include "../../forward.hpp" + +#include "../../basic_value.hpp" +#include "../../internal/escape.hpp" +#include "../../internal/format.hpp" +#include "../../internal/type_traits.hpp" + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4702 ) +#endif + +namespace tao::json::binding::internal +{ + template< typename... Ts > + void list_all_keys( std::ostream& oss, const std::map< std::string, Ts... >& m ) + { + for( const auto& p : m ) { + json::internal::format_to( oss, ' ', p.first ); + } + } + + template< std::size_t N, typename... Ts > + void list_missing_keys( std::ostream& oss, const std::bitset< N >& t, const std::map< std::string, Ts... >& m ) + { + for( const auto& p : m ) { + if( !t.test( p.second.index ) ) { + json::internal::format_to( oss, ' ', p.first ); + } + } + } + + template< typename... As, std::size_t... Is > + auto make_bitset( std::index_sequence< Is... > /*unused*/ ) noexcept + { + std::bitset< sizeof...( As ) > r; + ( r.set( Is, As::kind == member_kind::optional ), ... ); + return r; + } + + template< typename F > + struct wrap + { + F function; + std::size_t index; + }; + + template< typename A, typename C, template< typename... > class Traits > + void wrap_to( const basic_value< Traits >& v, C& x ) + { + A::template to< Traits >( v, x ); + } + + template< template< typename... > class Traits, typename C, typename... As, std::size_t... Is > + auto make_map_to( std::index_sequence< Is... > /*unused*/ ) + { + using F = void ( * )( const basic_value< Traits >&, C& ); + return std::map< std::string, wrap< F > >{ + { As::template key< Traits >(), { &wrap_to< As, C, Traits >, Is } }... + }; + } + + template< typename A, typename C, template< typename... > class Traits, typename Producer > + void wrap_consume( Producer& p, C& x ) + { + A::template consume< Traits, Producer >( p, x ); + } + + template< typename C, template< typename... > class Traits, typename Producer, typename... As, std::size_t... Is > + auto make_map_consume( std::index_sequence< Is... > /*unused*/ ) + { + using F = void ( * )( Producer&, C& ); + return std::map< std::string, wrap< F > >{ + { As::template key< Traits >(), { &wrap_consume< As, C, Traits, Producer >, Is } }... + }; + } + + template< for_unknown_key E, for_nothing_value N, typename T > + struct basic_object; + + template< for_unknown_key E, for_nothing_value N, typename... As > + struct basic_object< E, N, json::internal::type_list< As... > > + { + using members = json::internal::type_list< As... >; + + template< template< typename... > class Traits, typename C > + static void to( const basic_value< Traits >& v, C& x ) + { + static const auto m = make_map_to< Traits, C, As... >( std::index_sequence_for< As... >() ); + static const auto o = make_bitset< As... >( std::index_sequence_for< As... >() ); + + const auto& a = v.get_object(); + std::bitset< sizeof...( As ) > b; + for( const auto& p : a ) { + const auto& k = p.first; + const auto i = m.find( k ); + if( i == m.end() ) { + if constexpr( E == for_unknown_key::skip ) { + continue; + } + std::ostringstream oss; + json::internal::format_to( oss, "unknown object key \"", json::internal::escape( k ), "\" -- known are" ); + list_all_keys( oss, m ); + json::internal::format_to( oss, " for type ", pegtl::internal::demangle< C >(), json::message_extension( v ) ); + throw std::runtime_error( oss.str() ); + } + i->second.function( p.second, x ); + b.set( i->second.index ); + } + b |= o; + if( !b.all() ) { + std::ostringstream oss; + json::internal::format_to( oss, "missing required key(s)" ); + list_missing_keys( oss, b, m ); + json::internal::format_to( oss, " for type ", pegtl::internal::demangle< C >(), json::message_extension( v ) ); + throw std::runtime_error( oss.str() ); + } + } + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4127 ) +#endif + template< typename A, template< typename... > class Traits, typename C > + static void assign_member( basic_value< Traits >& v, const C& x ) + { + if( ( N == for_nothing_value::encode ) || ( !A::template is_nothing< Traits >( x ) ) ) { + v.try_emplace( A::template key< Traits >(), A::read( x ) ); + } + } +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + + template< template< typename... > class Traits, typename C > + static void assign( basic_value< Traits >& v, const C& x ) + { + v.emplace_object(); + ( assign_member< As >( v, x ), ... ); + } + + template< template< typename... > class Traits = traits, typename Producer, typename C > + static void consume( Producer& parser, C& x ) + { + static const auto m = make_map_consume< C, Traits, Producer, As... >( std::index_sequence_for< As... >() ); + static const auto o = make_bitset< As... >( std::index_sequence_for< As... >() ); + + auto s = parser.begin_object(); + std::bitset< sizeof...( As ) > b; + while( parser.member_or_end_object( s ) ) { + const auto k = parser.key(); + const auto i = m.find( k ); + if( i == m.end() ) { + if constexpr( E == for_unknown_key::skip ) { + parser.skip_value(); + continue; + } + std::ostringstream oss; + json::internal::format_to( oss, "unknown object key \"", json::internal::escape( k ), "\" -- known are" ); + list_all_keys( oss, m ); + json::internal::format_to( oss, " for type ", pegtl::internal::demangle< C >() ); + parser.throw_parse_error( oss.str() ); + } + if( b.test( i->second.index ) ) { + parser.throw_parse_error( json::internal::format( "duplicate object key \"", json::internal::escape( k ), "\" for type ", pegtl::internal::demangle< C >() ) ); + } + i->second.function( parser, x ); + b.set( i->second.index ); + } + b |= o; + if( !b.all() ) { + std::ostringstream oss; + json::internal::format_to( oss, "missing required key(s)" ); + list_missing_keys( oss, b, m ); + json::internal::format_to( oss, " for type ", pegtl::internal::demangle< C >() ); + parser.throw_parse_error( oss.str() ); + } + } + + template< template< typename... > class Traits, typename C > + [[nodiscard]] static std::size_t produce_size( const C& x ) + { + if constexpr( N == for_nothing_value::encode ) { + return sizeof...( As ); + } + return ( std::size_t( !As::template is_nothing< Traits >( x ) ) + ... ); + } + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4127 ) +#endif + + template< typename A, template< typename... > class Traits, typename Consumer, typename C > + static void produce_member( Consumer& consumer, const C& x ) + { + if( ( N == for_nothing_value::encode ) || ( !A::template is_nothing< Traits >( x ) ) ) { + A::template produce_key< Traits >( consumer ); + A::template produce< Traits >( consumer, x ); + consumer.member(); + } + } + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + + template< template< typename... > class Traits = traits, typename Consumer, typename C > + static void produce( Consumer& consumer, const C& x ) + { + const auto size = produce_size< Traits >( x ); + consumer.begin_object( size ); + ( produce_member< As, Traits >( consumer, x ), ... ); + consumer.end_object( size ); + } + + template< typename A, template< typename... > class Traits, typename C > + [[nodiscard]] static bool equal_member( const std::map< std::string, basic_value< Traits >, std::less<> >& a, C& x ) + { + if( !A::template is_nothing< Traits >( x ) ) { + return a.at( A::template key< Traits >() ) == A::read( x ); + } + if constexpr( N == for_nothing_value::encode ) { + return a.at( A::template key< Traits >() ).is_null(); + } + const auto i = a.find( A::template key< Traits >() ); + return ( i == a.end() ) || i->second.is_null(); + } + + template< template< typename... > class Traits, typename C > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const C& rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + if( p.is_object() ) { + const auto& a = p.get_object(); + if( p.get_object().size() == sizeof...( As ) ) { + return ( equal_member< As >( a, rhs ) && ... ); + } + } + return false; + } + }; + +} // namespace tao::json::binding::internal + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + +#endif diff --git a/include/tao/json/binding/internal/type_key.hpp b/include/tao/json/binding/internal/type_key.hpp new file mode 100644 index 00000000..fd42a51e --- /dev/null +++ b/include/tao/json/binding/internal/type_key.hpp @@ -0,0 +1,54 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_BINDING_INTERNAL_TYPE_KEY_HPP +#define TAO_JSON_BINDING_INTERNAL_TYPE_KEY_HPP + +#include + +#include "../../internal/string_t.hpp" +#include "../../internal/type_traits.hpp" + +namespace tao::json::binding::internal +{ + struct use_default_key + {}; + + template< typename K, typename V > + struct type_key; + + template< char... Cs, typename V > + struct type_key< json::internal::string_t< Cs... >, V > + { + template< template< typename... > class Traits > + [[nodiscard]] static std::string key() + { + return json::internal::string_t< Cs... >::as_string(); + } + + template< template< typename... > class Traits = traits, typename Consumer > + static void produce_key( Consumer& consumer ) + { + consumer.key( json::internal::string_t< Cs... >::as_string_view() ); + } + }; + + template< typename V > + struct type_key< use_default_key, V > + { + template< template< typename... > class Traits > + [[nodiscard]] static std::string key() + { + return Traits< V >::template default_key< Traits >::as_string(); + } + + template< template< typename... > class Traits = traits, typename Consumer > + static void produce_key( Consumer& consumer ) + { + consumer.key( Traits< V >::template default_key< Traits >::as_string_view() ); + } + }; + +} // namespace tao::json::binding::internal + +#endif diff --git a/include/tao/json/binding/member.hpp b/include/tao/json/binding/member.hpp new file mode 100644 index 00000000..eb785a34 --- /dev/null +++ b/include/tao/json/binding/member.hpp @@ -0,0 +1,32 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_BINDING_MEMBER_HPP +#define TAO_JSON_BINDING_MEMBER_HPP + +#include + +#include "element.hpp" +#include "member_kind.hpp" + +#include "internal/type_key.hpp" + +namespace tao::json::binding +{ + template< member_kind R, typename K, auto P > + struct member + : element< P >, + internal::type_key< K, typename binding::element< P >::internal_t > + { + static constexpr member_kind kind = R; + + template< template< typename... > class Traits, typename C > + [[nodiscard]] static bool is_nothing( const C& x ) + { + return json::internal::is_nothing< Traits >( binding::element< P >::read( x ) ); + } + }; + +} // namespace tao::json::binding + +#endif diff --git a/include/tao/json/binding/member_kind.hpp b/include/tao/json/binding/member_kind.hpp new file mode 100644 index 00000000..019dad08 --- /dev/null +++ b/include/tao/json/binding/member_kind.hpp @@ -0,0 +1,17 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_BINDING_MEMBER_KIND_HPP +#define TAO_JSON_BINDING_MEMBER_KIND_HPP + +namespace tao::json::binding +{ + enum class member_kind : bool + { + optional, + required + }; + +} // namespace tao::json::binding + +#endif diff --git a/include/tao/json/binding/versions.hpp b/include/tao/json/binding/versions.hpp new file mode 100644 index 00000000..5759c5e9 --- /dev/null +++ b/include/tao/json/binding/versions.hpp @@ -0,0 +1,127 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_BINDING_VERSIONS_HPP +#define TAO_JSON_BINDING_VERSIONS_HPP + +#include +#include + +#include "../forward.hpp" +#include "../internal/format.hpp" +#include "../internal/type_traits.hpp" + +namespace tao::json::binding +{ + template< typename... Vs > + struct versions; + + template< typename V > + struct versions< V > + : V + {}; + + template< typename V, typename... Vs > + struct versions< V, Vs... > + : V + { + template< typename C > + static void throw_on_error( const bool ok, const std::exception_ptr& e ) + { + if( !ok ) { + try { + std::rethrow_exception( e ); // TODO: Did I miss a way to avoid the throw? + } + catch( ... ) { + std::throw_with_nested( std::runtime_error( json::internal::format( "all versions failed for type ", pegtl::internal::demangle< C >(), " -- see nested for first error" ) ) ); + } + } + } + + template< template< typename... > class Traits, typename C > + [[nodiscard]] static std::exception_ptr first_to( const basic_value< Traits >& v, C& x ) noexcept + { + try { + if constexpr( json::internal::has_to< V, basic_value< Traits >, C > ) { + V::to( v, x ); + } + else if constexpr( json::internal::has_as< V, basic_value< Traits > > ) { + x = V::as( v ); + } + else { + static_assert( std::is_void_v< V >, "neither V::to() nor V::as() found" ); + } + return std::exception_ptr(); + } + catch( ... ) { + return std::current_exception(); + } + } + + template< typename A, template< typename... > class Traits, typename C > + [[nodiscard]] static bool later_to( const basic_value< Traits >& v, C& x ) noexcept + { + try { + if constexpr( json::internal::has_to< A, basic_value< Traits >, C > ) { + A::to( v, x ); + } + else if constexpr( json::internal::has_as< A, basic_value< Traits > > ) { + x = A::as( v ); + } + else { + static_assert( std::is_void_v< A >, "neither A::to() nor A::as() found" ); + } + return true; + } + catch( ... ) { + return false; + } + } + + template< template< typename... > class Traits, typename C > + static void to( const basic_value< Traits >& v, C& x ) + { + const std::exception_ptr e = first_to( v, x ); + const bool ok = ( ( e == std::exception_ptr() ) || ... || later_to< Vs >( v, x ) ); + throw_on_error< C >( ok, e ); + } + + template< template< typename... > class Traits, typename Producer, typename C > + [[nodiscard]] static std::exception_ptr first_consume( Producer& parser, C& x ) + { + try { + auto m = parser.mark(); + V::template consume< Traits >( parser, x ); + (void)m( true ); + return std::exception_ptr(); + } + catch( ... ) { + return std::current_exception(); + } + } + + template< typename A, template< typename... > class Traits, typename Producer, typename C > + [[nodiscard]] static bool later_consume( Producer& parser, C& x ) + { + try { + auto m = parser.mark(); + A::template consume< Traits >( parser, x ); + return m( true ); + } + catch( ... ) { + return false; + } + } + + template< template< typename... > class Traits, typename Producer, typename C > + static void consume( Producer& parser, C& x ) + { + const std::exception_ptr e = first_consume< Traits >( parser, x ); + const bool ok = ( ( e == std::exception_ptr() ) || ... || later_consume< Vs, Traits >( parser, x ) ); + throw_on_error< C >( ok, e ); + } + }; + +} // namespace tao::json::binding + +#endif diff --git a/include/tao/json/byte_view.hpp b/include/tao/json/byte_view.hpp deleted file mode 100644 index f9c2d79a..00000000 --- a/include/tao/json/byte_view.hpp +++ /dev/null @@ -1,445 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_INCLUDE_BYTE_VIEW_HPP -#define TAOCPP_INCLUDE_BYTE_VIEW_HPP - -#include -#include -#include -#include -#include -#include -#include - -#include "internal/identity.hpp" - -#include "external/byte.hpp" - -namespace tao -{ - // modelled after C++17's basic_string_view - template< class byteT > - class basic_byte_view - { - public: - using value_type = byteT; - using pointer = value_type*; - using const_pointer = const value_type*; - using reference = value_type&; - using const_reference = const value_type&; - using const_iterator = const value_type*; - using iterator = const_iterator; - using const_reverse_iterator = std::reverse_iterator< const_iterator >; - using reverse_iterator = const_reverse_iterator; - using size_type = size_t; - using difference_type = ptrdiff_t; - - static constexpr size_type npos = size_type( -1 ); - - constexpr basic_byte_view() noexcept - : data_( nullptr ), size_( 0 ) - { - } - - constexpr basic_byte_view( const byteT* str, size_type len ) noexcept - : data_( str ), size_( len ) - { - } - - constexpr basic_byte_view( const byteT* b, const byteT* e ) noexcept - : data_( b ), size_( e - b ) - { - } - - constexpr basic_byte_view( const std::vector< byteT >& str ) noexcept - : data_( str.data() ), size_( str.size() ) - { - } - - constexpr basic_byte_view( const basic_byte_view& ) noexcept = default; - /*constexpr*/ basic_byte_view& operator=( const basic_byte_view& ) noexcept = default; - - constexpr const_iterator begin() const noexcept - { - return data_; - } - - constexpr const_iterator end() const noexcept - { - return begin() + size(); - } - - constexpr const_iterator cbegin() const noexcept - { - return begin(); - } - - constexpr const_iterator cend() const noexcept - { - return begin() + size(); - } - - constexpr const_reverse_iterator rbegin() const noexcept - { - return const_reverse_iterator( end() ); - } - - constexpr const_reverse_iterator rend() const noexcept - { - return const_reverse_iterator( begin() ); - } - - constexpr const_reverse_iterator crbegin() const noexcept - { - return const_reverse_iterator( end() ); - } - - constexpr const_reverse_iterator crend() const noexcept - { - return const_reverse_iterator( begin() ); - } - - constexpr size_type size() const noexcept - { - return size_; - } - - constexpr size_type length() const noexcept - { - return size_; - } - - constexpr size_type max_size() const noexcept - { - return npos - 1; - } - - constexpr bool empty() const noexcept - { - return size_ == 0; - } - - constexpr const_reference operator[]( size_type pos ) const noexcept - { - return data_[ pos ]; - } - - constexpr const_reference at( size_type pos ) const - { - return ( pos >= size() ) ? throw std::out_of_range( "index out of range in tao::basic_byte_view::at" ) : data_[ pos ]; - } - - constexpr const_reference front() const noexcept - { - return data_[ 0 ]; - } - - constexpr const_reference back() const noexcept - { - return data_[ size() - 1 ]; - } - - constexpr const_pointer data() const noexcept - { - return data_; - } - - /*constexpr*/ void remove_prefix( size_type n ) noexcept - { - data_ += n; - size_ -= n; - } - - /*constexpr*/ void remove_suffix( size_type n ) noexcept - { - size_ -= n; - } - - /*constexpr*/ void swap( basic_byte_view& s ) noexcept - { - std::swap( data_, s.data_ ); - std::swap( size_, s.size_ ); - } - - size_type copy( byteT* s, size_type n, size_type pos = 0 ) const - { - if( pos > size() ) { - throw std::out_of_range( "index out of range in tao::basic_byte_view::copy" ); - } - const size_type rlen = std::min( n, size() - pos ); - std::memcpy( s, data() + pos, rlen ); - return rlen; - } - - constexpr basic_byte_view substr( size_type pos = 0, size_type n = npos ) const - { - return ( pos > size() ) ? throw std::out_of_range( "index out of range in tao::basic_byte_view::substr" ) : basic_byte_view( data() + pos, std::min( n, size() - pos ) ); - } - - /*constexpr*/ int compare( basic_byte_view s ) const noexcept - { - const size_type rlen = std::min( size(), s.size() ); - const int result = std::memcmp( data(), s.data(), rlen ); - if( result == 0 && size() != s.size() ) { - return ( size() < s.size() ) ? -1 : 1; - } - return result; - } - - constexpr int compare( size_type pos1, size_type n1, basic_byte_view s ) const - { - return substr( pos1, n1 ).compare( s ); - } - - constexpr int compare( size_type pos1, size_type n1, basic_byte_view s, size_type pos2, size_type n2 ) const - { - return substr( pos1, n1 ).compare( s.substr( pos2, n2 ) ); - } - - constexpr int compare( const byteT* s ) const - { - return compare( basic_byte_view( s ) ); - } - - constexpr int compare( size_type pos1, size_type n1, const byteT* s, size_type n2 ) const - { - return substr( pos1, n1 ).compare( basic_byte_view( s, n2 ) ); - } - - /*constexpr*/ size_type find( basic_byte_view s, size_type pos = 0 ) const noexcept - { - if( pos > size() - s.size() ) { - return npos; - } - const auto iter = std::search( begin() + pos, end(), s.begin(), s.end() ); - return iter == end() ? npos : iter - begin(); - } - - constexpr size_type find( byteT c, size_type pos = 0 ) const noexcept - { - return find( basic_byte_view( &c, 1 ), pos ); - } - - constexpr size_type find( const byteT* s, size_type pos, size_type n ) const noexcept - { - return find( basic_byte_view( s, n ), pos ); - } - - /*constexpr*/ size_type rfind( basic_byte_view s, size_type pos = npos ) const noexcept - { - if( pos > size() - s.size() ) { - return npos; - } - const auto iter = std::find_end( begin() + pos, end(), s.begin(), s.end() ); - return iter == end() ? npos : iter - begin(); - } - - constexpr size_type rfind( byteT c, size_type pos = npos ) const noexcept - { - return rfind( basic_byte_view( &c, 1 ), pos ); - } - - constexpr size_type rfind( const byteT* s, size_type pos, size_type n ) const noexcept - { - return rfind( basic_byte_view( s, n ), pos ); - } - - /*constexpr*/ size_type find_first_of( basic_byte_view s, size_type pos = 0 ) const noexcept - { - if( pos > size() - 1 ) { - return npos; - } - const auto iter = std::find_first_of( begin() + pos, end(), s.begin(), s.end() ); - return iter == end() ? npos : iter - begin(); - } - - constexpr size_type find_first_of( byteT c, size_type pos = 0 ) const noexcept - { - return find_first_of( basic_byte_view( &c, 1 ), pos ); - } - - constexpr size_type find_first_of( const byteT* s, size_type pos, size_type n ) const noexcept - { - return find_first_of( basic_byte_view( s, n ), pos ); - } - - /*constexpr*/ size_type find_last_of( basic_byte_view s, size_type pos = npos ) const noexcept - { - if( pos > size() - 1 ) { - return npos; - } - const auto iter = std::find_first_of( rbegin() + pos, rend(), s.begin(), s.end() ); - return iter == rend() ? npos : iter.base() - 1 - begin(); - } - - constexpr size_type find_last_of( byteT c, size_type pos = npos ) const noexcept - { - return find_last_of( basic_byte_view( &c, 1 ), pos ); - } - - constexpr size_type find_last_of( const byteT* s, size_type pos, size_type n ) const noexcept - { - return find_last_of( basic_byte_view( s, n ), pos ); - } - - /*constexpr*/ size_type find_first_not_of( basic_byte_view s, size_type pos = 0 ) const noexcept - { - if( pos > size() - 1 ) { - return npos; - } - const auto iter = std::find_if( begin() + pos, end(), [&]( char c ) { - return std::find( s.begin(), s.end(), c ) == s.end(); - } ); - return iter == end() ? npos : iter - begin(); - } - - constexpr size_type find_first_not_of( byteT c, size_type pos = 0 ) const noexcept - { - return find_first_not_of( basic_byte_view( &c, 1 ), pos ); - } - - constexpr size_type find_first_not_of( const byteT* s, size_type pos, size_type n ) const noexcept - { - return find_first_not_of( basic_byte_view( s, n ), pos ); - } - - /*constexpr*/ size_type find_last_not_of( basic_byte_view s, size_type pos = npos ) const noexcept - { - if( pos > size() - 1 ) { - return npos; - } - const auto iter = std::find_if( rbegin() + pos, rend(), [&]( char c ) { - return std::find( s.begin(), s.end(), c ) == s.end(); - } ); - return iter == rend() ? npos : iter.base() - 1 - begin(); - } - - constexpr size_type find_last_not_of( byteT c, size_type pos = npos ) const noexcept - { - return find_last_not_of( basic_byte_view( &c, 1 ), pos ); - } - - constexpr size_type find_last_not_of( const byteT* s, size_type pos, size_type n ) const noexcept - { - return find_first_not_of( basic_byte_view( s, n ), pos ); - } - - private: - const_pointer data_; - size_type size_; - }; - - template< class byteT > - constexpr bool operator==( basic_byte_view< byteT > x, basic_byte_view< byteT > y ) noexcept - { - return x.compare( y ) == 0; - } - - template< class byteT > - constexpr bool operator==( basic_byte_view< byteT > x, internal::identity< basic_byte_view< byteT > > y ) noexcept - { - return x.compare( y ) == 0; - } - - template< class byteT > - constexpr bool operator==( internal::identity< basic_byte_view< byteT > > x, basic_byte_view< byteT > y ) noexcept - { - return x.compare( y ) == 0; - } - - template< class byteT > - constexpr bool operator!=( basic_byte_view< byteT > x, basic_byte_view< byteT > y ) noexcept - { - return x.compare( y ) != 0; - } - - template< class byteT > - constexpr bool operator!=( basic_byte_view< byteT > x, internal::identity< basic_byte_view< byteT > > y ) noexcept - { - return x.compare( y ) != 0; - } - - template< class byteT > - constexpr bool operator!=( internal::identity< basic_byte_view< byteT > > x, basic_byte_view< byteT > y ) noexcept - { - return x.compare( y ) != 0; - } - - template< class byteT > - constexpr bool operator<( basic_byte_view< byteT > x, basic_byte_view< byteT > y ) noexcept - { - return x.compare( y ) < 0; - } - - template< class byteT > - constexpr bool operator<( basic_byte_view< byteT > x, internal::identity< basic_byte_view< byteT > > y ) noexcept - { - return x.compare( y ) < 0; - } - - template< class byteT > - constexpr bool operator<( internal::identity< basic_byte_view< byteT > > x, basic_byte_view< byteT > y ) noexcept - { - return x.compare( y ) < 0; - } - - template< class byteT > - constexpr bool operator>( basic_byte_view< byteT > x, basic_byte_view< byteT > y ) noexcept - { - return x.compare( y ) > 0; - } - - template< class byteT > - constexpr bool operator>( basic_byte_view< byteT > x, internal::identity< basic_byte_view< byteT > > y ) noexcept - { - return x.compare( y ) > 0; - } - - template< class byteT > - constexpr bool operator>( internal::identity< basic_byte_view< byteT > > x, basic_byte_view< byteT > y ) noexcept - { - return x.compare( y ) > 0; - } - - template< class byteT > - constexpr bool operator<=( basic_byte_view< byteT > x, basic_byte_view< byteT > y ) noexcept - { - return x.compare( y ) <= 0; - } - - template< class byteT > - constexpr bool operator<=( basic_byte_view< byteT > x, internal::identity< basic_byte_view< byteT > > y ) noexcept - { - return x.compare( y ) <= 0; - } - - template< class byteT > - constexpr bool operator<=( internal::identity< basic_byte_view< byteT > > x, basic_byte_view< byteT > y ) noexcept - { - return x.compare( y ) <= 0; - } - - template< class byteT > - constexpr bool operator>=( basic_byte_view< byteT > x, basic_byte_view< byteT > y ) noexcept - { - return x.compare( y ) >= 0; - } - - template< class byteT > - constexpr bool operator>=( basic_byte_view< byteT > x, internal::identity< basic_byte_view< byteT > > y ) noexcept - { - return x.compare( y ) >= 0; - } - - template< class byteT > - constexpr bool operator>=( internal::identity< basic_byte_view< byteT > > x, basic_byte_view< byteT > y ) noexcept - { - return x.compare( y ) >= 0; - } - - using byte_view = basic_byte_view< tao::byte >; - -} // namespace tao - -#endif diff --git a/include/tao/json/cbor.hpp b/include/tao/json/cbor.hpp index cf5935dd..ccd77f60 100644 --- a/include/tao/json/cbor.hpp +++ b/include/tao/json/cbor.hpp @@ -1,12 +1,17 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_CBOR_HPP -#define TAOCPP_JSON_INCLUDE_CBOR_HPP +#ifndef TAO_JSON_CBOR_HPP +#define TAO_JSON_CBOR_HPP #include "../json.hpp" +#include "cbor/consume_file.hpp" +#include "cbor/consume_string.hpp" +#include "cbor/from_file.hpp" +#include "cbor/from_input.hpp" #include "cbor/from_string.hpp" +#include "cbor/parts_parser.hpp" #include "cbor/to_stream.hpp" #include "cbor/to_string.hpp" diff --git a/include/tao/json/cbor/consume_file.hpp b/include/tao/json/cbor/consume_file.hpp new file mode 100644 index 00000000..b09adf70 --- /dev/null +++ b/include/tao/json/cbor/consume_file.hpp @@ -0,0 +1,34 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CBOR_CONSUME_FILE_HPP +#define TAO_JSON_CBOR_CONSUME_FILE_HPP + +#include + +#include "../external/pegtl/file_input.hpp" + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "parts_parser.hpp" + +namespace tao::json::cbor +{ + template< typename T, template< typename... > class Traits = traits, typename F > + [[nodiscard]] T consume_file( F&& filename ) + { + cbor::basic_parts_parser< utf8_mode::check, pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); + return json::consume< T, Traits >( pp ); + } + + template< template< typename... > class Traits = traits, typename F, typename T > + void consume_file( F&& filename, T& t ) + { + cbor::basic_parts_parser< utf8_mode::check, pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); + json::consume< Traits >( pp, t ); + } + +} // namespace tao::json::cbor + +#endif diff --git a/include/tao/json/cbor/consume_string.hpp b/include/tao/json/cbor/consume_string.hpp new file mode 100644 index 00000000..a6d54dd5 --- /dev/null +++ b/include/tao/json/cbor/consume_string.hpp @@ -0,0 +1,32 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CBOR_CONSUME_STRING_HPP +#define TAO_JSON_CBOR_CONSUME_STRING_HPP + +#include "../external/pegtl/string_input.hpp" + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "parts_parser.hpp" + +namespace tao::json::cbor +{ + template< typename T, template< typename... > class Traits = traits, typename F > + [[nodiscard]] T consume_string( F&& string ) + { + cbor::basic_parts_parser< utf8_mode::check, pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); + return json::consume< T, Traits >( pp ); + } + + template< template< typename... > class Traits = traits, typename F, typename T > + void consume_string( F&& string, T& t ) + { + cbor::basic_parts_parser< utf8_mode::check, pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); + json::consume< Traits >( pp, t ); + } + +} // namespace tao::json::cbor + +#endif diff --git a/include/tao/json/cbor/events/from_file.hpp b/include/tao/json/cbor/events/from_file.hpp new file mode 100644 index 00000000..ea94b7b3 --- /dev/null +++ b/include/tao/json/cbor/events/from_file.hpp @@ -0,0 +1,27 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CBOR_EVENTS_FROM_FILE_HPP +#define TAO_JSON_CBOR_EVENTS_FROM_FILE_HPP + +#include + +#include "../../external/pegtl/file_input.hpp" +#include "../../external/pegtl/parse.hpp" + +#include "../internal/grammar.hpp" + +namespace tao::json::cbor::events +{ + // Events producer to parse a file containing a CBOR string representation. + + template< typename T, typename Consumer > + void from_file( Consumer& consumer, T&& filename ) + { + pegtl::file_input< pegtl::tracking_mode::lazy > in( std::forward< T >( filename ) ); + pegtl::parse< internal::grammar >( in, consumer ); + } + +} // namespace tao::json::cbor::events + +#endif diff --git a/include/tao/json/cbor/events/from_input.hpp b/include/tao/json/cbor/events/from_input.hpp new file mode 100644 index 00000000..22a46383 --- /dev/null +++ b/include/tao/json/cbor/events/from_input.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CBOR_EVENTS_FROM_INPUT_HPP +#define TAO_JSON_CBOR_EVENTS_FROM_INPUT_HPP + +#include + +#include "../../external/pegtl/parse.hpp" + +#include "../internal/grammar.hpp" + +namespace tao::json::cbor::events +{ + // Events producers that parse CBOR from a PEGTL input (or something compatible). + + template< typename Consumer, typename Input > + void from_input( Consumer& consumer, Input&& in ) + { + pegtl::parse< cbor::internal::grammar >( std::forward< Input >( in ), consumer ); + } + + template< typename Consumer, typename Input > + void from_input_embedded( Consumer& consumer, Input&& in ) + { + pegtl::parse< cbor::internal::embedded >( std::forward< Input >( in ), consumer ); + } + + template< typename Consumer, typename Outer, typename Input > + void from_input_nested( Consumer& consumer, const Outer& oi, Input&& in ) + { + pegtl::parse_nested< cbor::internal::grammar >( oi, std::forward< Input >( in ), consumer ); + } + + template< typename Consumer, typename Outer, typename Input > + void from_input_embedded_nested( Consumer& consumer, const Outer& oi, Input&& in ) + { + pegtl::parse_nested< cbor::internal::embedded >( oi, std::forward< Input >( in ), consumer ); + } + +} // namespace tao::json::cbor::events + +#endif diff --git a/include/tao/json/cbor/events/from_string.hpp b/include/tao/json/cbor/events/from_string.hpp new file mode 100644 index 00000000..3659ae50 --- /dev/null +++ b/include/tao/json/cbor/events/from_string.hpp @@ -0,0 +1,37 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CBOR_EVENTS_FROM_STRING_HPP +#define TAO_JSON_CBOR_EVENTS_FROM_STRING_HPP + +#include +#include + +#include "../../external/pegtl/memory_input.hpp" + +#include "from_input.hpp" + +namespace tao::json::cbor::events +{ + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t byte_in_line = 0 ) + { + pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::cbor::events::from_string", byte, line, byte_in_line ); + cbor::events::from_input( consumer, std::move( in ) ); + } + + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) + { + cbor::events::from_string( consumer, data, size, source.c_str(), byte, line, column ); + } + + template< typename Consumer, typename... Ts > + void from_string( Consumer& consumer, const std::string_view data, Ts&&... ts ) + { + cbor::events::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); + } + +} // namespace tao::json::cbor::events + +#endif diff --git a/include/tao/json/cbor/events/to_stream.hpp b/include/tao/json/cbor/events/to_stream.hpp new file mode 100644 index 00000000..db66da17 --- /dev/null +++ b/include/tao/json/cbor/events/to_stream.hpp @@ -0,0 +1,161 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CBOR_EVENTS_TO_STREAM_HPP +#define TAO_JSON_CBOR_EVENTS_TO_STREAM_HPP + +#include +#include +#include +#include + +#include "../internal/major.hpp" + +#include "../../binary_view.hpp" + +#include "../../internal/endian.hpp" + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4310 ) +#endif + +namespace tao::json::cbor::events +{ + class to_stream + { + private: + std::ostream& os; + + public: + explicit to_stream( std::ostream& in_os ) noexcept + : os( in_os ) + {} + + void null() + { + os.put( char( std::uint8_t( internal::major::OTHER ) + 22 ) ); + } + + void boolean( const bool v ) + { + os.put( char( std::uint8_t( internal::major::OTHER ) + 20 + std::uint8_t( v ) ) ); + } + + void number( const internal::major m, const std::uint64_t v ) + { + if( v < 24 ) { + os.put( char( std::uint8_t( m ) + v ) ); + } + else if( v < 256 ) { + os.put( char( std::uint8_t( m ) + 24 ) ); + os.put( char( v ) ); + } + else if( v < 65536 ) { + os.put( char( std::uint8_t( m ) + 25 ) ); + const std::uint16_t x = json::internal::h_to_be( std::uint16_t( v ) ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else if( v < 4294967296ULL ) { + os.put( char( std::uint8_t( m ) + 26 ) ); + const std::uint32_t x = json::internal::h_to_be( std::uint32_t( v ) ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else { + os.put( char( std::uint8_t( m ) + 27 ) ); + const std::uint64_t x = json::internal::h_to_be( v ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + } + + void number( const std::int64_t v ) + { + if( v >= 0 ) { + number( internal::major::UNSIGNED, v ); + } + else { + number( internal::major::NEGATIVE, -( v + 1 ) ); + } + } + + void number( const std::uint64_t v ) + { + number( internal::major::UNSIGNED, v ); + } + + void number( const double v ) + { + std::uint64_t n; + std::memcpy( &n, &v, sizeof( n ) ); + n = json::internal::h_to_be( n ); + os.put( char( std::uint8_t( internal::major::OTHER ) + 27 ) ); + os.write( reinterpret_cast< const char* >( &n ), sizeof( n ) ); + } + + void string( const std::string_view v ) + { + number( internal::major::STRING, v.size() ); + os.write( v.data(), v.size() ); + } + + void binary( const tao::binary_view v ) + { + number( internal::major::BINARY, v.size() ); + os.write( reinterpret_cast< const char* >( v.data() ), v.size() ); + } + + void begin_array() + { + os.put( char( std::uint8_t( internal::major::ARRAY ) + internal::minor_mask ) ); + } + + void begin_array( const std::size_t size ) + { + number( internal::major::ARRAY, size ); + } + + void element() noexcept + {} + + void end_array() + { + os.put( char( 0xff ) ); + } + + void end_array( const std::size_t /*unused*/ ) noexcept + {} + + void begin_object() + { + os.put( char( std::uint8_t( internal::major::OBJECT ) + internal::minor_mask ) ); + } + + void begin_object( const std::size_t size ) + { + number( internal::major::OBJECT, size ); + } + + void key( const std::string_view v ) + { + string( v ); + } + + void member() noexcept + {} + + void end_object() + { + os.put( char( 0xff ) ); + } + + void end_object( const std::size_t /*unused*/ ) noexcept + {} + }; + +} // namespace tao::json::cbor::events + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + +#endif diff --git a/include/tao/json/cbor/events/to_string.hpp b/include/tao/json/cbor/events/to_string.hpp new file mode 100644 index 00000000..f323e3c7 --- /dev/null +++ b/include/tao/json/cbor/events/to_string.hpp @@ -0,0 +1,31 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CBOR_EVENTS_TO_STRING_HPP +#define TAO_JSON_CBOR_EVENTS_TO_STRING_HPP + +#include + +#include "to_stream.hpp" + +namespace tao::json::cbor::events +{ + struct to_string + : to_stream + { + std::ostringstream oss; + + to_string() + : to_stream( oss ) + { + } + + [[nodiscard]] std::string value() const + { + return oss.str(); + } + }; + +} // namespace tao::json::cbor::events + +#endif diff --git a/include/tao/json/cbor/from_file.hpp b/include/tao/json/cbor/from_file.hpp new file mode 100644 index 00000000..89f18ff1 --- /dev/null +++ b/include/tao/json/cbor/from_file.hpp @@ -0,0 +1,33 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CBOR_FROM_FILE_HPP +#define TAO_JSON_CBOR_FROM_FILE_HPP + +#include +#include + +#include "../events/to_value.hpp" +#include "../events/transformer.hpp" + +#include "events/from_file.hpp" + +namespace tao::json::cbor +{ + template< template< typename... > class Traits, template< typename... > class... Transformers > + [[nodiscard]] basic_value< Traits > basic_from_file( const std::string& filename ) + { + json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; + events::from_file( consumer, filename ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers > + [[nodiscard]] value from_file( const std::string& filename ) + { + return basic_from_file< traits, Transformers... >( filename ); + } + +} // namespace tao::json::cbor + +#endif diff --git a/include/tao/json/cbor/from_input.hpp b/include/tao/json/cbor/from_input.hpp new file mode 100644 index 00000000..c5df41f9 --- /dev/null +++ b/include/tao/json/cbor/from_input.hpp @@ -0,0 +1,33 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CBOR_FROM_INPUT_HPP +#define TAO_JSON_CBOR_FROM_INPUT_HPP + +#include +#include + +#include "../events/to_value.hpp" +#include "../events/transformer.hpp" + +#include "events/from_input.hpp" + +namespace tao::json::cbor +{ + template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] basic_value< Traits > basic_from_input( Ts&&... ts ) + { + json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; + cbor::events::from_input( consumer, std::forward< Ts >( ts )... ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] value from_input( Ts&&... ts ) + { + return basic_from_input< traits, Transformers... >( std::forward< Ts >( ts )... ); + } + +} // namespace tao::json::cbor + +#endif diff --git a/include/tao/json/cbor/from_string.hpp b/include/tao/json/cbor/from_string.hpp index b5a4d112..d3c29112 100644 --- a/include/tao/json/cbor/from_string.hpp +++ b/include/tao/json/cbor/from_string.hpp @@ -1,40 +1,32 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_CBOR_FROM_STRING_HPP -#define TAOCPP_JSON_INCLUDE_CBOR_FROM_STRING_HPP +#ifndef TAO_JSON_CBOR_FROM_STRING_HPP +#define TAO_JSON_CBOR_FROM_STRING_HPP #include #include "../events/to_value.hpp" #include "../events/transformer.hpp" -#include "../events/cbor/from_string.hpp" +#include "events/from_string.hpp" -namespace tao +namespace tao::json::cbor { - namespace json + template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] basic_value< Traits > basic_from_string( Ts&&... ts ) { - namespace cbor - { - template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > - basic_value< Traits > basic_from_string( Ts&&... ts ) - { - events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; - events::cbor::from_string( consumer, std::forward< Ts >( ts )... ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers, typename... Ts > - value from_string( Ts&&... ts ) - { - return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); - } - - } // namespace cbor - - } // namespace json - -} // namespace tao + json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; + events::from_string( consumer, std::forward< Ts >( ts )... ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] value from_string( Ts&&... ts ) + { + return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); + } + +} // namespace tao::json::cbor #endif diff --git a/include/tao/json/cbor/internal/grammar.hpp b/include/tao/json/cbor/internal/grammar.hpp new file mode 100644 index 00000000..12449e92 --- /dev/null +++ b/include/tao/json/cbor/internal/grammar.hpp @@ -0,0 +1,417 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CBOR_INTERNAL_GRAMMAR_HPP +#define TAO_JSON_CBOR_INTERNAL_GRAMMAR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "major.hpp" + +#include "../../binary_view.hpp" +#include "../../external/pegtl.hpp" +#include "../../forward.hpp" +#include "../../internal/endian.hpp" +#include "../../internal/format.hpp" +#include "../../internal/parse_util.hpp" +#include "../../utf8.hpp" + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4702 ) +#endif + +namespace tao::json::cbor::internal +{ + template< typename Input > + void consume_or_throw( Input& in, const std::size_t size = 1 ) + { + json::internal::throw_on_empty( in, size ); + in.bump_in_this_line( size ); + } + + template< typename Input > + [[nodiscard]] major peek_major_unsafe( Input& in ) + { + return static_cast< major >( in.peek_uint8() & major_mask ); + } + + template< typename Input > + [[nodiscard]] std::uint8_t peek_minor_unsafe( Input& in ) + { + return in.peek_uint8() & minor_mask; + } + + template< typename Input > + [[nodiscard]] major peek_major( Input& in ) + { + return static_cast< major >( json::internal::peek_uint8( in ) & major_mask ); + } + + // Assume in.size( 1 ) >= 1 and in.peek_uint8() is the byte with major/minor. + + template< typename Input > + [[nodiscard]] double read_fp16( Input& in ) + { + json::internal::throw_on_empty( in, 3 ); + + const int half = ( in.peek_uint8( 1 ) << 8 ) + in.peek_uint8( 2 ); + const int exp = ( half >> 10 ) & 0x1f; + const int mant = half & 0x3ff; + + double val; + if( exp == 0 ) { + val = std::ldexp( mant, -24 ); + } + else if( exp != 31 ) { + val = std::ldexp( mant + 1024, exp - 25 ); + } + else { + val = ( mant == 0 ) ? INFINITY : NAN; + } + in.bump_in_this_line( 3 ); + return half & 0x8000 ? -val : val; + } + + template< typename Input > + [[nodiscard]] std::uint64_t read_embedded_unsafe( Input& in ) + { + const auto result = peek_minor_unsafe( in ) & minor_mask; + in.bump_in_this_line(); + return result; + } + + template< typename Input > + [[nodiscard]] std::uint64_t read_unsigned_unsafe( Input& in ) + { + switch( const auto m = peek_minor_unsafe( in ) ) { + default: + return read_embedded_unsafe( in ); + case 24: + return json::internal::read_big_endian_number< std::uint64_t, std::uint8_t >( in, 1 ); + case 25: + return json::internal::read_big_endian_number< std::uint64_t, std::uint16_t >( in, 1 ); + case 26: + return json::internal::read_big_endian_number< std::uint64_t, std::uint32_t >( in, 1 ); + case 27: + return json::internal::read_big_endian_number< std::uint64_t >( in, 1 ); + case 28: + case 29: + case 30: + case 31: + throw pegtl::parse_error( json::internal::format( "unexpected minor ", m, " for number or length" ), in ); + } + } + + template< typename Input > + [[nodiscard]] std::int64_t read_negative_unsafe( Input& in ) + { + const auto u = read_unsigned_unsafe( in ); + if( u > 9223372036854775808ULL ) { + throw pegtl::parse_error( "negative integer overflow", in ); + } + return std::int64_t( ~u ); + } + + template< typename Input > + [[nodiscard]] std::size_t read_size_unsafe( Input& in ) + { + const auto s = read_unsigned_unsafe( in ); + if( s > static_cast< std::uint64_t >( ( std::numeric_limits< std::size_t >::max )() ) ) { + throw pegtl::parse_error( "cbor size exceeds size_t " + std::to_string( s ), in ); + } + return static_cast< std::size_t >( s ); + } + + template< utf8_mode U, typename Result, typename Input > + [[nodiscard]] Result read_string_1( Input& in ) + { + const auto size = read_size_unsafe( in ); + json::internal::throw_on_empty( in, size ); + using value_t = typename Result::value_type; + const auto* pointer = reinterpret_cast< const value_t* >( in.current() ); + Result result( pointer, size ); + json::internal::consume_utf8_throws< U >( in, size ); + return result; + } + + template< utf8_mode U, typename Result, typename Input > + [[nodiscard]] Result read_string_n( Input& in, const major m ) + { + Result result; + in.bump_in_this_line(); + while( json::internal::peek_uint8( in ) != 0xff ) { + if( peek_major_unsafe( in ) != m ) { + throw pegtl::parse_error( "non-matching fragment in indefinite length string", in ); + } + const auto size = read_size_unsafe( in ); + json::internal::throw_on_empty( in, size ); + using value_t = typename Result::value_type; + const auto* pointer = static_cast< const value_t* >( static_cast< const void* >( in.current() ) ); + result.insert( result.end(), pointer, pointer + size ); + json::internal::consume_utf8_throws< U >( in, size ); + } + in.bump_in_this_line(); + return result; + } + + template< utf8_mode V > + struct data + { + using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; + + template< pegtl::apply_mode A, + pegtl::rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename Consumer > + [[nodiscard]] static bool match( Input& in, Consumer& consumer ) + { + if( !in.empty() ) { + parse_unsafe( in, consumer ); + return true; + } + return false; + } + + private: + template< typename Input, typename Consumer > + static void parse_unsafe( Input& in, Consumer& consumer ) + { + switch( peek_major_unsafe( in ) ) { + case major::UNSIGNED: + consumer.number( read_unsigned_unsafe( in ) ); + return; + case major::NEGATIVE: + consumer.number( read_negative_unsafe( in ) ); + return; + case major::BINARY: + parse_binary_unsafe( in, consumer ); + return; + case major::STRING: + parse_string_unsafe( in, consumer ); + return; + case major::ARRAY: + parse_array_unsafe( in, consumer ); + return; + case major::OBJECT: + parse_object_unsafe( in, consumer ); + return; + case major::TAG: + parse_tag_unsafe( in, consumer ); + return; + case major::OTHER: + parse_other_unsafe( in, consumer ); + return; + } + // LCOV_EXCL_START + assert( false ); + // LCOV_EXCL_STOP + } + + template< typename Input, typename Consumer > + static void parse_string_unsafe( Input& in, Consumer& consumer ) + { + if( peek_minor_unsafe( in ) != minor_mask ) { + consumer.string( read_string_1< V, std::string_view >( in ) ); + } + else { + consumer.string( read_string_n< V, std::string >( in, major::STRING ) ); + } + } + + template< typename Input, typename Consumer > + static void parse_binary_unsafe( Input& in, Consumer& consumer ) + { + if( peek_minor_unsafe( in ) != minor_mask ) { + consumer.binary( read_string_1< utf8_mode::trust, tao::binary_view >( in ) ); + } + else { + consumer.binary( read_string_n< utf8_mode::trust, std::vector< std::byte > >( in, major::BINARY ) ); + } + } + + template< typename Input, typename Consumer > + static void parse_key_unsafe( Input& in, Consumer& consumer ) + { + if( peek_minor_unsafe( in ) != minor_mask ) { + consumer.key( read_string_1< V, std::string_view >( in ) ); + } + else { + consumer.key( read_string_n< V, std::string >( in, major::STRING ) ); + } + } + + template< typename Input, typename Consumer > + static void parse_array_1( Input& in, Consumer& consumer ) + { + const auto size = read_size_unsafe( in ); + consumer.begin_array( size ); + for( std::size_t i = 0; i < size; ++i ) { + json::internal::throw_on_empty( in ); + parse_unsafe( in, consumer ); + consumer.element(); + } + consumer.end_array( size ); + } + + template< typename Input, typename Consumer > + static void parse_array_n( Input& in, Consumer& consumer ) + { + in.bump_in_this_line(); + consumer.begin_array(); + while( json::internal::peek_uint8( in ) != 0xff ) { + parse_unsafe( in, consumer ); + consumer.element(); + } + in.bump_in_this_line(); + consumer.end_array(); + } + + template< typename Input, typename Consumer > + static void parse_array_unsafe( Input& in, Consumer& consumer ) + { + if( peek_minor_unsafe( in ) != minor_mask ) { + parse_array_1( in, consumer ); + } + else { + parse_array_n( in, consumer ); + } + } + + template< typename Input, typename Consumer > + static void parse_object_1( Input& in, Consumer& consumer ) + { + const auto size = read_size_unsafe( in ); + consumer.begin_object( size ); + for( std::size_t i = 0; i < size; ++i ) { + if( peek_major( in ) != major::STRING ) { + throw pegtl::parse_error( "non-string object key", in ); + } + parse_key_unsafe( in, consumer ); + json::internal::throw_on_empty( in ); + parse_unsafe( in, consumer ); + consumer.member(); + } + consumer.end_object( size ); + } + + template< typename Input, typename Consumer > + static void parse_object_n( Input& in, Consumer& consumer ) + { + in.bump_in_this_line(); + consumer.begin_object(); + while( json::internal::peek_uint8( in ) != 0xff ) { + if( peek_major_unsafe( in ) != major::STRING ) { + throw pegtl::parse_error( "non-string object key", in ); + } + parse_key_unsafe( in, consumer ); + json::internal::throw_on_empty( in ); + parse_unsafe( in, consumer ); + consumer.member(); + } + in.bump_in_this_line(); + consumer.end_object(); + } + + template< typename Input, typename Consumer > + static void parse_object_unsafe( Input& in, Consumer& consumer ) + { + if( peek_minor_unsafe( in ) != minor_mask ) { + parse_object_1( in, consumer ); + } + else { + parse_object_n( in, consumer ); + } + } + + template< typename Input, typename Consumer > + static void parse_tag_unsafe( Input& in, Consumer& /*unused*/ ) + { + switch( const auto m = peek_minor_unsafe( in ) ) { + default: + in.bump_in_this_line(); + return; + case 24: + consume_or_throw( in, 2 ); + return; + case 25: + consume_or_throw( in, 3 ); + return; + case 26: + consume_or_throw( in, 5 ); + return; + case 27: + consume_or_throw( in, 9 ); + return; + case 28: + case 29: + case 30: + case 31: + throw pegtl::parse_error( json::internal::format( "unexpected minor ", m, " for tag" ), in ); + } + } + + template< typename Input, typename Consumer > + static void parse_other_unsafe( Input& in, Consumer& consumer ) + { + switch( const auto m = peek_minor_unsafe( in ) ) { + case 20: + consumer.boolean( false ); + in.bump_in_this_line(); + return; + case 21: + consumer.boolean( true ); + in.bump_in_this_line(); + return; + case 22: + consumer.null(); + in.bump_in_this_line(); + return; + case 25: + consumer.number( read_fp16( in ) ); + return; + case 26: + consumer.number( json::internal::read_big_endian_number< float >( in, 1 ) ); + return; + case 27: + consumer.number( json::internal::read_big_endian_number< double >( in, 1 ) ); + return; + default: + throw pegtl::parse_error( json::internal::format( "unsupported minor ", m, " for major 7" ), in ); + } + } + }; + + template< utf8_mode V > + struct basic_grammar + : pegtl::must< data< V >, pegtl::eof > + { + }; + + template< utf8_mode V > + struct basic_embedded + : pegtl::must< data< V > > + { + }; + + using grammar = basic_grammar< utf8_mode::check >; + using embedded = basic_embedded< utf8_mode::check >; + +} // namespace tao::json::cbor::internal + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + +#endif diff --git a/include/tao/json/cbor/internal/major.hpp b/include/tao/json/cbor/internal/major.hpp new file mode 100644 index 00000000..e0a9ebb7 --- /dev/null +++ b/include/tao/json/cbor/internal/major.hpp @@ -0,0 +1,28 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CBOR_INTERNAL_MAJOR_HPP +#define TAO_JSON_CBOR_INTERNAL_MAJOR_HPP + +#include + +namespace tao::json::cbor::internal +{ + enum class major : std::uint8_t + { + UNSIGNED = 0, + NEGATIVE = 0x20, + BINARY = 0x40, + STRING = 0x60, + ARRAY = 0x80, + OBJECT = 0xa0, + TAG = 0xc0, + OTHER = 0xe0 + }; + + static constexpr std::uint8_t major_mask = 0xe0; + static constexpr std::uint8_t minor_mask = 0x1f; + +} // namespace tao::json::cbor::internal + +#endif diff --git a/include/tao/json/cbor/parts_parser.hpp b/include/tao/json/cbor/parts_parser.hpp new file mode 100644 index 00000000..81bcfad5 --- /dev/null +++ b/include/tao/json/cbor/parts_parser.hpp @@ -0,0 +1,392 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CBOR_PARTS_PARSER_HPP +#define TAO_JSON_CBOR_PARTS_PARSER_HPP + +#include +#include + +#include "../events/discard.hpp" +#include "../external/pegtl/string_input.hpp" +#include "../utf8.hpp" + +#include "internal/grammar.hpp" + +namespace tao::json::cbor +{ + namespace internal + { + template< typename Input > + [[nodiscard]] major peek_first_major( Input& in ) + { + const auto m = peek_major( in ); + if( m != major::TAG ) { + return m; + } + switch( auto n = peek_minor_unsafe( in ) ) { + default: + in.bump_in_this_line(); + break; + case 24: + consume_or_throw( in, 2 ); + break; + case 25: + consume_or_throw( in, 3 ); + break; + case 26: + consume_or_throw( in, 5 ); + break; + case 27: + consume_or_throw( in, 9 ); + break; + case 28: + case 29: + case 30: + case 31: + throw pegtl::parse_error( json::internal::format( "unexpected minor ", n, " for tag" ), in ); + } + return peek_major( in ); + } + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4702 ) +#endif + template< typename Input > + [[nodiscard]] bool read_boolean( Input& in ) + { + const auto b = json::internal::peek_uint8( in ); + switch( b ) { + case std::uint8_t( major::OTHER ) + 20: + case std::uint8_t( major::OTHER ) + 21: + in.bump_in_this_line( 1 ); + return bool( b - std::uint8_t( major::OTHER ) - 20 ); + default: + throw pegtl::parse_error( "expected boolean", in ); + } + std::abort(); + } +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + + } // namespace internal + + template< utf8_mode V = utf8_mode::check, typename Input = pegtl::string_input< pegtl::tracking_mode::lazy > > + class basic_parts_parser + { + public: + template< typename... Ts > + explicit basic_parts_parser( Ts&&... ts ) + : m_input( std::forward< Ts >( ts )... ) + { + } + + [[nodiscard]] bool empty() + { + return m_input.empty(); + } + + [[nodiscard]] bool null() + { + if( json::internal::peek_uint8( m_input ) == std::uint8_t( internal::major::OTHER ) + 22 ) { + m_input.bump_in_this_line( 1 ); + return true; + } + return false; + } + + [[nodiscard]] bool boolean() + { + return internal::read_boolean( m_input ); + } + + private: + void check_major( const internal::major m, const char* e ) + { + const auto b = internal::peek_first_major( m_input ); + if( b != m ) { + throw pegtl::parse_error( e, m_input ); + } + } + + template< utf8_mode U, typename T > + [[nodiscard]] T string_impl( const internal::major m, const char* e ) + { + check_major( m, e ); + if( internal::peek_minor_unsafe( m_input ) != internal::minor_mask ) { + return internal::read_string_1< U, T >( m_input ); + } + return internal::read_string_n< U, T >( m_input, m ); + } + + public: + [[nodiscard]] std::string string() + { + return string_impl< V, std::string >( internal::major::STRING, "expected string" ); + } + + [[nodiscard]] std::string binary() + { + return string_impl< utf8_mode::trust, std::vector< std::byte > >( internal::major::BINARY, "expected binary" ); + } + + [[nodiscard]] std::string key() + { + return string(); + } + + [[nodiscard]] std::string_view string_view() + { + const auto b = json::internal::peek_uint8( m_input ); + if( b != std::uint8_t( internal::major::STRING ) + internal::minor_mask ) { + throw pegtl::parse_error( "expected definitive string", m_input ); + } + return internal::read_string_1< V, std::string_view >( m_input ); + } + + [[nodiscard]] tao::binary_view binary_view() + { + const auto b = json::internal::peek_uint8( m_input ); + if( b != std::uint8_t( internal::major::BINARY ) + internal::minor_mask ) { + throw pegtl::parse_error( "expected definitive binary", m_input ); + } + return internal::read_string_1< utf8_mode::trust, tao::binary_view >( m_input ); + } + + [[nodiscard]] std::string_view key_view() + { + return string_view(); + } + + private: + [[nodiscard]] std::int64_t number_signed_unsigned() + { + const auto u = internal::read_unsigned_unsafe( m_input ); + if( u > 9223372036854775807ULL ) { + throw pegtl::parse_error( "positive integer overflow", m_input ); + } + return std::int64_t( u ); + } + + [[nodiscard]] std::int64_t number_signed_negative() + { + const auto u = internal::read_unsigned_unsafe( m_input ); + if( u > 9223372036854775808ULL ) { + throw pegtl::parse_error( "negative integer overflow", m_input ); + } + return std::int64_t( ~u ); + } + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4702 ) +#endif + public: + [[nodiscard]] std::int64_t number_signed() + { + const auto b = internal::peek_first_major( m_input ); + switch( b ) { + case internal::major::UNSIGNED: + return number_signed_unsigned(); + case internal::major::NEGATIVE: + return number_signed_negative(); + default: + throw pegtl::parse_error( "expected integer", m_input ); + } + std::abort(); + } +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + + [[nodiscard]] std::uint64_t number_unsigned() + { + check_major( internal::major::UNSIGNED, "expected unsigned" ); + return internal::read_unsigned_unsafe( m_input ); + } + + [[nodiscard]] double number_double() + { + const auto b = json::internal::peek_uint8( m_input ); + switch( b ) { + case std::uint8_t( internal::major::OTHER ) + 25: + return internal::read_fp16( m_input ); + case std::uint8_t( internal::major::OTHER ) + 26: + return json::internal::read_big_endian_number< float >( m_input + 1 ); + case std::uint8_t( internal::major::OTHER ) + 27: + return json::internal::read_big_endian_number< double >( m_input + 1 ); + default: + throw pegtl::parse_error( "expected floating point number", m_input ); + } + } + + private: + struct state_t + { + state_t() = default; + + explicit state_t( const std::size_t in_size ) + : size( in_size ) + {} + + std::size_t i = 0; + std::optional< std::size_t > size; + }; + + [[nodiscard]] state_t begin_container() + { + if( internal::peek_minor_unsafe( m_input ) == 31 ) { + m_input.bump_in_this_line( 1 ); + return state_t(); + } + return state_t( internal::read_size_unsafe( m_input ) ); + } + + public: + [[nodiscard]] state_t begin_array() + { + check_major( internal::major::ARRAY, "expected array" ); + return begin_container(); + } + + [[nodiscard]] state_t begin_object() + { + check_major( internal::major::OBJECT, "expected object" ); + return begin_container(); + } + + private: + void end_container_sized( const state_t& p ) + { + if( *p.size != p.i ) { + throw pegtl::parse_error( "container size mismatch", m_input ); + } + } + + void end_container_indefinite() + { + if( json::internal::peek_uint8( m_input ) != 0xff ) { + throw pegtl::parse_error( "container not at end", m_input ); + } + m_input.bump_in_this_line( 1 ); + } + + void end_container( const state_t& p ) + { + if( p.size ) { + end_container_sized( p ); + } + else { + end_container_indefinite(); + } + } + + public: + void end_array( const state_t& p ) + { + end_container( p ); + } + + void end_object( const state_t& p ) + { + end_container( p ); + } + + private: + void next_in_container_sized( state_t& p ) + { + if( p.i++ >= *p.size ) { + throw pegtl::parse_error( "unexpected end of sized container", m_input ); + } + } + + void next_in_container_indefinite() + { + if( json::internal::peek_uint8( m_input ) == 0xff ) { + throw pegtl::parse_error( "unexpected end of indefinite container", m_input ); + } + } + + void next_in_container( state_t& p ) + { + if( p.size ) { + next_in_container_sized( p ); + } + else { + next_in_container_indefinite(); + } + } + + public: + void element( state_t& p ) + { + next_in_container( p ); + } + + void member( state_t& p ) + { + next_in_container( p ); + } + + private: + [[nodiscard]] bool next_or_end_container_sized( state_t& p ) + { + return p.i++ < *p.size; + } + + [[nodiscard]] bool next_or_end_container_indefinite() + { + if( json::internal::peek_uint8( m_input ) == 0xff ) { + m_input.bump_in_this_line( 1 ); + return false; + } + return true; + } + + [[nodiscard]] bool next_or_end_container( state_t& p ) + { + if( p.size ) { + return next_or_end_container_sized( p ); + } + return next_or_end_container_indefinite(); + } + + public: + [[nodiscard]] bool element_or_end_array( state_t& p ) + { + return next_or_end_container( p ); + } + + [[nodiscard]] bool member_or_end_object( state_t& p ) + { + return next_or_end_container( p ); + } + + void skip_value() + { + json::events::discard consumer; // TODO: Optimise to not generate events (which requires preparing their - discarded - arguments)? + pegtl::parse< pegtl::must< internal::data< V > > >( m_input, consumer ); + } + + [[nodiscard]] auto mark() + { + return m_input.template mark< pegtl::rewind_mode::required >(); + } + + template< typename T > + void throw_parse_error( T&& t ) const + { + throw pegtl::parse_error( std::forward< T >( t ), m_input ); + } + + protected: + Input m_input; + }; + + using parts_parser = basic_parts_parser<>; + +} // namespace tao::json::cbor + +#endif diff --git a/include/tao/json/cbor/to_stream.hpp b/include/tao/json/cbor/to_stream.hpp index f91f4d9b..520552b2 100644 --- a/include/tao/json/cbor/to_stream.hpp +++ b/include/tao/json/cbor/to_stream.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_CBOR_TO_STREAM_HPP -#define TAOCPP_JSON_INCLUDE_CBOR_TO_STREAM_HPP +#ifndef TAO_JSON_CBOR_TO_STREAM_HPP +#define TAO_JSON_CBOR_TO_STREAM_HPP #include @@ -11,25 +11,17 @@ #include "../events/from_value.hpp" #include "../events/transformer.hpp" -#include "../events/cbor/to_stream.hpp" +#include "events/to_stream.hpp" -namespace tao +namespace tao::json::cbor { - namespace json + template< template< typename... > class... Transformers, template< typename... > class Traits > + void to_stream( std::ostream& os, const basic_value< Traits >& v ) { - namespace cbor - { - template< template< typename... > class... Transformers, template< typename... > class Traits > - void to_stream( std::ostream& os, const basic_value< Traits >& v ) - { - events::transformer< events::cbor::to_stream, Transformers... > consumer( os ); - events::from_value( consumer, v ); - } + json::events::transformer< events::to_stream, Transformers... > consumer( os ); + json::events::from_value( consumer, v ); + } - } // namespace cbor - - } // namespace json - -} // namespace tao +} // namespace tao::json::cbor #endif diff --git a/include/tao/json/cbor/to_string.hpp b/include/tao/json/cbor/to_string.hpp index cf2eb45d..2f711689 100644 --- a/include/tao/json/cbor/to_string.hpp +++ b/include/tao/json/cbor/to_string.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_CBOR_TO_STRING_HPP -#define TAOCPP_JSON_INCLUDE_CBOR_TO_STRING_HPP +#ifndef TAO_JSON_CBOR_TO_STRING_HPP +#define TAO_JSON_CBOR_TO_STRING_HPP #include @@ -11,26 +11,18 @@ #include "../events/from_value.hpp" #include "../events/transformer.hpp" -#include "../events/cbor/to_string.hpp" +#include "events/to_string.hpp" -namespace tao +namespace tao::json::cbor { - namespace json + template< template< typename... > class... Transformers, template< typename... > class Traits > + [[nodiscard]] std::string to_string( const basic_value< Traits >& v ) { - namespace cbor - { - template< template< typename... > class... Transformers, template< typename... > class Traits > - std::string to_string( const basic_value< Traits >& v ) - { - events::transformer< events::cbor::to_string, Transformers... > consumer; - events::from_value( consumer, v ); - return consumer.value(); - } + json::events::transformer< events::to_string, Transformers... > consumer; + json::events::from_value( consumer, v ); + return consumer.value(); + } - } // namespace cbor - - } // namespace json - -} // namespace tao +} // namespace tao::json::cbor #endif diff --git a/include/tao/json/consume.hpp b/include/tao/json/consume.hpp new file mode 100644 index 00000000..7ec5ebae --- /dev/null +++ b/include/tao/json/consume.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONSUME_HPP +#define TAO_JSON_CONSUME_HPP + +#include + +#include "forward.hpp" + +#include "internal/type_traits.hpp" + +namespace tao::json +{ + template< typename T, template< typename... > class Traits = traits, typename Producer > + [[nodiscard]] std::enable_if_t< internal::has_consume_one< Traits, Producer, T >, T > consume( Producer& parser ) + { + return Traits< T >::template consume< Traits >( parser ); + } + + template< typename T, template< typename... > class Traits = traits, typename Producer > + [[nodiscard]] std::enable_if_t< !internal::has_consume_one< Traits, Producer, T >, T > consume( Producer& parser ) + { + T t; + Traits< T >::template consume< Traits >( parser, t ); + return t; + } + + template< template< typename... > class Traits = traits, typename Producer, typename T > + std::enable_if_t< internal::has_consume_two< Traits, Producer, T >, void > consume( Producer& parser, T& t ) + { + Traits< T >::template consume< Traits >( parser, t ); + } + + template< template< typename... > class Traits = traits, typename Producer, typename T > + std::enable_if_t< !internal::has_consume_two< Traits, Producer, T >, void > consume( Producer& parser, T& t ) + { + t = Traits< T >::template consume< Traits >( parser ); + } + +} // namespace tao::json + +#endif diff --git a/include/tao/json/consume_file.hpp b/include/tao/json/consume_file.hpp new file mode 100644 index 00000000..1ed6c5b2 --- /dev/null +++ b/include/tao/json/consume_file.hpp @@ -0,0 +1,33 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONSUME_FILE_HPP +#define TAO_JSON_CONSUME_FILE_HPP + +#include + +#include "external/pegtl/file_input.hpp" + +#include "consume.hpp" +#include "forward.hpp" +#include "parts_parser.hpp" + +namespace tao::json +{ + template< typename T, template< typename... > class Traits = traits, typename F > + [[nodiscard]] T consume_file( F&& filename ) + { + basic_parts_parser< pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); + return consume< T, Traits >( pp ); + } + + template< template< typename... > class Traits = traits, typename F, typename T > + void consume_file( F&& filename, T& t ) + { + basic_parts_parser< pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); + consume< Traits >( pp, t ); + } + +} // namespace tao::json + +#endif diff --git a/include/tao/json/consume_string.hpp b/include/tao/json/consume_string.hpp new file mode 100644 index 00000000..5c1573d8 --- /dev/null +++ b/include/tao/json/consume_string.hpp @@ -0,0 +1,31 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONSUME_STRING_HPP +#define TAO_JSON_CONSUME_STRING_HPP + +#include "external/pegtl/string_input.hpp" + +#include "consume.hpp" +#include "forward.hpp" +#include "parts_parser.hpp" + +namespace tao::json +{ + template< typename T, template< typename... > class Traits = traits, typename F > + [[nodiscard]] T consume_string( F&& string ) + { + basic_parts_parser< pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); + return consume< T, Traits >( pp ); + } + + template< template< typename... > class Traits = traits, typename F, typename T > + void consume_string( F&& string, T& t ) + { + basic_parts_parser< pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); + consume< Traits >( pp, t ); + } + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/array_traits.hpp b/include/tao/json/contrib/array_traits.hpp new file mode 100644 index 00000000..e05bef5e --- /dev/null +++ b/include/tao/json/contrib/array_traits.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_ARRAY_TRAITS_HPP +#define TAO_JSON_CONTRIB_ARRAY_TRAITS_HPP + +#include + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "internal/array_traits.hpp" + +namespace tao::json +{ + template< typename T, std::size_t N > + struct array_traits + : internal::array_traits< std::array< T, N > > + { + template< template< typename... > class Traits, typename... With > + static void to( const basic_value< Traits >& v, std::array< T, N >& r, With&... with ) + { + const auto& a = v.get_array(); + for( std::size_t i = 0; i < N; ++i ) { + v.to_with( r[ i ], with... ); + } + } + + template< template< typename... > class Traits, typename Producer > + static void consume( Producer& parser, std::array< T, N >& r ) + { + auto s = parser.begin_array(); + for( std::size_t i = 0; i < N; ++i ) { + parser.element( s ); + json::consume< Traits >( parser, r[ i ] ); + } + parser.end_array( s ); + } + }; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/deque_traits.hpp b/include/tao/json/contrib/deque_traits.hpp new file mode 100644 index 00000000..7ffbbd94 --- /dev/null +++ b/include/tao/json/contrib/deque_traits.hpp @@ -0,0 +1,41 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_DEQUE_TRAITS_HPP +#define TAO_JSON_CONTRIB_DEQUE_TRAITS_HPP + +#include + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "internal/array_traits.hpp" + +namespace tao::json +{ + template< typename T, typename... Ts > + struct deque_traits + : internal::array_traits< std::deque< T, Ts... > > + { + template< template< typename... > class Traits, typename... With > + static void to( const basic_value< Traits >& v, std::deque< T, Ts... >& r, With&... with ) + { + const auto& a = v.get_array(); + for( const auto& i : a ) { + r.emplace_back( i.template as_with< T >( with... ) ); + } + } + + template< template< typename... > class Traits, typename Producer > + static void consume( Producer& parser, std::vector< T, Ts... >& v ) + { + auto s = parser.begin_array(); + while( parser.element_or_end_array( s ) ) { + v.emplace_back( json::consume< T, Traits >( parser ) ); + } + } + }; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/diff.hpp b/include/tao/json/contrib/diff.hpp new file mode 100644 index 00000000..579f3d9c --- /dev/null +++ b/include/tao/json/contrib/diff.hpp @@ -0,0 +1,106 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_DIFF_HPP +#define TAO_JSON_CONTRIB_DIFF_HPP + +#include +#include +#include +#include + +#include "../pointer.hpp" +#include "../value.hpp" + +namespace tao::json +{ + namespace internal + { + template< typename... Ts > + void move_append( std::vector< Ts... >& lhs, std::vector< Ts... >& rhs ) + { + if( lhs.empty() ) { + lhs = std::move( rhs ); + } + else if( !rhs.empty() ) { + lhs.reserve( lhs.size() + rhs.size() ); + std::move( std::begin( rhs ), std::end( rhs ), std::back_inserter( lhs ) ); + } + } + + } // namespace internal + + template< template< typename... > class Traits > + [[nodiscard]] basic_value< Traits > diff( const basic_value< Traits >& source, const basic_value< Traits >& destination, const pointer& path = pointer() ) + { + basic_value< Traits > result = empty_array; + if( source == destination ) { + return result; + } + if( source.type() != destination.type() ) { + result.push_back( { { "op", "replace" }, + { "path", to_string( path ) }, + { "value", destination } } ); + } + else { + auto& a = result.get_array(); + switch( source.type() ) { + case type::ARRAY: { + const auto ss = source.get_array().size(); + const auto ds = destination.get_array().size(); + std::size_t i = 0; + while( ( i < ss ) && ( i < ds ) ) { + internal::move_append( a, diff( source.at( i ), destination.at( i ), path + i ).get_array() ); + ++i; + } + const auto s = ss + i - 1; + while( i < ss ) { + result.push_back( { { "op", "remove" }, + { "path", to_string( path + ( s - i ) ) } } ); + ++i; + } + while( i < ds ) { + result.push_back( { { "op", "add" }, + { "path", to_string( path + i ) }, + { "value", destination.at( i ) } } ); + ++i; + } + } break; + + case type::OBJECT: { + const auto& sm = source.get_object(); + const auto& dm = destination.get_object(); + auto sit = sm.begin(); + auto dit = dm.begin(); + while( ( sit != sm.end() ) || ( dit != dm.end() ) ) { + if( ( sit == sm.end() ) || ( ( dit != dm.end() ) && ( sit->first > dit->first ) ) ) { + result.push_back( { { "op", "add" }, + { "path", to_string( path + dit->first ) }, + { "value", dit->second } } ); + ++dit; + } + else if( ( dit == dm.end() ) || ( ( sit != sm.end() ) && ( sit->first < dit->first ) ) ) { + result.push_back( { { "op", "remove" }, + { "path", to_string( path + sit->first ) } } ); + ++sit; + } + else { + internal::move_append( a, diff( sit->second, dit->second, path + sit->first ).get_array() ); + ++sit; + ++dit; + } + } + } break; + + default: + result.push_back( { { "op", "replace" }, + { "path", to_string( path ) }, + { "value", destination } } ); + } + } + return result; + } + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/get.hpp b/include/tao/json/contrib/get.hpp new file mode 100644 index 00000000..e83dda13 --- /dev/null +++ b/include/tao/json/contrib/get.hpp @@ -0,0 +1,152 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_GET_HPP +#define TAO_JSON_CONTRIB_GET_HPP + +#include "../basic_value.hpp" + +namespace tao::json::get +{ + namespace internal + { + template< template< typename... > class Traits > + [[nodiscard]] const basic_value< Traits >* find( const basic_value< Traits >& v, const std::string& key ) + { + return v.find( key ); + } + + template< template< typename... > class Traits > + [[nodiscard]] const basic_value< Traits >* find( const basic_value< Traits >& v, const std::size_t index ) + { + const auto& a = v.get_array(); + return ( index < a.size() ) ? ( a.data() + index ) : nullptr; + } + + } // namespace internal + + template< template< typename... > class Traits, typename K > + [[nodiscard]] basic_value< Traits > value( const basic_value< Traits >& v, const K& key ) + { + if( const auto& w = v.skip_value_ptr() ) { + if( const auto* p = internal::find( w, key ) ) { + return basic_value< Traits >( &p->skip_value_ptr() ); // Returns a Value with tao::json::type::VALUE_PTR that is invalidated when v is destroyed! + } + } + return basic_value< Traits >(); + } + + template< template< typename... > class Traits, typename K, typename... Ks > + [[nodiscard]] basic_value< Traits > value( const basic_value< Traits >& v, const K& key, const Ks&... ks ) + { + if( const auto& w = v.skip_value_ptr() ) { + if( const auto* p = internal::find( w, key ) ) { + return get::value( *p, ks... ); + } + } + return basic_value< Traits >(); + } + + template< typename T, typename U, template< typename... > class Traits > + [[nodiscard]] T as( const basic_value< Traits >& v ) + { + return v.skip_value_ptr().template as< U >(); + } + + template< typename T, template< typename... > class Traits > + [[nodiscard]] auto as( const basic_value< Traits >& v ) + { + return as< T, T >( v ); + } + + template< typename T, typename U, template< typename... > class Traits, typename K, typename... Ks > + [[nodiscard]] T as( const basic_value< Traits >& v, const K& key, Ks&&... ks ) + { + return get::as< T, U >( v.skip_value_ptr().at( key ), ks... ); + } + + template< typename T, template< typename... > class Traits, typename K, typename... Ks > + [[nodiscard]] auto as( const basic_value< Traits >& v, const K& key, Ks&&... ks ) + { + return as< T, T >( v, key, ks... ); + } + + template< typename T, template< typename... > class Traits > + void to( const basic_value< Traits >& v, T& t ) + { + v.skip_value_ptr().to( t ); + } + + template< typename T, template< typename... > class Traits, typename K, typename... Ks > + void to( const basic_value< Traits >& v, T& t, const K& key, Ks&&... ks ) + { + get::to( v.skip_value_ptr().at( key ), t, ks... ); + } + + template< typename T, typename U, template< typename... > class Traits > + [[nodiscard]] std::optional< T > optional( const basic_value< Traits >& v ) + { + if( const auto& w = v.skip_value_ptr() ) { + return std::optional< T >( std::in_place, get::as< U >( w ) ); + } + return std::nullopt; + } + + template< typename T, template< typename... > class Traits > + [[nodiscard]] auto optional( const basic_value< Traits >& v ) + { + return optional< T, T >( v ); + } + + template< typename T, typename U, template< typename... > class Traits, typename K, typename... Ks > + [[nodiscard]] std::optional< T > optional( const basic_value< Traits >& v, const K& key, const Ks&... ks ) + { + if( const auto& w = v.skip_value_ptr() ) { + if( const auto* p = internal::find( w, key ) ) { + return get::optional< T, U >( *p, ks... ); + } + } + return std::nullopt; + } + + template< typename T, template< typename... > class Traits, typename K, typename... Ks > + [[nodiscard]] auto optional( const basic_value< Traits >& v, const K& key, const Ks&... ks ) + { + return optional< T, T >( v, key, ks... ); + } + + template< typename T, typename U, template< typename... > class Traits > + [[nodiscard]] T defaulted( const T& t, const basic_value< Traits >& v ) + { + if( const auto& w = v.skip_value_ptr() ) { + return get::as< T, U >( w ); + } + return t; + } + + template< typename T, template< typename... > class Traits > + [[nodiscard]] auto defaulted( const T& t, const basic_value< Traits >& v ) + { + return defaulted< T, T >( t, v ); + } + + template< typename T, typename U, template< typename... > class Traits, typename K, typename... Ks > + [[nodiscard]] T defaulted( const T& t, const basic_value< Traits >& v, const K& key, const Ks&... ks ) + { + if( const auto& w = v.skip_value_ptr() ) { + if( const auto* p = internal::find( w, key ) ) { + return get::defaulted< T, U >( t, *p, ks... ); + } + } + return t; + } + + template< typename T, template< typename... > class Traits, typename K, typename... Ks > + [[nodiscard]] auto defaulted( const T& t, const basic_value< Traits >& v, const K& key, const Ks&... ks ) + { + return defaulted< T, T >( t, v, key, ks... ); + } + +} // namespace tao::json::get + +#endif diff --git a/include/tao/json/contrib/internal/array_traits.hpp b/include/tao/json/contrib/internal/array_traits.hpp new file mode 100644 index 00000000..6d59cf7b --- /dev/null +++ b/include/tao/json/contrib/internal/array_traits.hpp @@ -0,0 +1,92 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_INTERNAL_ARRAY_TRAITS_HPP +#define TAO_JSON_CONTRIB_INTERNAL_ARRAY_TRAITS_HPP + +#include + +#include "../../forward.hpp" +#include "../../type.hpp" + +#include "../../events/produce.hpp" + +namespace tao::json::internal +{ + template< typename T > + struct array_multi_traits + { + template< template< typename... > class Traits > + [[nodiscard]] static bool is_nothing( const T& o ) + { + return o.empty(); + } + + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const T& o ) = delete; + + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, const T& o ) + { + c.begin_array( o.size() ); + for( const auto& i : o ) { + json::events::produce< Traits >( c, i ); + c.element(); + } + c.end_array( o.size() ); + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const T& rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + if( !p.is_array() ) { + return false; + } + const auto& a = p.get_array(); + return ( a.size() == rhs.size() ) && std::equal( rhs.begin(), rhs.end(), a.begin() ); + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const T& rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + const auto t = p.type(); + if( t != type::ARRAY ) { + return t < type::ARRAY; + } + const auto& a = p.get_array(); + return std::lexicographical_compare( a.begin(), a.end(), rhs.begin(), rhs.end() ); + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const T& rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + const auto t = p.type(); + if( t != type::ARRAY ) { + return t > type::ARRAY; + } + const auto& a = p.get_array(); + return std::lexicographical_compare( rhs.begin(), rhs.end(), a.begin(), a.end() ); + } + }; + + template< typename T > + struct array_traits + : array_multi_traits< T > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const T& o ) + { + v.emplace_array(); + v.get_array().reserve( o.size() ); + for( const auto& e : o ) { + v.emplace_back( e ); + } + } + }; + +} // namespace tao::json::internal + +#endif diff --git a/include/tao/json/contrib/internal/indirect_traits.hpp b/include/tao/json/contrib/internal/indirect_traits.hpp new file mode 100644 index 00000000..7022b325 --- /dev/null +++ b/include/tao/json/contrib/internal/indirect_traits.hpp @@ -0,0 +1,69 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_INTERNAL_INDIRECT_TRAITS_HPP +#define TAO_JSON_CONTRIB_INTERNAL_INDIRECT_TRAITS_HPP + +#include + +#include "../../forward.hpp" +#include "../../type.hpp" + +#include "../../events/produce.hpp" + +#include "../../internal/type_traits.hpp" + +namespace tao::json::internal +{ + template< typename T > + struct indirect_traits + { + template< typename U > + [[nodiscard]] static const U& add_const( const U& u ) + { + return u; + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool is_nothing( const T& o ) + { + assert( o ); + return internal::is_nothing< Traits >( add_const( *o ) ); + } + + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const T& o ) + { + assert( o ); + v = add_const( *o ); + } + + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, const T& o ) + { + assert( o ); + json::events::produce< Traits >( c, add_const( *o ) ); + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const T& rhs ) noexcept + { + return rhs ? ( lhs == *rhs ) : ( lhs == null ); + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const T& rhs ) noexcept + { + return rhs ? ( lhs < *rhs ) : ( lhs < null ); + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const T& rhs ) noexcept + { + return rhs ? ( lhs > *rhs ) : ( lhs > null ); + } + }; + +} // namespace tao::json::internal + +#endif diff --git a/include/tao/json/contrib/internal/object_traits.hpp b/include/tao/json/contrib/internal/object_traits.hpp new file mode 100644 index 00000000..7f531de6 --- /dev/null +++ b/include/tao/json/contrib/internal/object_traits.hpp @@ -0,0 +1,105 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_INTERNAL_OBJECT_TRAITS_HPP +#define TAO_JSON_CONTRIB_INTERNAL_OBJECT_TRAITS_HPP + +#include +#include + +#include "../../forward.hpp" +#include "../../type.hpp" + +#include "../../events/produce.hpp" + +namespace tao::json::internal +{ + template< typename T > + struct object_multi_traits + { + template< template< typename... > class Traits > + [[nodiscard]] static bool is_nothing( const T& o ) + { + return o.empty(); + } + + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const T& o ) = delete; + + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, const T& o ) + { + c.begin_object( o.size() ); + for( const auto& i : o ) { + c.key( i.first ); + json::events::produce< Traits >( c, i.second ); + c.member(); + } + c.end_object( o.size() ); + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const T& rhs ) noexcept + { + static const auto eq = []( const typename T::value_type& r, const std::pair< const std::string, basic_value< Traits > >& l ) { + return ( l.first == r.first ) && ( l.second == r.second ); + }; + const auto& p = lhs.skip_value_ptr(); + if( !p.is_object() ) { + return false; + } + const auto& o = p.get_object(); + return ( o.size() == rhs.size() ) && std::equal( rhs.begin(), rhs.end(), o.begin(), eq ); + } + + struct pair_less + { + template< typename L, typename R > + [[nodiscard]] bool operator()( const L& l, const R& r ) const noexcept + { + return ( l.first < r.first ) || ( ( l.first == r.first ) && ( l.second < r.second ) ); + } + }; + + template< template< typename... > class Traits > + [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const T& rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + const auto t = p.type(); + if( t != type::OBJECT ) { + return t < type::OBJECT; + } + const auto& o = p.get_object(); + return std::lexicographical_compare( o.begin(), o.end(), rhs.begin(), rhs.end(), pair_less() ); + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const T& rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + const auto t = p.type(); + if( t != type::OBJECT ) { + return t > type::OBJECT; + } + const auto& o = p.get_object(); + return std::lexicographical_compare( rhs.begin(), rhs.end(), o.begin(), o.end(), pair_less() ); + } + }; + + template< typename T > + struct object_traits + : object_multi_traits< T > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const T& o ) + { + v.prepare_object(); + for( const auto& i : o ) { + v.try_emplace( i.first, i.second ); + } + } + }; + +} // namespace tao::json::internal + +#endif diff --git a/include/tao/json/contrib/internal/type_traits.hpp b/include/tao/json/contrib/internal/type_traits.hpp new file mode 100644 index 00000000..4cdf44b0 --- /dev/null +++ b/include/tao/json/contrib/internal/type_traits.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_INTERNAL_TYPE_TRAITS_HPP +#define TAO_JSON_CONTRIB_INTERNAL_TYPE_TRAITS_HPP + +#include "../../forward.hpp" + +#include "../../internal/type_traits.hpp" + +namespace tao::json::internal +{ + template< typename T, template< typename... > class Traits, typename... With > + inline constexpr bool use_first_ptr_as = std::is_constructible_v< T, const basic_value< Traits >&, With&... >; + + template< typename T, template< typename... > class Traits, typename... With > + inline constexpr bool use_second_ptr_as = !use_first_ptr_as< T, Traits, With... > && std::is_move_constructible_v< T > && has_as< Traits< T >, basic_value< Traits >, With... >; + + template< typename T, template< typename... > class Traits, typename... With > + inline constexpr bool use_third_ptr_as = !use_first_ptr_as< T, Traits, With... > && !use_second_ptr_as< T, Traits, With... > && std::is_default_constructible_v< T > && has_to< Traits< T >, basic_value< Traits >, T, With... >; + + template< typename T, template< typename... > class Traits, typename... With > + inline constexpr bool use_fourth_ptr_as = !use_first_ptr_as< T, Traits, With... > && !use_third_ptr_as< T, Traits, With... > && std::is_copy_constructible_v< T > && has_as< Traits< T >, basic_value< Traits >, With... >; + + template< typename T, template< typename... > class Traits, class Producer > + inline constexpr bool use_first_ptr_consume = std::is_move_constructible_v< T >&& has_consume_one< Traits, Producer, T >; + + template< typename T, template< typename... > class Traits, class Producer > + inline constexpr bool use_second_ptr_consume = !use_first_ptr_consume< T, Traits, Producer > && std::is_default_constructible_v< T > && has_consume_two< Traits, Producer, T >; + + template< typename T, template< typename... > class Traits, class Producer > + inline constexpr bool use_third_ptr_consume = !use_second_ptr_consume< T, Traits, Producer > && std::is_copy_constructible_v< T > && has_consume_one< Traits, Producer, T >; + +} // namespace tao::json::internal + +#endif diff --git a/include/tao/json/contrib/list_traits.hpp b/include/tao/json/contrib/list_traits.hpp new file mode 100644 index 00000000..5416cd0e --- /dev/null +++ b/include/tao/json/contrib/list_traits.hpp @@ -0,0 +1,41 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_LIST_TRAITS_HPP +#define TAO_JSON_CONTRIB_LIST_TRAITS_HPP + +#include + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "internal/array_traits.hpp" + +namespace tao::json +{ + template< typename T, typename... Ts > + struct list_traits + : internal::array_traits< std::list< T, Ts... > > + { + template< template< typename... > class Traits, typename... With > + static void to( const basic_value< Traits >& v, std::list< T, Ts... >& r, With&... with ) + { + const auto& a = v.get_array(); + for( const auto& i : a ) { + r.emplace_back( i.template as_with< T >( with... ) ); + } + } + + template< template< typename... > class Traits, typename Producer > + static void consume( Producer& parser, std::list< T, Ts... >& r ) + { + auto s = parser.begin_array(); + while( parser.element_or_end_array( s ) ) { + r.emplace_back( json::consume< T, Traits >( parser ) ); + } + } + }; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/map_traits.hpp b/include/tao/json/contrib/map_traits.hpp new file mode 100644 index 00000000..c0c9e3e2 --- /dev/null +++ b/include/tao/json/contrib/map_traits.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_MAP_TRAITS_HPP +#define TAO_JSON_CONTRIB_MAP_TRAITS_HPP + +#include +#include + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "internal/object_traits.hpp" + +namespace tao::json +{ + template< typename T, typename... Ts > + struct map_traits + : internal::object_traits< std::map< std::string, T, Ts... > > + { + template< template< typename... > class Traits, typename... With > + static void to( const basic_value< Traits >& v, std::map< std::string, T, Ts... >& r, With&... with ) + { + const auto& o = v.get_object(); + for( const auto& i : o ) { + r.try_emplace( i.first, i.second.template as_with< T >( with... ) ); + } + } + + template< template< typename... > class Traits, typename Producer > + static void consume( Producer& parser, std::map< std::string, T, Ts... >& v ) + { + auto s = parser.begin_object(); + while( parser.member_or_end_object( s ) ) { + auto k = parser.key(); + v.try_emplace( std::move( k ), json::consume< T, Traits >( parser ) ); + } + } + }; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/multimap_traits.hpp b/include/tao/json/contrib/multimap_traits.hpp new file mode 100644 index 00000000..ee480395 --- /dev/null +++ b/include/tao/json/contrib/multimap_traits.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_MULTIMAP_TRAITS_HPP +#define TAO_JSON_CONTRIB_MULTIMAP_TRAITS_HPP + +#include +#include + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "internal/object_traits.hpp" + +namespace tao::json +{ + template< typename T, typename... Ts > + struct multimap_traits + : internal::object_multi_traits< std::multimap< std::string, T, Ts... > > + { + template< template< typename... > class Traits, typename... With > + static void to( const basic_value< Traits >& v, std::multimap< std::string, T, Ts... >& r, With&... with ) + { + const auto& o = v.get_object(); + for( const auto& i : o ) { + r.try_emplace( i.first, i.second.template as_with< T >( with... ) ); + } + } + + template< template< typename... > class Traits, typename Producer > + static void consume( Producer& parser, std::multimap< std::string, T, Ts... >& v ) + { + auto s = parser.begin_object(); + while( parser.member_or_end_object( s ) ) { + auto k = parser.key(); + v.try_emplace( std::move( k ), json::consume< T, Traits >( parser ) ); + } + } + }; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/multiset_traits.hpp b/include/tao/json/contrib/multiset_traits.hpp new file mode 100644 index 00000000..2ace4adf --- /dev/null +++ b/include/tao/json/contrib/multiset_traits.hpp @@ -0,0 +1,41 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_MULTISET_TRAITS_HPP +#define TAO_JSON_CONTRIB_MULTISET_TRAITS_HPP + +#include + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "internal/array_traits.hpp" + +namespace tao::json +{ + template< typename T, typename... Ts > + struct multiset_traits + : internal::array_traits< std::multiset< T, Ts... > > + { + template< template< typename... > class Traits, typename... With > + static void to( const basic_value< Traits >& v, std::multiset< T, Ts... >& r, With&... with ) + { + const auto& a = v.get_array(); + for( const auto& i : a ) { + r.emplace( i.template as_with< T >( with... ) ); + } + } + + template< template< typename... > class Traits, typename Producer > + static void consume( Producer& parser, std::multiset< T, Ts... >& r ) + { + auto s = parser.begin_array(); + while( parser.element_or_end_array( s ) ) { + r.emplace( json::consume< T, Traits >( parser ) ); + } + } + }; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/pair_traits.hpp b/include/tao/json/contrib/pair_traits.hpp new file mode 100644 index 00000000..f6413cde --- /dev/null +++ b/include/tao/json/contrib/pair_traits.hpp @@ -0,0 +1,21 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_PAIR_TRAITS_HPP +#define TAO_JSON_CONTRIB_PAIR_TRAITS_HPP + +#include + +#include "../binding.hpp" + +namespace tao::json +{ + template< typename U, typename V > + struct pair_traits + : binding::array< TAO_JSON_BIND_ELEMENT( &std::pair< U, V >::first ), + TAO_JSON_BIND_ELEMENT( &std::pair< U, V >::second ) > + {}; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/patch.hpp b/include/tao/json/contrib/patch.hpp new file mode 100644 index 00000000..1c2ee384 --- /dev/null +++ b/include/tao/json/contrib/patch.hpp @@ -0,0 +1,105 @@ +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_PATCH_HPP +#define TAO_JSON_CONTRIB_PATCH_HPP + +#include +#include + +#include "../pointer.hpp" +#include "../value.hpp" + +namespace tao::json +{ + template< template< typename... > class Traits > + void patch_inplace( basic_value< Traits >& v, const basic_value< Traits >& patch ) + { + for( const auto& entry : patch.get_array() ) { + const auto& op = entry.at( "op" ).get_string(); + const auto& path = entry.at( "path" ).get_string(); + const pointer path_pointer( path ); + if( op == "test" ) { + if( v.at( path_pointer ) != entry.at( "value" ) ) { + throw std::runtime_error( internal::format( "json patch 'test' failed for '", path, '\'', json::message_extension( v ) ) ); + } + } + else if( op == "remove" ) { + v.erase( path_pointer ); + } + else if( op == "add" ) { + v.insert( path_pointer, entry.at( "value" ) ); + } + else if( op == "replace" ) { + v.at( path_pointer ) = entry.at( "value" ); + } + else if( op == "move" ) { + const pointer from( entry.at( "from" ).get_string() ); + auto t = std::move( v.at( from ) ); + v.erase( from ); + v.insert( path_pointer, std::move( t ) ); + } + else if( op == "copy" ) { + const pointer from( entry.at( "from" ).get_string() ); + v.insert( path_pointer, v.at( from ) ); + } + else { + throw std::runtime_error( internal::format( "unknown json patch operation '", op, '\'' ) ); + } + } + } + + template< template< typename... > class Traits > + void patch_inplace( basic_value< Traits >& v, basic_value< Traits >&& patch ) + { + for( const auto& entry : patch.get_array() ) { + const auto& op = entry.at( "op" ).get_string(); + const auto& path = entry.at( "path" ).get_string(); + const pointer path_pointer( path ); + if( op == "test" ) { + if( v.at( path_pointer ) != entry.at( "value" ) ) { + throw std::runtime_error( internal::format( "json patch 'test' failed for '", path, '\'', json::message_extension( v ) ) ); + } + } + else if( op == "remove" ) { + v.erase( path_pointer ); + } + else if( op == "add" ) { + v.insert( path_pointer, std::move( entry.at( "value" ) ) ); + } + else if( op == "replace" ) { + v.at( path_pointer ) = std::move( entry.at( "value" ) ); + } + else if( op == "move" ) { + const pointer from( entry.at( "from" ).get_string() ); + auto t = std::move( v.at( from ) ); + v.erase( from ); + v.insert( path_pointer, std::move( t ) ); + } + else if( op == "copy" ) { + const pointer from( entry.at( "from" ).get_string() ); + v.insert( path_pointer, v.at( from ) ); + } + else { + throw std::runtime_error( internal::format( "unknown json patch operation '", op, '\'' ) ); + } + } + } + + template< template< typename... > class Traits > + [[nodiscard]] basic_value< Traits > patch( basic_value< Traits > v, const basic_value< Traits >& patch ) + { + patch_inplace( v, patch ); + return v; + } + + template< template< typename... > class Traits > + [[nodiscard]] basic_value< Traits > patch( basic_value< Traits > v, basic_value< Traits >&& patch ) + { + patch_inplace( v, std::move( patch ) ); + return v; + } + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/pointer_traits.hpp b/include/tao/json/contrib/pointer_traits.hpp new file mode 100644 index 00000000..c079f468 --- /dev/null +++ b/include/tao/json/contrib/pointer_traits.hpp @@ -0,0 +1,59 @@ +#ifndef TAO_JSON_CONTRIB_POINTER_TRAITS_HPP +#define TAO_JSON_CONTRIB_POINTER_TRAITS_HPP + +#include "../pointer.hpp" +#include "../traits.hpp" + +namespace tao::json +{ + struct token_traits + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const token& t ) + { + if( t.has_index() ) { + v = t.index(); + } + else { + v = t.key(); + } + } + + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, const token& t ) + { + if( t.has_index() ) { + json::events::produce< Traits >( c, t.index() ); + } + else { + json::events::produce< Traits >( c, t.key() ); + } + } + }; + + struct pointer_traits + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const pointer& p ) + { + v.prepare_array().reserve( p.size() ); + for( const auto& i : p ) { + v.emplace_back( i ); + } + } + + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, const pointer& p ) + { + c.begin_array( p.size() ); + for( const auto& i : p ) { + json::events::produce< Traits >( c, i ); + c.element(); + } + c.end_array( p.size() ); + } + }; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/position.hpp b/include/tao/json/contrib/position.hpp new file mode 100644 index 00000000..fd80f13e --- /dev/null +++ b/include/tao/json/contrib/position.hpp @@ -0,0 +1,166 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_POSITION_HPP +#define TAO_JSON_CONTRIB_POSITION_HPP + +#include +#include +#include +#include + +#include "../events/to_value.hpp" +#include "../events/transformer.hpp" +#include "../from_file.hpp" +#include "../message_extension.hpp" +#include "../value.hpp" + +namespace tao::json +{ + struct position + { + private: + std::size_t m_line = 0; + std::size_t m_byte_in_line = 0; + std::string m_source; + + public: + position() noexcept + {} + + position( std::string in_source, const std::size_t in_line, const std::size_t in_byte_in_line ) + : m_line( in_line ), + m_byte_in_line( in_byte_in_line ), + m_source( std::move( in_source ) ) + {} + + position( const position& ) = default; + + position( position&& p ) noexcept + { + m_line = p.m_line; + m_byte_in_line = p.m_byte_in_line; + m_source = std::move( p.m_source ); + } + + ~position() = default; + + position& operator=( const position& ) = default; + + position& operator=( position&& p ) noexcept + { + m_line = p.m_line; + m_byte_in_line = p.m_byte_in_line; + m_source = std::move( p.m_source ); + return *this; + } + + [[nodiscard]] const std::string& source() const noexcept + { + return m_source; + } + + [[nodiscard]] std::size_t line() const noexcept + { + return m_line; + } + + [[nodiscard]] std::size_t byte_in_line() const noexcept + { + return m_byte_in_line; + } + + void set_source( const std::string& s ) + { + m_source = s; + } + + template< typename T > + void set_position( const T& p ) + { + m_line = p.line; + m_byte_in_line = p.byte_in_line; + m_source = p.source; + } + + void append_message_extension( std::ostream& os ) const + { + os << '[' << m_source << ':' << m_line << ':' << m_byte_in_line << ']'; + } + }; + + namespace internal + { + template< typename Rule > + struct position_action + : action< Rule > + { + }; + + template<> + struct position_action< rules::object::begin > + { + template< typename Input, typename Consumer > + static void apply( const Input& in, Consumer& consumer ) + { + action< rules::object::begin >::apply0( consumer ); + consumer.stack_.back().set_position( in.position() ); + } + }; + + template<> + struct position_action< rules::array::begin > + { + template< typename Input, typename Consumer > + static void apply( const Input& in, Consumer& consumer ) + { + action< rules::array::begin >::apply0( consumer ); + consumer.stack_.back().set_position( in.position() ); + } + }; + + template<> + struct position_action< rules::sor_value > + { + template< typename Input, typename Consumer > + static void apply( const Input& in, Consumer& consumer ) + { + consumer.value.set_position( in.position() ); + } + }; + + template< template< typename... > class Traits > + struct position_traits + : Traits< void > + { + template< typename > + using public_base = position; + }; + + } // namespace internal + + template< template< typename... > class Traits > + struct make_position_traits + { + template< typename T > + using type = std::conditional_t< std::is_same_v< T, void >, internal::position_traits< Traits >, Traits< T > >; + }; + + template< template< typename... > class Traits, template< typename... > class... Transformers > + [[nodiscard]] auto basic_from_file_with_position( const std::string& filename ) + { + events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; + pegtl::file_input< pegtl::tracking_mode::eager > in( filename ); + pegtl::parse< internal::grammar, internal::position_action, internal::errors >( in, consumer ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers > + [[nodiscard]] auto from_file_with_position( const std::string& filename ) + { + return basic_from_file_with_position< make_position_traits< traits >::template type, Transformers... >( filename ); + } + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/reference.hpp b/include/tao/json/contrib/reference.hpp new file mode 100644 index 00000000..422efd7c --- /dev/null +++ b/include/tao/json/contrib/reference.hpp @@ -0,0 +1,115 @@ +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_REFERENCE_HPP +#define TAO_JSON_CONTRIB_REFERENCE_HPP + +#include "../internal/uri_fragment.hpp" +#include "../pointer.hpp" +#include "../value.hpp" + +namespace tao::json +{ + namespace internal + { + // JSON Reference, see draft ("work in progress") RFC at + // https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03 + + // NOTE: Currently, only URI fragments are supported. + // Remote references are ignored, i.e., left untouched. + + // JSON References are replaced with a VALUE_PTR, + // which might lead to infinite loops if you try + // to traverse the value. Make sure you understand + // the consequences and handle the resulting value + // accordingly! + + // Self-references will throw an exception, as well as + // references into JSON Reference additional members + // (which shall be ignored as per the specification). + + template< template< typename... > class Traits > + void resolve_references( basic_value< Traits >& r, basic_value< Traits >& v ) + { + switch( v.type() ) { + case type::UNINITIALIZED: + return; + case type::NULL_: + case type::BOOLEAN: + case type::SIGNED: + case type::UNSIGNED: + case type::DOUBLE: + case type::STRING: + case type::STRING_VIEW: + case type::BINARY: + case type::BINARY_VIEW: + return; + case type::ARRAY: + for( auto& e : v.get_array() ) { + resolve_references( r, e ); + } + return; + case type::OBJECT: + for( auto& e : v.get_object() ) { + resolve_references( r, e.second ); + } + if( const auto* ref = v.find( "$ref" ) ) { + ref = &ref->skip_value_ptr(); + if( ref->is_string_type() ) { + const std::string_view s = ref->get_string_type(); + if( !s.empty() && s[ 0 ] == '#' ) { + const pointer ptr = internal::uri_fragment_to_pointer( s ); + const auto* p = &r; + auto it = ptr.begin(); + while( it != ptr.end() ) { + switch( p->type() ) { + case type::ARRAY: + p = &p->at( it->index() ).skip_value_ptr(); + break; + case type::OBJECT: + if( const auto* t = p->find( "$ref" ) ) { + if( t->is_string_type() ) { + throw std::runtime_error( "invalid JSON Reference: referencing additional data members is invalid" ); + } + } + p = &p->at( it->key() ).skip_value_ptr(); + break; + default: + throw invalid_type( ptr.begin(), std::next( it ) ); + } + ++it; + } + if( p == &v ) { + throw std::runtime_error( "JSON Reference: invalid self reference" ); + } + v.set_value_ptr( p ); + resolve_references( r, v ); + } + else { + // Ignore remote references for now... + // throw std::runtime_error( "JSON Reference: unsupported or invalid URI: " + s ); // NOLINT + } + } + } + return; + case type::VALUE_PTR: + return; + case type::OPAQUE_PTR: + return; + case type::VALUELESS_BY_EXCEPTION: + return; + } + throw std::logic_error( "invalid value for tao::json::type" ); // LCOV_EXCL_LINE + } + + } // namespace internal + + template< template< typename... > class Traits > + void resolve_references( basic_value< Traits >& r ) + { + internal::resolve_references( r, r ); + } + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/schema.hpp b/include/tao/json/contrib/schema.hpp new file mode 100644 index 00000000..4f74dd01 --- /dev/null +++ b/include/tao/json/contrib/schema.hpp @@ -0,0 +1,1851 @@ +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_SCHEMA_HPP +#define TAO_JSON_CONTRIB_SCHEMA_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "reference.hpp" + +#include "../events/compare.hpp" +#include "../events/from_value.hpp" +#include "../events/hash.hpp" +#include "../pointer.hpp" +#include "../value.hpp" + +#include "../external/pegtl/contrib/uri.hpp" +#include "../external/pegtl/parse.hpp" + +namespace tao::json +{ + namespace internal + { + // TODO: Check if these grammars are correct. + struct local_part_label + : pegtl::plus< pegtl::sor< pegtl::alnum, pegtl::one< '!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', '=', '?', '^', '_', '`', '{', '|', '}', '~' > > > + {}; + + struct local_part + : pegtl::list_must< local_part_label, pegtl::one< '.' > > + {}; + + struct hostname_label + : pegtl::seq< pegtl::alnum, pegtl::rep_max< 62, pegtl::ranges< 'a', 'z', 'A', 'Z', '0', '9', '-' > > > + {}; + + struct hostname + : pegtl::list_must< hostname_label, pegtl::one< '.' > > + {}; + + struct email + : pegtl::seq< local_part, pegtl::one< '@' >, hostname > + {}; + + template< typename Rule > + [[nodiscard]] bool parse( const std::string_view v ) + { + pegtl::memory_input in( v.data(), v.size(), "" ); + return pegtl::parse< pegtl::seq< Rule, pegtl::eof > >( in ); + } + + [[nodiscard]] inline bool parse_date_time( const std::string_view v ) + { + static std::regex re( "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:[0-5]\\d:[0-5]\\d(\\.\\d+)?(Z|[+-]\\d{2}:[0-5]\\d)$" ); + if( !std::regex_search( v.begin(), v.end(), re ) ) { + return false; + } + + const unsigned year = ( v[ 0 ] - '0' ) * 1000 + ( v[ 1 ] - '0' ) * 100 + ( v[ 2 ] - '0' ) * 10 + ( v[ 3 ] - '0' ); + const unsigned month = ( v[ 5 ] - '0' ) * 10 + ( v[ 6 ] - '0' ); + const unsigned day = ( v[ 8 ] - '0' ) * 10 + ( v[ 9 ] - '0' ); + + if( month == 0 || month > 12 ) { + return false; + } + if( day == 0 || day > 31 ) { + return false; + } + if( month == 2 ) { + const bool is_leap_year = ( year % 4 == 0 ) && ( year % 100 != 0 || year % 400 == 0 ); + if( day > ( is_leap_year ? 29U : 28U ) ) { + return false; + } + } + else if( day == 31 ) { + switch( month ) { + case 4: + case 6: + case 9: + case 11: + return false; + default:; + } + } + + const unsigned hour = ( v[ 11 ] - '0' ) * 10 + ( v[ 12 ] - '0' ); + if( hour >= 24 ) { + return false; + } + + if( *v.rbegin() != 'Z' ) { + const auto s = v.size(); + const unsigned tz_hour = ( v[ s - 5 ] - '0' ) * 10 + ( v[ s - 4 ] - '0' ); + if( tz_hour >= 24 ) { + return false; + } + } + + return true; + } + + enum schema_flags + { + NONE = 0, + + HAS_TYPE = 1 << 0, + NULL_ = 1 << 1, + BOOLEAN = 1 << 2, + INTEGER = 1 << 3, + NUMBER = 1 << 4, + STRING = 1 << 5, + ARRAY = 1 << 6, + OBJECT = 1 << 7, + + HAS_ENUM = 1 << 8, + + HAS_MULTIPLE_OF_UNSIGNED = 1 << 9, + HAS_MULTIPLE_OF_DOUBLE = 1 << 10, + HAS_MULTIPLE_OF = 3 << 9, + + HAS_MAXIMUM_SIGNED = 1 << 11, + HAS_MAXIMUM_UNSIGNED = 1 << 12, + HAS_MAXIMUM_DOUBLE = 3 << 11, + HAS_MAXIMUM = 3 << 11, + EXCLUSIVE_MAXIMUM = 1 << 13, + + HAS_MINIMUM_SIGNED = 1 << 14, + HAS_MINIMUM_UNSIGNED = 1 << 15, + HAS_MINIMUM_DOUBLE = 3 << 14, + HAS_MINIMUM = 3 << 14, + EXCLUSIVE_MINIMUM = 1 << 16, + + HAS_MAX_LENGTH = 1 << 17, + HAS_MIN_LENGTH = 1 << 18, + + HAS_MAX_ITEMS = 1 << 19, + HAS_MIN_ITEMS = 1 << 20, + HAS_UNIQUE_ITEMS = 1 << 21, + + HAS_MAX_PROPERTIES = 1 << 22, + HAS_MIN_PROPERTIES = 1 << 23, + NO_ADDITIONAL_PROPERTIES = 1 << 24, + HAS_DEPENDENCIES = 1 << 25 + }; + + enum class schema_format + { + none, + date_time, + email, + hostname, + ipv4, + ipv6, + uri + }; + + [[nodiscard]] inline constexpr schema_flags operator|( const schema_flags lhs, const schema_flags rhs ) noexcept + { + return static_cast< schema_flags >( static_cast< std::underlying_type< schema_flags >::type >( lhs ) | static_cast< std::underlying_type< schema_flags >::type >( rhs ) ); + } + + union schema_limit + { + std::int64_t i; + std::uint64_t u; + double d; + }; + + template< template< typename... > class Traits > + class schema_container; + + template< template< typename... > class Traits > + struct schema_node + { + const schema_container< Traits >* m_container; + const basic_value< Traits >* m_value; + const basic_value< Traits >* m_all_of = nullptr; + const basic_value< Traits >* m_any_of = nullptr; + const basic_value< Traits >* m_one_of = nullptr; + const basic_value< Traits >* m_not = nullptr; + const basic_value< Traits >* m_items = nullptr; + const basic_value< Traits >* m_additional_items = nullptr; + const basic_value< Traits >* m_properties = nullptr; + const basic_value< Traits >* m_additional_properties = nullptr; + + std::map< std::string, std::set< std::string > > m_property_dependencies; + std::map< std::string, const basic_value< Traits >* > m_schema_dependencies; + + std::vector< std::pair< std::regex, const basic_value< Traits >* > > m_pattern_properties; + + std::set< const basic_value< Traits >* > m_referenced_pointers; + + // number + schema_limit m_multiple_of; + schema_limit m_maximum; + schema_limit m_minimum; + + // string + std::uint64_t m_max_length; + std::uint64_t m_min_length; + std::unique_ptr< std::regex > m_pattern; + + // array + std::uint64_t m_max_items; + std::uint64_t m_min_items; + + // object + std::uint64_t m_max_properties; + std::uint64_t m_min_properties; + std::set< std::string > m_required; + + schema_flags m_flags = NONE; + schema_format m_format = schema_format::none; + + void add_type( const schema_flags v ) + { + if( ( m_flags & v ) != 0 ) { + throw std::runtime_error( "invalid JSON Schema: duplicate primitive type" ); + } + m_flags = m_flags | v; + } + + void add_type( const std::string& v ) + { + if( !v.empty() ) { + switch( v[ 0 ] ) { + case 'n': + if( v == "number" ) { + return add_type( NUMBER ); + } + else if( v == "null" ) { + return add_type( NULL_ ); + } + break; + case 'b': + if( v == "boolean" ) { + return add_type( BOOLEAN ); + } + break; + case 'i': + if( v == "integer" ) { + return add_type( INTEGER ); + } + break; + case 's': + if( v == "string" ) { + return add_type( STRING ); + } + break; + case 'a': + if( v == "array" ) { + return add_type( ARRAY ); + } + break; + case 'o': + if( v == "object" ) { + return add_type( OBJECT ); + } + break; + } + } + throw std::runtime_error( "invalid JSON Schema: invalid primitive type '" + v + '\'' ); + } + + [[nodiscard]] const basic_value< Traits >* find( const char* s ) const + { + const auto* p = m_value->find( s ); + if( p != nullptr ) { + p = &p->skip_value_ptr(); + } + return p; + } + + schema_node( const schema_container< Traits >* c, const basic_value< Traits >& v ) + : m_container( c ), + m_value( &v ) + { + // general + if( !m_value->is_object() ) { + throw std::runtime_error( "invalid JSON Schema: a schema must be of type 'object'" ); + } + + // title + if( const auto* p = find( "title" ) ) { + if( !p->is_string() ) { + throw std::runtime_error( "invalid JSON Schema: \"title\" must be of type 'string'" ); + } + } + + // description + if( const auto* p = find( "description" ) ) { + if( !p->is_string() ) { + throw std::runtime_error( "invalid JSON Schema: \"description\" must be of type 'string'" ); + } + } + + // type + if( const auto* p = find( "type" ) ) { + switch( p->type() ) { + case type::STRING: + add_type( p->get_string() ); + break; + case type::ARRAY: + for( const auto& e : p->get_array() ) { + if( !e.is_string() ) { + throw std::runtime_error( "invalid JSON Schema: elements in array \"type\" must be of type 'string'" ); + } + add_type( e.get_string() ); + } + break; + default: + throw std::runtime_error( "invalid JSON Schema: \"type\" must be of type 'string' or 'array'" ); + } + m_flags = m_flags | HAS_TYPE; + } + + // enum + if( const auto* p = find( "enum" ) ) { + if( !p->is_array() ) { + throw std::runtime_error( "invalid JSON Schema: \"enum\" must be of type 'array'" ); + } + m_flags = m_flags | HAS_ENUM; + } + + // allOf + if( const auto* p = find( "allOf" ) ) { + if( !p->is_array() ) { + throw std::runtime_error( "invalid JSON Schema: \"allOf\" must be of type 'array'" ); + } + if( p->get_array().empty() ) { + throw std::runtime_error( "invalid JSON Schema: \"allOf\" must have at least one element" ); + } + for( const auto& e : p->get_array() ) { + m_referenced_pointers.insert( &e.skip_value_ptr() ); + } + m_all_of = p; + } + + // anyOf + if( const auto* p = find( "anyOf" ) ) { + if( !p->is_array() ) { + throw std::runtime_error( "invalid JSON Schema: \"anyOf\" must be of type 'array'" ); + } + if( p->get_array().empty() ) { + throw std::runtime_error( "invalid JSON Schema: \"anyOf\" must have at least one element" ); + } + for( const auto& e : p->get_array() ) { + m_referenced_pointers.insert( &e.skip_value_ptr() ); + } + m_any_of = p; + } + + // oneOf + if( const auto* p = find( "oneOf" ) ) { + if( !p->is_array() ) { + throw std::runtime_error( "invalid JSON Schema: \"oneOf\" must be of type 'array'" ); + } + if( p->get_array().empty() ) { + throw std::runtime_error( "invalid JSON Schema: \"oneOf\" must have at least one element" ); + } + for( const auto& e : p->get_array() ) { + m_referenced_pointers.insert( &e.skip_value_ptr() ); + } + m_one_of = p; + } + + // not + if( const auto* p = find( "not" ) ) { + m_referenced_pointers.insert( p ); + m_not = p; + } + + // definitions + if( const auto* p = find( "definitions" ) ) { + if( !p->is_object() ) { + throw std::runtime_error( "invalid JSON Schema: \"definitions\" must be of type 'object'" ); + } + for( const auto& e : p->get_object() ) { + m_referenced_pointers.insert( &e.second.skip_value_ptr() ); + } + } + + // multipleOf + if( const auto* p = find( "multipleOf" ) ) { + switch( p->type() ) { + case type::SIGNED: { + const auto i = p->get_signed(); + if( i <= 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"multipleOf\" must be strictly greater than zero" ); + } + m_multiple_of.u = i; + m_flags = m_flags | HAS_MULTIPLE_OF_UNSIGNED; + } break; + case type::UNSIGNED: { + const auto u = p->get_unsigned(); + if( u == 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"multipleOf\" must be strictly greater than zero" ); + } + m_multiple_of.u = u; + m_flags = m_flags | HAS_MULTIPLE_OF_UNSIGNED; + } break; + case type::DOUBLE: { + const auto d = p->get_double(); + if( d <= 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"multipleOf\" must be strictly greater than zero" ); + } + m_multiple_of.d = d; + m_flags = m_flags | HAS_MULTIPLE_OF_DOUBLE; + } break; + default: + throw std::runtime_error( "invalid JSON Schema: \"multipleOf\" must be of type 'number'" ); + } + } + + // maximum + if( const auto* p = find( "maximum" ) ) { + switch( p->type() ) { + case type::SIGNED: + m_maximum.i = p->get_signed(); + m_flags = m_flags | HAS_MAXIMUM_SIGNED; + break; + case type::UNSIGNED: + m_maximum.u = p->get_unsigned(); + m_flags = m_flags | HAS_MAXIMUM_UNSIGNED; + break; + case type::DOUBLE: + m_maximum.d = p->get_double(); + m_flags = m_flags | HAS_MAXIMUM_DOUBLE; + break; + default: + throw std::runtime_error( "invalid JSON Schema: \"maximum\" must be of type 'number'" ); + } + } + + // exclusiveMaximum + if( const auto* p = find( "exclusiveMaximum" ) ) { + if( !p->is_boolean() ) { + throw std::runtime_error( "invalid JSON Schema: \"exclusiveMaximum\" must be of type 'boolean'" ); + } + if( ( m_flags & HAS_MAXIMUM ) == 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"exclusiveMaximum\" requires presence of \"maximum\"" ); + } + if( p->get_boolean() ) { + m_flags = m_flags | EXCLUSIVE_MAXIMUM; + } + } + + // minimum + if( const auto* p = find( "minimum" ) ) { + switch( p->type() ) { + case type::SIGNED: + m_minimum.i = p->get_signed(); + m_flags = m_flags | HAS_MINIMUM_SIGNED; + break; + case type::UNSIGNED: + m_minimum.u = p->get_unsigned(); + m_flags = m_flags | HAS_MINIMUM_UNSIGNED; + break; + case type::DOUBLE: + m_minimum.d = p->get_double(); + m_flags = m_flags | HAS_MINIMUM_DOUBLE; + break; + default: + throw std::runtime_error( "invalid JSON Schema: \"minimum\" must be of type 'number'" ); + } + } + + // exclusiveMinimum + if( const auto* p = find( "exclusiveMinimum" ) ) { + if( !p->is_boolean() ) { + throw std::runtime_error( "invalid JSON Schema: \"exclusiveMinimum\" must be of type 'boolean'" ); + } + if( ( m_flags & HAS_MINIMUM ) == 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"exclusiveMinimum\" requires presence of \"minimum\"" ); + } + if( p->get_boolean() ) { + m_flags = m_flags | EXCLUSIVE_MINIMUM; + } + } + + // maxLength + if( const auto* p = find( "maxLength" ) ) { + switch( p->type() ) { + case type::SIGNED: { + const auto i = p->get_signed(); + if( i < 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"maxLength\" must be greater than or equal to zero" ); + } + m_max_length = i; + m_flags = m_flags | HAS_MAX_LENGTH; + } break; + case type::UNSIGNED: + m_max_length = p->get_unsigned(); + m_flags = m_flags | HAS_MAX_LENGTH; + break; + default: + throw std::runtime_error( "invalid JSON Schema: \"maxLength\" must be of type 'integer'" ); + } + } + + // minLength + if( const auto* p = find( "minLength" ) ) { + switch( p->type() ) { + case type::SIGNED: { + const auto i = p->get_signed(); + if( i < 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"minLength\" must be greater than or equal to zero" ); + } + if( i > 0 ) { + m_min_length = i; + m_flags = m_flags | HAS_MIN_LENGTH; + } + } break; + case type::UNSIGNED: { + const auto u = p->get_unsigned(); + if( u > 0 ) { + m_min_length = u; + m_flags = m_flags | HAS_MIN_LENGTH; + } + } break; + default: + throw std::runtime_error( "invalid JSON Schema: \"minLength\" must be of type 'integer'" ); + } + } + + // pattern + if( const auto* p = find( "pattern" ) ) { + if( !p->is_string() ) { + throw std::runtime_error( "invalid JSON Schema: \"pattern\" must be of type 'string'" ); + } + try { + m_pattern = std::make_unique< std::regex >( p->get_string() ); + } + catch( const std::regex_error& e ) { + throw std::runtime_error( "invalid JSON Schema: \"pattern\" must be a regular expression: " + std::string( e.what() ) ); + } + } + + // format + // TODO: offer an option to disable "format" support? + if( const auto* p = find( "format" ) ) { + if( !p->is_string() ) { + throw std::runtime_error( "invalid JSON Schema: \"format\" must be of type 'string'" ); + } + const auto& s = p->get_string(); + if( s == "date-time" ) { + m_format = schema_format::date_time; + } + else if( s == "email" ) { + m_format = schema_format::email; + } + else if( s == "hostname" ) { + m_format = schema_format::hostname; + } + else if( s == "ipv4" ) { + m_format = schema_format::ipv4; + } + else if( s == "ipv6" ) { + m_format = schema_format::ipv6; + } + else if( s == "uri" ) { + m_format = schema_format::uri; + } + // unknown "format" values are ignored + } + + // items + if( const auto* p = find( "items" ) ) { + if( p->is_array() ) { + for( const auto& e : p->get_array() ) { + m_referenced_pointers.insert( &e.skip_value_ptr() ); + } + } + else if( p->is_object() ) { + m_referenced_pointers.insert( p ); + } + else { + throw std::runtime_error( "invalid JSON Schema: \"items\" must be of type 'object' or 'array'" ); + } + m_items = p; + } + + // additionalItems + if( const auto* p = find( "additionalItems" ) ) { + if( p->is_object() ) { + m_referenced_pointers.insert( p ); + } + else if( !p->is_boolean() ) { + throw std::runtime_error( "invalid JSON Schema: \"additionalItems\" must be of type 'boolean' or 'object'" ); + } + m_additional_items = p; + } + + // maxItems + if( const auto* p = find( "maxItems" ) ) { + switch( p->type() ) { + case type::SIGNED: { + const auto i = p->get_signed(); + if( i < 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"maxItems\" must be greater than or equal to zero" ); + } + m_max_items = i; + m_flags = m_flags | HAS_MAX_ITEMS; + } break; + case type::UNSIGNED: + m_max_items = p->get_unsigned(); + m_flags = m_flags | HAS_MAX_ITEMS; + break; + default: + throw std::runtime_error( "invalid JSON Schema: \"maxItems\" must be of type 'integer'" ); + } + } + + // minItems + if( const auto* p = find( "minItems" ) ) { + switch( p->type() ) { + case type::SIGNED: { + const auto i = p->get_signed(); + if( i < 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"minItems\" must be greater than or equal to zero" ); + } + m_min_items = i; + m_flags = m_flags | HAS_MIN_ITEMS; + } break; + case type::UNSIGNED: + m_min_items = p->get_unsigned(); + m_flags = m_flags | HAS_MIN_ITEMS; + break; + default: + throw std::runtime_error( "invalid JSON Schema: \"minItems\" must be of type 'integer'" ); + } + } + + // uniqueItems + if( const auto* p = find( "uniqueItems" ) ) { + if( p->get_boolean() ) { + m_flags = m_flags | HAS_UNIQUE_ITEMS; + } + } + + // maxProperties + if( const auto* p = find( "maxProperties" ) ) { + switch( p->type() ) { + case type::SIGNED: { + const auto i = p->get_signed(); + if( i < 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"maxProperties\" must be greater than or equal to zero" ); + } + m_max_properties = i; + m_flags = m_flags | HAS_MAX_PROPERTIES; + } break; + case type::UNSIGNED: + m_max_properties = p->get_unsigned(); + m_flags = m_flags | HAS_MAX_PROPERTIES; + break; + default: + throw std::runtime_error( "invalid JSON Schema: \"maxProperties\" must be of type 'integer'" ); + } + } + + // minProperties + if( const auto* p = find( "minProperties" ) ) { + switch( p->type() ) { + case type::SIGNED: { + const auto i = p->get_signed(); + if( i < 0 ) { + throw std::runtime_error( "invalid JSON Schema: \"minProperties\" must be greater than or equal to zero" ); + } + m_min_properties = i; + m_flags = m_flags | HAS_MIN_PROPERTIES; + } break; + case type::UNSIGNED: + m_min_properties = p->get_unsigned(); + m_flags = m_flags | HAS_MIN_PROPERTIES; + break; + default: + throw std::runtime_error( "invalid JSON Schema: \"minProperties\" must be of type 'integer'" ); + } + } + + // required + if( const auto* p = find( "required" ) ) { + if( !p->is_array() ) { + throw std::runtime_error( "invalid JSON Schema: \"required\" must be of type 'array'" ); + } + if( p->get_array().empty() ) { + throw std::runtime_error( "invalid JSON Schema: \"required\" must have at least one element" ); + } + for( const auto& e : p->get_array() ) { + if( !m_required.insert( e.get_string() ).second ) { + throw std::runtime_error( "invalid JSON Schema: duplicate required key" ); + } + } + } + + // properties + if( const auto* p = find( "properties" ) ) { + if( !p->is_object() ) { + throw std::runtime_error( "invalid JSON Schema: \"properties\" must be of type 'object'" ); + } + for( const auto& e : p->get_object() ) { + m_referenced_pointers.insert( &e.second.skip_value_ptr() ); + } + m_properties = p; + } + + // patternProperties + if( const auto* p = find( "patternProperties" ) ) { + if( !p->is_object() ) { + throw std::runtime_error( "invalid JSON Schema: \"patternProperties\" must be of type 'object'" ); + } + for( const auto& e : p->get_object() ) { + try { + m_pattern_properties.emplace_back( std::regex( e.first ), &e.second.skip_value_ptr() ); + } + catch( const std::regex_error& ex ) { + throw std::runtime_error( "invalid JSON Schema: keys in object \"patternProperties\" must be regular expressions: " + std::string( ex.what() ) ); + } + m_referenced_pointers.insert( &e.second.skip_value_ptr() ); + } + } + + // additionalProperties + if( const auto* p = find( "additionalProperties" ) ) { + const type t = p->type(); + if( t == type::OBJECT ) { + m_referenced_pointers.insert( p ); + } + else if( t != type::BOOLEAN ) { + throw std::runtime_error( "invalid JSON Schema: \"additionalProperties\" must be of type 'boolean' or 'object'" ); + } + m_additional_properties = p; + } + + // dependencies + if( const auto* p = find( "dependencies" ) ) { + if( !p->is_object() ) { + throw std::runtime_error( "invalid JSON Schema: \"dependencies\" must be of type 'object'" ); + } + for( const auto& e : p->get_object() ) { + const auto* p2 = &e.second.skip_value_ptr(); + if( p2->is_object() ) { + m_schema_dependencies.emplace( e.first, p2 ); + m_referenced_pointers.insert( p2 ); + } + else if( p2->is_array() ) { + if( p2->get_array().empty() ) { + throw std::runtime_error( "invalid JSON Schema: values in object \"dependencies\" of type 'array' must have at least one element" ); + } + std::set< std::string > s; + for( const auto& r : p2->get_array() ) { + if( !r.is_string() ) { + throw std::runtime_error( "invalid JSON Schema: values in object \"dependencies\" of type 'array' must contain elements of type 'string'" ); + } + if( !s.emplace( r.get_string() ).second ) { + throw std::runtime_error( "invalid JSON Schema: values in object \"dependencies\" of type 'array' must contain unique elements of type 'string'" ); + } + } + m_property_dependencies.emplace( e.first, std::move( s ) ); + } + else { + throw std::runtime_error( "invalid JSON Schema: values in object \"dependencies\" must be of type 'object' or 'array'" ); + } + } + if( !p->get_object().empty() ) { + m_flags = m_flags | HAS_DEPENDENCIES; + } + } + + // default + if( const auto* p = find( "default" ) ) { + // TODO: the value should validate against the JSON Schema itself + } + } + + schema_node( const schema_node& ) = delete; + schema_node( schema_node&& ) = delete; + + ~schema_node() = default; + + void operator=( const schema_node& ) = delete; + void operator=( schema_node&& ) = delete; + + [[nodiscard]] const std::set< const basic_value< Traits >* >& referenced_pointers() const noexcept + { + return m_referenced_pointers; + } + }; + + template< template< typename... > class Traits > + class schema_consumer + { + private: + const std::shared_ptr< const schema_container< Traits > > m_container; + const schema_node< Traits >* const m_node; + + std::vector< std::unique_ptr< events_compare< Traits > > > m_enum; + std::unique_ptr< events::hash > m_hash; + std::set< std::string > m_unique; + std::set< std::string > m_keys; + std::vector< std::size_t > m_count; + std::vector< std::unique_ptr< schema_consumer > > m_properties; + std::vector< std::unique_ptr< schema_consumer > > m_all_of; + std::vector< std::unique_ptr< schema_consumer > > m_any_of; + std::vector< std::unique_ptr< schema_consumer > > m_one_of; + std::map< std::string, std::unique_ptr< schema_consumer > > m_schema_dependencies; + std::unique_ptr< schema_consumer > m_not; + std::unique_ptr< schema_consumer > m_item; + bool m_match = true; + + void validate_type( const schema_flags t ) + { + if( !m_count.empty() ) { + return; + } + if( ( m_node->m_flags & HAS_TYPE ) == 0 ) { + return; + } + if( ( m_node->m_flags & t ) == 0 ) { + m_match = false; + } + } + + // note: lambda returns true if validation failure detected + template< typename F > + void validate_enum( F&& f ) + { + assert( m_match ); + if( m_node->m_flags & HAS_ENUM ) { + m_enum.erase( std::remove_if( m_enum.begin(), m_enum.end(), [&]( const std::unique_ptr< events_compare< Traits > >& p ) { return f( *p ); } ), m_enum.end() ); + if( m_enum.empty() ) { + m_match = false; + } + } + } + + template< typename F > + void validate_item( F&& f ) + { + if( m_item ) { + if( f( m_item ) ) { + m_match = false; + } + } + } + + template< typename F > + void validate_properties( F&& f ) + { + for( auto& p : m_properties ) { + if( f( p ) ) { + m_match = false; + break; + } + } + } + + template< typename F > + void validate_schema_dependencies( F&& f ) + { + auto it = m_schema_dependencies.begin(); + while( it != m_schema_dependencies.end() ) { + if( f( it->second ) ) { + it = m_schema_dependencies.erase( it ); + } + else { + ++it; + } + } + } + + template< typename F > + void validate_all_of( F&& f ) + { + for( auto& p : m_all_of ) { + if( f( p ) ) { + m_match = false; + break; + } + } + } + + template< typename F > + void validate_any_of( F&& f ) + { + if( !m_any_of.empty() ) { + m_any_of.erase( std::remove_if( m_any_of.begin(), m_any_of.end(), f ), m_any_of.end() ); + if( m_any_of.empty() ) { + m_match = false; + } + } + } + + template< typename F > + void validate_one_of( F&& f ) + { + if( !m_one_of.empty() ) { + m_one_of.erase( std::remove_if( m_one_of.begin(), m_one_of.end(), f ), m_one_of.end() ); + if( m_one_of.empty() ) { + m_match = false; + } + } + } + + template< typename F > + void validate_not( F&& f ) + { + if( m_not ) { + if( f( m_not ) ) { + m_not.reset(); + } + } + } + + // note: lambda returns true if validation failure detected + template< typename F > + void validate_collections( F&& f ) + { + assert( m_match ); + const auto f2 = [&]( const std::unique_ptr< schema_consumer >& p ) { return f( *p ); }; + if( m_match ) { + validate_item( f2 ); + } + if( m_match ) { + validate_properties( f2 ); + } + if( m_match ) { + validate_all_of( f2 ); + } + if( m_match ) { + validate_any_of( f2 ); + } + if( m_match ) { + validate_one_of( f2 ); + } + if( m_match ) { + validate_not( f2 ); + } + if( m_match ) { + validate_schema_dependencies( f2 ); + } + } + + [[nodiscard]] static bool is_multiple_of( const double v, const double d ) + { + const auto r = std::fmod( v, d ); + if( std::fabs( r ) < std::numeric_limits< double >::epsilon() ) { + return true; + } + if( std::fabs( r - d ) < std::numeric_limits< double >::epsilon() ) { + return true; + } + return false; + } + + void validate_multiple_of( const std::int64_t v ) + { + switch( m_node->m_flags & HAS_MULTIPLE_OF ) { + case HAS_MULTIPLE_OF_UNSIGNED: + if( v < 0 ) { + if( ( -v % m_node->m_multiple_of.u ) != 0 ) { + m_match = false; + } + } + else { + if( ( v % m_node->m_multiple_of.u ) != 0 ) { + m_match = false; + } + } + break; + case HAS_MULTIPLE_OF_DOUBLE: + if( !is_multiple_of( double( v ), m_node->m_multiple_of.d ) ) { + m_match = false; + } + break; + } + } + + void validate_multiple_of( const std::uint64_t v ) + { + switch( m_node->m_flags & HAS_MULTIPLE_OF ) { + case HAS_MULTIPLE_OF_UNSIGNED: + if( ( v % m_node->m_multiple_of.u ) != 0 ) { + m_match = false; + } + break; + case HAS_MULTIPLE_OF_DOUBLE: + if( !is_multiple_of( double( v ), m_node->m_multiple_of.d ) ) { + m_match = false; + } + break; + } + } + + void validate_multiple_of( const double v ) + { + switch( m_node->m_flags & HAS_MULTIPLE_OF ) { + case HAS_MULTIPLE_OF_UNSIGNED: + if( !is_multiple_of( v, double( m_node->m_multiple_of.u ) ) ) { + m_match = false; + } + break; + case HAS_MULTIPLE_OF_DOUBLE: + if( !is_multiple_of( v, m_node->m_multiple_of.d ) ) { + m_match = false; + } + break; + } + } + + void validate_number( const std::int64_t v ) + { + validate_multiple_of( v ); + switch( m_node->m_flags & ( HAS_MAXIMUM | EXCLUSIVE_MAXIMUM ) ) { + case HAS_MAXIMUM_SIGNED: + if( v > m_node->m_maximum.i ) { + m_match = false; + } + break; + case HAS_MAXIMUM_SIGNED | EXCLUSIVE_MAXIMUM: + if( v >= m_node->m_maximum.i ) { + m_match = false; + } + break; + case HAS_MAXIMUM_UNSIGNED: + if( v >= 0 && static_cast< std::uint64_t >( v ) > m_node->m_maximum.u ) { + m_match = false; + } + break; + case HAS_MAXIMUM_UNSIGNED | EXCLUSIVE_MAXIMUM: + if( v >= 0 && static_cast< std::uint64_t >( v ) >= m_node->m_maximum.u ) { + m_match = false; + } + break; + case HAS_MAXIMUM_DOUBLE: + if( v > m_node->m_maximum.d ) { + m_match = false; + } + break; + case HAS_MAXIMUM_DOUBLE | EXCLUSIVE_MAXIMUM: + if( v >= m_node->m_maximum.d ) { + m_match = false; + } + break; + } + switch( m_node->m_flags & ( HAS_MINIMUM | EXCLUSIVE_MINIMUM ) ) { + case HAS_MINIMUM_SIGNED: + if( v < m_node->m_minimum.i ) { + m_match = false; + } + break; + case HAS_MINIMUM_SIGNED | EXCLUSIVE_MINIMUM: + if( v <= m_node->m_minimum.i ) { + m_match = false; + } + break; + case HAS_MINIMUM_UNSIGNED: + if( v < 0 || static_cast< std::uint64_t >( v ) < m_node->m_minimum.u ) { + m_match = false; + } + break; + case HAS_MINIMUM_UNSIGNED | EXCLUSIVE_MINIMUM: + if( v < 0 || static_cast< std::uint64_t >( v ) <= m_node->m_minimum.u ) { + m_match = false; + } + break; + case HAS_MINIMUM_DOUBLE: + if( v < m_node->m_minimum.d ) { + m_match = false; + } + break; + case HAS_MINIMUM_DOUBLE | EXCLUSIVE_MINIMUM: + if( v <= m_node->m_minimum.d ) { + m_match = false; + } + break; + } + } + + void validate_number( const std::uint64_t v ) + { + validate_multiple_of( v ); + switch( m_node->m_flags & ( HAS_MAXIMUM | EXCLUSIVE_MAXIMUM ) ) { + case HAS_MAXIMUM_SIGNED: + if( m_node->m_maximum.i < 0 || v > static_cast< std::uint64_t >( m_node->m_maximum.i ) ) { + m_match = false; + } + break; + case HAS_MAXIMUM_SIGNED | EXCLUSIVE_MAXIMUM: + if( m_node->m_maximum.i < 0 || v >= static_cast< std::uint64_t >( m_node->m_maximum.i ) ) { + m_match = false; + } + break; + case HAS_MAXIMUM_UNSIGNED: + if( v > m_node->m_maximum.u ) { + m_match = false; + } + break; + case HAS_MAXIMUM_UNSIGNED | EXCLUSIVE_MAXIMUM: + if( v >= m_node->m_maximum.u ) { + m_match = false; + } + break; + case HAS_MAXIMUM_DOUBLE: + if( v > m_node->m_maximum.d ) { + m_match = false; + } + break; + case HAS_MAXIMUM_DOUBLE | EXCLUSIVE_MAXIMUM: + if( v >= m_node->m_maximum.d ) { + m_match = false; + } + break; + } + switch( m_node->m_flags & ( HAS_MINIMUM | EXCLUSIVE_MINIMUM ) ) { + case HAS_MINIMUM_SIGNED: + if( m_node->m_minimum.i >= 0 && v < static_cast< std::uint64_t >( m_node->m_minimum.i ) ) { + m_match = false; + } + break; + case HAS_MINIMUM_SIGNED | EXCLUSIVE_MINIMUM: + if( m_node->m_minimum.i >= 0 && v <= static_cast< std::uint64_t >( m_node->m_minimum.i ) ) { + m_match = false; + } + break; + case HAS_MINIMUM_UNSIGNED: + if( v < m_node->m_minimum.u ) { + m_match = false; + } + break; + case HAS_MINIMUM_UNSIGNED | EXCLUSIVE_MINIMUM: + if( v <= m_node->m_minimum.u ) { + m_match = false; + } + break; + case HAS_MINIMUM_DOUBLE: + if( v < m_node->m_minimum.d ) { + m_match = false; + } + break; + case HAS_MINIMUM_DOUBLE | EXCLUSIVE_MINIMUM: + if( v <= m_node->m_minimum.d ) { + m_match = false; + } + break; + } + } + + void validate_number( const double v ) + { + validate_multiple_of( v ); + switch( m_node->m_flags & ( HAS_MAXIMUM | EXCLUSIVE_MAXIMUM ) ) { + case HAS_MAXIMUM_SIGNED: + if( v > m_node->m_maximum.i ) { + m_match = false; + } + break; + case HAS_MAXIMUM_SIGNED | EXCLUSIVE_MAXIMUM: + if( v >= m_node->m_maximum.i ) { + m_match = false; + } + break; + case HAS_MAXIMUM_UNSIGNED: + if( v > m_node->m_maximum.u ) { + m_match = false; + } + break; + case HAS_MAXIMUM_UNSIGNED | EXCLUSIVE_MAXIMUM: + if( v >= m_node->m_maximum.u ) { + m_match = false; + } + break; + case HAS_MAXIMUM_DOUBLE: + if( v > m_node->m_maximum.d ) { + m_match = false; + } + break; + case HAS_MAXIMUM_DOUBLE | EXCLUSIVE_MAXIMUM: + if( v >= m_node->m_maximum.d ) { + m_match = false; + } + break; + } + switch( m_node->m_flags & ( HAS_MINIMUM | EXCLUSIVE_MINIMUM ) ) { + case HAS_MINIMUM_SIGNED: + if( v < m_node->m_minimum.i ) { + m_match = false; + } + break; + case HAS_MINIMUM_SIGNED | EXCLUSIVE_MINIMUM: + if( v <= m_node->m_minimum.i ) { + m_match = false; + } + break; + case HAS_MINIMUM_UNSIGNED: + if( v < m_node->m_minimum.u ) { + m_match = false; + } + break; + case HAS_MINIMUM_UNSIGNED | EXCLUSIVE_MINIMUM: + if( v <= m_node->m_minimum.u ) { + m_match = false; + } + break; + case HAS_MINIMUM_DOUBLE: + if( v < m_node->m_minimum.d ) { + m_match = false; + } + break; + case HAS_MINIMUM_DOUBLE | EXCLUSIVE_MINIMUM: + if( v <= m_node->m_minimum.d ) { + m_match = false; + } + break; + } + } + + void validate_string( const std::string_view v ) + { + if( m_node->m_flags & HAS_MAX_LENGTH && v.size() > m_node->m_max_length ) { + m_match = false; + } + if( m_node->m_flags & HAS_MIN_LENGTH && v.size() < m_node->m_min_length ) { + m_match = false; + } + if( m_match && m_node->m_pattern ) { + if( !std::regex_search( v.begin(), v.end(), *m_node->m_pattern ) ) { + m_match = false; + } + } + if( m_match && m_node->m_format != schema_format::none ) { + switch( m_node->m_format ) { + case schema_format::date_time: + if( !internal::parse_date_time( v ) ) { + m_match = false; + } + break; + case schema_format::email: + if( ( v.size() > 255 ) || !internal::parse< internal::email >( v ) ) { + m_match = false; + } + break; + case schema_format::hostname: + if( ( v.size() > 255 ) || !internal::parse< internal::hostname >( v ) ) { + m_match = false; + } + break; + case schema_format::ipv4: + if( !internal::parse< pegtl::uri::IPv4address >( v ) ) { + m_match = false; + } + break; + case schema_format::ipv6: + if( !internal::parse< pegtl::uri::IPv6address >( v ) ) { + m_match = false; + } + break; + case schema_format::uri: + // TODO: What rule exactly should we apply here?? JSON Schema is not exactly the best spec I've ever read... + if( !internal::parse< pegtl::uri::URI >( v ) ) { + m_match = false; + } + break; + case schema_format::none:; + } + } + } + + void validate_elements( const std::size_t v ) + { + if( m_node->m_flags & HAS_MAX_ITEMS && v > m_node->m_max_items ) { + m_match = false; + } + if( m_node->m_flags & HAS_MIN_ITEMS && v < m_node->m_min_items ) { + m_match = false; + } + } + + void validate_members( const std::size_t v ) + { + if( m_node->m_flags & HAS_MAX_PROPERTIES && v > m_node->m_max_properties ) { + m_match = false; + } + if( m_node->m_flags & HAS_MIN_PROPERTIES && v < m_node->m_min_properties ) { + m_match = false; + } + } + + public: + schema_consumer( const std::shared_ptr< const schema_container< Traits > >& c, const schema_node< Traits >& n ) + : m_container( c ), + m_node( &n ) + { + if( m_node->m_flags & HAS_ENUM ) { + const auto& a = m_node->m_value->at( "enum" ).get_array(); + m_enum.reserve( a.size() ); + for( const auto& e : a ) { + m_enum.emplace_back( std::make_unique< events_compare< Traits > >() ); + m_enum.back()->push( &e ); + } + } + if( const auto* p = m_node->m_all_of ) { + for( const auto& e : p->get_array() ) { + m_all_of.push_back( m_container->consumer( &e.skip_value_ptr() ) ); + } + } + if( const auto* p = m_node->m_any_of ) { + for( const auto& e : p->get_array() ) { + m_any_of.push_back( m_container->consumer( &e.skip_value_ptr() ) ); + } + } + if( const auto* p = m_node->m_one_of ) { + for( const auto& e : p->get_array() ) { + m_one_of.push_back( m_container->consumer( &e.skip_value_ptr() ) ); + } + } + if( const auto* p = m_node->m_not ) { + m_not = m_container->consumer( p ); + } + for( const auto& e : m_node->m_schema_dependencies ) { + m_schema_dependencies.emplace( e.first, m_container->consumer( e.second ) ); + } + } + + schema_consumer( const schema_consumer& ) = delete; + schema_consumer( schema_consumer&& ) = delete; + + ~schema_consumer() = default; + + void operator=( const schema_consumer& ) = delete; + void operator=( schema_consumer&& ) = delete; + + [[nodiscard]] bool finalize() + { + if( m_match && !m_all_of.empty() ) { + for( auto& e : m_all_of ) { + if( !e->finalize() ) { + m_match = false; + break; + } + } + } + if( m_match && !m_any_of.empty() ) { + m_any_of.erase( std::remove_if( m_any_of.begin(), m_any_of.end(), []( const std::unique_ptr< schema_consumer >& c ) { return !c->finalize(); } ), m_any_of.end() ); + if( m_any_of.empty() ) { + m_match = false; + } + } + if( m_match && !m_one_of.empty() ) { + m_one_of.erase( std::remove_if( m_one_of.begin(), m_one_of.end(), []( const std::unique_ptr< schema_consumer >& c ) { return !c->finalize(); } ), m_one_of.end() ); + if( m_one_of.size() != 1 ) { + m_match = false; + } + } + if( m_match && m_not && m_not->finalize() ) { + m_match = false; + } + if( m_match && m_node->m_flags & HAS_DEPENDENCIES ) { + for( const auto& e : m_node->m_schema_dependencies ) { + if( m_keys.count( e.first ) != 0 ) { + const auto it = m_schema_dependencies.find( e.first ); + if( it == m_schema_dependencies.end() ) { + m_match = false; + break; + } + if( !it->second->finalize() ) { + m_match = false; + break; + } + } + } + } + return m_match; + } + + [[nodiscard]] bool match() const noexcept + { + return m_match; + } + + void null() + { + if( m_match ) { + validate_type( NULL_ ); + } + if( m_match ) { + validate_enum( []( events_compare< Traits >& c ) { c.null(); return ! c.match(); } ); + } + if( m_match ) { + validate_collections( []( schema_consumer& c ) { c.null(); return ! c.match(); } ); + } + if( m_match && m_hash ) { + m_hash->null(); + } + } + + void boolean( const bool v ) + { + if( m_match ) { + validate_type( BOOLEAN ); + } + if( m_match ) { + validate_enum( [=]( events_compare< Traits >& c ) { c.boolean( v ); return ! c.match(); } ); + } + if( m_match ) { + validate_collections( [=]( schema_consumer& c ) { c.boolean( v ); return ! c.match(); } ); + } + if( m_match && m_hash ) { + m_hash->boolean( v ); + } + } + + void number( const std::int64_t v ) + { + if( m_match ) { + validate_type( INTEGER | NUMBER ); + } + if( m_match ) { + validate_enum( [=]( events_compare< Traits >& c ) { c.number( v ); return ! c.match(); } ); + } + if( m_match ) { + validate_collections( [=]( schema_consumer& c ) { c.number( v ); return ! c.match(); } ); + } + if( m_match && m_count.empty() ) { + validate_number( v ); + } + if( m_match && m_hash ) { + m_hash->number( v ); + } + } + + void number( const std::uint64_t v ) + { + if( m_match ) { + validate_type( INTEGER | NUMBER ); + } + if( m_match ) { + validate_enum( [=]( events_compare< Traits >& c ) { c.number( v ); return ! c.match(); } ); + } + if( m_match ) { + validate_collections( [=]( schema_consumer& c ) { c.number( v ); return ! c.match(); } ); + } + if( m_match && m_count.empty() ) { + validate_number( v ); + } + if( m_match && m_hash ) { + m_hash->number( v ); + } + } + + void number( const double v ) + { + if( m_match ) { + validate_type( NUMBER ); + } + if( m_match ) { + validate_enum( [=]( events_compare< Traits >& c ) { c.number( v ); return ! c.match(); } ); + } + if( m_match ) { + validate_collections( [=]( schema_consumer& c ) { c.number( v ); return ! c.match(); } ); + } + if( m_match && m_count.empty() ) { + validate_number( v ); + } + if( m_match && m_hash ) { + m_hash->number( v ); + } + } + + void string( const std::string_view v ) + { + if( m_match ) { + validate_type( STRING ); + } + if( m_match ) { + validate_enum( [&]( events_compare< Traits >& c ) { c.string( v ); return ! c.match(); } ); + } + if( m_match ) { + validate_collections( [&]( schema_consumer& c ) { c.string( v ); return ! c.match(); } ); + } + if( m_match && m_count.empty() ) { + validate_string( v ); + } + if( m_match && m_hash ) { + m_hash->string( v ); + } + } + + void binary( const tao::binary_view /*unused*/ ) + { + // TODO: What? + } + + void begin_array( const std::size_t /*unused*/ = 0 ) + { + if( m_match ) { + validate_type( ARRAY ); + } + if( m_match ) { + validate_enum( []( events_compare< Traits >& c ) { c.begin_array(); return ! c.match(); } ); + } + if( m_match ) { + validate_collections( []( schema_consumer& c ) { c.begin_array(); return ! c.match(); } ); + } + if( m_match ) { + if( m_hash ) { + m_hash->begin_array(); + } + else if( m_count.empty() && ( ( m_node->m_flags & HAS_UNIQUE_ITEMS ) != 0 ) ) { + m_hash = std::make_unique< events::hash >(); + } + } + if( m_match && m_count.empty() ) { + if( const auto* p = m_node->m_items ) { + if( p->is_object() ) { + m_item = m_container->consumer( p ); + } + else { + const auto& a = p->get_array(); + if( !a.empty() ) { + m_item = m_container->consumer( &a[ 0 ].skip_value_ptr() ); + } + } + } + if( !m_item ) { + if( const auto* p = m_node->m_additional_items ) { + if( p->is_object() ) { + m_item = m_container->consumer( p ); + } + } + } + } + m_count.push_back( 0 ); + } + + void element() + { + if( m_match ) { + validate_enum( []( events_compare< Traits >& c ) { c.element(); return ! c.match(); } ); + } + if( m_match && m_item ) { + if( m_count.size() == 1 ) { + if( !m_item->finalize() ) { + m_match = false; + } + m_item.reset(); + } + } + if( m_match ) { + validate_collections( []( schema_consumer& c ) { c.element(); return ! c.match(); } ); + } + if( m_match && m_hash ) { + if( m_count.size() == 1 ) { + if( !m_unique.emplace( m_hash->value() ).second ) { + m_match = false; + } + m_hash->reset(); + } + else { + m_hash->element(); + } + } + const auto next = ++m_count.back(); + if( m_match && ( m_count.size() == 1 ) ) { + if( const auto* p = m_node->m_items ) { + if( p->is_object() ) { + m_item = m_container->consumer( p ); + } + else { + const auto& a = p->get_array(); + if( next < a.size() ) { + m_item = m_container->consumer( &a[ next ].skip_value_ptr() ); + } + } + } + if( !m_item ) { + if( const auto* p = m_node->m_additional_items ) { + if( p->is_object() ) { + m_item = m_container->consumer( p ); + } + } + } + } + } + + void end_array( const std::size_t /*unused*/ = 0 ) + { + if( m_match ) { + validate_enum( []( events_compare< Traits >& c ) { c.end_array(); return ! c.match(); } ); + } + if( m_match && m_item && ( m_count.size() == 1 ) ) { + if( !m_item->finalize() ) { + m_match = false; + } + m_item.reset(); + } + if( m_match && ( m_count.size() == 1 ) ) { + if( m_node->m_items && m_node->m_items->is_array() ) { + if( m_node->m_additional_items && m_node->m_additional_items->is_boolean() ) { + if( !m_node->m_additional_items->get_boolean() ) { + if( m_count.back() > m_node->m_items->get_array().size() ) { + m_match = false; + } + } + } + } + } + if( m_match ) { + validate_collections( []( schema_consumer& c ) { c.end_array(); return ! c.match(); } ); + } + if( m_match && m_hash ) { + m_hash->end_array(); + } + if( m_match && ( m_count.size() == 1 ) ) { + validate_elements( m_count.back() ); + } + m_count.pop_back(); + } + + void begin_object( const std::size_t /*unused*/ = 0 ) + { + if( m_match ) { + validate_type( OBJECT ); + } + if( m_match ) { + validate_enum( []( events_compare< Traits >& c ) { c.begin_object(); return ! c.match(); } ); + } + if( m_match ) { + validate_collections( []( schema_consumer& c ) { c.begin_object(); return ! c.match(); } ); + } + if( m_match && m_hash ) { + m_hash->begin_object(); + } + m_count.push_back( 0 ); + } + + void key( const std::string& v ) + { + if( m_match ) { + validate_enum( [&]( events_compare< Traits >& c ) { c.key( v ); return ! c.match(); } ); + } + if( m_match ) { + validate_collections( [&]( schema_consumer& c ) { c.key( v ); return ! c.match(); } ); + } + if( m_match && m_hash ) { + m_hash->key( v ); + } + if( m_match && ( m_count.size() == 1 ) && ( m_node->m_flags & HAS_DEPENDENCIES || !m_node->m_required.empty() ) ) { + if( !m_keys.insert( v ).second ) { + // duplicate keys immediately invalidate! + // TODO: throw? + m_match = false; + } + } + if( m_match && m_properties.empty() && ( m_count.size() == 1 ) ) { + if( const auto* p = m_node->m_properties ) { + const auto& o = p->get_object(); + const auto it = o.find( v ); + if( it != o.end() ) { + m_properties.push_back( m_container->consumer( &it->second.skip_value_ptr() ) ); + } + } + for( const auto& e : m_node->m_pattern_properties ) { + if( std::regex_search( v, e.first ) ) { + m_properties.push_back( m_container->consumer( e.second ) ); + } + } + if( m_properties.empty() ) { + if( const auto* p = m_node->m_additional_properties ) { + if( p->is_boolean() ) { + if( !p->get_boolean() ) { + m_match = false; + } + } + else { + m_properties.push_back( m_container->consumer( p ) ); + } + } + } + } + } + + void key( const std::string_view sv ) + { + key( std::string( sv ) ); + } + + void key( const char* v ) + { + key( std::string( v ) ); + } + + void member() + { + if( m_match ) { + validate_enum( []( events_compare< Traits >& c ) { c.member(); return ! c.match(); } ); + } + if( m_match && !m_properties.empty() && ( m_count.size() == 1 ) ) { + for( auto& e : m_properties ) { + if( !e->finalize() ) { + m_match = false; + break; + } + } + m_properties.clear(); + } + if( m_match ) { + validate_collections( []( schema_consumer& c ) { c.member(); return ! c.match(); } ); + } + if( m_match && m_hash ) { + m_hash->member(); + } + ++m_count.back(); + } + + void end_object( const std::size_t /*unused*/ = 0 ) + { + if( m_match ) { + validate_enum( []( events_compare< Traits >& c ) { c.end_object(); return ! c.match(); } ); + } + if( m_match ) { + validate_collections( []( schema_consumer& c ) { c.end_object(); return ! c.match(); } ); + } + if( m_match && m_hash ) { + m_hash->end_object(); + } + if( m_match && ( m_count.size() == 1 ) ) { + validate_members( m_count.back() ); + } + if( m_match && ( m_count.size() == 1 ) && !m_node->m_required.empty() ) { + if( !std::includes( m_keys.begin(), m_keys.end(), m_node->m_required.begin(), m_node->m_required.end() ) ) { + m_match = false; + } + } + if( m_match && ( m_count.size() == 1 ) && m_node->m_flags & HAS_DEPENDENCIES ) { + for( const auto& e : m_node->m_property_dependencies ) { + if( m_keys.count( e.first ) != 0 ) { + if( !std::includes( m_keys.begin(), m_keys.end(), e.second.begin(), e.second.end() ) ) { + m_match = false; + break; + } + } + } + } + m_count.pop_back(); + } + }; + + template< template< typename... > class Traits > + class schema_container + : public std::enable_shared_from_this< schema_container< Traits > > + { + private: + basic_value< Traits > m_value; + + using nodes_t = std::map< const basic_value< Traits >*, std::unique_ptr< schema_node< Traits > > >; + nodes_t m_nodes; + + void make_node( const basic_value< Traits >* p ) + { + m_nodes.emplace( p, std::make_unique< schema_node< Traits > >( this, *p ) ); + } + + public: + explicit schema_container( const basic_value< Traits >& v ) + : m_value( v.skip_value_ptr() ) + { + resolve_references( m_value ); + make_node( &m_value ); + while( true ) { + std::set< const basic_value< Traits >* > required; + for( const auto& e : m_nodes ) { + auto s = e.second->referenced_pointers(); + required.insert( s.begin(), s.end() ); + } + for( const auto& e : m_nodes ) { + required.erase( e.first ); + } + if( required.empty() ) { + break; + } + for( const auto& e : required ) { + make_node( e ); + } + } + } + + [[nodiscard]] std::unique_ptr< schema_consumer< Traits > > consumer( const basic_value< Traits >* p ) const + { + const auto it = m_nodes.find( p ); + if( it == m_nodes.end() ) { + throw std::logic_error( "invalid node ptr, no schema registered" ); + } + return std::make_unique< schema_consumer< Traits > >( this->shared_from_this(), *it->second ); + } + + [[nodiscard]] std::unique_ptr< schema_consumer< Traits > > consumer() const + { + return consumer( &m_value ); + } + }; + + } // namespace internal + + template< template< typename... > class Traits > + class basic_schema + { + private: + const std::shared_ptr< const internal::schema_container< Traits > > m_container; + + public: + explicit basic_schema( const basic_value< Traits >& v ) + : m_container( std::make_shared< internal::schema_container< Traits > >( v ) ) + { + } + + [[nodiscard]] std::unique_ptr< internal::schema_consumer< Traits > > consumer() const + { + return m_container->consumer(); + } + + [[nodiscard]] bool validate( const basic_value< Traits >& v ) const + { + // TODO: Value validation should be implemented independently, + // as it could be more efficient than Events validation! + const auto c = consumer(); + events::from_value( *c, v ); + return c->finalize(); + } + }; + + using schema = basic_schema< traits >; + + template< template< typename... > class Traits > + [[nodiscard]] basic_schema< Traits > make_schema( const basic_value< Traits >& v ) + { + return basic_schema< Traits >( v ); + } + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/set_traits.hpp b/include/tao/json/contrib/set_traits.hpp new file mode 100644 index 00000000..0b4b5fd4 --- /dev/null +++ b/include/tao/json/contrib/set_traits.hpp @@ -0,0 +1,41 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_SET_TRAITS_HPP +#define TAO_JSON_CONTRIB_SET_TRAITS_HPP + +#include + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "internal/array_traits.hpp" + +namespace tao::json +{ + template< typename T, typename... Ts > + struct set_traits + : internal::array_traits< std::set< T, Ts... > > + { + template< template< typename... > class Traits, typename... With > + static void to( const basic_value< Traits >& v, std::set< T, Ts... >& r, With&... with ) + { + const auto& a = v.get_array(); + for( const auto& i : a ) { + r.emplace( i.template as_with< T >( with... ) ); + } + } + + template< template< typename... > class Traits, typename Producer > + static void consume( Producer& parser, std::set< T, Ts... >& r ) + { + auto s = parser.begin_array(); + while( parser.element_or_end_array( s ) ) { + r.emplace( json::consume< T, Traits >( parser ) ); + } + } + }; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/shared_ptr_traits.hpp b/include/tao/json/contrib/shared_ptr_traits.hpp new file mode 100644 index 00000000..a6c45713 --- /dev/null +++ b/include/tao/json/contrib/shared_ptr_traits.hpp @@ -0,0 +1,90 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_SHARED_PTR_TRAITS_HPP +#define TAO_JSON_CONTRIB_SHARED_PTR_TRAITS_HPP + +#include +#include +#include + +#include "../forward.hpp" + +#include "internal/indirect_traits.hpp" +#include "internal/type_traits.hpp" + +namespace tao::json +{ + namespace internal + { + template< typename T, typename U > + struct shared_ptr_traits + { + template< template< typename... > class Traits, typename... With > + [[nodiscard]] static auto as( const basic_value< Traits >& v, With&... with ) -> std::enable_if_t< use_first_ptr_as< T, Traits, With... >, std::shared_ptr< U > > + { + return std::make_shared< T >( v, with... ); + } + + template< template< typename... > class Traits, typename... With > + [[nodiscard]] static auto as( const basic_value< Traits >& v, With&... with ) -> std::enable_if_t< use_second_ptr_as< T, Traits, With... > || use_fourth_ptr_as< T, Traits, With... >, std::shared_ptr< U > > + { + return std::make_shared< T >( Traits< T >::as( v, with... ) ); + } + + template< template< typename... > class Traits, typename... With > + [[nodiscard]] static auto as( const basic_value< Traits >& v, With&... with ) -> std::enable_if_t< use_third_ptr_as< T, Traits, With... >, std::shared_ptr< U > > + { + auto t = std::make_shared< T >(); + Traits< T >::to( v, *t, with... ); + return t; + } + + template< template< typename... > class Traits, typename Producer > + [[nodiscard]] static auto consume( Producer& parser ) -> std::enable_if_t< use_first_ptr_consume< T, Traits, Producer > || use_third_ptr_consume< T, Traits, Producer >, std::shared_ptr< U > > + { + return Traits< T >::template consume< Traits >( parser ); + } + + template< template< typename... > class Traits, typename Producer > + [[nodiscard]] static auto consume( Producer& parser ) -> std::enable_if_t< use_second_ptr_consume< T, Traits, Producer >, std::shared_ptr< U > > + { + auto t = std::make_shared< T >(); + Traits< T >::template consume< Traits >( parser, *t ); + return t; + } + }; + + } // namespace internal + + template< typename T, typename U = T > + struct shared_ptr_traits + : internal::shared_ptr_traits< T, U > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const std::shared_ptr< U >& o ) + { + assert( o ); + v = static_cast< const T& >( *o ); + } + + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, const std::shared_ptr< U >& o ) + { + assert( o ); + json::events::produce< Traits >( c, static_cast< const T& >( *o ) ); + } + }; + + template< typename T > + struct shared_ptr_traits< T, T > + : internal::shared_ptr_traits< T, T >, + internal::indirect_traits< std::shared_ptr< T > > + { + template< typename V > + using with_base = shared_ptr_traits< T, V >; + }; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/traits.hpp b/include/tao/json/contrib/traits.hpp new file mode 100644 index 00000000..16504d76 --- /dev/null +++ b/include/tao/json/contrib/traits.hpp @@ -0,0 +1,121 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_TRAITS_HPP +#define TAO_JSON_CONTRIB_TRAITS_HPP + +#include "../traits.hpp" + +#include "pair_traits.hpp" +#include "tuple_traits.hpp" + +#include "pointer_traits.hpp" + +#include "array_traits.hpp" +#include "deque_traits.hpp" +#include "list_traits.hpp" +#include "set_traits.hpp" +#include "unordered_set_traits.hpp" +#include "vector_traits.hpp" + +#include "vector_bool_traits.hpp" + +#include "map_traits.hpp" +#include "unordered_map_traits.hpp" + +#include "multimap_traits.hpp" +#include "multiset_traits.hpp" + +#include "shared_ptr_traits.hpp" +#include "unique_ptr_traits.hpp" + +namespace tao::json +{ + template< typename U, typename V > + struct traits< std::pair< U, V > > + : pair_traits< U, V > + {}; + + template< typename... Ts > + struct traits< std::tuple< Ts... > > + : tuple_traits< Ts... > + {}; + + template<> + struct traits< token > + : token_traits + {}; + + template<> + struct traits< pointer > + : pointer_traits + {}; + + template< typename T, std::size_t N > + struct traits< std::array< T, N > > + : array_traits< T, N > + {}; + + template< typename T, typename... Ts > + struct traits< std::deque< T, Ts... > > + : deque_traits< T, Ts... > + {}; + + template< typename T, typename... Ts > + struct traits< std::list< T, Ts... > > + : list_traits< T, Ts... > + {}; + + template< typename T, typename... Ts > + struct traits< std::set< T, Ts... > > + : set_traits< T, Ts... > + {}; + + template< typename T, typename... Ts > + struct traits< std::unordered_set< T, Ts... > > + : unordered_set_traits< T, Ts... > + {}; + + template< typename T, typename... Ts > + struct traits< std::vector< T, Ts... > > + : vector_traits< T, Ts... > + {}; + + template<> + struct traits< std::vector< bool > > + : vector_bool_traits + {}; + + template< typename T, typename... Ts > + struct traits< std::map< std::string, T, Ts... > > + : map_traits< T, Ts... > + {}; + + template< typename T, typename... Ts > + struct traits< std::unordered_map< std::string, T, Ts... > > + : unordered_map_traits< T, Ts... > + {}; + + template< typename T, typename... Ts > + struct traits< std::multiset< T, Ts... > > + : multiset_traits< T, Ts... > + {}; + + template< typename T, typename... Ts > + struct traits< std::multimap< std::string, T, Ts... > > + : multimap_traits< T, Ts... > + {}; + + template< typename T > + struct traits< std::shared_ptr< T > > + : shared_ptr_traits< T > + {}; + + template< typename T > + struct traits< std::unique_ptr< T > > + : unique_ptr_traits< T > + {}; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/tuple_traits.hpp b/include/tao/json/contrib/tuple_traits.hpp new file mode 100644 index 00000000..3061cfa2 --- /dev/null +++ b/include/tao/json/contrib/tuple_traits.hpp @@ -0,0 +1,51 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_TUPLE_TRAITS_HPP +#define TAO_JSON_CONTRIB_TUPLE_TRAITS_HPP + +#include +#include + +#include "../binding.hpp" + +namespace tao::json +{ + namespace internal + { + template< std::size_t I, typename... Ts > + struct getter + { + [[nodiscard]] static decltype( auto ) get( std::tuple< Ts... >& t ) noexcept + { + return std::get< I >( t ); + } + + [[nodiscard]] static decltype( auto ) cget( const std::tuple< Ts... >& t ) noexcept + { + return std::get< I >( t ); + } + }; + + template< typename Indices, typename... Ts > + struct tuple_traits; + + template< std::size_t... Is, typename... Ts > + struct tuple_traits< std::index_sequence< Is... >, Ts... > + { + template< std::size_t I > + using helper_t = binding::element2< &getter< I, Ts... >::cget, &getter< I, Ts... >::get >; + + using type = binding::array< helper_t< Is >... >; + }; + + } // namespace internal + + template< typename... Ts > + struct tuple_traits + : internal::tuple_traits< std::index_sequence_for< Ts... >, Ts... >::type + {}; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/unique_ptr_traits.hpp b/include/tao/json/contrib/unique_ptr_traits.hpp new file mode 100644 index 00000000..58f87483 --- /dev/null +++ b/include/tao/json/contrib/unique_ptr_traits.hpp @@ -0,0 +1,89 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_UNIQUE_PTR_TRAITS_HPP +#define TAO_JSON_CONTRIB_UNIQUE_PTR_TRAITS_HPP + +#include +#include + +#include "../forward.hpp" + +#include "internal/indirect_traits.hpp" +#include "internal/type_traits.hpp" + +namespace tao::json +{ + namespace internal + { + template< typename T, typename U > + struct unique_ptr_traits + { + template< template< typename... > class Traits, typename... With > + [[nodiscard]] static auto as( const basic_value< Traits >& v, With&... with ) -> std::enable_if_t< use_first_ptr_as< T, Traits, With... >, std::unique_ptr< U > > + { + return std::unique_ptr< U >( new T( v, with... ) ); + } + + template< template< typename... > class Traits, typename... With > + [[nodiscard]] static auto as( const basic_value< Traits >& v, With&... with ) -> std::enable_if_t< use_second_ptr_as< T, Traits, With... > || use_fourth_ptr_as< T, Traits, With... >, std::unique_ptr< U > > + { + return std::unique_ptr< U >( new T( Traits< T >::as( v, with... ) ) ); + } + + template< template< typename... > class Traits, typename... With > + [[nodiscard]] static auto as( const basic_value< Traits >& v, With&... with ) -> std::enable_if_t< use_third_ptr_as< T, Traits, With... >, std::unique_ptr< U > > + { + std::unique_ptr< U > t( new T() ); + Traits< T >::to( v, static_cast< T& >( *t ), with... ); + return t; + } + + template< template< typename... > class Traits, typename Producer > + [[nodiscard]] static auto consume( Producer& parser ) -> std::enable_if_t< use_first_ptr_consume< T, Traits, Producer > || use_third_ptr_consume< T, Traits, Producer >, std::unique_ptr< U > > + { + return Traits< T >::template consume< Traits >( parser ); + } + + template< template< typename... > class Traits, typename Producer > + [[nodiscard]] static auto consume( Producer& parser ) -> std::enable_if_t< use_second_ptr_consume< T, Traits, Producer >, std::unique_ptr< U > > + { + std::unique_ptr< U > t( new T() ); + Traits< T >::template consume< Traits >( parser, static_cast< T& >( *t ) ); + return t; + } + }; + + } // namespace internal + + template< typename T, typename U = T > + struct unique_ptr_traits + : internal::unique_ptr_traits< T, U > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const std::unique_ptr< U >& o ) + { + assert( o ); + v = static_cast< const T& >( *o ); + } + + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, const std::unique_ptr< U >& o ) + { + assert( o ); + json::events::produce< Traits >( c, static_cast< const T& >( *o ) ); + } + }; + + template< typename T > + struct unique_ptr_traits< T, T > + : internal::unique_ptr_traits< T, T >, + internal::indirect_traits< std::unique_ptr< T > > + { + template< typename V > + using with_base = unique_ptr_traits< T, V >; + }; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/unordered_map_traits.hpp b/include/tao/json/contrib/unordered_map_traits.hpp new file mode 100644 index 00000000..b591981a --- /dev/null +++ b/include/tao/json/contrib/unordered_map_traits.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_UNORDERED_MAP_TRAITS_HPP +#define TAO_JSON_CONTRIB_UNORDERED_MAP_TRAITS_HPP + +#include +#include + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "internal/object_traits.hpp" + +namespace tao::json +{ + template< typename T, typename... Ts > + struct unordered_map_traits + : internal::object_traits< std::unordered_map< std::string, T, Ts... > > + { + template< template< typename... > class Traits, typename... With > + static void to( const basic_value< Traits >& v, std::unordered_map< std::string, T, Ts... >& r, With&... with ) + { + const auto& o = v.get_object(); + for( const auto& i : o ) { + r.try_emplace( i.first, Traits< T >::as( i.second, with... ) ); + } + } + + template< template< typename... > class Traits, typename Producer > + static void consume( Producer& parser, std::unordered_map< std::string, T, Ts... >& v ) + { + auto s = parser.begin_object(); + while( parser.member_or_end_object( s ) ) { + auto k = parser.key(); + v.try_emplace( std::move( k ), json::consume< T, Traits >( parser ) ); + } + } + }; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/unordered_set_traits.hpp b/include/tao/json/contrib/unordered_set_traits.hpp new file mode 100644 index 00000000..45b5de01 --- /dev/null +++ b/include/tao/json/contrib/unordered_set_traits.hpp @@ -0,0 +1,41 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_UNORDERED_SET_TRAITS_HPP +#define TAO_JSON_CONTRIB_UNORDERED_SET_TRAITS_HPP + +#include + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "internal/array_traits.hpp" + +namespace tao::json +{ + template< typename T, typename... Ts > + struct unordered_set_traits + : internal::array_traits< std::unordered_set< T, Ts... > > + { + template< template< typename... > class Traits, typename... With > + static void to( const basic_value< Traits >& v, std::unordered_set< T, Ts... >& r, With&... with ) + { + const auto& a = v.get_array(); + for( const auto& i : a ) { + r.try_emplace( Traits< T >::as( i, with... ) ); + } + } + + template< template< typename... > class Traits, typename Producer > + static void consume( Producer& parser, std::unordered_set< T, Ts... >& r ) + { + auto s = parser.begin_array(); + while( parser.element_or_end_array( s ) ) { + r.try_emplace( json::consume< T, Traits >( parser ) ); + } + } + }; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/vector_bool_traits.hpp b/include/tao/json/contrib/vector_bool_traits.hpp new file mode 100644 index 00000000..3b1d8db6 --- /dev/null +++ b/include/tao/json/contrib/vector_bool_traits.hpp @@ -0,0 +1,45 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_VECTOR_BOOL_TRAITS_HPP +#define TAO_JSON_CONTRIB_VECTOR_BOOL_TRAITS_HPP + +#include + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "vector_traits.hpp" + +namespace tao::json +{ + struct vector_bool_traits + : vector_traits< bool > + { + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const std::vector< bool >& o ) + { + v.emplace_array(); + v.get_array().reserve( o.size() ); + for( const auto& e : o ) { + v.emplace_back( bool( e ) ); + } + } + + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, const std::vector< bool >& o ) + { + c.begin_array( o.size() ); + for( const auto& i : o ) { + json::events::produce< Traits >( c, bool( i ) ); + c.element(); + } + c.end_array( o.size() ); + } + + // TODO: Check whether anything else needs "special-casing". + }; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/contrib/vector_traits.hpp b/include/tao/json/contrib/vector_traits.hpp new file mode 100644 index 00000000..32c3734f --- /dev/null +++ b/include/tao/json/contrib/vector_traits.hpp @@ -0,0 +1,51 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_CONTRIB_VECTOR_TRAITS_HPP +#define TAO_JSON_CONTRIB_VECTOR_TRAITS_HPP + +#include + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "internal/array_traits.hpp" + +namespace tao::json +{ + template< typename T, typename... Ts > + struct vector_traits + : internal::array_traits< std::vector< T, Ts... > > + { + template< template< typename... > class Traits, typename... With > + static void to( const basic_value< Traits >& v, std::vector< T, Ts... >& r, With&... with ) + { + const auto& a = v.get_array(); + for( const auto& i : a ) { + r.emplace_back( i.template as_with< T >( with... ) ); + } + } + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4127 ) +#endif + template< template< typename... > class Traits, typename Producer > + static void consume( Producer& parser, std::vector< T, Ts... >& v ) + { + auto s = parser.begin_array(); + if( s.size ) { + v.reserve( *s.size ); + } + while( parser.element_or_end_array( s ) ) { + v.emplace_back( json::consume< T, Traits >( parser ) ); + } + } +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + }; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/events.hpp b/include/tao/json/events.hpp new file mode 100644 index 00000000..8063909c --- /dev/null +++ b/include/tao/json/events.hpp @@ -0,0 +1,47 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_EVENTS_HPP +#define TAO_JSON_EVENTS_HPP + +// Events producers +#include "events/from_file.hpp" +#include "events/from_input.hpp" +#include "events/from_stream.hpp" +#include "events/from_string.hpp" +#include "events/from_value.hpp" +#include "events/produce.hpp" + +// Events consumers +#include "events/to_pretty_stream.hpp" +#include "events/to_stream.hpp" +#include "events/to_string.hpp" +#include "events/to_value.hpp" + +// Events transformers +#include "events/binary_to_base64.hpp" +#include "events/binary_to_base64url.hpp" +#include "events/binary_to_exception.hpp" +#include "events/binary_to_hex.hpp" +#include "events/invalid_string_to_binary.hpp" +#include "events/invalid_string_to_exception.hpp" +#include "events/invalid_string_to_hex.hpp" +#include "events/key_camel_case_to_snake_case.hpp" +#include "events/key_snake_case_to_camel_case.hpp" +#include "events/limit_nesting_depth.hpp" +#include "events/limit_value_count.hpp" +#include "events/non_finite_to_exception.hpp" +#include "events/non_finite_to_null.hpp" +#include "events/non_finite_to_string.hpp" +#include "events/prefer_signed.hpp" +#include "events/prefer_unsigned.hpp" + +// Events other +#include "events/debug.hpp" +#include "events/discard.hpp" +#include "events/hash.hpp" +#include "events/tee.hpp" +#include "events/validate_event_order.hpp" +#include "events/validate_keys.hpp" + +#endif diff --git a/include/tao/json/events/apply.hpp b/include/tao/json/events/apply.hpp index 8a772d8a..78a1ba90 100644 --- a/include/tao/json/events/apply.hpp +++ b/include/tao/json/events/apply.hpp @@ -1,28 +1,20 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_APPLY_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_APPLY_HPP +#ifndef TAO_JSON_EVENTS_APPLY_HPP +#define TAO_JSON_EVENTS_APPLY_HPP #include "ref.hpp" #include "transformer.hpp" -namespace tao +namespace tao::json::events { - namespace json + template< template< typename... > class... Transformer, typename Consumer > + [[nodiscard]] transformer< ref< Consumer >, Transformer... > apply( Consumer& c ) noexcept( noexcept( transformer< ref< Consumer >, Transformer... >( c ) ) ) { - namespace events - { - template< template< typename... > class... Transformer, typename Consumer > - transformer< ref< Consumer >, Transformer... > apply( Consumer& c ) noexcept( noexcept( transformer< ref< Consumer >, Transformer... >( c ) ) ) - { - return transformer< ref< Consumer >, Transformer... >( c ); - } + return transformer< ref< Consumer >, Transformer... >( c ); + } - } // namespace events - - } // namespace json - -} // namespace tao +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/binary_to_base64.hpp b/include/tao/json/events/binary_to_base64.hpp index a8729ead..dcf930d2 100644 --- a/include/tao/json/events/binary_to_base64.hpp +++ b/include/tao/json/events/binary_to_base64.hpp @@ -1,34 +1,26 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_BINARY_TO_BASE64_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_BINARY_TO_BASE64_HPP +#ifndef TAO_JSON_EVENTS_BINARY_TO_BASE64_HPP +#define TAO_JSON_EVENTS_BINARY_TO_BASE64_HPP -#include "../byte_view.hpp" +#include "../binary_view.hpp" #include "../internal/base64.hpp" -namespace tao +namespace tao::json::events { - namespace json + template< typename Consumer > + struct binary_to_base64 + : Consumer { - namespace events - { - template< typename Consumer > - struct binary_to_base64 - : public Consumer - { - using Consumer::Consumer; - - void binary( const tao::byte_view v ) - { - Consumer::string( internal::base64( v ) ); - } - }; + using Consumer::Consumer; - } // namespace events - - } // namespace json + void binary( const tao::binary_view v ) + { + Consumer::string( internal::base64( v ) ); + } + }; -} // namespace tao +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/binary_to_base64url.hpp b/include/tao/json/events/binary_to_base64url.hpp index 9d46e014..e46bd6cc 100644 --- a/include/tao/json/events/binary_to_base64url.hpp +++ b/include/tao/json/events/binary_to_base64url.hpp @@ -1,36 +1,28 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_BINARY_TO_BASE64URL_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_BINARY_TO_BASE64URL_HPP +#ifndef TAO_JSON_EVENTS_BINARY_TO_BASE64URL_HPP +#define TAO_JSON_EVENTS_BINARY_TO_BASE64URL_HPP #include -#include "../byte_view.hpp" +#include "../binary_view.hpp" #include "../internal/base64url.hpp" -namespace tao +namespace tao::json::events { - namespace json + template< typename Consumer > + struct binary_to_base64url + : Consumer { - namespace events - { - template< typename Consumer > - struct binary_to_base64url - : public Consumer - { - using Consumer::Consumer; - - void binary( const tao::byte_view v ) - { - Consumer::string( internal::base64url( v ) ); - } - }; + using Consumer::Consumer; - } // namespace events - - } // namespace json + void binary( const tao::binary_view v ) + { + Consumer::string( internal::base64url( v ) ); + } + }; -} // namespace tao +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/binary_to_exception.hpp b/include/tao/json/events/binary_to_exception.hpp index 9101ac08..c14b34a5 100644 --- a/include/tao/json/events/binary_to_exception.hpp +++ b/include/tao/json/events/binary_to_exception.hpp @@ -1,35 +1,27 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_BINARY_TO_EXCEPTION_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_BINARY_TO_EXCEPTION_HPP +#ifndef TAO_JSON_EVENTS_BINARY_TO_EXCEPTION_HPP +#define TAO_JSON_EVENTS_BINARY_TO_EXCEPTION_HPP #include -#include "../byte_view.hpp" +#include "../binary_view.hpp" -namespace tao +namespace tao::json::events { - namespace json + template< typename Consumer > + struct binary_to_exception + : Consumer { - namespace events - { - template< typename Consumer > - struct binary_to_exception - : public Consumer - { - using Consumer::Consumer; - - void binary( const tao::byte_view ) - { - throw std::runtime_error( "invalid binary data" ); - } - }; + using Consumer::Consumer; - } // namespace events - - } // namespace json + void binary( const tao::binary_view /*unused*/ ) + { + throw std::runtime_error( "invalid binary data" ); + } + }; -} // namespace tao +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/binary_to_hex.hpp b/include/tao/json/events/binary_to_hex.hpp index 0c85c4dc..87cb21e3 100644 --- a/include/tao/json/events/binary_to_hex.hpp +++ b/include/tao/json/events/binary_to_hex.hpp @@ -1,34 +1,26 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_BINARY_TO_HEX_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_BINARY_TO_HEX_HPP +#ifndef TAO_JSON_EVENTS_BINARY_TO_HEX_HPP +#define TAO_JSON_EVENTS_BINARY_TO_HEX_HPP -#include "../byte_view.hpp" +#include "../binary_view.hpp" #include "../internal/hexdump.hpp" -namespace tao +namespace tao::json::events { - namespace json + template< typename Consumer > + struct binary_to_hex + : Consumer { - namespace events - { - template< typename Consumer > - struct binary_to_hex - : public Consumer - { - using Consumer::Consumer; - - void binary( const tao::byte_view v ) - { - Consumer::string( internal::hexdump( v ) ); - } - }; + using Consumer::Consumer; - } // namespace events - - } // namespace json + void binary( const tao::binary_view v ) + { + Consumer::string( internal::hexdump( v ) ); + } + }; -} // namespace tao +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/cbor/from_string.hpp b/include/tao/json/events/cbor/from_string.hpp deleted file mode 100644 index 25de7275..00000000 --- a/include/tao/json/events/cbor/from_string.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_CBOR_FROM_STRING_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_CBOR_FROM_STRING_HPP - -#include "../../external/pegtl/parse.hpp" -#include "../../external/string_view.hpp" - -#include "grammar.hpp" - -namespace tao -{ - namespace json - { - namespace events - { - namespace cbor - { - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t byte_in_line = 0 ) - { - json_pegtl::memory_input< json_pegtl::tracking_mode::LAZY, json_pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::cbor::from_string", byte, line, byte_in_line ); - json_pegtl::parse< cbor::grammar >( in, consumer ); - } - - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) - { - cbor::from_string( consumer, data, size, source.c_str(), byte, line, column ); - } - - template< typename Consumer, typename... Ts > - void from_string( Consumer& consumer, const tao::string_view data, Ts&&... ts ) - { - cbor::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); - } - - } // namespace cbor - - } // namespace events - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/events/cbor/grammar.hpp b/include/tao/json/events/cbor/grammar.hpp deleted file mode 100644 index 193af008..00000000 --- a/include/tao/json/events/cbor/grammar.hpp +++ /dev/null @@ -1,444 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_CBOR_GRAMMAR_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_CBOR_GRAMMAR_HPP - -#include -#include -#include - -#include "major.hpp" - -#include "../../external/byte.hpp" -#include "../../external/pegtl.hpp" -#include "../../internal/endian.hpp" - -namespace tao -{ - namespace json - { - namespace events - { - namespace cbor - { - namespace internal - { - template< typename Input > - void throw_on_empty( Input& in ) - { - if( in.empty() ) { - throw json_pegtl::parse_error( "unexpected end of input", in ); - } - } - - template< typename Input > - major peek_major( Input& in ) - { - return static_cast< major >( in.peek_byte() & major_mask ); - } - - template< typename Input > - std::uint8_t peek_minor( Input& in ) - { - return in.peek_byte() & minor_mask; - } - - template< typename Input > - std::uint8_t peek_byte_safe( Input& in ) - { - throw_on_empty( in ); - return in.peek_byte(); - } - - template< typename Input > - major peek_major_safe( Input& in ) - { - return static_cast< major >( peek_byte_safe( in ) & major_mask ); - } - - } // namespace internal - - struct data - { - using analyze_t = json_pegtl::analysis::generic< json_pegtl::analysis::rule_type::ANY >; - - template< json_pegtl::apply_mode A, - json_pegtl::rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename Consumer > - static bool match( Input& in, Consumer& consumer ) - { - // This rule never returns false unless the input is empty. - return ( !in.empty() ) && match_impl( in, consumer ); - } - - template< typename Input, typename Consumer > - static bool match_impl( Input& in, Consumer& consumer ) - { - switch( internal::peek_major( in ) ) { - case major::UNSIGNED: - return match_unsigned( in, consumer ); - case major::NEGATIVE: - return match_negative( in, consumer ); - case major::BINARY: - return match_binary( in, consumer ); - case major::STRING: - return match_string( in, consumer ); - case major::ARRAY: - return match_array( in, consumer ); - case major::OBJECT: - return match_object( in, consumer ); - case major::TAG: - return match_tag( in, consumer ); - case major::OTHER: - return match_other( in, consumer ); - } - // LCOV_EXCL_START - assert( false ); - return false; - // LCOV_EXCL_STOP - } - - template< typename Input > - static void skip_unsigned( Input& in ) - { - // Assumes in.size( 1 ) >= 1 and in.peek_byte() is the byte with major/minor. - - switch( internal::peek_minor( in ) ) { - default: - in.bump_in_this_line(); - return; - case 24: - in.bump_in_this_line( 2 ); - return; - case 25: - in.bump_in_this_line( 3 ); - return; - case 26: - in.bump_in_this_line( 5 ); - return; - case 27: - in.bump_in_this_line( 9 ); - return; - case 28: - case 29: - case 30: - case 31: - throw json_pegtl::parse_error( "unexpected minor for number or length", in ); - } - } - - template< typename Input > - static std::uint64_t read_embedded_impl( Input& in ) - { - const auto result = internal::peek_minor( in ) & minor_mask; - in.bump_in_this_line(); - return result; - } - - template< typename Unsigned, typename Input > - static std::uint64_t read_unsigned_impl( Input& in ) - { - if( in.size( sizeof( Unsigned ) ) > sizeof( Unsigned ) ) { - const Unsigned result = json::internal::be_to_h< Unsigned >( in.current() + 1 ); - in.bump_in_this_line( 1 + sizeof( Unsigned ) ); - return result; - } - throw json_pegtl::parse_error( "unexpected end of input", in ); - } - - template< typename Input > - static std::uint64_t read_unsigned( Input& in ) - { - // Assumes in.size( 1 ) >= 1 and in.peek_byte() is the byte with major/minor. - - switch( internal::peek_minor( in ) ) { - default: - return read_embedded_impl( in ); - case 24: - return read_unsigned_impl< std::uint8_t >( in ); - case 25: - return read_unsigned_impl< std::uint16_t >( in ); - case 26: - return read_unsigned_impl< std::uint32_t >( in ); - case 27: - return read_unsigned_impl< std::uint64_t >( in ); - case 28: - case 29: - case 30: - case 31: - throw json_pegtl::parse_error( "unexpected minor for number or length", in ); - } - } - - template< typename Input, typename Consumer > - static bool match_unsigned( Input& in, Consumer& consumer ) - { - consumer.number( read_unsigned( in ) ); - return true; - } - - template< typename Input, typename Consumer > - static bool match_negative( Input& in, Consumer& consumer ) - { - const auto u = read_unsigned( in ); - if( u > 9223372036854775808ull ) { - throw json_pegtl::parse_error( "negative integer overflow", in ); - } - consumer.number( std::int64_t( ~u ) ); - return true; - } - - // TODO: Check text strings and text string chunks for valid UTF-8 as per RFC 7049? - - template< typename Result, typename Input > - static Result read_string_1( Input& in ) - { - using value_t = typename Result::value_type; - const auto size = read_unsigned( in ); - if( in.size( size ) < size ) { - throw json_pegtl::parse_error( "unexpected end of input", in ); - } - const value_t* pointer = reinterpret_cast< const value_t* >( in.current() ); - Result result( pointer, size ); - in.bump_in_this_line( size ); - return result; - } - - template< typename Result, typename Input > - static Result read_string_n( Input& in, const major m ) - { - using value_t = typename Result::value_type; - - Result result; - in.bump_in_this_line(); - while( internal::peek_byte_safe( in ) != 0xff ) { - if( internal::peek_major( in ) != m ) { - throw json_pegtl::parse_error( "non-matching fragment in indefinite length string", in ); // "String" is text or byte string in RFC 7049 terminology. - } - const auto size = read_unsigned( in ); - if( in.size( size ) < size ) { - throw json_pegtl::parse_error( "unexpected end of input", in ); - } - const value_t* pointer = reinterpret_cast< const value_t* >( in.current() ); - result.insert( result.end(), pointer, pointer + size ); - in.bump_in_this_line( size ); - } - in.bump_in_this_line(); - return result; - } - - template< typename Input, typename Consumer > - static bool match_string( Input& in, Consumer& consumer ) - { - // Assumes in.size( 1 ) >= 1 and in.peek_byte() is the byte with major/minor. - - if( internal::peek_minor( in ) != minor_mask ) { - consumer.string( read_string_1< tao::string_view >( in ) ); - } - else { - consumer.string( read_string_n< std::string >( in, major::STRING ) ); - } - return true; - } - - template< typename Input, typename Consumer > - static bool match_binary( Input& in, Consumer& consumer ) - { - // Assumes in.size( 1 ) >= 1 and in.peek_byte() is the byte with major/minor. - - if ( internal::peek_minor( in ) != minor_mask ) { - consumer.binary( read_string_1< tao::byte_view >( in ) ); - } - else { - consumer.binary( read_string_n< std::vector< tao::byte > >( in, major::BINARY ) ); - } - return true; - } - - template< typename Input, typename Consumer > - static void match_array_1( Input& in, Consumer& consumer ) - { - const auto size = read_unsigned( in ); - consumer.begin_array( size ); - for( std::uint64_t i = 0; i < size; ++i ) { - internal::throw_on_empty( in ); - match_impl( in, consumer ); - consumer.element(); - } - consumer.end_array( size ); - } - - template< typename Input, typename Consumer > - static void match_array_n( Input& in, Consumer& consumer ) - { - in.bump_in_this_line(); - consumer.begin_array(); - while( internal::peek_byte_safe( in ) != 0xff ) { - match_impl( in, consumer ); - consumer.element(); - } - in.bump_in_this_line(); - consumer.end_array(); - } - - template< typename Input, typename Consumer > - static bool match_array( Input& in, Consumer& consumer ) - { - if( internal::peek_minor( in ) != minor_mask ) { - match_array_1( in, consumer ); - } - else { - match_array_n( in, consumer ); - } - return true; - } - - template< typename Input, typename Consumer > - static void match_object_1( Input& in, Consumer& consumer ) - { - const auto size = read_unsigned( in ); - consumer.begin_object( size ); - for( std::uint64_t i = 0; i < size; ++i ) { - if( internal::peek_major_safe( in ) != major::STRING ) { - throw json_pegtl::parse_error( "non-string object key", in ); - } - internal::throw_on_empty( in ); - if ( internal::peek_minor( in ) != minor_mask ) { - consumer.key( read_string_1< tao::string_view >( in ) ); - } - else { - consumer.key( read_string_n< std::string >( in, major::STRING ) ); - } - internal::throw_on_empty( in ); - match_impl( in, consumer ); - consumer.member(); - } - consumer.end_object( size ); - } - - template< typename Input, typename Consumer > - static void match_object_n( Input& in, Consumer& consumer ) - { - in.bump_in_this_line(); - consumer.begin_object(); - while( internal::peek_byte_safe( in ) != 0xff ) { - if( internal::peek_major( in ) != major::STRING ) { - throw json_pegtl::parse_error( "non-string object key", in ); - } - if ( internal::peek_minor( in ) != minor_mask ) { - consumer.key( read_string_1< tao::string_view >( in ) ); - } - else { - consumer.key( read_string_n< std::string >( in, major::STRING ) ); - } - internal::throw_on_empty( in ); - match_impl( in, consumer ); - consumer.member(); - } - in.bump_in_this_line(); - consumer.end_object(); - } - - template< typename Input, typename Consumer > - static bool match_object( Input& in, Consumer& consumer ) - { - if( internal::peek_minor( in ) != minor_mask ) { - match_object_1( in, consumer ); - } - else { - match_object_n( in, consumer ); - } - return true; - } - - template< typename Input, typename Consumer > - static bool match_tag( Input& in, Consumer& ) - { - skip_unsigned( in ); - return true; - } - - template< typename Floating, typename Input > - static double read_floating_impl( Input& in ) - { - if( in.size( sizeof( Floating ) ) >= 1 + sizeof( Floating ) ) { - const Floating result = json::internal::be_to_h< Floating >( in.current() + 1 ); - in.bump_in_this_line( 1 + sizeof( Floating ) ); - return result; - } - throw json_pegtl::parse_error( "unexpected end of input", in ); - } - - template< typename Input > - static double read_floating_half_impl( Input& in ) - { - if( in.size( 3 ) < 3 ) { - throw json_pegtl::parse_error( "unexpected end of input", in ); - } - const int half = ( in.peek_byte( 1 ) << 8 ) + in.peek_byte( 2 ); - const int exp = ( half >> 10 ) & 0x1f; - const int mant = half & 0x3ff; - - double val; - if( exp == 0 ) { - val = std::ldexp( mant, -24 ); - } - else if( exp != 31 ) { - val = std::ldexp( mant + 1024, exp - 25 ); - } - else { - val = ( mant == 0 ) ? INFINITY : NAN; - } - in.bump_in_this_line( 3 ); - return half & 0x8000 ? -val : val; - } - - template< typename Input, typename Consumer > - static bool match_other( Input& in, Consumer& consumer ) - { - switch( internal::peek_minor( in ) ) { - case 20: - consumer.boolean( false ); - in.bump_in_this_line(); - return true; - case 21: - consumer.boolean( true ); - in.bump_in_this_line(); - return true; - case 22: - consumer.null(); - in.bump_in_this_line(); - return true; - case 25: - consumer.number( read_floating_half_impl( in ) ); - return true; - case 26: - consumer.number( read_floating_impl< float >( in ) ); - return true; - case 27: - consumer.number( read_floating_impl< double >( in ) ); - return true; - case 24: - default: - throw json_pegtl::parse_error( "unsupported minor for major 7", in ); - } - } - }; - - struct grammar : json_pegtl::must< data, json_pegtl::eof > - { - }; - - } // namespace cbor - - } // namespace events - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/events/cbor/major.hpp b/include/tao/json/events/cbor/major.hpp deleted file mode 100644 index afe5f511..00000000 --- a/include/tao/json/events/cbor/major.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_CBOR_MAJOR_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_CBOR_MAJOR_HPP - -#include - -namespace tao -{ - namespace json - { - namespace events - { - namespace cbor - { - enum class major : std::uint8_t - { - UNSIGNED = 0, - NEGATIVE = 0x20, - BINARY = 0x40, - STRING = 0x60, - ARRAY = 0x80, - OBJECT = 0xa0, - TAG = 0xc0, - OTHER = 0xe0 - }; - - static constexpr std::uint8_t major_mask = 0xe0; - static constexpr std::uint8_t minor_mask = 0x1f; - - } // namespace cbor - - } // namespace events - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/events/cbor/to_stream.hpp b/include/tao/json/events/cbor/to_stream.hpp deleted file mode 100644 index b67b0d10..00000000 --- a/include/tao/json/events/cbor/to_stream.hpp +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_CBOR_TO_STREAM_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_CBOR_TO_STREAM_HPP - -#include -#include -#include - -#include "major.hpp" - -#include "../../internal/endian.hpp" - -namespace tao -{ - namespace json - { - namespace events - { - namespace cbor - { - class to_stream - { - private: - std::ostream& os; - - public: - explicit to_stream( std::ostream& in_os ) noexcept - : os( in_os ) - { - } - - void null() - { - os.put( char( std::uint8_t( major::OTHER ) + 22 ) ); - } - - void boolean( const bool v ) - { - os.put( char( std::uint8_t( major::OTHER ) + 20 + std::uint8_t( v ) ) ); - } - - void number( const major m, const std::uint64_t v ) - { - if( v < 24 ) { - os.put( char( std::uint8_t( m ) + v ) ); - } - else if( v < 256 ) { - os.put( char( std::uint8_t( m ) + 24 ) ); - os.put( char( v ) ); - } - else if( v < 65536 ) { - os.put( char( std::uint8_t( m ) + 25 ) ); - const std::uint16_t x = json::internal::h_to_be( std::uint16_t( v ) ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else if( v < 4294967296ull ) { - os.put( char( std::uint8_t( m ) + 26 ) ); - const std::uint32_t x = json::internal::h_to_be( std::uint32_t( v ) ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else { - os.put( char( std::uint8_t( m ) + 27 ) ); - const std::uint64_t x = json::internal::h_to_be( v ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - } - - void number( const std::int64_t v ) - { - if( v >= 0 ) { - number( major::UNSIGNED, v ); - } - else { - number( major::NEGATIVE, -( v + 1 ) ); - } - } - - void number( const std::uint64_t v ) - { - number( major::UNSIGNED, v ); - } - - void number( const double v ) - { - std::uint64_t n; - std::memcpy( &n, &v, sizeof( n ) ); - n = json::internal::h_to_be( n ); - os.put( char( std::uint8_t( major::OTHER ) + 27 ) ); - os.write( reinterpret_cast< const char* >( &n ), sizeof( n ) ); - } - - void string( const tao::string_view v ) - { - number( major::STRING, v.size() ); - os.write( v.data(), v.size() ); - } - - void binary( const tao::byte_view v ) - { - number( major::BINARY, v.size() ); - os.write( reinterpret_cast< const char* >( v.data() ), v.size() ); - } - - void begin_array() - { - os.put( char( std::uint8_t( major::ARRAY ) + minor_mask ) ); - } - - void begin_array( const std::size_t size ) - { - number( major::ARRAY, size ); - } - - void element() noexcept - { - } - - void end_array() - { - os.put( char( 0xff ) ); - } - - void end_array( const std::size_t ) noexcept - { - } - - void begin_object() - { - os.put( char( std::uint8_t( major::OBJECT ) + minor_mask ) ); - } - - void begin_object( const std::size_t size ) - { - number( major::OBJECT, size ); - } - - void key( const tao::string_view v ) - { - string( v ); - } - - void member() noexcept - { - } - - void end_object() - { - os.put( char( 0xff ) ); - } - - void end_object( const std::size_t ) noexcept - { - } - }; - - } // namespace cbor - - } // namespace events - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/events/cbor/to_string.hpp b/include/tao/json/events/cbor/to_string.hpp deleted file mode 100644 index 0bea1cf2..00000000 --- a/include/tao/json/events/cbor/to_string.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JSON_CBOR_TO_STRING_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_JSON_CBOR_TO_STRING_HPP - -#include - -#include "to_stream.hpp" - -namespace tao -{ - namespace json - { - namespace events - { - namespace cbor - { - struct to_string - : public to_stream - { - std::ostringstream oss; - - to_string() - : to_stream( oss ) - { - } - - std::string value() const - { - return oss.str(); - } - }; - - } // namespace cbor - - } // namespace events - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/events/compare.hpp b/include/tao/json/events/compare.hpp index 7ea73d15..80c907d3 100644 --- a/include/tao/json/events/compare.hpp +++ b/include/tao/json/events/compare.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_COMPARE_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_COMPARE_HPP +#ifndef TAO_JSON_EVENTS_COMPARE_HPP +#define TAO_JSON_EVENTS_COMPARE_HPP #include #include @@ -12,248 +12,254 @@ #include "../value.hpp" -namespace tao +namespace tao::json { - namespace json + namespace internal { - namespace internal + template< template< typename... > class Traits > + class events_compare { - template< template< typename... > class Traits > - class events_compare + protected: + std::vector< const basic_value< Traits >* > m_current; + std::vector< std::size_t > m_array_index; + // TODO: use std::unordered_set? or even std::vector!? + std::vector< std::set< const basic_value< Traits >* > > m_object_keys; + bool m_match = true; + + public: + events_compare() = default; + + events_compare( const events_compare& ) = delete; + events_compare( events_compare&& ) = delete; + + ~events_compare() = default; + + void operator=( const events_compare& ) = delete; + void operator=( events_compare&& ) = delete; + + void reset() noexcept { - protected: - std::vector< const basic_value< Traits >* > m_current; - std::vector< std::size_t > m_array_index; - // TODO: use std::unordered_set? or even std::vector!? - std::vector< std::set< const basic_value< Traits >* > > m_object_keys; - bool m_match = true; - - public: - events_compare() = default; - - events_compare( const events_compare& ) = delete; - events_compare( events_compare&& ) = delete; - - void operator=( const events_compare& ) = delete; - void operator=( events_compare&& ) = delete; - - void reset() noexcept - { - m_current.clear(); - m_array_index.clear(); - m_object_keys.clear(); - m_match = true; - } + m_current.clear(); + m_array_index.clear(); + m_object_keys.clear(); + m_match = true; + } - static const basic_value< Traits >* skip_pointer( const basic_value< Traits >* p ) noexcept - { - while( p && p->is_raw_ptr() ) { - p = p->unsafe_get_raw_ptr(); - } - return p; + [[nodiscard]] static const basic_value< Traits >* skip_pointer( const basic_value< Traits >* p ) noexcept + { + while( p && p->is_value_ptr() ) { + p = p->get_value_ptr(); } + return p; + } - void push( const basic_value< Traits >* p ) - { - m_current.push_back( skip_pointer( p ) ); - } + void push( const basic_value< Traits >* p ) + { + m_current.push_back( skip_pointer( p ) ); + } - bool match() const noexcept - { - return m_match; - } + [[nodiscard]] bool match() const noexcept + { + return m_match; + } - const basic_value< Traits >& current() const noexcept - { - return *m_current.back(); - } + [[nodiscard]] const basic_value< Traits >& current() const noexcept + { + return *m_current.back(); + } - void null() noexcept - { - m_match = m_match && ( m_current.back() != nullptr ) && ( current().is_null() ); - } + void null() noexcept + { + m_match = m_match && ( m_current.back() != nullptr ) && ( current().is_null() ); + } - void boolean( const bool v ) noexcept - { - m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); - } + void boolean( const bool v ) noexcept + { + m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); + } - void number( const std::int64_t v ) noexcept - { - m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); - } + void number( const std::int64_t v ) noexcept + { + m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); + } - void number( const std::uint64_t v ) noexcept - { - m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); - } + void number( const std::uint64_t v ) noexcept + { + m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); + } - void number( const double v ) noexcept - { - m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); - } + void number( const double v ) noexcept + { + m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); + } - void string( const tao::string_view v ) noexcept - { - m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); - } + void string( const std::string_view v ) noexcept + { + m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); + } - void binary( const tao::byte_view v ) noexcept - { - m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); - } + void binary( const tao::binary_view v ) noexcept + { + m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); + } - void begin_array( const std::size_t = 0 ) - { - if( m_current.back() == nullptr ) { + void begin_array( const std::size_t /*unused*/ = 0 ) + { + if( m_current.back() == nullptr ) { + m_match = false; + m_current.push_back( nullptr ); + } + else { + const auto& a = current(); + if( !a.is_array() ) { m_match = false; m_current.push_back( nullptr ); } else { - const auto& a = current(); - if( !a.is_array() ) { - m_match = false; - m_current.push_back( nullptr ); - } - else if( !a.unsafe_get_array().empty() ) { - push( &a.unsafe_get_array().front() ); + const auto& v = a.get_array(); + if( !v.empty() ) { + push( &v.front() ); } else { m_current.push_back( nullptr ); } } - m_array_index.push_back( 0 ); } + m_array_index.push_back( 0 ); + } - void element() noexcept - { - const auto i = ++m_array_index.back(); - if( m_match ) { - if( m_current.back() != nullptr ) { - const auto& a = ( *( m_current.end() - 2 ) )->unsafe_get_array(); - if( i < a.size() ) { - m_current.back() = skip_pointer( &a[ i ] ); - } - else { - m_current.back() = nullptr; - } + void element() noexcept + { + const auto i = ++m_array_index.back(); + if( m_match ) { + if( m_current.back() != nullptr ) { + const auto& a = ( *( m_current.end() - 2 ) )->get_array(); + if( i < a.size() ) { + m_current.back() = skip_pointer( &a[ i ] ); + } + else { + m_current.back() = nullptr; } } } + } - void end_array( const std::size_t = 0 ) noexcept - { - m_current.pop_back(); - if( m_match ) { - if( m_array_index.back() != current().unsafe_get_array().size() ) { - m_match = false; - } + void end_array( const std::size_t /*unused*/ = 0 ) noexcept + { + m_current.pop_back(); + if( m_match ) { + if( m_array_index.back() != current().get_array().size() ) { + m_match = false; } - m_array_index.pop_back(); } + m_array_index.pop_back(); + } - void begin_object( const std::size_t = 0 ) - { - if( m_current.back() == nullptr ) { + void begin_object( const std::size_t /*unused*/ = 0 ) + { + if( m_current.back() == nullptr ) { + m_match = false; + } + else { + const auto& o = current(); + if( !o.is_object() ) { m_match = false; } - else { - const auto& o = current(); - if( !o.is_object() ) { - m_match = false; - } - } - m_object_keys.emplace_back(); } + m_object_keys.emplace_back(); + } - void key( const std::string& v ) - { - if( !m_match ) { + void key( const std::string& v ) + { + if( !m_match ) { + m_current.push_back( nullptr ); + } + else if( const auto* p = current().find( v ) ) { + if( !m_object_keys.back().insert( p ).second ) { + m_match = false; // duplicate key found! -> fail m_current.push_back( nullptr ); } - else if( const auto* p = current().unsafe_find( v ) ) { - if( !m_object_keys.back().insert( p ).second ) { - m_match = false; // duplicate key found! -> fail - m_current.push_back( nullptr ); - } - else { - push( p ); - } - } else { - m_match = false; - m_current.push_back( nullptr ); + push( p ); } } - - void key( const tao::string_view v ) - { - key( std::string( v.data(), v.size() ) ); + else { + m_match = false; + m_current.push_back( nullptr ); } + } - void key( const char* v ) - { - key( std::string( v ) ); - } + void key( const std::string_view v ) + { + key( std::string( v ) ); + } - void member() noexcept - { - m_current.pop_back(); - } + void key( const char* v ) + { + key( std::string( v ) ); + } - void end_object( const std::size_t = 0 ) noexcept - { - if( m_match ) { - if( m_object_keys.back().size() != current().unsafe_get_object().size() ) { - m_match = false; - } + void member() noexcept + { + m_current.pop_back(); + } + + void end_object( const std::size_t /*unused*/ = 0 ) noexcept + { + if( m_match ) { + if( m_object_keys.back().size() != current().get_object().size() ) { + m_match = false; } - m_object_keys.pop_back(); } - }; + m_object_keys.pop_back(); + } + }; - } // namespace internal + } // namespace internal - namespace events + namespace events + { + // Events consumer that compares against a JSON Value. + + template< template< typename... > class Traits > + class basic_compare + : public internal::events_compare< Traits > { - // Events consumer that compares against a JSON Value. + private: + const basic_value< Traits > m_value; - template< template< typename... > class Traits > - class basic_compare - : public internal::events_compare< Traits > + public: + explicit basic_compare( const basic_value< Traits >& v ) + : m_value( v ) { - private: - const basic_value< Traits > m_value; - - public: - explicit basic_compare( const basic_value< Traits >& v ) - : m_value( v ) - { - reset(); - } + reset(); + } - explicit basic_compare( basic_value< Traits >&& v ) - : m_value( std::move( v ) ) - { - reset(); - } + explicit basic_compare( basic_value< Traits >&& v ) + : m_value( std::move( v ) ) + { + reset(); + } - basic_compare( const basic_compare& ) = delete; - void operator=( const basic_compare& ) = delete; + basic_compare( const basic_compare& ) = delete; + basic_compare( basic_compare&& ) = delete; - void reset() - { - internal::events_compare< Traits >::reset(); - internal::events_compare< Traits >::push( &m_value ); - } - }; + ~basic_compare() = default; - using compare = basic_compare< traits >; + void operator=( const basic_compare& ) = delete; + void operator=( basic_compare&& ) = delete; + + void reset() + { + internal::events_compare< Traits >::reset(); + internal::events_compare< Traits >::push( &m_value ); + } + }; - } // namespace events + using compare = basic_compare< traits >; - } // namespace json + } // namespace events -} // namespace tao +} // namespace tao::json #endif diff --git a/include/tao/json/events/debug.hpp b/include/tao/json/events/debug.hpp index cd7c8e6d..44eead54 100644 --- a/include/tao/json/events/debug.hpp +++ b/include/tao/json/events/debug.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_DEBUG_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_DEBUG_HPP +#ifndef TAO_JSON_EVENTS_DEBUG_HPP +#define TAO_JSON_EVENTS_DEBUG_HPP #include #include @@ -10,144 +10,136 @@ #include #include -#include "../byte_view.hpp" -#include "../external/double.hpp" +#include "../binary_view.hpp" + +#include "../external/ryu.hpp" #include "../internal/escape.hpp" #include "../internal/hexdump.hpp" -namespace tao +namespace tao::json::events { - namespace json + // Events consumer that writes the events to a stream for debug purposes. + + class debug { - namespace events - { - // Events consumer that writes the events to a stream for debug purposes. - - class debug - { - private: - std::ostream& os; - - public: - explicit debug( std::ostream& in_os ) noexcept - : os( in_os ) - { - } - - void null() - { - os << "null\n"; - } - - void boolean( const bool v ) - { - if( v ) { - os << "boolean: true\n"; - } - else { - os << "boolean: false\n"; - } - } - - void number( const std::int64_t v ) - { - os << "std::int64_t: " << v << '\n'; - } - - void number( const std::uint64_t v ) - { - os << "std::uint64_t: " << v << '\n'; - } - - void number( const double v ) - { - os << "double: "; - if( !std::isfinite( v ) ) { - os << v; - } - else { - json_double_conversion::Dtostr( os, v ); - } - os << '\n'; - } - - void string( const tao::string_view v ) - { - os << "string: \""; - internal::escape( os, v ); - os << "\"\n"; - } - - void binary( const tao::byte_view v ) - { - os << "binary: "; - internal::hexdump( os, v ); - os << '\n'; - } - - void begin_array() - { - os << "begin array\n"; - } - - void begin_array( const std::size_t size ) - { - os << "begin array " << size << '\n'; - } - - void element() - { - os << "element\n"; - } - - void end_array() - { - os << "end array\n"; - } - - void end_array( const std::size_t size ) - { - os << "end array " << size << '\n'; - } - - void begin_object() - { - os << "begin object\n"; - } - - void begin_object( const std::size_t size ) - { - os << "begin object " << size << '\n'; - } - - void key( const tao::string_view v ) - { - os << "key: \""; - internal::escape( os, v ); - os << "\"\n"; - } - - void member() - { - os << "member\n"; - } - - void end_object() - { - os << "end object\n"; - } - - void end_object( const std::size_t size ) - { - os << "end object " << size << '\n'; - } - }; - - } // namespace events - - } // namespace json - -} // namespace tao + private: + std::ostream& os; + + public: + explicit debug( std::ostream& in_os ) noexcept + : os( in_os ) + {} + + void null() + { + os << "null\n"; + } + + void boolean( const bool v ) + { + if( v ) { + os << "boolean: true\n"; + } + else { + os << "boolean: false\n"; + } + } + + void number( const std::int64_t v ) + { + os << "std::int64_t: " << v << '\n'; + } + + void number( const std::uint64_t v ) + { + os << "std::uint64_t: " << v << '\n'; + } + + void number( const double v ) + { + os << "double: "; + if( !std::isfinite( v ) ) { + os << v; + } + else { + ryu::d2s_stream( os, v ); + } + os << '\n'; + } + + void string( const std::string_view v ) + { + os << "string: \""; + internal::escape( os, v ); + os << "\"\n"; + } + + void binary( const tao::binary_view v ) + { + os << "binary: "; + internal::hexdump( os, v ); + os << '\n'; + } + + void begin_array() + { + os << "begin array\n"; + } + + void begin_array( const std::size_t size ) + { + os << "begin array " << size << '\n'; + } + + void element() + { + os << "element\n"; + } + + void end_array() + { + os << "end array\n"; + } + + void end_array( const std::size_t size ) + { + os << "end array " << size << '\n'; + } + + void begin_object() + { + os << "begin object\n"; + } + + void begin_object( const std::size_t size ) + { + os << "begin object " << size << '\n'; + } + + void key( const std::string_view v ) + { + os << "key: \""; + internal::escape( os, v ); + os << "\"\n"; + } + + void member() + { + os << "member\n"; + } + + void end_object() + { + os << "end object\n"; + } + + void end_object( const std::size_t size ) + { + os << "end object " << size << '\n'; + } + }; + +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/discard.hpp b/include/tao/json/events/discard.hpp index a12026b2..ffe6a39b 100644 --- a/include/tao/json/events/discard.hpp +++ b/include/tao/json/events/discard.hpp @@ -1,88 +1,43 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_DISCARD_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_DISCARD_HPP +#ifndef TAO_JSON_EVENTS_DISCARD_HPP +#define TAO_JSON_EVENTS_DISCARD_HPP #include #include -#include +#include -#include "../byte_view.hpp" +#include "../binary_view.hpp" -#include "../external/string_view.hpp" - -namespace tao +namespace tao::json::events { - namespace json - { - namespace events - { - // Events consumer that discards events. - - struct discard - { - void null() noexcept - { - } - - void boolean( const bool ) noexcept - { - } - - void number( const std::int64_t ) noexcept - { - } - - void number( const std::uint64_t ) noexcept - { - } + // Events consumer that discards events. - void number( const double ) noexcept - { - } - - void string( const tao::string_view ) noexcept - { - } - - void binary( const tao::byte_view ) noexcept - { - } - - void begin_array( const std::size_t = 0 ) noexcept - { - } - - void element() noexcept - { - } - - void end_array( const std::size_t = 0 ) noexcept - { - } + struct discard + { + void null() noexcept {} - void begin_object( const std::size_t = 0 ) noexcept - { - } + void boolean( const bool /*unused*/ ) noexcept {} - void key( const tao::string_view ) noexcept - { - } + void number( const std::int64_t /*unused*/ ) noexcept {} + void number( const std::uint64_t /*unused*/ ) noexcept {} + void number( const double /*unused*/ ) noexcept {} - void member() noexcept - { - } + void string( const std::string_view /*unused*/ ) noexcept {} - void end_object( const std::size_t = 0 ) noexcept - { - } - }; + void binary( const tao::binary_view /*unused*/ ) noexcept {} - } // namespace events + void begin_array( const std::size_t /*unused*/ = 0 ) noexcept {} + void element() noexcept {} + void end_array( const std::size_t /*unused*/ = 0 ) noexcept {} - } // namespace json + void begin_object( const std::size_t /*unused*/ = 0 ) noexcept {} + void key( const std::string_view /*unused*/ ) noexcept {} + void member() noexcept {} + void end_object( const std::size_t /*unused*/ = 0 ) noexcept {} + }; -} // namespace tao +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/from_file.hpp b/include/tao/json/events/from_file.hpp new file mode 100644 index 00000000..c94024fd --- /dev/null +++ b/include/tao/json/events/from_file.hpp @@ -0,0 +1,28 @@ +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_EVENTS_FROM_FILE_HPP +#define TAO_JSON_EVENTS_FROM_FILE_HPP + +#include + +#include "../internal/action.hpp" +#include "../internal/errors.hpp" +#include "../internal/grammar.hpp" + +#include "../external/pegtl/file_input.hpp" + +namespace tao::json::events +{ + // Events producer to parse a file containing a JSON string representation. + + template< typename T, typename Consumer > + void from_file( Consumer& consumer, T&& filename ) + { + pegtl::file_input< pegtl::tracking_mode::lazy > in( std::forward< T >( filename ) ); + pegtl::parse< internal::grammar, internal::action, internal::errors >( in, consumer ); + } + +} // namespace tao::json::events + +#endif diff --git a/include/tao/json/events/from_input.hpp b/include/tao/json/events/from_input.hpp new file mode 100644 index 00000000..0845db92 --- /dev/null +++ b/include/tao/json/events/from_input.hpp @@ -0,0 +1,45 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_EVENTS_FROM_INPUT_HPP +#define TAO_JSON_EVENTS_FROM_INPUT_HPP + +#include + +#include "../external/pegtl/parse.hpp" + +#include "../internal/action.hpp" +#include "../internal/errors.hpp" +#include "../internal/grammar.hpp" + +namespace tao::json::events +{ + // Events producers that parse a JSON string representation from a PEGTL input (or something compatible). + + template< typename Consumer, typename Input > + void from_input( Consumer& consumer, Input&& in ) + { + pegtl::parse< internal::grammar, internal::action, internal::errors >( std::forward< Input >( in ), consumer ); + } + + template< typename Consumer, typename Input > + void from_input_embedded( Consumer& consumer, Input&& in ) + { + pegtl::parse< internal::embedded, internal::action, internal::errors >( std::forward< Input >( in ), consumer ); + } + + template< typename Consumer, typename Outer, typename Input > + void from_input_nested( Consumer& consumer, const Outer& oi, Input&& in ) + { + pegtl::parse_nested< internal::grammar, internal::action, internal::errors >( oi, std::forward< Input >( in ), consumer ); + } + + template< typename Consumer, typename Outer, typename Input > + void from_input_embedded_nested( Consumer& consumer, const Outer& oi, Input&& in ) + { + pegtl::parse_nested< internal::embedded, internal::action, internal::errors >( oi, std::forward< Input >( in ), consumer ); + } + +} // namespace tao::json::events + +#endif diff --git a/include/tao/json/events/from_stream.hpp b/include/tao/json/events/from_stream.hpp index 273a3152..5c6a03ef 100644 --- a/include/tao/json/events/from_stream.hpp +++ b/include/tao/json/events/from_stream.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_FROM_STREAM_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_FROM_STREAM_HPP +#ifndef TAO_JSON_EVENTS_FROM_STREAM_HPP +#define TAO_JSON_EVENTS_FROM_STREAM_HPP #include @@ -10,32 +10,24 @@ #include "../external/pegtl/parse.hpp" #include "../internal/action.hpp" -#include "../internal/control.hpp" +#include "../internal/errors.hpp" #include "../internal/grammar.hpp" -namespace tao +namespace tao::json::events { - namespace json + template< typename Consumer > + void from_stream( Consumer& consumer, std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) { - namespace events - { - template< typename Consumer > - void from_stream( Consumer& consumer, std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) - { - json_pegtl::istream_input<> in( stream, maximum_buffer_size, source ? source : "tao::json::events::from_stream" ); - json_pegtl::parse< internal::grammar, internal::action, internal::control >( in, consumer ); - } - - template< typename Consumer > - void from_stream( Consumer& consumer, std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) - { - events::from_stream( consumer, stream, source.c_str(), maximum_buffer_size ); - } - - } // namespace events - - } // namespace json - -} // namespace tao + pegtl::istream_input in( stream, maximum_buffer_size, source ? source : "tao::json::events::from_stream" ); + pegtl::parse< internal::grammar, internal::action, internal::errors >( in, consumer ); + } + + template< typename Consumer > + void from_stream( Consumer& consumer, std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) + { + events::from_stream( consumer, stream, source.c_str(), maximum_buffer_size ); + } + +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/from_string.hpp b/include/tao/json/events/from_string.hpp index 70517ac7..5710d795 100644 --- a/include/tao/json/events/from_string.hpp +++ b/include/tao/json/events/from_string.hpp @@ -1,47 +1,38 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_FROM_STRING_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_FROM_STRING_HPP +#ifndef TAO_JSON_EVENTS_FROM_STRING_HPP +#define TAO_JSON_EVENTS_FROM_STRING_HPP -#include "../external/pegtl/parse.hpp" -#include "../external/string_view.hpp" +#include -#include "../internal/action.hpp" -#include "../internal/control.hpp" -#include "../internal/grammar.hpp" +#include "../external/pegtl/memory_input.hpp" -namespace tao +#include "from_input.hpp" + +namespace tao::json::events { - namespace json + // Events producer to parse a JSON string representation. + + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) + { + pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::events::from_string", byte, line, column ); + json::events::from_input( consumer, std::move( in ) ); + } + + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) { - namespace events - { - // Events producer to parse a JSON string representation. - - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) - { - json_pegtl::memory_input< json_pegtl::tracking_mode::LAZY, json_pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::events::from_string", byte, line, column ); - json_pegtl::parse< internal::grammar, internal::action, internal::control >( in, consumer ); - } - - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) - { - events::from_string( consumer, data, size, source.c_str(), byte, line, column ); - } - - template< typename Consumer, typename... Ts > - void from_string( Consumer& consumer, const tao::string_view data, Ts&&... ts ) - { - events::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); - } - - } // namespace events - - } // namespace json - -} // namespace tao + events::from_string( consumer, data, size, source.c_str(), byte, line, column ); + } + + template< typename Consumer, typename... Ts > + void from_string( Consumer& consumer, const std::string_view data, Ts&&... ts ) + { + events::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); + } + +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/from_value.hpp b/include/tao/json/events/from_value.hpp index 77cb9860..aa4124f9 100644 --- a/include/tao/json/events/from_value.hpp +++ b/include/tao/json/events/from_value.hpp @@ -1,194 +1,202 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_FROM_VALUE_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_FROM_VALUE_HPP +#ifndef TAO_JSON_EVENTS_FROM_VALUE_HPP +#define TAO_JSON_EVENTS_FROM_VALUE_HPP #include -#include "../value.hpp" +#include "../basic_value.hpp" +#include "../internal/format.hpp" -namespace tao +#include "virtual_ref.hpp" + +namespace tao::json::events { - namespace json + // Events producer to generate events from a JSON Value. + + template< auto Recurse, typename Consumer, template< typename... > class Traits > + void from_value( Consumer& consumer, const basic_value< Traits >& v ) { - namespace events - { - // Events producer to generate events from a JSON Value. - - template< typename Consumer, template< typename... > class Traits > - void from_value( Consumer& consumer, const basic_value< Traits >& v ) - { - switch( v.type() ) { - case type::UNINITIALIZED: - throw std::logic_error( "unable to produce events from uninitialized values" ); - - case type::DISCARDED: - throw std::logic_error( "unable to produce events from discarded values" ); - - case type::DESTROYED: - throw std::logic_error( "unable to produce events from destroyed values" ); - - case type::NULL_: - consumer.null(); - return; - - case type::BOOLEAN: - consumer.boolean( v.unsafe_get_boolean() ); - return; - - case type::SIGNED: - consumer.number( v.unsafe_get_signed() ); - return; - - case type::UNSIGNED: - consumer.number( v.unsafe_get_unsigned() ); - return; - - case type::DOUBLE: - consumer.number( v.unsafe_get_double() ); - return; - - case type::STRING: - consumer.string( v.unsafe_get_string() ); - return; - - case type::STRING_VIEW: - consumer.string( v.unsafe_get_string_view() ); - return; - - case type::BINARY: - consumer.binary( v.unsafe_get_binary() ); - return; - - case type::BINARY_VIEW: - consumer.binary( v.unsafe_get_binary_view() ); - return; - - case type::ARRAY: { - const auto& a = v.unsafe_get_array(); - const auto s = a.size(); - consumer.begin_array( s ); - for( const auto& e : a ) { - events::from_value( consumer, e ); - consumer.element(); - } - consumer.end_array( s ); - return; - } - - case type::OBJECT: { - const auto& o = v.unsafe_get_object(); - const auto s = o.size(); - consumer.begin_object( s ); - for( const auto& e : o ) { - consumer.key( e.first ); - events::from_value( consumer, e.second ); - consumer.member(); - } - consumer.end_object( s ); - return; - } - - case type::RAW_PTR: - if( const basic_value< Traits >* p = v.unsafe_get_raw_ptr() ) { - events::from_value( consumer, *p ); - } - else { - consumer.null(); - } - return; + switch( v.type() ) { + case type::UNINITIALIZED: + throw std::logic_error( "unable to produce events from uninitialized values" ); + + case type::NULL_: + consumer.null(); + return; + + case type::BOOLEAN: + consumer.boolean( v.get_boolean() ); + return; + + case type::SIGNED: + consumer.number( v.get_signed() ); + return; + + case type::UNSIGNED: + consumer.number( v.get_unsigned() ); + return; + + case type::DOUBLE: + consumer.number( v.get_double() ); + return; + + case type::STRING: + consumer.string( v.get_string() ); + return; + + case type::STRING_VIEW: + consumer.string( v.get_string_view() ); + return; + + case type::BINARY: + consumer.binary( v.get_binary() ); + return; + + case type::BINARY_VIEW: + consumer.binary( v.get_binary_view() ); + return; + + case type::ARRAY: { + const auto& a = v.get_array(); + const auto s = a.size(); + consumer.begin_array( s ); + for( const auto& e : a ) { + Recurse( consumer, e ); + consumer.element(); } - throw std::logic_error( "invalid value for tao::json::type" ); // LCOV_EXCL_LINE + consumer.end_array( s ); + return; } - // Events producer to generate events from an rvalue JSON value. - // Note: Strings from the source might be moved to the consumer. - - template< typename Consumer, template< typename... > class Traits > - void from_value( Consumer& consumer, basic_value< Traits >&& v ) - { - switch( v.type() ) { - case type::UNINITIALIZED: - throw std::logic_error( "unable to produce events from uninitialized values" ); - - case type::DISCARDED: - throw std::logic_error( "unable to produce events from discarded values" ); - - case type::DESTROYED: - throw std::logic_error( "unable to produce events from destroyed values" ); - - case type::NULL_: - consumer.null(); - return; - - case type::BOOLEAN: - consumer.boolean( v.unsafe_get_boolean() ); - return; - - case type::SIGNED: - consumer.number( v.unsafe_get_signed() ); - return; - - case type::UNSIGNED: - consumer.number( v.unsafe_get_unsigned() ); - return; - - case type::DOUBLE: - consumer.number( v.unsafe_get_double() ); - return; - - case type::STRING: - consumer.string( std::move( v.unsafe_get_string() ) ); - return; - - case type::STRING_VIEW: - consumer.string( v.unsafe_get_string_view() ); - return; - - case type::BINARY: - consumer.binary( std::move( v.unsafe_get_binary() ) ); - return; - - case type::BINARY_VIEW: - consumer.binary( v.unsafe_get_binary_view() ); - return; - - case type::ARRAY: - consumer.begin_array( v.unsafe_get_array().size() ); - for( auto&& e : v.unsafe_get_array() ) { - events::from_value( consumer, std::move( e ) ); - consumer.element(); - } - consumer.end_array( v.unsafe_get_array().size() ); - return; - - case type::OBJECT: - consumer.begin_object( v.unsafe_get_object().size() ); - for( auto&& e : v.unsafe_get_object() ) { - consumer.key( e.first ); - events::from_value( consumer, std::move( e.second ) ); - consumer.member(); - } - consumer.end_object( v.unsafe_get_object().size() ); - return; - - case type::RAW_PTR: - if( const basic_value< Traits >* p = v.unsafe_get_raw_ptr() ) { - events::from_value( consumer, *p ); - } - else { - consumer.null(); - } - return; + case type::OBJECT: { + const auto& o = v.get_object(); + const auto s = o.size(); + consumer.begin_object( s ); + for( const auto& e : o ) { + consumer.key( e.first ); + Recurse( consumer, e.second ); + consumer.member(); } - throw std::logic_error( "invalid value for tao::json::type" ); // LCOV_EXCL_LINE + consumer.end_object( s ); + return; + } + + case type::VALUE_PTR: + Recurse( consumer, *v.get_value_ptr() ); + return; + + case type::OPAQUE_PTR: { + const auto& q = v.get_opaque_ptr(); + virtual_ref< Consumer > ref( consumer ); + q.producer( ref, q.data ); + return; } - } // namespace events + case type::VALUELESS_BY_EXCEPTION: + throw std::logic_error( "unable to produce events from valueless-by-exception value" ); + } + throw std::logic_error( internal::format( "invalid value '", static_cast< std::uint8_t >( v.type() ), "' for tao::json::type" ) ); // LCOV_EXCL_LINE + } - } // namespace json + template< typename Consumer, template< typename... > class Traits > + void from_value( Consumer& consumer, const basic_value< Traits >& v ) + { + from_value< static_cast< void ( * )( Consumer&, const basic_value< Traits >& ) >( &from_value< Consumer, Traits > ), Consumer, Traits >( consumer, v ); + } + + // Events producer to generate events from an rvalue JSON value. + // Note: Strings from the source might be moved to the consumer. + + template< auto Recurse, typename Consumer, template< typename... > class Traits > + void from_value( Consumer& consumer, basic_value< Traits >&& v ) + { + switch( v.type() ) { + case type::UNINITIALIZED: + throw std::logic_error( "unable to produce events from uninitialized values" ); + + case type::NULL_: + consumer.null(); + return; + + case type::BOOLEAN: + consumer.boolean( v.get_boolean() ); + return; + + case type::SIGNED: + consumer.number( v.get_signed() ); + return; + + case type::UNSIGNED: + consumer.number( v.get_unsigned() ); + return; + + case type::DOUBLE: + consumer.number( v.get_double() ); + return; + + case type::STRING: + consumer.string( std::move( v.get_string() ) ); + return; + + case type::STRING_VIEW: + consumer.string( v.get_string_view() ); + return; + + case type::BINARY: + consumer.binary( std::move( v.get_binary() ) ); + return; + + case type::BINARY_VIEW: + consumer.binary( v.get_binary_view() ); + return; + + case type::ARRAY: { + const auto& a = v.get_array(); + const auto s = a.size(); + consumer.begin_array( s ); + for( auto&& e : a ) { + Recurse( consumer, std::move( e ) ); + consumer.element(); + } + consumer.end_array( s ); + return; + } + + case type::OBJECT: { + const auto& o = v.get_object(); + const auto s = o.size(); + consumer.begin_object( s ); + for( auto&& e : o ) { + consumer.key( e.first ); + Recurse( consumer, std::move( e.second ) ); + consumer.member(); + } + consumer.end_object( s ); + return; + } + + case type::VALUE_PTR: + Recurse( consumer, *v.get_value_ptr() ); + return; + + case type::OPAQUE_PTR: { + const auto& q = v.get_opaque_ptr(); + virtual_ref< Consumer > ref( consumer ); + q.producer( ref, q.data ); + return; + } + } + throw std::logic_error( internal::format( "invalid value '", static_cast< std::uint8_t >( v.type() ), "' for tao::json::type" ) ); // LCOV_EXCL_LINE + } + + template< typename Consumer, template< typename... > class Traits > + void from_value( Consumer& consumer, basic_value< Traits >&& v ) + { + from_value< static_cast< void ( * )( Consumer&, basic_value< Traits > && ) >( &from_value< Consumer, Traits > ), Consumer, Traits >( consumer, std::move( v ) ); + } -} // namespace tao +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/hash.hpp b/include/tao/json/events/hash.hpp index 8907c963..e0d2e7ea 100644 --- a/include/tao/json/events/hash.hpp +++ b/include/tao/json/events/hash.hpp @@ -1,176 +1,174 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_HASH_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_HASH_HPP +#ifndef TAO_JSON_EVENTS_HASH_HPP +#define TAO_JSON_EVENTS_HASH_HPP #include #include #include #include #include +#include #include #include +#include "../binary_view.hpp" + #include "../internal/sha256.hpp" -namespace tao +namespace tao::json::events { - namespace json - { - namespace events - { - // Events consumer that calculates an SHA-256 hash. - - class hash - { - private: - std::vector< std::unique_ptr< internal::sha256 > > m_digests; - std::vector< std::string > m_keys; - std::vector< std::map< std::string, std::string > > m_properties; - - void push() - { - m_digests.emplace_back( new internal::sha256 ); - } + // Events consumer that calculates an SHA-256 hash. - public: - hash() - { - push(); - } - - hash( const hash& ) = delete; - hash( hash&& ) = delete; - - void operator=( const hash& ) = delete; - void operator=( hash&& ) = delete; - - std::string value() const - { - return m_digests.back()->get(); - } + class hash + { + private: + std::vector< std::unique_ptr< internal::sha256 > > m_digests; + std::vector< std::string > m_keys; + std::vector< std::map< std::string, std::string > > m_properties; - void reset() - { - m_digests.back()->reset(); - } + void push() + { + m_digests.push_back( std::make_unique< internal::sha256 >() ); + } - void null() - { - m_digests.back()->feed( 'n' ); - } + public: + hash() + { + push(); + } - void boolean( const bool v ) - { - m_digests.back()->feed( v ? 't' : 'f' ); - } + hash( const hash& ) = delete; + hash( hash&& ) = delete; - void number( const std::int64_t v ) - { - if( v >= 0 ) { - number( static_cast< std::uint64_t >( v ) ); - } - else { - m_digests.back()->feed( 'i' ); - m_digests.back()->feed( &v, sizeof( v ) ); - } - } + ~hash() = default; - void number( const std::uint64_t v ) - { - m_digests.back()->feed( 'u' ); - m_digests.back()->feed( &v, sizeof( v ) ); - } + void operator=( const hash& ) = delete; + void operator=( hash&& ) = delete; - void number( const double v ) - { - if( v >= 0 ) { - const std::uint64_t u = v; - if( u == v ) { - number( u ); - return; - } - } - const std::int64_t i = v; - if( i == v ) { - number( i ); - return; - } - m_digests.back()->feed( 'd' ); - m_digests.back()->feed( &v, sizeof( v ) ); - } + [[nodiscard]] std::string value() const + { + return m_digests.back()->get(); + } - void string( const tao::string_view v ) - { - m_digests.back()->feed( 's' ); - const auto s = v.size(); - m_digests.back()->feed( &s, sizeof( s ) ); - m_digests.back()->feed( v.data(), v.size() ); - } + void reset() + { + m_digests.back()->reset(); + } - void binary( const tao::byte_view v ) - { - m_digests.back()->feed( 'x' ); - const auto s = v.size(); - m_digests.back()->feed( &s, sizeof( s ) ); - m_digests.back()->feed( v.data(), v.size() ); - } + void null() + { + m_digests.back()->feed( 'n' ); + } - void begin_array( const std::size_t = 0 ) - { - m_digests.back()->feed( '[' ); - } + void boolean( const bool v ) + { + m_digests.back()->feed( v ? 't' : 'f' ); + } - void element() - { - } + void number( const std::int64_t v ) + { + if( v >= 0 ) { + number( static_cast< std::uint64_t >( v ) ); + } + else { + m_digests.back()->feed( 'i' ); + m_digests.back()->feed( &v, sizeof( v ) ); + } + } + + void number( const std::uint64_t v ) + { + m_digests.back()->feed( 'u' ); + m_digests.back()->feed( &v, sizeof( v ) ); + } - void end_array( const std::size_t = 0 ) - { - m_digests.back()->feed( ']' ); - } + void number( const double v ) + { + if( v >= 0 ) { + const auto u = static_cast< std::uint64_t >( v ); + if( u == v ) { + number( u ); + return; + } + } + else { + const auto i = static_cast< std::int64_t >( v ); + if( i == v ) { + number( i ); + return; + } + } + m_digests.back()->feed( 'd' ); + m_digests.back()->feed( &v, sizeof( v ) ); + } + + void string( const std::string_view v ) + { + m_digests.back()->feed( 's' ); + const auto s = v.size(); + m_digests.back()->feed( &s, sizeof( s ) ); + m_digests.back()->feed( v ); + } - void begin_object( const std::size_t = 0 ) - { - m_digests.back()->feed( '{' ); - m_properties.emplace_back(); - push(); - } + void binary( const tao::binary_view v ) + { + m_digests.back()->feed( 'x' ); + const auto s = v.size(); + m_digests.back()->feed( &s, sizeof( s ) ); + m_digests.back()->feed( v.data(), v.size() ); + } - void key( const tao::string_view v ) - { - m_digests.back()->feed( v.data(), v.size() ); - m_keys.emplace_back( m_digests.back()->get() ); - if( m_properties.back().count( m_keys.back() ) != 0 ) { - throw std::runtime_error( "duplicate JSON object key: " + std::string( v.data(), v.size() ) ); - } - m_digests.back()->reset(); - } + void begin_array( const std::size_t /*unused*/ = 0 ) + { + m_digests.back()->feed( '[' ); + } - void member() - { - m_properties.back().emplace( std::move( m_keys.back() ), m_digests.back()->get() ); - m_keys.pop_back(); - m_digests.back()->reset(); - } + void element() + {} - void end_object( const std::size_t = 0 ) - { - m_digests.pop_back(); - for( const auto& e : m_properties.back() ) { - m_digests.back()->feed( e.first ); - m_digests.back()->feed( e.second ); - } - m_properties.pop_back(); - m_digests.back()->feed( '}' ); - } - }; + void end_array( const std::size_t /*unused*/ = 0 ) + { + m_digests.back()->feed( ']' ); + } - } // namespace events + void begin_object( const std::size_t /*unused*/ = 0 ) + { + m_digests.back()->feed( '{' ); + m_properties.emplace_back(); + push(); + } - } // namespace json + void key( const std::string_view v ) + { + m_digests.back()->feed( v ); + m_keys.emplace_back( m_digests.back()->get() ); + if( m_properties.back().count( m_keys.back() ) != 0 ) { + throw std::runtime_error( "duplicate JSON object key: " + std::string( v ) ); + } + m_digests.back()->reset(); + } + + void member() + { + m_properties.back().emplace( std::move( m_keys.back() ), m_digests.back()->get() ); + m_keys.pop_back(); + m_digests.back()->reset(); + } -} // namespace tao + void end_object( const std::size_t /*unused*/ = 0 ) + { + m_digests.pop_back(); + for( const auto& e : m_properties.back() ) { + m_digests.back()->feed( e.first ); + m_digests.back()->feed( e.second ); + } + m_properties.pop_back(); + m_digests.back()->feed( '}' ); + } + }; + +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/invalid_string_to_binary.hpp b/include/tao/json/events/invalid_string_to_binary.hpp new file mode 100644 index 00000000..a0636bc0 --- /dev/null +++ b/include/tao/json/events/invalid_string_to_binary.hpp @@ -0,0 +1,50 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_EVENTS_INVALID_STRING_TO_BINARY_HPP +#define TAO_JSON_EVENTS_INVALID_STRING_TO_BINARY_HPP + +#include +#include + +#include "../binary_view.hpp" +#include "../utf8.hpp" + +namespace tao::json::events +{ + template< typename Consumer > + struct invalid_string_to_binary + : Consumer + { + using Consumer::Consumer; + + void string( const char* v ) + { + string( std::string_view( v ) ); + } + + void string( std::string&& v ) + { + if( internal::validate_utf8_nothrow( v ) ) { + Consumer::string( std::move( v ) ); + } + else { + const std::byte* data = reinterpret_cast< const std::byte* >( v.data() ); + Consumer::binary( std::vector< std::byte >( data, data + v.size() ) ); + } + } + + void string( const std::string_view v ) + { + if( internal::validate_utf8_nothrow( v ) ) { + Consumer::string( v ); + } + else { + Consumer::binary( tao::binary_view( reinterpret_cast< const std::byte* >( v.data() ), v.size() ) ); + } + } + }; + +} // namespace tao::json::events + +#endif diff --git a/include/tao/json/events/invalid_string_to_exception.hpp b/include/tao/json/events/invalid_string_to_exception.hpp new file mode 100644 index 00000000..aeb2ed18 --- /dev/null +++ b/include/tao/json/events/invalid_string_to_exception.hpp @@ -0,0 +1,49 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_EVENTS_INVALID_STRING_TO_EXCEPTION_HPP +#define TAO_JSON_EVENTS_INVALID_STRING_TO_EXCEPTION_HPP + +#include +#include + +#include "../internal/hexdump.hpp" +#include "../utf8.hpp" + +namespace tao::json::events +{ + template< typename Consumer > + struct invalid_string_to_exception + : Consumer + { + using Consumer::Consumer; + + void string( const char* v ) + { + string( std::string_view( v ) ); + } + + void string( std::string&& v ) + { + if( internal::validate_utf8_nothrow( v ) ) { + Consumer::string( std::move( v ) ); + } + else { + throw std::runtime_error( "invalid UTF8 string: $" + internal::hexdump( v ) ); + } + } + + void string( const std::string_view v ) + { + if( internal::validate_utf8_nothrow( v ) ) { + Consumer::string( v ); + } + else { + throw std::runtime_error( "invalid UTF8 string: $" + internal::hexdump( v ) ); + } + } + }; + +} // namespace tao::json::events + +#endif diff --git a/include/tao/json/events/invalid_string_to_hex.hpp b/include/tao/json/events/invalid_string_to_hex.hpp new file mode 100644 index 00000000..6950e422 --- /dev/null +++ b/include/tao/json/events/invalid_string_to_hex.hpp @@ -0,0 +1,48 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_EVENTS_INVALID_STRING_TO_HEX_HPP +#define TAO_JSON_EVENTS_INVALID_STRING_TO_HEX_HPP + +#include + +#include "../internal/hexdump.hpp" +#include "../utf8.hpp" + +namespace tao::json::events +{ + template< typename Consumer > + struct invalid_string_to_hex + : Consumer + { + using Consumer::Consumer; + + void string( const char* v ) + { + string( std::string_view( v ) ); + } + + void string( std::string&& v ) + { + if( internal::validate_utf8_nothrow( v ) ) { + Consumer::string( std::move( v ) ); + } + else { + Consumer::string( internal::hexdump( v ) ); + } + } + + void string( const std::string_view v ) + { + if( internal::validate_utf8_nothrow( v ) ) { + Consumer::string( v ); + } + else { + Consumer::string( internal::hexdump( v ) ); + } + } + }; + +} // namespace tao::json::events + +#endif diff --git a/include/tao/json/events/jaxn/from_stream.hpp b/include/tao/json/events/jaxn/from_stream.hpp deleted file mode 100644 index 444da8b0..00000000 --- a/include/tao/json/events/jaxn/from_stream.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JAXN_FROM_STREAM_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_JAXN_FROM_STREAM_HPP - -#include - -#include "../../external/pegtl/internal/istream_reader.hpp" -#include "../../external/pegtl/parse.hpp" - -#include "../../internal/jaxn/action.hpp" -#include "../../internal/jaxn/control.hpp" -#include "../../internal/jaxn/grammar.hpp" - -namespace tao -{ - namespace json - { - namespace events - { - namespace jaxn - { - template< typename Consumer > - void from_stream( Consumer& consumer, std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) - { - json_pegtl::istream_input<> in( stream, maximum_buffer_size, source ? source : "tao::json::events::jaxn::from_stream" ); - json_pegtl::parse< internal::jaxn::grammar, internal::jaxn::action, internal::jaxn::control >( in, consumer ); - } - - template< typename Consumer > - void from_stream( Consumer& consumer, std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) - { - jaxn::from_stream( consumer, stream, source.c_str(), maximum_buffer_size ); - } - - } // namespace jaxn - - } // namespace events - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/events/jaxn/from_string.hpp b/include/tao/json/events/jaxn/from_string.hpp deleted file mode 100644 index c91941cc..00000000 --- a/include/tao/json/events/jaxn/from_string.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JAXN_FROM_STRING_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_JAXN_FROM_STRING_HPP - -#include "../../external/pegtl/parse.hpp" -#include "../../external/string_view.hpp" - -#include "../../internal/jaxn/action.hpp" -#include "../../internal/jaxn/control.hpp" -#include "../../internal/jaxn/grammar.hpp" - -namespace tao -{ - namespace json - { - namespace events - { - namespace jaxn - { - // Events producer to parse a JAXN string representation. - - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) - { - json_pegtl::memory_input< json_pegtl::tracking_mode::LAZY, json_pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::events::jaxn::from_string", byte, line, column ); - json_pegtl::parse< internal::jaxn::grammar, internal::jaxn::action, internal::jaxn::control >( in, consumer ); - } - - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) - { - jaxn::from_string( consumer, data, size, source.c_str(), byte, line, column ); - } - - template< typename Consumer, typename... Ts > - void from_string( Consumer& consumer, const tao::string_view data, Ts&&... ts ) - { - jaxn::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); - } - - } // namespace jaxn - - } // namespace events - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/events/jaxn/parse_file.hpp b/include/tao/json/events/jaxn/parse_file.hpp deleted file mode 100644 index ffc12708..00000000 --- a/include/tao/json/events/jaxn/parse_file.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JAXN_PARSE_FILE_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_JAXN_PARSE_FILE_HPP - -#include - -#include "../../internal/jaxn/action.hpp" -#include "../../internal/jaxn/control.hpp" -#include "../../internal/jaxn/grammar.hpp" - -#include "../../external/pegtl/file_input.hpp" - -namespace tao -{ - namespace json - { - namespace events - { - namespace jaxn - { - // Events producer to parse a file containing a JAXN string representation. - - template< typename T, typename Consumer > - void parse_file( Consumer& consumer, T&& filename ) - { - json_pegtl::file_input< json_pegtl::tracking_mode::LAZY > in( std::forward< T >( filename ) ); - json_pegtl::parse< internal::jaxn::grammar, internal::jaxn::action, internal::jaxn::control >( in, consumer ); - } - - } // namespace jaxn - - } // namespace events - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/events/jaxn/to_pretty_stream.hpp b/include/tao/json/events/jaxn/to_pretty_stream.hpp deleted file mode 100644 index 66100e74..00000000 --- a/include/tao/json/events/jaxn/to_pretty_stream.hpp +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JAXN_TO_PRETTY_STREAM_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_JAXN_TO_PRETTY_STREAM_HPP - -#include "../../internal/hexdump.hpp" -#include "../../jaxn/is_identifier.hpp" -#include "../to_pretty_stream.hpp" - -namespace tao -{ - namespace json - { - namespace events - { - namespace jaxn - { - // Events consumer to build a JAXN string representation. - - struct to_pretty_stream : events::to_pretty_stream - { - using events::to_pretty_stream::to_pretty_stream; - - using events::to_pretty_stream::number; - - void number( const double v ) - { - next(); - if( !std::isfinite( v ) ) { - if( std::isnan( v ) ) { - os.write( "NaN", 3 ); - } - else if( v < 0 ) { - os.write( "-Infinity", 9 ); - } - else { - os.write( "Infinity", 8 ); - } - } - else { - json_double_conversion::Dtostr( os, v ); - } - } - - void key( const tao::string_view v ) - { - if( json::jaxn::is_identifier( v ) ) { - next(); - os.write( v.data(), v.size() ); - } - else { - string( v ); - } - os.write( ": ", 2 ); - first = true; - after_key = true; - } - - void binary( const tao::byte_view v ) - { - next(); - os.put( '$' ); - internal::hexdump( os, v ); - } - }; - - } // namespace jaxn - - } // namespace events - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/events/jaxn/to_stream.hpp b/include/tao/json/events/jaxn/to_stream.hpp deleted file mode 100644 index bf2c33c4..00000000 --- a/include/tao/json/events/jaxn/to_stream.hpp +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JAXN_TO_STREAM_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_JAXN_TO_STREAM_HPP - -#include "../../internal/hexdump.hpp" -#include "../../jaxn/is_identifier.hpp" -#include "../to_stream.hpp" - -namespace tao -{ - namespace json - { - namespace events - { - namespace jaxn - { - // Events consumer to build a JAXN string representation. - - struct to_stream : events::to_stream - { - using events::to_stream::to_stream; - - using events::to_stream::number; - - void number( const double v ) - { - next(); - if( !std::isfinite( v ) ) { - if( std::isnan( v ) ) { - os << "NaN"; - } - else if( v < 0 ) { - os << "-Infinity"; - } - else { - os << "Infinity"; - } - } - else { - json_double_conversion::Dtostr( os, v ); - } - } - - void key( const tao::string_view v ) - { - if( json::jaxn::is_identifier( v ) ) { - next(); - os.write( v.data(), v.size() ); - } - else { - string( v ); - } - os.put( ':' ); - first = true; - } - - void binary( const tao::byte_view v ) - { - next(); - os.put( '$' ); - internal::hexdump( os, v ); - } - }; - - } // namespace jaxn - - } // namespace events - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/events/key_camel_case_to_snake_case.hpp b/include/tao/json/events/key_camel_case_to_snake_case.hpp index 5b3a244f..b7e78d4c 100644 --- a/include/tao/json/events/key_camel_case_to_snake_case.hpp +++ b/include/tao/json/events/key_camel_case_to_snake_case.hpp @@ -1,71 +1,62 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_KEY_CAMEL_CASE_TO_SNAKE_CASE_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_KEY_CAMEL_CASE_TO_SNAKE_CASE_HPP +#ifndef TAO_JSON_EVENTS_KEY_CAMEL_CASE_TO_SNAKE_CASE_HPP +#define TAO_JSON_EVENTS_KEY_CAMEL_CASE_TO_SNAKE_CASE_HPP #include #include +#include -#include "../external/string_view.hpp" - -namespace tao +namespace tao::json::events { - namespace json + template< typename Consumer > + struct key_camel_case_to_snake_case + : Consumer { - namespace events - { - template< typename Consumer > - struct key_camel_case_to_snake_case - : public Consumer - { - using Consumer::Consumer; + using Consumer::Consumer; - void key( const tao::string_view v ) - { - std::string t; - bool last_upper = false; - for( const auto c : v ) { - if( std::isupper( c ) ) { - last_upper = true; - t += c; - } - else { - if( last_upper ) { - const char o = t.back(); - t.pop_back(); - if( !t.empty() && t.back() != '_' ) { - t += '_'; - } - t += o; - } - last_upper = false; - t += c; + void key( const std::string_view v ) + { + std::string t; + bool last_upper = false; + for( const auto c : v ) { + if( std::isupper( c ) ) { + last_upper = true; + t += c; + } + else { + if( last_upper ) { + const char o = t.back(); + t.pop_back(); + if( !t.empty() && t.back() != '_' ) { + t += '_'; } + t += o; } - std::string r; - bool last_lower = false; - for( const auto c : t ) { - if( std::isupper( c ) ) { - if( last_lower ) { - r += '_'; - } - last_lower = false; - r += std::tolower( c ); - } - else { - last_lower = std::islower( c ); - r += c; - } + last_upper = false; + t += c; + } + } + std::string r; + bool last_lower = false; + for( const auto c : t ) { + if( std::isupper( c ) ) { + if( last_lower ) { + r += '_'; } - Consumer::key( std::move( r ) ); + last_lower = false; + r += static_cast< char >( std::tolower( c ) ); } - }; - - } // namespace events - - } // namespace json + else { + last_lower = static_cast< bool >( std::islower( c ) ); + r += c; + } + } + Consumer::key( std::move( r ) ); + } + }; -} // namespace tao +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/key_snake_case_to_camel_case.hpp b/include/tao/json/events/key_snake_case_to_camel_case.hpp index 6a659305..4889fbf8 100644 --- a/include/tao/json/events/key_snake_case_to_camel_case.hpp +++ b/include/tao/json/events/key_snake_case_to_camel_case.hpp @@ -1,66 +1,57 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_KEY_SNAKE_CASE_TO_CAMEL_CASE_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_KEY_SNAKE_CASE_TO_CAMEL_CASE_HPP +#ifndef TAO_JSON_EVENTS_KEY_SNAKE_CASE_TO_CAMEL_CASE_HPP +#define TAO_JSON_EVENTS_KEY_SNAKE_CASE_TO_CAMEL_CASE_HPP #include #include +#include -#include "../external/string_view.hpp" - -namespace tao +namespace tao::json::events { - namespace json + template< typename Consumer > + struct key_snake_case_to_camel_case + : Consumer { - namespace events - { - template< typename Consumer > - struct key_snake_case_to_camel_case - : public Consumer - { - using Consumer::Consumer; + using Consumer::Consumer; - void key( const tao::string_view v ) - { - std::string r; - r.reserve( v.size() ); - bool active = false; - for( const auto c : v ) { - if( active ) { - if( c == '_' ) { - r += c; - } - else if( std::isupper( c ) ) { - r += '_'; - r += c; - active = false; - } - else { - r += std::toupper( c ); - active = false; - } - } - else { - if( c == '_' ) { - active = true; - } - else { - r += c; - } - } + void key( const std::string_view v ) + { + std::string r; + r.reserve( v.size() ); + bool active = false; + for( const auto c : v ) { + if( active ) { + if( c == '_' ) { + r += c; } - if( active ) { + else if( std::isupper( c ) ) { r += '_'; + r += c; + active = false; + } + else { + r += static_cast< char >( std::toupper( c ) ); + active = false; } - Consumer::key( std::move( r ) ); } - }; - - } // namespace events - - } // namespace json - -} // namespace tao + else { + if( c == '_' ) { + active = true; + } + else { + r += c; + } + } + } + if( active ) { + r += '_'; + } + Consumer::key( std::move( r ) ); + } + }; + +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/limit_nesting_depth.hpp b/include/tao/json/events/limit_nesting_depth.hpp new file mode 100644 index 00000000..d3e9c428 --- /dev/null +++ b/include/tao/json/events/limit_nesting_depth.hpp @@ -0,0 +1,82 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_EVENTS_LIMIT_NESTING_DEPTH_HPP +#define TAO_JSON_EVENTS_LIMIT_NESTING_DEPTH_HPP + +#include +#include + +#include + +namespace tao::json::events +{ + template< typename Consumer, std::size_t Limit > + class limit_nesting_depth + : public Consumer + { + private: + std::size_t m_depth = 0; + + void count_and_limit() + { + if( ++m_depth > Limit ) { + throw std::runtime_error( "nesting depth limit exceeded" ); + } + } + + public: + using Consumer::Consumer; + + void begin_array() + { + count_and_limit(); + Consumer::begin_array(); + } + + void begin_array( const std::size_t size ) + { + count_and_limit(); + Consumer::begin_array( size ); + } + + void end_array() + { + Consumer::end_array(); + --m_depth; + } + + void end_array( const std::size_t size ) + { + Consumer::end_array( size ); + --m_depth; + } + + void begin_object() + { + count_and_limit(); + Consumer::begin_object(); + } + + void begin_object( const std::size_t size ) + { + count_and_limit(); + Consumer::begin_object( size ); + } + + void end_object() + { + Consumer::end_object(); + --m_depth; + } + + void end_object( const std::size_t size ) + { + Consumer::end_object( size ); + --m_depth; + } + }; + +} // namespace tao::json::events + +#endif diff --git a/include/tao/json/events/limit_value_count.hpp b/include/tao/json/events/limit_value_count.hpp new file mode 100644 index 00000000..6c70aaaf --- /dev/null +++ b/include/tao/json/events/limit_value_count.hpp @@ -0,0 +1,46 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_EVENTS_LIMIT_VALUE_COUNT_HPP +#define TAO_JSON_EVENTS_LIMIT_VALUE_COUNT_HPP + +#include +#include + +#include + +namespace tao::json::events +{ + template< typename Consumer, std::size_t Limit > + class limit_value_count + : public Consumer + { + private: + std::size_t m_count = 1; // Top-level value is implied. + + void count_and_limit() + { + if( ++m_count > Limit ) { + throw std::runtime_error( "value count limit exceeded" ); + } + } + + public: + using Consumer::Consumer; + + void element() + { + count_and_limit(); + Consumer::element(); + } + + void member() + { + count_and_limit(); + Consumer::member(); + } + }; + +} // namespace tao::json::events + +#endif diff --git a/include/tao/json/events/msgpack/from_string.hpp b/include/tao/json/events/msgpack/from_string.hpp deleted file mode 100644 index b670c62f..00000000 --- a/include/tao/json/events/msgpack/from_string.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_MSGPACK_FROM_STRING_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_MSGPACK_FROM_STRING_HPP - -#include "../../external/pegtl/parse.hpp" - -#include "grammar.hpp" - -namespace tao -{ - namespace json - { - namespace events - { - namespace msgpack - { - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t byte_in_line = 0 ) - { - json_pegtl::memory_input< json_pegtl::tracking_mode::LAZY, json_pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::msgpack::from_string", byte, line, byte_in_line ); - json_pegtl::parse< msgpack::grammar >( in, consumer ); - } - - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t byte_in_line = 0 ) - { - msgpack::from_string( consumer, data, size, source.c_str(), byte, line, byte_in_line ); - } - - template< typename Consumer, typename... Ts > - void from_string( Consumer& consumer, const tao::string_view data, Ts&&... ts ) - { - msgpack::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); - } - - } // namespace msgpack - - } // namespace events - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/events/msgpack/grammar.hpp b/include/tao/json/events/msgpack/grammar.hpp deleted file mode 100644 index 7fc504ed..00000000 --- a/include/tao/json/events/msgpack/grammar.hpp +++ /dev/null @@ -1,261 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_MSGPACK_GRAMMAR_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_MSGPACK_GRAMMAR_HPP - -#include - -#include "../../external/byte.hpp" -#include "../../internal/endian.hpp" - -namespace tao -{ - namespace json - { - namespace events - { - namespace msgpack - { - struct data - { - using analyze_t = json_pegtl::analysis::generic< json_pegtl::analysis::rule_type::ANY >; - - template< json_pegtl::apply_mode A, - json_pegtl::rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename Consumer > - static bool match( Input& in, Consumer& consumer ) - { - // This rule never returns false unless the input is empty. - return ( !in.empty() ) && match_impl( in, consumer ); - } - - template< typename Input, typename Consumer > - static bool match_impl( Input& in, Consumer& consumer ) - { - const auto b = in.peek_byte(); - if( b <= 0x7f ) { - consumer.number( std::uint64_t( b ) ); - in.bump_in_this_line(); - return true; - } - else if( b >= 0xe0 ) { - consumer.number( std::int64_t( std::int8_t( b ) ) ); - in.bump_in_this_line(); - return true; - } - else if( ( 0x80 <= b ) && ( b <= 0x8f ) ) { - in.bump_in_this_line(); - return match_object( in, consumer, b - 0x80 ); - } - else if( ( 0x90 <= b ) && ( b <= 0x9f ) ) { - in.bump_in_this_line(); - return match_array( in, consumer, b - 0x90 ); - } - else if( ( 0xa0 <= b ) && ( b <= 0xbf ) ) { - in.bump_in_this_line(); - consumer.string( read_container< tao::string_view >( in, b - 0xa0 ) ); - return true; - } - switch( b ) { - case 0xc0: - consumer.null(); - in.bump_in_this_line(); - return true; - case 0xc1: - throw json_pegtl::parse_error( "unused msgpack first byte 0xc1", in ); - case 0xc2: - case 0xc3: - consumer.boolean( b & 1 ); - in.bump_in_this_line(); - return true; - case 0xc4: - consumer.binary( read_container< tao::byte_view >( in, read_number< std::size_t, std::uint8_t >( in ) ) ); - return true; - case 0xc5: - consumer.binary( read_container< tao::byte_view >( in, read_number< std::size_t, std::uint16_t >( in ) ) ); - return true; - case 0xc6: - consumer.binary( read_container< tao::byte_view >( in, read_number< std::size_t, std::uint32_t >( in ) ) ); - return true; - case 0xc7: - discard( in, read_number< std::size_t, std::uint8_t >( in ) + 1 ); - return true; - case 0xc8: - discard( in, read_number< std::size_t, std::uint16_t >( in ) + 1 ); - return true; - case 0xc9: - discard( in, read_number< std::size_t, std::uint32_t >( in ) + 1 ); - return true; - case 0xca: - consumer.number( read_number< double, float >( in ) ); - return true; - case 0xcb: - consumer.number( read_number< double, double >( in ) ); - return true; - case 0xcc: - consumer.number( read_number< std::uint64_t, std::uint8_t >( in ) ); - return true; - case 0xcd: - consumer.number( read_number< std::uint64_t, std::uint16_t >( in ) ); - return true; - case 0xce: - consumer.number( read_number< std::uint64_t, std::uint32_t >( in ) ); - return true; - case 0xcf: - consumer.number( read_number< std::uint64_t, std::uint64_t >( in ) ); - return true; - case 0xd0: - consumer.number( read_number< std::int64_t, std::int8_t >( in ) ); - return true; - case 0xd1: - consumer.number( read_number< std::int64_t, std::int16_t >( in ) ); - return true; - case 0xd2: - consumer.number( read_number< std::int64_t, std::int32_t >( in ) ); - return true; - case 0xd3: - consumer.number( read_number< std::int64_t, std::int64_t >( in ) ); - return true; - case 0xd4: - discard( in, 3 ); - return true; - case 0xd5: - discard( in, 4 ); - return true; - case 0xd6: - discard( in, 6 ); - return true; - case 0xd7: - discard( in, 10 ); - return true; - case 0xd8: - discard( in, 18 ); - return true; - case 0xd9: - consumer.string( read_container< tao::string_view >( in, read_number< std::size_t, std::uint8_t >( in ) ) ); - return true; - case 0xda: - consumer.string( read_container< tao::string_view >( in, read_number< std::size_t, std::uint16_t >( in ) ) ); - return true; - case 0xdb: - consumer.string( read_container< tao::string_view >( in, read_number< std::size_t, std::uint32_t >( in ) ) ); - return true; - case 0xdc: - return match_array( in, consumer, read_number< std::size_t, std::uint16_t >( in ) ); - case 0xdd: - return match_array( in, consumer, read_number< std::size_t, std::uint32_t >( in ) ); - case 0xde: - return match_object( in, consumer, read_number< std::size_t, std::uint16_t >( in ) ); - case 0xdf: - return match_object( in, consumer, read_number< std::size_t, std::uint32_t >( in ) ); - } - // LCOV_EXCL_START - assert( false ); - return false; - // LCOV_EXCL_STOP - } - - template< typename Input > - static void discard( Input& in, const std::size_t count ) - { - if( in.size( count ) < count ) { - throw json_pegtl::parse_error( "unexpected end of input", in ); - } - in.bump_in_this_line( count ); - } - - template< typename Result, typename Number, typename Input > - static Result read_number( Input& in ) - { - if( in.size( sizeof( Number ) ) > sizeof( Number ) ) { - const Result result = json::internal::be_to_h< Number >( in.current() + 1 ); - in.bump_in_this_line( 1 + sizeof( Number ) ); - return result; - } - throw json_pegtl::parse_error( "unexpected end of msgpack input", in ); - } - - template< typename Result, typename Input > - static Result read_container( Input& in, const std::size_t size ) - { - using value_t = typename Result::value_type; - if( in.size( size ) < size ) { - throw json_pegtl::parse_error( "unexpected end of input", in ); - } - const value_t* pointer = reinterpret_cast< const value_t* >( in.current() ); - Result result( pointer, size ); - in.bump_in_this_line( size ); - return result; - } - - template< typename Input > - static tao::string_view read_key( Input& in ) - { - if( in.empty() ) { - throw json_pegtl::parse_error( "unexpected end of input", in ); - } - const auto b = in.peek_byte(); - if ( ( 0xa0 <= b ) && ( b <= 0xbf ) ) { - in.bump_in_this_line(); - return read_container< tao::string_view >( in, b - 0xa0 ); - } - switch( b ) { - case 0xd9: - return read_container< tao::string_view >( in, read_number< std::size_t, std::uint8_t >( in ) ); - case 0xda: - return read_container< tao::string_view >( in, read_number< std::size_t, std::uint16_t >( in ) ); - case 0xdb: - return read_container< tao::string_view >( in, read_number< std::size_t, std::uint32_t >( in ) ); - } - throw json_pegtl::parse_error( "unexpected key type", in ); - } - - template< typename Input, typename Consumer > - static bool match_array( Input& in, Consumer& consumer, const std::size_t size ) - { - consumer.begin_array( size ); - for( std::size_t i = 0; i < size; ++i ) { - if( in.empty() ) { - throw json_pegtl::parse_error( "unexpected end of input", in ); - } - match_impl( in, consumer ); - consumer.element(); - } - consumer.end_array( size ); - return true; - } - - template< typename Input, typename Consumer > - static bool match_object( Input& in, Consumer& consumer, const std::size_t size ) - { - consumer.begin_object( size ); - for( std::size_t i = 0; i < size; ++i ) { - consumer.key( read_key( in ) ); - if( in.empty() ) { - throw json_pegtl::parse_error( "unexpected end of input", in ); - } - match_impl( in, consumer ); - consumer.member(); - } - consumer.end_object( size ); - return true; - } - }; - - struct grammar : json_pegtl::must< data, json_pegtl::eof > - { - }; - - } // namespace msgpack - - } // namespace events - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/events/msgpack/to_stream.hpp b/include/tao/json/events/msgpack/to_stream.hpp deleted file mode 100644 index 23b2df89..00000000 --- a/include/tao/json/events/msgpack/to_stream.hpp +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JSON_MSGPACK_TO_STREAM_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_JSON_MSGPACK_TO_STREAM_HPP - -#include -#include -#include -#include - -#include "../../external/byte.hpp" -#include "../../internal/endian.hpp" - -namespace tao -{ - namespace json - { - namespace events - { - namespace msgpack - { - class to_stream - { - private: - std::ostream& os; - - public: - explicit to_stream( std::ostream& in_os ) noexcept - : os( in_os ) - { - } - - void null() - { - os.put( char( 0xc0 ) ); - } - - void boolean( const bool v ) - { - os.put( char( 0xc2 ) + char( v ) ); - } - - template< typename Integer > - void number_impl( const unsigned char tag, const std::uint64_t v ) - { - os.put( char( tag ) ); - const Integer x = internal::h_to_be( Integer( v ) ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - - void number( const std::int64_t v ) - { - if( ( v >= -32 ) && ( v <= -1 ) ) { - const std::int8_t x = v; - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else if( ( v >= -128 ) && ( v <= 127 ) ) { - number_impl< std::uint8_t >( 0xd0, v ); - } - else if( ( v >= -32768 ) && ( v <= 32767 ) ) { - number_impl< std::uint16_t >( 0xd1, v ); - } - else if( ( v >= -2147483648 ) && ( v <= 2147483647 ) ) { - number_impl< std::uint32_t >( 0xd2, v ); - } - else { - number_impl< std::uint64_t >( 0xd3, v ); - } - } - - void number( const std::uint64_t v ) - { - if( v <= 127 ) { - const std::uint8_t x = v; - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else if( v <= 255 ) { - number_impl< std::uint8_t >( 0xcc, v ); - } - else if( v <= 65535 ) { - number_impl< std::uint16_t >( 0xcd, v ); - } - else if( v <= 4294967295ul ) { - number_impl< std::uint32_t >( 0xce, v ); - } - else { - number_impl< std::uint64_t >( 0xcf, v ); - } - } - - void number( const double v ) - { - os.put( char( 0xcb ) ); - const auto x = internal::h_to_be( v ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - - void string( const tao::string_view v ) - { - if( v.size() <= 31 ) { - os.put( char( v.size() + 0xa0 ) ); - } - else if( v.size() <= 255 ) { - number_impl< std::uint8_t >( 0xd9, v.size() ); - } - else if( v.size() <= 65535 ) { - number_impl< std::uint16_t >( 0xda, v.size() ); - } - else if( v.size() <= 4294967295ul ) { - number_impl< std::uint32_t >( 0xdb, v.size() ); - } - else { - throw std::runtime_error( "string too long for msgpack" ); - } - os.write( v.data(), v.size() ); - } - - void binary( const tao::byte_view v ) - { - if( v.size() <= 255 ) { - number_impl< std::uint8_t >( 0xc4, v.size() ); - } - else if( v.size() <= 65535 ) { - number_impl< std::uint16_t >( 0xc5, v.size() ); - } - else if( v.size() <= 4294967295ul ) { - number_impl< std::uint32_t >( 0xc6, v.size() ); - } - else { - throw std::runtime_error( "binary too long for msgpack" ); - } - os.write( reinterpret_cast< const char* >( v.data() ), v.size() ); - } - - void begin_array() - { - throw std::runtime_error( "msgpack requires array size" ); // TODO: Fix this by counting and buffering? - } - - void begin_array( const std::size_t size ) - { - if( size <= 15 ) { - os.put( char( 0x90 + size ) ); - } - else if( size <= 65535 ) { - number_impl< std::uint16_t >( 0xdc, size ); - } - else if( size <= 4294967295ul ) { - number_impl< std::uint32_t >( 0xdd, size ); - } - else { - throw std::runtime_error( "array too large for msgpack" ); - } - } - - void element() noexcept - { - } - - void end_array() - { - assert( false ); // LCOV_EXCL_LINE - } - - void end_array( const std::size_t ) noexcept - { - } - - void begin_object() - { - throw std::runtime_error( "msgpack requires object size" ); // TODO: Fix this by counting and buffering? - } - - void begin_object( const std::size_t size ) - { - if( size <= 15 ) { - os.put( char( 0x80 + size ) ); - } - else if( size <= 65535 ) { - number_impl< std::uint16_t >( 0xde, size ); - } - else if( size <= 4294967295ul ) { - number_impl< std::uint32_t >( 0xdf, size ); - } - else { - throw std::runtime_error( "array too large for msgpack" ); - } - } - - void key( const tao::string_view v ) - { - string( v ); - } - - void member() noexcept - { - } - - void end_object() - { - assert( false ); // LCOV_EXCL_LINE - } - - void end_object( const std::size_t ) noexcept - { - } - }; - - } // namespace msgpack - - } // namespace events - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/events/msgpack/to_string.hpp b/include/tao/json/events/msgpack/to_string.hpp deleted file mode 100644 index 668a8f03..00000000 --- a/include/tao/json/events/msgpack/to_string.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JSON_MSGPACK_TO_STRING_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_JSON_MSGPACK_TO_STRING_HPP - -#include -#include - -#include "to_stream.hpp" - -namespace tao -{ - namespace json - { - namespace events - { - namespace msgpack - { - struct to_string - : public to_stream - { - std::ostringstream oss; - - to_string() - : to_stream( oss ) - { - } - - std::string value() const - { - return oss.str(); - } - }; - - } // namespace msgpack - - } // namespace events - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/events/non_finite_to_exception.hpp b/include/tao/json/events/non_finite_to_exception.hpp index 023b3a91..a4f48049 100644 --- a/include/tao/json/events/non_finite_to_exception.hpp +++ b/include/tao/json/events/non_finite_to_exception.hpp @@ -1,39 +1,31 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_NON_FINITE_TO_EXCEPTION_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_NON_FINITE_TO_EXCEPTION_HPP +#ifndef TAO_JSON_EVENTS_NON_FINITE_TO_EXCEPTION_HPP +#define TAO_JSON_EVENTS_NON_FINITE_TO_EXCEPTION_HPP #include #include -namespace tao +namespace tao::json::events { - namespace json + template< typename Consumer > + struct non_finite_to_exception + : Consumer { - namespace events - { - template< typename Consumer > - struct non_finite_to_exception - : public Consumer - { - using Consumer::Consumer; - - using Consumer::number; - - void number( const double v ) - { - if( !std::isfinite( v ) ) { - throw std::runtime_error( "invalid non-finite double value" ); - } - Consumer::number( v ); - } - }; + using Consumer::Consumer; - } // namespace events + using Consumer::number; - } // namespace json - -} // namespace tao + void number( const double v ) + { + if( !std::isfinite( v ) ) { + throw std::runtime_error( "invalid non-finite double value" ); + } + Consumer::number( v ); + } + }; + +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/non_finite_to_null.hpp b/include/tao/json/events/non_finite_to_null.hpp index 70e8c69a..1556d1fa 100644 --- a/include/tao/json/events/non_finite_to_null.hpp +++ b/include/tao/json/events/non_finite_to_null.hpp @@ -1,40 +1,32 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_NON_FINITE_TO_NULL_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_NON_FINITE_TO_NULL_HPP +#ifndef TAO_JSON_EVENTS_NON_FINITE_TO_NULL_HPP +#define TAO_JSON_EVENTS_NON_FINITE_TO_NULL_HPP #include -namespace tao +namespace tao::json::events { - namespace json + template< typename Consumer > + struct non_finite_to_null + : Consumer { - namespace events - { - template< typename Consumer > - struct non_finite_to_null - : public Consumer - { - using Consumer::Consumer; - - using Consumer::number; - - void number( const double v ) - { - if( !std::isfinite( v ) ) { - Consumer::null(); - } - else { - Consumer::number( v ); - } - } - }; + using Consumer::Consumer; - } // namespace events + using Consumer::number; - } // namespace json - -} // namespace tao + void number( const double v ) + { + if( !std::isfinite( v ) ) { + Consumer::null(); + } + else { + Consumer::number( v ); + } + } + }; + +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/non_finite_to_string.hpp b/include/tao/json/events/non_finite_to_string.hpp index 0e2cd09b..a61855cf 100644 --- a/include/tao/json/events/non_finite_to_string.hpp +++ b/include/tao/json/events/non_finite_to_string.hpp @@ -1,48 +1,40 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_NON_FINITE_TO_STRING_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_NON_FINITE_TO_STRING_HPP +#ifndef TAO_JSON_EVENTS_NON_FINITE_TO_STRING_HPP +#define TAO_JSON_EVENTS_NON_FINITE_TO_STRING_HPP #include -namespace tao +namespace tao::json::events { - namespace json + template< typename Consumer > + struct non_finite_to_string + : Consumer { - namespace events - { - template< typename Consumer > - struct non_finite_to_string - : public Consumer - { - using Consumer::Consumer; + using Consumer::Consumer; - using Consumer::number; + using Consumer::number; - void number( const double v ) - { - if( !std::isfinite( v ) ) { - if( std::isnan( v ) ) { - Consumer::string( "NaN" ); - } - else if( v > 0 ) { - Consumer::string( "Infinity" ); - } - else { - Consumer::string( "-Infinity" ); - } - } - else { - Consumer::number( v ); - } + void number( const double v ) + { + if( !std::isfinite( v ) ) { + if( std::isnan( v ) ) { + Consumer::string( "NaN" ); } - }; - - } // namespace events - - } // namespace json - -} // namespace tao + else if( v > 0 ) { + Consumer::string( "Infinity" ); + } + else { + Consumer::string( "-Infinity" ); + } + } + else { + Consumer::number( v ); + } + } + }; + +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/parse_file.hpp b/include/tao/json/events/parse_file.hpp deleted file mode 100644 index 3673fa13..00000000 --- a/include/tao/json/events/parse_file.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_PARSE_FILE_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_PARSE_FILE_HPP - -#include - -#include "../internal/action.hpp" -#include "../internal/control.hpp" -#include "../internal/grammar.hpp" - -#include "../external/pegtl/file_input.hpp" - -namespace tao -{ - namespace json - { - namespace events - { - // Events producer to parse a file containing a JSON string representation. - - template< typename T, typename Consumer > - void parse_file( Consumer& consumer, T&& filename ) - { - json_pegtl::file_input< json_pegtl::tracking_mode::LAZY > in( std::forward< T >( filename ) ); - json_pegtl::parse< internal::grammar, internal::action, internal::control >( in, consumer ); - } - - } // namespace events - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/events/prefer_signed.hpp b/include/tao/json/events/prefer_signed.hpp index 779774b3..3df0e979 100644 --- a/include/tao/json/events/prefer_signed.hpp +++ b/include/tao/json/events/prefer_signed.hpp @@ -1,40 +1,32 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_PREFER_SIGNED_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_PREFER_SIGNED_HPP +#ifndef TAO_JSON_EVENTS_PREFER_SIGNED_HPP +#define TAO_JSON_EVENTS_PREFER_SIGNED_HPP #include -namespace tao +namespace tao::json::events { - namespace json + template< typename Consumer > + struct prefer_signed + : Consumer { - namespace events - { - template< typename Consumer > - struct prefer_signed - : public Consumer - { - using Consumer::Consumer; - - using Consumer::number; - - void number( const std::uint64_t v ) - { - if( v <= 9223372036854775807ull ) { - Consumer::number( std::int64_t( v ) ); - } - else { - Consumer::number( v ); - } - } - }; + using Consumer::Consumer; - } // namespace events + using Consumer::number; - } // namespace json - -} // namespace tao + void number( const std::uint64_t v ) + { + if( v <= 9223372036854775807ULL ) { + Consumer::number( std::int64_t( v ) ); + } + else { + Consumer::number( v ); + } + } + }; + +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/prefer_unsigned.hpp b/include/tao/json/events/prefer_unsigned.hpp index 780d58c9..1e082a83 100644 --- a/include/tao/json/events/prefer_unsigned.hpp +++ b/include/tao/json/events/prefer_unsigned.hpp @@ -1,40 +1,32 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_PREFER_UNSIGNED_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_PREFER_UNSIGNED_HPP +#ifndef TAO_JSON_EVENTS_PREFER_UNSIGNED_HPP +#define TAO_JSON_EVENTS_PREFER_UNSIGNED_HPP #include -namespace tao +namespace tao::json::events { - namespace json + template< typename Consumer > + struct prefer_unsigned + : Consumer { - namespace events - { - template< typename Consumer > - struct prefer_unsigned - : public Consumer - { - using Consumer::Consumer; - - using Consumer::number; - - void number( const std::int64_t v ) - { - if( v >= 0 ) { - Consumer::number( std::uint64_t( v ) ); - } - else { - Consumer::number( v ); - } - } - }; + using Consumer::Consumer; - } // namespace events + using Consumer::number; - } // namespace json - -} // namespace tao + void number( const std::int64_t v ) + { + if( v >= 0 ) { + Consumer::number( std::uint64_t( v ) ); + } + else { + Consumer::number( v ); + } + } + }; + +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/produce.hpp b/include/tao/json/events/produce.hpp new file mode 100644 index 00000000..14d0ecf1 --- /dev/null +++ b/include/tao/json/events/produce.hpp @@ -0,0 +1,22 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_EVENTS_PRODUCE_HPP +#define TAO_JSON_EVENTS_PRODUCE_HPP + +#include +#include + +#include "../forward.hpp" + +namespace tao::json::events +{ + template< template< typename... > class Traits = traits, typename Consumer, typename T > + void produce( Consumer& c, T&& t ) + { + Traits< std::decay_t< T > >::template produce< Traits >( c, std::forward< T >( t ) ); + } + +} // namespace tao::json::events + +#endif diff --git a/include/tao/json/events/ref.hpp b/include/tao/json/events/ref.hpp index 04e37225..0c4b78d3 100644 --- a/include/tao/json/events/ref.hpp +++ b/include/tao/json/events/ref.hpp @@ -1,120 +1,111 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_REF_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_REF_HPP +#ifndef TAO_JSON_EVENTS_REF_HPP +#define TAO_JSON_EVENTS_REF_HPP #include #include -namespace tao +namespace tao::json::events { - namespace json + template< typename Consumer > + class ref { - namespace events - { - template< typename Consumer > - class ref - { - private: - Consumer& r_; - - public: - explicit ref( Consumer& r ) noexcept - : r_( r ) - { - } - - void null() noexcept( noexcept( r_.null() ) ) - { - r_.null(); - } - - template< typename T > - void boolean( T&& v ) noexcept( noexcept( r_.boolean( std::forward< T >( v ) ) ) ) - { - r_.boolean( std::forward< T >( v ) ); - } - - template< typename T > - void number( T&& v ) noexcept( noexcept( r_.number( std::forward< T >( v ) ) ) ) - { - r_.number( std::forward< T >( v ) ); - } - - template< typename T > - void string( T&& v ) noexcept( noexcept( r_.string( std::forward< T >( v ) ) ) ) - { - r_.string( std::forward< T >( v ) ); - } - - template< typename T > - void binary( T&& v ) noexcept( noexcept( r_.binary( std::forward< T >( v ) ) ) ) - { - r_.binary( std::forward< T >( v ) ); - } - - void begin_array() noexcept( noexcept( r_.begin_array() ) ) - { - r_.begin_array(); - } - - void begin_array( const std::size_t size ) noexcept( noexcept( r_.begin_array( size ) ) ) - { - r_.begin_array( size ); - } - - void element() noexcept( noexcept( r_.element() ) ) - { - r_.element(); - } - - void end_array() noexcept( noexcept( r_.end_array() ) ) - { - r_.end_array(); - } - - void end_array( const std::size_t size ) noexcept( noexcept( r_.end_array( size ) ) ) - { - r_.end_array( size ); - } - - void begin_object() noexcept( noexcept( r_.begin_object() ) ) - { - r_.begin_object(); - } - - void begin_object( const std::size_t size ) noexcept( noexcept( r_.begin_object( size ) ) ) - { - r_.begin_object( size ); - } - - template< typename T > - void key( T&& v ) noexcept( noexcept( r_.key( std::forward< T >( v ) ) ) ) - { - r_.key( std::forward< T >( v ) ); - } - - void member() noexcept( noexcept( r_.member() ) ) - { - r_.member(); - } - - void end_object() noexcept( noexcept( r_.end_object() ) ) - { - r_.end_object(); - } - - void end_object( const std::size_t size ) noexcept( noexcept( r_.end_object( size ) ) ) - { - r_.end_object( size ); - } - }; - - } // namespace events - - } // namespace json - -} // namespace tao + private: + Consumer& r_; + + public: + explicit ref( Consumer& r ) noexcept + : r_( r ) + {} + + void null() noexcept( noexcept( r_.null() ) ) + { + r_.null(); + } + + template< typename T > + void boolean( T&& v ) noexcept( noexcept( r_.boolean( std::forward< T >( v ) ) ) ) + { + r_.boolean( std::forward< T >( v ) ); + } + + template< typename T > + void number( T&& v ) noexcept( noexcept( r_.number( std::forward< T >( v ) ) ) ) + { + r_.number( std::forward< T >( v ) ); + } + + template< typename T > + void string( T&& v ) noexcept( noexcept( r_.string( std::forward< T >( v ) ) ) ) + { + r_.string( std::forward< T >( v ) ); + } + + template< typename T > + void binary( T&& v ) noexcept( noexcept( r_.binary( std::forward< T >( v ) ) ) ) + { + r_.binary( std::forward< T >( v ) ); + } + + void begin_array() noexcept( noexcept( r_.begin_array() ) ) + { + r_.begin_array(); + } + + void begin_array( const std::size_t size ) noexcept( noexcept( r_.begin_array( size ) ) ) + { + r_.begin_array( size ); + } + + void element() noexcept( noexcept( r_.element() ) ) + { + r_.element(); + } + + void end_array() noexcept( noexcept( r_.end_array() ) ) + { + r_.end_array(); + } + + void end_array( const std::size_t size ) noexcept( noexcept( r_.end_array( size ) ) ) + { + r_.end_array( size ); + } + + void begin_object() noexcept( noexcept( r_.begin_object() ) ) + { + r_.begin_object(); + } + + void begin_object( const std::size_t size ) noexcept( noexcept( r_.begin_object( size ) ) ) + { + r_.begin_object( size ); + } + + template< typename T > + void key( T&& v ) noexcept( noexcept( r_.key( std::forward< T >( v ) ) ) ) + { + r_.key( std::forward< T >( v ) ); + } + + void member() noexcept( noexcept( r_.member() ) ) + { + r_.member(); + } + + void end_object() noexcept( noexcept( r_.end_object() ) ) + { + r_.end_object(); + } + + void end_object( const std::size_t size ) noexcept( noexcept( r_.end_object( size ) ) ) + { + r_.end_object( size ); + } + }; + +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/statistics.hpp b/include/tao/json/events/statistics.hpp new file mode 100644 index 00000000..895b2ce6 --- /dev/null +++ b/include/tao/json/events/statistics.hpp @@ -0,0 +1,112 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_EVENTS_STATISTICS_HPP +#define TAO_JSON_EVENTS_STATISTICS_HPP + +#include +#include +#include +#include +#include +#include + +#include "../binary_view.hpp" + +namespace tao::json::events +{ + struct statistics + { + std::size_t null_count = 0; + std::size_t true_count = 0; + std::size_t false_count = 0; + + std::size_t signed_count = 0; + std::size_t unsigned_count = 0; + std::size_t double_count = 0; + + std::size_t string_count = 0; + std::size_t string_lengths = 0; + std::size_t key_count = 0; + std::size_t key_lengths = 0; + std::size_t binary_count = 0; + std::size_t binary_lengths = 0; + + std::size_t array_count = 0; + std::size_t array_elements = 0; + std::size_t object_count = 0; + std::size_t object_members = 0; + + void null() noexcept + { + ++null_count; + } + + void boolean( const bool v ) noexcept + { + ++( v ? true_count : false_count ); + } + + void number( const std::int64_t /*unused*/ ) noexcept + { + ++signed_count; + } + + void number( const std::uint64_t /*unused*/ ) noexcept + { + ++unsigned_count; + } + + void number( const double /*unused*/ ) noexcept + { + ++double_count; + } + + void string( const std::string_view v ) noexcept + { + ++string_count; + string_lengths += v.size(); + } + + void binary( const tao::binary_view v ) noexcept + { + ++binary_count; + binary_lengths += v.size(); + } + + void begin_array( const std::size_t /*unused*/ = 0 ) noexcept + { + ++array_count; + } + + void element() noexcept + { + ++array_elements; + } + + void end_array( const std::size_t /*unused*/ = 0 ) noexcept + {} + + void begin_object( const std::size_t /*unused*/ = 0 ) noexcept + { + ++object_count; + } + + void key( const std::string_view v ) noexcept + { + ++key_count; + key_lengths += v.size(); + } + + void member() noexcept + { + ++object_members; + } + + void end_object( const std::size_t /*unused*/ = 0 ) noexcept + {} + }; + +} // namespace tao::json::events + +#endif diff --git a/include/tao/json/events/tee.hpp b/include/tao/json/events/tee.hpp index 57e42701..b1cd1f93 100644 --- a/include/tao/json/events/tee.hpp +++ b/include/tao/json/events/tee.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_TEE_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_TEE_HPP +#ifndef TAO_JSON_EVENTS_TEE_HPP +#define TAO_JSON_EVENTS_TEE_HPP #include #include @@ -13,405 +13,374 @@ #include "discard.hpp" -#include "../external/pegtl/internal/integer_sequence.hpp" - -namespace tao +namespace tao::json { - namespace json + namespace internal { - namespace internal + template< typename T > + struct strip_reference_wrapper + { + using type = T; + }; + + template< typename T > + struct strip_reference_wrapper< std::reference_wrapper< T > > + { + using type = T&; + }; + + template< typename T > + using decay_and_strip_t = typename strip_reference_wrapper< std::decay_t< T > >::type; + + template< typename > + struct events_apply; + + template<> + struct events_apply< std::index_sequence<> > { - template< typename T > - struct strip_reference_wrapper - { - using type = T; - }; - - template< typename T > - struct strip_reference_wrapper< std::reference_wrapper< T > > - { - using type = T&; - }; - - template< typename T > - using decay_and_strip_t = typename strip_reference_wrapper< typename std::decay< T >::type >::type; - - template< typename > - struct events_apply; - - template<> - struct events_apply< TAOCPP_JSON_PEGTL_NAMESPACE::internal::index_sequence<> > - { - template< typename... Ts > - static void null( std::tuple< Ts... >& ) - { - } - - template< typename... Ts > - static void boolean( std::tuple< Ts... >&, const bool ) - { - } - - template< typename... Ts > - static void number( std::tuple< Ts... >&, const std::int64_t ) - { - } - - template< typename... Ts > - static void number( std::tuple< Ts... >&, const std::uint64_t ) - { - } - - template< typename... Ts > - static void number( std::tuple< Ts... >&, const double ) - { - } - - template< typename... Ts > - static void string( std::tuple< Ts... >&, const tao::string_view ) - { - } - - template< typename... Ts > - static void binary( std::tuple< Ts... >&, const tao::byte_view ) - { - } - - template< typename... Ts > - static void begin_array( std::tuple< Ts... >& ) - { - } - - template< typename... Ts > - static void begin_array( std::tuple< Ts... >&, const std::size_t ) - { - } - - template< typename... Ts > - static void element( std::tuple< Ts... >& ) - { - } - - template< typename... Ts > - static void end_array( std::tuple< Ts... >& ) - { - } - - template< typename... Ts > - static void end_array( std::tuple< Ts... >&, const std::size_t ) - { - } - - template< typename... Ts > - static void begin_object( std::tuple< Ts... >& ) - { - } - - template< typename... Ts > - static void begin_object( std::tuple< Ts... >&, const std::size_t ) - { - } - - template< typename... Ts > - static void key( std::tuple< Ts... >&, const tao::string_view ) - { - } - - template< typename... Ts > - static void member( std::tuple< Ts... >& ) - { - } - - template< typename... Ts > - static void end_object( std::tuple< Ts... >& ) - { - } - - template< typename... Ts > - static void end_object( std::tuple< Ts... >&, const std::size_t ) - { - } - }; - - template< std::size_t... Is > - struct events_apply< TAOCPP_JSON_PEGTL_NAMESPACE::internal::index_sequence< Is... > > - { - using sink = bool[]; - - template< typename... Ts > - static void null( std::tuple< Ts... >& t ) - { - (void)sink{ ( std::get< Is >( t ).null(), true )... }; - } - - template< typename... Ts > - static void boolean( std::tuple< Ts... >& t, const bool v ) - { - (void)sink{ ( std::get< Is >( t ).boolean( v ), true )... }; - } - - template< typename... Ts > - static void number( std::tuple< Ts... >& t, const std::int64_t v ) - { - (void)sink{ ( std::get< Is >( t ).number( v ), true )... }; - } - - template< typename... Ts > - static void number( std::tuple< Ts... >& t, const std::uint64_t v ) - { - (void)sink{ ( std::get< Is >( t ).number( v ), true )... }; - } - - template< typename... Ts > - static void number( std::tuple< Ts... >& t, const double v ) - { - (void)sink{ ( std::get< Is >( t ).number( v ), true )... }; - } - - template< typename... Ts > - static void string( std::tuple< Ts... >& t, const tao::string_view v ) - { - (void)sink{ ( std::get< Is >( t ).string( v ), true )... }; - } - - template< typename... Ts > - static void binary( std::tuple< Ts... >& t, const tao::byte_view v ) - { - (void)sink{ ( std::get< Is >( t ).binary( v ), true )... }; - } - - template< typename... Ts > - static void begin_array( std::tuple< Ts... >& t ) - { - (void)sink{ ( std::get< Is >( t ).begin_array(), true )... }; - } - - template< typename... Ts > - static void begin_array( std::tuple< Ts... >& t, const std::size_t size ) - { - (void)sink{ ( std::get< Is >( t ).begin_array( size ), true )... }; - } - - template< typename... Ts > - static void element( std::tuple< Ts... >& t ) - { - (void)sink{ ( std::get< Is >( t ).element(), true )... }; - } - - template< typename... Ts > - static void end_array( std::tuple< Ts... >& t ) - { - (void)sink{ ( std::get< Is >( t ).end_array(), true )... }; - } - - template< typename... Ts > - static void end_array( std::tuple< Ts... >& t, const std::size_t size ) - { - (void)sink{ ( std::get< Is >( t ).end_array( size ), true )... }; - } - - template< typename... Ts > - static void begin_object( std::tuple< Ts... >& t ) - { - (void)sink{ ( std::get< Is >( t ).begin_object(), true )... }; - } - - template< typename... Ts > - static void begin_object( std::tuple< Ts... >& t, const std::size_t size ) - { - (void)sink{ ( std::get< Is >( t ).begin_object( size ), true )... }; - } - - template< typename... Ts > - static void key( std::tuple< Ts... >& t, const tao::string_view v ) - { - (void)sink{ ( std::get< Is >( t ).key( v ), true )... }; - } - - template< typename... Ts > - static void member( std::tuple< Ts... >& t ) - { - (void)sink{ ( std::get< Is >( t ).member(), true )... }; - } - - template< typename... Ts > - static void end_object( std::tuple< Ts... >& t ) - { - (void)sink{ ( std::get< Is >( t ).end_object(), true )... }; - } - - template< typename... Ts > - static void end_object( std::tuple< Ts... >& t, const std::size_t size ) - { - (void)sink{ ( std::get< Is >( t ).end_object( size ), true )... }; - } - }; - - } // namespace internal - - namespace events + template< typename... Ts > + static void null( std::tuple< Ts... >& /*unused*/ ) + {} + + template< typename... Ts > + static void boolean( std::tuple< Ts... >& /*unused*/, const bool /*unused*/ ) + {} + + template< typename... Ts > + static void number( std::tuple< Ts... >& /*unused*/, const std::int64_t /*unused*/ ) + {} + + template< typename... Ts > + static void number( std::tuple< Ts... >& /*unused*/, const std::uint64_t /*unused*/ ) + {} + + template< typename... Ts > + static void number( std::tuple< Ts... >& /*unused*/, const double /*unused*/ ) + {} + + template< typename... Ts > + static void string( std::tuple< Ts... >& /*unused*/, const std::string_view /*unused*/ ) + {} + + template< typename... Ts > + static void binary( std::tuple< Ts... >& /*unused*/, const tao::binary_view /*unused*/ ) + {} + + template< typename... Ts > + static void begin_array( std::tuple< Ts... >& /*unused*/ ) + {} + + template< typename... Ts > + static void begin_array( std::tuple< Ts... >& /*unused*/, const std::size_t /*unused*/ ) + {} + + template< typename... Ts > + static void element( std::tuple< Ts... >& /*unused*/ ) + {} + + template< typename... Ts > + static void end_array( std::tuple< Ts... >& /*unused*/ ) + {} + + template< typename... Ts > + static void end_array( std::tuple< Ts... >& /*unused*/, const std::size_t /*unused*/ ) + {} + + template< typename... Ts > + static void begin_object( std::tuple< Ts... >& /*unused*/ ) + {} + + template< typename... Ts > + static void begin_object( std::tuple< Ts... >& /*unused*/, const std::size_t /*unused*/ ) + {} + + template< typename... Ts > + static void key( std::tuple< Ts... >& /*unused*/, const std::string_view /*unused*/ ) + {} + + template< typename... Ts > + static void member( std::tuple< Ts... >& /*unused*/ ) + {} + + template< typename... Ts > + static void end_object( std::tuple< Ts... >& /*unused*/ ) + {} + + template< typename... Ts > + static void end_object( std::tuple< Ts... >& /*unused*/, const std::size_t /*unused*/ ) + {} + }; + + template< std::size_t... Is > + struct events_apply< std::index_sequence< Is... > > + { + template< typename... Ts > + static void null( std::tuple< Ts... >& t ) + { + ( std::get< Is >( t ).null(), ... ); + } + + template< typename... Ts > + static void boolean( std::tuple< Ts... >& t, const bool v ) + { + ( std::get< Is >( t ).boolean( v ), ... ); + } + + template< typename... Ts > + static void number( std::tuple< Ts... >& t, const std::int64_t v ) + { + ( std::get< Is >( t ).number( v ), ... ); + } + + template< typename... Ts > + static void number( std::tuple< Ts... >& t, const std::uint64_t v ) + { + ( std::get< Is >( t ).number( v ), ... ); + } + + template< typename... Ts > + static void number( std::tuple< Ts... >& t, const double v ) + { + ( std::get< Is >( t ).number( v ), ... ); + } + + template< typename... Ts > + static void string( std::tuple< Ts... >& t, const std::string_view v ) + { + ( std::get< Is >( t ).string( v ), ... ); + } + + template< typename... Ts > + static void binary( std::tuple< Ts... >& t, const tao::binary_view v ) + { + ( std::get< Is >( t ).binary( v ), ... ); + } + + template< typename... Ts > + static void begin_array( std::tuple< Ts... >& t ) + { + ( std::get< Is >( t ).begin_array(), ... ); + } + + template< typename... Ts > + static void begin_array( std::tuple< Ts... >& t, const std::size_t size ) + { + ( std::get< Is >( t ).begin_array( size ), ... ); + } + + template< typename... Ts > + static void element( std::tuple< Ts... >& t ) + { + ( std::get< Is >( t ).element(), ... ); + } + + template< typename... Ts > + static void end_array( std::tuple< Ts... >& t ) + { + ( std::get< Is >( t ).end_array(), ... ); + } + + template< typename... Ts > + static void end_array( std::tuple< Ts... >& t, const std::size_t size ) + { + ( std::get< Is >( t ).end_array( size ), ... ); + } + + template< typename... Ts > + static void begin_object( std::tuple< Ts... >& t ) + { + ( std::get< Is >( t ).begin_object(), ... ); + } + + template< typename... Ts > + static void begin_object( std::tuple< Ts... >& t, const std::size_t size ) + { + ( std::get< Is >( t ).begin_object( size ), ... ); + } + + template< typename... Ts > + static void key( std::tuple< Ts... >& t, const std::string_view v ) + { + ( std::get< Is >( t ).key( v ), ... ); + } + + template< typename... Ts > + static void member( std::tuple< Ts... >& t ) + { + ( std::get< Is >( t ).member(), ... ); + } + + template< typename... Ts > + static void end_object( std::tuple< Ts... >& t ) + { + ( std::get< Is >( t ).end_object(), ... ); + } + + template< typename... Ts > + static void end_object( std::tuple< Ts... >& t, const std::size_t size ) + { + ( std::get< Is >( t ).end_object( size ), ... ); + } + }; + + } // namespace internal + + namespace events + { + // Events consumer that forwards to multiple nested consumers. + + template< typename... Ts > + class tee { - // Events consumer that forwards to multiple nested consumers. - - template< typename... Ts > - class tee - { - private: - static constexpr std::size_t S = sizeof...( Ts ); - - using I = TAOCPP_JSON_PEGTL_NAMESPACE::internal::make_index_sequence< S >; - using H = TAOCPP_JSON_PEGTL_NAMESPACE::internal::make_index_sequence< S - 1 >; - - std::tuple< Ts... > ts; - - public: - template< typename... Us > - tee( Us&&... us ) - : ts( std::forward< Us >( us )... ) - { - } - - void null() - { - internal::events_apply< I >::null( ts ); - } - - void boolean( const bool v ) - { - internal::events_apply< I >::boolean( ts, v ); - } - - void number( const std::int64_t v ) - { - internal::events_apply< I >::number( ts, v ); - } - - void number( const std::uint64_t v ) - { - internal::events_apply< I >::number( ts, v ); - } - - void number( const double v ) - { - internal::events_apply< I >::number( ts, v ); - } - - void string( const tao::string_view v ) - { - internal::events_apply< I >::string( ts, v ); - } - - void string( const char* v ) - { - internal::events_apply< I >::string( ts, v ); - } - - void string( std::string&& v ) - { - internal::events_apply< H >::string( ts, v ); - std::get< S - 1 >( ts ).string( std::move( v ) ); - } + private: + static constexpr std::size_t S = sizeof...( Ts ); + + using I = std::make_index_sequence< S >; + using H = std::make_index_sequence< S - 1 >; + + std::tuple< Ts... > ts; + + public: + template< typename... Us > + explicit tee( Us&&... us ) + : ts( std::forward< Us >( us )... ) + {} + + void null() + { + internal::events_apply< I >::null( ts ); + } + + void boolean( const bool v ) + { + internal::events_apply< I >::boolean( ts, v ); + } + + void number( const std::int64_t v ) + { + internal::events_apply< I >::number( ts, v ); + } + + void number( const std::uint64_t v ) + { + internal::events_apply< I >::number( ts, v ); + } + + void number( const double v ) + { + internal::events_apply< I >::number( ts, v ); + } - void binary( const tao::byte_view v ) - { - internal::events_apply< I >::binary( ts, v ); - } + void string( const std::string_view v ) + { + internal::events_apply< I >::string( ts, v ); + } - void binary( std::vector< tao::byte >&& v ) - { - internal::events_apply< H >::binary( ts, v ); - std::get< S - 1 >( ts ).binary( std::move( v ) ); - } + void string( const char* v ) + { + internal::events_apply< I >::string( ts, v ); + } - void begin_array() - { - internal::events_apply< I >::begin_array( ts ); - } + void string( std::string&& v ) + { + internal::events_apply< H >::string( ts, v ); + std::get< S - 1 >( ts ).string( std::move( v ) ); + } - void begin_array( const std::size_t size ) - { - internal::events_apply< I >::begin_array( ts, size ); - } + void binary( const tao::binary_view v ) + { + internal::events_apply< I >::binary( ts, v ); + } - void element() - { - internal::events_apply< I >::element( ts ); - } + void binary( std::vector< std::byte >&& v ) + { + internal::events_apply< H >::binary( ts, v ); + std::get< S - 1 >( ts ).binary( std::move( v ) ); + } - void end_array() - { - internal::events_apply< I >::end_array( ts ); - } + void begin_array() + { + internal::events_apply< I >::begin_array( ts ); + } - void end_array( const std::size_t size ) - { - internal::events_apply< I >::end_array( ts, size ); - } + void begin_array( const std::size_t size ) + { + internal::events_apply< I >::begin_array( ts, size ); + } - void begin_object() - { - internal::events_apply< I >::begin_object( ts ); - } + void element() + { + internal::events_apply< I >::element( ts ); + } - void begin_object( const std::size_t size ) - { - internal::events_apply< I >::begin_object( ts, size ); - } - - void key( const tao::string_view v ) - { - internal::events_apply< I >::key( ts, v ); - } - - void key( const char* v ) - { - internal::events_apply< I >::key( ts, v ); - } - - void key( std::string&& v ) - { - internal::events_apply< H >::key( ts, v ); - std::get< S - 1 >( ts ).key( std::move( v ) ); - } - - void member() - { - internal::events_apply< I >::member( ts ); - } - - void end_object() - { - internal::events_apply< I >::end_object( ts ); - } - - void end_object( const std::size_t size ) - { - internal::events_apply< I >::end_object( ts, size ); - } - }; - - template<> - class tee<> - : public discard - { - }; + void end_array() + { + internal::events_apply< I >::end_array( ts ); + } - template< typename... T > - tee< internal::decay_and_strip_t< T >... > make_tee( T&&... t ) + void end_array( const std::size_t size ) { - return tee< internal::decay_and_strip_t< T >... >( std::forward< T >( t )... ); + internal::events_apply< I >::end_array( ts, size ); } - - template< typename... T > - tee< T&... > tie( T&... t ) + + void begin_object() { - return tee< T&... >( t... ); + internal::events_apply< I >::begin_object( ts ); } - } // namespace events + void begin_object( const std::size_t size ) + { + internal::events_apply< I >::begin_object( ts, size ); + } + + void key( const std::string_view v ) + { + internal::events_apply< I >::key( ts, v ); + } + + void key( const char* v ) + { + internal::events_apply< I >::key( ts, v ); + } + + void key( std::string&& v ) + { + internal::events_apply< H >::key( ts, v ); + std::get< S - 1 >( ts ).key( std::move( v ) ); + } + + void member() + { + internal::events_apply< I >::member( ts ); + } + + void end_object() + { + internal::events_apply< I >::end_object( ts ); + } + + void end_object( const std::size_t size ) + { + internal::events_apply< I >::end_object( ts, size ); + } + }; + + template<> + class tee<> + : public discard + {}; + + template< typename... Ts > + tee( Ts&&... )->tee< internal::decay_and_strip_t< Ts >... >; + + template< typename... T > + [[nodiscard]] tee< T&... > tie( T&... t ) + { + return tee< T&... >( t... ); + } - } // namespace json + } // namespace events -} // namespace tao +} // namespace tao::json #endif diff --git a/include/tao/json/events/to_pretty_stream.hpp b/include/tao/json/events/to_pretty_stream.hpp index e188fae1..9e7b5698 100644 --- a/include/tao/json/events/to_pretty_stream.hpp +++ b/include/tao/json/events/to_pretty_stream.hpp @@ -1,170 +1,172 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_TO_PRETTY_STREAM_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_TO_PRETTY_STREAM_HPP +#ifndef TAO_JSON_EVENTS_TO_PRETTY_STREAM_HPP +#define TAO_JSON_EVENTS_TO_PRETTY_STREAM_HPP #include #include #include +#include #include #include #include +#include +#include #include -#include "../external/byte.hpp" -#include "../external/double.hpp" +#include "../binary_view.hpp" + +#include "../external/itoa.hpp" +#include "../external/ryu.hpp" #include "../internal/escape.hpp" -namespace tao +namespace tao::json::events { - namespace json + // Events consumer to build a JSON pretty string representation. + + class to_pretty_stream { - namespace events + protected: + std::ostream& os; + const std::size_t indent; + std::string eol; + + bool first = true; + bool after_key = true; + + void next() + { + if( !first ) { + os.put( ',' ); + } + if( after_key ) { + after_key = false; + } + else { + os << eol; + } + } + + public: + template< typename S > + to_pretty_stream( std::ostream& in_os, const std::size_t in_indent, S&& in_eol ) + : os( in_os ), + indent( in_indent ), + eol( std::forward< S >( in_eol ) ) + {} + + to_pretty_stream( std::ostream& in_os, const std::size_t in_indent ) + : to_pretty_stream( in_os, in_indent, "\n" ) + {} + + void null() + { + next(); + os.write( "null", 4 ); + } + + void boolean( const bool v ) + { + next(); + if( v ) { + os.write( "true", 4 ); + } + else { + os.write( "false", 5 ); + } + } + + void number( const std::int64_t v ) + { + next(); + itoa::i64tos( os, v ); + } + + void number( const std::uint64_t v ) + { + next(); + itoa::u64tos( os, v ); + } + + void number( const double v ) + { + next(); + if( !std::isfinite( v ) ) { + // if this throws, consider using non_finite_to_* transformers + throw std::runtime_error( "non-finite double value invalid for JSON string representation" ); + } + ryu::d2s_stream( os, v ); + } + + void string( const std::string_view v ) + { + next(); + os.put( '"' ); + internal::escape( os, v ); + os.put( '"' ); + } + + void binary( const tao::binary_view /*unused*/ ) + { + // if this throws, consider using binary_to_* transformers + throw std::runtime_error( "binary data invalid for JSON string representation" ); + } + + void begin_array( const std::size_t /*unused*/ = 0 ) + { + next(); + os.put( '[' ); + eol.resize( eol.size() + indent, os.fill() ); + first = true; + } + + void element() noexcept + { + first = false; + } + + void end_array( const std::size_t /*unused*/ = 0 ) + { + eol.resize( eol.size() - indent ); + if( !first ) { + os << eol; + } + os.put( ']' ); + } + + void begin_object( const std::size_t /*unused*/ = 0 ) + { + next(); + os.put( '{' ); + eol.resize( eol.size() + indent, os.fill() ); + first = true; + } + + void key( const std::string_view v ) + { + string( v ); + os.write( ": ", 2 ); + first = true; + after_key = true; + } + + void member() noexcept + { + first = false; + } + + void end_object( const std::size_t /*unused*/ = 0 ) { - // Events consumer to build a JSON pretty string representation. - - class to_pretty_stream - { - protected: - std::ostream& os; - const std::size_t indent; - - std::string current = "\n"; - bool first = true; - bool after_key = true; - - void next() - { - if( !first ) { - os.put( ',' ); - } - if( after_key ) { - after_key = false; - } - else { - os << current; - } - } - - public: - to_pretty_stream( std::ostream& in_os, const std::size_t in_indent ) - : os( in_os ), - indent( in_indent ), - first( true ) - { - } - - void null() - { - next(); - os.write( "null", 4 ); - } - - void boolean( const bool v ) - { - next(); - if( v ) { - os.write( "true", 4 ); - } - else { - os.write( "false", 5 ); - } - } - - void number( const std::int64_t v ) - { - next(); - os << v; - } - - void number( const std::uint64_t v ) - { - next(); - os << v; - } - - void number( const double v ) - { - next(); - if( !std::isfinite( v ) ) { - throw std::runtime_error( "non-finite double value invalid for JSON string representation" ); - } - json_double_conversion::Dtostr( os, v ); - } - - void string( const tao::string_view v ) - { - next(); - os.put( '"' ); - internal::escape( os, v ); - os.put( '"' ); - } - - void binary( const tao::byte_view ) - { - // if this throws, consider using binary_to_* wrappers - throw std::runtime_error( "binary data invalid for JSON string representation" ); - } - - void begin_array( const std::size_t = 0 ) - { - next(); - os.put( '[' ); - current.resize( current.size() + indent, ' ' ); - first = true; - } - - void element() noexcept - { - first = false; - } - - void end_array( const std::size_t = 0 ) - { - current.resize( current.size() - indent ); - if( !first ) { - os << current; - } - os.put( ']' ); - } - - void begin_object( const std::size_t = 0 ) - { - next(); - os.put( '{' ); - current.resize( current.size() + indent, ' ' ); - first = true; - } - - void key( const tao::string_view v ) - { - string( v ); - os.write( ": ", 2 ); - first = true; - after_key = true; - } - - void member() noexcept - { - first = false; - } - - void end_object( const std::size_t = 0 ) - { - current.resize( current.size() - indent ); - if( !first ) { - os << current; - } - os.put( '}' ); - } - }; - - } // namespace events - - } // namespace json - -} // namespace tao + eol.resize( eol.size() - indent ); + if( !first ) { + os << eol; + } + os.put( '}' ); + } + }; + +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/to_stream.hpp b/include/tao/json/events/to_stream.hpp index b469c6f3..a144622e 100644 --- a/include/tao/json/events/to_stream.hpp +++ b/include/tao/json/events/to_stream.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_TO_STREAM_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_TO_STREAM_HPP +#ifndef TAO_JSON_EVENTS_TO_STREAM_HPP +#define TAO_JSON_EVENTS_TO_STREAM_HPP #include #include @@ -10,140 +10,133 @@ #include #include #include +#include -#include "../byte_view.hpp" +#include "../binary_view.hpp" -#include "../external/double.hpp" -#include "../external/string_view.hpp" +#include "../external/itoa.hpp" +#include "../external/ryu.hpp" #include "../internal/escape.hpp" -namespace tao +namespace tao::json::events { - namespace json + // Events consumer to build a JSON string representation. + + class to_stream { - namespace events + protected: + std::ostream& os; + bool first; + + void next() + { + if( !first ) { + os.put( ',' ); + } + } + + public: + explicit to_stream( std::ostream& in_os ) noexcept + : os( in_os ), + first( true ) + {} + + void null() + { + next(); + os.write( "null", 4 ); + } + + void boolean( const bool v ) + { + next(); + if( v ) { + os.write( "true", 4 ); + } + else { + os.write( "false", 5 ); + } + } + + void number( const std::int64_t v ) + { + next(); + itoa::i64tos( os, v ); + } + + void number( const std::uint64_t v ) + { + next(); + itoa::u64tos( os, v ); + } + + void number( const double v ) + { + next(); + if( !std::isfinite( v ) ) { + // if this throws, consider using non_finite_to_* transformers + throw std::runtime_error( "non-finite double value invalid for JSON string representation" ); + } + ryu::d2s_stream( os, v ); + } + + void string( const std::string_view v ) + { + next(); + os.put( '"' ); + internal::escape( os, v ); + os.put( '"' ); + } + + void binary( const tao::binary_view /*unused*/ ) + { + // if this throws, consider using binary_to_* transformers + throw std::runtime_error( "binary data invalid for JSON string representation" ); + } + + void begin_array( const std::size_t /*unused*/ = 0 ) + { + next(); + os.put( '[' ); + first = true; + } + + void element() noexcept + { + first = false; + } + + void end_array( const std::size_t /*unused*/ = 0 ) + { + os.put( ']' ); + } + + void begin_object( const std::size_t /*unused*/ = 0 ) { - // Events consumer to build a JSON string representation. - - class to_stream - { - protected: - std::ostream& os; - bool first; - - void next() - { - if( !first ) { - os.put( ',' ); - } - } - - public: - explicit to_stream( std::ostream& in_os ) noexcept - : os( in_os ), - first( true ) - { - } - - void null() - { - next(); - os.write( "null", 4 ); - } - - void boolean( const bool v ) - { - next(); - if( v ) { - os.write( "true", 4 ); - } - else { - os.write( "false", 5 ); - } - } - - void number( const std::int64_t v ) - { - next(); - os << v; - } - - void number( const std::uint64_t v ) - { - next(); - os << v; - } - - void number( const double v ) - { - next(); - if( !std::isfinite( v ) ) { - throw std::runtime_error( "non-finite double value invalid for JSON string representation" ); - } - json_double_conversion::Dtostr( os, v ); - } - - void string( const tao::string_view v ) - { - next(); - os.put( '"' ); - internal::escape( os, v ); - os.put( '"' ); - } - - void binary( const tao::byte_view ) - { - // if this throws, consider using binary_to_* wrappers - throw std::runtime_error( "binary data invalid for JSON string representation" ); - } - - void begin_array( const std::size_t = 0 ) - { - next(); - os.put( '[' ); - first = true; - } - - void element() noexcept - { - first = false; - } - - void end_array( const std::size_t = 0 ) - { - os.put( ']' ); - } - - void begin_object( const std::size_t = 0 ) - { - next(); - os.put( '{' ); - first = true; - } - - void key( const tao::string_view v ) - { - string( v ); - os.put( ':' ); - first = true; - } - - void member() noexcept - { - first = false; - } - - void end_object( const std::size_t = 0 ) - { - os.put( '}' ); - } - }; - - } // namespace events - - } // namespace json - -} // namespace tao + next(); + os.put( '{' ); + first = true; + } + + void key( const std::string_view v ) + { + string( v ); + os.put( ':' ); + first = true; + } + + void member() noexcept + { + first = false; + } + + void end_object( const std::size_t /*unused*/ = 0 ) + { + os.put( '}' ); + } + }; + +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/to_string.hpp b/include/tao/json/events/to_string.hpp index d91d8e2f..972f09f3 100644 --- a/include/tao/json/events/to_string.hpp +++ b/include/tao/json/events/to_string.hpp @@ -1,42 +1,33 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_TO_STRING_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_TO_STRING_HPP +#ifndef TAO_JSON_EVENTS_TO_STRING_HPP +#define TAO_JSON_EVENTS_TO_STRING_HPP #include #include #include "to_stream.hpp" -namespace tao +namespace tao::json::events { - namespace json - { - namespace events - { - // Events consumer to build a JSON string representation. - - struct to_string - : public to_stream - { - std::ostringstream oss; + // Events consumer to build a JSON string representation. - to_string() - : to_stream( oss ) - { - } - - std::string value() const - { - return oss.str(); - } - }; + struct to_string + : to_stream + { + std::ostringstream oss; - } // namespace events + to_string() + : to_stream( oss ) + {} - } // namespace json + [[nodiscard]] std::string value() const + { + return oss.str(); + } + }; -} // namespace tao +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/to_value.hpp b/include/tao/json/events/to_value.hpp index 9417b9a0..4d47d555 100644 --- a/include/tao/json/events/to_value.hpp +++ b/include/tao/json/events/to_value.hpp @@ -1,152 +1,137 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_TO_VALUE_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_TO_VALUE_HPP +#ifndef TAO_JSON_EVENTS_TO_VALUE_HPP +#define TAO_JSON_EVENTS_TO_VALUE_HPP #include #include #include +#include #include #include -#include "../external/byte.hpp" -#include "../external/string_view.hpp" - -#include "../byte_view.hpp" +#include "../binary_view.hpp" #include "../value.hpp" -namespace tao +namespace tao::json::events { - namespace json + // Events consumer to build a JSON Value. + + template< template< typename... > class Traits > + struct to_basic_value { - namespace events - { - // Events consumer to build a JSON Value. - - template< template< typename... > class Traits > - class to_basic_value - { - private: - std::vector< basic_value< Traits > > stack_; - std::vector< std::string > keys_; - - public: - basic_value< Traits > value; - - void null() - { - value.unsafe_assign_null(); - } - - void boolean( const bool v ) - { - value.unsafe_assign_bool( v ); - } - - void number( const std::int64_t v ) - { - value.unsafe_assign_signed( v ); - } - - void number( const std::uint64_t v ) - { - value.unsafe_assign_unsigned( v ); - } - - void number( const double v ) - { - value.unsafe_assign_double( v ); - } - - void string( const tao::string_view v ) - { - value.unsafe_emplace_string( v.data(), v.size() ); - } - - void string( const char* v ) - { - value.unsafe_emplace_string( v ); - } - - void string( std::string&& v ) - { - value.unsafe_assign_string( std::move( v ) ); - } - - void binary( const tao::byte_view v ) - { - value.unsafe_emplace_binary( v.begin(), v.end() ); - } - - void binary( std::vector< tao::byte >&& v ) - { - value.unsafe_assign_binary( std::move( v ) ); - } - - void begin_array() - { - stack_.push_back( empty_array ); - } - - void begin_array( const std::size_t size ) - { - begin_array(); - stack_.back().unsafe_get_array().reserve( size ); - } - - void element() - { - stack_.back().unsafe_emplace_back( std::move( value ) ); - value.discard(); - } - - void end_array( const std::size_t = 0 ) - { - value = std::move( stack_.back() ); - stack_.pop_back(); - } - - void begin_object( const std::size_t = 0 ) - { - stack_.push_back( empty_object ); - } - - void key( const tao::string_view v ) - { - keys_.emplace_back( v.data(), v.size() ); - } - - void key( const char* v ) - { - keys_.emplace_back( v ); - } - - void key( std::string&& v ) - { - keys_.push_back( std::move( v ) ); - } - - void member() - { - stack_.back().unsafe_emplace( std::move( keys_.back() ), std::move( value ) ); - value.discard(); - keys_.pop_back(); - } - - void end_object( const std::size_t = 0 ) - { - value = std::move( stack_.back() ); - stack_.pop_back(); - } - }; - - using to_value = to_basic_value< traits >; - - } // namespace events - - } // namespace json - -} // namespace tao + std::vector< basic_value< Traits > > stack_; + std::vector< std::string > keys_; + basic_value< Traits > value; + + void null() + { + value.set_null(); + } + + void boolean( const bool v ) + { + value.set_boolean( v ); + } + + void number( const std::int64_t v ) + { + value.set_signed( v ); + } + + void number( const std::uint64_t v ) + { + value.set_unsigned( v ); + } + + void number( const double v ) + { + value.set_double( v ); + } + + void string( const std::string_view v ) + { + value.emplace_string( v ); + } + + void string( const char* v ) + { + value.emplace_string( v ); + } + + void string( std::string&& v ) + { + value.emplace_string( std::move( v ) ); + } + + void binary( const tao::binary_view v ) + { + value.emplace_binary( v.begin(), v.end() ); + } + + void binary( std::vector< std::byte >&& v ) + { + value.emplace_binary( std::move( v ) ); + } + + void begin_array() + { + stack_.emplace_back( empty_array ); + } + + void begin_array( const std::size_t size ) + { + begin_array(); + stack_.back().get_array().reserve( size ); + } + + void element() + { + stack_.back().emplace_back( std::move( value ) ); + } + + void end_array( const std::size_t /*unused*/ = 0 ) + { + value = std::move( stack_.back() ); + stack_.pop_back(); + } + + void begin_object( const std::size_t /*unused*/ = 0 ) + { + stack_.emplace_back( empty_object ); + } + + void key( const std::string_view v ) + { + keys_.emplace_back( v ); + } + + void key( const char* v ) + { + keys_.emplace_back( v ); + } + + void key( std::string&& v ) + { + keys_.emplace_back( std::move( v ) ); + } + + void member() + { + stack_.back().try_emplace( std::move( keys_.back() ), std::move( value ) ); + keys_.pop_back(); + } + + void end_object( const std::size_t /*unused*/ = 0 ) + { + value = std::move( stack_.back() ); + stack_.pop_back(); + } + }; + + using to_value = to_basic_value< traits >; + +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/transformer.hpp b/include/tao/json/events/transformer.hpp index 4125d9e7..564a3896 100644 --- a/include/tao/json/events/transformer.hpp +++ b/include/tao/json/events/transformer.hpp @@ -1,41 +1,70 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_TRANSFORMER_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_TRANSFORMER_HPP +#ifndef TAO_JSON_EVENTS_TRANSFORMER_HPP +#define TAO_JSON_EVENTS_TRANSFORMER_HPP -namespace tao +#include + +#include "../external/pegtl/internal/always_false.hpp" + +namespace tao::json { - namespace json + namespace internal { - namespace internal + template< template< typename... > class T > + struct invalid_transformer { - template< typename Consumer, template< typename... > class... Transformer > - struct transformer; + // if this static assert is triggered there is a high chance that 'T' is + // a traits class template and you intended to call a method starting with "basic_*", + // e.g. basic_from_file< my_traits >( ... ) instead of from_file< my_traits >( ... ). + static_assert( pegtl::internal::always_false< invalid_transformer< T > >::value, "T is not a valid transformer" ); + }; - template< typename Consumer > - struct transformer< Consumer > - { - using type = Consumer; - }; + template< typename B, template< typename... > class T, typename = void > + struct check_transformer + : invalid_transformer< T > + { + using type = B; + }; - template< typename Consumer, template< typename... > class Head, template< typename... > class... Tail > - struct transformer< Consumer, Head, Tail... > - { - using type = Head< typename transformer< Consumer, Tail... >::type >; - }; + template< typename B, template< typename... > class T > + struct check_transformer< B, + T, + decltype( std::declval< T< B > >().null(), + std::declval< T< B > >().boolean( true ), + std::declval< T< B > >().number( double( 0.0 ) ), + std::declval< T< B > >().string( "" ), + std::declval< T< B > >().element(), + std::declval< T< B > >().member(), + void() ) > + { + using type = T< B >; + }; - } // namespace internal + template< typename Consumer, template< typename... > class... Transformer > + struct transformer; - namespace events + template< typename Consumer > + struct transformer< Consumer > { - template< typename Consumer, template< typename... > class... Transformer > - using transformer = typename internal::transformer< Consumer, Transformer... >::type; + using type = Consumer; + }; - } // namespace events + template< typename Consumer, template< typename... > class Head, template< typename... > class... Tail > + struct transformer< Consumer, Head, Tail... > + : check_transformer< typename transformer< Consumer, Tail... >::type, Head > + {}; + + } // namespace internal + + namespace events + { + template< typename Consumer, template< typename... > class... Transformer > + using transformer = typename internal::transformer< Consumer, Transformer... >::type; - } // namespace json + } // namespace events -} // namespace tao +} // namespace tao::json #endif diff --git a/include/tao/json/events/ubjson/from_string.hpp b/include/tao/json/events/ubjson/from_string.hpp deleted file mode 100644 index d685f36f..00000000 --- a/include/tao/json/events/ubjson/from_string.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_UBJSON_FROM_STRING_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_UBJSON_FROM_STRING_HPP - -#include "../../external/pegtl/parse.hpp" -#include "../../external/string_view.hpp" - -#include "grammar.hpp" - -namespace tao -{ - namespace json - { - namespace events - { - namespace ubjson - { - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t byte_in_line = 0 ) - { - json_pegtl::memory_input< json_pegtl::tracking_mode::LAZY, json_pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::ubjson::from_string", byte, line, byte_in_line ); - json_pegtl::parse< ubjson::grammar >( in, consumer ); - } - - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) - { - ubjson::from_string( consumer, data, size, source.c_str(), byte, line, column ); - } - - template< typename Consumer, typename... Ts > - void from_string( Consumer& consumer, const tao::string_view data, Ts&&... ts ) - { - ubjson::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); - } - - } // namespace ubjson - - } // namespace events - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/events/ubjson/grammar.hpp b/include/tao/json/events/ubjson/grammar.hpp deleted file mode 100644 index f8fff13e..00000000 --- a/include/tao/json/events/ubjson/grammar.hpp +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_UBJSON_GRAMMAR_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_UBJSON_GRAMMAR_HPP - -#include - -#include "../../internal/action.hpp" -#include "../../internal/control.hpp" -#include "../../internal/endian.hpp" -#include "../../internal/grammar.hpp" - -namespace tao -{ - namespace json - { - namespace events - { - namespace ubjson - { - struct number - { - using analyze_t = json_pegtl::analysis::generic< json_pegtl::analysis::rule_type::ANY >; - - template< json_pegtl::apply_mode A, - json_pegtl::rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename Consumer > - static bool match_impl( Input& in, Consumer& consumer ) - { - if( in.peek_char() == '-' ) { - in.bump_in_this_line(); - if( in.empty() || !internal::rules::sor_value::match_number< true, A, json_pegtl::rewind_mode::DONTCARE, Action, Control >( in, consumer ) ) { - throw json_pegtl::parse_error( "incomplete number", in ); - } - return true; - } - return internal::rules::sor_value::match_number< false, A, M, Action, Control >( in, consumer ); - } - - template< json_pegtl::apply_mode A, - json_pegtl::rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename Consumer > - static bool match( Input& in, Consumer& consumer ) - { - if( in.size( 2 ) && match_impl< A, M, Action, Control >( in, consumer ) ) { - in.discard(); - return true; - } - return false; - } - }; - - } // namespace ubjson - - } // namespace events - - namespace internal - { - // clang-format off - template<> WEAK_PREFIX const std::string errors< events::ubjson::number >::error_message WEAK_SUFFIX = "invalid ubjson high-precision number"; - // clang-format on - - } // namespace internal - - namespace events - { - namespace ubjson - { - struct data - { - using analyze_t = json_pegtl::analysis::generic< json_pegtl::analysis::rule_type::ANY >; - - template< json_pegtl::apply_mode A, - json_pegtl::rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename Consumer > - static bool match( Input& in, Consumer& consumer ) - { - // This rule never returns false unless the input is empty. - return ( !in.empty() ) && match_impl( in, consumer ); - } - - template< typename Input, typename Consumer > - static bool match_impl( Input& in, Consumer& consumer ) - { - switch( in.peek_char() ) { - case 'Z': - consumer.null(); - in.bump_in_this_line(); - return true; - case 'N': - in.bump_in_this_line(); - return true; - case 'T': - consumer.boolean( true ); - in.bump_in_this_line(); - return true; - case 'F': - consumer.boolean( false ); - in.bump_in_this_line(); - return true; - case 'i': - consumer.number( read_number< std::int64_t, std::int8_t >( in ) ); - return true; - case 'U': - consumer.number( read_number< std::uint64_t, std::uint8_t >( in ) ); - return true; - case 'I': - consumer.number( read_number< std::int64_t, std::int16_t >( in ) ); - return true; - case 'l': - consumer.number( read_number< std::int64_t, std::int32_t >( in ) ); - return true; - case 'L': - consumer.number( read_number< std::int64_t, std::int64_t >( in ) ); - return true; - case 'd': - consumer.number( read_number< double, float >( in ) ); - return true; - case 'D': - consumer.number( read_number< double, double >( in ) ); - return true; - case 'H': - return match_high_precision( in, consumer ); - case 'C': - return match_char( in, consumer ); - case 'S': - consumer.string( read_container< tao::string_view >( in, read_size( in ) ) ); - } - throw json_pegtl::parse_error( "unknown ubjson marker", in ); - } - - template< typename Input, typename Consumer > - static bool match_char( Input& in, Consumer& consumer ) - { - if( ( in.size( 2 ) < 2 ) || ( in.peek_byte( 1 ) > 127 ) ) { - throw json_pegtl::parse_error( "invalid ubjson char", in ); - } - consumer.string( std::string( 1, in.peek_char( 1 ) ) ); - in.bump_in_this_line( 2 ); - return true; - } - - template< typename Input > - static std::size_t read_size( Input& in ) - { - in.bump_in_this_line(); // Skip marker byte. - if( !in.size( 1 ) ) { - throw json_pegtl::parse_error( "unexpected end of ubjson input", in ); - } - switch( in.peek_char() ) { - case 'i': - return read_number< std::int64_t, std::int8_t >( in ); - case 'U': - return read_number< std::int64_t, std::uint8_t >( in ); - case 'I': - return read_number< std::int64_t, std::int16_t >( in ); - case 'l': - return read_number< std::int64_t, std::int32_t >( in ); - case 'L': - return read_number< std::int64_t, std::int64_t >( in ); - case 'd': - return read_number< std::int64_t, float >( in ); - case 'D': - return read_number< std::int64_t, double >( in ); - } - throw json_pegtl::parse_error( "unexpected ubjson high precision number size marker", in ); - } - - template< typename Input, typename Consumer > - static bool match_high_precision( Input& in, Consumer& consumer ) - { - const auto size = read_size( in ); - if( size < 0 ) { - throw json_pegtl::parse_error( "negative ubjson high precision number size", in ); - } - if( in.size( size ) < size ) { - throw json_pegtl::parse_error( "unexpected end of ubjson input", in ); - } - json_pegtl::memory_input< json_pegtl::tracking_mode::LAZY, json_pegtl::eol::lf_crlf, const char* > i2( in.current(), in.current() + size, "UBJSON" ); - json_pegtl::parse_nested< json_pegtl::must< number, json_pegtl::eof >, internal::action, internal::control >( in, i2, consumer ); - return true; - } - - template< typename Result, typename Number, typename Input > - static Result read_number( Input& in ) - { - if( in.size( sizeof( Number ) ) > sizeof( Number ) ) { - const Result result = json::internal::be_to_h< Number >( in.current() + 1 ); - in.bump_in_this_line( 1 + sizeof( Number ) ); - return result; - } - throw json_pegtl::parse_error( "unexpected end of ubjson input", in ); - } - - template< typename Result, typename Input > - static Result read_container( Input& in, const std::size_t size ) - { - using value_t = typename Result::value_type; - if( in.size( size ) < size ) { - throw json_pegtl::parse_error( "unexpected end of ubjson input", in ); - } - const value_t* pointer = reinterpret_cast< const value_t* >( in.current() ); - Result result( pointer, size ); - in.bump_in_this_line( size ); - return result; - } - - template< typename Input > - static tao::string_view read_key( Input& in ) - { - if( in.empty() ) { - throw json_pegtl::parse_error( "unexpected end of ubjson input", in ); - } - switch( in.peek_byte() ) { - case 0xd9: - return read_container< tao::string_view >( in, read_number< std::size_t, std::uint8_t >( in ) ); - case 0xda: - return read_container< tao::string_view >( in, read_number< std::size_t, std::uint16_t >( in ) ); - case 0xdb: - return read_container< tao::string_view >( in, read_number< std::size_t, std::uint32_t >( in ) ); - } - throw json_pegtl::parse_error( "unexpected key type", in ); - } - - template< typename Input, typename Consumer > - static bool match_array( Input& in, Consumer& consumer, const std::size_t size ) - { - consumer.begin_array( size ); - for( std::size_t i = 0; i < size; ++i ) { - if( in.empty() ) { - throw json_pegtl::parse_error( "unexpected end of ubjson input", in ); - } - match_impl( in, consumer ); - consumer.element(); - } - consumer.end_array( size ); - return true; - } - - template< typename Input, typename Consumer > - static bool match_object( Input& in, Consumer& consumer, const std::size_t size ) - { - consumer.begin_object( size ); - for( std::size_t i = 0; i < size; ++i ) { - consumer.key( read_key( in ) ); - if( in.empty() ) { - throw json_pegtl::parse_error( "unexpected end of ubjson input", in ); - } - match_impl( in, consumer ); - consumer.member(); - } - consumer.end_object( size ); - return true; - } - }; - - struct grammar : json_pegtl::must< data, json_pegtl::eof > - { - }; - - } // namespace ubjson - - } // namespace events - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/events/ubjson/to_stream.hpp b/include/tao/json/events/ubjson/to_stream.hpp deleted file mode 100644 index 356c7fdc..00000000 --- a/include/tao/json/events/ubjson/to_stream.hpp +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JSON_UBJSON_TO_STREAM_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_JSON_UBJSON_TO_STREAM_HPP - -#include -#include -#include -#include - -#include "../../internal/endian.hpp" - -namespace tao -{ - namespace json - { - namespace events - { - namespace ubjson - { - class to_stream - { - private: - std::ostream& os; - - public: - explicit to_stream( std::ostream& in_os ) noexcept - : os( in_os ) - { - } - - void null() - { - os.put( 'Z' ); - } - - void boolean( const bool v ) - { - os.put( v ? 'T' : 'F' ); - } - - void number( const std::int64_t v ) - { - if( ( v >= -128 ) && ( v <= 127 ) ) { - os.put( 'i' ); - const std::int8_t x = v; - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else if( ( v >= -32768 ) && ( v <= 32767 ) ) { - os.put( 'I' ); - const std::uint16_t x = internal::h_to_be( std::uint16_t( v ) ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else if( ( v >= -2147483648 ) && ( v <= 2147483647 ) ) { - os.put( 'l' ); - const std::uint32_t x = internal::h_to_be( std::uint32_t( v ) ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else { - os.put( 'L' ); - const std::uint64_t x = internal::h_to_be( std::uint64_t( v ) ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - } - - void number( const std::uint64_t v ) - { - if( v <= 255 ) { - os.put( 'U' ); - const std::uint8_t x = v; - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else if( v <= 32767 ) { - os.put( 'I' ); - const std::uint16_t x = internal::h_to_be( std::uint16_t( v ) ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else if( v <= 2147483647ul ) { - os.put( 'l' ); - const std::uint32_t x = internal::h_to_be( std::uint32_t( v ) ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else if( v <= 9223372036854775807ull ) { - os.put( 'L' ); - const std::uint64_t x = internal::h_to_be( v ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else { - os.put( 'H' ); - os.put( 'U' ); - os.put( char( 19 ) + char( v >= 10000000000000000000ull ) ); - os << v; - } - } - - void number( const double v ) - { - os.put( 'D' ); - const auto x = internal::h_to_be( v ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - - void string( const tao::string_view v ) - { - if( ( v.size() == 1 ) && ( ( v[ 0 ] & 0x80 ) == 0 ) ) { - os.put( 'C' ); - os.put( v[ 0 ] ); - } - else { - os.put( 'S' ); - number( std::uint64_t( v.size() ) ); - os.write( v.data(), v.size() ); - } - } - - void binary( const tao::byte_view v ) - { - // NOTE: UBJSON encodes binary data as 'strongly typed array of uint8 values'. - os.write( "[$U#", 4 ); - number( std::uint64_t( v.size() ) ); - os.write( reinterpret_cast< const char* >( v.data() ), v.size() ); - } - - void begin_array() - { - os.put( '[' ); - } - - void begin_array( const std::size_t size ) - { - os.write( "[#", 2 ); - number( std::uint64_t( size ) ); - } - - void element() noexcept - { - } - - void end_array() - { - os.put( ']' ); - } - - void end_array( const std::size_t ) noexcept - { - } - - void begin_object() - { - os.put( '{' ); - } - - void begin_object( const std::size_t size ) - { - os.write( "{#", 2 ); - number( std::uint64_t( size ) ); - } - - void key( const tao::string_view v ) - { - number( std::uint64_t( v.size() ) ); - os.write( v.data(), v.size() ); - } - - void member() noexcept - { - } - - void end_object() - { - os.put( '}' ); - } - - void end_object( const std::size_t ) noexcept - { - } - }; - - } // namespace ubjson - - } // namespace events - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/events/ubjson/to_string.hpp b/include/tao/json/events/ubjson/to_string.hpp deleted file mode 100644 index b5b248af..00000000 --- a/include/tao/json/events/ubjson/to_string.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_JSON_UBJSON_TO_STRING_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_JSON_UBJSON_TO_STRING_HPP - -#include -#include - -#include "to_stream.hpp" - -namespace tao -{ - namespace json - { - namespace events - { - namespace ubjson - { - struct to_string - : public to_stream - { - std::ostringstream oss; - - to_string() - : to_stream( oss ) - { - } - - std::string value() const - { - return oss.str(); - } - }; - - } // namespace ubjson - - } // namespace events - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/events/validate_event_order.hpp b/include/tao/json/events/validate_event_order.hpp index 121da3cd..f4106e13 100644 --- a/include/tao/json/events/validate_event_order.hpp +++ b/include/tao/json/events/validate_event_order.hpp @@ -1,387 +1,411 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_VALIDATE_EVENT_ORDER_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_VALIDATE_EVENT_ORDER_HPP +#ifndef TAO_JSON_EVENTS_VALIDATE_EVENT_ORDER_HPP +#define TAO_JSON_EVENTS_VALIDATE_EVENT_ORDER_HPP +#include #include #include +#include #include #include +#include #include -#include "../external/byte.hpp" +#include "../binary_view.hpp" -namespace tao +namespace tao::json::events { - namespace json + // Events consumer that validates the order of events. + + class validate_event_order { - namespace events + private: + enum state_t + { + EXPECT_TOP_LEVEL_VALUE, + EXPECT_ARRAY_VALUE_OR_END, + EXPECT_ARRAY_ELEMENT, + EXPECT_SIZED_ARRAY_VALUE_OR_END, + EXPECT_SIZED_ARRAY_ELEMENT, + EXPECT_OBJECT_KEY_OR_END, + EXPECT_OBJECT_VALUE, + EXPECT_OBJECT_MEMBER, + EXPECT_SIZED_OBJECT_KEY_OR_END, + EXPECT_SIZED_OBJECT_VALUE, + EXPECT_SIZED_OBJECT_MEMBER, + EXPECT_NOTHING + }; + + struct sizes_t { - // Events consumer that validates the order of events. + explicit sizes_t( const std::size_t in_expected ) + : expected( in_expected ) + {} - class validate_event_order + void check( const std::size_t in_expected ) { - private: - enum state_t - { - EXPECT_TOP_LEVEL_VALUE, - EXPECT_ARRAY_VALUE_OR_END, - EXPECT_ARRAY_ELEMENT, - EXPECT_OBJECT_KEY_OR_END, - EXPECT_OBJECT_VALUE, - EXPECT_OBJECT_MEMBER, - EXPECT_NOTHING - }; + if( expected != in_expected ) { + throw std::logic_error( "inconsistent size" ); + } + if( expected != counted ) { + throw std::logic_error( "wrong size" ); + } + } - state_t state = EXPECT_TOP_LEVEL_VALUE; - std::vector< state_t > stack; - // TODO: Another stack for array/object sizes. + std::size_t expected; + std::size_t counted = 0; + }; - public: - bool is_complete() const noexcept - { - return state == EXPECT_NOTHING; - } + state_t state = EXPECT_TOP_LEVEL_VALUE; + std::vector< state_t > stack; + std::vector< sizes_t > sizes; - void null() - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - state = EXPECT_NOTHING; - return; - case EXPECT_ARRAY_VALUE_OR_END: - state = EXPECT_ARRAY_ELEMENT; - return; - case EXPECT_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but null() was called" ); - case EXPECT_OBJECT_KEY_OR_END: - throw std::logic_error( "expected key() or end_object(), but null() was called" ); - case EXPECT_OBJECT_VALUE: - state = EXPECT_OBJECT_MEMBER; - return; - case EXPECT_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but null() was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but null() was called" ); - } - throw std::logic_error( "invalid state" ); - } + void atom( const std::string& function ) + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + state = EXPECT_NOTHING; + return; + case EXPECT_ARRAY_VALUE_OR_END: + state = EXPECT_ARRAY_ELEMENT; + return; + case EXPECT_SIZED_ARRAY_VALUE_OR_END: + state = EXPECT_SIZED_ARRAY_ELEMENT; + return; + case EXPECT_ARRAY_ELEMENT: + case EXPECT_SIZED_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but " + function + " was called" ); + case EXPECT_OBJECT_KEY_OR_END: + case EXPECT_SIZED_OBJECT_KEY_OR_END: + throw std::logic_error( "expected key() or end_object(...), but " + function + " was called" ); + case EXPECT_OBJECT_VALUE: + state = EXPECT_OBJECT_MEMBER; + return; + case EXPECT_SIZED_OBJECT_VALUE: + state = EXPECT_SIZED_OBJECT_MEMBER; + return; + case EXPECT_OBJECT_MEMBER: + case EXPECT_SIZED_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but " + function + " was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but " + function + " was called" ); + } + throw std::logic_error( "invalid state" ); + } - void boolean( const bool ) - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - state = EXPECT_NOTHING; - return; - case EXPECT_ARRAY_VALUE_OR_END: - state = EXPECT_ARRAY_ELEMENT; - return; - case EXPECT_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but boolean() was called" ); - case EXPECT_OBJECT_KEY_OR_END: - throw std::logic_error( "expected key() or end_object(), but boolean() was called" ); - case EXPECT_OBJECT_VALUE: - state = EXPECT_OBJECT_MEMBER; - return; - case EXPECT_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but boolean() was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but boolean() was called" ); - } - throw std::logic_error( "invalid state" ); - } + public: + [[nodiscard]] bool is_complete() const noexcept + { + return state == EXPECT_NOTHING; + } - void number( const std::int64_t ) - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - state = EXPECT_NOTHING; - return; - case EXPECT_ARRAY_VALUE_OR_END: - state = EXPECT_ARRAY_ELEMENT; - return; - case EXPECT_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but number(std::int64_t) was called" ); - case EXPECT_OBJECT_KEY_OR_END: - throw std::logic_error( "expected key() or end_object(), but number(std::int64_t) was called" ); - case EXPECT_OBJECT_VALUE: - state = EXPECT_OBJECT_MEMBER; - return; - case EXPECT_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but number(std::int64_t) was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but number(std::int64_t) was called" ); - } - throw std::logic_error( "invalid state" ); - } + void null() + { + atom( "null()" ); + } - void number( const std::uint64_t ) - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - state = EXPECT_NOTHING; - return; - case EXPECT_ARRAY_VALUE_OR_END: - state = EXPECT_ARRAY_ELEMENT; - return; - case EXPECT_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but number(std::uint64_t) was called" ); - case EXPECT_OBJECT_KEY_OR_END: - throw std::logic_error( "expected key() or end_object(), but number(std::uint64_t) was called" ); - case EXPECT_OBJECT_VALUE: - state = EXPECT_OBJECT_MEMBER; - return; - case EXPECT_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but number(std::uint64_t) was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but number(std::uint64_t) was called" ); - } - throw std::logic_error( "invalid state" ); - } + void boolean( const bool /*unused*/ ) + { + atom( "boolen()" ); + } - void number( const double ) - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - state = EXPECT_NOTHING; - return; - case EXPECT_ARRAY_VALUE_OR_END: - state = EXPECT_ARRAY_ELEMENT; - return; - case EXPECT_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but number(double) was called" ); - case EXPECT_OBJECT_KEY_OR_END: - throw std::logic_error( "expected key() or end_object(), but number(double) was called" ); - case EXPECT_OBJECT_VALUE: - state = EXPECT_OBJECT_MEMBER; - return; - case EXPECT_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but number(double) was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but number(double) was called" ); - } - throw std::logic_error( "invalid state" ); - } + void number( const std::int64_t /*unused*/ ) + { + atom( "number(std::int64_t)" ); + } - void string( const tao::string_view ) - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - state = EXPECT_NOTHING; - return; - case EXPECT_ARRAY_VALUE_OR_END: - state = EXPECT_ARRAY_ELEMENT; - return; - case EXPECT_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but string() was called" ); - case EXPECT_OBJECT_KEY_OR_END: - throw std::logic_error( "expected key() or end_object(), but string() was called" ); - case EXPECT_OBJECT_VALUE: - state = EXPECT_OBJECT_MEMBER; - return; - case EXPECT_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but string() was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but string() was called" ); - } - throw std::logic_error( "invalid state" ); - } + void number( const std::uint64_t /*unused*/ ) + { + atom( "number(std::uint64_t)" ); + } - void binary( const tao::byte_view ) - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - state = EXPECT_NOTHING; - return; - case EXPECT_ARRAY_VALUE_OR_END: - state = EXPECT_ARRAY_ELEMENT; - return; - case EXPECT_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but binary() was called" ); - case EXPECT_OBJECT_KEY_OR_END: - throw std::logic_error( "expected key() or end_object(), but binary() was called" ); - case EXPECT_OBJECT_VALUE: - state = EXPECT_OBJECT_MEMBER; - return; - case EXPECT_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but binary() was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but binary() was called" ); - } - throw std::logic_error( "invalid state" ); - } + void number( const double /*unused*/ ) + { + atom( "number(double)" ); + } - void begin_array( const std::size_t = 0 ) - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - stack.push_back( EXPECT_NOTHING ); - state = EXPECT_ARRAY_VALUE_OR_END; - return; - case EXPECT_ARRAY_VALUE_OR_END: - stack.push_back( EXPECT_ARRAY_ELEMENT ); - return; - case EXPECT_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but begin_array() was called" ); - case EXPECT_OBJECT_KEY_OR_END: - throw std::logic_error( "expected key() or end_object(), but begin_array() was called" ); - case EXPECT_OBJECT_VALUE: - stack.push_back( EXPECT_OBJECT_MEMBER ); - state = EXPECT_ARRAY_VALUE_OR_END; - return; - case EXPECT_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but begin_array() was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but begin_array() was called" ); - } - throw std::logic_error( "invalid state" ); - } + void string( const std::string_view /*unused*/ ) + { + atom( "string(...)" ); + } - void element() - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - throw std::logic_error( "expected any value, but element() was called" ); - case EXPECT_ARRAY_VALUE_OR_END: - throw std::logic_error( "expected any value or end_array(), but element() was called" ); - case EXPECT_ARRAY_ELEMENT: - state = EXPECT_ARRAY_VALUE_OR_END; - return; - case EXPECT_OBJECT_KEY_OR_END: - throw std::logic_error( "expected key() or end_object(), but element() was called" ); - case EXPECT_OBJECT_VALUE: - throw std::logic_error( "expected any value, but element() was called" ); - case EXPECT_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but element() was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but element() was called" ); - } - throw std::logic_error( "invalid state" ); - } + void binary( const tao::binary_view /*unused*/ ) + { + atom( "binary(...)" ); + } - void end_array( const std::size_t = 0 ) - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - throw std::logic_error( "expected any value, but end_array() was called" ); - case EXPECT_ARRAY_VALUE_OR_END: - state = stack.back(); - stack.pop_back(); - return; - case EXPECT_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but end_array() was called" ); - case EXPECT_OBJECT_KEY_OR_END: - throw std::logic_error( "expected key() or end_object(), but end_array() was called" ); - case EXPECT_OBJECT_VALUE: - throw std::logic_error( "expected any value, but end_array() was called" ); - case EXPECT_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but end_array() was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but end_array() was called" ); - } - throw std::logic_error( "invalid state" ); - } + void begin_array() + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + stack.push_back( EXPECT_NOTHING ); + state = EXPECT_ARRAY_VALUE_OR_END; + return; + case EXPECT_ARRAY_VALUE_OR_END: + stack.push_back( EXPECT_ARRAY_ELEMENT ); + return; + case EXPECT_SIZED_ARRAY_VALUE_OR_END: + stack.push_back( EXPECT_SIZED_ARRAY_ELEMENT ); + return; + case EXPECT_ARRAY_ELEMENT: + case EXPECT_SIZED_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but begin_array(...) was called" ); + case EXPECT_OBJECT_KEY_OR_END: + case EXPECT_SIZED_OBJECT_KEY_OR_END: + throw std::logic_error( "expected key() or end_object(...), but begin_array(...) was called" ); + case EXPECT_OBJECT_VALUE: + stack.push_back( EXPECT_OBJECT_MEMBER ); + state = EXPECT_ARRAY_VALUE_OR_END; + return; + case EXPECT_SIZED_OBJECT_VALUE: + stack.push_back( EXPECT_SIZED_OBJECT_MEMBER ); + state = EXPECT_ARRAY_VALUE_OR_END; + return; + case EXPECT_OBJECT_MEMBER: + case EXPECT_SIZED_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but begin_array(...) was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but begin_array(...) was called" ); + } + throw std::logic_error( "invalid state" ); + } - void begin_object( const std::size_t = 0 ) - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - stack.push_back( EXPECT_NOTHING ); - state = EXPECT_OBJECT_KEY_OR_END; - return; - case EXPECT_ARRAY_VALUE_OR_END: - stack.push_back( EXPECT_ARRAY_ELEMENT ); - state = EXPECT_OBJECT_KEY_OR_END; - return; - case EXPECT_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but begin_object() was called" ); - case EXPECT_OBJECT_KEY_OR_END: - throw std::logic_error( "expected key() or end_object(), but begin_object() was called" ); - case EXPECT_OBJECT_VALUE: - stack.push_back( EXPECT_OBJECT_MEMBER ); - state = EXPECT_OBJECT_KEY_OR_END; - return; - case EXPECT_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but begin_object() was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but begin_object() was called" ); - } - throw std::logic_error( "invalid state" ); - } + void begin_array( const std::size_t expected ) + { + begin_array(); + sizes.emplace_back( expected ); + state = EXPECT_SIZED_ARRAY_VALUE_OR_END; + } - void key( const tao::string_view ) - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - throw std::logic_error( "expected any value, but key() was called" ); - case EXPECT_ARRAY_VALUE_OR_END: - throw std::logic_error( "expected any value or end_array(), but key() was called" ); - case EXPECT_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but key() was called" ); - case EXPECT_OBJECT_KEY_OR_END: - state = EXPECT_OBJECT_VALUE; - return; - case EXPECT_OBJECT_VALUE: - throw std::logic_error( "expected any value, but key() was called" ); - case EXPECT_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but key() was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but key() was called" ); - } - throw std::logic_error( "invalid state" ); - } + void element() + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + throw std::logic_error( "expected any value, but element() was called" ); + case EXPECT_ARRAY_VALUE_OR_END: + case EXPECT_SIZED_ARRAY_VALUE_OR_END: + throw std::logic_error( "expected any value or end_array(...), but element() was called" ); + case EXPECT_ARRAY_ELEMENT: + state = EXPECT_ARRAY_VALUE_OR_END; + return; + case EXPECT_SIZED_ARRAY_ELEMENT: + state = EXPECT_SIZED_ARRAY_VALUE_OR_END; + ++sizes.back().counted; + return; + case EXPECT_OBJECT_KEY_OR_END: + case EXPECT_SIZED_OBJECT_KEY_OR_END: + throw std::logic_error( "expected key() or end_object(...), but element() was called" ); + case EXPECT_OBJECT_VALUE: + case EXPECT_SIZED_OBJECT_VALUE: + throw std::logic_error( "expected any value, but element() was called" ); + case EXPECT_OBJECT_MEMBER: + case EXPECT_SIZED_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but element() was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but element() was called" ); + } + throw std::logic_error( "invalid state" ); + } - void member() - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - throw std::logic_error( "expected any value, but member() was called" ); - case EXPECT_ARRAY_VALUE_OR_END: - throw std::logic_error( "expected any value or end_array(), but member() was called" ); - case EXPECT_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but member() was called" ); - case EXPECT_OBJECT_KEY_OR_END: - throw std::logic_error( "expected key() or end_object(), but member() was called" ); - case EXPECT_OBJECT_VALUE: - throw std::logic_error( "expected any value, but member() was called" ); - case EXPECT_OBJECT_MEMBER: - state = EXPECT_OBJECT_KEY_OR_END; - return; - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but member() was called" ); - } - throw std::logic_error( "invalid state" ); - } + void end_array() + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + throw std::logic_error( "expected any value, but end_array(....) was called" ); + case EXPECT_ARRAY_VALUE_OR_END: + state = stack.back(); + stack.pop_back(); + return; + case EXPECT_SIZED_ARRAY_VALUE_OR_END: + throw std::logic_error( "expected end_array(std::size_t), but end_array() was called" ); + case EXPECT_ARRAY_ELEMENT: + case EXPECT_SIZED_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but end_array(...) was called" ); + case EXPECT_OBJECT_KEY_OR_END: + case EXPECT_SIZED_OBJECT_KEY_OR_END: + throw std::logic_error( "expected key() or end_object(...), but end_array(...) was called" ); + case EXPECT_OBJECT_VALUE: + case EXPECT_SIZED_OBJECT_VALUE: + throw std::logic_error( "expected any value, but end_array(...) was called" ); + case EXPECT_OBJECT_MEMBER: + case EXPECT_SIZED_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but end_array(...) was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but end_array(...) was called" ); + } + throw std::logic_error( "invalid state" ); + } - void end_object( const std::size_t = 0 ) - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - throw std::logic_error( "expected any value, but end_object() was called" ); - case EXPECT_ARRAY_VALUE_OR_END: - throw std::logic_error( "expected any value or end_array(), but end_object() was called" ); - case EXPECT_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but end_object() was called" ); - case EXPECT_OBJECT_KEY_OR_END: - state = stack.back(); - stack.pop_back(); - return; - case EXPECT_OBJECT_VALUE: - throw std::logic_error( "expected any value, but end_object() was called" ); - case EXPECT_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but end_object() was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but end_object() was called" ); - } - throw std::logic_error( "invalid state" ); - } - }; + void end_array( const std::size_t expected ) + { + switch( state ) { + case EXPECT_SIZED_ARRAY_VALUE_OR_END: + state = EXPECT_ARRAY_VALUE_OR_END; + break; + case EXPECT_ARRAY_VALUE_OR_END: + throw std::logic_error( "expected any value or end_array(), but end_array(std::size_t) was called" ); + default: + break; + } + assert( sizes.size() ); + sizes.back().check( expected ); + sizes.pop_back(); + end_array(); + } + + void begin_object() + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + stack.push_back( EXPECT_NOTHING ); + state = EXPECT_OBJECT_KEY_OR_END; + return; + case EXPECT_ARRAY_VALUE_OR_END: + stack.push_back( EXPECT_ARRAY_ELEMENT ); + state = EXPECT_OBJECT_KEY_OR_END; + return; + case EXPECT_SIZED_ARRAY_VALUE_OR_END: + stack.push_back( EXPECT_SIZED_ARRAY_ELEMENT ); + state = EXPECT_OBJECT_KEY_OR_END; + return; + case EXPECT_ARRAY_ELEMENT: + case EXPECT_SIZED_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but begin_object(...) was called" ); + case EXPECT_OBJECT_KEY_OR_END: + case EXPECT_SIZED_OBJECT_KEY_OR_END: + throw std::logic_error( "expected key() or end_object(...), but begin_object(...) was called" ); + case EXPECT_OBJECT_VALUE: + stack.push_back( EXPECT_OBJECT_MEMBER ); + state = EXPECT_OBJECT_KEY_OR_END; + return; + case EXPECT_SIZED_OBJECT_VALUE: + stack.push_back( EXPECT_SIZED_OBJECT_MEMBER ); + state = EXPECT_OBJECT_KEY_OR_END; + return; + case EXPECT_OBJECT_MEMBER: + case EXPECT_SIZED_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but begin_object(...) was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but begin_object(...) was called" ); + } + throw std::logic_error( "invalid state" ); + } - } // namespace events + void begin_object( const std::size_t expected ) + { + begin_object(); + sizes.emplace_back( expected ); + state = EXPECT_SIZED_OBJECT_KEY_OR_END; + } + + void key( const std::string_view /*unused*/ ) + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + throw std::logic_error( "expected any value, but key() was called" ); + case EXPECT_ARRAY_VALUE_OR_END: + case EXPECT_SIZED_ARRAY_VALUE_OR_END: + throw std::logic_error( "expected any value or end_array(...), but key() was called" ); + case EXPECT_ARRAY_ELEMENT: + case EXPECT_SIZED_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but key() was called" ); + case EXPECT_OBJECT_KEY_OR_END: + state = EXPECT_OBJECT_VALUE; + return; + case EXPECT_SIZED_OBJECT_KEY_OR_END: + state = EXPECT_SIZED_OBJECT_VALUE; + return; + case EXPECT_OBJECT_VALUE: + case EXPECT_SIZED_OBJECT_VALUE: + throw std::logic_error( "expected any value, but key() was called" ); + case EXPECT_OBJECT_MEMBER: + case EXPECT_SIZED_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but key() was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but key() was called" ); + } + throw std::logic_error( "invalid state" ); + } - } // namespace json + void member() + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + throw std::logic_error( "expected any value, but member() was called" ); + case EXPECT_ARRAY_VALUE_OR_END: + case EXPECT_SIZED_ARRAY_VALUE_OR_END: + throw std::logic_error( "expected any value or end_array(...), but member() was called" ); + case EXPECT_ARRAY_ELEMENT: + case EXPECT_SIZED_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but member() was called" ); + case EXPECT_OBJECT_KEY_OR_END: + case EXPECT_SIZED_OBJECT_KEY_OR_END: + throw std::logic_error( "expected key() or end_object(...), but member() was called" ); + case EXPECT_OBJECT_VALUE: + case EXPECT_SIZED_OBJECT_VALUE: + throw std::logic_error( "expected any value, but member() was called" ); + case EXPECT_OBJECT_MEMBER: + state = EXPECT_OBJECT_KEY_OR_END; + return; + case EXPECT_SIZED_OBJECT_MEMBER: + state = EXPECT_SIZED_OBJECT_KEY_OR_END; + ++sizes.back().counted; + return; + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but member() was called" ); + } + throw std::logic_error( "invalid state" ); + } + + void end_object() + { + switch( state ) { + case EXPECT_TOP_LEVEL_VALUE: + throw std::logic_error( "expected any value, but end_object(...) was called" ); + case EXPECT_ARRAY_VALUE_OR_END: + case EXPECT_SIZED_ARRAY_VALUE_OR_END: + throw std::logic_error( "expected any value or end_array(...), but end_object(...) was called" ); + case EXPECT_ARRAY_ELEMENT: + case EXPECT_SIZED_ARRAY_ELEMENT: + throw std::logic_error( "expected element(), but end_object(...) was called" ); + case EXPECT_OBJECT_KEY_OR_END: + state = stack.back(); + stack.pop_back(); + return; + case EXPECT_SIZED_OBJECT_KEY_OR_END: + throw std::logic_error( "expected any value or end_object(std::size_t), but end_object() was called" ); + case EXPECT_OBJECT_VALUE: + case EXPECT_SIZED_OBJECT_VALUE: + throw std::logic_error( "expected any value, but end_object(...) was called" ); + case EXPECT_OBJECT_MEMBER: + case EXPECT_SIZED_OBJECT_MEMBER: + throw std::logic_error( "expected member(), but end_object(...) was called" ); + case EXPECT_NOTHING: + throw std::logic_error( "expected nothing, but end_object(...) was called" ); + } + throw std::logic_error( "invalid state" ); + } + + void end_object( const std::size_t expected ) + { + switch( state ) { + case EXPECT_SIZED_OBJECT_KEY_OR_END: + state = EXPECT_OBJECT_KEY_OR_END; + break; + case EXPECT_OBJECT_KEY_OR_END: + throw std::logic_error( "expected any value or end_object(), but end_object(std::size_t) was called" ); + default: + break; + } + assert( sizes.size() ); + sizes.back().check( expected ); + sizes.pop_back(); + end_object(); + } + }; -} // namespace tao +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/validate_keys.hpp b/include/tao/json/events/validate_keys.hpp index 8c6ec000..c03d123d 100644 --- a/include/tao/json/events/validate_keys.hpp +++ b/include/tao/json/events/validate_keys.hpp @@ -1,58 +1,51 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_EVENTS_VALIDATE_KEYS_HPP -#define TAOCPP_JSON_INCLUDE_EVENTS_VALIDATE_KEYS_HPP +#ifndef TAO_JSON_EVENTS_VALIDATE_KEYS_HPP +#define TAO_JSON_EVENTS_VALIDATE_KEYS_HPP #include #include +#include #include #include "../external/pegtl.hpp" -namespace tao +namespace tao::json::events { - namespace json + template< typename Consumer, typename Rule > + struct validate_keys + : Consumer { - namespace events + using Consumer::Consumer; + + void validate_key( const std::string_view v ) + { + pegtl::memory_input< pegtl::tracking_mode::lazy > in( v.data(), v.size(), "validate_key" ); + if( !pegtl::parse< Rule >( in ) ) { + throw std::runtime_error( "invalid key: " + std::string( v ) ); + } + } + + void key( const std::string_view v ) + { + validate_key( v ); + Consumer::key( v ); + } + + void key( const char* v ) + { + validate_key( v ); + Consumer::key( v ); + } + + void key( std::string&& v ) { - template< typename Consumer, typename Rule > - struct validate_keys - : public Consumer - { - using Consumer::Consumer; - - void validate_key( const tao::string_view v ) - { - json_pegtl::memory_input< json_pegtl::tracking_mode::LAZY > in( v.data(), v.size(), __PRETTY_FUNCTION__ ); - if( !json_pegtl::parse< Rule >( in ) ) { - throw std::runtime_error( "invalid key: " + std::string( v.data(), v.size() ) ); - } - } - - void key( const tao::string_view v ) - { - validate_key( v ); - Consumer::key( v ); - } - - void key( const char* v ) - { - validate_key( v ); - Consumer::key( v ); - } - - void key( std::string&& v ) - { - validate_key( v ); - Consumer::key( std::move( v ) ); - } - }; - - } // namespace events - - } // namespace json - -} // namespace tao + validate_key( v ); + Consumer::key( std::move( v ) ); + } + }; + +} // namespace tao::json::events #endif diff --git a/include/tao/json/events/virtual_base.hpp b/include/tao/json/events/virtual_base.hpp new file mode 100644 index 00000000..553f2443 --- /dev/null +++ b/include/tao/json/events/virtual_base.hpp @@ -0,0 +1,192 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_EVENTS_VIRTUAL_BASE_HPP +#define TAO_JSON_EVENTS_VIRTUAL_BASE_HPP + +#include +#include +#include +#include +#include + +#include "../binary_view.hpp" + +namespace tao::json::events +{ + // Events consumer interface with virtual functions. + + class virtual_base + { + public: + void null() + { + v_null(); + } + + void boolean( const bool v ) + { + v_boolean( v ); + } + + void number( const std::int64_t v ) + { + v_number( v ); + } + + void number( const std::uint64_t v ) + { + v_number( v ); + } + + void number( const double v ) + { + v_number( v ); + } + + void string( const char* v ) + { + v_string( v ); + } + + void string( std::string&& v ) + { + v_string( std::move( v ) ); + } + + void string( const std::string& v ) + { + v_string( v ); + } + + void string( const std::string_view v ) + { + v_string( v ); + } + + void binary( std::vector< std::byte >&& v ) + { + v_binary( std::move( v ) ); + } + + void binary( const std::vector< std::byte >& v ) + { + v_binary( v ); + } + + void binary( const tao::binary_view v ) + { + v_binary( v ); + } + + void begin_array() + { + v_begin_array(); + } + + void begin_array( const std::size_t v ) + { + v_begin_array( v ); + } + + void element() + { + v_element(); + } + + void end_array() + { + v_end_array(); + } + + void end_array( const std::size_t v ) + { + v_end_array( v ); + } + + void begin_object() + { + v_begin_object(); + } + + void begin_object( const std::size_t v ) + { + v_begin_object( v ); + } + + void key( const char* v ) + { + v_key( v ); + } + + void key( std::string&& v ) + { + v_key( std::move( v ) ); + } + + void key( const std::string& v ) + { + v_key( v ); + } + + void key( const std::string_view v ) + { + v_key( v ); + } + + void member() + { + v_member(); + } + + void end_object() + { + v_end_object(); + } + + void end_object( const std::size_t v ) + { + v_end_object( v ); + } + + virtual_base( virtual_base&& ) = delete; + virtual_base( const virtual_base& ) = delete; + + void operator=( virtual_base&& ) = delete; + void operator=( const virtual_base& ) = delete; + + protected: + virtual_base() = default; + ~virtual_base() = default; + + virtual void v_null() = 0; + virtual void v_boolean( bool ) = 0; + virtual void v_number( std::int64_t ) = 0; + virtual void v_number( std::uint64_t ) = 0; + virtual void v_number( double ) = 0; + virtual void v_string( const char* ) = 0; + virtual void v_string( std::string&& ) = 0; + virtual void v_string( const std::string& ) = 0; + virtual void v_string( std::string_view ) = 0; + virtual void v_binary( std::vector< std::byte >&& ) = 0; + virtual void v_binary( const std::vector< std::byte >& ) = 0; + virtual void v_binary( tao::binary_view ) = 0; + virtual void v_begin_array() = 0; + virtual void v_begin_array( std::size_t ) = 0; + virtual void v_element() = 0; + virtual void v_end_array() = 0; + virtual void v_end_array( std::size_t ) = 0; + virtual void v_begin_object() = 0; + virtual void v_begin_object( std::size_t ) = 0; + virtual void v_key( const char* ) = 0; + virtual void v_key( std::string&& ) = 0; + virtual void v_key( const std::string& ) = 0; + virtual void v_key( std::string_view ) = 0; + virtual void v_member() = 0; + virtual void v_end_object() = 0; + virtual void v_end_object( std::size_t ) = 0; + }; + +} // namespace tao::json::events + +#endif diff --git a/include/tao/json/events/virtual_ref.hpp b/include/tao/json/events/virtual_ref.hpp new file mode 100644 index 00000000..f5d40e96 --- /dev/null +++ b/include/tao/json/events/virtual_ref.hpp @@ -0,0 +1,170 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_EVENTS_VIRTUAL_REF_HPP +#define TAO_JSON_EVENTS_VIRTUAL_REF_HPP + +#include +#include + +#include "virtual_base.hpp" + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4373 ) +#endif + +namespace tao::json::events +{ + template< typename Consumer > + class virtual_ref + : public virtual_base + { + public: + explicit virtual_ref( Consumer& r ) noexcept + : m_r( r ) + {} + + virtual ~virtual_ref() = default; + + private: + Consumer& m_r; + + void v_null() override + { + m_r.null(); + } + + void v_boolean( const bool v ) override + { + m_r.boolean( v ); + } + + void v_number( const std::int64_t v ) override + { + m_r.number( v ); + } + + void v_number( const std::uint64_t v ) override + { + m_r.number( v ); + } + + void v_number( const double v ) override + { + m_r.number( v ); + } + + void v_string( const char* v ) override + { + m_r.string( v ); + } + + void v_string( std::string&& v ) override + { + m_r.string( std::move( v ) ); + } + + void v_string( const std::string& v ) override + { + m_r.string( v ); + } + + void v_string( const std::string_view v ) override + { + m_r.string( v ); + } + + void v_binary( std::vector< std::byte >&& v ) override + { + m_r.binary( std::move( v ) ); + } + + void v_binary( const std::vector< std::byte >& v ) override + { + m_r.binary( v ); + } + + void v_binary( const tao::binary_view v ) override + { + m_r.binary( v ); + } + + void v_begin_array() override + { + m_r.begin_array(); + } + + void v_begin_array( const std::size_t v ) override + { + m_r.begin_array( v ); + } + + void v_element() override + { + m_r.element(); + } + + void v_end_array() override + { + m_r.end_array(); + } + + void v_end_array( const std::size_t v ) override + { + m_r.end_array( v ); + } + + void v_begin_object() override + { + m_r.begin_object(); + } + + void v_begin_object( const std::size_t v ) override + { + m_r.begin_object( v ); + } + + void v_key( const char* v ) override + { + m_r.key( v ); + } + + void v_key( std::string&& v ) override + { + m_r.key( std::move( v ) ); + } + + void v_key( const std::string& v ) override + { + m_r.key( v ); + } + + void v_key( const std::string_view v ) override + { + m_r.key( v ); + } + + void v_member() override + { + m_r.member(); + } + + void v_end_object() override + { + m_r.end_object(); + } + + void v_end_object( const std::size_t v ) override + { + m_r.end_object( v ); + } + }; + +} // namespace tao::json::events + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + +#endif diff --git a/include/tao/json/external/akrzemi1/CMakeLists.txt b/include/tao/json/external/akrzemi1/CMakeLists.txt deleted file mode 100644 index 1af707f6..00000000 --- a/include/tao/json/external/akrzemi1/CMakeLists.txt +++ /dev/null @@ -1,46 +0,0 @@ -# if CMAKE_VERSION >= 3.0 this project installs an INTERFACE target for -# the optional.hpp file. -# -# Usage: -# -# In your project's CMakeLists.txt: -# -# find_package(akrzemi1_optional REQUIRED) -# ... -# target_link_libraries(mytarget ... akrzemi1::optional ...) -# -# In your C++ source file: -# -# #include "akrzemi1/optional.hpp" -# - -project(optional) -cmake_minimum_required(VERSION 2.8) -enable_testing() - -if(CMAKE_VERSION VERSION_LESS 3.1) - set(CMAKE_CXX_FLAGS "-std=c++11") -elseif(NOT CMAKE_CXX_STANDARD) # don't override c++ standard if already set - set(CMAKE_CXX_STANDARD 11) -endif() - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") - -# if CMAKE_VERSION >= 3.0 -if(NOT (CMAKE_VERSION VERSION_LESS 3.0)) - add_library(optional INTERFACE) - target_include_directories(optional INTERFACE - $ - $) - install(TARGETS optional EXPORT optional-targets) - install(EXPORT optional-targets DESTINATION lib/cmake/akrzemi1_optional - FILE akrzemi1_optional-config.cmake - NAMESPACE akrzemi1::) - install(FILES optional.hpp DESTINATION include/akrzemi1) -endif() - -add_executable(test_optional test_optional.cpp) -add_executable(test_type_traits test_type_traits.cpp) - -add_test(test_optional test_optional) -add_test(test_type_traits test_type_traits) diff --git a/include/tao/json/external/akrzemi1/LICENSE b/include/tao/json/external/akrzemi1/LICENSE deleted file mode 100644 index 36b7cd93..00000000 --- a/include/tao/json/external/akrzemi1/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/include/tao/json/external/akrzemi1/LICENSE_1_0.txt b/include/tao/json/external/akrzemi1/LICENSE_1_0.txt deleted file mode 100644 index 36b7cd93..00000000 --- a/include/tao/json/external/akrzemi1/LICENSE_1_0.txt +++ /dev/null @@ -1,23 +0,0 @@ -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/include/tao/json/external/akrzemi1/README.md b/include/tao/json/external/akrzemi1/README.md deleted file mode 100644 index 881390ae..00000000 --- a/include/tao/json/external/akrzemi1/README.md +++ /dev/null @@ -1,39 +0,0 @@ -Optional -======== - -A single-header header-only library for representing optional (nullable) objects for C++14 (and C++11 to some extent) and passing them by value. This is the reference implementation of proposal N3793 (see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3793.html). Optional is now accepted into Library Fundamentals Technical Specification (see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3848.html). The interface is based on Fernando Cacciola's Boost.Optional library (see http://www.boost.org/doc/libs/1_52_0/libs/optional/doc/html/index.html) - - -Usage ------ - -```cpp -optional readInt(); // this function may return int or a not-an-int - -if (optional oi = readInt()) // did I get a real int - cout << "my int is: " << *oi; // use my int -else - cout << "I have no int"; -``` - -For more usage examples and the overview see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3527.html - - -Supported compilers -------------------- - -Clang 3.2, Clang 3.4, G++ 4.7.2, G++ 4.8.1. Tested only with libstdc++, versions 20130531, 20120920, 20110428. Others have reported it also works with libc++. - - - -Known Issues ------------- - - - Currently, the reference (and the only known) implementation of certain pieces of functionality explore what C++11 identifies as undefined behavior (see national body comment FI 15: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3770.html#FI15). This is mostly why Optional was removed from C++14 and put into Library Fundamentals TS. Luckily what the Standard identifies as UB is well defined on all known platforms. We expect that the C++14 wil fix this problem, so that our trick becomes well-defined. - - In libstdc++ versions below 20130531 the constructor taking `initializer_list` argument is not `constexpr`. This is because `initializer_list` operations are not `constexpr` in C++11. This works however in version 20130531. It is also not enabled for libc++ because I do not have access to it and do not know if it provides `constexpr` `initializer_list`. - - In G++ 4.7.2 and 4.8.0 member function `value_or` does not have rvalue reference overload. These compilers do not support rvalue overloding on `*this`. - - In order for the library to work with slightly older compilers, we emulate some missing type traits. On some platforms we cannot correctly detect the available features, and attempts at workarounds for missing type trait definitions can cause compile-time errors. Define macro `TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS` if you know that all the necessary type traits are defined, and no emulation is required. - -License -------- -Distributed under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt). diff --git a/include/tao/json/external/akrzemi1/copyright.txt b/include/tao/json/external/akrzemi1/copyright.txt deleted file mode 100644 index b1088ac0..00000000 --- a/include/tao/json/external/akrzemi1/copyright.txt +++ /dev/null @@ -1,10 +0,0 @@ -Copyright (C) 2011-2016 Andrzej Krzemienski - -Distributed under the Boost Software License, Version 1.0 -(see accompanying file LICENSE_1_0.txt or a copy at -http://www.boost.org/LICENSE_1_0.txt) - -The idea and interface is based on Boost.Optional library -authored by Fernando Luis Cacciola Carballal - -Home at https://github.com/akrzemi1/Optional diff --git a/include/tao/json/external/akrzemi1/optional.hpp b/include/tao/json/external/akrzemi1/optional.hpp deleted file mode 100644 index 7b9148f3..00000000 --- a/include/tao/json/external/akrzemi1/optional.hpp +++ /dev/null @@ -1,1052 +0,0 @@ -// Copyright (C) 2011 - 2012 Andrzej Krzemienski. -// -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The idea and interface is based on Boost.Optional library -// authored by Fernando Luis Cacciola Carballal - -# ifndef ___OPTIONAL_HPP___ -# define ___OPTIONAL_HPP___ - -# include -# include -# include -# include -# include -# include -# include - -# define TR2_OPTIONAL_REQUIRES(...) typename enable_if<__VA_ARGS__::value, bool>::type = false - -# if defined __GNUC__ // NOTE: GNUC is also defined for Clang -# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) -# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ -# elif (__GNUC__ > 4) -# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ -# endif -# -# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7) -# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ -# elif (__GNUC__ > 4) -# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ -# endif -# -# if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1) -# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9) -# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# elif (__GNUC__ > 4) -# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# endif -# endif -# -# if defined __clang_major__ -# if (__clang_major__ == 3 && __clang_minor__ >= 5) -# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ -# elif (__clang_major__ > 3) -# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ -# endif -# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ -# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ -# elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2) -# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ -# endif -# endif -# -# if defined _MSC_VER -# if (_MSC_VER >= 1900) -# define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ -# endif -# endif - -# if defined __clang__ -# if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9) -# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 -# else -# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 -# endif -# elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 -# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ -# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 -# else -# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 -# endif - - -# if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1 -# define OPTIONAL_CONSTEXPR_INIT_LIST constexpr -# else -# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0 -# define OPTIONAL_CONSTEXPR_INIT_LIST -# endif - -# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L) -# define OPTIONAL_HAS_MOVE_ACCESSORS 1 -# else -# define OPTIONAL_HAS_MOVE_ACCESSORS 0 -# endif - -# // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr -# if (defined __cplusplus) && (__cplusplus == 201103L) -# define OPTIONAL_MUTABLE_CONSTEXPR -# else -# define OPTIONAL_MUTABLE_CONSTEXPR constexpr -# endif - -namespace std{ - -namespace experimental{ - -// BEGIN workaround for missing is_trivially_destructible -# if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ - // leave it: it is already there -# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ - // leave it: it is already there -# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ - // leave it: it is already there -# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS - // leave it: the user doesn't want it -# else - template - using is_trivially_destructible = std::has_trivial_destructor; -# endif -// END workaround for missing is_trivially_destructible - -# if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___) - // leave it; our metafunctions are already defined. -# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ - // leave it; our metafunctions are already defined. -# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ - // leave it: it is already there -# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS - // leave it: the user doesn't want it -# else - - -// workaround for missing traits in GCC and CLANG -template -struct is_nothrow_move_constructible -{ - constexpr static bool value = std::is_nothrow_constructible::value; -}; - - -template -struct is_assignable -{ - template - constexpr static bool has_assign(...) { return false; } - - template () = std::declval(), true)) > - // the comma operator is necessary for the cases where operator= returns void - constexpr static bool has_assign(bool) { return true; } - - constexpr static bool value = has_assign(true); -}; - - -template -struct is_nothrow_move_assignable -{ - template - struct has_nothrow_move_assign { - constexpr static bool value = false; - }; - - template - struct has_nothrow_move_assign { - constexpr static bool value = noexcept( std::declval() = std::declval() ); - }; - - constexpr static bool value = has_nothrow_move_assign::value>::value; -}; -// end workaround - - -# endif - - - -// 20.5.4, optional for object types -template class optional; - -// 20.5.5, optional for lvalue reference types -template class optional; - - -// workaround: std utility functions aren't constexpr yet -template inline constexpr T&& constexpr_forward(typename std::remove_reference::type& t) noexcept -{ - return static_cast(t); -} - -template inline constexpr T&& constexpr_forward(typename std::remove_reference::type&& t) noexcept -{ - static_assert(!std::is_lvalue_reference::value, "!!"); - return static_cast(t); -} - -template inline constexpr typename std::remove_reference::type&& constexpr_move(T&& t) noexcept -{ - return static_cast::type&&>(t); -} - - -#if defined NDEBUG -# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) -#else -# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR))) -#endif - - -namespace detail_ -{ - -// static_addressof: a constexpr version of addressof -template -struct has_overloaded_addressof -{ - template - constexpr static bool has_overload(...) { return false; } - - template ().operator&()) > - constexpr static bool has_overload(bool) { return true; } - - constexpr static bool value = has_overload(true); -}; - -template )> -constexpr T* static_addressof(T& ref) -{ - return &ref; -} - -template )> -T* static_addressof(T& ref) -{ - return std::addressof(ref); -} - - -// the call to convert(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A -template -constexpr U convert(U v) { return v; } - -} // namespace detail - - -constexpr struct trivial_init_t{} trivial_init{}; - - -// 20.5.6, In-place construction -constexpr struct in_place_t{} in_place{}; - - -// 20.5.7, Disengaged state indicator -struct nullopt_t -{ - struct init{}; - constexpr explicit nullopt_t(init){} -}; -constexpr nullopt_t nullopt{nullopt_t::init()}; - - -// 20.5.8, class bad_optional_access -class bad_optional_access : public logic_error { -public: - explicit bad_optional_access(const string& what_arg) : logic_error{what_arg} {} - explicit bad_optional_access(const char* what_arg) : logic_error{what_arg} {} -}; - - -template -union storage_t -{ - unsigned char dummy_; - T value_; - - constexpr storage_t( trivial_init_t ) noexcept : dummy_() {}; - - template - constexpr storage_t( Args&&... args ) : value_(constexpr_forward(args)...) {} - - ~storage_t(){} -}; - - -template -union constexpr_storage_t -{ - unsigned char dummy_; - T value_; - - constexpr constexpr_storage_t( trivial_init_t ) noexcept : dummy_() {}; - - template - constexpr constexpr_storage_t( Args&&... args ) : value_(constexpr_forward(args)...) {} - - ~constexpr_storage_t() = default; -}; - - -template -struct optional_base -{ - bool init_; - storage_t storage_; - - constexpr optional_base() noexcept : init_(false), storage_(trivial_init) {}; - - explicit constexpr optional_base(const T& v) : init_(true), storage_(v) {} - - explicit constexpr optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} - - template explicit optional_base(in_place_t, Args&&... args) - : init_(true), storage_(constexpr_forward(args)...) {} - - template >)> - explicit optional_base(in_place_t, std::initializer_list il, Args&&... args) - : init_(true), storage_(il, std::forward(args)...) {} - - ~optional_base() { if (init_) storage_.value_.T::~T(); } -}; - - -template -struct constexpr_optional_base -{ - bool init_; - constexpr_storage_t storage_; - - constexpr constexpr_optional_base() noexcept : init_(false), storage_(trivial_init) {}; - - explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_(v) {} - - explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} - - template explicit constexpr constexpr_optional_base(in_place_t, Args&&... args) - : init_(true), storage_(constexpr_forward(args)...) {} - - template >)> - OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, std::initializer_list il, Args&&... args) - : init_(true), storage_(il, std::forward(args)...) {} - - ~constexpr_optional_base() = default; -}; - -template -using OptionalBase = typename std::conditional< - is_trivially_destructible::value, // if possible - constexpr_optional_base::type>, // use base with trivial destructor - optional_base::type> ->::type; - - - -template -class optional : private OptionalBase -{ - static_assert( !std::is_same::type, nullopt_t>::value, "bad T" ); - static_assert( !std::is_same::type, in_place_t>::value, "bad T" ); - - - constexpr bool initialized() const noexcept { return OptionalBase::init_; } - typename std::remove_const::type* dataptr() { return std::addressof(OptionalBase::storage_.value_); } - constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase::storage_.value_); } - -# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 - constexpr const T& contained_val() const& { return OptionalBase::storage_.value_; } -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 - OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return std::move(OptionalBase::storage_.value_); } - OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase::storage_.value_; } -# else - T& contained_val() & { return OptionalBase::storage_.value_; } - T&& contained_val() && { return std::move(OptionalBase::storage_.value_); } -# endif -# else - constexpr const T& contained_val() const { return OptionalBase::storage_.value_; } - T& contained_val() { return OptionalBase::storage_.value_; } -# endif - - void clear() noexcept { - if (initialized()) dataptr()->T::~T(); - OptionalBase::init_ = false; - } - - template - void initialize(Args&&... args) noexcept(noexcept(T(std::forward(args)...))) - { - assert(!OptionalBase::init_); - ::new (static_cast(dataptr())) T(std::forward(args)...); - OptionalBase::init_ = true; - } - - template - void initialize(std::initializer_list il, Args&&... args) noexcept(noexcept(T(il, std::forward(args)...))) - { - assert(!OptionalBase::init_); - ::new (static_cast(dataptr())) T(il, std::forward(args)...); - OptionalBase::init_ = true; - } - -public: - typedef T value_type; - - // 20.5.5.1, constructors - constexpr optional() noexcept : OptionalBase() {}; - constexpr optional(nullopt_t) noexcept : OptionalBase() {}; - - optional(const optional& rhs) - : OptionalBase() - { - if (rhs.initialized()) { - ::new (static_cast(dataptr())) T(*rhs); - OptionalBase::init_ = true; - } - } - - optional(optional&& rhs) noexcept(is_nothrow_move_constructible::value) - : OptionalBase() - { - if (rhs.initialized()) { - ::new (static_cast(dataptr())) T(std::move(*rhs)); - OptionalBase::init_ = true; - } - } - - constexpr optional(const T& v) : OptionalBase(v) {} - - constexpr optional(T&& v) : OptionalBase(constexpr_move(v)) {} - - template - explicit constexpr optional(in_place_t, Args&&... args) - : OptionalBase(in_place_t{}, constexpr_forward(args)...) {} - - template >)> - OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, std::initializer_list il, Args&&... args) - : OptionalBase(in_place_t{}, il, constexpr_forward(args)...) {} - - // 20.5.4.2, Destructor - ~optional() = default; - - // 20.5.4.3, assignment - optional& operator=(nullopt_t) noexcept - { - clear(); - return *this; - } - - optional& operator=(const optional& rhs) - { - if (initialized() == true && rhs.initialized() == false) clear(); - else if (initialized() == false && rhs.initialized() == true) initialize(*rhs); - else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs; - return *this; - } - - optional& operator=(optional&& rhs) - noexcept(is_nothrow_move_assignable::value && is_nothrow_move_constructible::value) - { - if (initialized() == true && rhs.initialized() == false) clear(); - else if (initialized() == false && rhs.initialized() == true) initialize(std::move(*rhs)); - else if (initialized() == true && rhs.initialized() == true) contained_val() = std::move(*rhs); - return *this; - } - - template - auto operator=(U&& v) - -> typename enable_if - < - is_same::type, T>::value, - optional& - >::type - { - if (initialized()) { contained_val() = std::forward(v); } - else { initialize(std::forward(v)); } - return *this; - } - - - template - void emplace(Args&&... args) - { - clear(); - initialize(std::forward(args)...); - } - - template - void emplace(initializer_list il, Args&&... args) - { - clear(); - initialize(il, std::forward(args)...); - } - - // 20.5.4.4, Swap - void swap(optional& rhs) noexcept(is_nothrow_move_constructible::value && noexcept(swap(declval(), declval()))) - { - if (initialized() == true && rhs.initialized() == false) { rhs.initialize(std::move(**this)); clear(); } - else if (initialized() == false && rhs.initialized() == true) { initialize(std::move(*rhs)); rhs.clear(); } - else if (initialized() == true && rhs.initialized() == true) { using std::swap; swap(**this, *rhs); } - } - - // 20.5.4.5, Observers - - explicit constexpr operator bool() const noexcept { return initialized(); } - constexpr bool has_value() const noexcept { return initialized(); } - - constexpr T const* operator ->() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr()); - } - -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 - - OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() { - assert (initialized()); - return dataptr(); - } - - constexpr T const& operator *() const& { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); - } - - OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & { - assert (initialized()); - return contained_val(); - } - - OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && { - assert (initialized()); - return constexpr_move(contained_val()); - } - - constexpr T const& value() const& { - return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); - } - - OPTIONAL_MUTABLE_CONSTEXPR T& value() & { - return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); - } - - OPTIONAL_MUTABLE_CONSTEXPR T&& value() && { - if (!initialized()) throw bad_optional_access("bad optional access"); - return std::move(contained_val()); - } - -# else - - T* operator ->() { - assert (initialized()); - return dataptr(); - } - - constexpr T const& operator *() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); - } - - T& operator *() { - assert (initialized()); - return contained_val(); - } - - constexpr T const& value() const { - return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); - } - - T& value() { - return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); - } - -# endif - -# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 - - template - constexpr T value_or(V&& v) const& - { - return *this ? **this : detail_::convert(constexpr_forward(v)); - } - -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 - - template - OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) && - { - return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v)); - } - -# else - - template - T value_or(V&& v) && - { - return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v)); - } - -# endif - -# else - - template - constexpr T value_or(V&& v) const - { - return *this ? **this : detail_::convert(constexpr_forward(v)); - } - -# endif - - // 20.6.3.6, modifiers - void reset() noexcept { clear(); } -}; - - -template -class optional -{ - static_assert( !std::is_same::value, "bad T" ); - static_assert( !std::is_same::value, "bad T" ); - T* ref; - -public: - - // 20.5.5.1, construction/destruction - constexpr optional() noexcept : ref(nullptr) {} - - constexpr optional(nullopt_t) noexcept : ref(nullptr) {} - - constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {} - - optional(T&&) = delete; - - constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {} - - explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {} - - explicit optional(in_place_t, T&&) = delete; - - ~optional() = default; - - // 20.5.5.2, mutation - optional& operator=(nullopt_t) noexcept { - ref = nullptr; - return *this; - } - - // optional& operator=(const optional& rhs) noexcept { - // ref = rhs.ref; - // return *this; - // } - - // optional& operator=(optional&& rhs) noexcept { - // ref = rhs.ref; - // return *this; - // } - - template - auto operator=(U&& rhs) noexcept - -> typename enable_if - < - is_same::type, optional>::value, - optional& - >::type - { - ref = rhs.ref; - return *this; - } - - template - auto operator=(U&& rhs) noexcept - -> typename enable_if - < - !is_same::type, optional>::value, - optional& - >::type - = delete; - - void emplace(T& v) noexcept { - ref = detail_::static_addressof(v); - } - - void emplace(T&&) = delete; - - - void swap(optional& rhs) noexcept - { - std::swap(ref, rhs.ref); - } - - // 20.5.5.3, observers - constexpr T* operator->() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref); - } - - constexpr T& operator*() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref); - } - - constexpr T& value() const { - return ref ? *ref : (throw bad_optional_access("bad optional access"), *ref); - } - - explicit constexpr operator bool() const noexcept { - return ref != nullptr; - } - - constexpr bool has_value() const noexcept { - return ref != nullptr; - } - - template - constexpr typename decay::type value_or(V&& v) const - { - return *this ? **this : detail_::convert::type>(constexpr_forward(v)); - } - - // x.x.x.x, modifiers - void reset() noexcept { ref = nullptr; } -}; - - -template -class optional -{ - static_assert( sizeof(T) == 0, "optional rvalue references disallowed" ); -}; - - -// 20.5.8, Relational operators -template constexpr bool operator==(const optional& x, const optional& y) -{ - return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y; -} - -template constexpr bool operator!=(const optional& x, const optional& y) -{ - return !(x == y); -} - -template constexpr bool operator<(const optional& x, const optional& y) -{ - return (!y) ? false : (!x) ? true : *x < *y; -} - -template constexpr bool operator>(const optional& x, const optional& y) -{ - return (y < x); -} - -template constexpr bool operator<=(const optional& x, const optional& y) -{ - return !(y < x); -} - -template constexpr bool operator>=(const optional& x, const optional& y) -{ - return !(x < y); -} - - -// 20.5.9, Comparison with nullopt -template constexpr bool operator==(const optional& x, nullopt_t) noexcept -{ - return (!x); -} - -template constexpr bool operator==(nullopt_t, const optional& x) noexcept -{ - return (!x); -} - -template constexpr bool operator!=(const optional& x, nullopt_t) noexcept -{ - return bool(x); -} - -template constexpr bool operator!=(nullopt_t, const optional& x) noexcept -{ - return bool(x); -} - -template constexpr bool operator<(const optional&, nullopt_t) noexcept -{ - return false; -} - -template constexpr bool operator<(nullopt_t, const optional& x) noexcept -{ - return bool(x); -} - -template constexpr bool operator<=(const optional& x, nullopt_t) noexcept -{ - return (!x); -} - -template constexpr bool operator<=(nullopt_t, const optional&) noexcept -{ - return true; -} - -template constexpr bool operator>(const optional& x, nullopt_t) noexcept -{ - return bool(x); -} - -template constexpr bool operator>(nullopt_t, const optional&) noexcept -{ - return false; -} - -template constexpr bool operator>=(const optional&, nullopt_t) noexcept -{ - return true; -} - -template constexpr bool operator>=(nullopt_t, const optional& x) noexcept -{ - return (!x); -} - - - -// 20.5.10, Comparison with T -template constexpr bool operator==(const optional& x, const T& v) -{ - return bool(x) ? *x == v : false; -} - -template constexpr bool operator==(const T& v, const optional& x) -{ - return bool(x) ? v == *x : false; -} - -template constexpr bool operator!=(const optional& x, const T& v) -{ - return bool(x) ? *x != v : true; -} - -template constexpr bool operator!=(const T& v, const optional& x) -{ - return bool(x) ? v != *x : true; -} - -template constexpr bool operator<(const optional& x, const T& v) -{ - return bool(x) ? *x < v : true; -} - -template constexpr bool operator>(const T& v, const optional& x) -{ - return bool(x) ? v > *x : true; -} - -template constexpr bool operator>(const optional& x, const T& v) -{ - return bool(x) ? *x > v : false; -} - -template constexpr bool operator<(const T& v, const optional& x) -{ - return bool(x) ? v < *x : false; -} - -template constexpr bool operator>=(const optional& x, const T& v) -{ - return bool(x) ? *x >= v : false; -} - -template constexpr bool operator<=(const T& v, const optional& x) -{ - return bool(x) ? v <= *x : false; -} - -template constexpr bool operator<=(const optional& x, const T& v) -{ - return bool(x) ? *x <= v : true; -} - -template constexpr bool operator>=(const T& v, const optional& x) -{ - return bool(x) ? v >= *x : true; -} - - -// Comparison of optional with T -template constexpr bool operator==(const optional& x, const T& v) -{ - return bool(x) ? *x == v : false; -} - -template constexpr bool operator==(const T& v, const optional& x) -{ - return bool(x) ? v == *x : false; -} - -template constexpr bool operator!=(const optional& x, const T& v) -{ - return bool(x) ? *x != v : true; -} - -template constexpr bool operator!=(const T& v, const optional& x) -{ - return bool(x) ? v != *x : true; -} - -template constexpr bool operator<(const optional& x, const T& v) -{ - return bool(x) ? *x < v : true; -} - -template constexpr bool operator>(const T& v, const optional& x) -{ - return bool(x) ? v > *x : true; -} - -template constexpr bool operator>(const optional& x, const T& v) -{ - return bool(x) ? *x > v : false; -} - -template constexpr bool operator<(const T& v, const optional& x) -{ - return bool(x) ? v < *x : false; -} - -template constexpr bool operator>=(const optional& x, const T& v) -{ - return bool(x) ? *x >= v : false; -} - -template constexpr bool operator<=(const T& v, const optional& x) -{ - return bool(x) ? v <= *x : false; -} - -template constexpr bool operator<=(const optional& x, const T& v) -{ - return bool(x) ? *x <= v : true; -} - -template constexpr bool operator>=(const T& v, const optional& x) -{ - return bool(x) ? v >= *x : true; -} - -// Comparison of optional with T -template constexpr bool operator==(const optional& x, const T& v) -{ - return bool(x) ? *x == v : false; -} - -template constexpr bool operator==(const T& v, const optional& x) -{ - return bool(x) ? v == *x : false; -} - -template constexpr bool operator!=(const optional& x, const T& v) -{ - return bool(x) ? *x != v : true; -} - -template constexpr bool operator!=(const T& v, const optional& x) -{ - return bool(x) ? v != *x : true; -} - -template constexpr bool operator<(const optional& x, const T& v) -{ - return bool(x) ? *x < v : true; -} - -template constexpr bool operator>(const T& v, const optional& x) -{ - return bool(x) ? v > *x : true; -} - -template constexpr bool operator>(const optional& x, const T& v) -{ - return bool(x) ? *x > v : false; -} - -template constexpr bool operator<(const T& v, const optional& x) -{ - return bool(x) ? v < *x : false; -} - -template constexpr bool operator>=(const optional& x, const T& v) -{ - return bool(x) ? *x >= v : false; -} - -template constexpr bool operator<=(const T& v, const optional& x) -{ - return bool(x) ? v <= *x : false; -} - -template constexpr bool operator<=(const optional& x, const T& v) -{ - return bool(x) ? *x <= v : true; -} - -template constexpr bool operator>=(const T& v, const optional& x) -{ - return bool(x) ? v >= *x : true; -} - - -// 20.5.12, Specialized algorithms -template -void swap(optional& x, optional& y) noexcept(noexcept(x.swap(y))) -{ - x.swap(y); -} - - -template -constexpr optional::type> make_optional(T&& v) -{ - return optional::type>(constexpr_forward(v)); -} - -template -constexpr optional make_optional(reference_wrapper v) -{ - return optional(v.get()); -} - - -} // namespace experimental -} // namespace std - -namespace std -{ - template - struct hash> - { - typedef typename hash::result_type result_type; - typedef std::experimental::optional argument_type; - - constexpr result_type operator()(argument_type const& arg) const { - return arg ? std::hash{}(*arg) : result_type{}; - } - }; - - template - struct hash> - { - typedef typename hash::result_type result_type; - typedef std::experimental::optional argument_type; - - constexpr result_type operator()(argument_type const& arg) const { - return arg ? std::hash{}(*arg) : result_type{}; - } - }; -} - -# undef TR2_OPTIONAL_REQUIRES -# undef TR2_OPTIONAL_ASSERTED_EXPRESSION - -# endif //___OPTIONAL_HPP___ diff --git a/include/tao/json/external/akrzemi1/test_optional.cpp b/include/tao/json/external/akrzemi1/test_optional.cpp deleted file mode 100644 index 1b2d6cc1..00000000 --- a/include/tao/json/external/akrzemi1/test_optional.cpp +++ /dev/null @@ -1,1520 +0,0 @@ -// Copyright (C) 2011 - 2016 Andrzej Krzemienski. -// -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The idea and interface is based on Boost.Optional library -// authored by Fernando Luis Cacciola Carballal - -# include "optional.hpp" -# include -# include -# include -# include - - - -struct caller { - template caller(T fun) { fun(); } -}; -# define CAT2(X, Y) X ## Y -# define CAT(X, Y) CAT2(X, Y) -# define TEST(NAME) caller CAT(__VAR, __LINE__) = [] - -enum State -{ - sDefaultConstructed, - sValueCopyConstructed, - sValueMoveConstructed, - sCopyConstructed, - sMoveConstructed, - sMoveAssigned, - sCopyAssigned, - sValueCopyAssigned, - sValueMoveAssigned, - sMovedFrom, - sValueConstructed -}; - -struct OracleVal -{ - State s; - int i; - OracleVal(int i = 0) : s(sValueConstructed), i(i) {} -}; - -struct Oracle -{ - State s; - OracleVal val; - - Oracle() : s(sDefaultConstructed) {} - Oracle(const OracleVal& v) : s(sValueCopyConstructed), val(v) {} - Oracle(OracleVal&& v) : s(sValueMoveConstructed), val(std::move(v)) {v.s = sMovedFrom;} - Oracle(const Oracle& o) : s(sCopyConstructed), val(o.val) {} - Oracle(Oracle&& o) : s(sMoveConstructed), val(std::move(o.val)) {o.s = sMovedFrom;} - - Oracle& operator=(const OracleVal& v) { s = sValueCopyConstructed; val = v; return *this; } - Oracle& operator=(OracleVal&& v) { s = sValueMoveConstructed; val = std::move(v); v.s = sMovedFrom; return *this; } - Oracle& operator=(const Oracle& o) { s = sCopyConstructed; val = o.val; return *this; } - Oracle& operator=(Oracle&& o) { s = sMoveConstructed; val = std::move(o.val); o.s = sMovedFrom; return *this; } -}; - -struct Guard -{ - std::string val; - Guard() : val{} {} - explicit Guard(std::string s, int = 0) : val(s) {} - Guard(const Guard&) = delete; - Guard(Guard&&) = delete; - void operator=(const Guard&) = delete; - void operator=(Guard&&) = delete; -}; - -struct ExplicitStr -{ - std::string s; - explicit ExplicitStr(const char* chp) : s(chp) {}; -}; - -struct Date -{ - int i; - Date() = delete; - Date(int i) : i{i} {}; - Date(Date&& d) : i(d.i) { d.i = 0; } - Date(const Date&) = delete; - Date& operator=(const Date&) = delete; - Date& operator=(Date&& d) { i = d.i; d.i = 0; return *this;}; -}; - -bool operator==( Oracle const& a, Oracle const& b ) { return a.val.i == b.val.i; } -bool operator!=( Oracle const& a, Oracle const& b ) { return a.val.i != b.val.i; } - - -namespace tr2 = std::experimental; - - -TEST(disengaged_ctor) -{ - tr2::optional o1; - assert (!o1); - - tr2::optional o2 = tr2::nullopt; - assert (!o2); - - tr2::optional o3 = o2; - assert (!o3); - - assert (o1 == tr2::nullopt); - assert (o1 == tr2::optional{}); - assert (!o1); - assert (bool(o1) == false); - - assert (o2 == tr2::nullopt); - assert (o2 == tr2::optional{}); - assert (!o2); - assert (bool(o2) == false); - - assert (o3 == tr2::nullopt); - assert (o3 == tr2::optional{}); - assert (!o3); - assert (bool(o3) == false); - - assert (o1 == o2); - assert (o2 == o1); - assert (o1 == o3); - assert (o3 == o1); - assert (o2 == o3); - assert (o3 == o2); -}; - - -TEST(value_ctor) -{ - OracleVal v; - tr2::optional oo1(v); - assert (oo1 != tr2::nullopt); - assert (oo1 != tr2::optional{}); - assert (oo1 == tr2::optional{v}); - assert (!!oo1); - assert (bool(oo1)); - // NA: assert (oo1->s == sValueCopyConstructed); - assert (oo1->s == sMoveConstructed); - assert (v.s == sValueConstructed); - - tr2::optional oo2(std::move(v)); - assert (oo2 != tr2::nullopt); - assert (oo2 != tr2::optional{}); - assert (oo2 == oo1); - assert (!!oo2); - assert (bool(oo2)); - // NA: assert (oo2->s == sValueMoveConstructed); - assert (oo2->s == sMoveConstructed); - assert (v.s == sMovedFrom); - - { - OracleVal v; - tr2::optional oo1{tr2::in_place, v}; - assert (oo1 != tr2::nullopt); - assert (oo1 != tr2::optional{}); - assert (oo1 == tr2::optional{v}); - assert (!!oo1); - assert (bool(oo1)); - assert (oo1->s == sValueCopyConstructed); - assert (v.s == sValueConstructed); - - tr2::optional oo2{tr2::in_place, std::move(v)}; - assert (oo2 != tr2::nullopt); - assert (oo2 != tr2::optional{}); - assert (oo2 == oo1); - assert (!!oo2); - assert (bool(oo2)); - assert (oo2->s == sValueMoveConstructed); - assert (v.s == sMovedFrom); - } -}; - - -TEST(assignment) -{ - tr2::optional oi; - oi = tr2::optional{1}; - assert (*oi == 1); - - oi = tr2::nullopt; - assert (!oi); - - oi = 2; - assert (*oi == 2); - - oi = {}; - assert (!oi); -}; - - -template -struct MoveAware -{ - T val; - bool moved; - MoveAware(T val) : val(val), moved(false) {} - MoveAware(MoveAware const&) = delete; - MoveAware(MoveAware&& rhs) : val(rhs.val), moved(rhs.moved) { - rhs.moved = true; - } - MoveAware& operator=(MoveAware const&) = delete; - MoveAware& operator=(MoveAware&& rhs) { - val = (rhs.val); - moved = (rhs.moved); - rhs.moved = true; - return *this; - } -}; - -TEST(moved_from_state) -{ - // first, test mock: - MoveAware i{1}, j{2}; - assert (i.val == 1); - assert (!i.moved); - assert (j.val == 2); - assert (!j.moved); - - MoveAware k = std::move(i); - assert (k.val == 1); - assert (!k.moved); - assert (i.val == 1); - assert (i.moved); - - k = std::move(j); - assert (k.val == 2); - assert (!k.moved); - assert (j.val == 2); - assert (j.moved); - - // now, test optional - tr2::optional> oi{1}, oj{2}; - assert (oi); - assert (!oi->moved); - assert (oj); - assert (!oj->moved); - - tr2::optional> ok = std::move(oi); - assert (ok); - assert (!ok->moved); - assert (oi); - assert (oi->moved); - - ok = std::move(oj); - assert (ok); - assert (!ok->moved); - assert (oj); - assert (oj->moved); -}; - - -TEST(copy_move_ctor_optional_int) -{ - tr2::optional oi; - tr2::optional oj = oi; - - assert (!oj); - assert (oj == oi); - assert (oj == tr2::nullopt); - assert (!bool(oj)); - - oi = 1; - tr2::optional ok = oi; - assert (!!ok); - assert (bool(ok)); - assert (ok == oi); - assert (ok != oj); - assert (*ok == 1); - - tr2::optional ol = std::move(oi); - assert (!!ol); - assert (bool(ol)); - assert (ol == oi); - assert (ol != oj); - assert (*ol == 1); -}; - - -TEST(optional_optional) -{ - tr2::optional> oi1 = tr2::nullopt; - assert (oi1 == tr2::nullopt); - assert (!oi1); - - { - tr2::optional> oi2 {tr2::in_place}; - assert (oi2 != tr2::nullopt); - assert (bool(oi2)); - assert (*oi2 == tr2::nullopt); - //assert (!(*oi2)); - //std::cout << typeid(**oi2).name() << std::endl; - } - - { - tr2::optional> oi2 {tr2::in_place, tr2::nullopt}; - assert (oi2 != tr2::nullopt); - assert (bool(oi2)); - assert (*oi2 == tr2::nullopt); - assert (!*oi2); - } - - { - tr2::optional> oi2 {tr2::optional{}}; - assert (oi2 != tr2::nullopt); - assert (bool(oi2)); - assert (*oi2 == tr2::nullopt); - assert (!*oi2); - } - - tr2::optional oi; - auto ooi = tr2::make_optional(oi); - static_assert( std::is_same>, decltype(ooi)>::value, ""); - -}; - -TEST(example_guard) -{ - using namespace tr2; - //FAILS: optional ogx(Guard("res1")); - //FAILS: optional ogx = "res1"; - //FAILS: optional ogx("res1"); - optional oga; // Guard is non-copyable (and non-moveable) - optional ogb(in_place, "res1"); // initialzes the contained value with "res1" - assert (bool(ogb)); - assert (ogb->val == "res1"); - - optional ogc(in_place); // default-constructs the contained value - assert (bool(ogc)); - assert (ogc->val == ""); - - oga.emplace("res1"); // initialzes the contained value with "res1" - assert (bool(oga)); - assert (oga->val == "res1"); - - oga.emplace(); // destroys the contained value and - // default-constructs the new one - assert (bool(oga)); - assert (oga->val == ""); - - oga = nullopt; // OK: make disengaged the optional Guard - assert (!(oga)); - //FAILS: ogb = {}; // ERROR: Guard is not Moveable -}; - - -void process(){} -void process(int ){} -void processNil(){} - - -TEST(example1) -{ - using namespace tr2; - optional oi; // create disengaged object - optional oj = nullopt; // alternative syntax - oi = oj; // assign disengaged object - optional ok = oj; // ok is disengaged - - if (oi) assert(false); // 'if oi is engaged...' - if (!oi) assert(true); // 'if oi is disengaged...' - - if (oi != nullopt) assert(false); // 'if oi is engaged...' - if (oi == nullopt) assert(true); // 'if oi is disengaged...' - - assert(oi == ok); // two disengaged optionals compare equal - - /////////////////////////////////////////////////////////////////////////// - optional ol{1}; // ol is engaged; its contained value is 1 - ok = 2; // ok becomes engaged; its contained value is 2 - oj = ol; // oj becomes engaged; its contained value is 1 - - assert(oi != ol); // disengaged != engaged - assert(ok != ol); // different contained values - assert(oj == ol); // same contained value - assert(oi < ol); // disengaged < engaged - assert(ol < ok); // less by contained value - - ///////////////////////////////////////////////////////////////////////////// - optional om{1}; // om is engaged; its contained value is 1 - optional on = om; // on is engaged; its contained value is 1 - om = 2; // om is engaged; its contained value is 2 - assert (on != om); // on still contains 3. They are not pointers - - ///////////////////////////////////////////////////////////////////////////// - int i = *ol; // i obtains the value contained in ol - assert (i == 1); - *ol = 9; // the object contained in ol becomes 9 - assert(*ol == 9); - assert(ol == make_optional(9)); - - /////////////////////////////////// - int p = 1; - optional op = p; - assert(*op == 1); - p = 2; - assert(*op == 1); // value contained in op is separated from p - - //////////////////////////////// - if (ol) - process(*ol); // use contained value if present - else - process(); // proceed without contained value - - if (!om) - processNil(); - else - process(*om); - - ///////////////////////////////////////// - process(ol.value_or(0)); // use 0 if ol is disengaged - - //////////////////////////////////////////// - ok = nullopt; // if ok was engaged calls T's dtor - oj = {}; // assigns a temporary disengaged optional -}; - - -TEST(example_guard) -{ - using std::experimental::optional; - const optional c = 4; - int i = *c; // i becomes 4 - assert (i == 4); - // FAILS: *c = i; // ERROR: cannot assign to const int& -}; - - -TEST(example_ref) -{ - using namespace std::experimental; - int i = 1; - int j = 2; - optional ora; // disengaged optional reference to int - optional orb = i; // contained reference refers to object i - - *orb = 3; // i becomes 3 - // FAILS: ora = j; // ERROR: optional refs do not have assignment from T - // FAILS: ora = {j}; // ERROR: optional refs do not have copy/move assignment - // FAILS: ora = orb; // ERROR: no copy/move assignment - ora.emplace(j); // OK: contained reference refers to object j - ora.emplace(i); // OK: contained reference now refers to object i - - ora = nullopt; // OK: ora becomes disengaged -}; - - -template -T getValue( tr2::optional newVal = tr2::nullopt, tr2::optional storeHere = tr2::nullopt ) -{ - T cached{}; - - if (newVal) { - cached = *newVal; - - if (storeHere) { - *storeHere = *newVal; // LEGAL: assigning T to T - } - } - return cached; -} - -TEST(example_optional_arg) -{ - int iii = 0; - iii = getValue(iii, iii); - iii = getValue(iii); - iii = getValue(); - - { - using namespace std::experimental; - optional grd1{in_place, "res1", 1}; // guard 1 initialized - optional grd2; - - grd2.emplace("res2", 2); // guard 2 initialized - grd1 = nullopt; // guard 1 released - - } // guard 2 released (in dtor) -}; - - -std::tuple getStartMidEnd() { return std::tuple{Date{1}, Date{2}, Date{3}}; } -void run(Date const&, Date const&, Date const&) {} - -TEST(example_date) -{ - using namespace std::experimental; - optional start, mid, end; // Date doesn't have default ctor (no good default date) - - std::tie(start, mid, end) = getStartMidEnd(); - run(*start, *mid, *end); -}; - - -std::experimental::optional readNextChar(){ return{}; } - -void run(std::experimental::optional) {} -void run(std::complex) {} - - -template -void assign_norebind(tr2::optional& optref, T& obj) -{ - if (optref) *optref = obj; - else optref.emplace(obj); -} - -template void unused(T&&) {} - -TEST(example_conceptual_model) -{ - using namespace std::experimental; - - optional oi = 0; - optional oj = 1; - optional ok = nullopt; - - oi = 1; - oj = nullopt; - ok = 0; - - unused(oi == nullopt); - unused(oj == 0); - unused(ok == 1); -}; - -TEST(example_rationale) -{ - using namespace std::experimental; - if (optional ch = readNextChar()) { - unused(ch); - // ... - } - - ////////////////////////////////// - optional opt1 = nullopt; - optional opt2 = {}; - - opt1 = nullopt; - opt2 = {}; - - if (opt1 == nullopt) {} - if (!opt2) {} - if (opt2 == optional{}) {} - - - - //////////////////////////////// - - run(nullopt); // pick the second overload - // FAILS: run({}); // ambiguous - - if (opt1 == nullopt) {} // fine - // FAILS: if (opt2 == {}) {} // ilegal - - //////////////////////////////// - assert (optional{} < optional{0}); - assert (optional{0} < optional{1}); - assert (!(optional{} < optional{}) ); - assert (!(optional{1} < optional{1})); - - assert (optional{} != optional{0}); - assert (optional{0} != optional{1}); - assert (optional{} == optional{} ); - assert (optional{0} == optional{0}); - - ///////////////////////////////// - optional o; - o = make_optional(1); // copy/move assignment - o = 1; // assignment from T - o.emplace(1); // emplacement - - //////////////////////////////////// - int isas = 0, i = 9; - optional asas = i; - assign_norebind(asas, isas); - - ///////////////////////////////////// - ////tr2::optional> ov2 = {2, 3}; - ////assert (bool(ov2)); - ////assert ((*ov2)[1] == 3); - //// - //////////////////////////////// - ////std::vector v = {1, 2, 4, 8}; - ////optional> ov = {1, 2, 4, 8}; - - ////assert (v == *ov); - //// - ////ov = {1, 2, 4, 8}; - - ////std::allocator a; - ////optional> ou { in_place, {1, 2, 4, 8}, a }; - - ////assert (ou == ov); - - ////////////////////////////// - // inconvenient syntax: - { - - tr2::optional> ov2{tr2::in_place, {2, 3}}; - - assert (bool(ov2)); - assert ((*ov2)[1] == 3); - - //////////////////////////// - - std::vector v = {1, 2, 4, 8}; - optional> ov{tr2::in_place, {1, 2, 4, 8}}; - - assert (v == *ov); - - ov.emplace({1, 2, 4, 8}); -/* - std::allocator a; - optional> ou { in_place, {1, 2, 4, 8}, a }; - - assert (ou == ov); -*/ - } - - ///////////////////////////////// - { - typedef int T; - optional> ot {in_place}; - optional> ou {in_place, nullopt}; - optional> ov {optional{}}; - - optional oi; - auto ooi = make_optional(oi); - static_assert( std::is_same>, decltype(ooi)>::value, ""); - } -}; - - -bool fun(std::string , std::experimental::optional oi = std::experimental::nullopt) -{ - return bool(oi); -} - -TEST(example_converting_ctor) -{ - using namespace std::experimental; - - assert (true == fun("dog", 2)); - assert (false == fun("dog")); - assert (false == fun("dog", nullopt)); // just to be explicit -}; - - -TEST(bad_comparison) -{ - tr2::optional oi, oj; - int i; - bool b = (oi == oj); - b = (oi >= i); - b = (oi == i); - unused(b); -}; - - -//// NOT APPLICABLE ANYMORE -////TEST(perfect_ctor) -////{ -//// //tr2::optional ois = "OS"; -//// assert (*ois == "OS"); -//// -//// // FAILS: tr2::optional oes = "OS"; -//// tr2::optional oes{"OS"}; -//// assert (oes->s == "OS"); -////}; - -TEST(value_or) -{ - tr2::optional oi = 1; - int i = oi.value_or(0); - assert (i == 1); - - oi = tr2::nullopt; - assert (oi.value_or(3) == 3); - - tr2::optional os{"AAA"}; - assert (os.value_or("BBB") == "AAA"); - os = {}; - assert (os.value_or("BBB") == "BBB"); -}; - -TEST(reset) -{ - using namespace std::experimental; - optional oi {1}; - oi.reset(); - assert (!oi); - - int i = 1; - optional oir {i}; - oir.reset(); - assert (!oir); -}; - -TEST(mixed_order) -{ - using namespace std::experimental; - - optional oN {nullopt}; - optional o0 {0}; - optional o1 {1}; - - assert ( (oN < 0)); - assert ( (oN < 1)); - assert (!(o0 < 0)); - assert ( (o0 < 1)); - assert (!(o1 < 0)); - assert (!(o1 < 1)); - - assert (!(oN >= 0)); - assert (!(oN >= 1)); - assert ( (o0 >= 0)); - assert (!(o0 >= 1)); - assert ( (o1 >= 0)); - assert ( (o1 >= 1)); - - assert (!(oN > 0)); - assert (!(oN > 1)); - assert (!(o0 > 0)); - assert (!(o0 > 1)); - assert ( (o1 > 0)); - assert (!(o1 > 1)); - - assert ( (oN <= 0)); - assert ( (oN <= 1)); - assert ( (o0 <= 0)); - assert ( (o0 <= 1)); - assert (!(o1 <= 0)); - assert ( (o1 <= 1)); - - assert ( (0 > oN)); - assert ( (1 > oN)); - assert (!(0 > o0)); - assert ( (1 > o0)); - assert (!(0 > o1)); - assert (!(1 > o1)); - - assert (!(0 <= oN)); - assert (!(1 <= oN)); - assert ( (0 <= o0)); - assert (!(1 <= o0)); - assert ( (0 <= o1)); - assert ( (1 <= o1)); - - assert (!(0 < oN)); - assert (!(1 < oN)); - assert (!(0 < o0)); - assert (!(1 < o0)); - assert ( (0 < o1)); - assert (!(1 < o1)); - - assert ( (0 >= oN)); - assert ( (1 >= oN)); - assert ( (0 >= o0)); - assert ( (1 >= o0)); - assert (!(0 >= o1)); - assert ( (1 >= o1)); -}; - -struct BadRelops -{ - int i; -}; - -constexpr bool operator<(BadRelops a, BadRelops b) { return a.i < b.i; } -constexpr bool operator>(BadRelops a, BadRelops b) { return a.i < b.i; } // intentional error! - -TEST(bad_relops) -{ - using namespace std::experimental; - BadRelops a{1}, b{2}; - assert (a < b); - assert (a > b); - - optional oa = a, ob = b; - assert (oa < ob); - assert (!(oa > ob)); - - assert (oa < b); - assert (oa > b); - - optional ra = a, rb = b; - assert (ra < rb); - assert (!(ra > rb)); - - assert (ra < b); - assert (ra > b); -}; - - -TEST(mixed_equality) -{ - using namespace std::experimental; - - assert (make_optional(0) == 0); - assert (make_optional(1) == 1); - assert (make_optional(0) != 1); - assert (make_optional(1) != 0); - - optional oN {nullopt}; - optional o0 {0}; - optional o1 {1}; - - assert (o0 == 0); - assert ( 0 == o0); - assert (o1 == 1); - assert ( 1 == o1); - assert (o1 != 0); - assert ( 0 != o1); - assert (o0 != 1); - assert ( 1 != o0); - - assert ( 1 != oN); - assert ( 0 != oN); - assert (oN != 1); - assert (oN != 0); - assert (!( 1 == oN)); - assert (!( 0 == oN)); - assert (!(oN == 1)); - assert (!(oN == 0)); - - std::string cat{"cat"}, dog{"dog"}; - optional oNil{}, oDog{"dog"}, oCat{"cat"}; - - assert (oCat == cat); - assert ( cat == oCat); - assert (oDog == dog); - assert ( dog == oDog); - assert (oDog != cat); - assert ( cat != oDog); - assert (oCat != dog); - assert ( dog != oCat); - - assert ( dog != oNil); - assert ( cat != oNil); - assert (oNil != dog); - assert (oNil != cat); - assert (!( dog == oNil)); - assert (!( cat == oNil)); - assert (!(oNil == dog)); - assert (!(oNil == cat)); -}; - -TEST(const_propagation) -{ - using namespace std::experimental; - - optional mmi{0}; - static_assert(std::is_same::value, "WTF"); - - const optional cmi{0}; - static_assert(std::is_same::value, "WTF"); - - optional mci{0}; - static_assert(std::is_same::value, "WTF"); - - optional cci{0}; - static_assert(std::is_same::value, "WTF"); -}; - - -static_assert(std::is_base_of::value, ""); - -TEST(safe_value) -{ - using namespace std::experimental; - - try { - optional ovN{}, ov1{1}; - - int& r1 = ov1.value(); - assert (r1 == 1); - - try { - ovN.value(); - assert (false); - } - catch (bad_optional_access const&) { - } - - { // ref variant - int i1 = 1; - optional orN{}, or1{i1}; - - int& r2 = or1.value(); - assert (r2 == 1); - - try { - orN.value(); - assert (false); - } - catch (bad_optional_access const&) { - } - } - } - catch(...) { - assert (false); - } -}; - -TEST(optional_ref) -{ - using namespace tr2; - // FAILS: optional orr; - // FAILS: optional on; - int i = 8; - optional ori; - assert (!ori); - ori.emplace(i); - assert (bool(ori)); - assert (*ori == 8); - assert (&*ori == &i); - *ori = 9; - assert (i == 9); - - // FAILS: int& ir = ori.value_or(i); - int ii = ori.value_or(i); - assert (ii == 9); - ii = 7; - assert (*ori == 9); - - int j = 22; - auto&& oj = make_optional(std::ref(j)); - *oj = 23; - assert (&*oj == &j); - assert (j == 23); -}; - -TEST(optional_ref_const_propagation) -{ - using namespace std::experimental; - - int i = 9; - const optional mi = i; - int& r = *mi; - optional ci = i; - static_assert(std::is_same::value, "WTF"); - static_assert(std::is_same::value, "WTF"); - - unused(r); -}; - -TEST(optional_ref_assign) -{ - using namespace std::experimental; - - int i = 9; - optional ori = i; - - int j = 1; - ori = optional{j}; - ori = {j}; - // FAILS: ori = j; - - optional orx = ori; - ori = orx; - - optional orj = j; - - assert (ori); - assert (*ori == 1); - assert (ori == orj); - assert (i == 9); - - *ori = 2; - assert (*ori == 2); - assert (ori == 2); - assert (2 == ori); - assert (ori != 3); - - assert (ori == orj); - assert (j == 2); - assert (i == 9); - - ori = {}; - assert (!ori); - assert (ori != orj); - assert (j == 2); - assert (i == 9); -}; - - -TEST(optional_ref_swap) -{ - using namespace std::experimental; - int i = 0; - int j = 1; - optional oi = i; - optional oj = j; - - assert (&*oi == &i); - assert (&*oj == &j); - - swap(oi, oj); - assert (&*oi == &j); - assert (&*oj == &i); -}; - -TEST(optional_initialization) -{ - using namespace tr2; - using std::string; - string s = "STR"; - - optional os{s}; - optional ot = s; - optional ou{"STR"}; - optional ov = string{"STR"}; - -}; - -#include - -TEST(optional_hashing) -{ - using namespace tr2; - using std::string; - - std::hash hi; - std::hash> hoi; - std::hash hs; - std::hash> hos; - - assert (hi(0) == hoi(optional{0})); - assert (hi(1) == hoi(optional{1})); - assert (hi(3198) == hoi(optional{3198})); - - assert (hs("") == hos(optional{""})); - assert (hs("0") == hos(optional{"0"})); - assert (hs("Qa1#") == hos(optional{"Qa1#"})); - - std::unordered_set> set; - assert(set.find({"Qa1#"}) == set.end()); - - set.insert({"0"}); - assert(set.find({"Qa1#"}) == set.end()); - - set.insert({"Qa1#"}); - assert(set.find({"Qa1#"}) != set.end()); -}; - - -// optional_ref_emulation -template -struct generic -{ - typedef T type; -}; - -template -struct generic -{ - typedef std::reference_wrapper type; -}; - -template -using Generic = typename generic::type; - -template -bool generic_fun() -{ - std::experimental::optional> op; - return bool(op); -} - -TEST(optional_ref_emulation) -{ - using namespace std::experimental; - optional> oi = 1; - assert (*oi == 1); - - int i = 8; - int j = 4; - optional> ori {i}; - assert (*ori == 8); - assert ((void*)&*ori != (void*)&i); // !DIFFERENT THAN optional - - *ori = j; - assert (*ori == 4); -}; - - -# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 -TEST(moved_on_value_or) -{ - using namespace tr2; - optional oo{in_place}; - - assert (oo); - assert (oo->s == sDefaultConstructed); - - Oracle o = std::move(oo).value_or( Oracle{OracleVal{}} ); - assert (oo); - assert (oo->s == sMovedFrom); - assert (o.s == sMoveConstructed); - - optional> om {in_place, 1}; - assert (om); - assert (om->moved == false); - - /*MoveAware m =*/ std::move(om).value_or( MoveAware{1} ); - assert (om); - assert (om->moved == true); - -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 - { - Date d = optional{in_place, 1}.value(); - assert (d.i); // to silence compiler warning - - Date d2 = *optional{in_place, 1}; - assert (d2.i); // to silence compiler warning - } -# endif -}; -# endif - - -TEST(optional_ref_hashing) -{ - using namespace tr2; - using std::string; - - std::hash hi; - std::hash> hoi; - std::hash hs; - std::hash> hos; - - int i0 = 0; - int i1 = 1; - assert (hi(0) == hoi(optional{i0})); - assert (hi(1) == hoi(optional{i1})); - - string s{""}; - string s0{"0"}; - string sCAT{"CAT"}; - assert (hs("") == hos(optional{s})); - assert (hs("0") == hos(optional{s0})); - assert (hs("CAT") == hos(optional{sCAT})); - - std::unordered_set> set; - assert(set.find({sCAT}) == set.end()); - - set.insert({s0}); - assert(set.find({sCAT}) == set.end()); - - set.insert({sCAT}); - assert(set.find({sCAT}) != set.end()); -}; - -struct Combined -{ - int m = 0; - int n = 1; - - constexpr Combined() : m{5}, n{6} {} - constexpr Combined(int m, int n) : m{m}, n{n} {} -}; - -struct Nasty -{ - int m = 0; - int n = 1; - - constexpr Nasty() : m{5}, n{6} {} - constexpr Nasty(int m, int n) : m{m}, n{n} {} - - int operator&() { return n; } - int operator&() const { return n; } -}; - -TEST(arrow_operator) -{ - using namespace std::experimental; - - optional oc1{in_place, 1, 2}; - assert (oc1); - assert (oc1->m == 1); - assert (oc1->n == 2); - - optional on{in_place, 1, 2}; - assert (on); - assert (on->m == 1); - assert (on->n == 2); -}; - -TEST(arrow_wit_optional_ref) -{ - using namespace std::experimental; - - Combined c{1, 2}; - optional oc = c; - assert (oc); - assert (oc->m == 1); - assert (oc->n == 2); - - Nasty n{1, 2}; - Nasty m{3, 4}; - Nasty p{5, 6}; - - optional on{n}; - assert (on); - assert (on->m == 1); - assert (on->n == 2); - - on = {m}; - assert (on); - assert (on->m == 3); - assert (on->n == 4); - - on.emplace(p); - assert (on); - assert (on->m == 5); - assert (on->n == 6); - - optional om{in_place, n}; - assert (om); - assert (om->m == 1); - assert (om->n == 2); -}; - -TEST(no_dangling_reference_in_value) -{ - // this mostly tests compiler warnings - using namespace std::experimental; - optional oi {2}; - unused (oi.value()); - const optional coi {3}; - unused (coi.value()); -}; - -struct CountedObject -{ - static int _counter; - bool _throw; - CountedObject(bool b) : _throw(b) { ++_counter; } - CountedObject(CountedObject const& rhs) : _throw(rhs._throw) { if (_throw) throw int(); } - ~CountedObject() { --_counter; } -}; - -int CountedObject::_counter = 0; - -TEST(exception_safety) -{ - using namespace std::experimental; - try { - optional oo(in_place, true); // throw - optional o1(oo); - } - catch(...) - { - // - } - assert(CountedObject::_counter == 0); - - try { - optional oo(in_place, true); // throw - optional o1(std::move(oo)); // now move - } - catch(...) - { - // - } - assert(CountedObject::_counter == 0); -}; - -TEST(nested_optional) -{ - using namespace std::experimental; - - optional>> o1 {nullopt}; - assert (!o1); - - optional>> o2 {in_place, nullopt}; - assert (o2); - assert (!*o2); - - optional>> o3 (in_place, in_place, nullopt); - assert (o3); - assert (*o3); - assert (!**o3); -}; - -TEST(three_ways_of_having_value) -{ - using namespace std::experimental; - optional oN, o1 (1); - - assert (!oN); - assert (!oN.has_value()); - assert (oN == nullopt); - - assert (o1); - assert (o1.has_value()); - assert (o1 != nullopt); - - assert (bool(oN) == oN.has_value()); - assert (bool(o1) == o1.has_value()); - - int i = 1; - optional rN, r1 (i); - - assert (!rN); - assert (!rN.has_value()); - assert (rN == nullopt); - - assert (r1); - assert (r1.has_value()); - assert (r1 != nullopt); - - assert (bool(rN) == rN.has_value()); - assert (bool(r1) == r1.has_value()); -}; - -//// constexpr tests - -// these 4 classes have different noexcept signatures in move operations -struct NothrowBoth { - NothrowBoth(NothrowBoth&&) noexcept(true) {}; - void operator=(NothrowBoth&&) noexcept(true) {}; -}; -struct NothrowCtor { - NothrowCtor(NothrowCtor&&) noexcept(true) {}; - void operator=(NothrowCtor&&) noexcept(false) {}; -}; -struct NothrowAssign { - NothrowAssign(NothrowAssign&&) noexcept(false) {}; - void operator=(NothrowAssign&&) noexcept(true) {}; -}; -struct NothrowNone { - NothrowNone(NothrowNone&&) noexcept(false) {}; - void operator=(NothrowNone&&) noexcept(false) {}; -}; - -void test_noexcept() -{ - { - tr2::optional b1, b2; - static_assert(noexcept(tr2::optional{tr2::constexpr_move(b1)}), "bad noexcept!"); - static_assert(noexcept(b1 = tr2::constexpr_move(b2)), "bad noexcept!"); - } - { - tr2::optional c1, c2; - static_assert(noexcept(tr2::optional{tr2::constexpr_move(c1)}), "bad noexcept!"); - static_assert(!noexcept(c1 = tr2::constexpr_move(c2)), "bad noexcept!"); - } - { - tr2::optional a1, a2; - static_assert(!noexcept(tr2::optional{tr2::constexpr_move(a1)}), "bad noexcept!"); - static_assert(!noexcept(a1 = tr2::constexpr_move(a2)), "bad noexcept!"); - } - { - tr2::optional n1, n2; - static_assert(!noexcept(tr2::optional{tr2::constexpr_move(n1)}), "bad noexcept!"); - static_assert(!noexcept(n1 = tr2::constexpr_move(n2)), "bad noexcept!"); - } -} - - -void constexpr_test_disengaged() -{ - constexpr tr2::optional g0{}; - constexpr tr2::optional g1{tr2::nullopt}; - static_assert( !g0, "initialized!" ); - static_assert( !g1, "initialized!" ); - - static_assert( bool(g1) == bool(g0), "ne!" ); - - static_assert( g1 == g0, "ne!" ); - static_assert( !(g1 != g0), "ne!" ); - static_assert( g1 >= g0, "ne!" ); - static_assert( !(g1 > g0), "ne!" ); - static_assert( g1 <= g0, "ne!" ); - static_assert( !(g1 = tr2::nullopt, "!" ); - static_assert( !(g1 > tr2::nullopt), "!" ); - - static_assert( (tr2::nullopt == g0), "!" ); - static_assert( !(tr2::nullopt != g0), "!" ); - static_assert( (tr2::nullopt >= g0), "!" ); - static_assert( !(tr2::nullopt > g0), "!" ); - static_assert( (tr2::nullopt <= g0), "!" ); - static_assert( !(tr2::nullopt < g0), "!" ); - - static_assert( (g1 != tr2::optional(1)), "!" ); - static_assert( !(g1 == tr2::optional(1)), "!" ); - static_assert( (g1 < tr2::optional(1)), "!" ); - static_assert( (g1 <= tr2::optional(1)), "!" ); - static_assert( !(g1 > tr2::optional(1)), "!" ); - static_assert( !(g1 > tr2::optional(1)), "!" ); -} - - -constexpr tr2::optional g0{}; -constexpr tr2::optional g2{2}; -static_assert( g2, "not initialized!" ); -static_assert( *g2 == 2, "not 2!" ); -static_assert( g2 == tr2::optional(2), "not 2!" ); -static_assert( g2 != g0, "eq!" ); - -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 -static_assert( *tr2::optional{3} == 3, "WTF!" ); -static_assert( tr2::optional{3}.value() == 3, "WTF!" ); -static_assert( tr2::optional{3}.value_or(1) == 3, "WTF!" ); -static_assert( tr2::optional{}.value_or(4) == 4, "WTF!" ); -# endif - -constexpr tr2::optional gc0{tr2::in_place}; -static_assert(gc0->n == 6, "WTF!"); - -// optional refs -int gi = 0; -constexpr tr2::optional gori = gi; -constexpr tr2::optional gorn{}; -constexpr int& gri = *gori; -static_assert(gori, "WTF"); -static_assert(!gorn, "WTF"); -static_assert(gori != tr2::nullopt, "WTF"); -static_assert(gorn == tr2::nullopt, "WTF"); -static_assert(&gri == &*gori, "WTF"); - -constexpr int gci = 1; -constexpr tr2::optional gorci = gci; -constexpr tr2::optional gorcn{}; - -static_assert(gorcn < gorci, "WTF"); -static_assert(gorcn <= gorci, "WTF"); -static_assert(gorci == gorci, "WTF"); -static_assert(*gorci == 1, "WTF"); -static_assert(gorci == gci, "WTF"); - -namespace constexpr_optional_ref_and_arrow -{ - using namespace std::experimental; - constexpr Combined c{1, 2}; - constexpr optional oc = c; - static_assert(oc, "WTF!"); - static_assert(oc->m == 1, "WTF!"); - static_assert(oc->n == 2, "WTF!"); -} - -#if OPTIONAL_HAS_CONSTEXPR_INIT_LIST - -namespace InitList -{ - using namespace std::experimental; - - struct ConstInitLister - { - template - constexpr ConstInitLister(std::initializer_list il) : len (il.size()) {} - size_t len; - }; - - constexpr ConstInitLister CIL {2, 3, 4}; - static_assert(CIL.len == 3, "WTF!"); - - constexpr optional oil {in_place, {4, 5, 6, 7}}; - static_assert(oil, "WTF!"); - static_assert(oil->len == 4, "WTF!"); -} - -#endif // OPTIONAL_HAS_CONSTEXPR_INIT_LIST - -// end constexpr tests - - -#include - - -struct VEC -{ - std::vector v; - template - VEC( X&&...x) : v(std::forward(x)...) {} - - template - VEC(std::initializer_list il, X&&...x) : v(il, std::forward(x)...) {} -}; - - - -int main() { - tr2::optional oi = 1; - assert (bool(oi)); - oi.operator=({}); - assert (!oi); - - VEC v = {5, 6}; - - if (OPTIONAL_HAS_THIS_RVALUE_REFS) - std::cout << "Optional has rvalue references for *this" << std::endl; - else - std::cout << "Optional doesn't have rvalue references for *this" << std::endl; - - if (OPTIONAL_HAS_CONSTEXPR_INIT_LIST) - std::cout << "Optional has constexpr initializer_list" << std::endl; - else - std::cout << "Optional doesn't have constexpr initializer_list" << std::endl; - - if (OPTIONAL_HAS_MOVE_ACCESSORS) - std::cout << "Optional has constexpr move accessors" << std::endl; - else - std::cout << "Optional doesn't have constexpr move accessors" << std::endl; -} - diff --git a/include/tao/json/external/akrzemi1/test_type_traits.cpp b/include/tao/json/external/akrzemi1/test_type_traits.cpp deleted file mode 100644 index 8ec82b70..00000000 --- a/include/tao/json/external/akrzemi1/test_type_traits.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (C) 2011 - 2012 Andrzej Krzemienski. -// -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#if (defined __clang__) - namespace std { class type_info; } -#endif - -# include "optional.hpp" - -namespace std { namespace experimental { - -struct Val -{ - Val(){} - Val( Val const & ){} - Val( Val && ) noexcept {} - - Val & operator=( Val const & ) = delete; - Val & operator=( Val && ) noexcept = delete; -}; - -struct Safe -{ - Safe(){} - Safe( Safe const & ){} - Safe( Safe && ) noexcept {} - - Safe & operator=( Safe const & ){ return *this; } - Safe & operator=( Safe && ) noexcept { return *this; } -}; - -struct Unsafe -{ - Unsafe(){} - Unsafe( Unsafe const & ){} - Unsafe( Unsafe && ){} - - Unsafe & operator=( Unsafe const & ){ return *this; } - Unsafe & operator=( Unsafe && ) { return *this; } -}; - -struct VoidNothrowBoth -{ - VoidNothrowBoth(VoidNothrowBoth&&) noexcept(true) {}; - void operator=(VoidNothrowBoth&&) noexcept(true) {}; // note void return type -}; - - -static_assert(is_nothrow_move_constructible::value, "WTF!"); -static_assert(!is_nothrow_move_constructible::value, "WTF!"); - -static_assert(is_assignable::value, "WTF!"); -static_assert(!is_assignable::value, "WTF!"); - -static_assert(is_nothrow_move_assignable::value, "WTF!"); -static_assert(!is_nothrow_move_assignable::value, "WTF!"); - -static_assert(is_nothrow_move_constructible::value, "WTF!"); -static_assert(is_nothrow_move_assignable::value, "WTF!"); - -}} // namespace std::experimental - -int main() { } diff --git a/include/tao/json/external/byte.hpp b/include/tao/json/external/byte.hpp deleted file mode 100644 index c3325093..00000000 --- a/include/tao/json/external/byte.hpp +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_INCLUDE_BYTE_HPP -#define TAOCPP_INCLUDE_BYTE_HPP - -#ifndef TAOCPP_USE_STD_BYTE -#if __cplusplus >= 201703L -#define TAOCPP_USE_STD_BYTE -#endif -#endif - -#if defined( TAOCPP_USE_STD_BYTE ) -#include -#else -#include -#endif - -namespace tao -{ - -#if defined( TAOCPP_USE_STD_BYTE ) - using std::byte; - using std::to_integer; -#else - - // this is C++17's std::byte, including support functions. - // note that prior to C++17, due to the lack of the - // relaxed enum class initialization rules, - // the byte{42}-syntax does not work. - enum class byte : unsigned char - { - }; - - template< class IntType > - typename std::enable_if< std::is_integral< IntType >::value, byte& >::type - operator<<=( byte& b, IntType shift ) noexcept - { - return b = byte( static_cast< unsigned char >( b ) << shift ); - } - - template< class IntType > - constexpr typename std::enable_if< std::is_integral< IntType >::value, byte >::type - operator<<( byte b, IntType shift ) noexcept - { - return byte( static_cast< unsigned char >( b ) << shift ); - } - - template< class IntType > - typename std::enable_if< std::is_integral< IntType >::value, byte& >::type - operator>>=( byte& b, IntType shift ) noexcept - { - return b = byte( static_cast< unsigned char >( b ) >> shift ); - } - - template< class IntType > - constexpr typename std::enable_if< std::is_integral< IntType >::value, byte >::type - operator>>( byte b, IntType shift ) noexcept - { - return byte( static_cast< unsigned char >( b ) >> shift ); - } - - inline byte& operator|=( byte& l, byte r ) noexcept - { - return l = byte( static_cast< unsigned char >( l ) | static_cast< unsigned char >( r ) ); - } - - constexpr byte operator|( byte l, byte r ) noexcept - { - return byte( static_cast< unsigned char >( l ) | static_cast< unsigned char >( r ) ); - } - - inline byte& operator&=( byte& l, byte r ) noexcept - { - return l = byte( static_cast< unsigned char >( l ) & static_cast< unsigned char >( r ) ); - } - - constexpr byte operator&( byte l, byte r ) noexcept - { - return byte( static_cast< unsigned char >( l ) & static_cast< unsigned char >( r ) ); - } - - inline byte& operator^=( byte& l, byte r ) noexcept - { - return l = byte( static_cast< unsigned char >( l ) ^ static_cast< unsigned char >( r ) ); - } - - constexpr byte operator^( byte l, byte r ) noexcept - { - return byte( static_cast< unsigned char >( l ) ^ static_cast< unsigned char >( r ) ); - } - - constexpr byte operator~( byte b ) noexcept - { - return byte( ~static_cast< unsigned char >( b ) ); - } - - template< class IntType > - constexpr typename std::enable_if< std::is_integral< IntType >::value, IntType >::type - to_integer( byte b ) noexcept - { - return IntType( b ); - } - -#endif - -} // namespace tao - -#endif diff --git a/include/tao/json/external/double.hpp b/include/tao/json/external/double.hpp index 6e634bc5..9087c4e8 100644 --- a/include/tao/json/external/double.hpp +++ b/include/tao/json/external/double.hpp @@ -30,26 +30,18 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#ifndef TAOCPP_JSON_INCLUDE_EXTERNAL_DOUBLE_HPP -#define TAOCPP_JSON_INCLUDE_EXTERNAL_DOUBLE_HPP +#ifndef TAO_JSON_EXTERNAL_DOUBLE_HPP +#define TAO_JSON_EXTERNAL_DOUBLE_HPP + +// clang-format off -#include -#include -#include -#include #include -#include - -#ifndef ASSERT -#define ASSERT( eXPReSSioN ) ((void)0) -#endif -#ifndef UNIMPLEMENTED -#define UNIMPLEMENTED() (abort()) -#endif -#ifndef UNREACHABLE -#define UNREACHABLE() (abort()) -#endif +#include +#include +#include +#include +#include // Double operations detection based on target architecture. // Linux uses a 80bit wide floating point stack on x86. This induces double @@ -62,7 +54,7 @@ // disabled.) // On Linux,x86 89255e-22 != Div_double(89255.0/1e22) #if defined(_M_X64) || defined(__x86_64__) || \ - defined(__ARMEL__) || defined(__avr32__) || \ + defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || defined(_M_ARM64) || \ defined(__hppa__) || defined(__ia64__) || \ defined(__mips__) || \ defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \ @@ -71,32 +63,32 @@ defined(__SH4__) || defined(__alpha__) || \ defined(_MIPS_ARCH_MIPS32R2) || \ defined(__AARCH64EL__) || defined(__aarch64__) -#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 +#define TAO_JSON_DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 #elif defined(__mc68000__) -#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS +#undef TAO_JSON_DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS #elif defined(_M_IX86) || defined(__i386__) || defined(__i386) #if defined(_WIN32) // Windows uses a 64bit wide floating point stack. -#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 +#define TAO_JSON_DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 #else -#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS +#undef TAO_JSON_DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS #endif // _WIN32 #else #error Target architecture was not detected as supported by Double-Conversion. #endif #if defined(__GNUC__) -#define DOUBLE_CONVERSION_UNUSED __attribute__((unused)) +#define TAO_JSON_DOUBLE_CONVERSION_UNUSED __attribute__((unused)) #else -#define DOUBLE_CONVERSION_UNUSED +#define TAO_JSON_DOUBLE_CONVERSION_UNUSED #endif #if defined(_WIN32) && !defined(__MINGW32__) typedef signed char int8_t; typedef unsigned char uint8_t; -typedef short int16_t; // NOLINT -typedef unsigned short uint16_t; // NOLINT +typedef short int16_t; +typedef unsigned short uint16_t; typedef int int32_t; typedef unsigned int uint32_t; typedef __int64 int64_t; @@ -112,76 +104,33 @@ typedef unsigned __int64 uint64_t; typedef uint16_t uc16; -#define UINT64_2PART_C(a, b) (((static_cast(a) << 32) + 0x##b##u)) +#define TAO_JSON_UINT64_2PART_C(a, b) (((static_cast(a) << 32) + 0x##b##u)) -#ifndef GDCV8_ARRAY_SIZE -#define GDCV8_ARRAY_SIZE(a) \ +#ifndef TAO_JSON_GDCV8_ARRAY_SIZE +#define TAO_JSON_GDCV8_ARRAY_SIZE(a) \ ((sizeof(a) / sizeof(*(a))) / \ static_cast(!(sizeof(a) % sizeof(*(a))))) #endif -#ifndef DISALLOW_COPY_AND_ASSIGN -#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName&) = delete; \ - void operator=(const TypeName&) = delete -#endif - -#ifndef DISALLOW_IMPLICIT_CONSTRUCTORS -#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ - TypeName() = delete; \ - DISALLOW_COPY_AND_ASSIGN(TypeName) -#endif - -namespace json_double_conversion +namespace tao::json::double_conversion { static const int kCharSize = sizeof( char ); - template - static T Max(T a, T b) { - return a < b ? b : a; - } - - template - static T Min(T a, T b) { - return a < b ? a : b; - } - - inline int StrLength(const char* string) { - size_t length = strlen(string); - ASSERT(length == static_cast(static_cast(length))); - return static_cast(length); - } - template class Vector { public: - Vector() : start_(NULL), length_(0) {} + Vector() : start_(nullptr), length_(0) {} Vector(T* data, int len) : start_(data), length_(len) { - ASSERT(len == 0 || (len > 0 && data != NULL)); - } - - Vector SubVector(int from, int to) { - ASSERT(to <= length_); - ASSERT(from < to); - ASSERT(0 <= from); - return Vector(start() + from, to - from); + assert(len == 0 || (len > 0 && data != nullptr)); } int length() const { return length_; } - bool is_empty() const { return length_ == 0; } - - T* start() const { return start_; } - T& operator[](int index) const { - ASSERT(0 <= index && index < length_); + assert(0 <= index && index < length_); return start_[index]; } - T& first() { return start_[0]; } - - T& last() { return start_[length_ - 1]; } - private: T* start_; int length_; @@ -189,11 +138,11 @@ namespace json_double_conversion template inline Dest BitCast(const Source& source) { - DOUBLE_CONVERSION_UNUSED + TAO_JSON_DOUBLE_CONVERSION_UNUSED typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1]; Dest dest; - memmove(&dest, &source, sizeof(dest)); + std::memmove(&dest, &source, sizeof(dest)); return dest; } @@ -208,12 +157,11 @@ namespace json_double_conversion static const int kMaxSignificantBits = 3584; Bignum(); + void AssignUInt16(uint16_t value); void AssignUInt64(uint64_t value); - void AssignBignum(const Bignum& other); void AssignDecimalString(Vector value); - void AssignHexString(Vector value); void AssignPowerUInt16(uint16_t base, int exponent); @@ -226,31 +174,12 @@ namespace json_double_conversion void MultiplyByUInt32(uint32_t factor); void MultiplyByUInt64(uint64_t factor); void MultiplyByPowerOfTen(int exponent); - void Times10() { return MultiplyByUInt32(10); } - uint16_t DivideModuloIntBignum(const Bignum& other); - - bool ToHexString(char* buffer, int buffer_size) const; static int Compare(const Bignum& a, const Bignum& b); - static bool Equal(const Bignum& a, const Bignum& b) { - return Compare(a, b) == 0; - } static bool LessEqual(const Bignum& a, const Bignum& b) { return Compare(a, b) <= 0; } - static bool Less(const Bignum& a, const Bignum& b) { - return Compare(a, b) < 0; - } - static int PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c); - static bool PlusEqual(const Bignum& a, const Bignum& b, const Bignum& c) { - return PlusCompare(a, b, c) == 0; - } - static bool PlusLessEqual(const Bignum& a, const Bignum& b, const Bignum& c) { - return PlusCompare(a, b, c) <= 0; - } - static bool PlusLess(const Bignum& a, const Bignum& b, const Bignum& c) { - return PlusCompare(a, b, c) < 0; - } + private: typedef uint32_t Chunk; typedef uint64_t DoubleChunk; @@ -262,9 +191,8 @@ namespace json_double_conversion static const int kBigitCapacity = kMaxSignificantBits / kBigitSize; void EnsureCapacity(int size) { - if (size > kBigitCapacity) { - UNREACHABLE(); - } + assert(size <= kBigitCapacity); + (void)size; } void Align(const Bignum& other); void Clamp(); @@ -299,7 +227,7 @@ namespace json_double_conversion } inline void Bignum::AssignUInt16(uint16_t value) { - ASSERT(kBigitSize >= BitSize(value)); + assert(kBigitSize >= BitSize(value)); Zero(); if (value == 0) return; @@ -324,25 +252,13 @@ namespace json_double_conversion Clamp(); } - inline void Bignum::AssignBignum(const Bignum& other) { - exponent_ = other.exponent_; - for (int i = 0; i < other.used_digits_; ++i) { - bigits_[i] = other.bigits_[i]; - } - for (int i = other.used_digits_; i < used_digits_; ++i) { - bigits_[i] = 0; - } - used_digits_ = other.used_digits_; - } - - inline uint64_t ReadUInt64(Vector buffer, int from, int digits_to_read) { uint64_t result = 0; for (int i = from; i < from + digits_to_read; ++i) { int digit = buffer[i] - '0'; - ASSERT(0 <= digit && digit <= 9); + assert(0 <= digit && digit <= 9); result = result * 10 + digit; } return result; @@ -366,41 +282,6 @@ namespace json_double_conversion Clamp(); } - inline int HexCharValue(char c) { - if ('0' <= c && c <= '9') return c - '0'; - if ('a' <= c && c <= 'f') return 10 + c - 'a'; - ASSERT('A' <= c && c <= 'F'); - return 10 + c - 'A'; - } - - inline void Bignum::AssignHexString(Vector value) { - Zero(); - int length = value.length(); - - int needed_bigits = length * 4 / kBigitSize + 1; - EnsureCapacity(needed_bigits); - int string_index = length - 1; - for (int i = 0; i < needed_bigits - 1; ++i) { - Chunk current_bigit = 0; - for (int j = 0; j < kBigitSize / 4; j++) { - current_bigit += HexCharValue(value[string_index--]) << (j * 4); - } - bigits_[i] = current_bigit; - } - used_digits_ = needed_bigits - 1; - - Chunk most_significant_bigit = 0; - for (int j = 0; j <= string_index; ++j) { - most_significant_bigit <<= 4; - most_significant_bigit += HexCharValue(value[j]); - } - if (most_significant_bigit != 0) { - bigits_[used_digits_] = most_significant_bigit; - used_digits_++; - } - Clamp(); - } - inline void Bignum::AddUInt64(uint64_t operand) { if (operand == 0) return; Bignum other; @@ -409,13 +290,13 @@ namespace json_double_conversion } inline void Bignum::AddBignum(const Bignum& other) { - ASSERT(IsClamped()); - ASSERT(other.IsClamped()); + assert(IsClamped()); + assert(other.IsClamped()); Align(other); - EnsureCapacity(1 + Max(BigitLength(), other.BigitLength()) - exponent_); + EnsureCapacity(1 + (std::max)(BigitLength(), other.BigitLength()) - exponent_); Chunk carry = 0; int bigit_pos = other.exponent_ - exponent_; - ASSERT(bigit_pos >= 0); + assert(bigit_pos >= 0); for (int i = 0; i < other.used_digits_; ++i) { Chunk sum = bigits_[bigit_pos] + other.bigits_[i] + carry; bigits_[bigit_pos] = sum & kBigitMask; @@ -428,21 +309,21 @@ namespace json_double_conversion carry = sum >> kBigitSize; bigit_pos++; } - used_digits_ = Max(bigit_pos, used_digits_); - ASSERT(IsClamped()); + used_digits_ = (std::max)(bigit_pos, used_digits_); + assert(IsClamped()); } inline void Bignum::SubtractBignum(const Bignum& other) { - ASSERT(IsClamped()); - ASSERT(other.IsClamped()); - ASSERT(LessEqual(other, *this)); + assert(IsClamped()); + assert(other.IsClamped()); + assert(LessEqual(other, *this)); Align(other); int offset = other.exponent_ - exponent_; Chunk borrow = 0; int i; for (i = 0; i < other.used_digits_; ++i) { - ASSERT((borrow == 0) || (borrow == 1)); + assert((borrow == 0) || (borrow == 1)); Chunk difference = bigits_[i + offset] - other.bigits_[i] - borrow; bigits_[i + offset] = difference & kBigitMask; borrow = difference >> (kChunkSize - 1); @@ -471,7 +352,7 @@ namespace json_double_conversion return; } if (used_digits_ == 0) return; - ASSERT(kDoubleChunkSize >= kBigitSize + 32 + 1); + assert(kDoubleChunkSize >= kBigitSize + 32 + 1); DoubleChunk carry = 0; for (int i = 0; i < used_digits_; ++i) { DoubleChunk product = static_cast(factor) * bigits_[i] + carry; @@ -492,7 +373,7 @@ namespace json_double_conversion Zero(); return; } - ASSERT(kBigitSize < 32); + assert(kBigitSize < 32); uint64_t carry = 0; uint64_t low = factor & 0xFFFFFFFF; uint64_t high = factor >> 32; @@ -513,7 +394,7 @@ namespace json_double_conversion } inline void Bignum::MultiplyByPowerOfTen(int exponent) { - const uint64_t kFive27 = UINT64_2PART_C(0x6765c793, fa10079d); + const uint64_t kFive27 = TAO_JSON_UINT64_2PART_C(0x6765c793, fa10079d); const uint16_t kFive1 = 5; const uint16_t kFive2 = kFive1 * 5; const uint16_t kFive3 = kFive2 * 5; @@ -531,7 +412,7 @@ namespace json_double_conversion { kFive1, kFive2, kFive3, kFive4, kFive5, kFive6, kFive7, kFive8, kFive9, kFive10, kFive11, kFive12 }; - ASSERT(exponent >= 0); + assert(exponent >= 0); if (exponent == 0) return; if (used_digits_ == 0) return; int remaining_exponent = exponent; @@ -550,12 +431,12 @@ namespace json_double_conversion } inline void Bignum::Square() { - ASSERT(IsClamped()); + assert(IsClamped()); int product_length = 2 * used_digits_; EnsureCapacity(product_length); if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_digits_) { - UNIMPLEMENTED(); + std::abort(); // Unimplemented. } DoubleChunk accumulator = 0; int copy_offset = used_digits_; @@ -588,15 +469,15 @@ namespace json_double_conversion bigits_[i] = static_cast(accumulator) & kBigitMask; accumulator >>= kBigitSize; } - ASSERT(accumulator == 0); + assert(accumulator == 0); used_digits_ = product_length; exponent_ *= 2; Clamp(); } inline void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) { - ASSERT(base != 0); - ASSERT(power_exponent >= 0); + assert(base != 0); + assert(power_exponent >= 0); if (power_exponent == 0) { AssignUInt16(1); return; @@ -649,105 +530,6 @@ namespace json_double_conversion ShiftLeft(shifts * power_exponent); } - inline uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) { - ASSERT(IsClamped()); - ASSERT(other.IsClamped()); - ASSERT(other.used_digits_ > 0); - - if (BigitLength() < other.BigitLength()) { - return 0; - } - Align(other); - - uint16_t result = 0; - - while (BigitLength() > other.BigitLength()) { - ASSERT(other.bigits_[other.used_digits_ - 1] >= ((1 << kBigitSize) / 16)); - ASSERT(bigits_[used_digits_ - 1] < 0x10000); - result += static_cast(bigits_[used_digits_ - 1]); - SubtractTimes(other, bigits_[used_digits_ - 1]); - } - ASSERT(BigitLength() == other.BigitLength()); - - Chunk this_bigit = bigits_[used_digits_ - 1]; - Chunk other_bigit = other.bigits_[other.used_digits_ - 1]; - - if (other.used_digits_ == 1) { - int quotient = this_bigit / other_bigit; - bigits_[used_digits_ - 1] = this_bigit - other_bigit * quotient; - ASSERT(quotient < 0x10000); - result += static_cast(quotient); - Clamp(); - return result; - } - int division_estimate = this_bigit / (other_bigit + 1); - ASSERT(division_estimate < 0x10000); - result += static_cast(division_estimate); - SubtractTimes(other, division_estimate); - - if (other_bigit * (division_estimate + 1) > this_bigit) { - return result; - } - while (LessEqual(other, *this)) { - SubtractBignum(other); - result++; - } - return result; - } - - template - inline int SizeInHexChars(S number) { - ASSERT(number > 0); - int result = 0; - while (number != 0) { - number >>= 4; - result++; - } - return result; - } - - inline char HexCharOfValue(int value) { - ASSERT(0 <= value && value <= 16); - if (value < 10) return static_cast(value + '0'); - return static_cast(value - 10 + 'A'); - } - - inline bool Bignum::ToHexString(char* buffer, int buffer_size) const { - ASSERT(IsClamped()); - ASSERT(kBigitSize % 4 == 0); - const int kHexCharsPerBigit = kBigitSize / 4; - - if (used_digits_ == 0) { - if (buffer_size < 2) return false; - buffer[0] = '0'; - buffer[1] = '\0'; - return true; - } - int needed_chars = (BigitLength() - 1) * kHexCharsPerBigit + - SizeInHexChars(bigits_[used_digits_ - 1]) + 1; - if (needed_chars > buffer_size) return false; - int string_index = needed_chars - 1; - buffer[string_index--] = '\0'; - for (int i = 0; i < exponent_; ++i) { - for (int j = 0; j < kHexCharsPerBigit; ++j) { - buffer[string_index--] = '0'; - } - } - for (int i = 0; i < used_digits_ - 1; ++i) { - Chunk current_bigit = bigits_[i]; - for (int j = 0; j < kHexCharsPerBigit; ++j) { - buffer[string_index--] = HexCharOfValue(current_bigit & 0xF); - current_bigit >>= 4; - } - } - Chunk most_significant_bigit = bigits_[used_digits_ - 1]; - while (most_significant_bigit != 0) { - buffer[string_index--] = HexCharOfValue(most_significant_bigit & 0xF); - most_significant_bigit >>= 4; - } - return true; - } - inline Bignum::Chunk Bignum::BigitAt(int index) const { if (index >= BigitLength()) return 0; if (index < exponent_) return 0; @@ -755,52 +537,21 @@ namespace json_double_conversion } inline int Bignum::Compare(const Bignum& a, const Bignum& b) { - ASSERT(a.IsClamped()); - ASSERT(b.IsClamped()); + assert(a.IsClamped()); + assert(b.IsClamped()); int bigit_length_a = a.BigitLength(); int bigit_length_b = b.BigitLength(); if (bigit_length_a < bigit_length_b) return -1; if (bigit_length_a > bigit_length_b) return +1; - for (int i = bigit_length_a - 1; i >= Min(a.exponent_, b.exponent_); --i) { - Chunk bigit_a = a.BigitAt(i); - Chunk bigit_b = b.BigitAt(i); + for (int i = bigit_length_a - 1; i >= (std::min)(a.exponent_, b.exponent_); --i) { + const Chunk bigit_a = a.BigitAt(i); + const Chunk bigit_b = b.BigitAt(i); if (bigit_a < bigit_b) return -1; if (bigit_a > bigit_b) return +1; } return 0; } - inline int Bignum::PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c) { - ASSERT(a.IsClamped()); - ASSERT(b.IsClamped()); - ASSERT(c.IsClamped()); - if (a.BigitLength() < b.BigitLength()) { - return PlusCompare(b, a, c); - } - if (a.BigitLength() + 1 < c.BigitLength()) return -1; - if (a.BigitLength() > c.BigitLength()) return +1; - if (a.exponent_ >= b.BigitLength() && a.BigitLength() < c.BigitLength()) { - return -1; - } - Chunk borrow = 0; - int min_exponent = Min(Min(a.exponent_, b.exponent_), c.exponent_); - for (int i = c.BigitLength() - 1; i >= min_exponent; --i) { - Chunk chunk_a = a.BigitAt(i); - Chunk chunk_b = b.BigitAt(i); - Chunk chunk_c = c.BigitAt(i); - Chunk sum = chunk_a + chunk_b; - if (sum > chunk_c + borrow) { - return +1; - } else { - borrow = chunk_c + borrow - sum; - if (borrow > 1) return -1; - borrow <<= kBigitSize; - } - } - if (borrow == 0) return 0; - return -1; - } - inline void Bignum::Clamp() { while (used_digits_ > 0 && bigits_[used_digits_ - 1] == 0) { used_digits_--; @@ -834,14 +585,14 @@ namespace json_double_conversion } used_digits_ += zero_digits; exponent_ -= zero_digits; - ASSERT(used_digits_ >= 0); - ASSERT(exponent_ >= 0); + assert(used_digits_ >= 0); + assert(exponent_ >= 0); } } inline void Bignum::BigitsShiftLeft(int shift_amount) { - ASSERT(shift_amount < kBigitSize); - ASSERT(shift_amount >= 0); + assert(shift_amount < kBigitSize); + assert(shift_amount >= 0); Chunk carry = 0; for (int i = 0; i < used_digits_; ++i) { Chunk new_carry = bigits_[i] >> (kBigitSize - shift_amount); @@ -855,7 +606,7 @@ namespace json_double_conversion } inline void Bignum::SubtractTimes(const Bignum& other, int factor) { - ASSERT(exponent_ <= other.exponent_); + assert(exponent_ <= other.exponent_); if (factor < 3) { for (int i = 0; i < factor; ++i) { SubtractBignum(other); @@ -890,8 +641,8 @@ namespace json_double_conversion DiyFp(uint64_t significand, int exponent) : f_(significand), e_(exponent) {} void Subtract(const DiyFp& other) { - ASSERT(e_ == other.e_); - ASSERT(f_ >= other.f_); + assert(e_ == other.e_); + assert(f_ >= other.f_); f_ -= other.f_; } @@ -927,11 +678,11 @@ namespace json_double_conversion } void Normalize() { - ASSERT(f_ != 0); + assert(f_ != 0); uint64_t significand = f_; int exponent = e_; - const uint64_t k10MSBits = UINT64_2PART_C(0xFFC00000, 00000000); + const uint64_t k10MSBits = TAO_JSON_UINT64_2PART_C(0xFFC00000, 00000000); while ((significand & k10MSBits) == 0) { significand <<= 10; exponent -= 10; @@ -957,7 +708,7 @@ namespace json_double_conversion void set_e(int new_value) { e_ = new_value; } private: - static const uint64_t kUint64MSB = UINT64_2PART_C(0x80000000, 00000000); + static const uint64_t kUint64MSB = TAO_JSON_UINT64_2PART_C(0x80000000, 00000000); uint64_t f_; int e_; @@ -968,10 +719,10 @@ namespace json_double_conversion class Double { public: - static const uint64_t kSignMask = UINT64_2PART_C(0x80000000, 00000000); - static const uint64_t kExponentMask = UINT64_2PART_C(0x7FF00000, 00000000); - static const uint64_t kSignificandMask = UINT64_2PART_C(0x000FFFFF, FFFFFFFF); - static const uint64_t kHiddenBit = UINT64_2PART_C(0x00100000, 00000000); + static const uint64_t kSignMask = TAO_JSON_UINT64_2PART_C(0x80000000, 00000000); + static const uint64_t kExponentMask = TAO_JSON_UINT64_2PART_C(0x7FF00000, 00000000); + static const uint64_t kSignificandMask = TAO_JSON_UINT64_2PART_C(0x000FFFFF, FFFFFFFF); + static const uint64_t kHiddenBit = TAO_JSON_UINT64_2PART_C(0x00100000, 00000000); static const int kPhysicalSignificandSize = 52; static const int kSignificandSize = 53; @@ -982,13 +733,13 @@ namespace json_double_conversion : d64_(DiyFpToUint64(diy_fp)) {} DiyFp AsDiyFp() const { - ASSERT(Sign() > 0); - ASSERT(!IsSpecial()); + assert(Sign() > 0); + assert(!IsSpecial()); return DiyFp(Significand(), Exponent()); } DiyFp AsNormalizedDiyFp() const { - ASSERT(value() > 0.0); + assert(value() > 0.0); uint64_t f = Significand(); int e = Exponent(); @@ -1074,12 +825,12 @@ namespace json_double_conversion } DiyFp UpperBoundary() const { - ASSERT(Sign() > 0); + assert(Sign() > 0); return DiyFp(Significand() * 2 + 1, Exponent() - 1); } void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const { - ASSERT(value() > 0.0); + assert(value() > 0.0); DiyFp v = this->AsDiyFp(); DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1)); DiyFp m_minus; @@ -1121,8 +872,8 @@ namespace json_double_conversion static const int kExponentBias = 0x3FF + kPhysicalSignificandSize; static const int kDenormalExponent = -kExponentBias + 1; static const int kMaxExponent = 0x7FF - kExponentBias; - static const uint64_t kInfinity = UINT64_2PART_C(0x7FF00000, 00000000); - static const uint64_t kNaN = UINT64_2PART_C(0x7FF80000, 00000000); + static const uint64_t kInfinity = TAO_JSON_UINT64_2PART_C(0x7FF00000, 00000000); + static const uint64_t kNaN = TAO_JSON_UINT64_2PART_C(0x7FF80000, 00000000); const uint64_t d64_; @@ -1153,7 +904,8 @@ namespace json_double_conversion (biased_exponent << kPhysicalSignificandSize); } - DISALLOW_COPY_AND_ASSIGN(Double); + Double( const Double& ) = delete; + void operator=( const Double& ) = delete; }; struct PowersOfTenCache @@ -1163,11 +915,6 @@ namespace json_double_conversion static const int kMinDecimalExponent = -348; static const int kMaxDecimalExponent = 340; - static void GetCachedPowerForBinaryExponentRange(int min_exponent, - int max_exponent, - DiyFp* power, - int* decimal_exponent); - static void GetCachedPowerForDecimalExponent(int requested_exponent, DiyFp* power, int* found_exponent); @@ -1180,130 +927,111 @@ namespace json_double_conversion }; static const CachedPower kCachedPowers[] = { - {UINT64_2PART_C(0xfa8fd5a0, 081c0288), -1220, -348}, - {UINT64_2PART_C(0xbaaee17f, a23ebf76), -1193, -340}, - {UINT64_2PART_C(0x8b16fb20, 3055ac76), -1166, -332}, - {UINT64_2PART_C(0xcf42894a, 5dce35ea), -1140, -324}, - {UINT64_2PART_C(0x9a6bb0aa, 55653b2d), -1113, -316}, - {UINT64_2PART_C(0xe61acf03, 3d1a45df), -1087, -308}, - {UINT64_2PART_C(0xab70fe17, c79ac6ca), -1060, -300}, - {UINT64_2PART_C(0xff77b1fc, bebcdc4f), -1034, -292}, - {UINT64_2PART_C(0xbe5691ef, 416bd60c), -1007, -284}, - {UINT64_2PART_C(0x8dd01fad, 907ffc3c), -980, -276}, - {UINT64_2PART_C(0xd3515c28, 31559a83), -954, -268}, - {UINT64_2PART_C(0x9d71ac8f, ada6c9b5), -927, -260}, - {UINT64_2PART_C(0xea9c2277, 23ee8bcb), -901, -252}, - {UINT64_2PART_C(0xaecc4991, 4078536d), -874, -244}, - {UINT64_2PART_C(0x823c1279, 5db6ce57), -847, -236}, - {UINT64_2PART_C(0xc2109436, 4dfb5637), -821, -228}, - {UINT64_2PART_C(0x9096ea6f, 3848984f), -794, -220}, - {UINT64_2PART_C(0xd77485cb, 25823ac7), -768, -212}, - {UINT64_2PART_C(0xa086cfcd, 97bf97f4), -741, -204}, - {UINT64_2PART_C(0xef340a98, 172aace5), -715, -196}, - {UINT64_2PART_C(0xb23867fb, 2a35b28e), -688, -188}, - {UINT64_2PART_C(0x84c8d4df, d2c63f3b), -661, -180}, - {UINT64_2PART_C(0xc5dd4427, 1ad3cdba), -635, -172}, - {UINT64_2PART_C(0x936b9fce, bb25c996), -608, -164}, - {UINT64_2PART_C(0xdbac6c24, 7d62a584), -582, -156}, - {UINT64_2PART_C(0xa3ab6658, 0d5fdaf6), -555, -148}, - {UINT64_2PART_C(0xf3e2f893, dec3f126), -529, -140}, - {UINT64_2PART_C(0xb5b5ada8, aaff80b8), -502, -132}, - {UINT64_2PART_C(0x87625f05, 6c7c4a8b), -475, -124}, - {UINT64_2PART_C(0xc9bcff60, 34c13053), -449, -116}, - {UINT64_2PART_C(0x964e858c, 91ba2655), -422, -108}, - {UINT64_2PART_C(0xdff97724, 70297ebd), -396, -100}, - {UINT64_2PART_C(0xa6dfbd9f, b8e5b88f), -369, -92}, - {UINT64_2PART_C(0xf8a95fcf, 88747d94), -343, -84}, - {UINT64_2PART_C(0xb9447093, 8fa89bcf), -316, -76}, - {UINT64_2PART_C(0x8a08f0f8, bf0f156b), -289, -68}, - {UINT64_2PART_C(0xcdb02555, 653131b6), -263, -60}, - {UINT64_2PART_C(0x993fe2c6, d07b7fac), -236, -52}, - {UINT64_2PART_C(0xe45c10c4, 2a2b3b06), -210, -44}, - {UINT64_2PART_C(0xaa242499, 697392d3), -183, -36}, - {UINT64_2PART_C(0xfd87b5f2, 8300ca0e), -157, -28}, - {UINT64_2PART_C(0xbce50864, 92111aeb), -130, -20}, - {UINT64_2PART_C(0x8cbccc09, 6f5088cc), -103, -12}, - {UINT64_2PART_C(0xd1b71758, e219652c), -77, -4}, - {UINT64_2PART_C(0x9c400000, 00000000), -50, 4}, - {UINT64_2PART_C(0xe8d4a510, 00000000), -24, 12}, - {UINT64_2PART_C(0xad78ebc5, ac620000), 3, 20}, - {UINT64_2PART_C(0x813f3978, f8940984), 30, 28}, - {UINT64_2PART_C(0xc097ce7b, c90715b3), 56, 36}, - {UINT64_2PART_C(0x8f7e32ce, 7bea5c70), 83, 44}, - {UINT64_2PART_C(0xd5d238a4, abe98068), 109, 52}, - {UINT64_2PART_C(0x9f4f2726, 179a2245), 136, 60}, - {UINT64_2PART_C(0xed63a231, d4c4fb27), 162, 68}, - {UINT64_2PART_C(0xb0de6538, 8cc8ada8), 189, 76}, - {UINT64_2PART_C(0x83c7088e, 1aab65db), 216, 84}, - {UINT64_2PART_C(0xc45d1df9, 42711d9a), 242, 92}, - {UINT64_2PART_C(0x924d692c, a61be758), 269, 100}, - {UINT64_2PART_C(0xda01ee64, 1a708dea), 295, 108}, - {UINT64_2PART_C(0xa26da399, 9aef774a), 322, 116}, - {UINT64_2PART_C(0xf209787b, b47d6b85), 348, 124}, - {UINT64_2PART_C(0xb454e4a1, 79dd1877), 375, 132}, - {UINT64_2PART_C(0x865b8692, 5b9bc5c2), 402, 140}, - {UINT64_2PART_C(0xc83553c5, c8965d3d), 428, 148}, - {UINT64_2PART_C(0x952ab45c, fa97a0b3), 455, 156}, - {UINT64_2PART_C(0xde469fbd, 99a05fe3), 481, 164}, - {UINT64_2PART_C(0xa59bc234, db398c25), 508, 172}, - {UINT64_2PART_C(0xf6c69a72, a3989f5c), 534, 180}, - {UINT64_2PART_C(0xb7dcbf53, 54e9bece), 561, 188}, - {UINT64_2PART_C(0x88fcf317, f22241e2), 588, 196}, - {UINT64_2PART_C(0xcc20ce9b, d35c78a5), 614, 204}, - {UINT64_2PART_C(0x98165af3, 7b2153df), 641, 212}, - {UINT64_2PART_C(0xe2a0b5dc, 971f303a), 667, 220}, - {UINT64_2PART_C(0xa8d9d153, 5ce3b396), 694, 228}, - {UINT64_2PART_C(0xfb9b7cd9, a4a7443c), 720, 236}, - {UINT64_2PART_C(0xbb764c4c, a7a44410), 747, 244}, - {UINT64_2PART_C(0x8bab8eef, b6409c1a), 774, 252}, - {UINT64_2PART_C(0xd01fef10, a657842c), 800, 260}, - {UINT64_2PART_C(0x9b10a4e5, e9913129), 827, 268}, - {UINT64_2PART_C(0xe7109bfb, a19c0c9d), 853, 276}, - {UINT64_2PART_C(0xac2820d9, 623bf429), 880, 284}, - {UINT64_2PART_C(0x80444b5e, 7aa7cf85), 907, 292}, - {UINT64_2PART_C(0xbf21e440, 03acdd2d), 933, 300}, - {UINT64_2PART_C(0x8e679c2f, 5e44ff8f), 960, 308}, - {UINT64_2PART_C(0xd433179d, 9c8cb841), 986, 316}, - {UINT64_2PART_C(0x9e19db92, b4e31ba9), 1013, 324}, - {UINT64_2PART_C(0xeb96bf6e, badf77d9), 1039, 332}, - {UINT64_2PART_C(0xaf87023b, 9bf0ee6b), 1066, 340}, + {TAO_JSON_UINT64_2PART_C(0xfa8fd5a0, 081c0288), -1220, -348}, + {TAO_JSON_UINT64_2PART_C(0xbaaee17f, a23ebf76), -1193, -340}, + {TAO_JSON_UINT64_2PART_C(0x8b16fb20, 3055ac76), -1166, -332}, + {TAO_JSON_UINT64_2PART_C(0xcf42894a, 5dce35ea), -1140, -324}, + {TAO_JSON_UINT64_2PART_C(0x9a6bb0aa, 55653b2d), -1113, -316}, + {TAO_JSON_UINT64_2PART_C(0xe61acf03, 3d1a45df), -1087, -308}, + {TAO_JSON_UINT64_2PART_C(0xab70fe17, c79ac6ca), -1060, -300}, + {TAO_JSON_UINT64_2PART_C(0xff77b1fc, bebcdc4f), -1034, -292}, + {TAO_JSON_UINT64_2PART_C(0xbe5691ef, 416bd60c), -1007, -284}, + {TAO_JSON_UINT64_2PART_C(0x8dd01fad, 907ffc3c), -980, -276}, + {TAO_JSON_UINT64_2PART_C(0xd3515c28, 31559a83), -954, -268}, + {TAO_JSON_UINT64_2PART_C(0x9d71ac8f, ada6c9b5), -927, -260}, + {TAO_JSON_UINT64_2PART_C(0xea9c2277, 23ee8bcb), -901, -252}, + {TAO_JSON_UINT64_2PART_C(0xaecc4991, 4078536d), -874, -244}, + {TAO_JSON_UINT64_2PART_C(0x823c1279, 5db6ce57), -847, -236}, + {TAO_JSON_UINT64_2PART_C(0xc2109436, 4dfb5637), -821, -228}, + {TAO_JSON_UINT64_2PART_C(0x9096ea6f, 3848984f), -794, -220}, + {TAO_JSON_UINT64_2PART_C(0xd77485cb, 25823ac7), -768, -212}, + {TAO_JSON_UINT64_2PART_C(0xa086cfcd, 97bf97f4), -741, -204}, + {TAO_JSON_UINT64_2PART_C(0xef340a98, 172aace5), -715, -196}, + {TAO_JSON_UINT64_2PART_C(0xb23867fb, 2a35b28e), -688, -188}, + {TAO_JSON_UINT64_2PART_C(0x84c8d4df, d2c63f3b), -661, -180}, + {TAO_JSON_UINT64_2PART_C(0xc5dd4427, 1ad3cdba), -635, -172}, + {TAO_JSON_UINT64_2PART_C(0x936b9fce, bb25c996), -608, -164}, + {TAO_JSON_UINT64_2PART_C(0xdbac6c24, 7d62a584), -582, -156}, + {TAO_JSON_UINT64_2PART_C(0xa3ab6658, 0d5fdaf6), -555, -148}, + {TAO_JSON_UINT64_2PART_C(0xf3e2f893, dec3f126), -529, -140}, + {TAO_JSON_UINT64_2PART_C(0xb5b5ada8, aaff80b8), -502, -132}, + {TAO_JSON_UINT64_2PART_C(0x87625f05, 6c7c4a8b), -475, -124}, + {TAO_JSON_UINT64_2PART_C(0xc9bcff60, 34c13053), -449, -116}, + {TAO_JSON_UINT64_2PART_C(0x964e858c, 91ba2655), -422, -108}, + {TAO_JSON_UINT64_2PART_C(0xdff97724, 70297ebd), -396, -100}, + {TAO_JSON_UINT64_2PART_C(0xa6dfbd9f, b8e5b88f), -369, -92}, + {TAO_JSON_UINT64_2PART_C(0xf8a95fcf, 88747d94), -343, -84}, + {TAO_JSON_UINT64_2PART_C(0xb9447093, 8fa89bcf), -316, -76}, + {TAO_JSON_UINT64_2PART_C(0x8a08f0f8, bf0f156b), -289, -68}, + {TAO_JSON_UINT64_2PART_C(0xcdb02555, 653131b6), -263, -60}, + {TAO_JSON_UINT64_2PART_C(0x993fe2c6, d07b7fac), -236, -52}, + {TAO_JSON_UINT64_2PART_C(0xe45c10c4, 2a2b3b06), -210, -44}, + {TAO_JSON_UINT64_2PART_C(0xaa242499, 697392d3), -183, -36}, + {TAO_JSON_UINT64_2PART_C(0xfd87b5f2, 8300ca0e), -157, -28}, + {TAO_JSON_UINT64_2PART_C(0xbce50864, 92111aeb), -130, -20}, + {TAO_JSON_UINT64_2PART_C(0x8cbccc09, 6f5088cc), -103, -12}, + {TAO_JSON_UINT64_2PART_C(0xd1b71758, e219652c), -77, -4}, + {TAO_JSON_UINT64_2PART_C(0x9c400000, 00000000), -50, 4}, + {TAO_JSON_UINT64_2PART_C(0xe8d4a510, 00000000), -24, 12}, + {TAO_JSON_UINT64_2PART_C(0xad78ebc5, ac620000), 3, 20}, + {TAO_JSON_UINT64_2PART_C(0x813f3978, f8940984), 30, 28}, + {TAO_JSON_UINT64_2PART_C(0xc097ce7b, c90715b3), 56, 36}, + {TAO_JSON_UINT64_2PART_C(0x8f7e32ce, 7bea5c70), 83, 44}, + {TAO_JSON_UINT64_2PART_C(0xd5d238a4, abe98068), 109, 52}, + {TAO_JSON_UINT64_2PART_C(0x9f4f2726, 179a2245), 136, 60}, + {TAO_JSON_UINT64_2PART_C(0xed63a231, d4c4fb27), 162, 68}, + {TAO_JSON_UINT64_2PART_C(0xb0de6538, 8cc8ada8), 189, 76}, + {TAO_JSON_UINT64_2PART_C(0x83c7088e, 1aab65db), 216, 84}, + {TAO_JSON_UINT64_2PART_C(0xc45d1df9, 42711d9a), 242, 92}, + {TAO_JSON_UINT64_2PART_C(0x924d692c, a61be758), 269, 100}, + {TAO_JSON_UINT64_2PART_C(0xda01ee64, 1a708dea), 295, 108}, + {TAO_JSON_UINT64_2PART_C(0xa26da399, 9aef774a), 322, 116}, + {TAO_JSON_UINT64_2PART_C(0xf209787b, b47d6b85), 348, 124}, + {TAO_JSON_UINT64_2PART_C(0xb454e4a1, 79dd1877), 375, 132}, + {TAO_JSON_UINT64_2PART_C(0x865b8692, 5b9bc5c2), 402, 140}, + {TAO_JSON_UINT64_2PART_C(0xc83553c5, c8965d3d), 428, 148}, + {TAO_JSON_UINT64_2PART_C(0x952ab45c, fa97a0b3), 455, 156}, + {TAO_JSON_UINT64_2PART_C(0xde469fbd, 99a05fe3), 481, 164}, + {TAO_JSON_UINT64_2PART_C(0xa59bc234, db398c25), 508, 172}, + {TAO_JSON_UINT64_2PART_C(0xf6c69a72, a3989f5c), 534, 180}, + {TAO_JSON_UINT64_2PART_C(0xb7dcbf53, 54e9bece), 561, 188}, + {TAO_JSON_UINT64_2PART_C(0x88fcf317, f22241e2), 588, 196}, + {TAO_JSON_UINT64_2PART_C(0xcc20ce9b, d35c78a5), 614, 204}, + {TAO_JSON_UINT64_2PART_C(0x98165af3, 7b2153df), 641, 212}, + {TAO_JSON_UINT64_2PART_C(0xe2a0b5dc, 971f303a), 667, 220}, + {TAO_JSON_UINT64_2PART_C(0xa8d9d153, 5ce3b396), 694, 228}, + {TAO_JSON_UINT64_2PART_C(0xfb9b7cd9, a4a7443c), 720, 236}, + {TAO_JSON_UINT64_2PART_C(0xbb764c4c, a7a44410), 747, 244}, + {TAO_JSON_UINT64_2PART_C(0x8bab8eef, b6409c1a), 774, 252}, + {TAO_JSON_UINT64_2PART_C(0xd01fef10, a657842c), 800, 260}, + {TAO_JSON_UINT64_2PART_C(0x9b10a4e5, e9913129), 827, 268}, + {TAO_JSON_UINT64_2PART_C(0xe7109bfb, a19c0c9d), 853, 276}, + {TAO_JSON_UINT64_2PART_C(0xac2820d9, 623bf429), 880, 284}, + {TAO_JSON_UINT64_2PART_C(0x80444b5e, 7aa7cf85), 907, 292}, + {TAO_JSON_UINT64_2PART_C(0xbf21e440, 03acdd2d), 933, 300}, + {TAO_JSON_UINT64_2PART_C(0x8e679c2f, 5e44ff8f), 960, 308}, + {TAO_JSON_UINT64_2PART_C(0xd433179d, 9c8cb841), 986, 316}, + {TAO_JSON_UINT64_2PART_C(0x9e19db92, b4e31ba9), 1013, 324}, + {TAO_JSON_UINT64_2PART_C(0xeb96bf6e, badf77d9), 1039, 332}, + {TAO_JSON_UINT64_2PART_C(0xaf87023b, 9bf0ee6b), 1066, 340}, }; - static const int kCachedPowersLength = GDCV8_ARRAY_SIZE(kCachedPowers); + static const int kCachedPowersLength = TAO_JSON_GDCV8_ARRAY_SIZE(kCachedPowers); static const int kCachedPowersOffset = 348; static const double kD_1_LOG2_10 = 0.30102999566398114; - inline void PowersOfTenCache::GetCachedPowerForBinaryExponentRange( - int min_exponent, - int max_exponent, - DiyFp* power, - int* decimal_exponent) { - int kQ = DiyFp::kSignificandSize; - double k = ceil((min_exponent + kQ - 1) * kD_1_LOG2_10); - int foo = kCachedPowersOffset; - int index = - (foo + static_cast(k) - 1) / kDecimalExponentDistance + 1; - ASSERT(0 <= index && index < kCachedPowersLength); - CachedPower cached_power = kCachedPowers[index]; - ASSERT(min_exponent <= cached_power.binary_exponent); - (void) max_exponent; - ASSERT(cached_power.binary_exponent <= max_exponent); - *decimal_exponent = cached_power.decimal_exponent; - *power = DiyFp(cached_power.significand, cached_power.binary_exponent); - } - inline void PowersOfTenCache::GetCachedPowerForDecimalExponent(int requested_exponent, DiyFp* power, int* found_exponent) { - ASSERT(kMinDecimalExponent <= requested_exponent); - ASSERT(requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance); + assert(kMinDecimalExponent <= requested_exponent); + assert(requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance); int index = (requested_exponent + kCachedPowersOffset) / kDecimalExponentDistance; CachedPower cached_power = kCachedPowers[index]; *power = DiyFp(cached_power.significand, cached_power.binary_exponent); *found_exponent = cached_power.decimal_exponent; - ASSERT(*found_exponent <= requested_exponent); - ASSERT(requested_exponent < *found_exponent + kDecimalExponentDistance); + assert(*found_exponent <= requested_exponent); + assert(requested_exponent < *found_exponent + kDecimalExponentDistance); } static const int kMaxExactDoubleIntegerDecimalDigits = 15; @@ -1312,7 +1040,7 @@ namespace json_double_conversion static const int kMaxDecimalPower = 309; static const int kMinDecimalPower = -324; - static const uint64_t kMaxUint64 = UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF); + static const uint64_t kMaxUint64 = TAO_JSON_UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF); static const double exact_powers_of_ten[] = { 1.0, // 10^0 @@ -1340,65 +1068,16 @@ namespace json_double_conversion 10000000000000000000000.0 }; - static const int kExactPowersOfTenSize = GDCV8_ARRAY_SIZE(exact_powers_of_ten); + static const int kExactPowersOfTenSize = TAO_JSON_GDCV8_ARRAY_SIZE(exact_powers_of_ten); static const int kMaxSignificantDecimalDigits = 780; - inline Vector TrimLeadingZeros(Vector buffer) { - for (int i = 0; i < buffer.length(); i++) { - if (buffer[i] != '0') { - return buffer.SubVector(i, buffer.length()); - } - } - return Vector(buffer.start(), 0); - } - - inline Vector TrimTrailingZeros(Vector buffer) { - for (int i = buffer.length() - 1; i >= 0; --i) { - if (buffer[i] != '0') { - return buffer.SubVector(0, i + 1); - } - } - return Vector(buffer.start(), 0); - } - - inline void CutToMaxSignificantDigits(Vector buffer, - int exponent, - char* significant_buffer, - int* significant_exponent) { - for (int i = 0; i < kMaxSignificantDecimalDigits - 1; ++i) { - significant_buffer[i] = buffer[i]; - } - ASSERT(buffer[buffer.length() - 1] != '0'); - significant_buffer[kMaxSignificantDecimalDigits - 1] = '1'; - *significant_exponent = - exponent + (buffer.length() - kMaxSignificantDecimalDigits); - } - - inline void TrimAndCut(Vector buffer, int exponent, - char* buffer_copy_space, int space_size, - Vector* trimmed, int* updated_exponent) { - Vector right_trimmed = TrimTrailingZeros(buffer); - exponent -= right_trimmed.length(); - if (right_trimmed.length() > kMaxSignificantDecimalDigits) { - (void) space_size; - ASSERT(space_size >= kMaxSignificantDecimalDigits); - CutToMaxSignificantDigits(right_trimmed, exponent, - buffer_copy_space, updated_exponent); - *trimmed = Vector(buffer_copy_space, - kMaxSignificantDecimalDigits); - } else { - *trimmed = right_trimmed; - *updated_exponent = exponent; - } - } - inline uint64_t ReadUint64(Vector buffer, int* number_of_read_digits) { uint64_t result = 0; int i = 0; while (i < buffer.length() && result <= (kMaxUint64 / 10 - 1)) { int digit = buffer[i++] - '0'; - ASSERT(0 <= digit && digit <= 9); + assert(0 <= digit && digit <= 9); result = 10 * result + digit; } *number_of_read_digits = i; @@ -1426,7 +1105,7 @@ namespace json_double_conversion inline bool DoubleStrtod(Vector trimmed, int exponent, double* result) { -#if !defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS) +#if !defined(TAO_JSON_DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS) // On x86 the floating-point stack can be 64 or 80 bits wide. If it is // 80 bits wide (as is the case on Linux) then double-rounding occurs and the // result is not accurate. @@ -1439,13 +1118,13 @@ namespace json_double_conversion int read_digits; if (exponent < 0 && -exponent < kExactPowersOfTenSize) { *result = static_cast(ReadUint64(trimmed, &read_digits)); - ASSERT(read_digits == trimmed.length()); + assert(read_digits == trimmed.length()); *result /= exact_powers_of_ten[-exponent]; return true; } if (0 <= exponent && exponent < kExactPowersOfTenSize) { *result = static_cast(ReadUint64(trimmed, &read_digits)); - ASSERT(read_digits == trimmed.length()); + assert(read_digits == trimmed.length()); *result *= exact_powers_of_ten[exponent]; return true; } @@ -1454,7 +1133,7 @@ namespace json_double_conversion if ((0 <= exponent) && (exponent - remaining_digits < kExactPowersOfTenSize)) { *result = static_cast(ReadUint64(trimmed, &read_digits)); - ASSERT(read_digits == trimmed.length()); + assert(read_digits == trimmed.length()); *result *= exact_powers_of_ten[remaining_digits]; *result *= exact_powers_of_ten[exponent - remaining_digits]; return true; @@ -1464,19 +1143,19 @@ namespace json_double_conversion } inline DiyFp AdjustmentPowerOfTen(int exponent) { - ASSERT(0 < exponent); - ASSERT(exponent < PowersOfTenCache::kDecimalExponentDistance); - ASSERT(PowersOfTenCache::kDecimalExponentDistance == 8); + assert(0 < exponent); + assert(exponent < PowersOfTenCache::kDecimalExponentDistance); + assert(PowersOfTenCache::kDecimalExponentDistance == 8); switch (exponent) { - case 1: return DiyFp(UINT64_2PART_C(0xa0000000, 00000000), -60); - case 2: return DiyFp(UINT64_2PART_C(0xc8000000, 00000000), -57); - case 3: return DiyFp(UINT64_2PART_C(0xfa000000, 00000000), -54); - case 4: return DiyFp(UINT64_2PART_C(0x9c400000, 00000000), -50); - case 5: return DiyFp(UINT64_2PART_C(0xc3500000, 00000000), -47); - case 6: return DiyFp(UINT64_2PART_C(0xf4240000, 00000000), -44); - case 7: return DiyFp(UINT64_2PART_C(0x98968000, 00000000), -40); + case 1: return DiyFp(TAO_JSON_UINT64_2PART_C(0xa0000000, 00000000), -60); + case 2: return DiyFp(TAO_JSON_UINT64_2PART_C(0xc8000000, 00000000), -57); + case 3: return DiyFp(TAO_JSON_UINT64_2PART_C(0xfa000000, 00000000), -54); + case 4: return DiyFp(TAO_JSON_UINT64_2PART_C(0x9c400000, 00000000), -50); + case 5: return DiyFp(TAO_JSON_UINT64_2PART_C(0xc3500000, 00000000), -47); + case 6: return DiyFp(TAO_JSON_UINT64_2PART_C(0xf4240000, 00000000), -44); + case 7: return DiyFp(TAO_JSON_UINT64_2PART_C(0x98968000, 00000000), -40); default: - UNREACHABLE(); + std::abort(); } } @@ -1495,7 +1174,7 @@ namespace json_double_conversion input.Normalize(); error <<= old_e - input.e(); - ASSERT(exponent <= PowersOfTenCache::kMaxDecimalExponent); + assert(exponent <= PowersOfTenCache::kMaxDecimalExponent); if (exponent < PowersOfTenCache::kMinDecimalExponent) { *result = 0.0; return true; @@ -1511,7 +1190,7 @@ namespace json_double_conversion DiyFp adjustment_power = AdjustmentPowerOfTen(adjustment_exponent); input.Multiply(adjustment_power); if (kMaxUint64DecimalDigits - buffer.length() >= adjustment_exponent) { - ASSERT(DiyFp::kSignificandSize == 64); + assert(DiyFp::kSignificandSize == 64); } else { error += kDenominator / 2; } @@ -1540,8 +1219,8 @@ namespace json_double_conversion error = (error >> shift_amount) + 1 + kDenominator; precision_digits_count -= shift_amount; } - ASSERT(DiyFp::kSignificandSize == 64); - ASSERT(precision_digits_count < 64); + assert(DiyFp::kSignificandSize == 64); + assert(precision_digits_count < 64); uint64_t one64 = 1; uint64_t precision_bits_mask = (one64 << precision_digits_count) - 1; uint64_t precision_bits = input.f() & precision_bits_mask; @@ -1564,10 +1243,10 @@ namespace json_double_conversion inline int CompareBufferWithDiyFp(Vector buffer, int exponent, DiyFp diy_fp) { - ASSERT(buffer.length() + exponent <= kMaxDecimalPower + 1); - ASSERT(buffer.length() + exponent > kMinDecimalPower); - ASSERT(buffer.length() <= kMaxSignificantDecimalDigits); - ASSERT(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits); + assert(buffer.length() + exponent <= kMaxDecimalPower + 1); + assert(buffer.length() + exponent > kMinDecimalPower); + assert(buffer.length() <= kMaxSignificantDecimalDigits); + assert(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits); Bignum buffer_bignum; Bignum diy_fp_bignum; buffer_bignum.AssignDecimalString(buffer); @@ -1629,508 +1308,6 @@ namespace json_double_conversion } } - namespace - { - const int kBase10MaximalLength = 17; - const int kMaxExponentialDigits = 120; - const int kFastDtoaMaximalLength = 17; - const int kMinimalTargetExponent = -60; - const int kMaximalTargetExponent = -32; - - const unsigned int kSmallPowersOfTen[] = {0, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; - - } // - - inline void BiggestPowerTen(uint32_t number, - int number_bits, - uint32_t* power, - int* exponent_plus_one) { - ASSERT(number < (1u << (number_bits + 1))); - int exponent_plus_one_guess = ((number_bits + 1) * 1233 >> 12); - exponent_plus_one_guess++; - if (number < kSmallPowersOfTen[exponent_plus_one_guess]) { - exponent_plus_one_guess--; - } - *power = kSmallPowersOfTen[exponent_plus_one_guess]; - *exponent_plus_one = exponent_plus_one_guess; - } - - inline bool RoundWeed(Vector buffer, - int length, - uint64_t distance_too_high_w, - uint64_t unsafe_interval, - uint64_t rest, - uint64_t ten_kappa, - uint64_t unit) { - uint64_t small_distance = distance_too_high_w - unit; - uint64_t big_distance = distance_too_high_w + unit; - ASSERT(rest <= unsafe_interval); - while (rest < small_distance && - unsafe_interval - rest >= ten_kappa && - (rest + ten_kappa < small_distance || - small_distance - rest >= rest + ten_kappa - small_distance)) { - buffer[length - 1]--; - rest += ten_kappa; - } - if (rest < big_distance && - unsafe_interval - rest >= ten_kappa && - (rest + ten_kappa < big_distance || - big_distance - rest > rest + ten_kappa - big_distance)) { - return false; - } - return (2 * unit <= rest) && (rest <= unsafe_interval - 4 * unit); - } - - inline bool DigitGen(DiyFp low, - DiyFp w, - DiyFp high, - Vector buffer, - int* length, - int* kappa) { - ASSERT(low.e() == w.e() && w.e() == high.e()); - ASSERT(low.f() + 1 <= high.f() - 1); - ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent); - uint64_t unit = 1; - DiyFp too_low = DiyFp(low.f() - unit, low.e()); - DiyFp too_high = DiyFp(high.f() + unit, high.e()); - DiyFp unsafe_interval = DiyFp::Minus(too_high, too_low); - DiyFp one = DiyFp(static_cast(1) << -w.e(), w.e()); - uint32_t integrals = static_cast(too_high.f() >> -one.e()); - uint64_t fractionals = too_high.f() & (one.f() - 1); - uint32_t divisor; - int divisor_exponent_plus_one; - BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.e()), - &divisor, &divisor_exponent_plus_one); - *kappa = divisor_exponent_plus_one; - *length = 0; - while (*kappa > 0) { - int digit = integrals / divisor; - ASSERT(digit <= 9); - buffer[*length] = static_cast('0' + digit); - (*length)++; - integrals %= divisor; - (*kappa)--; - uint64_t rest = - (static_cast(integrals) << -one.e()) + fractionals; - if (rest < unsafe_interval.f()) { - return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).f(), - unsafe_interval.f(), rest, - static_cast(divisor) << -one.e(), unit); - } - divisor /= 10; - } - ASSERT(one.e() >= -60); - ASSERT(fractionals < one.f()); - ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f()); - for (;;) { - fractionals *= 10; - unit *= 10; - unsafe_interval.set_f(unsafe_interval.f() * 10); - int digit = static_cast(fractionals >> -one.e()); - ASSERT(digit <= 9); - buffer[*length] = static_cast('0' + digit); - (*length)++; - fractionals &= one.f() - 1; - (*kappa)--; - if (fractionals < unsafe_interval.f()) { - return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).f() * unit, - unsafe_interval.f(), fractionals, one.f(), unit); - } - } - } - - inline bool Grisu3( const double v, - Vector buffer, - int * length, - int * decimal_exponent ) - { - DiyFp w = Double(v).AsNormalizedDiyFp(); - DiyFp boundary_minus, boundary_plus; - Double(v).NormalizedBoundaries(&boundary_minus, &boundary_plus); - ASSERT(boundary_plus.e() == w.e()); - DiyFp ten_mk; - int mk; - int ten_mk_minimal_binary_exponent = - kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize); - int ten_mk_maximal_binary_exponent = - kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize); - PowersOfTenCache::GetCachedPowerForBinaryExponentRange(ten_mk_minimal_binary_exponent, - ten_mk_maximal_binary_exponent, - &ten_mk, &mk); - ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() + - DiyFp::kSignificandSize) && - (kMaximalTargetExponent >= w.e() + ten_mk.e() + - DiyFp::kSignificandSize)); - DiyFp scaled_w = DiyFp::Times(w, ten_mk); - ASSERT(scaled_w.e() == - boundary_plus.e() + ten_mk.e() + DiyFp::kSignificandSize); - DiyFp scaled_boundary_minus = DiyFp::Times(boundary_minus, ten_mk); - DiyFp scaled_boundary_plus = DiyFp::Times(boundary_plus, ten_mk); - int kappa; - bool result = DigitGen(scaled_boundary_minus, scaled_w, scaled_boundary_plus, - buffer, length, &kappa); - *decimal_exponent = -mk + kappa; - return result; - } - - inline bool FastDtoa( const double v, - Vector< char > buffer, - int * length, - int * decimal_point ) - { - int decimal_exponent = 0; - if ( Grisu3(v, buffer, length, &decimal_exponent) ) { - *decimal_point = *length + decimal_exponent; - buffer[*length] = '\0'; - return true; - } - return false; - } - - static int NormalizedExponent(uint64_t significand, int exponent) { - ASSERT(significand != 0); - while ((significand & Double::kHiddenBit) == 0) { - significand = significand << 1; - exponent = exponent - 1; - } - return exponent; - } - - inline int EstimatePower(int exponent) { - const double k1Log10 = 0.30102999566398114; - const int kSignificandSize = Double::kSignificandSize; - double estimate = ceil((exponent + kSignificandSize - 1) * k1Log10 - 1e-10); - return static_cast(estimate); - } - - inline void InitialScaledStartValuesPositiveExponent(uint64_t significand, int exponent, - int estimated_power, bool need_boundary_deltas, - Bignum* numerator, Bignum* denominator, - Bignum* delta_minus, Bignum* delta_plus) { - ASSERT(estimated_power >= 0); - numerator->AssignUInt64(significand); - numerator->ShiftLeft(exponent); - denominator->AssignPowerUInt16(10, estimated_power); - - if (need_boundary_deltas) { - denominator->ShiftLeft(1); - numerator->ShiftLeft(1); - delta_plus->AssignUInt16(1); - delta_plus->ShiftLeft(exponent); - delta_minus->AssignUInt16(1); - delta_minus->ShiftLeft(exponent); - } - } - - inline void InitialScaledStartValuesNegativeExponentPositivePower( - uint64_t significand, int exponent, - int estimated_power, bool need_boundary_deltas, - Bignum* numerator, Bignum* denominator, - Bignum* delta_minus, Bignum* delta_plus) { - numerator->AssignUInt64(significand); - denominator->AssignPowerUInt16(10, estimated_power); - denominator->ShiftLeft(-exponent); - - if (need_boundary_deltas) { - denominator->ShiftLeft(1); - numerator->ShiftLeft(1); - delta_plus->AssignUInt16(1); - delta_minus->AssignUInt16(1); - } - } - - inline void InitialScaledStartValuesNegativeExponentNegativePower( - uint64_t significand, int exponent, - int estimated_power, bool need_boundary_deltas, - Bignum* numerator, Bignum* denominator, - Bignum* delta_minus, Bignum* delta_plus) { - Bignum* power_ten = numerator; - power_ten->AssignPowerUInt16(10, -estimated_power); - - if (need_boundary_deltas) { - delta_plus->AssignBignum(*power_ten); - delta_minus->AssignBignum(*power_ten); - } - ASSERT(numerator == power_ten); - numerator->MultiplyByUInt64(significand); - denominator->AssignUInt16(1); - denominator->ShiftLeft(-exponent); - - if (need_boundary_deltas) { - numerator->ShiftLeft(1); - denominator->ShiftLeft(1); - } - } - - inline void InitialScaledStartValues(uint64_t significand, - int exponent, - bool lower_boundary_is_closer, - int estimated_power, - bool need_boundary_deltas, - Bignum* numerator, - Bignum* denominator, - Bignum* delta_minus, - Bignum* delta_plus) { - if (exponent >= 0) { - InitialScaledStartValuesPositiveExponent( - significand, exponent, estimated_power, need_boundary_deltas, - numerator, denominator, delta_minus, delta_plus); - } else if (estimated_power >= 0) { - InitialScaledStartValuesNegativeExponentPositivePower( - significand, exponent, estimated_power, need_boundary_deltas, - numerator, denominator, delta_minus, delta_plus); - } else { - InitialScaledStartValuesNegativeExponentNegativePower( - significand, exponent, estimated_power, need_boundary_deltas, - numerator, denominator, delta_minus, delta_plus); - } - if (need_boundary_deltas && lower_boundary_is_closer) { - denominator->ShiftLeft(1); - numerator->ShiftLeft(1); - delta_plus->ShiftLeft(1); - } - } - - inline void GenerateShortestDigits(Bignum* numerator, Bignum* denominator, - Bignum* delta_minus, Bignum* delta_plus, - bool is_even, - Vector buffer, int* length); - - inline void FixupMultiply10(int estimated_power, bool is_even, - int* decimal_point, - Bignum* numerator, Bignum* denominator, - Bignum* delta_minus, Bignum* delta_plus) { - bool in_range; - if (is_even) { - in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0; - } else { - in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0; - } - if (in_range) { - *decimal_point = estimated_power + 1; - } else { - *decimal_point = estimated_power; - numerator->Times10(); - if (Bignum::Equal(*delta_minus, *delta_plus)) { - delta_minus->Times10(); - delta_plus->AssignBignum(*delta_minus); - } else { - delta_minus->Times10(); - delta_plus->Times10(); - } - } - } - - inline void BignumDtoa(const double v, Vector buffer, int* length, int* decimal_point) { - ASSERT(v > 0); - ASSERT(!Double(v).IsSpecial()); - uint64_t significand; - int exponent; - bool lower_boundary_is_closer; - significand = Double(v).Significand(); - exponent = Double(v).Exponent(); - lower_boundary_is_closer = Double(v).LowerBoundaryIsCloser(); - const bool need_boundary_deltas = true; - - bool is_even = (significand & 1) == 0; - int normalized_exponent = NormalizedExponent(significand, exponent); - int estimated_power = EstimatePower(normalized_exponent); - - Bignum numerator; - Bignum denominator; - Bignum delta_minus; - Bignum delta_plus; - ASSERT(Bignum::kMaxSignificantBits >= 324*4); - InitialScaledStartValues(significand, exponent, lower_boundary_is_closer, - estimated_power, need_boundary_deltas, - &numerator, &denominator, - &delta_minus, &delta_plus); - FixupMultiply10(estimated_power, is_even, decimal_point, - &numerator, &denominator, - &delta_minus, &delta_plus); - GenerateShortestDigits(&numerator, &denominator, - &delta_minus, &delta_plus, - is_even, buffer, length); - buffer[*length] = '\0'; - } - - inline void GenerateShortestDigits(Bignum* numerator, Bignum* denominator, - Bignum* delta_minus, Bignum* delta_plus, - bool is_even, - Vector buffer, int* length) { - if (Bignum::Equal(*delta_minus, *delta_plus)) { - delta_plus = delta_minus; - } - *length = 0; - for (;;) { - uint16_t digit; - digit = numerator->DivideModuloIntBignum(*denominator); - ASSERT(digit <= 9); - buffer[(*length)++] = static_cast(digit + '0'); - - bool in_delta_room_minus; - bool in_delta_room_plus; - if (is_even) { - in_delta_room_minus = Bignum::LessEqual(*numerator, *delta_minus); - } else { - in_delta_room_minus = Bignum::Less(*numerator, *delta_minus); - } - if (is_even) { - in_delta_room_plus = - Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0; - } else { - in_delta_room_plus = - Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0; - } - if (!in_delta_room_minus && !in_delta_room_plus) { - numerator->Times10(); - delta_minus->Times10(); - if (delta_minus != delta_plus) { - delta_plus->Times10(); - } - } else if (in_delta_room_minus && in_delta_room_plus) { - int compare = Bignum::PlusCompare(*numerator, *numerator, *denominator); - if (compare < 0) { - } else if (compare > 0) { - ASSERT(buffer[(*length) - 1] != '9'); - buffer[(*length) - 1]++; - } else { - if ((buffer[(*length) - 1] - '0') % 2 == 0) { - } else { - ASSERT(buffer[(*length) - 1] != '9'); - buffer[(*length) - 1]++; - } - } - return; - } else if (in_delta_room_minus) { - return; - } else { - ASSERT(buffer[(*length) -1] != '9'); - buffer[(*length) - 1]++; - return; - } - } - } - - inline bool DoubleToAscii( double v, - char * buffer, - int buffer_length, - std::ostream & oss, - int * length, - int * point ) - { - if ( Double( v ).Sign() < 0 ) { - oss << '-'; - v = -v; - } - if ( v == 0.0 ) { - oss << "0.0"; - return true; - } - Vector< char > vector( buffer, buffer_length ); - - if ( ! FastDtoa(v, vector, length, point) ) { - BignumDtoa( v, vector, length, point ); - vector[ * length ] = '\0'; - } - return false; - } - - inline void CreateDecimalRepresentation(const char* decimal_digits, - int length, - int decimal_point, - int digits_after_point, - std::ostream & oss) { - if (decimal_point <= 0) { - oss << '0'; - if (digits_after_point > 0) { - oss << '.'; - for ( int i = 0; i < -decimal_point; ++i ) { - oss << '0'; - } - ASSERT(length <= digits_after_point - (-decimal_point)); - oss.write( decimal_digits, length ); - int remaining_digits = digits_after_point - (-decimal_point) - length; - for ( int i = 0; i < remaining_digits; ++i ) { - oss << '0'; - } - } - } else if (decimal_point >= length) { - oss.write( decimal_digits, length ); - for ( int i = 0; i < decimal_point - length; ++i ) { - oss << '0'; - } - if (digits_after_point > 0) { - oss << '.'; - for ( int i = 0; i < digits_after_point; ++i ) { - oss << '0'; - } - } - } else { - ASSERT(digits_after_point > 0); - oss.write( decimal_digits, decimal_point ); - oss << '.'; - ASSERT(length - decimal_point <= digits_after_point); - oss.write( decimal_digits + decimal_point, length - decimal_point ); - int remaining_digits = digits_after_point - (length - decimal_point); - for ( int i = 0; i < remaining_digits; ++i ) { - oss << '0'; - } - } - if (digits_after_point == 0) { - oss << '.'; - oss << '0'; - } - } - - inline void CreateExponentialRepresentation(const char* decimal_digits, - int length, - int exponent, - std::ostream & oss) { - ASSERT(length != 0); - oss << decimal_digits[ 0 ]; - if (length != 1) { - oss << '.'; - oss.write( decimal_digits + 1, length - 1 ); - } - oss << 'e'; - if (exponent < 0) { - oss << '-'; - exponent = -exponent; - } else { - // oss << '+'; - } - if (exponent == 0) { - oss << '0'; - return; - } - oss << exponent; - } - - inline void Dtostr( std::ostream & oss, const double value ) - { - int decimal_point; - const int kDecimalRepCapacity = kBase10MaximalLength + 1; // Plus 1 is '\0'. - char decimal_rep[ kDecimalRepCapacity ]; - int decimal_rep_length; - - if ( ! DoubleToAscii(value, decimal_rep, kDecimalRepCapacity, - oss, &decimal_rep_length, &decimal_point) ) - { - const int exponent = decimal_point - 1; - if ((-6 <= exponent) && - (exponent < 21)) { - CreateDecimalRepresentation(decimal_rep, decimal_rep_length, - decimal_point, - Max(0, decimal_rep_length - decimal_point), - oss); - } else { - CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent, - oss); - } - } - } - -} // json_double_conversion +} // namespace tao::json::double_conversion #endif diff --git a/include/tao/json/external/itoa.hpp b/include/tao/json/external/itoa.hpp new file mode 100644 index 00000000..5e3afde9 --- /dev/null +++ b/include/tao/json/external/itoa.hpp @@ -0,0 +1,149 @@ +// This header include/tao/json/external/jeaiii.hpp contains +// modified portions of the jeaiii/itoa library from +// https://github.com/jeaiii/itoa +// which is licensed as follows: + +// Copyright (c) 2017 James Edward Anhalt III - https://github.com/jeaiii/itoa +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#ifndef TAO_JSON_EXTERNAL_ITOA_HPP +#define TAO_JSON_EXTERNAL_ITOA_HPP + +#include +#include + +// form a 4.32 fixed point number: t = u * 2^32 / 10^log10(u) +// use as much precision as possible when needed (log10(u) >= 5) +// so shift up then down afterwards by log10(u) * log2(10) ~= 53/16 +// need to round up before and or after in some cases +// once we have the fixed point number we can read off the digit in the upper 32 bits +// and multiply the lower 32 bits by 10 to get the next digit and so on +// we can do 2 digits at a time by multiplying by 100 each time + +// MISSING: +// - x64 optimized version (no need to line up on 32bit boundary, so can multiply by 5 instead of 10 using lea instruction) +// - full 64 bit LG() +// - try splitting the number into chucks that can be processed independently +// - try odd digit first +// - try writing 4 chars at a time + +namespace tao::json::itoa +{ + struct pair + { + char t; + char o; + }; + + // clang-format off +#define TAO_JSON_ITOA_P( T ) { T, '0' }, { T, '1' }, { T, '2' }, { T, '3' }, { T, '4' }, { T, '5' }, { T, '6' }, { T, '7' }, { T, '8' }, { T, '9' } + // clang-format on + + static const pair s_pairs[] = { TAO_JSON_ITOA_P( '0' ), + TAO_JSON_ITOA_P( '1' ), + TAO_JSON_ITOA_P( '2' ), + TAO_JSON_ITOA_P( '3' ), + TAO_JSON_ITOA_P( '4' ), + TAO_JSON_ITOA_P( '5' ), + TAO_JSON_ITOA_P( '6' ), + TAO_JSON_ITOA_P( '7' ), + TAO_JSON_ITOA_P( '8' ), + TAO_JSON_ITOA_P( '9' ) }; + +#define TAO_JSON_ITOA_W( N, I ) *(pair*)&b[ N ] = s_pairs[ I ] +#define TAO_JSON_ITOA_A( N ) t = ( std::uint64_t( 1 ) << ( 32 + N / 5 * N * 53 / 16 ) ) / std::uint32_t( 1e##N ) + 1 + N / 6 - N / 8, t *= u, t >>= N / 5 * N * 53 / 16, t += N / 6 * 4, TAO_JSON_ITOA_W( 0, t >> 32 ) +#define TAO_JSON_ITOA_S( N ) b[ N ] = char( std::uint64_t( 10 ) * std::uint32_t( t ) >> 32 ) + '0' +#define TAO_JSON_ITOA_D( N ) t = std::uint64_t( 100 ) * std::uint32_t( t ), TAO_JSON_ITOA_W( N, t >> 32 ) + +#define TAO_JSON_ITOA_L0 b[ 0 ] = char( u ) + '0' +#define TAO_JSON_ITOA_L1 TAO_JSON_ITOA_W( 0, u ) +#define TAO_JSON_ITOA_L2 TAO_JSON_ITOA_A( 1 ), TAO_JSON_ITOA_S( 2 ) +#define TAO_JSON_ITOA_L3 TAO_JSON_ITOA_A( 2 ), TAO_JSON_ITOA_D( 2 ) +#define TAO_JSON_ITOA_L4 TAO_JSON_ITOA_A( 3 ), TAO_JSON_ITOA_D( 2 ), TAO_JSON_ITOA_S( 4 ) +#define TAO_JSON_ITOA_L5 TAO_JSON_ITOA_A( 4 ), TAO_JSON_ITOA_D( 2 ), TAO_JSON_ITOA_D( 4 ) +#define TAO_JSON_ITOA_L6 TAO_JSON_ITOA_A( 5 ), TAO_JSON_ITOA_D( 2 ), TAO_JSON_ITOA_D( 4 ), TAO_JSON_ITOA_S( 6 ) +#define TAO_JSON_ITOA_L7 TAO_JSON_ITOA_A( 6 ), TAO_JSON_ITOA_D( 2 ), TAO_JSON_ITOA_D( 4 ), TAO_JSON_ITOA_D( 6 ) +#define TAO_JSON_ITOA_L8 TAO_JSON_ITOA_A( 7 ), TAO_JSON_ITOA_D( 2 ), TAO_JSON_ITOA_D( 4 ), TAO_JSON_ITOA_D( 6 ), TAO_JSON_ITOA_S( 8 ) +#define TAO_JSON_ITOA_L9 TAO_JSON_ITOA_A( 8 ), TAO_JSON_ITOA_D( 2 ), TAO_JSON_ITOA_D( 4 ), TAO_JSON_ITOA_D( 6 ), TAO_JSON_ITOA_D( 8 ) + +#define TAO_JSON_ITOA_LN( N ) ( TAO_JSON_ITOA_L##N, b += N + 1 ) + +#define TAO_JSON_ITOA_LG( F ) ( u < 100 ? u < 10 ? F( 0 ) : F( 1 ) : u < 1000000 ? u < 10000 ? u < 1000 ? F( 2 ) : F( 3 ) : u < 100000 ? F( 4 ) : F( 5 ) : u < 100000000 ? u < 10000000 ? F( 6 ) : F( 7 ) : u < 1000000000 ? F( 8 ) : F( 9 ) ) + + inline char* u32toa( const std::uint32_t u, char* b ) + { + std::uint64_t t; + return TAO_JSON_ITOA_LG( TAO_JSON_ITOA_LN ); + } + + inline char* i32toa( const std::int32_t i, char* b ) + { + const std::uint32_t u = i < 0 ? ( *b++ = '-', 0 - std::uint32_t( i ) ) : i; + std::uint64_t t; + return TAO_JSON_ITOA_LG( TAO_JSON_ITOA_LN ); + } + + inline char* u64toa( const std::uint64_t n, char* b ) + { + std::uint32_t u; + std::uint64_t t; + + if( std::uint32_t( n >> 32 ) == 0 ) { + return u = std::uint32_t( n ), TAO_JSON_ITOA_LG( TAO_JSON_ITOA_LN ); + } + std::uint64_t a = n / 100000000; + + if( std::uint32_t( a >> 32 ) == 0 ) { + u = std::uint32_t( a ); + TAO_JSON_ITOA_LG( TAO_JSON_ITOA_LN ); + } + else { + u = std::uint32_t( a / 100000000 ); + TAO_JSON_ITOA_LG( TAO_JSON_ITOA_LN ); + u = a % 100000000; + TAO_JSON_ITOA_LN( 7 ); + } + u = n % 100000000; + return TAO_JSON_ITOA_LN( 7 ); + } + + inline char* i64toa( const std::int64_t i, char* b ) + { + const std::uint64_t n = i < 0 ? ( *b++ = '-', 0 - std::uint64_t( i ) ) : i; + return u64toa( n, b ); + } + + inline void i64tos( std::ostream& o, const std::int64_t i ) + { + char b[ 24 ]; + const auto* s = i64toa( i, b ); + o.write( b, s - b ); + } + + inline void u64tos( std::ostream& o, const std::uint64_t i ) + { + char b[ 24 ]; + const auto* s = u64toa( i, b ); + o.write( b, s - b ); + } + +} // namespace tao::json::itoa + +#endif diff --git a/include/tao/json/external/operators.hpp b/include/tao/json/external/operators.hpp deleted file mode 100644 index bc40f0ba..00000000 --- a/include/tao/json/external/operators.hpp +++ /dev/null @@ -1,658 +0,0 @@ -// The Art of C++ / Operators -// Copyright (c) 2013-2017 Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/operators/ - -#ifndef TAOCPP_OPERATORS_INCLUDE_OPERATORS_HPP -#define TAOCPP_OPERATORS_INCLUDE_OPERATORS_HPP - -#include - -#ifndef TAOCPP_NO_RVALUE_REFERENCE_RESULTS -#define TAOCPP_OPERATORS_BASIC_OP( name, op ) \ - template< typename T, typename U = T > \ - class name \ - { \ - friend T operator op( const T& lhs, const U& rhs ) \ - noexcept( noexcept( T( lhs ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ - { \ - T nrv( lhs ); \ - nrv op##= rhs; \ - return nrv; \ - } \ - \ - friend T operator op( const T& lhs, U&& rhs ) \ - noexcept( noexcept( T( lhs ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ - { \ - T nrv( lhs ); \ - nrv op##= std::move( rhs ); \ - return nrv; \ - } \ - \ - friend T&& operator op( T&& lhs, const U& rhs ) \ - noexcept( noexcept( lhs op##= rhs ) ) \ - { \ - lhs op##= rhs; \ - return std::move( lhs ); \ - } \ - \ - friend T&& operator op( T&& lhs, U&& rhs ) \ - noexcept( noexcept( lhs op##= std::move( rhs ) ) ) \ - { \ - lhs op##= std::move( rhs ); \ - return std::move( lhs ); \ - } \ - } -#else -#define TAOCPP_OPERATORS_BASIC_OP( name, op ) \ - template< typename T, typename U = T > \ - class name \ - { \ - friend T operator op( const T& lhs, const U& rhs ) \ - noexcept( noexcept( T( lhs ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ - { \ - T nrv( lhs ); \ - nrv op##= rhs; \ - return nrv; \ - } \ - \ - friend T operator op( const T& lhs, U&& rhs ) \ - noexcept( noexcept( T( lhs ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ - { \ - T nrv( lhs ); \ - nrv op##= std::move( rhs ); \ - return nrv; \ - } \ - \ - friend T operator op( T&& lhs, const U& rhs ) \ - noexcept( noexcept( T( std::move( lhs ) ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ - { \ - T nrv( std::move( lhs ) ); \ - nrv op##= rhs; \ - return nrv; \ - } \ - \ - friend T operator op( T&& lhs, U&& rhs ) \ - noexcept( noexcept( T( std::move( lhs ) ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ - { \ - T nrv( std::move( lhs ) ); \ - nrv op##= std::move( rhs ); \ - return nrv; \ - } \ - } -#endif - -#define TAOCPP_OPERATORS_BASIC_OP_LEFT( name, op ) \ - template< typename T, typename U > \ - class name##_left \ - { \ - friend T operator op( const U& lhs, const T& rhs ) \ - noexcept( noexcept( T( lhs ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ - { \ - T nrv( lhs ); \ - nrv op##= rhs; \ - return nrv; \ - } \ - \ - friend T operator op( const U& lhs, T&& rhs ) \ - noexcept( noexcept( T( lhs ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ - { \ - T nrv( lhs ); \ - nrv op##= std::move( rhs ); \ - return nrv; \ - } \ - \ - friend T operator op( U&& lhs, const T& rhs ) \ - noexcept( noexcept( T( std::move( lhs ) ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ - { \ - T nrv( std::move( lhs ) ); \ - nrv op##= rhs; \ - return nrv; \ - } \ - \ - friend T operator op( U&& lhs, T&& rhs ) \ - noexcept( noexcept( T( std::move( lhs ) ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ - { \ - T nrv( std::move( lhs ) ); \ - nrv op##= std::move( rhs ); \ - return nrv; \ - } \ - } - -#ifndef TAOCPP_NO_RVALUE_REFERENCE_RESULTS -#define TAOCPP_OPERATORS_BASIC_OP_COMMUTATIVE( name, op ) \ - template< typename T, typename U = T > \ - class commutative_##name \ - { \ - friend T operator op( const T& lhs, const U& rhs ) \ - noexcept( noexcept( T( lhs ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ - { \ - T nrv( lhs ); \ - nrv op##= rhs; \ - return nrv; \ - } \ - \ - friend T operator op( const T& lhs, U&& rhs ) \ - noexcept( noexcept( T( lhs ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ - { \ - T nrv( lhs ); \ - nrv op##= std::move( rhs ); \ - return nrv; \ - } \ - \ - friend T&& operator op( T&& lhs, const U& rhs ) \ - noexcept( noexcept( lhs op##= rhs ) ) \ - { \ - lhs op##= rhs; \ - return std::move( lhs ); \ - } \ - \ - friend T&& operator op( T&& lhs, U&& rhs ) \ - noexcept( noexcept( lhs op##= std::move( rhs ) ) ) \ - { \ - lhs op##= std::move( rhs ); \ - return std::move( lhs ); \ - } \ - \ - friend T operator op( const U& lhs, const T& rhs ) \ - noexcept( noexcept( T( rhs ), std::declval< T& >() op##= lhs, T( std::declval< T& >() ) ) ) \ - { \ - T nrv( rhs ); \ - nrv op##= lhs; \ - return nrv; \ - } \ - \ - friend T&& operator op( const U& lhs, T&& rhs ) \ - noexcept( noexcept( rhs op##= lhs ) ) \ - { \ - rhs op##= lhs; \ - return std::move( rhs ); \ - } \ - \ - friend T operator op( U&& lhs, const T& rhs ) \ - noexcept( noexcept( T( rhs ), std::declval< T& >() op##= std::move( lhs ) ) ) \ - { \ - T nrv( rhs ); \ - nrv op##= std::move( lhs ); \ - return nrv; \ - } \ - \ - friend T&& operator op( U&& lhs, T&& rhs ) \ - noexcept( noexcept( rhs op##= std::move( lhs ) ) ) \ - { \ - rhs op##= std::move( lhs ); \ - return std::move( rhs ); \ - } \ - }; \ - \ - template< typename T > \ - class commutative_##name< T > \ - { \ - friend T operator op( const T& lhs, const T& rhs ) \ - noexcept( noexcept( T( lhs ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ - { \ - T nrv( lhs ); \ - nrv op##= rhs; \ - return nrv; \ - } \ - \ - friend T&& operator op( const T& lhs, T&& rhs ) \ - noexcept( noexcept( rhs op##= lhs ) ) \ - { \ - rhs op##= lhs; \ - return std::move( rhs ); \ - } \ - \ - friend T&& operator op( T&& lhs, const T& rhs ) \ - noexcept( noexcept( lhs op##= rhs ) ) \ - { \ - lhs op##= rhs; \ - return std::move( lhs ); \ - } \ - \ - friend T&& operator op( T&& lhs, T&& rhs ) \ - noexcept( noexcept( lhs op##= std::move( rhs ) ) ) \ - { \ - lhs op##= std::move( rhs ); \ - return std::move( lhs ); \ - } \ - } -#else -#define TAOCPP_OPERATORS_BASIC_OP_COMMUTATIVE( name, op ) \ - template< typename T, typename U = T > \ - class commutative_##name \ - { \ - friend T operator op( const T& lhs, const U& rhs ) \ - noexcept( noexcept( T( lhs ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ - { \ - T nrv( lhs ); \ - nrv op##= rhs; \ - return nrv; \ - } \ - \ - friend T operator op( const T& lhs, U&& rhs ) \ - noexcept( noexcept( T( lhs ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ - { \ - T nrv( lhs ); \ - nrv op##= std::move( rhs ); \ - return nrv; \ - } \ - \ - friend T operator op( T&& lhs, const U& rhs ) \ - noexcept( noexcept( T( std::move( lhs ) ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ - { \ - T nrv( std::move( lhs ) ); \ - nrv op##= rhs; \ - return nrv; \ - } \ - \ - friend T operator op( T&& lhs, U&& rhs ) \ - noexcept( noexcept( T( std::move( lhs ) ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ - { \ - T nrv( std::move( lhs ) ); \ - nrv op##= std::move( rhs ); \ - return nrv; \ - } \ - \ - friend T operator op( const U& lhs, const T& rhs ) \ - noexcept( noexcept( T( rhs ), std::declval< T& >() op##= lhs, T( std::declval< T& >() ) ) ) \ - { \ - T nrv( rhs ); \ - nrv op##= lhs; \ - return nrv; \ - } \ - \ - friend T operator op( const U& lhs, T&& rhs ) \ - noexcept( noexcept( T( std::move( rhs ) ), std::declval< T& >() op##= lhs, T( std::declval< T& >() ) ) ) \ - { \ - T nrv( std::move( rhs ) ); \ - nrv op##= lhs; \ - return nrv; \ - } \ - \ - friend T operator op( U&& lhs, const T& rhs ) \ - noexcept( noexcept( T( rhs ), std::declval< T& >() op##= std::move( lhs ) ) ) \ - { \ - T nrv( rhs ); \ - nrv op##= std::move( lhs ); \ - return nrv; \ - } \ - \ - friend T operator op( U&& lhs, T&& rhs ) \ - noexcept( noexcept( T( std::move( rhs ) ), std::declval< T& >() op##= std::move( lhs ) ) ) \ - { \ - T nrv( std::move( rhs ) ); \ - nrv op##= std::move( lhs ); \ - return nrv; \ - } \ - }; \ - \ - template< typename T > \ - class commutative_##name< T > \ - { \ - friend T operator op( const T& lhs, const T& rhs ) \ - noexcept( noexcept( T( lhs ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ - { \ - T nrv( lhs ); \ - nrv op##= rhs; \ - return nrv; \ - } \ - \ - friend T operator op( const T& lhs, T&& rhs ) \ - noexcept( noexcept( T( lhs ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ - { \ - T nrv( lhs ); \ - nrv op##= std::move( rhs ); \ - return nrv; \ - } \ - \ - friend T operator op( T&& lhs, const T& rhs ) \ - noexcept( noexcept( T( std::move( lhs ) ), std::declval< T& >() op##= rhs, T( std::declval< T& >() ) ) ) \ - { \ - T nrv( std::move( lhs ) ); \ - nrv op##= rhs; \ - return nrv; \ - } \ - \ - friend T operator op( T&& lhs, T&& rhs ) \ - noexcept( noexcept( T( std::move( lhs ) ), std::declval< T& >() op##= std::move( rhs ), T( std::declval< T& >() ) ) ) \ - { \ - T nrv( std::move( lhs ) ); \ - nrv op##= std::move( rhs ); \ - return nrv; \ - } \ - } -#endif - -namespace tao -{ - namespace operators - { - template< typename T, typename U = T > - class equality_comparable - { - friend bool operator!=( const T& lhs, const U& rhs ) - noexcept( noexcept( static_cast< bool >( lhs == rhs ) ) ) - { - return !static_cast< bool >( lhs == rhs ); - } - - friend bool operator==( const U& lhs, const T& rhs ) - noexcept( noexcept( static_cast< bool >( rhs == lhs ) ) ) - { - return static_cast< bool >( rhs == lhs ); - } - - friend bool operator!=( const U& lhs, const T& rhs ) - noexcept( noexcept( static_cast< bool >( rhs != lhs ) ) ) - { - return static_cast< bool >( rhs != lhs ); - } - }; - - template< typename T > - class equality_comparable< T > - { - friend bool operator!=( const T& lhs, const T& rhs ) - noexcept( noexcept( static_cast< bool >( lhs == rhs ) ) ) - { - return !static_cast< bool >( lhs == rhs ); - } - }; - - template< typename T, typename U = T > - class less_than_comparable - { - friend bool operator<=( const T& lhs, const U& rhs ) - noexcept( noexcept( static_cast< bool >( lhs > rhs ) ) ) - { - return !static_cast< bool >( lhs > rhs ); - } - - friend bool operator>=( const T& lhs, const U& rhs ) - noexcept( noexcept( static_cast< bool >( lhs < rhs ) ) ) - { - return !static_cast< bool >( lhs < rhs ); - } - - friend bool operator<( const U& lhs, const T& rhs ) - noexcept( noexcept( static_cast< bool >( rhs > lhs ) ) ) - { - return static_cast< bool >( rhs > lhs ); - } - - friend bool operator>( const U& lhs, const T& rhs ) - noexcept( noexcept( static_cast< bool >( rhs < lhs ) ) ) - { - return static_cast< bool >( rhs < lhs ); - } - - friend bool operator<=( const U& lhs, const T& rhs ) - noexcept( noexcept( static_cast< bool >( rhs >= lhs ) ) ) - { - return static_cast< bool >( rhs >= lhs ); - } - - friend bool operator>=( const U& lhs, const T& rhs ) - noexcept( noexcept( static_cast< bool >( rhs <= lhs ) ) ) - { - return static_cast< bool >( rhs <= lhs ); - } - }; - - template< typename T > - class less_than_comparable< T > - { - friend bool operator>( const T& lhs, const T& rhs ) - noexcept( noexcept( static_cast< bool >( rhs < lhs ) ) ) - { - return static_cast< bool >( rhs < lhs ); - } - - friend bool operator<=( const T& lhs, const T& rhs ) - noexcept( noexcept( static_cast< bool >( rhs < lhs ) ) ) - { - return !static_cast< bool >( rhs < lhs ); - } - - friend bool operator>=( const T& lhs, const T& rhs ) - noexcept( noexcept( static_cast< bool >( lhs < rhs ) ) ) - { - return !static_cast< bool >( lhs < rhs ); - } - }; - - template< typename T, typename U = T > - class totally_ordered - : less_than_comparable< T, U >, equality_comparable< T, U > - { - }; - - template< typename T, typename U = T > - class equivalent - { - friend bool operator==( const T& lhs, const U& rhs ) - noexcept( noexcept( static_cast< bool >( lhs < rhs ), static_cast< bool >( lhs > rhs ) ) ) - { - return !static_cast< bool >( lhs < rhs ) && !static_cast< bool >( lhs > rhs ); - } - }; - - template< typename T > - class equivalent< T > - { - friend bool operator==( const T& lhs, const T& rhs ) - noexcept( noexcept( static_cast< bool >( lhs < rhs ) ) ) - { - return !static_cast< bool >( lhs < rhs ) && !static_cast< bool >( rhs < lhs ); - } - }; - - template< typename T, typename U = T > - class partially_ordered - { - friend bool operator<=( const T& lhs, const U& rhs ) - noexcept( noexcept( static_cast< bool >( lhs < rhs ), static_cast< bool >( lhs == rhs ) ) ) - { - return static_cast< bool >( lhs < rhs ) || static_cast< bool >( lhs == rhs ); - } - - friend bool operator>=( const T& lhs, const U& rhs ) - noexcept( noexcept( static_cast< bool >( lhs > rhs ), static_cast< bool >( lhs == rhs ) ) ) - { - return static_cast< bool >( lhs > rhs ) || static_cast< bool >( lhs == rhs ); - } - - friend bool operator<( const U& lhs, const T& rhs ) - noexcept( noexcept( static_cast< bool >( rhs > lhs ) ) ) - { - return static_cast< bool >( rhs > lhs ); - } - - friend bool operator>( const U& lhs, const T& rhs ) - noexcept( noexcept( static_cast< bool >( rhs < lhs ) ) ) - { - return static_cast< bool >( rhs < lhs ); - } - - friend bool operator<=( const U& lhs, const T& rhs ) - noexcept( noexcept( static_cast< bool >( rhs >= lhs ) ) ) - { - return static_cast< bool >( rhs >= lhs ); - } - - friend bool operator>=( const U& lhs, const T& rhs ) - noexcept( noexcept( static_cast< bool >( rhs <= lhs ) ) ) - { - return static_cast< bool >( rhs <= lhs ); - } - }; - - template< typename T > - class partially_ordered< T > - { - friend bool operator>( const T& lhs, const T& rhs ) - noexcept( noexcept( static_cast< bool >( rhs < lhs ) ) ) - { - return static_cast< bool >( rhs < lhs ); - } - - friend bool operator<=( const T& lhs, const T& rhs ) - noexcept( noexcept( static_cast< bool >( lhs < rhs ), static_cast< bool >( lhs == rhs ) ) ) - { - return static_cast< bool >( lhs < rhs ) || static_cast< bool >( lhs == rhs ); - } - - friend bool operator>=( const T& lhs, const T& rhs ) - noexcept( noexcept( static_cast< bool >( rhs < lhs ), static_cast< bool >( lhs == rhs ) ) ) - { - return static_cast< bool >( rhs < lhs ) || static_cast< bool >( lhs == rhs ); - } - }; - - TAOCPP_OPERATORS_BASIC_OP( addable, + ); - TAOCPP_OPERATORS_BASIC_OP_LEFT( addable, + ); - TAOCPP_OPERATORS_BASIC_OP_COMMUTATIVE( addable, + ); - - TAOCPP_OPERATORS_BASIC_OP( subtractable, - ); - TAOCPP_OPERATORS_BASIC_OP_LEFT( subtractable, - ); - - TAOCPP_OPERATORS_BASIC_OP( multipliable, * ); - TAOCPP_OPERATORS_BASIC_OP_LEFT( multipliable, * ); - TAOCPP_OPERATORS_BASIC_OP_COMMUTATIVE( multipliable, * ); - - TAOCPP_OPERATORS_BASIC_OP( dividable, / ); - TAOCPP_OPERATORS_BASIC_OP_LEFT( dividable, / ); - - TAOCPP_OPERATORS_BASIC_OP( modable, % ); - TAOCPP_OPERATORS_BASIC_OP_LEFT( modable, % ); - - template< typename T, typename U = T > - class ring - : commutative_addable< T, U >, subtractable< T, U >, subtractable_left< T, U >, multipliable< T, U > - { - }; - - template< typename T > - class ring< T > - : commutative_addable< T >, subtractable< T >, multipliable< T > - { - }; - - template< typename T, typename U = T > - class ordered_ring - : ring< T, U >, totally_ordered< T, U > - { - }; - - template< typename T, typename U = T > - class commutative_ring - : commutative_addable< T, U >, subtractable< T, U >, subtractable_left< T, U >, commutative_multipliable< T, U > - { - }; - - template< typename T > - class commutative_ring< T > - : commutative_addable< T >, subtractable< T >, commutative_multipliable< T > - { - }; - - template< typename T, typename U = T > - class ordered_commutative_ring - : commutative_ring< T, U >, totally_ordered< T, U > - { - }; - - template< typename T, typename U = T > - class field - : commutative_ring< T, U >, dividable< T, U >, dividable_left< T, U > - { - }; - - template< typename T > - class field< T > - : commutative_ring< T >, dividable< T > - { - }; - - template< typename T, typename U = T > - class ordered_field - : field< T, U >, totally_ordered< T, U > - { - }; - - TAOCPP_OPERATORS_BASIC_OP( andable, & ); - TAOCPP_OPERATORS_BASIC_OP_LEFT( andable, & ); - TAOCPP_OPERATORS_BASIC_OP_COMMUTATIVE( andable, & ); - - TAOCPP_OPERATORS_BASIC_OP( orable, | ); - TAOCPP_OPERATORS_BASIC_OP_LEFT( orable, | ); - TAOCPP_OPERATORS_BASIC_OP_COMMUTATIVE( orable, | ); - - TAOCPP_OPERATORS_BASIC_OP( xorable, ^ ); - TAOCPP_OPERATORS_BASIC_OP_LEFT( xorable, ^ ); - TAOCPP_OPERATORS_BASIC_OP_COMMUTATIVE( xorable, ^ ); - - template< typename T, typename U = T > - class bitwise - : andable< T, U >, orable< T, U >, xorable< T, U > - { - }; - - template< typename T, typename U > - class bitwise_left - : andable_left< T, U >, orable_left< T, U >, xorable_left< T, U > - { - }; - - template< typename T, typename U = T > - class commutative_bitwise - : commutative_andable< T, U >, commutative_orable< T, U >, commutative_xorable< T, U > - { - }; - - TAOCPP_OPERATORS_BASIC_OP( left_shiftable, << ); - TAOCPP_OPERATORS_BASIC_OP( right_shiftable, >> ); - - template< typename T, typename U = T > - class shiftable - : left_shiftable< T, U >, right_shiftable< T, U > - { - }; - - template< typename T > - class incrementable - { - friend T operator++( T& arg, int ) - noexcept( noexcept( T( arg ), ++arg, T( std::declval< T >() ) ) ) - { - const T nrv( arg ); - ++arg; - return nrv; - } - }; - - template< typename T > - class decrementable - { - friend T operator--( T& arg, int ) - noexcept( noexcept( T( arg ), --arg, T( std::declval< T >() ) ) ) - { - const T nrv( arg ); - --arg; - return nrv; - } - }; - - template< typename T > - class unit_steppable - : incrementable< T >, decrementable< T > - { - }; - } -} - -#undef TAOCPP_OPERATORS_BASIC_OP -#undef TAOCPP_OPERATORS_BASIC_OP_LEFT -#undef TAOCPP_OPERATORS_BASIC_OP_COMMUTATIVE - -#endif diff --git a/include/tao/json/external/optional.hpp b/include/tao/json/external/optional.hpp deleted file mode 100644 index c947c5ae..00000000 --- a/include/tao/json/external/optional.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// The Art of C++ -// Copyright (c) 2016-2017 Daniel Frey - -#ifndef TAOCPP_INCLUDE_OPTIONAL_HPP -#define TAOCPP_INCLUDE_OPTIONAL_HPP - -#ifndef TAOCPP_USE_STD_OPTIONAL -#if __cplusplus >= 201703L -#define TAOCPP_USE_STD_OPTIONAL -#endif -#endif - -#ifndef TAOCPP_USE_STD_OPTIONAL -#ifndef TAOCPP_USE_TS_OPTIONAL -#if( __cplusplus >= 201402L ) && ( ( __GNUC__ > 4 ) || ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 9 ) ) -#define TAOCPP_USE_TS_OPTIONAL -#endif -#endif -#endif - -#if defined( TAOCPP_USE_STD_OPTIONAL ) -#include -#elif defined( TAOCPP_USE_TS_OPTIONAL ) -#include -#else -#include "akrzemi1/optional.hpp" -#endif - -namespace tao -{ - -#if defined( TAOCPP_USE_STD_OPTIONAL ) - using std::optional; - using std::nullopt; - using std::in_place; - using std::make_optional; -#else - using std::experimental::optional; - using std::experimental::nullopt; - using std::experimental::in_place; - using std::experimental::make_optional; -#endif - -} // namespace tao - -#endif diff --git a/include/tao/json/external/pegtl.hpp b/include/tao/json/external/pegtl.hpp index 2855db08..414dd7fa 100644 --- a/include/tao/json/external/pegtl.hpp +++ b/include/tao/json/external/pegtl.hpp @@ -1,15 +1,20 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_PEGTL_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_PEGTL_HPP +#ifndef TAO_JSON_PEGTL_HPP +#define TAO_JSON_PEGTL_HPP #include "pegtl/config.hpp" #include "pegtl/version.hpp" -#include "pegtl/ascii.hpp" #include "pegtl/parse.hpp" + +#include "pegtl/ascii.hpp" #include "pegtl/rules.hpp" +#include "pegtl/uint16.hpp" +#include "pegtl/uint32.hpp" +#include "pegtl/uint64.hpp" +#include "pegtl/uint8.hpp" #include "pegtl/utf16.hpp" #include "pegtl/utf32.hpp" #include "pegtl/utf8.hpp" @@ -17,12 +22,29 @@ #include "pegtl/argv_input.hpp" #include "pegtl/buffer_input.hpp" #include "pegtl/cstream_input.hpp" -#include "pegtl/file_input.hpp" #include "pegtl/istream_input.hpp" #include "pegtl/memory_input.hpp" #include "pegtl/read_input.hpp" #include "pegtl/string_input.hpp" +// this has to be included *after* the above inputs, +// otherwise the amalgamated header will not work! +#include "pegtl/file_input.hpp" + +#include "pegtl/change_action.hpp" +#include "pegtl/change_action_and_state.hpp" +#include "pegtl/change_action_and_states.hpp" +#include "pegtl/change_control.hpp" +#include "pegtl/change_state.hpp" +#include "pegtl/change_states.hpp" + +#include "pegtl/disable_action.hpp" +#include "pegtl/enable_action.hpp" + +#include "pegtl/discard_input.hpp" +#include "pegtl/discard_input_on_failure.hpp" +#include "pegtl/discard_input_on_success.hpp" + // The following are not included by // default because they include . diff --git a/include/tao/json/external/pegtl/analysis/analyze_cycles.hpp b/include/tao/json/external/pegtl/analysis/analyze_cycles.hpp index 78c252e5..4586d5d0 100644 --- a/include/tao/json/external/pegtl/analysis/analyze_cycles.hpp +++ b/include/tao/json/external/pegtl/analysis/analyze_cycles.hpp @@ -1,13 +1,15 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_ANALYZE_CYCLES_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_ANALYZE_CYCLES_HPP +#ifndef TAO_JSON_PEGTL_ANALYSIS_ANALYZE_CYCLES_HPP +#define TAO_JSON_PEGTL_ANALYSIS_ANALYZE_CYCLES_HPP #include #include #include +#include +#include #include #include @@ -17,118 +19,109 @@ #include "grammar_info.hpp" #include "insert_guard.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::analysis { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct analyze_cycles_impl { - namespace analysis + protected: + explicit analyze_cycles_impl( const bool verbose ) noexcept + : m_verbose( verbose ), + m_problems( 0 ) { - class analyze_cycles_impl - { - protected: - explicit analyze_cycles_impl( const bool verbose ) noexcept - : m_verbose( verbose ), - m_problems( 0 ) - { - } + } - const bool m_verbose; - unsigned m_problems; - grammar_info m_info; - std::set< std::string > m_stack; - std::map< std::string, bool > m_cache; - std::map< std::string, bool > m_results; - - const std::map< std::string, rule_info >::const_iterator find( const std::string& name ) const noexcept - { - const auto iter = m_info.map.find( name ); - assert( iter != m_info.map.end() ); - return iter; - } + const bool m_verbose; + unsigned m_problems; + grammar_info m_info; + std::set< std::string_view > m_stack; + std::map< std::string_view, bool > m_cache; + std::map< std::string_view, bool > m_results; - bool work( const std::map< std::string, rule_info >::const_iterator& start, const bool accum ) - { - const auto j = m_cache.find( start->first ); + [[nodiscard]] std::map< std::string_view, rule_info >::const_iterator find( const std::string_view name ) const noexcept + { + const auto iter = m_info.map.find( name ); + assert( iter != m_info.map.end() ); + return iter; + } - if( j != m_cache.end() ) { - return j->second; + [[nodiscard]] bool work( const std::map< std::string_view, rule_info >::const_iterator& start, const bool accum ) + { + const auto j = m_cache.find( start->first ); + + if( j != m_cache.end() ) { + return j->second; + } + if( const auto g = insert_guard( m_stack, start->first ) ) { + switch( start->second.type ) { + case rule_type::any: { + bool a = false; + for( const auto& r : start->second.rules ) { + a = a || work( find( r ), accum || a ); + } + return m_cache[ start->first ] = true; } - if( const auto g = make_insert_guard( m_stack, start->first ) ) { - switch( start->second.type ) { - case rule_type::ANY: { - bool a = false; - for( const auto& r : start->second.rules ) { - a = a || work( find( r ), accum || a ); - } - return m_cache[ start->first ] = true; - } - case rule_type::OPT: { - bool a = false; - for( const auto& r : start->second.rules ) { - a = a || work( find( r ), accum || a ); - } - return m_cache[ start->first ] = false; - } - case rule_type::SEQ: { - bool a = false; - for( const auto& r : start->second.rules ) { - a = a || work( find( r ), accum || a ); - } - return m_cache[ start->first ] = a; - } - case rule_type::SOR: { - bool a = true; - for( const auto& r : start->second.rules ) { - a = a && work( find( r ), accum ); - } - return m_cache[ start->first ] = a; - } + case rule_type::opt: { + bool a = false; + for( const auto& r : start->second.rules ) { + a = a || work( find( r ), accum || a ); } - throw std::runtime_error( "code should be unreachable" ); // LCOV_EXCL_LINE + return m_cache[ start->first ] = false; } - if( !accum ) { - ++m_problems; - if( m_verbose ) { - std::cout << "problem: cycle without progress detected at rule class " << start->first << std::endl; // LCOV_EXCL_LINE + case rule_type::seq: { + bool a = false; + for( const auto& r : start->second.rules ) { + a = a || work( find( r ), accum || a ); } + return m_cache[ start->first ] = a; } - return m_cache[ start->first ] = accum; - } - }; - - template< typename Grammar > - class analyze_cycles - : private analyze_cycles_impl - { - public: - explicit analyze_cycles( const bool verbose ) - : analyze_cycles_impl( verbose ) - { - Grammar::analyze_t::template insert< Grammar >( m_info ); - } - - std::size_t problems() - { - for( auto i = m_info.map.begin(); i != m_info.map.end(); ++i ) { - m_results[ i->first ] = work( i, false ); - m_cache.clear(); + case rule_type::sor: { + bool a = true; + for( const auto& r : start->second.rules ) { + a = a && work( find( r ), accum ); + } + return m_cache[ start->first ] = a; } - return m_problems; } - - template< typename Rule > - bool consumes() const noexcept - { - const auto i = m_results.find( internal::demangle< Rule >() ); - assert( i != m_results.end() ); - return i->second; + throw std::logic_error( "code should be unreachable: invalid rule_type value" ); // LCOV_EXCL_LINE + } + if( !accum ) { + ++m_problems; + if( m_verbose ) { + std::cout << "problem: cycle without progress detected at rule class " << start->first << std::endl; // LCOV_EXCL_LINE } - }; - - } // namespace analysis + } + return m_cache[ start->first ] = accum; + } + }; + + template< typename Grammar > + struct analyze_cycles + : private analyze_cycles_impl + { + explicit analyze_cycles( const bool verbose ) + : analyze_cycles_impl( verbose ) + { + Grammar::analyze_t::template insert< Grammar >( m_info ); + } - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + [[nodiscard]] std::size_t problems() + { + for( auto i = m_info.map.begin(); i != m_info.map.end(); ++i ) { + m_results[ i->first ] = work( i, false ); + m_cache.clear(); + } + return m_problems; + } + + template< typename Rule > + [[nodiscard]] bool consumes() const noexcept + { + const auto i = m_results.find( internal::demangle< Rule >() ); + assert( i != m_results.end() ); + return i->second; + } + }; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::analysis #endif diff --git a/include/tao/json/external/pegtl/analysis/counted.hpp b/include/tao/json/external/pegtl/analysis/counted.hpp index f04673ea..5e34638b 100644 --- a/include/tao/json/external/pegtl/analysis/counted.hpp +++ b/include/tao/json/external/pegtl/analysis/counted.hpp @@ -1,29 +1,23 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_COUNTED_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_COUNTED_HPP +#ifndef TAO_JSON_PEGTL_ANALYSIS_COUNTED_HPP +#define TAO_JSON_PEGTL_ANALYSIS_COUNTED_HPP #include "../config.hpp" +#include + #include "generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::analysis { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< rule_type Type, std::size_t Count, typename... Rules > + struct counted + : generic< ( Count != 0 ) ? Type : rule_type::opt, Rules... > { - namespace analysis - { - template< rule_type Type, unsigned Count, typename... Rules > - struct counted - : generic< ( Count != 0 ) ? Type : rule_type::OPT, Rules... > - { - }; - - } // namespace analysis - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + }; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::analysis #endif diff --git a/include/tao/json/external/pegtl/analysis/generic.hpp b/include/tao/json/external/pegtl/analysis/generic.hpp index e2ebef50..01cd0142 100644 --- a/include/tao/json/external/pegtl/analysis/generic.hpp +++ b/include/tao/json/external/pegtl/analysis/generic.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_GENERIC_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_GENERIC_HPP +#ifndef TAO_JSON_PEGTL_ANALYSIS_GENERIC_HPP +#define TAO_JSON_PEGTL_ANALYSIS_GENERIC_HPP #include "../config.hpp" @@ -10,30 +10,22 @@ #include "insert_rules.hpp" #include "rule_type.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::analysis { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< rule_type Type, typename... Rules > + struct generic { - namespace analysis + template< typename Name > + static std::string_view insert( grammar_info& g ) { - template< rule_type Type, typename... Rules > - struct generic - { - template< typename Name > - static std::string insert( grammar_info& g ) - { - const auto r = g.insert< Name >( Type ); - if( r.second ) { - insert_rules< Rules... >::insert( g, r.first->second ); - } - return r.first->first; - } - }; - - } // namespace analysis - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + const auto [ it, success ] = g.insert< Name >( Type ); + if( success ) { + insert_rules< Rules... >::insert( g, it->second ); + } + return it->first; + } + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::analysis #endif diff --git a/include/tao/json/external/pegtl/analysis/grammar_info.hpp b/include/tao/json/external/pegtl/analysis/grammar_info.hpp index 6ca96f47..f1ade3a6 100644 --- a/include/tao/json/external/pegtl/analysis/grammar_info.hpp +++ b/include/tao/json/external/pegtl/analysis/grammar_info.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_GRAMMAR_INFO_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_GRAMMAR_INFO_HPP +#ifndef TAO_JSON_PEGTL_ANALYSIS_GRAMMAR_INFO_HPP +#define TAO_JSON_PEGTL_ANALYSIS_GRAMMAR_INFO_HPP #include #include @@ -13,28 +13,20 @@ #include "rule_info.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::analysis { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct grammar_info { - namespace analysis - { - struct grammar_info - { - using map_t = std::map< std::string, rule_info >; - map_t map; - - template< typename Name > - std::pair< map_t::iterator, bool > insert( const rule_type type ) - { - return map.insert( map_t::value_type( internal::demangle< Name >(), rule_info( type ) ) ); - } - }; + using map_t = std::map< std::string_view, rule_info >; + map_t map; - } // namespace analysis - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Name > + auto insert( const rule_type type ) + { + return map.try_emplace( internal::demangle< Name >(), rule_info( type ) ); + } + }; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::analysis #endif diff --git a/include/tao/json/external/pegtl/analysis/insert_guard.hpp b/include/tao/json/external/pegtl/analysis/insert_guard.hpp index 4b558412..597d4b8c 100644 --- a/include/tao/json/external/pegtl/analysis/insert_guard.hpp +++ b/include/tao/json/external/pegtl/analysis/insert_guard.hpp @@ -1,66 +1,51 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_INSERT_GUARD_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_INSERT_GUARD_HPP +#ifndef TAO_JSON_PEGTL_ANALYSIS_INSERT_GUARD_HPP +#define TAO_JSON_PEGTL_ANALYSIS_INSERT_GUARD_HPP #include #include "../config.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::analysis { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename C > + class insert_guard { - namespace analysis + public: + insert_guard( C& container, const typename C::value_type& value ) + : m_i( container.insert( value ) ), + m_c( container ) { - template< typename C > - class insert_guard - { - public: - insert_guard( insert_guard&& other ) noexcept - : m_i( other.m_i ), - m_c( other.m_c ) - { - other.m_c = nullptr; - } + } - insert_guard( C& container, const typename C::value_type& value ) - : m_i( container.insert( value ) ), - m_c( &container ) - { - } + insert_guard( const insert_guard& ) = delete; + insert_guard( insert_guard&& ) = delete; - ~insert_guard() - { - if( m_c && m_i.second ) { - m_c->erase( m_i.first ); - } - } - - insert_guard( const insert_guard& ) = delete; - void operator=( const insert_guard& ) = delete; - - explicit operator bool() const noexcept - { - return m_i.second; - } + ~insert_guard() + { + if( m_i.second ) { + m_c.erase( m_i.first ); + } + } - private: - const std::pair< typename C::iterator, bool > m_i; - C* m_c; - }; + void operator=( const insert_guard& ) = delete; + void operator=( insert_guard&& ) = delete; - template< typename C > - insert_guard< C > make_insert_guard( C& container, const typename C::value_type& value ) - { - return insert_guard< C >( container, value ); - } + explicit operator bool() const noexcept + { + return m_i.second; + } - } // namespace analysis + private: + const std::pair< typename C::iterator, bool > m_i; + C& m_c; + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename C > + insert_guard( C&, const typename C::value_type& )->insert_guard< C >; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::analysis #endif diff --git a/include/tao/json/external/pegtl/analysis/insert_rules.hpp b/include/tao/json/external/pegtl/analysis/insert_rules.hpp index f8be0728..9cfb51f0 100644 --- a/include/tao/json/external/pegtl/analysis/insert_rules.hpp +++ b/include/tao/json/external/pegtl/analysis/insert_rules.hpp @@ -1,45 +1,25 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_INSERT_RULES_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_INSERT_RULES_HPP +#ifndef TAO_JSON_PEGTL_ANALYSIS_INSERT_RULES_HPP +#define TAO_JSON_PEGTL_ANALYSIS_INSERT_RULES_HPP #include "../config.hpp" #include "grammar_info.hpp" #include "rule_info.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::analysis { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename... Rules > + struct insert_rules { - namespace analysis + static void insert( grammar_info& g, rule_info& r ) { - template< typename... > - struct insert_rules; + ( r.rules.emplace_back( Rules::analyze_t::template insert< Rules >( g ) ), ... ); + } + }; - template<> - struct insert_rules<> - { - static void insert( grammar_info&, rule_info& ) - { - } - }; - - template< typename Rule, typename... Rules > - struct insert_rules< Rule, Rules... > - { - static void insert( grammar_info& g, rule_info& r ) - { - r.rules.push_back( Rule::analyze_t::template insert< Rule >( g ) ); - insert_rules< Rules... >::insert( g, r ); - } - }; - - } // namespace analysis - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::analysis #endif diff --git a/include/tao/json/external/pegtl/analysis/rule_info.hpp b/include/tao/json/external/pegtl/analysis/rule_info.hpp index 3bff9b66..25efeccb 100644 --- a/include/tao/json/external/pegtl/analysis/rule_info.hpp +++ b/include/tao/json/external/pegtl/analysis/rule_info.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_RULE_INFO_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_RULE_INFO_HPP +#ifndef TAO_JSON_PEGTL_ANALYSIS_RULE_INFO_HPP +#define TAO_JSON_PEGTL_ANALYSIS_RULE_INFO_HPP #include #include @@ -11,27 +11,19 @@ #include "rule_type.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::analysis { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct rule_info { - namespace analysis + explicit rule_info( const rule_type in_type ) noexcept + : type( in_type ) { - struct rule_info - { - explicit rule_info( const rule_type in_type ) - : type( in_type ) - { - } + } - rule_type type; - std::vector< std::string > rules; - }; + rule_type type; + std::vector< std::string > rules; + }; - } // namespace analysis - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::analysis #endif diff --git a/include/tao/json/external/pegtl/analysis/rule_type.hpp b/include/tao/json/external/pegtl/analysis/rule_type.hpp index 78efe4ca..f82f2299 100644 --- a/include/tao/json/external/pegtl/analysis/rule_type.hpp +++ b/include/tao/json/external/pegtl/analysis/rule_type.hpp @@ -1,29 +1,21 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_RULE_TYPE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_ANALYSIS_RULE_TYPE_HPP +#ifndef TAO_JSON_PEGTL_ANALYSIS_RULE_TYPE_HPP +#define TAO_JSON_PEGTL_ANALYSIS_RULE_TYPE_HPP #include "../config.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::analysis { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + enum class rule_type : char { - namespace analysis - { - enum class rule_type : char - { - ANY, // Consumption-on-success is always true; assumes bounded repetition of conjunction of sub-rules. - OPT, // Consumption-on-success not necessarily true; assumes bounded repetition of conjunction of sub-rules. - SEQ, // Consumption-on-success depends on consumption of (non-zero bounded repetition of) conjunction of sub-rules. - SOR // Consumption-on-success depends on consumption of (non-zero bounded repetition of) disjunction of sub-rules. - }; + any, // Consumption-on-success is always true; assumes bounded repetition of conjunction of sub-rules. + opt, // Consumption-on-success not necessarily true; assumes bounded repetition of conjunction of sub-rules. + seq, // Consumption-on-success depends on consumption of (non-zero bounded repetition of) conjunction of sub-rules. + sor // Consumption-on-success depends on consumption of (non-zero bounded repetition of) disjunction of sub-rules. + }; - } // namespace analysis - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::analysis #endif diff --git a/include/tao/json/external/pegtl/analyze.hpp b/include/tao/json/external/pegtl/analyze.hpp index 4b30e0ca..4b0ff629 100644 --- a/include/tao/json/external/pegtl/analyze.hpp +++ b/include/tao/json/external/pegtl/analyze.hpp @@ -1,25 +1,21 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ANALYZE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_ANALYZE_HPP +#ifndef TAO_JSON_PEGTL_ANALYZE_HPP +#define TAO_JSON_PEGTL_ANALYZE_HPP #include "config.hpp" #include "analysis/analyze_cycles.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Rule > + [[nodiscard]] std::size_t analyze( const bool verbose = true ) { - template< typename Rule > - std::size_t analyze( const bool verbose = true ) - { - return analysis::analyze_cycles< Rule >( verbose ).problems(); - } + return analysis::analyze_cycles< Rule >( verbose ).problems(); + } - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/apply_mode.hpp b/include/tao/json/external/pegtl/apply_mode.hpp index a496b0a5..b06b029c 100644 --- a/include/tao/json/external/pegtl/apply_mode.hpp +++ b/include/tao/json/external/pegtl/apply_mode.hpp @@ -1,23 +1,19 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_APPLY_MODE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_APPLY_MODE_HPP +#ifndef TAO_JSON_PEGTL_APPLY_MODE_HPP +#define TAO_JSON_PEGTL_APPLY_MODE_HPP #include "config.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + enum class apply_mode : bool { - enum class apply_mode : bool - { - ACTION = true, - NOTHING = false - }; + action = true, + nothing = false + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/argv_input.hpp b/include/tao/json/external/pegtl/argv_input.hpp index ea1fe271..bbb6d008 100644 --- a/include/tao/json/external/pegtl/argv_input.hpp +++ b/include/tao/json/external/pegtl/argv_input.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ARGV_INPUT_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_ARGV_INPUT_HPP +#ifndef TAO_JSON_PEGTL_ARGV_INPUT_HPP +#define TAO_JSON_PEGTL_ARGV_INPUT_HPP #include #include @@ -14,39 +14,38 @@ #include "memory_input.hpp" #include "tracking_mode.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + namespace internal { - namespace internal + [[nodiscard]] inline std::string make_argv_source( const std::size_t argn ) { - inline std::string make_argv_source( const std::size_t argn ) - { - std::ostringstream os; - os << "argv[" << argn << ']'; - return os.str(); - } - - } // namespace internal - - template< tracking_mode P = tracking_mode::IMMEDIATE, typename Eol = eol::lf_crlf > - struct argv_input - : public memory_input< P, Eol > + std::ostringstream os; + os << "argv[" << argn << ']'; + return os.str(); + } + + } // namespace internal + + template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf > + struct argv_input + : memory_input< P, Eol > + { + template< typename T > + argv_input( char** argv, const std::size_t argn, T&& in_source ) + : memory_input< P, Eol >( static_cast< const char* >( argv[ argn ] ), std::forward< T >( in_source ) ) { - template< typename T > - argv_input( char** argv, const std::size_t argn, T&& in_source ) - : memory_input< P, Eol >( static_cast< const char* >( argv[ argn ] ), std::forward< T >( in_source ) ) - { - } + } - argv_input( char** argv, const std::size_t argn ) - : argv_input( argv, argn, internal::make_argv_source( argn ) ) - { - } - }; + argv_input( char** argv, const std::size_t argn ) + : argv_input( argv, argn, internal::make_argv_source( argn ) ) + { + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename... Ts > + argv_input( Ts&&... )->argv_input<>; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/ascii.hpp b/include/tao/json/external/pegtl/ascii.hpp index ed7f194a..066c2ad5 100644 --- a/include/tao/json/external/pegtl/ascii.hpp +++ b/include/tao/json/external/pegtl/ascii.hpp @@ -1,66 +1,66 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ASCII_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_ASCII_HPP +#ifndef TAO_JSON_PEGTL_ASCII_HPP +#define TAO_JSON_PEGTL_ASCII_HPP #include "config.hpp" #include "eol.hpp" +#include "internal/always_false.hpp" #include "internal/result_on_found.hpp" #include "internal/rules.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + inline namespace ascii { - inline namespace ascii - { - // clang-format off - struct alnum : internal::alnum {}; - struct alpha : internal::alpha {}; - struct any : internal::any< internal::peek_char > {}; - struct blank : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, ' ', '\t' > {}; - struct digit : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, '0', '9' > {}; - struct eolf : internal::eolf {}; - struct identifier_first : internal::identifier_first {}; - struct identifier_other : internal::identifier_other {}; - struct identifier : internal::identifier {}; - template< char... Cs > struct istring : internal::istring< Cs... > {}; - template< char... Cs > struct keyword : internal::seq< internal::string< Cs... >, internal::not_at< internal::identifier_other > > {}; - struct lower : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, 'a', 'z' > {}; - template< char... Cs > struct not_one : internal::one< internal::result_on_found::FAILURE, internal::peek_char, Cs... > {}; - template< char Lo, char Hi > struct not_range : internal::range< internal::result_on_found::FAILURE, internal::peek_char, Lo, Hi > {}; - struct nul : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, char( 0 ) > {}; - template< char... Cs > struct one : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, Cs... > {}; - struct print : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, char( 32 ), char( 126 ) > {}; - template< char Lo, char Hi > struct range : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, Lo, Hi > {}; - template< char... Cs > struct ranges : internal::ranges< internal::peek_char, Cs... > {}; - struct seven : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, char( 0 ), char( 127 ) > {}; - struct shebang : internal::if_must< internal::string< '#', '!' >, internal::until< internal::eolf > > {}; - struct space : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, ' ', '\n', '\r', '\t', '\v', '\f' > {}; - template< char... Cs > struct string : internal::string< Cs... > {}; - template< char C > struct two : internal::string< C, C > {}; - struct upper : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, 'A', 'Z' > {}; - struct xdigit : internal::ranges< internal::peek_char, '0', '9', 'a', 'f', 'A', 'F' > {}; - // clang-format on + // clang-format off + struct alnum : internal::alnum {}; + struct alpha : internal::alpha {}; + struct any : internal::any< internal::peek_char > {}; + struct blank : internal::one< internal::result_on_found::success, internal::peek_char, ' ', '\t' > {}; + struct digit : internal::range< internal::result_on_found::success, internal::peek_char, '0', '9' > {}; + struct ellipsis : internal::string< '.', '.', '.' > {}; + struct eolf : internal::eolf {}; + template< char... Cs > struct forty_two : internal::rep< 42, internal::one< internal::result_on_found::success, internal::peek_char, Cs... > > {}; + struct identifier_first : internal::identifier_first {}; + struct identifier_other : internal::identifier_other {}; + struct identifier : internal::identifier {}; + template< char... Cs > struct istring : internal::istring< Cs... > {}; + template< char... Cs > struct keyword : internal::seq< internal::string< Cs... >, internal::not_at< internal::identifier_other > > {}; + struct lower : internal::range< internal::result_on_found::success, internal::peek_char, 'a', 'z' > {}; + template< char... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_char, Cs... > {}; + template< char Lo, char Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_char, Lo, Hi > {}; + struct nul : internal::one< internal::result_on_found::success, internal::peek_char, char( 0 ) > {}; + template< char... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_char, Cs... > {}; + struct print : internal::range< internal::result_on_found::success, internal::peek_char, char( 32 ), char( 126 ) > {}; + template< char Lo, char Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_char, Lo, Hi > {}; + template< char... Cs > struct ranges : internal::ranges< internal::peek_char, Cs... > {}; + struct seven : internal::range< internal::result_on_found::success, internal::peek_char, char( 0 ), char( 127 ) > {}; + struct shebang : internal::if_must< false, internal::string< '#', '!' >, internal::until< internal::eolf > > {}; + struct space : internal::one< internal::result_on_found::success, internal::peek_char, ' ', '\n', '\r', '\t', '\v', '\f' > {}; + template< char... Cs > struct string : internal::string< Cs... > {}; + template< char C > struct three : internal::string< C, C, C > {}; + template< char C > struct two : internal::string< C, C > {}; + struct upper : internal::range< internal::result_on_found::success, internal::peek_char, 'A', 'Z' > {}; + struct xdigit : internal::ranges< internal::peek_char, '0', '9', 'a', 'f', 'A', 'F' > {}; + // clang-format on - template<> - struct keyword<> + template<> + struct keyword<> + { + template< typename Input > + [[nodiscard]] static bool match( Input& /*unused*/ ) noexcept { - template< typename Input > - static bool match( Input& ) noexcept - { - static_assert( sizeof( Input ) == 0, "empty keywords not allowed" ); - return false; - } - }; - - } // namespace ascii + static_assert( internal::always_false< Input >::value, "empty keywords not allowed" ); + return false; + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + } // namespace ascii -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #include "internal/pegtl_string.hpp" diff --git a/include/tao/json/external/pegtl/buffer_input.hpp b/include/tao/json/external/pegtl/buffer_input.hpp index d92d22b0..2f6ef8c7 100644 --- a/include/tao/json/external/pegtl/buffer_input.hpp +++ b/include/tao/json/external/pegtl/buffer_input.hpp @@ -1,12 +1,16 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_BUFFER_INPUT_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_BUFFER_INPUT_HPP +#ifndef TAO_JSON_PEGTL_BUFFER_INPUT_HPP +#define TAO_JSON_PEGTL_BUFFER_INPUT_HPP +#include +#include #include +#include #include #include +#include #include #include "config.hpp" @@ -16,164 +20,193 @@ #include "tracking_mode.hpp" #include "internal/action_input.hpp" -#include "internal/bump_impl.hpp" +#include "internal/bump.hpp" #include "internal/iterator.hpp" #include "internal/marker.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Reader, typename Eol = eol::lf_crlf, typename Source = std::string, std::size_t Chunk = 64 > + class buffer_input { - template< typename Reader, typename Eol = eol::lf_crlf, typename Source = std::string > - class buffer_input - { - public: - static constexpr tracking_mode tracking_mode_v = tracking_mode::IMMEDIATE; - using reader_t = Reader; + public: + using reader_t = Reader; - using eol_t = Eol; - using source_t = Source; + using eol_t = Eol; + using source_t = Source; - using iterator_t = internal::iterator; + using iterator_t = internal::iterator; - using action_t = internal::action_input< buffer_input >; + using action_t = internal::action_input< buffer_input >; - template< typename T, typename... As > - buffer_input( T&& in_source, const std::size_t maximum, As&&... as ) - : m_reader( std::forward< As >( as )... ), - m_maximum( maximum ), - m_buffer( new char[ maximum ] ), - m_current( m_buffer.get() ), - m_end( m_buffer.get() ), - m_source( std::forward< T >( in_source ) ) - { - } + static constexpr std::size_t chunk_size = Chunk; + static constexpr tracking_mode tracking_mode_v = tracking_mode::eager; - buffer_input( const buffer_input& ) = delete; - void operator=( const buffer_input& ) = delete; + template< typename T, typename... As > + buffer_input( T&& in_source, const std::size_t maximum, As&&... as ) + : m_reader( std::forward< As >( as )... ), + m_maximum( maximum + Chunk ), + m_buffer( new char[ maximum + Chunk ] ), + m_current( m_buffer.get() ), + m_end( m_buffer.get() ), + m_source( std::forward< T >( in_source ) ) + { + static_assert( Chunk, "zero chunk size not implemented" ); + assert( m_maximum > maximum ); // Catches overflow; change to >= when zero chunk size is implemented. + } - bool empty() - { - require( 1 ); - return m_current.data == m_end; - } + buffer_input( const buffer_input& ) = delete; + buffer_input( buffer_input&& ) = delete; - std::size_t size( const std::size_t amount ) - { - require( amount ); - return std::size_t( m_end - m_current.data ); - } + ~buffer_input() = default; - const char* current() const noexcept - { - return m_current.data; - } + void operator=( const buffer_input& ) = delete; + void operator=( buffer_input&& ) = delete; - const char* end( const std::size_t amount ) - { - require( amount ); - return m_end; - } + [[nodiscard]] bool empty() + { + require( 1 ); + return m_current.data == m_end; + } - std::size_t byte() const noexcept - { - return m_current.byte; - } + [[nodiscard]] std::size_t size( const std::size_t amount ) + { + require( amount ); + return buffer_occupied(); + } - std::size_t line() const noexcept - { - return m_current.line; - } + [[nodiscard]] const char* current() const noexcept + { + return m_current.data; + } - std::size_t byte_in_line() const noexcept - { - return m_current.byte_in_line; - } + [[nodiscard]] const char* end( const std::size_t amount ) + { + require( amount ); + return m_end; + } - const Source& source() const noexcept - { - return m_source; - } + [[nodiscard]] std::size_t byte() const noexcept + { + return m_current.byte; + } - char peek_char( const std::size_t offset = 0 ) const noexcept - { - return m_current.data[ offset ]; - } + [[nodiscard]] std::size_t line() const noexcept + { + return m_current.line; + } - unsigned char peek_byte( const std::size_t offset = 0 ) const noexcept - { - return static_cast< unsigned char >( peek_char( offset ) ); - } + [[nodiscard]] std::size_t byte_in_line() const noexcept + { + return m_current.byte_in_line; + } - void bump( const std::size_t in_count = 1 ) noexcept - { - internal::bump( m_current, in_count, Eol::ch ); - } + [[nodiscard]] const Source& source() const noexcept + { + return m_source; + } - void bump_in_this_line( const std::size_t in_count = 1 ) noexcept - { - internal::bump_in_this_line( m_current, in_count ); - } + [[nodiscard]] char peek_char( const std::size_t offset = 0 ) const noexcept + { + return m_current.data[ offset ]; + } - void bump_to_next_line( const std::size_t in_count = 1 ) noexcept - { - internal::bump_to_next_line( m_current, in_count ); - } + [[nodiscard]] std::uint8_t peek_uint8( const std::size_t offset = 0 ) const noexcept + { + return static_cast< std::uint8_t >( peek_char( offset ) ); + } + + void bump( const std::size_t in_count = 1 ) noexcept + { + internal::bump( m_current, in_count, Eol::ch ); + } + + void bump_in_this_line( const std::size_t in_count = 1 ) noexcept + { + internal::bump_in_this_line( m_current, in_count ); + } + + void bump_to_next_line( const std::size_t in_count = 1 ) noexcept + { + internal::bump_to_next_line( m_current, in_count ); + } - void discard() noexcept - { + void discard() noexcept + { + if( m_current.data > m_buffer.get() + Chunk ) { const auto s = m_end - m_current.data; std::memmove( m_buffer.get(), m_current.data, s ); m_current.data = m_buffer.get(); m_end = m_buffer.get() + s; } + } - void require( const std::size_t amount ) - { - if( m_current.data + amount > m_end ) { - if( m_current.data + amount <= m_buffer.get() + m_maximum ) { - if( const auto r = m_reader( const_cast< char* >( m_end ), amount - std::size_t( m_end - m_current.data ) ) ) { - m_end += r; - } - else { - m_maximum = 0; - } - } - } + void require( const std::size_t amount ) + { + if( m_current.data + amount <= m_end ) { + return; } - - template< rewind_mode M > - internal::marker< iterator_t, M > mark() noexcept - { - return internal::marker< iterator_t, M >( m_current ); + if( m_current.data + amount > m_buffer.get() + m_maximum ) { + throw std::overflow_error( "require beyond end of buffer" ); } - - TAOCPP_JSON_PEGTL_NAMESPACE::position position( const iterator_t& it ) const - { - return TAOCPP_JSON_PEGTL_NAMESPACE::position( it, m_source ); + if( const auto r = m_reader( m_end, ( std::min )( buffer_free_after_end(), ( std::max )( amount, Chunk ) ) ) ) { + m_end += r; } + } - TAOCPP_JSON_PEGTL_NAMESPACE::position position() const - { - return position( m_current ); - } + template< rewind_mode M > + [[nodiscard]] internal::marker< iterator_t, M > mark() noexcept + { + return internal::marker< iterator_t, M >( m_current ); + } - const iterator_t& iterator() const noexcept - { - return m_current; - } + [[nodiscard]] TAO_JSON_PEGTL_NAMESPACE::position position( const iterator_t& it ) const + { + return TAO_JSON_PEGTL_NAMESPACE::position( it, m_source ); + } + + [[nodiscard]] TAO_JSON_PEGTL_NAMESPACE::position position() const + { + return position( m_current ); + } + + [[nodiscard]] const iterator_t& iterator() const noexcept + { + return m_current; + } + + [[nodiscard]] std::size_t buffer_capacity() const noexcept + { + return m_maximum; + } - private: - Reader m_reader; - std::size_t m_maximum; - std::unique_ptr< char[] > m_buffer; - iterator_t m_current; - const char* m_end; - const Source m_source; - }; + [[nodiscard]] std::size_t buffer_occupied() const noexcept + { + assert( m_end >= m_current.data ); + return std::size_t( m_end - m_current.data ); + } - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + [[nodiscard]] std::size_t buffer_free_before_current() const noexcept + { + assert( m_current.data >= m_buffer.get() ); + return std::size_t( m_current.data - m_buffer.get() ); + } -} // namespace tao + [[nodiscard]] std::size_t buffer_free_after_end() const noexcept + { + assert( m_buffer.get() + m_maximum >= m_end ); + return std::size_t( m_buffer.get() + m_maximum - m_end ); + } + + private: + Reader m_reader; + std::size_t m_maximum; + std::unique_ptr< char[] > m_buffer; + iterator_t m_current; + char* m_end; + const Source m_source; + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/change_action.hpp b/include/tao/json/external/pegtl/change_action.hpp new file mode 100644 index 00000000..0738c4b4 --- /dev/null +++ b/include/tao/json/external/pegtl/change_action.hpp @@ -0,0 +1,38 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_CHANGE_ACTION_HPP +#define TAO_JSON_PEGTL_CHANGE_ACTION_HPP + +#include + +#include "apply_mode.hpp" +#include "config.hpp" +#include "nothing.hpp" +#include "rewind_mode.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + template< template< typename... > class NewAction > + struct change_action + : maybe_nothing + { + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + static_assert( !std::is_same_v< Action< void >, NewAction< void > >, "old and new action class templates are identical" ); + return Control< Rule >::template match< A, M, NewAction, Control >( in, st... ); + } + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/change_action_and_state.hpp b/include/tao/json/external/pegtl/change_action_and_state.hpp new file mode 100644 index 00000000..edcd03a3 --- /dev/null +++ b/include/tao/json/external/pegtl/change_action_and_state.hpp @@ -0,0 +1,53 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_CHANGE_ACTION_AND_STATE_HPP +#define TAO_JSON_PEGTL_CHANGE_ACTION_AND_STATE_HPP + +#include + +#include "apply_mode.hpp" +#include "config.hpp" +#include "match.hpp" +#include "nothing.hpp" +#include "rewind_mode.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + template< template< typename... > class NewAction, typename NewState > + struct change_action_and_state + : maybe_nothing + { + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + static_assert( !std::is_same_v< Action< void >, NewAction< void > >, "old and new action class templates are identical" ); + NewState s( static_cast< const Input& >( in ), st... ); + if( Control< Rule >::template match< A, M, NewAction, Control >( in, s ) ) { + if constexpr( A == apply_mode::action ) { + Action< Rule >::success( static_cast< const Input& >( in ), s, st... ); + } + return true; + } + return false; + } + + template< typename Input, + typename... States > + static void success( const Input& in, NewState& s, States&&... st ) noexcept( noexcept( s.success( in, st... ) ) ) + { + s.success( in, st... ); + } + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/change_action_and_states.hpp b/include/tao/json/external/pegtl/change_action_and_states.hpp new file mode 100644 index 00000000..e7d5bee2 --- /dev/null +++ b/include/tao/json/external/pegtl/change_action_and_states.hpp @@ -0,0 +1,62 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_CHANGE_ACTION_AND_STATES_HPP +#define TAO_JSON_PEGTL_CHANGE_ACTION_AND_STATES_HPP + +#include +#include + +#include "apply_mode.hpp" +#include "config.hpp" +#include "match.hpp" +#include "nothing.hpp" +#include "rewind_mode.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + template< template< typename... > class NewAction, typename... NewStates > + struct change_action_and_states + : maybe_nothing + { + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + std::size_t... Ns, + typename Input, + typename... States > + [[nodiscard]] static bool match( std::index_sequence< Ns... > /*unused*/, Input& in, States&&... st ) + { + auto t = std::tie( st... ); + if( Control< Rule >::template match< A, M, NewAction, Control >( in, std::get< Ns >( t )... ) ) { + if constexpr( A == apply_mode::action ) { + Action< Rule >::success( static_cast< const Input& >( in ), st... ); + } + return true; + } + return false; + } + + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + static_assert( !std::is_same_v< Action< void >, NewAction< void > >, "old and new action class templates are identical" ); + return match< Rule, A, M, Action, Control >( std::index_sequence_for< NewStates... >(), in, NewStates()..., st... ); + } + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/change_control.hpp b/include/tao/json/external/pegtl/change_control.hpp new file mode 100644 index 00000000..eee03415 --- /dev/null +++ b/include/tao/json/external/pegtl/change_control.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_CHANGE_CONTROL_HPP +#define TAO_JSON_PEGTL_CHANGE_CONTROL_HPP + +#include "apply_mode.hpp" +#include "config.hpp" +#include "match.hpp" +#include "nothing.hpp" +#include "rewind_mode.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + template< template< typename... > class NewControl > + struct change_control + : maybe_nothing + { + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + return TAO_JSON_PEGTL_NAMESPACE::match< Rule, A, M, Action, NewControl >( in, st... ); + } + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/change_state.hpp b/include/tao/json/external/pegtl/change_state.hpp new file mode 100644 index 00000000..9f3f9e52 --- /dev/null +++ b/include/tao/json/external/pegtl/change_state.hpp @@ -0,0 +1,50 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_CHANGE_STATE_HPP +#define TAO_JSON_PEGTL_CHANGE_STATE_HPP + +#include "apply_mode.hpp" +#include "config.hpp" +#include "match.hpp" +#include "nothing.hpp" +#include "rewind_mode.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + template< typename NewState > + struct change_state + : maybe_nothing + { + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + NewState s( static_cast< const Input& >( in ), st... ); + if( TAO_JSON_PEGTL_NAMESPACE::match< Rule, A, M, Action, Control >( in, s ) ) { + if constexpr( A == apply_mode::action ) { + Action< Rule >::success( static_cast< const Input& >( in ), s, st... ); + } + return true; + } + return false; + } + + template< typename Input, + typename... States > + static void success( const Input& in, NewState& s, States&&... st ) noexcept( noexcept( s.success( in, st... ) ) ) + { + s.success( in, st... ); + } + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/change_states.hpp b/include/tao/json/external/pegtl/change_states.hpp new file mode 100644 index 00000000..ce246977 --- /dev/null +++ b/include/tao/json/external/pegtl/change_states.hpp @@ -0,0 +1,61 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_CHANGE_STATES_HPP +#define TAO_JSON_PEGTL_CHANGE_STATES_HPP + +#include +#include + +#include "apply_mode.hpp" +#include "config.hpp" +#include "match.hpp" +#include "nothing.hpp" +#include "rewind_mode.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + template< typename... NewStates > + struct change_states + : maybe_nothing + { + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + std::size_t... Ns, + typename Input, + typename... States > + [[nodiscard]] static bool match( std::index_sequence< Ns... > /*unused*/, Input& in, States&&... st ) + { + auto t = std::tie( st... ); + if( TAO_JSON_PEGTL_NAMESPACE::match< Rule, A, M, Action, Control >( in, std::get< Ns >( t )... ) ) { + if constexpr( A == apply_mode::action ) { + Action< Rule >::success( static_cast< const Input& >( in ), st... ); + } + return true; + } + return false; + } + + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + return match< Rule, A, M, Action, Control >( std::index_sequence_for< NewStates... >(), in, NewStates()..., st... ); + } + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/config.hpp b/include/tao/json/external/pegtl/config.hpp index f2f0e4d4..91cd8e10 100644 --- a/include/tao/json/external/pegtl/config.hpp +++ b/include/tao/json/external/pegtl/config.hpp @@ -1,15 +1,11 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONFIG_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_CONFIG_HPP +#ifndef TAO_JSON_PEGTL_CONFIG_HPP +#define TAO_JSON_PEGTL_CONFIG_HPP -#ifndef TAOCPP_JSON_PEGTL_NAMESPACE -#define TAOCPP_JSON_PEGTL_NAMESPACE json_pegtl +#if !defined( TAO_JSON_PEGTL_NAMESPACE ) +#define TAO_JSON_PEGTL_NAMESPACE tao::json::pegtl #endif -// Enable some improvements to the readability of -// demangled type names under some circumstances. -// #define TAOCPP_JSON_PEGTL_PRETTY_DEMANGLE - #endif diff --git a/include/tao/json/external/pegtl/contrib/abnf.hpp b/include/tao/json/external/pegtl/contrib/abnf.hpp index 5c1d36e9..67e7bbe9 100644 --- a/include/tao/json/external/pegtl/contrib/abnf.hpp +++ b/include/tao/json/external/pegtl/contrib/abnf.hpp @@ -1,43 +1,35 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_ABNF_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_ABNF_HPP +#ifndef TAO_JSON_PEGTL_CONTRIB_ABNF_HPP +#define TAO_JSON_PEGTL_CONTRIB_ABNF_HPP #include "../config.hpp" #include "../internal/rules.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::abnf { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace abnf - { - // Core ABNF rules according to RFC 5234, Appendix B - - // clang-format off - struct ALPHA : internal::ranges< internal::peek_char, 'a', 'z', 'A', 'Z' > {}; - struct BIT : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, '0', '1' > {}; - struct CHAR : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, char( 1 ), char( 127 ) > {}; - struct CR : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, '\r' > {}; - struct CRLF : internal::string< '\r', '\n' > {}; - struct CTL : internal::ranges< internal::peek_char, char( 0 ), char( 31 ), char( 127 ) > {}; - struct DIGIT : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, '0', '9' > {}; - struct DQUOTE : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, '"' > {}; - struct HEXDIG : internal::ranges< internal::peek_char, '0', '9', 'a', 'f', 'A', 'F' > {}; - struct HTAB : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, '\t' > {}; - struct LF : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, '\n' > {}; - struct LWSP : internal::star< internal::sor< internal::string< '\r', '\n' >, internal::one< internal::result_on_found::SUCCESS, internal::peek_char, ' ', '\t' > >, internal::one< internal::result_on_found::SUCCESS, internal::peek_char, ' ', '\t' > > {}; - struct OCTET : internal::any< internal::peek_char > {}; - struct SP : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, ' ' > {}; - struct VCHAR : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, char( 33 ), char( 126 ) > {}; - struct WSP : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, ' ', '\t' > {}; - // clang-format on - - } // namespace abnf - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + // Core ABNF rules according to RFC 5234, Appendix B + + // clang-format off + struct ALPHA : internal::ranges< internal::peek_char, 'a', 'z', 'A', 'Z' > {}; + struct BIT : internal::one< internal::result_on_found::success, internal::peek_char, '0', '1' > {}; + struct CHAR : internal::range< internal::result_on_found::success, internal::peek_char, char( 1 ), char( 127 ) > {}; + struct CR : internal::one< internal::result_on_found::success, internal::peek_char, '\r' > {}; + struct CRLF : internal::string< '\r', '\n' > {}; + struct CTL : internal::ranges< internal::peek_char, char( 0 ), char( 31 ), char( 127 ) > {}; + struct DIGIT : internal::range< internal::result_on_found::success, internal::peek_char, '0', '9' > {}; + struct DQUOTE : internal::one< internal::result_on_found::success, internal::peek_char, '"' > {}; + struct HEXDIG : internal::ranges< internal::peek_char, '0', '9', 'a', 'f', 'A', 'F' > {}; + struct HTAB : internal::one< internal::result_on_found::success, internal::peek_char, '\t' > {}; + struct LF : internal::one< internal::result_on_found::success, internal::peek_char, '\n' > {}; + struct LWSP : internal::star< internal::sor< internal::string< '\r', '\n' >, internal::one< internal::result_on_found::success, internal::peek_char, ' ', '\t' > >, internal::one< internal::result_on_found::success, internal::peek_char, ' ', '\t' > > {}; + struct OCTET : internal::any< internal::peek_char > {}; + struct SP : internal::one< internal::result_on_found::success, internal::peek_char, ' ' > {}; + struct VCHAR : internal::range< internal::result_on_found::success, internal::peek_char, char( 33 ), char( 126 ) > {}; + struct WSP : internal::one< internal::result_on_found::success, internal::peek_char, ' ', '\t' > {}; + // clang-format on + +} // namespace TAO_JSON_PEGTL_NAMESPACE::abnf #endif diff --git a/include/tao/json/external/pegtl/contrib/alphabet.hpp b/include/tao/json/external/pegtl/contrib/alphabet.hpp index 738db535..8a10eed0 100644 --- a/include/tao/json/external/pegtl/contrib/alphabet.hpp +++ b/include/tao/json/external/pegtl/contrib/alphabet.hpp @@ -1,75 +1,67 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_ALPHABET_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_ALPHABET_HPP +#ifndef TAO_JSON_PEGTL_CONTRIB_ALPHABET_HPP +#define TAO_JSON_PEGTL_CONTRIB_ALPHABET_HPP #include "../config.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::alphabet { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - inline namespace alphabet - { - static const int a = 'a'; - static const int b = 'b'; - static const int c = 'c'; - static const int d = 'd'; - static const int e = 'e'; - static const int f = 'f'; - static const int g = 'g'; - static const int h = 'h'; - static const int i = 'i'; - static const int j = 'j'; - static const int k = 'k'; - static const int l = 'l'; - static const int m = 'm'; - static const int n = 'n'; - static const int o = 'o'; - static const int p = 'p'; - static const int q = 'q'; - static const int r = 'r'; - static const int s = 's'; - static const int t = 't'; - static const int u = 'u'; - static const int v = 'v'; - static const int w = 'w'; - static const int x = 'x'; - static const int y = 'y'; - static const int z = 'z'; + static const int a = 'a'; + static const int b = 'b'; + static const int c = 'c'; + static const int d = 'd'; + static const int e = 'e'; + static const int f = 'f'; + static const int g = 'g'; + static const int h = 'h'; + static const int i = 'i'; + static const int j = 'j'; + static const int k = 'k'; + static const int l = 'l'; + static const int m = 'm'; + static const int n = 'n'; + static const int o = 'o'; + static const int p = 'p'; + static const int q = 'q'; + static const int r = 'r'; + static const int s = 's'; + static const int t = 't'; + static const int u = 'u'; + static const int v = 'v'; + static const int w = 'w'; + static const int x = 'x'; + static const int y = 'y'; + static const int z = 'z'; - static const int A = 'A'; - static const int B = 'B'; - static const int C = 'C'; - static const int D = 'D'; - static const int E = 'E'; - static const int F = 'F'; - static const int G = 'G'; - static const int H = 'H'; - static const int I = 'I'; - static const int J = 'J'; - static const int K = 'K'; - static const int L = 'L'; - static const int M = 'M'; - static const int N = 'N'; - static const int O = 'O'; - static const int P = 'P'; - static const int Q = 'Q'; - static const int R = 'R'; - static const int S = 'S'; - static const int T = 'T'; - static const int U = 'U'; - static const int V = 'V'; - static const int W = 'W'; - static const int X = 'X'; - static const int Y = 'Y'; - static const int Z = 'Z'; + static const int A = 'A'; // NOLINT(readability-identifier-naming) + static const int B = 'B'; // NOLINT(readability-identifier-naming) + static const int C = 'C'; // NOLINT(readability-identifier-naming) + static const int D = 'D'; // NOLINT(readability-identifier-naming) + static const int E = 'E'; // NOLINT(readability-identifier-naming) + static const int F = 'F'; // NOLINT(readability-identifier-naming) + static const int G = 'G'; // NOLINT(readability-identifier-naming) + static const int H = 'H'; // NOLINT(readability-identifier-naming) + static const int I = 'I'; // NOLINT(readability-identifier-naming) + static const int J = 'J'; // NOLINT(readability-identifier-naming) + static const int K = 'K'; // NOLINT(readability-identifier-naming) + static const int L = 'L'; // NOLINT(readability-identifier-naming) + static const int M = 'M'; // NOLINT(readability-identifier-naming) + static const int N = 'N'; // NOLINT(readability-identifier-naming) + static const int O = 'O'; // NOLINT(readability-identifier-naming) + static const int P = 'P'; // NOLINT(readability-identifier-naming) + static const int Q = 'Q'; // NOLINT(readability-identifier-naming) + static const int R = 'R'; // NOLINT(readability-identifier-naming) + static const int S = 'S'; // NOLINT(readability-identifier-naming) + static const int T = 'T'; // NOLINT(readability-identifier-naming) + static const int U = 'U'; // NOLINT(readability-identifier-naming) + static const int V = 'V'; // NOLINT(readability-identifier-naming) + static const int W = 'W'; // NOLINT(readability-identifier-naming) + static const int X = 'X'; // NOLINT(readability-identifier-naming) + static const int Y = 'Y'; // NOLINT(readability-identifier-naming) + static const int Z = 'Z'; // NOLINT(readability-identifier-naming) - } // namespace alphabet - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::alphabet #endif diff --git a/include/tao/json/external/pegtl/contrib/changes.hpp b/include/tao/json/external/pegtl/contrib/changes.hpp deleted file mode 100644 index 24649139..00000000 --- a/include/tao/json/external/pegtl/contrib/changes.hpp +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_CHANGES_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_CHANGES_HPP - -#include - -#include "../config.hpp" -#include "../normal.hpp" - -namespace tao -{ - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - struct dummy_disabled_state - { - template< typename... Ts > - void success( Ts&&... ) const noexcept - { - } - }; - - template< apply_mode A, typename State > - using state_disable_helper = typename std::conditional< A == apply_mode::ACTION, State, dummy_disabled_state >::type; - - } // namespace internal - - template< typename Rule, typename State, template< typename... > class Base = normal > - struct change_state - : public Base< Rule > - { - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - internal::state_disable_helper< A, State > s; - - if( Base< Rule >::template match< A, M, Action, Control >( in, s ) ) { - s.success( st... ); - return true; - } - return false; - } - }; - - template< typename Rule, template< typename... > class Action, template< typename... > class Base = normal > - struct change_action - : public Base< Rule > - { - template< apply_mode A, - rewind_mode M, - template< typename... > class, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - return Base< Rule >::template match< A, M, Action, Control >( in, st... ); - } - }; - - template< template< typename... > class Action, template< typename... > class Base > - struct change_both_helper - { - template< typename T > - using change_action = change_action< T, Action, Base >; - }; - - template< typename Rule, typename State, template< typename... > class Action, template< typename... > class Base = normal > - struct change_state_and_action - : public change_state< Rule, State, change_both_helper< Action, Base >::template change_action > - { - }; - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao - -#endif diff --git a/include/tao/json/external/pegtl/contrib/counter.hpp b/include/tao/json/external/pegtl/contrib/counter.hpp index 6aab2746..98b80656 100644 --- a/include/tao/json/external/pegtl/contrib/counter.hpp +++ b/include/tao/json/external/pegtl/contrib/counter.hpp @@ -1,58 +1,54 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_COUNTER_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_COUNTER_HPP +#ifndef TAO_JSON_PEGTL_CONTRIB_COUNTER_HPP +#define TAO_JSON_PEGTL_CONTRIB_COUNTER_HPP -#include -#include +#include +#include #include "../config.hpp" #include "../normal.hpp" #include "../internal/demangle.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct counter_data { - struct counter_data + unsigned start = 0; + unsigned success = 0; + unsigned failure = 0; + }; + + struct counter_state + { + std::map< std::string_view, counter_data > counts; + }; + + template< typename Rule > + struct counter + : normal< Rule > + { + template< typename Input > + static void start( const Input& /*unused*/, counter_state& ts ) { - unsigned start = 0; - unsigned success = 0; - unsigned failure = 0; - }; + ++ts.counts[ internal::demangle< Rule >() ].start; + } - struct counter_state + template< typename Input > + static void success( const Input& /*unused*/, counter_state& ts ) { - std::map< std::string, counter_data > counts; - }; + ++ts.counts[ internal::demangle< Rule >() ].success; + } - template< typename Rule > - struct counter - : normal< Rule > + template< typename Input > + static void failure( const Input& /*unused*/, counter_state& ts ) { - template< typename Input > - static void start( const Input&, counter_state& ts ) - { - ++ts.counts[ internal::demangle< Rule >() ].start; - } - - template< typename Input > - static void success( const Input&, counter_state& ts ) - { - ++ts.counts[ internal::demangle< Rule >() ].success; - } - - template< typename Input > - static void failure( const Input&, counter_state& ts ) - { - ++ts.counts[ internal::demangle< Rule >() ].failure; - } - }; - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + ++ts.counts[ internal::demangle< Rule >() ].failure; + } + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/contrib/http.hpp b/include/tao/json/external/pegtl/contrib/http.hpp index 63268b97..f9a24e9f 100644 --- a/include/tao/json/external/pegtl/contrib/http.hpp +++ b/include/tao/json/external/pegtl/contrib/http.hpp @@ -1,152 +1,253 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_HTTP_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_HTTP_HPP +#ifndef TAO_JSON_PEGTL_CONTRIB_HTTP_HPP +#define TAO_JSON_PEGTL_CONTRIB_HTTP_HPP #include "../ascii.hpp" #include "../config.hpp" +#include "../nothing.hpp" #include "../rules.hpp" #include "../utf8.hpp" + #include "abnf.hpp" +#include "remove_first_state.hpp" #include "uri.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::http { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace http - { - // HTTP 1.1 grammar according to RFC 7230. - - // This grammar is a direct PEG translation of the original HTTP grammar. - // It should be considered experimental -- in case of any issues, in particular - // missing rules for attached actions, please contact the developers. + // HTTP 1.1 grammar according to RFC 7230. - using namespace abnf; + // This grammar is a direct PEG translation of the original HTTP grammar. + // It should be considered experimental -- in case of any issues, in particular + // missing rules for attached actions, please contact the developers. - using OWS = star< WSP >; // optional whitespace - using RWS = plus< WSP >; // required whitespace - using BWS = OWS; // "bad" whitespace + using OWS = star< abnf::WSP >; // optional whitespace + using RWS = plus< abnf::WSP >; // required whitespace + using BWS = OWS; // "bad" whitespace - // cppcheck-suppress constStatement - using obs_text = not_range< 0x00, 0x7F >; - using obs_fold = seq< CRLF, plus< WSP > >; + using obs_text = not_range< 0x00, 0x7F >; + using obs_fold = seq< abnf::CRLF, plus< abnf::WSP > >; - // clang-format off - struct tchar : sor< ALPHA, DIGIT, one< '!', '#', '$', '%', '&', '\'', '*', '+', '-', '.', '^', '_', '`', '|', '~' > > {}; - struct token : plus< tchar > {}; + // clang-format off + struct tchar : sor< abnf::ALPHA, abnf::DIGIT, one< '!', '#', '$', '%', '&', '\'', '*', '+', '-', '.', '^', '_', '`', '|', '~' > > {}; + struct token : plus< tchar > {}; - struct field_name : token {}; + struct field_name : token {}; - struct field_vchar : sor< VCHAR, obs_text > {}; - struct field_content : list< field_vchar, plus< WSP > > {}; - struct field_value : star< sor< field_content, obs_fold > > {}; + struct field_vchar : sor< abnf::VCHAR, obs_text > {}; + struct field_content : list< field_vchar, plus< abnf::WSP > > {}; + struct field_value : star< sor< field_content, obs_fold > > {}; - struct header_field : seq< field_name, one< ':' >, OWS, field_value, OWS > {}; + struct header_field : seq< field_name, one< ':' >, OWS, field_value, OWS > {}; - struct method : token {}; + struct method : token {}; - struct absolute_path : plus< one< '/' >, uri::segment > {}; + struct absolute_path : plus< one< '/' >, uri::segment > {}; - struct origin_form : seq< absolute_path, uri::opt_query > {}; - struct absolute_form : uri::absolute_URI {}; - struct authority_form : uri::authority {}; - struct asterisk_form : one< '*' > {}; + struct origin_form : seq< absolute_path, uri::opt_query > {}; + struct absolute_form : uri::absolute_URI {}; + struct authority_form : uri::authority {}; + struct asterisk_form : one< '*' > {}; - struct request_target : sor< origin_form, absolute_form, authority_form, asterisk_form > {}; + struct request_target : sor< origin_form, absolute_form, authority_form, asterisk_form > {}; - struct status_code : rep< 3, DIGIT > {}; - struct reason_phrase : star< sor< VCHAR, obs_text, WSP > > {}; + struct status_code : rep< 3, abnf::DIGIT > {}; + struct reason_phrase : star< sor< abnf::VCHAR, obs_text, abnf::WSP > > {}; - struct HTTP_version : if_must< TAOCPP_JSON_PEGTL_STRING( "HTTP/" ), DIGIT, one< '.' >, DIGIT > {}; + struct HTTP_version : if_must< string< 'H', 'T', 'T', 'P', '/' >, abnf::DIGIT, one< '.' >, abnf::DIGIT > {}; - struct request_line : if_must< method, SP, request_target, SP, HTTP_version, CRLF > {}; - struct status_line : if_must< HTTP_version, SP, status_code, SP, reason_phrase, CRLF > {}; - struct start_line : sor< status_line, request_line > {}; + struct request_line : if_must< method, abnf::SP, request_target, abnf::SP, HTTP_version, abnf::CRLF > {}; + struct status_line : if_must< HTTP_version, abnf::SP, status_code, abnf::SP, reason_phrase, abnf::CRLF > {}; + struct start_line : sor< status_line, request_line > {}; - struct message_body : star< OCTET > {}; - struct HTTP_message : seq< start_line, star< header_field, CRLF >, CRLF, opt< message_body > > {}; + struct message_body : star< abnf::OCTET > {}; + struct HTTP_message : seq< start_line, star< header_field, abnf::CRLF >, abnf::CRLF, opt< message_body > > {}; - struct Content_Length : plus< DIGIT > {}; + struct Content_Length : plus< abnf::DIGIT > {}; - struct uri_host : uri::host {}; - struct port : uri::port {}; + struct uri_host : uri::host {}; + struct port : uri::port {}; - struct Host : seq< uri_host, opt< one< ':' >, port > > {}; + struct Host : seq< uri_host, opt< one< ':' >, port > > {}; - // PEG are different from CFGs! (this replaces ctext and qdtext) - using text = sor< HTAB, range< 0x20, 0x7E >, obs_text >; + // PEG are different from CFGs! (this replaces ctext and qdtext) + using text = sor< abnf::HTAB, range< 0x20, 0x7E >, obs_text >; - struct quoted_pair : if_must< one< '\\' >, sor< VCHAR, obs_text, WSP > > {}; - struct quoted_string : if_must< DQUOTE, until< DQUOTE, sor< quoted_pair, text > > > {}; + struct quoted_pair : if_must< one< '\\' >, sor< abnf::VCHAR, obs_text, abnf::WSP > > {}; + struct quoted_string : if_must< abnf::DQUOTE, until< abnf::DQUOTE, sor< quoted_pair, text > > > {}; - struct transfer_parameter : seq< token, BWS, one< '=' >, BWS, sor< token, quoted_string > > {}; - struct transfer_extension : seq< token, star< OWS, one< ';' >, OWS, transfer_parameter > > {}; - struct transfer_coding : sor< TAOCPP_JSON_PEGTL_ISTRING( "chunked" ), - TAOCPP_JSON_PEGTL_ISTRING( "compress" ), - TAOCPP_JSON_PEGTL_ISTRING( "deflate" ), - TAOCPP_JSON_PEGTL_ISTRING( "gzip" ), - transfer_extension > {}; + struct transfer_parameter : seq< token, BWS, one< '=' >, BWS, sor< token, quoted_string > > {}; + struct transfer_extension : seq< token, star< OWS, one< ';' >, OWS, transfer_parameter > > {}; + struct transfer_coding : sor< istring< 'c', 'h', 'u', 'n', 'k', 'e', 'd' >, + istring< 'c', 'o', 'm', 'p', 'r', 'e', 's', 's' >, + istring< 'd', 'e', 'f', 'l', 'a', 't', 'e' >, + istring< 'g', 'z', 'i', 'p' >, + transfer_extension > {}; - struct rank : sor< seq< one< '0' >, opt< one< '.' >, rep_opt< 3, DIGIT > > >, - seq< one< '1' >, opt< one< '.' >, rep_opt< 3, one< '0' > > > > > {}; + struct rank : sor< seq< one< '0' >, opt< one< '.' >, rep_opt< 3, abnf::DIGIT > > >, + seq< one< '1' >, opt< one< '.' >, rep_opt< 3, one< '0' > > > > > {}; - struct t_ranking : seq< OWS, one< ';' >, OWS, one< 'q', 'Q' >, one< '=' >, rank > {}; - struct t_codings : sor< TAOCPP_JSON_PEGTL_ISTRING( "trailers" ), seq< transfer_coding, opt< t_ranking > > > {}; + struct t_ranking : seq< OWS, one< ';' >, OWS, one< 'q', 'Q' >, one< '=' >, rank > {}; + struct t_codings : sor< istring< 't', 'r', 'a', 'i', 'l', 'e', 'r', 's' >, seq< transfer_coding, opt< t_ranking > > > {}; - struct TE : opt< sor< one< ',' >, t_codings >, star< OWS, one< ',' >, opt< OWS, t_codings > > > {}; + struct TE : opt< sor< one< ',' >, t_codings >, star< OWS, one< ',' >, opt< OWS, t_codings > > > {}; - template< typename T > - using make_comma_list = seq< star< one< ',' >, OWS >, T, star< OWS, one< ',' >, opt< OWS, T > > >; + template< typename T > + using make_comma_list = seq< star< one< ',' >, OWS >, T, star< OWS, one< ',' >, opt< OWS, T > > >; - struct connection_option : token {}; - struct Connection : make_comma_list< connection_option > {}; + struct connection_option : token {}; + struct Connection : make_comma_list< connection_option > {}; - struct Trailer : make_comma_list< field_name > {}; + struct Trailer : make_comma_list< field_name > {}; - struct Transfer_Encoding : make_comma_list< transfer_coding > {}; + struct Transfer_Encoding : make_comma_list< transfer_coding > {}; - struct protocol_name : token {}; - struct protocol_version : token {}; - struct protocol : seq< protocol_name, opt< one< '/' >, protocol_version > > {}; - struct Upgrade : make_comma_list< protocol > {}; + struct protocol_name : token {}; + struct protocol_version : token {}; + struct protocol : seq< protocol_name, opt< one< '/' >, protocol_version > > {}; + struct Upgrade : make_comma_list< protocol > {}; - struct pseudonym : token {}; + struct pseudonym : token {}; - struct received_protocol : seq< opt< protocol_name, one< '/' > >, protocol_version > {}; - struct received_by : sor< seq< uri_host, opt< one< ':' >, port > >, pseudonym > {}; + struct received_protocol : seq< opt< protocol_name, one< '/' > >, protocol_version > {}; + struct received_by : sor< seq< uri_host, opt< one< ':' >, port > >, pseudonym > {}; - struct comment : if_must< one< '(' >, until< one< ')' >, sor< comment, quoted_pair, text > > > {}; + struct comment : if_must< one< '(' >, until< one< ')' >, sor< comment, quoted_pair, text > > > {}; - struct Via : make_comma_list< seq< received_protocol, RWS, received_by, opt< RWS, comment > > > {}; + struct Via : make_comma_list< seq< received_protocol, RWS, received_by, opt< RWS, comment > > > {}; - struct http_URI : if_must< TAOCPP_JSON_PEGTL_ISTRING( "http://" ), uri::authority, uri::path_abempty, uri::opt_query, uri::opt_fragment > {}; - struct https_URI : if_must< TAOCPP_JSON_PEGTL_ISTRING( "https://" ), uri::authority, uri::path_abempty, uri::opt_query, uri::opt_fragment > {}; + struct http_URI : if_must< istring< 'h', 't', 't', 'p', ':', '/', '/' >, uri::authority, uri::path_abempty, uri::opt_query, uri::opt_fragment > {}; + struct https_URI : if_must< istring< 'h', 't', 't', 'p', 's', ':', '/', '/' >, uri::authority, uri::path_abempty, uri::opt_query, uri::opt_fragment > {}; - struct partial_URI : seq< uri::relative_part, uri::opt_query > {}; + struct partial_URI : seq< uri::relative_part, uri::opt_query > {}; - struct chunk_size : plus< HEXDIG > {}; - - struct chunk_ext_name : token {}; - struct chunk_ext_val : sor< quoted_string, token > {}; - struct chunk_ext : star< if_must< one< ';' >, chunk_ext_name, if_must< one< '=' >, chunk_ext_val > > > {}; - - struct chunk_data : until< at< CRLF >, OCTET > {}; - - struct chunk : seq< chunk_size, opt< chunk_ext >, CRLF, chunk_data, CRLF > {}; + // clang-format on + struct chunk_size + { + using analyze_t = plus< abnf::HEXDIG >::analyze_t; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, std::size_t& size, States&&... /*unused*/ ) + { + size = 0; + std::size_t i = 0; + while( in.size( i + 1 ) >= i + 1 ) { + const auto c = in.peek_char( i ); + if( ( '0' <= c ) && ( c <= '9' ) ) { + size <<= 4; + size |= std::size_t( c - '0' ); + ++i; + continue; + } + if( ( 'a' <= c ) && ( c <= 'f' ) ) { + size <<= 4; + size |= std::size_t( c - 'a' + 10 ); + ++i; + continue; + } + if( ( 'A' <= c ) && ( c <= 'F' ) ) { + size <<= 4; + size |= std::size_t( c - 'A' + 10 ); + ++i; + continue; + } + break; + } + in.bump_in_this_line( i ); + return i > 0; + } + }; + // clang-format off + + struct chunk_ext_name : token {}; + struct chunk_ext_val : sor< quoted_string, token > {}; + struct chunk_ext : star_must< one< ';' >, chunk_ext_name, if_must< one< '=' >, chunk_ext_val > > {}; + + // clang-format on + struct chunk_data + { + using analyze_t = star< abnf::OCTET >::analyze_t; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, const std::size_t size, States&&... /*unused*/ ) + { + if( in.size( size ) >= size ) { + in.bump( size ); + return true; + } + return false; + } + }; + + namespace internal::chunk_helper + { + template< typename Rule, template< typename... > class Control > + struct control + : remove_self_and_first_state< Rule, Control > + {}; + + template< template< typename... > class Control > + struct control< chunk_size, Control > + : remove_first_state_after_match< chunk_size, Control > + {}; + + template< template< typename... > class Control > + struct control< chunk_data, Control > + : remove_first_state_after_match< chunk_data, Control > + {}; + + template< template< typename... > class Control > + struct bind + { + template< typename Rule > + using type = control< Rule, Control >; + }; - struct last_chunk : seq< plus< one< '0' > >, opt< chunk_ext >, CRLF > {}; + } // namespace internal::chunk_helper - struct trailer_part : star< header_field, CRLF > {}; + struct chunk + { + using impl = seq< chunk_size, chunk_ext, abnf::CRLF, chunk_data, abnf::CRLF >; + using analyze_t = impl::analyze_t; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + std::size_t size{}; + return impl::template match< A, M, Action, internal::chunk_helper::bind< Control >::template type >( in, size, st... ); + } + }; - struct chunked_body : seq< until< last_chunk, chunk >, trailer_part, CRLF > {}; - // clang-format on + // clang-format off + struct last_chunk : seq< plus< one< '0' > >, not_at< digit >, chunk_ext, abnf::CRLF > {}; - } // namespace http + struct trailer_part : star< header_field, abnf::CRLF > {}; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct chunked_body : seq< until< last_chunk, chunk >, trailer_part, abnf::CRLF > {}; + // clang-format on -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::http #endif diff --git a/include/tao/json/external/pegtl/contrib/icu/internal.hpp b/include/tao/json/external/pegtl/contrib/icu/internal.hpp new file mode 100644 index 00000000..726b0de6 --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/icu/internal.hpp @@ -0,0 +1,68 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_CONTRIB_ICU_INTERNAL_HPP +#define TAO_JSON_PEGTL_CONTRIB_ICU_INTERNAL_HPP + +#include + +#include "../../config.hpp" + +#include "../../analysis/generic.hpp" +#include "../../internal/skip_control.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ + namespace icu + { + template< typename Peek, UProperty P, bool V = true > + struct binary_property + { + using analyze_t = analysis::generic< analysis::rule_type::any >; + + template< typename Input > + [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( Peek::max_input_size ) ) ) + { + if( const std::size_t s = in.size( Peek::max_input_size ); s >= Peek::min_input_size ) { + if( const auto r = Peek::peek( in, s ) ) { + if( u_hasBinaryProperty( r.data, P ) == V ) { + in.bump( r.size ); + return true; + } + } + } + return false; + } + }; + + template< typename Peek, UProperty P, int V > + struct property_value + { + using analyze_t = analysis::generic< analysis::rule_type::any >; + + template< typename Input > + [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( Peek::max_input_size ) ) ) + { + if( const std::size_t s = in.size( Peek::max_input_size ); s >= Peek::min_input_size ) { + if( const auto r = Peek::peek( in, s ) ) { + if( u_getIntPropertyValue( r.data, P ) == V ) { + in.bump( r.size ); + return true; + } + } + } + return false; + } + }; + + } // namespace icu + + template< typename Peek, UProperty P, bool V > + inline constexpr bool skip_control< icu::binary_property< Peek, P, V > > = true; + + template< typename Peek, UProperty P, int V > + inline constexpr bool skip_control< icu::property_value< Peek, P, V > > = true; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/json/external/pegtl/contrib/icu/utf16.hpp b/include/tao/json/external/pegtl/contrib/icu/utf16.hpp new file mode 100644 index 00000000..04af052e --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/icu/utf16.hpp @@ -0,0 +1,200 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_CONTRIB_ICU_UTF16_HPP +#define TAO_JSON_PEGTL_CONTRIB_ICU_UTF16_HPP + +#include "internal.hpp" + +#include "../../config.hpp" +#include "../../utf16.hpp" + +#include "../../internal/peek_utf16.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + namespace utf16_be::icu + { + template< UProperty P, bool V = true > + struct binary_property + : internal::icu::binary_property< internal::peek_utf16_be, P, V > + { + }; + + template< UProperty P, int V > + struct property_value + : internal::icu::property_value< internal::peek_utf16_be, P, V > + { + }; + + // clang-format off + struct alphabetic : binary_property< UCHAR_ALPHABETIC > {}; + struct ascii_hex_digit : binary_property< UCHAR_ASCII_HEX_DIGIT > {}; + struct bidi_control : binary_property< UCHAR_BIDI_CONTROL > {}; + struct bidi_mirrored : binary_property< UCHAR_BIDI_MIRRORED > {}; + struct case_sensitive : binary_property< UCHAR_CASE_SENSITIVE > {}; + struct dash : binary_property< UCHAR_DASH > {}; + struct default_ignorable_code_point : binary_property< UCHAR_DEFAULT_IGNORABLE_CODE_POINT > {}; + struct deprecated : binary_property< UCHAR_DEPRECATED > {}; + struct diacritic : binary_property< UCHAR_DIACRITIC > {}; + struct extender : binary_property< UCHAR_EXTENDER > {}; + struct full_composition_exclusion : binary_property< UCHAR_FULL_COMPOSITION_EXCLUSION > {}; + struct grapheme_base : binary_property< UCHAR_GRAPHEME_BASE > {}; + struct grapheme_extend : binary_property< UCHAR_GRAPHEME_EXTEND > {}; + struct grapheme_link : binary_property< UCHAR_GRAPHEME_LINK > {}; + struct hex_digit : binary_property< UCHAR_HEX_DIGIT > {}; + struct hyphen : binary_property< UCHAR_HYPHEN > {}; + struct id_continue : binary_property< UCHAR_ID_CONTINUE > {}; + struct id_start : binary_property< UCHAR_ID_START > {}; + struct ideographic : binary_property< UCHAR_IDEOGRAPHIC > {}; + struct ids_binary_operator : binary_property< UCHAR_IDS_BINARY_OPERATOR > {}; + struct ids_trinary_operator : binary_property< UCHAR_IDS_TRINARY_OPERATOR > {}; + struct join_control : binary_property< UCHAR_JOIN_CONTROL > {}; + struct logical_order_exception : binary_property< UCHAR_LOGICAL_ORDER_EXCEPTION > {}; + struct lowercase : binary_property< UCHAR_LOWERCASE > {}; + struct math : binary_property< UCHAR_MATH > {}; + struct nfc_inert : binary_property< UCHAR_NFC_INERT > {}; + struct nfd_inert : binary_property< UCHAR_NFD_INERT > {}; + struct nfkc_inert : binary_property< UCHAR_NFKC_INERT > {}; + struct nfkd_inert : binary_property< UCHAR_NFKD_INERT > {}; + struct noncharacter_code_point : binary_property< UCHAR_NONCHARACTER_CODE_POINT > {}; + struct pattern_syntax : binary_property< UCHAR_PATTERN_SYNTAX > {}; + struct pattern_white_space : binary_property< UCHAR_PATTERN_WHITE_SPACE > {}; + struct posix_alnum : binary_property< UCHAR_POSIX_ALNUM > {}; + struct posix_blank : binary_property< UCHAR_POSIX_BLANK > {}; + struct posix_graph : binary_property< UCHAR_POSIX_GRAPH > {}; + struct posix_print : binary_property< UCHAR_POSIX_PRINT > {}; + struct posix_xdigit : binary_property< UCHAR_POSIX_XDIGIT > {}; + struct quotation_mark : binary_property< UCHAR_QUOTATION_MARK > {}; + struct radical : binary_property< UCHAR_RADICAL > {}; + struct s_term : binary_property< UCHAR_S_TERM > {}; + struct segment_starter : binary_property< UCHAR_SEGMENT_STARTER > {}; + struct soft_dotted : binary_property< UCHAR_SOFT_DOTTED > {}; + struct terminal_punctuation : binary_property< UCHAR_TERMINAL_PUNCTUATION > {}; + struct unified_ideograph : binary_property< UCHAR_UNIFIED_IDEOGRAPH > {}; + struct uppercase : binary_property< UCHAR_UPPERCASE > {}; + struct variation_selector : binary_property< UCHAR_VARIATION_SELECTOR > {}; + struct white_space : binary_property< UCHAR_WHITE_SPACE > {}; + struct xid_continue : binary_property< UCHAR_XID_CONTINUE > {}; + struct xid_start : binary_property< UCHAR_XID_START > {}; + + template< UCharDirection V > struct bidi_class : property_value< UCHAR_BIDI_CLASS, V > {}; + template< UBlockCode V > struct block : property_value< UCHAR_BLOCK, V > {}; + template< UDecompositionType V > struct decomposition_type : property_value< UCHAR_DECOMPOSITION_TYPE, V > {}; + template< UEastAsianWidth V > struct east_asian_width : property_value< UCHAR_EAST_ASIAN_WIDTH, V > {}; + template< UCharCategory V > struct general_category : property_value< UCHAR_GENERAL_CATEGORY, V > {}; + template< UGraphemeClusterBreak V > struct grapheme_cluster_break : property_value< UCHAR_GRAPHEME_CLUSTER_BREAK, V > {}; + template< UHangulSyllableType V > struct hangul_syllable_type : property_value< UCHAR_HANGUL_SYLLABLE_TYPE, V > {}; + template< UJoiningGroup V > struct joining_group : property_value< UCHAR_JOINING_GROUP, V > {}; + template< UJoiningType V > struct joining_type : property_value< UCHAR_JOINING_TYPE, V > {}; + template< ULineBreak V > struct line_break : property_value< UCHAR_LINE_BREAK, V > {}; + // UNormalizationCheckResult requires an additional header : + // template< UNormalizationCheckResult V > struct nfc_quick_check : property_value< UCHAR_NFC_QUICK_CHECK, V > {}; + // template< UNormalizationCheckResult V > struct nfd_quick_check : property_value< UCHAR_NFD_QUICK_CHECK, V > {}; + // template< UNormalizationCheckResult V > struct nfkc_quick_check : property_value< UCHAR_NFKC_QUICK_CHECK, V > {}; + // template< UNormalizationCheckResult V > struct nfkd_quick_check : property_value< UCHAR_NFKD_QUICK_CHECK, V > {}; + template< UNumericType V > struct numeric_type : property_value< UCHAR_NUMERIC_TYPE, V > {}; + template< USentenceBreak V > struct sentence_break : property_value< UCHAR_SENTENCE_BREAK, V > {}; + template< UWordBreakValues V > struct word_break : property_value< UCHAR_WORD_BREAK, V > {}; + + template< std::uint8_t V > struct canonical_combining_class : property_value< UCHAR_CANONICAL_COMBINING_CLASS, V > {}; + template< std::uint8_t V > struct lead_canonical_combining_class : property_value< UCHAR_LEAD_CANONICAL_COMBINING_CLASS, V > {}; + template< std::uint8_t V > struct trail_canonical_combining_class : property_value< UCHAR_TRAIL_CANONICAL_COMBINING_CLASS, V > {}; + // clang-format on + + } // namespace utf16_be::icu + + namespace utf16_le::icu + { + template< UProperty P, bool V = true > + struct binary_property + : internal::icu::binary_property< internal::peek_utf16_le, P, V > + { + }; + + template< UProperty P, int V > + struct property_value + : internal::icu::property_value< internal::peek_utf16_le, P, V > + { + }; + + // clang-format off + struct alphabetic : binary_property< UCHAR_ALPHABETIC > {}; + struct ascii_hex_digit : binary_property< UCHAR_ASCII_HEX_DIGIT > {}; + struct bidi_control : binary_property< UCHAR_BIDI_CONTROL > {}; + struct bidi_mirrored : binary_property< UCHAR_BIDI_MIRRORED > {}; + struct case_sensitive : binary_property< UCHAR_CASE_SENSITIVE > {}; + struct dash : binary_property< UCHAR_DASH > {}; + struct default_ignorable_code_point : binary_property< UCHAR_DEFAULT_IGNORABLE_CODE_POINT > {}; + struct deprecated : binary_property< UCHAR_DEPRECATED > {}; + struct diacritic : binary_property< UCHAR_DIACRITIC > {}; + struct extender : binary_property< UCHAR_EXTENDER > {}; + struct full_composition_exclusion : binary_property< UCHAR_FULL_COMPOSITION_EXCLUSION > {}; + struct grapheme_base : binary_property< UCHAR_GRAPHEME_BASE > {}; + struct grapheme_extend : binary_property< UCHAR_GRAPHEME_EXTEND > {}; + struct grapheme_link : binary_property< UCHAR_GRAPHEME_LINK > {}; + struct hex_digit : binary_property< UCHAR_HEX_DIGIT > {}; + struct hyphen : binary_property< UCHAR_HYPHEN > {}; + struct id_continue : binary_property< UCHAR_ID_CONTINUE > {}; + struct id_start : binary_property< UCHAR_ID_START > {}; + struct ideographic : binary_property< UCHAR_IDEOGRAPHIC > {}; + struct ids_binary_operator : binary_property< UCHAR_IDS_BINARY_OPERATOR > {}; + struct ids_trinary_operator : binary_property< UCHAR_IDS_TRINARY_OPERATOR > {}; + struct join_control : binary_property< UCHAR_JOIN_CONTROL > {}; + struct logical_order_exception : binary_property< UCHAR_LOGICAL_ORDER_EXCEPTION > {}; + struct lowercase : binary_property< UCHAR_LOWERCASE > {}; + struct math : binary_property< UCHAR_MATH > {}; + struct nfc_inert : binary_property< UCHAR_NFC_INERT > {}; + struct nfd_inert : binary_property< UCHAR_NFD_INERT > {}; + struct nfkc_inert : binary_property< UCHAR_NFKC_INERT > {}; + struct nfkd_inert : binary_property< UCHAR_NFKD_INERT > {}; + struct noncharacter_code_point : binary_property< UCHAR_NONCHARACTER_CODE_POINT > {}; + struct pattern_syntax : binary_property< UCHAR_PATTERN_SYNTAX > {}; + struct pattern_white_space : binary_property< UCHAR_PATTERN_WHITE_SPACE > {}; + struct posix_alnum : binary_property< UCHAR_POSIX_ALNUM > {}; + struct posix_blank : binary_property< UCHAR_POSIX_BLANK > {}; + struct posix_graph : binary_property< UCHAR_POSIX_GRAPH > {}; + struct posix_print : binary_property< UCHAR_POSIX_PRINT > {}; + struct posix_xdigit : binary_property< UCHAR_POSIX_XDIGIT > {}; + struct quotation_mark : binary_property< UCHAR_QUOTATION_MARK > {}; + struct radical : binary_property< UCHAR_RADICAL > {}; + struct s_term : binary_property< UCHAR_S_TERM > {}; + struct segment_starter : binary_property< UCHAR_SEGMENT_STARTER > {}; + struct soft_dotted : binary_property< UCHAR_SOFT_DOTTED > {}; + struct terminal_punctuation : binary_property< UCHAR_TERMINAL_PUNCTUATION > {}; + struct unified_ideograph : binary_property< UCHAR_UNIFIED_IDEOGRAPH > {}; + struct uppercase : binary_property< UCHAR_UPPERCASE > {}; + struct variation_selector : binary_property< UCHAR_VARIATION_SELECTOR > {}; + struct white_space : binary_property< UCHAR_WHITE_SPACE > {}; + struct xid_continue : binary_property< UCHAR_XID_CONTINUE > {}; + struct xid_start : binary_property< UCHAR_XID_START > {}; + + template< UCharDirection V > struct bidi_class : property_value< UCHAR_BIDI_CLASS, V > {}; + template< UBlockCode V > struct block : property_value< UCHAR_BLOCK, V > {}; + template< UDecompositionType V > struct decomposition_type : property_value< UCHAR_DECOMPOSITION_TYPE, V > {}; + template< UEastAsianWidth V > struct east_asian_width : property_value< UCHAR_EAST_ASIAN_WIDTH, V > {}; + template< UCharCategory V > struct general_category : property_value< UCHAR_GENERAL_CATEGORY, V > {}; + template< UGraphemeClusterBreak V > struct grapheme_cluster_break : property_value< UCHAR_GRAPHEME_CLUSTER_BREAK, V > {}; + template< UHangulSyllableType V > struct hangul_syllable_type : property_value< UCHAR_HANGUL_SYLLABLE_TYPE, V > {}; + template< UJoiningGroup V > struct joining_group : property_value< UCHAR_JOINING_GROUP, V > {}; + template< UJoiningType V > struct joining_type : property_value< UCHAR_JOINING_TYPE, V > {}; + template< ULineBreak V > struct line_break : property_value< UCHAR_LINE_BREAK, V > {}; + // UNormalizationCheckResult requires an additional header : + // template< UNormalizationCheckResult V > struct nfc_quick_check : property_value< UCHAR_NFC_QUICK_CHECK, V > {}; + // template< UNormalizationCheckResult V > struct nfd_quick_check : property_value< UCHAR_NFD_QUICK_CHECK, V > {}; + // template< UNormalizationCheckResult V > struct nfkc_quick_check : property_value< UCHAR_NFKC_QUICK_CHECK, V > {}; + // template< UNormalizationCheckResult V > struct nfkd_quick_check : property_value< UCHAR_NFKD_QUICK_CHECK, V > {}; + template< UNumericType V > struct numeric_type : property_value< UCHAR_NUMERIC_TYPE, V > {}; + template< USentenceBreak V > struct sentence_break : property_value< UCHAR_SENTENCE_BREAK, V > {}; + template< UWordBreakValues V > struct word_break : property_value< UCHAR_WORD_BREAK, V > {}; + + template< std::uint8_t V > struct canonical_combining_class : property_value< UCHAR_CANONICAL_COMBINING_CLASS, V > {}; + template< std::uint8_t V > struct lead_canonical_combining_class : property_value< UCHAR_LEAD_CANONICAL_COMBINING_CLASS, V > {}; + template< std::uint8_t V > struct trail_canonical_combining_class : property_value< UCHAR_TRAIL_CANONICAL_COMBINING_CLASS, V > {}; + // clang-format on + + } // namespace utf16_le::icu + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/contrib/icu/utf32.hpp b/include/tao/json/external/pegtl/contrib/icu/utf32.hpp new file mode 100644 index 00000000..eebcd130 --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/icu/utf32.hpp @@ -0,0 +1,200 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_CONTRIB_ICU_UTF32_HPP +#define TAO_JSON_PEGTL_CONTRIB_ICU_UTF32_HPP + +#include "internal.hpp" + +#include "../../config.hpp" +#include "../../utf32.hpp" + +#include "../../internal/peek_utf32.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + namespace utf32_be::icu + { + template< UProperty P, bool V = true > + struct binary_property + : internal::icu::binary_property< internal::peek_utf32_be, P, V > + { + }; + + template< UProperty P, int V > + struct property_value + : internal::icu::property_value< internal::peek_utf32_be, P, V > + { + }; + + // clang-format off + struct alphabetic : binary_property< UCHAR_ALPHABETIC > {}; + struct ascii_hex_digit : binary_property< UCHAR_ASCII_HEX_DIGIT > {}; + struct bidi_control : binary_property< UCHAR_BIDI_CONTROL > {}; + struct bidi_mirrored : binary_property< UCHAR_BIDI_MIRRORED > {}; + struct case_sensitive : binary_property< UCHAR_CASE_SENSITIVE > {}; + struct dash : binary_property< UCHAR_DASH > {}; + struct default_ignorable_code_point : binary_property< UCHAR_DEFAULT_IGNORABLE_CODE_POINT > {}; + struct deprecated : binary_property< UCHAR_DEPRECATED > {}; + struct diacritic : binary_property< UCHAR_DIACRITIC > {}; + struct extender : binary_property< UCHAR_EXTENDER > {}; + struct full_composition_exclusion : binary_property< UCHAR_FULL_COMPOSITION_EXCLUSION > {}; + struct grapheme_base : binary_property< UCHAR_GRAPHEME_BASE > {}; + struct grapheme_extend : binary_property< UCHAR_GRAPHEME_EXTEND > {}; + struct grapheme_link : binary_property< UCHAR_GRAPHEME_LINK > {}; + struct hex_digit : binary_property< UCHAR_HEX_DIGIT > {}; + struct hyphen : binary_property< UCHAR_HYPHEN > {}; + struct id_continue : binary_property< UCHAR_ID_CONTINUE > {}; + struct id_start : binary_property< UCHAR_ID_START > {}; + struct ideographic : binary_property< UCHAR_IDEOGRAPHIC > {}; + struct ids_binary_operator : binary_property< UCHAR_IDS_BINARY_OPERATOR > {}; + struct ids_trinary_operator : binary_property< UCHAR_IDS_TRINARY_OPERATOR > {}; + struct join_control : binary_property< UCHAR_JOIN_CONTROL > {}; + struct logical_order_exception : binary_property< UCHAR_LOGICAL_ORDER_EXCEPTION > {}; + struct lowercase : binary_property< UCHAR_LOWERCASE > {}; + struct math : binary_property< UCHAR_MATH > {}; + struct nfc_inert : binary_property< UCHAR_NFC_INERT > {}; + struct nfd_inert : binary_property< UCHAR_NFD_INERT > {}; + struct nfkc_inert : binary_property< UCHAR_NFKC_INERT > {}; + struct nfkd_inert : binary_property< UCHAR_NFKD_INERT > {}; + struct noncharacter_code_point : binary_property< UCHAR_NONCHARACTER_CODE_POINT > {}; + struct pattern_syntax : binary_property< UCHAR_PATTERN_SYNTAX > {}; + struct pattern_white_space : binary_property< UCHAR_PATTERN_WHITE_SPACE > {}; + struct posix_alnum : binary_property< UCHAR_POSIX_ALNUM > {}; + struct posix_blank : binary_property< UCHAR_POSIX_BLANK > {}; + struct posix_graph : binary_property< UCHAR_POSIX_GRAPH > {}; + struct posix_print : binary_property< UCHAR_POSIX_PRINT > {}; + struct posix_xdigit : binary_property< UCHAR_POSIX_XDIGIT > {}; + struct quotation_mark : binary_property< UCHAR_QUOTATION_MARK > {}; + struct radical : binary_property< UCHAR_RADICAL > {}; + struct s_term : binary_property< UCHAR_S_TERM > {}; + struct segment_starter : binary_property< UCHAR_SEGMENT_STARTER > {}; + struct soft_dotted : binary_property< UCHAR_SOFT_DOTTED > {}; + struct terminal_punctuation : binary_property< UCHAR_TERMINAL_PUNCTUATION > {}; + struct unified_ideograph : binary_property< UCHAR_UNIFIED_IDEOGRAPH > {}; + struct uppercase : binary_property< UCHAR_UPPERCASE > {}; + struct variation_selector : binary_property< UCHAR_VARIATION_SELECTOR > {}; + struct white_space : binary_property< UCHAR_WHITE_SPACE > {}; + struct xid_continue : binary_property< UCHAR_XID_CONTINUE > {}; + struct xid_start : binary_property< UCHAR_XID_START > {}; + + template< UCharDirection V > struct bidi_class : property_value< UCHAR_BIDI_CLASS, V > {}; + template< UBlockCode V > struct block : property_value< UCHAR_BLOCK, V > {}; + template< UDecompositionType V > struct decomposition_type : property_value< UCHAR_DECOMPOSITION_TYPE, V > {}; + template< UEastAsianWidth V > struct east_asian_width : property_value< UCHAR_EAST_ASIAN_WIDTH, V > {}; + template< UCharCategory V > struct general_category : property_value< UCHAR_GENERAL_CATEGORY, V > {}; + template< UGraphemeClusterBreak V > struct grapheme_cluster_break : property_value< UCHAR_GRAPHEME_CLUSTER_BREAK, V > {}; + template< UHangulSyllableType V > struct hangul_syllable_type : property_value< UCHAR_HANGUL_SYLLABLE_TYPE, V > {}; + template< UJoiningGroup V > struct joining_group : property_value< UCHAR_JOINING_GROUP, V > {}; + template< UJoiningType V > struct joining_type : property_value< UCHAR_JOINING_TYPE, V > {}; + template< ULineBreak V > struct line_break : property_value< UCHAR_LINE_BREAK, V > {}; + // UNormalizationCheckResult requires an additional header : + // template< UNormalizationCheckResult V > struct nfc_quick_check : property_value< UCHAR_NFC_QUICK_CHECK, V > {}; + // template< UNormalizationCheckResult V > struct nfd_quick_check : property_value< UCHAR_NFD_QUICK_CHECK, V > {}; + // template< UNormalizationCheckResult V > struct nfkc_quick_check : property_value< UCHAR_NFKC_QUICK_CHECK, V > {}; + // template< UNormalizationCheckResult V > struct nfkd_quick_check : property_value< UCHAR_NFKD_QUICK_CHECK, V > {}; + template< UNumericType V > struct numeric_type : property_value< UCHAR_NUMERIC_TYPE, V > {}; + template< USentenceBreak V > struct sentence_break : property_value< UCHAR_SENTENCE_BREAK, V > {}; + template< UWordBreakValues V > struct word_break : property_value< UCHAR_WORD_BREAK, V > {}; + + template< std::uint8_t V > struct canonical_combining_class : property_value< UCHAR_CANONICAL_COMBINING_CLASS, V > {}; + template< std::uint8_t V > struct lead_canonical_combining_class : property_value< UCHAR_LEAD_CANONICAL_COMBINING_CLASS, V > {}; + template< std::uint8_t V > struct trail_canonical_combining_class : property_value< UCHAR_TRAIL_CANONICAL_COMBINING_CLASS, V > {}; + // clang-format on + + } // namespace utf32_be::icu + + namespace utf32_le::icu + { + template< UProperty P, bool V = true > + struct binary_property + : internal::icu::binary_property< internal::peek_utf32_le, P, V > + { + }; + + template< UProperty P, int V > + struct property_value + : internal::icu::property_value< internal::peek_utf32_le, P, V > + { + }; + + // clang-format off + struct alphabetic : binary_property< UCHAR_ALPHABETIC > {}; + struct ascii_hex_digit : binary_property< UCHAR_ASCII_HEX_DIGIT > {}; + struct bidi_control : binary_property< UCHAR_BIDI_CONTROL > {}; + struct bidi_mirrored : binary_property< UCHAR_BIDI_MIRRORED > {}; + struct case_sensitive : binary_property< UCHAR_CASE_SENSITIVE > {}; + struct dash : binary_property< UCHAR_DASH > {}; + struct default_ignorable_code_point : binary_property< UCHAR_DEFAULT_IGNORABLE_CODE_POINT > {}; + struct deprecated : binary_property< UCHAR_DEPRECATED > {}; + struct diacritic : binary_property< UCHAR_DIACRITIC > {}; + struct extender : binary_property< UCHAR_EXTENDER > {}; + struct full_composition_exclusion : binary_property< UCHAR_FULL_COMPOSITION_EXCLUSION > {}; + struct grapheme_base : binary_property< UCHAR_GRAPHEME_BASE > {}; + struct grapheme_extend : binary_property< UCHAR_GRAPHEME_EXTEND > {}; + struct grapheme_link : binary_property< UCHAR_GRAPHEME_LINK > {}; + struct hex_digit : binary_property< UCHAR_HEX_DIGIT > {}; + struct hyphen : binary_property< UCHAR_HYPHEN > {}; + struct id_continue : binary_property< UCHAR_ID_CONTINUE > {}; + struct id_start : binary_property< UCHAR_ID_START > {}; + struct ideographic : binary_property< UCHAR_IDEOGRAPHIC > {}; + struct ids_binary_operator : binary_property< UCHAR_IDS_BINARY_OPERATOR > {}; + struct ids_trinary_operator : binary_property< UCHAR_IDS_TRINARY_OPERATOR > {}; + struct join_control : binary_property< UCHAR_JOIN_CONTROL > {}; + struct logical_order_exception : binary_property< UCHAR_LOGICAL_ORDER_EXCEPTION > {}; + struct lowercase : binary_property< UCHAR_LOWERCASE > {}; + struct math : binary_property< UCHAR_MATH > {}; + struct nfc_inert : binary_property< UCHAR_NFC_INERT > {}; + struct nfd_inert : binary_property< UCHAR_NFD_INERT > {}; + struct nfkc_inert : binary_property< UCHAR_NFKC_INERT > {}; + struct nfkd_inert : binary_property< UCHAR_NFKD_INERT > {}; + struct noncharacter_code_point : binary_property< UCHAR_NONCHARACTER_CODE_POINT > {}; + struct pattern_syntax : binary_property< UCHAR_PATTERN_SYNTAX > {}; + struct pattern_white_space : binary_property< UCHAR_PATTERN_WHITE_SPACE > {}; + struct posix_alnum : binary_property< UCHAR_POSIX_ALNUM > {}; + struct posix_blank : binary_property< UCHAR_POSIX_BLANK > {}; + struct posix_graph : binary_property< UCHAR_POSIX_GRAPH > {}; + struct posix_print : binary_property< UCHAR_POSIX_PRINT > {}; + struct posix_xdigit : binary_property< UCHAR_POSIX_XDIGIT > {}; + struct quotation_mark : binary_property< UCHAR_QUOTATION_MARK > {}; + struct radical : binary_property< UCHAR_RADICAL > {}; + struct s_term : binary_property< UCHAR_S_TERM > {}; + struct segment_starter : binary_property< UCHAR_SEGMENT_STARTER > {}; + struct soft_dotted : binary_property< UCHAR_SOFT_DOTTED > {}; + struct terminal_punctuation : binary_property< UCHAR_TERMINAL_PUNCTUATION > {}; + struct unified_ideograph : binary_property< UCHAR_UNIFIED_IDEOGRAPH > {}; + struct uppercase : binary_property< UCHAR_UPPERCASE > {}; + struct variation_selector : binary_property< UCHAR_VARIATION_SELECTOR > {}; + struct white_space : binary_property< UCHAR_WHITE_SPACE > {}; + struct xid_continue : binary_property< UCHAR_XID_CONTINUE > {}; + struct xid_start : binary_property< UCHAR_XID_START > {}; + + template< UCharDirection V > struct bidi_class : property_value< UCHAR_BIDI_CLASS, V > {}; + template< UBlockCode V > struct block : property_value< UCHAR_BLOCK, V > {}; + template< UDecompositionType V > struct decomposition_type : property_value< UCHAR_DECOMPOSITION_TYPE, V > {}; + template< UEastAsianWidth V > struct east_asian_width : property_value< UCHAR_EAST_ASIAN_WIDTH, V > {}; + template< UCharCategory V > struct general_category : property_value< UCHAR_GENERAL_CATEGORY, V > {}; + template< UGraphemeClusterBreak V > struct grapheme_cluster_break : property_value< UCHAR_GRAPHEME_CLUSTER_BREAK, V > {}; + template< UHangulSyllableType V > struct hangul_syllable_type : property_value< UCHAR_HANGUL_SYLLABLE_TYPE, V > {}; + template< UJoiningGroup V > struct joining_group : property_value< UCHAR_JOINING_GROUP, V > {}; + template< UJoiningType V > struct joining_type : property_value< UCHAR_JOINING_TYPE, V > {}; + template< ULineBreak V > struct line_break : property_value< UCHAR_LINE_BREAK, V > {}; + // UNormalizationCheckResult requires an additional header : + // template< UNormalizationCheckResult V > struct nfc_quick_check : property_value< UCHAR_NFC_QUICK_CHECK, V > {}; + // template< UNormalizationCheckResult V > struct nfd_quick_check : property_value< UCHAR_NFD_QUICK_CHECK, V > {}; + // template< UNormalizationCheckResult V > struct nfkc_quick_check : property_value< UCHAR_NFKC_QUICK_CHECK, V > {}; + // template< UNormalizationCheckResult V > struct nfkd_quick_check : property_value< UCHAR_NFKD_QUICK_CHECK, V > {}; + template< UNumericType V > struct numeric_type : property_value< UCHAR_NUMERIC_TYPE, V > {}; + template< USentenceBreak V > struct sentence_break : property_value< UCHAR_SENTENCE_BREAK, V > {}; + template< UWordBreakValues V > struct word_break : property_value< UCHAR_WORD_BREAK, V > {}; + + template< std::uint8_t V > struct canonical_combining_class : property_value< UCHAR_CANONICAL_COMBINING_CLASS, V > {}; + template< std::uint8_t V > struct lead_canonical_combining_class : property_value< UCHAR_LEAD_CANONICAL_COMBINING_CLASS, V > {}; + template< std::uint8_t V > struct trail_canonical_combining_class : property_value< UCHAR_TRAIL_CANONICAL_COMBINING_CLASS, V > {}; + // clang-format on + + } // namespace utf32_le::icu + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/contrib/icu/utf8.hpp b/include/tao/json/external/pegtl/contrib/icu/utf8.hpp new file mode 100644 index 00000000..a47a2d2a --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/icu/utf8.hpp @@ -0,0 +1,105 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_CONTRIB_ICU_UTF8_HPP +#define TAO_JSON_PEGTL_CONTRIB_ICU_UTF8_HPP + +#include "internal.hpp" + +#include "../../config.hpp" +#include "../../utf8.hpp" + +#include "../../internal/peek_utf8.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::utf8::icu +{ + template< UProperty P, bool V = true > + struct binary_property + : internal::icu::binary_property< internal::peek_utf8, P, V > + { + }; + + template< UProperty P, int V > + struct property_value + : internal::icu::property_value< internal::peek_utf8, P, V > + { + }; + + // clang-format off + struct alphabetic : binary_property< UCHAR_ALPHABETIC > {}; + struct ascii_hex_digit : binary_property< UCHAR_ASCII_HEX_DIGIT > {}; + struct bidi_control : binary_property< UCHAR_BIDI_CONTROL > {}; + struct bidi_mirrored : binary_property< UCHAR_BIDI_MIRRORED > {}; + struct case_sensitive : binary_property< UCHAR_CASE_SENSITIVE > {}; + struct dash : binary_property< UCHAR_DASH > {}; + struct default_ignorable_code_point : binary_property< UCHAR_DEFAULT_IGNORABLE_CODE_POINT > {}; + struct deprecated : binary_property< UCHAR_DEPRECATED > {}; + struct diacritic : binary_property< UCHAR_DIACRITIC > {}; + struct extender : binary_property< UCHAR_EXTENDER > {}; + struct full_composition_exclusion : binary_property< UCHAR_FULL_COMPOSITION_EXCLUSION > {}; + struct grapheme_base : binary_property< UCHAR_GRAPHEME_BASE > {}; + struct grapheme_extend : binary_property< UCHAR_GRAPHEME_EXTEND > {}; + struct grapheme_link : binary_property< UCHAR_GRAPHEME_LINK > {}; + struct hex_digit : binary_property< UCHAR_HEX_DIGIT > {}; + struct hyphen : binary_property< UCHAR_HYPHEN > {}; + struct id_continue : binary_property< UCHAR_ID_CONTINUE > {}; + struct id_start : binary_property< UCHAR_ID_START > {}; + struct ideographic : binary_property< UCHAR_IDEOGRAPHIC > {}; + struct ids_binary_operator : binary_property< UCHAR_IDS_BINARY_OPERATOR > {}; + struct ids_trinary_operator : binary_property< UCHAR_IDS_TRINARY_OPERATOR > {}; + struct join_control : binary_property< UCHAR_JOIN_CONTROL > {}; + struct logical_order_exception : binary_property< UCHAR_LOGICAL_ORDER_EXCEPTION > {}; + struct lowercase : binary_property< UCHAR_LOWERCASE > {}; + struct math : binary_property< UCHAR_MATH > {}; + struct nfc_inert : binary_property< UCHAR_NFC_INERT > {}; + struct nfd_inert : binary_property< UCHAR_NFD_INERT > {}; + struct nfkc_inert : binary_property< UCHAR_NFKC_INERT > {}; + struct nfkd_inert : binary_property< UCHAR_NFKD_INERT > {}; + struct noncharacter_code_point : binary_property< UCHAR_NONCHARACTER_CODE_POINT > {}; + struct pattern_syntax : binary_property< UCHAR_PATTERN_SYNTAX > {}; + struct pattern_white_space : binary_property< UCHAR_PATTERN_WHITE_SPACE > {}; + struct posix_alnum : binary_property< UCHAR_POSIX_ALNUM > {}; + struct posix_blank : binary_property< UCHAR_POSIX_BLANK > {}; + struct posix_graph : binary_property< UCHAR_POSIX_GRAPH > {}; + struct posix_print : binary_property< UCHAR_POSIX_PRINT > {}; + struct posix_xdigit : binary_property< UCHAR_POSIX_XDIGIT > {}; + struct quotation_mark : binary_property< UCHAR_QUOTATION_MARK > {}; + struct radical : binary_property< UCHAR_RADICAL > {}; + struct s_term : binary_property< UCHAR_S_TERM > {}; + struct segment_starter : binary_property< UCHAR_SEGMENT_STARTER > {}; + struct soft_dotted : binary_property< UCHAR_SOFT_DOTTED > {}; + struct terminal_punctuation : binary_property< UCHAR_TERMINAL_PUNCTUATION > {}; + struct unified_ideograph : binary_property< UCHAR_UNIFIED_IDEOGRAPH > {}; + struct uppercase : binary_property< UCHAR_UPPERCASE > {}; + struct variation_selector : binary_property< UCHAR_VARIATION_SELECTOR > {}; + struct white_space : binary_property< UCHAR_WHITE_SPACE > {}; + struct xid_continue : binary_property< UCHAR_XID_CONTINUE > {}; + struct xid_start : binary_property< UCHAR_XID_START > {}; + + template< UCharDirection V > struct bidi_class : property_value< UCHAR_BIDI_CLASS, V > {}; + template< UBlockCode V > struct block : property_value< UCHAR_BLOCK, V > {}; + template< UDecompositionType V > struct decomposition_type : property_value< UCHAR_DECOMPOSITION_TYPE, V > {}; + template< UEastAsianWidth V > struct east_asian_width : property_value< UCHAR_EAST_ASIAN_WIDTH, V > {}; + template< UCharCategory V > struct general_category : property_value< UCHAR_GENERAL_CATEGORY, V > {}; + template< UGraphemeClusterBreak V > struct grapheme_cluster_break : property_value< UCHAR_GRAPHEME_CLUSTER_BREAK, V > {}; + template< UHangulSyllableType V > struct hangul_syllable_type : property_value< UCHAR_HANGUL_SYLLABLE_TYPE, V > {}; + template< UJoiningGroup V > struct joining_group : property_value< UCHAR_JOINING_GROUP, V > {}; + template< UJoiningType V > struct joining_type : property_value< UCHAR_JOINING_TYPE, V > {}; + template< ULineBreak V > struct line_break : property_value< UCHAR_LINE_BREAK, V > {}; + // UNormalizationCheckResult requires an additional header : + // template< UNormalizationCheckResult V > struct nfc_quick_check : property_value< UCHAR_NFC_QUICK_CHECK, V > {}; + // template< UNormalizationCheckResult V > struct nfd_quick_check : property_value< UCHAR_NFD_QUICK_CHECK, V > {}; + // template< UNormalizationCheckResult V > struct nfkc_quick_check : property_value< UCHAR_NFKC_QUICK_CHECK, V > {}; + // template< UNormalizationCheckResult V > struct nfkd_quick_check : property_value< UCHAR_NFKD_QUICK_CHECK, V > {}; + template< UNumericType V > struct numeric_type : property_value< UCHAR_NUMERIC_TYPE, V > {}; + template< USentenceBreak V > struct sentence_break : property_value< UCHAR_SENTENCE_BREAK, V > {}; + template< UWordBreakValues V > struct word_break : property_value< UCHAR_WORD_BREAK, V > {}; + + template< std::uint8_t V > struct canonical_combining_class : property_value< UCHAR_CANONICAL_COMBINING_CLASS, V > {}; + template< std::uint8_t V > struct lead_canonical_combining_class : property_value< UCHAR_LEAD_CANONICAL_COMBINING_CLASS, V > {}; + template< std::uint8_t V > struct trail_canonical_combining_class : property_value< UCHAR_TRAIL_CANONICAL_COMBINING_CLASS, V > {}; + // clang-format on + +} // namespace TAO_JSON_PEGTL_NAMESPACE::utf8::icu + +#endif diff --git a/include/tao/json/external/pegtl/contrib/if_then.hpp b/include/tao/json/external/pegtl/contrib/if_then.hpp new file mode 100644 index 00000000..85079031 --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/if_then.hpp @@ -0,0 +1,55 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_CONTRIB_IF_THEN_HPP +#define TAO_JSON_PEGTL_CONTRIB_IF_THEN_HPP + +#include + +#include "../config.hpp" + +#include "../internal/if_then_else.hpp" +#include "../internal/seq.hpp" +#include "../internal/skip_control.hpp" +#include "../internal/trivial.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + namespace internal + { + template< typename Cond, typename Then > + struct if_pair + { + }; + + template< typename... Pairs > + struct if_then; + + template< typename Cond, typename Then, typename... Pairs > + struct if_then< if_pair< Cond, Then >, Pairs... > + : if_then_else< Cond, Then, if_then< Pairs... > > + { + template< typename ElseCond, typename... Thens > + using else_if_then = if_then< if_pair< Cond, Then >, Pairs..., if_pair< ElseCond, seq< Thens... > > >; + + template< typename... Thens > + using else_then = if_then_else< Cond, Then, if_then< Pairs..., if_pair< trivial< true >, seq< Thens... > > > >; + }; + + template<> + struct if_then<> + : trivial< false > + { + }; + + template< typename... Pairs > + inline constexpr bool skip_control< if_then< Pairs... > > = true; + + } // namespace internal + + template< typename Cond, typename... Thens > + using if_then = internal::if_then< internal::if_pair< Cond, internal::seq< Thens... > > >; + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/contrib/integer.hpp b/include/tao/json/external/pegtl/contrib/integer.hpp new file mode 100644 index 00000000..332168a2 --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/integer.hpp @@ -0,0 +1,446 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_CONTRIB_INTEGER_HPP +#define TAO_JSON_PEGTL_CONTRIB_INTEGER_HPP + +#include +#include + +#include + +#include "../ascii.hpp" +#include "../parse.hpp" +#include "../parse_error.hpp" +#include "../rules.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::integer +{ + namespace internal + { + struct unsigned_rule_old + : plus< digit > + { + // Pre-3.0 version of this rule. + }; + + struct unsigned_rule_new + : if_then_else< one< '0' >, not_at< digit >, plus< digit > > + { + // New version that does not allow leading zeros. + }; + + struct signed_rule_old + : seq< opt< one< '-', '+' > >, plus< digit > > + { + // Pre-3.0 version of this rule. + }; + + struct signed_rule_new + : seq< opt< one< '-', '+' > >, if_then_else< one< '0' >, not_at< digit >, plus< digit > > > + { + // New version that does not allow leading zeros. + }; + + struct signed_rule_bis + : seq< opt< one< '-' > >, if_then_else< one< '0' >, not_at< digit >, plus< digit > > > + { + }; + + struct signed_rule_ter + : seq< one< '-', '+' >, if_then_else< one< '0' >, not_at< digit >, plus< digit > > > + { + }; + + [[nodiscard]] constexpr bool is_digit( const char c ) noexcept + { + // We don't use std::isdigit() because it might + // return true for other values on MS platforms. + + return ( '0' <= c ) && ( c <= '9' ); + } + + template< typename Integer, Integer Maximum = ( std::numeric_limits< Integer >::max )() > + [[nodiscard]] constexpr bool accumulate_digit( Integer& result, const char digit ) noexcept + { + // Assumes that digit is a digit as per is_digit(); returns false on overflow. + + static_assert( std::is_integral_v< Integer > ); + + constexpr Integer cutoff = Maximum / 10; + constexpr Integer cutlim = Maximum % 10; + + const Integer c = digit - '0'; + + if( ( result > cutoff ) || ( ( result == cutoff ) && ( c > cutlim ) ) ) { + return false; + } + result *= 10; + result += c; + return true; + } + + template< typename Integer, Integer Maximum = ( std::numeric_limits< Integer >::max )() > + [[nodiscard]] constexpr bool accumulate_digits( Integer& result, const std::string_view input ) noexcept + { + // Assumes input is a non-empty sequence of digits; returns false on overflow. + + for( char c : input ) { + if( !accumulate_digit< Integer, Maximum >( result, c ) ) { + return false; + } + } + return true; + } + + template< typename Integer, Integer Maximum = ( std::numeric_limits< Integer >::max )() > + [[nodiscard]] constexpr bool convert_positive( Integer& result, const std::string_view input ) noexcept + { + // Assumes result == 0 and that input is a non-empty sequence of digits; returns false on overflow. + + static_assert( std::is_integral_v< Integer > ); + return accumulate_digits< Integer, Maximum >( result, input ); + } + + template< typename Signed > + [[nodiscard]] constexpr bool convert_negative( Signed& result, const std::string_view input ) noexcept + { + // Assumes result == 0 and that input is a non-empty sequence of digits; returns false on overflow. + + static_assert( std::is_signed_v< Signed > ); + using Unsigned = std::make_unsigned_t< Signed >; + constexpr Unsigned maximum = static_cast< Unsigned >( ( std::numeric_limits< Signed >::max )() ) + 1; + Unsigned temporary = 0; + if( accumulate_digits< Unsigned, maximum >( temporary, input ) ) { + result = static_cast< Signed >( ~temporary ) + 1; + return true; + } + return false; + } + + template< typename Unsigned, Unsigned Maximum = ( std::numeric_limits< Unsigned >::max )() > + [[nodiscard]] constexpr bool convert_unsigned( Unsigned& result, const std::string_view input ) noexcept + { + // Assumes result == 0 and that input is a non-empty sequence of digits; returns false on overflow. + + static_assert( std::is_unsigned_v< Unsigned > ); + return accumulate_digits< Unsigned, Maximum >( result, input ); + } + + template< typename Signed > + [[nodiscard]] constexpr bool convert_signed( Signed& result, const std::string_view input ) noexcept + { + // Assumes result == 0 and that input is an optional sign followed by a non-empty sequence of digits; returns false on overflow. + + static_assert( std::is_signed_v< Signed > ); + if( input[ 0 ] == '-' ) { + return convert_negative< Signed >( result, std::string_view( input.data() + 1, input.size() - 1 ) ); + } + const auto offset = unsigned( input[ 0 ] == '+' ); + return convert_positive< Signed >( result, std::string_view( input.data() + offset, input.size() - offset ) ); + } + + template< typename Input > + [[nodiscard]] bool match_unsigned( Input& in ) noexcept( noexcept( in.empty() ) ) + { + if( !in.empty() ) { + const char c = in.peek_char(); + if( is_digit( c ) ) { + in.bump_in_this_line(); + if( c == '0' ) { + return in.empty() || ( !is_digit( in.peek_char() ) ); // TODO: Throw exception on digit? + } + while( ( !in.empty() ) && is_digit( in.peek_char() ) ) { + in.bump_in_this_line(); + } + return true; + } + } + return false; + } + + template< typename Input, + typename Unsigned, + Unsigned Maximum = ( std::numeric_limits< Unsigned >::max )() > + [[nodiscard]] bool match_and_convert_unsigned_with_maximum( Input& in, Unsigned& st ) + { + // Assumes st == 0. + + if( !in.empty() ) { + char c = in.peek_char(); + if( is_digit( c ) ) { + if( c == '0' ) { + in.bump_in_this_line(); + return in.empty() || ( !is_digit( in.peek_char() ) ); // TODO: Throw exception on digit? + } + do { + if( !accumulate_digit< Unsigned, Maximum >( st, c ) ) { + throw parse_error( "integer overflow", in ); // Consistent with "as if" an action was doing the conversion. + } + in.bump_in_this_line(); + } while( ( !in.empty() ) && is_digit( c = in.peek_char() ) ); + return true; + } + } + return false; + } + + } // namespace internal + + struct unsigned_action + { + // Assumes that 'in' contains a non-empty sequence of ASCII digits. + + template< typename Input, typename Unsigned > + static auto apply( const Input& in, Unsigned& st ) -> std::enable_if_t< std::is_unsigned_v< Unsigned >, void > + { + // This function "only" offers basic exception safety. + st = 0; + if( !internal::convert_unsigned( st, in.string_view() ) ) { + throw parse_error( "unsigned integer overflow", in ); + } + } + + template< typename Input, typename State > + static auto apply( const Input& in, State& st ) -> std::enable_if_t< std::is_class_v< State >, void > + { + apply( in, st.converted ); // Compatibility for pre-3.0 behaviour. + } + + template< typename Input, typename Unsigned, typename... Ts > + static auto apply( const Input& in, std::vector< Unsigned, Ts... >& st ) -> std::enable_if_t< std::is_unsigned_v< Unsigned >, void > + { + Unsigned u = 0; + apply( in, u ); + st.emplace_back( u ); + } + }; + + struct unsigned_rule + { + using analyze_t = internal::unsigned_rule_new::analyze_t; + + template< typename Input > + [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.empty() ) ) + { + return internal::match_unsigned( in ); // Does not check for any overflow. + } + }; + + struct unsigned_rule_with_action + { + using analyze_t = internal::unsigned_rule_new::analyze_t; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static auto match( Input& in, States&&... /*unused*/ ) noexcept( noexcept( in.empty() ) ) -> std::enable_if_t< A == apply_mode::nothing, bool > + { + return internal::match_unsigned( in ); // Does not check for any overflow. + } + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename Unsigned > + [[nodiscard]] static auto match( Input& in, Unsigned& st ) -> std::enable_if_t< ( A == apply_mode::action ) && std::is_unsigned_v< Unsigned >, bool > + { + // This function "only" offers basic exception safety. + st = 0; + return internal::match_and_convert_unsigned_with_maximum( in, st ); // Throws on overflow. + } + + // TODO: Overload for st.converted? + // TODO: Overload for std::vector< Unsigned >? + }; + + template< typename Unsigned, Unsigned Maximum > + struct maximum_action + { + // Assumes that 'in' contains a non-empty sequence of ASCII digits. + + static_assert( std::is_unsigned_v< Unsigned > ); + + template< typename Input, typename Unsigned2 > + static auto apply( const Input& in, Unsigned2& st ) -> std::enable_if_t< std::is_same_v< Unsigned, Unsigned2 >, void > + { + // This function "only" offers basic exception safety. + st = 0; + if( !internal::convert_unsigned< Unsigned, Maximum >( st, in.string_view() ) ) { + throw parse_error( "unsigned integer overflow", in ); + } + } + + template< typename Input, typename State > + static auto apply( const Input& in, State& st ) -> std::enable_if_t< std::is_class_v< State >, void > + { + apply( in, st.converted ); // Compatibility for pre-3.0 behaviour. + } + + template< typename Input, typename Unsigned2, typename... Ts > + static auto apply( const Input& in, std::vector< Unsigned2, Ts... >& st ) -> std::enable_if_t< std::is_same_v< Unsigned, Unsigned2 >, void > + { + Unsigned u = 0; + apply( in, u ); + st.emplace_back( u ); + } + }; + + template< typename Unsigned, Unsigned Maximum = ( std::numeric_limits< Unsigned >::max )() > + struct maximum_rule + { + static_assert( std::is_unsigned_v< Unsigned > ); + + using analyze_t = internal::unsigned_rule_new::analyze_t; + + template< typename Input > + [[nodiscard]] static bool match( Input& in ) + { + Unsigned st = 0; + return internal::match_and_convert_unsigned_with_maximum< Input, Unsigned, Maximum >( in, st ); // Throws on overflow. + } + }; + + template< typename Unsigned, Unsigned Maximum = ( std::numeric_limits< Unsigned >::max )() > + struct maximum_rule_with_action + { + static_assert( std::is_unsigned_v< Unsigned > ); + + using analyze_t = internal::unsigned_rule_new::analyze_t; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static auto match( Input& in, States&&... /*unused*/ ) -> std::enable_if_t< A == apply_mode::nothing, bool > + { + Unsigned st = 0; + return internal::match_and_convert_unsigned_with_maximum< Input, Unsigned, Maximum >( in, st ); // Throws on overflow. + } + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename Unsigned2 > + [[nodiscard]] static auto match( Input& in, Unsigned2& st ) -> std::enable_if_t< ( A == apply_mode::action ) && std::is_same_v< Unsigned, Unsigned2 >, bool > + { + // This function "only" offers basic exception safety. + st = 0; + return internal::match_and_convert_unsigned_with_maximum< Input, Unsigned, Maximum >( in, st ); // Throws on overflow. + } + + // TODO: Overload for st.converted? + // TODO: Overload for std::vector< Unsigned >? + }; + + struct signed_action + { + // Assumes that 'in' contains a non-empty sequence of ASCII digits, + // with optional leading sign; with sign, in.size() must be >= 2. + + template< typename Input, typename Signed > + static auto apply( const Input& in, Signed& st ) -> std::enable_if_t< std::is_signed_v< Signed >, void > + { + // This function "only" offers basic exception safety. + st = 0; + if( !internal::convert_signed( st, in.string_view() ) ) { + throw parse_error( "signed integer overflow", in ); + } + } + + template< typename Input, typename State > + static auto apply( const Input& in, State& st ) -> std::enable_if_t< std::is_class_v< State >, void > + { + apply( in, st.converted ); // Compatibility for pre-3.0 behaviour. + } + + template< typename Input, typename Signed, typename... Ts > + static auto apply( const Input& in, std::vector< Signed, Ts... >& st ) -> std::enable_if_t< std::is_signed_v< Signed >, void > + { + Signed s = 0; + apply( in, s ); + st.emplace_back( s ); + } + }; + + struct signed_rule + { + using analyze_t = internal::signed_rule_new::analyze_t; + + template< typename Input > + [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.empty() ) ) + { + return TAO_JSON_PEGTL_NAMESPACE::parse< internal::signed_rule_new >( in ); // Does not check for any overflow. + } + }; + + namespace internal + { + template< typename Rule > + struct signed_action_action + : nothing< Rule > + { + }; + + template<> + struct signed_action_action< signed_rule_new > + : signed_action + { + }; + + } // namespace internal + + struct signed_rule_with_action + { + using analyze_t = internal::signed_rule_new::analyze_t; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static auto match( Input& in, States&&... /*unused*/ ) noexcept( noexcept( in.empty() ) ) -> std::enable_if_t< A == apply_mode::nothing, bool > + { + return TAO_JSON_PEGTL_NAMESPACE::parse< internal::signed_rule_new >( in ); // Does not check for any overflow. + } + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename Signed > + [[nodiscard]] static auto match( Input& in, Signed& st ) -> std::enable_if_t< ( A == apply_mode::action ) && std::is_signed_v< Signed >, bool > + { + return TAO_JSON_PEGTL_NAMESPACE::parse< internal::signed_rule_new, internal::signed_action_action >( in, st ); // Throws on overflow. + } + + // TODO: Overload for st.converted? + // TODO: Overload for std::vector< Signed >? + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::integer + +#endif diff --git a/include/tao/json/external/pegtl/contrib/json.hpp b/include/tao/json/external/pegtl/contrib/json.hpp index 352c3f70..ccdf5ea9 100644 --- a/include/tao/json/external/pegtl/contrib/json.hpp +++ b/include/tao/json/external/pegtl/contrib/json.hpp @@ -1,98 +1,88 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_JSON_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_JSON_HPP +#ifndef TAO_JSON_PEGTL_CONTRIB_JSON_HPP +#define TAO_JSON_PEGTL_CONTRIB_JSON_HPP #include "../ascii.hpp" #include "../config.hpp" #include "../rules.hpp" #include "../utf8.hpp" -#include "abnf.hpp" - -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::json { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + // JSON grammar according to RFC 8259 + + // clang-format off + struct ws : one< ' ', '\t', '\n', '\r' > {}; + + template< typename R, typename P = ws > + struct padr : internal::seq< R, internal::star< P > > {}; + + struct begin_array : padr< one< '[' > > {}; + struct begin_object : padr< one< '{' > > {}; + struct end_array : one< ']' > {}; + struct end_object : one< '}' > {}; + struct name_separator : pad< one< ':' >, ws > {}; + struct value_separator : padr< one< ',' > > {}; + + struct false_ : string< 'f', 'a', 'l', 's', 'e' > {}; // NOLINT(readability-identifier-naming) + struct null : string< 'n', 'u', 'l', 'l' > {}; + struct true_ : string< 't', 'r', 'u', 'e' > {}; // NOLINT(readability-identifier-naming) + + struct digits : plus< digit > {}; + struct exp : seq< one< 'e', 'E' >, opt< one< '-', '+'> >, must< digits > > {}; + struct frac : if_must< one< '.' >, digits > {}; + struct int_ : sor< one< '0' >, digits > {}; // NOLINT(readability-identifier-naming) + struct number : seq< opt< one< '-' > >, int_, opt< frac >, opt< exp > > {}; + + struct xdigit : pegtl::xdigit {}; + struct unicode : list< seq< one< 'u' >, rep< 4, must< xdigit > > >, one< '\\' > > {}; + struct escaped_char : one< '"', '\\', '/', 'b', 'f', 'n', 'r', 't' > {}; + struct escaped : sor< escaped_char, unicode > {}; + struct unescaped : utf8::range< 0x20, 0x10FFFF > {}; + struct char_ : if_then_else< one< '\\' >, must< escaped >, unescaped > {}; // NOLINT(readability-identifier-naming) + + struct string_content : until< at< one< '"' > >, must< char_ > > {}; + struct string : seq< one< '"' >, must< string_content >, any > + { + using content = string_content; + }; + + struct key_content : until< at< one< '"' > >, must< char_ > > {}; + struct key : seq< one< '"' >, must< key_content >, any > + { + using content = key_content; + }; + + struct value; + + struct array_element; + struct array_content : opt< list_must< array_element, value_separator > > {}; + struct array : seq< begin_array, array_content, must< end_array > > + { + using begin = begin_array; + using end = end_array; + using element = array_element; + using content = array_content; + }; + + struct member : if_must< key, name_separator, value > {}; + struct object_content : opt< list_must< member, value_separator > > {}; + struct object : seq< begin_object, object_content, must< end_object > > { - namespace json - { - // JSON grammar according to RFC 7159 (for UTF-8 encoded JSON only). - - // clang-format off - struct ws : one< ' ', '\t', '\n', '\r' > {}; - - template< typename R, typename P = ws > - struct padr : internal::seq< R, internal::star< P > > {}; - - struct begin_array : padr< one< '[' > > {}; - struct begin_object : padr< one< '{' > > {}; - struct end_array : one< ']' > {}; - struct end_object : one< '}' > {}; - struct name_separator : pad< one< ':' >, ws > {}; - struct value_separator : padr< one< ',' > > {}; - - struct false_ : TAOCPP_JSON_PEGTL_STRING( "false" ) {}; - struct null : TAOCPP_JSON_PEGTL_STRING( "null" ) {}; - struct true_ : TAOCPP_JSON_PEGTL_STRING( "true" ) {}; - - struct digits : plus< abnf::DIGIT > {}; - struct exp : seq< one< 'e', 'E' >, opt< one< '-', '+'> >, must< digits > > {}; - struct frac : if_must< one< '.' >, digits > {}; - struct int_ : sor< one< '0' >, digits > {}; - struct number : seq< opt< one< '-' > >, int_, opt< frac >, opt< exp > > {}; - - struct xdigit : abnf::HEXDIG {}; - struct unicode : list< seq< one< 'u' >, rep< 4, must< xdigit > > >, one< '\\' > > {}; - struct escaped_char : one< '"', '\\', '/', 'b', 'f', 'n', 'r', 't' > {}; - struct escaped : sor< escaped_char, unicode > {}; - struct unescaped : utf8::range< 0x20, 0x10FFFF > {}; - struct char_ : if_then_else< one< '\\' >, must< escaped >, unescaped > {}; - - struct string_content : until< at< one< '"' > >, must< char_ > > {}; - struct string : seq< one< '"' >, must< string_content >, any > - { - using content = string_content; - }; - - struct key_content : until< at< one< '"' > >, must< char_ > > {}; - struct key : seq< one< '"' >, must< key_content >, any > - { - using content = key_content; - }; - - struct value; - - struct array_element; - struct array_content : opt< list_must< array_element, value_separator > > {}; - struct array : seq< begin_array, array_content, must< end_array > > - { - using begin = begin_array; - using end = end_array; - using element = array_element; - using content = array_content; - }; - - struct member : if_must< key, name_separator, value > {}; - struct object_content : opt< list_must< member, value_separator > > {}; - struct object : seq< begin_object, object_content, must< end_object > > - { - using begin = begin_object; - using end = end_object; - using element = member; - using content = object_content; - }; - - struct value : padr< sor< string, number, object, array, false_, true_, null > > {}; - struct array_element : seq< value > {}; - - struct text : seq< star< ws >, value > {}; - // clang-format on - - } // namespace json - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + using begin = begin_object; + using end = end_object; + using element = member; + using content = object_content; + }; + + struct value : padr< sor< string, number, object, array, false_, true_, null > > {}; + struct array_element : seq< value > {}; + + struct text : seq< star< ws >, value > {}; + // clang-format on + +} // namespace TAO_JSON_PEGTL_NAMESPACE::json #endif diff --git a/include/tao/json/external/pegtl/contrib/json_pointer.hpp b/include/tao/json/external/pegtl/contrib/json_pointer.hpp new file mode 100644 index 00000000..153766fe --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/json_pointer.hpp @@ -0,0 +1,33 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_CONTRIB_JSON_POINTER_HPP +#define TAO_JSON_PEGTL_CONTRIB_JSON_POINTER_HPP + +#include "../ascii.hpp" +#include "../config.hpp" +#include "../rules.hpp" +#include "../utf8.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::json_pointer +{ + // JSON pointer grammar according to RFC 6901 + + // clang-format off + struct unescaped : utf8::ranges< 0x0, 0x2E, 0x30, 0x7D, 0x7F, 0x10FFFF > {}; + struct escaped : seq< one< '~' >, one< '0', '1' > > {}; + + struct reference_token : star< sor< unescaped, escaped > > {}; + struct json_pointer : star< one< '/' >, reference_token > {}; + // clang-format on + + // relative JSON pointer, see ... + + // clang-format off + struct non_negative_integer : sor< one< '0' >, plus< digit > > {}; + struct relative_json_pointer : seq< non_negative_integer, sor< one< '#' >, json_pointer > > {}; + // clang-format on + +} // namespace TAO_JSON_PEGTL_NAMESPACE::json_pointer + +#endif diff --git a/include/tao/json/external/pegtl/contrib/parse_tree.hpp b/include/tao/json/external/pegtl/contrib/parse_tree.hpp index ac654852..43f9f9ce 100644 --- a/include/tao/json/external/pegtl/contrib/parse_tree.hpp +++ b/include/tao/json/external/pegtl/contrib/parse_tree.hpp @@ -1,183 +1,561 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_PARSE_TREE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_PARSE_TREE_HPP +#ifndef TAO_JSON_PEGTL_CONTRIB_PARSE_TREE_HPP +#define TAO_JSON_PEGTL_CONTRIB_PARSE_TREE_HPP +#include #include +#include +#include +#include #include -#include +#include #include #include #include "../config.hpp" +#include "../memory_input.hpp" #include "../normal.hpp" +#include "../nothing.hpp" +#include "../parse.hpp" +#include "../analysis/counted.hpp" +#include "../analysis/generic.hpp" +#include "../internal/demangle.hpp" #include "../internal/iterator.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::parse_tree { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename T > + struct basic_node { - namespace parse_tree + using node_t = T; + using children_t = std::vector< std::unique_ptr< node_t > >; + children_t children; + + std::string_view type; + std::string source; + + TAO_JSON_PEGTL_NAMESPACE::internal::iterator m_begin; + TAO_JSON_PEGTL_NAMESPACE::internal::iterator m_end; + + // each node will be default constructed + basic_node() = default; + + // no copy/move is necessary + // (nodes are always owned/handled by a std::unique_ptr) + basic_node( const basic_node& ) = delete; + basic_node( basic_node&& ) = delete; + + ~basic_node() = default; + + // no assignment either + basic_node& operator=( const basic_node& ) = delete; + basic_node& operator=( basic_node&& ) = delete; + + [[nodiscard]] bool is_root() const noexcept + { + return type.empty(); + } + + template< typename U > + [[nodiscard]] bool is_type() const noexcept + { + return type == TAO_JSON_PEGTL_NAMESPACE::internal::demangle< U >(); + } + + template< typename U > + void set_type() noexcept + { + type = TAO_JSON_PEGTL_NAMESPACE::internal::demangle< U >(); + } + + [[nodiscard]] position begin() const + { + return position( m_begin, source ); + } + + [[nodiscard]] position end() const + { + return position( m_end, source ); + } + + [[nodiscard]] bool has_content() const noexcept + { + return m_end.data != nullptr; + } + + [[nodiscard]] std::string_view string_view() const noexcept + { + assert( has_content() ); + return std::string_view( m_begin.data, m_end.data - m_begin.data ); + } + + [[nodiscard]] std::string string() const + { + assert( has_content() ); + return std::string( m_begin.data, m_end.data ); + } + + template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf > + [[nodiscard]] memory_input< P, Eol > as_memory_input() const + { + assert( has_content() ); + return { m_begin.data, m_end.data, source, m_begin.byte, m_begin.line, m_begin.byte_in_line }; + } + + template< typename... States > + void remove_content( States&&... /*unused*/ ) noexcept + { + m_end.reset(); + } + + // all non-root nodes are initialized by calling this method + template< typename Rule, typename Input, typename... States > + void start( const Input& in, States&&... /*unused*/ ) + { + set_type< Rule >(); + source = in.source(); + m_begin = TAO_JSON_PEGTL_NAMESPACE::internal::iterator( in.iterator() ); + } + + // if parsing of the rule succeeded, this method is called + template< typename Rule, typename Input, typename... States > + void success( const Input& in, States&&... /*unused*/ ) noexcept + { + m_end = TAO_JSON_PEGTL_NAMESPACE::internal::iterator( in.iterator() ); + } + + // if parsing of the rule failed, this method is called + template< typename Rule, typename Input, typename... States > + void failure( const Input& /*unused*/, States&&... /*unused*/ ) noexcept + { + } + + // if parsing succeeded and the (optional) transform call + // did not discard the node, it is appended to its parent. + // note that "child" is the node whose Rule just succeeded + // and "*this" is the parent where the node should be appended. + template< typename... States > + void emplace_back( std::unique_ptr< node_t >&& child, States&&... /*unused*/ ) { - struct node + assert( child ); + children.emplace_back( std::move( child ) ); + } + }; + + struct node + : basic_node< node > + { + }; + + namespace internal + { + template< typename Node > + struct state + { + std::vector< std::unique_ptr< Node > > stack; + + state() { - std::vector< std::unique_ptr< node > > children; - const std::type_info* id = nullptr; - internal::iterator begin; - internal::iterator end; - }; + emplace_back(); + } - class state + void emplace_back() { - private: - std::vector< std::unique_ptr< node > > stack; + stack.emplace_back( std::make_unique< Node >() ); + } - public: - state() - { - emplace_back(); - } + [[nodiscard]] std::unique_ptr< Node >& back() noexcept + { + assert( !stack.empty() ); + return stack.back(); + } - const node& root() const noexcept - { - return *stack.front(); - } + void pop_back() noexcept + { + assert( !stack.empty() ); + return stack.pop_back(); + } + }; - std::unique_ptr< node >& back() noexcept - { - return stack.back(); - } + template< typename Selector, typename... Parameters > + void transform( Parameters&&... /*unused*/ ) noexcept + { + } - void pop_back() noexcept - { - return stack.pop_back(); - } + template< typename Selector, typename Input, typename Node, typename... States > + auto transform( const Input& in, std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( Selector::transform( in, n, st... ) ) ) + -> decltype( Selector::transform( in, n, st... ), void() ) + { + Selector::transform( in, n, st... ); + } - void emplace_back() - { - stack.emplace_back( std::unique_ptr< node >( new node ) ); - } - }; + template< typename Selector, typename Input, typename Node, typename... States > + auto transform( const Input& /*unused*/, std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( Selector::transform( n, st... ) ) ) + -> decltype( Selector::transform( n, st... ), void() ) + { + Selector::transform( n, st... ); + } - } // namespace parse_tree + template< unsigned Level, typename Analyse, template< typename... > class Selector > + struct is_leaf + : std::false_type + { + }; + + template< analysis::rule_type Type, template< typename... > class Selector > + struct is_leaf< 0, analysis::generic< Type >, Selector > + : std::true_type + { + }; + + template< analysis::rule_type Type, std::size_t Count, template< typename... > class Selector > + struct is_leaf< 0, analysis::counted< Type, Count >, Selector > + : std::true_type + { + }; + + template< analysis::rule_type Type, typename... Rules, template< typename... > class Selector > + struct is_leaf< 0, analysis::generic< Type, Rules... >, Selector > + : std::false_type + { + }; + + template< analysis::rule_type Type, std::size_t Count, typename... Rules, template< typename... > class Selector > + struct is_leaf< 0, analysis::counted< Type, Count, Rules... >, Selector > + : std::false_type + { + }; + + template< unsigned Level, typename Rule, template< typename... > class Selector > + inline constexpr bool is_unselected_leaf = !Selector< Rule >::value && is_leaf< Level, typename Rule::analyze_t, Selector >::value; + + template< unsigned Level, analysis::rule_type Type, typename... Rules, template< typename... > class Selector > + struct is_leaf< Level, analysis::generic< Type, Rules... >, Selector > + : std::bool_constant< ( is_unselected_leaf< Level - 1, Rules, Selector > && ... ) > + { + }; - namespace internal + template< unsigned Level, analysis::rule_type Type, std::size_t Count, typename... Rules, template< typename... > class Selector > + struct is_leaf< Level, analysis::counted< Type, Count, Rules... >, Selector > + : std::bool_constant< ( is_unselected_leaf< Level - 1, Rules, Selector > && ... ) > { - template< template< typename > class S, template< typename > class C > - struct parse_tree + }; + + template< typename T > + struct control + { + template< typename Input, typename Tuple, std::size_t... Is > + static void start_impl( const Input& in, const Tuple& t, std::index_sequence< Is... > /*unused*/ ) noexcept( noexcept( T::start( in, std::get< sizeof...( Is ) >( t ), std::get< Is >( t )... ) ) ) { - template< typename Rule, bool = S< Rule >::value, bool = C< Rule >::value > - struct builder; - }; + T::start( in, std::get< sizeof...( Is ) >( t ), std::get< Is >( t )... ); + } - template< template< typename > class S, template< typename > class C > - template< typename Rule > - struct parse_tree< S, C >::builder< Rule, false, false > - : normal< Rule > + template< typename Input, typename... States > + static void start( const Input& in, States&&... st ) noexcept( noexcept( start_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ) ) ) { - }; + start_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ); + } - template< template< typename > class S, template< typename > class C > - template< typename Rule > - struct parse_tree< S, C >::builder< Rule, true, true > - : normal< Rule > + template< typename Input, typename Tuple, std::size_t... Is > + static void success_impl( const Input& in, const Tuple& t, std::index_sequence< Is... > /*unused*/ ) noexcept( noexcept( T::success( in, std::get< sizeof...( Is ) >( t ), std::get< Is >( t )... ) ) ) { - static_assert( sizeof( Rule ) == 0, "error: both S::value and C::value are true" ); - }; + T::success( in, std::get< sizeof...( Is ) >( t ), std::get< Is >( t )... ); + } - template< template< typename > class S, template< typename > class C > - template< typename Rule > - struct parse_tree< S, C >::builder< Rule, true, false > - : normal< Rule > - { - template< typename Input > - static void start( const Input& in, TAOCPP_JSON_PEGTL_NAMESPACE::parse_tree::state& s ) - { - s.emplace_back(); - s.back()->begin = in.iterator(); - } + template< typename Input, typename... States > + static void success( const Input& in, States&&... st ) noexcept( noexcept( success_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ) ) ) + { + success_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ); + } - template< typename Input > - static void success( const Input&, TAOCPP_JSON_PEGTL_NAMESPACE::parse_tree::state& s ) - { - auto n = std::move( s.back() ); - n->id = &typeid( Rule ); - s.pop_back(); - s.back()->children.emplace_back( std::move( n ) ); - } + template< typename Input, typename Tuple, std::size_t... Is > + static void failure_impl( const Input& in, const Tuple& t, std::index_sequence< Is... > /*unused*/ ) noexcept( noexcept( T::failure( in, std::get< sizeof...( Is ) >( t ), std::get< Is >( t )... ) ) ) + { + T::failure( in, std::get< sizeof...( Is ) >( t ), std::get< Is >( t )... ); + } - template< typename Input > - static void failure( const Input&, TAOCPP_JSON_PEGTL_NAMESPACE::parse_tree::state& s ) - { - s.pop_back(); - } - }; + template< typename Input, typename... States > + static void failure( const Input& in, States&&... st ) noexcept( noexcept( failure_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ) ) ) + { + failure_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ); + } - template< template< typename > class S, template< typename > class C > - template< typename Rule > - struct parse_tree< S, C >::builder< Rule, false, true > - : normal< Rule > - { - template< typename Input > - static void start( const Input& in, TAOCPP_JSON_PEGTL_NAMESPACE::parse_tree::state& s ) - { - s.emplace_back(); - s.back()->begin = in.iterator(); - } + template< typename Input, typename Tuple, std::size_t... Is > + static void raise_impl( const Input& in, const Tuple& t, std::index_sequence< Is... > /*unused*/ ) noexcept( noexcept( T::raise( in, std::get< Is >( t )... ) ) ) + { + T::raise( in, std::get< Is >( t )... ); + } - template< typename Input > - static void success( const Input& in, TAOCPP_JSON_PEGTL_NAMESPACE::parse_tree::state& s ) - { - auto n = std::move( s.back() ); - n->id = &typeid( Rule ); - n->end = in.iterator(); - s.pop_back(); - s.back()->children.emplace_back( std::move( n ) ); - } + template< typename Input, typename... States > + static void raise( const Input& in, States&&... st ) noexcept( noexcept( raise_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ) ) ) + { + raise_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ); + } - template< typename Input > - static void failure( const Input&, TAOCPP_JSON_PEGTL_NAMESPACE::parse_tree::state& s ) - { - s.pop_back(); - } - }; + template< template< typename... > class Action, typename Iterator, typename Input, typename Tuple, std::size_t... Is > + static auto apply_impl( const Iterator& begin, const Input& in, const Tuple& t, std::index_sequence< Is... > /*unused*/ ) noexcept( noexcept( T::template apply< Action >( begin, in, std::get< Is >( t )... ) ) ) + -> decltype( T::template apply< Action >( begin, in, std::get< Is >( t )... ) ) + { + return T::template apply< Action >( begin, in, std::get< Is >( t )... ); + } + + template< template< typename... > class Action, typename Iterator, typename Input, typename... States > + static auto apply( const Iterator& begin, const Input& in, States&&... st ) noexcept( noexcept( apply_impl< Action >( begin, in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ) ) ) + -> decltype( apply_impl< Action >( begin, in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ) ) + { + return apply_impl< Action >( begin, in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ); + } - template< typename > - struct default_store_simple : std::false_type + template< template< typename... > class Action, typename Input, typename Tuple, std::size_t... Is > + static auto apply0_impl( const Input& in, const Tuple& t, std::index_sequence< Is... > /*unused*/ ) noexcept( noexcept( T::template apply0< Action >( in, std::get< Is >( t )... ) ) ) + -> decltype( T::template apply0< Action >( in, std::get< Is >( t )... ) ) { - }; + return T::template apply0< Action >( in, std::get< Is >( t )... ); + } - template< typename > - struct default_store_content : std::true_type + template< template< typename... > class Action, typename Input, typename... States > + static auto apply0( const Input& in, States&&... st ) noexcept( noexcept( apply0_impl< Action >( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ) ) ) + -> decltype( apply0_impl< Action >( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ) ) { - }; + return apply0_impl< Action >( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ); + } - } // namespace internal + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + return T::template match< A, M, Action, Control >( in, st... ); + } + }; - namespace parse_tree + template< typename Node, template< typename... > class Selector, template< typename... > class Control > + struct make_control { + template< typename Rule, bool, bool > + struct state_handler; + template< typename Rule > - struct builder - : internal::parse_tree< internal::default_store_simple, internal::default_store_content >::builder< Rule > + using type = control< state_handler< Rule, Selector< Rule >::value, is_leaf< 8, typename Rule::analyze_t, Selector >::value > >; + }; + + template< typename Node, template< typename... > class Selector, template< typename... > class Control > + template< typename Rule > + struct make_control< Node, Selector, Control >::state_handler< Rule, false, true > + : Control< Rule > + { + template< typename Input, typename... States > + static void start( const Input& in, state< Node >& /*unused*/, States&&... st ) noexcept( noexcept( Control< Rule >::start( in, st... ) ) ) + { + Control< Rule >::start( in, st... ); + } + + template< typename Input, typename... States > + static void success( const Input& in, state< Node >& /*unused*/, States&&... st ) noexcept( noexcept( Control< Rule >::success( in, st... ) ) ) + { + Control< Rule >::success( in, st... ); + } + + template< typename Input, typename... States > + static void failure( const Input& in, state< Node >& /*unused*/, States&&... st ) noexcept( noexcept( Control< Rule >::failure( in, st... ) ) ) + { + Control< Rule >::failure( in, st... ); + } + }; + + template< typename Node, template< typename... > class Selector, template< typename... > class Control > + template< typename Rule > + struct make_control< Node, Selector, Control >::state_handler< Rule, false, false > + : Control< Rule > + { + template< typename Input, typename... States > + static void start( const Input& in, state< Node >& state, States&&... st ) + { + Control< Rule >::start( in, st... ); + state.emplace_back(); + } + + template< typename Input, typename... States > + static void success( const Input& in, state< Node >& state, States&&... st ) { - }; + Control< Rule >::success( in, st... ); + auto n = std::move( state.back() ); + state.pop_back(); + for( auto& c : n->children ) { + state.back()->children.emplace_back( std::move( c ) ); + } + } - template< template< typename > class S, template< typename > class C > - struct make_builder + template< typename Input, typename... States > + static void failure( const Input& in, state< Node >& state, States&&... st ) noexcept( noexcept( Control< Rule >::failure( in, st... ) ) ) { - template< typename Rule > - struct type - : internal::parse_tree< S, C >::template builder< Rule > - { - }; - }; + Control< Rule >::failure( in, st... ); + state.pop_back(); + } + }; - } // namespace parse_tree + template< typename Node, template< typename... > class Selector, template< typename... > class Control > + template< typename Rule, bool B > + struct make_control< Node, Selector, Control >::state_handler< Rule, true, B > + : Control< Rule > + { + template< typename Input, typename... States > + static void start( const Input& in, state< Node >& state, States&&... st ) + { + Control< Rule >::start( in, st... ); + state.emplace_back(); + state.back()->template start< Rule >( in, st... ); + } - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Input, typename... States > + static void success( const Input& in, state< Node >& state, States&&... st ) + { + Control< Rule >::success( in, st... ); + auto n = std::move( state.back() ); + state.pop_back(); + n->template success< Rule >( in, st... ); + transform< Selector< Rule > >( in, n, st... ); + if( n ) { + state.back()->emplace_back( std::move( n ), st... ); + } + } + + template< typename Input, typename... States > + static void failure( const Input& in, state< Node >& state, States&&... st ) noexcept( noexcept( Control< Rule >::failure( in, st... ) ) && noexcept( std::declval< Node& >().template failure< Rule >( in, st... ) ) ) + { + Control< Rule >::failure( in, st... ); + state.back()->template failure< Rule >( in, st... ); + state.pop_back(); + } + }; + + template< typename > + using store_all = std::true_type; + + template< typename > + struct selector; + + template< typename T > + struct selector< std::tuple< T > > + { + using type = typename T::type; + }; + + template< typename... Ts > + struct selector< std::tuple< Ts... > > + { + static_assert( sizeof...( Ts ) == 0, "multiple matches found" ); + using type = std::false_type; + }; + + template< typename T > + using selector_t = typename selector< T >::type; + + template< typename Rule, typename Collection > + using select_tuple = std::conditional_t< Collection::template contains< Rule >, std::tuple< Collection >, std::tuple<> >; + + } // namespace internal + + template< typename Rule, typename... Collections > + using selector = internal::selector_t< decltype( std::tuple_cat( std::declval< internal::select_tuple< Rule, Collections > >()... ) ) >; + + template< typename Base > + struct apply + : std::true_type + { + template< typename... Rules > + struct on + { + using type = Base; + + template< typename Rule > + static constexpr bool contains = ( std::is_same_v< Rule, Rules > || ... ); + }; + }; + + struct store_content + : apply< store_content > + {}; + + // some nodes don't need to store their content + struct remove_content + : apply< remove_content > + { + template< typename Node, typename... States > + static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->Node::remove_content( st... ) ) ) + { + n->remove_content( st... ); + } + }; + + // if a node has only one child, replace the node with its child, otherwise remove content + struct fold_one + : apply< fold_one > + { + template< typename Node, typename... States > + static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->children.size(), n->Node::remove_content( st... ) ) ) + { + if( n->children.size() == 1 ) { + n = std::move( n->children.front() ); + } + else { + n->remove_content( st... ); + } + } + }; + + // if a node has no children, discard the node, otherwise remove content + struct discard_empty + : apply< discard_empty > + { + template< typename Node, typename... States > + static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->children.empty(), n->Node::remove_content( st... ) ) ) + { + if( n->children.empty() ) { + n.reset(); + } + else { + n->remove_content( st... ); + } + } + }; + + template< typename Rule, + typename Node, + template< typename... > class Selector = internal::store_all, + template< typename... > class Action = nothing, + template< typename... > class Control = normal, + typename Input, + typename... States > + [[nodiscard]] std::unique_ptr< Node > parse( Input&& in, States&&... st ) + { + internal::state< Node > state; + if( !TAO_JSON_PEGTL_NAMESPACE::parse< Rule, Action, internal::make_control< Node, Selector, Control >::template type >( in, st..., state ) ) { + return nullptr; + } + assert( state.stack.size() == 1 ); + return std::move( state.back() ); + } + + template< typename Rule, + template< typename... > class Selector = internal::store_all, + template< typename... > class Action = nothing, + template< typename... > class Control = normal, + typename Input, + typename... States > + [[nodiscard]] std::unique_ptr< node > parse( Input&& in, States&&... st ) + { + return parse< Rule, node, Selector, Action, Control >( in, st... ); + } -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::parse_tree #endif diff --git a/include/tao/json/external/pegtl/contrib/parse_tree_to_dot.hpp b/include/tao/json/external/pegtl/contrib/parse_tree_to_dot.hpp new file mode 100644 index 00000000..c4f0eee6 --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/parse_tree_to_dot.hpp @@ -0,0 +1,104 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_CONTRIB_PARSE_TREE_TO_DOT_HPP +#define TAO_JSON_PEGTL_CONTRIB_PARSE_TREE_TO_DOT_HPP + +#include +#include +#include + +#include "parse_tree.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::parse_tree +{ + namespace internal + { + inline void escape( std::ostream& os, const std::string_view s ) + { + static const char* h = "0123456789abcdef"; + + const char* p = s.data(); + const char* l = p; + const char* const e = s.data() + s.size(); + while( p != e ) { + const unsigned char c = *p; + if( c == '\\' ) { + os.write( l, p - l ); + l = ++p; + os << "\\\\"; + } + else if( c == '"' ) { + os.write( l, p - l ); + l = ++p; + os << "\\\""; + } + else if( c < 32 ) { + os.write( l, p - l ); + l = ++p; + switch( c ) { + case '\b': + os << "\\b"; + break; + case '\f': + os << "\\f"; + break; + case '\n': + os << "\\n"; + break; + case '\r': + os << "\\r"; + break; + case '\t': + os << "\\t"; + break; + default: + os << "\\u00" << h[ ( c & 0xf0 ) >> 4 ] << h[ c & 0x0f ]; + } + } + else if( c == 127 ) { + os.write( l, p - l ); + l = ++p; + os << "\\u007f"; + } + else { + ++p; + } + } + os.write( l, p - l ); + } + + template< typename Node > + void print_dot_node( std::ostream& os, const Node& n, const std::string_view s ) + { + os << " x" << &n << " [ label=\""; + escape( os, s ); + if( n.has_content() ) { + os << "\\n"; + escape( os, n.string_view() ); + } + os << "\" ]\n"; + if( !n.children.empty() ) { + os << " x" << &n << " -> { "; + for( auto& up : n.children ) { + os << "x" << up.get() << ( ( up == n.children.back() ) ? " }\n" : ", " ); + } + for( auto& up : n.children ) { + print_dot_node( os, *up, up->type ); + } + } + } + + } // namespace internal + + template< typename Node > + void print_dot( std::ostream& os, const Node& n ) + { + os << "digraph parse_tree\n{\n"; + internal::print_dot_node( os, n, n.is_root() ? "ROOT" : n.type ); + os << "}\n"; + } + +} // namespace TAO_JSON_PEGTL_NAMESPACE::parse_tree + +#endif diff --git a/include/tao/json/external/pegtl/contrib/raw_string.hpp b/include/tao/json/external/pegtl/contrib/raw_string.hpp index 842f7d91..1c141531 100644 --- a/include/tao/json/external/pegtl/contrib/raw_string.hpp +++ b/include/tao/json/external/pegtl/contrib/raw_string.hpp @@ -1,247 +1,225 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_RAW_STRING_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_RAW_STRING_HPP +#ifndef TAO_JSON_PEGTL_CONTRIB_RAW_STRING_HPP +#define TAO_JSON_PEGTL_CONTRIB_RAW_STRING_HPP + +#include +#include #include "../apply_mode.hpp" #include "../config.hpp" -#include "../nothing.hpp" #include "../rewind_mode.hpp" -#include "../internal/iterator.hpp" +#include "../internal/bytes.hpp" +#include "../internal/eof.hpp" +#include "../internal/eol.hpp" #include "../internal/must.hpp" +#include "../internal/not_at.hpp" +#include "../internal/seq.hpp" #include "../internal/skip_control.hpp" -#include "../internal/state.hpp" -#include "../internal/until.hpp" +#include "../internal/star.hpp" #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + namespace internal { - namespace internal + template< char Open, char Marker > + struct raw_string_open { - template< char Open, char Marker, char Close, typename... Contents > - struct raw_string_tag; - - template< bool use_apply_void, bool use_apply0_void, typename Tag > - struct raw_string_state_apply; + using analyze_t = analysis::generic< analysis::rule_type::any >; - template< typename Tag > - struct raw_string_state_apply< false, false, Tag > + template< apply_mode A, + rewind_mode, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, std::size_t& marker_size, States&&... /*unused*/ ) noexcept( noexcept( in.size( 0 ) ) ) { - template< template< typename... > class, - template< typename... > class, - typename State, - typename Input, - typename... States > - static void success( const State&, const Input&, States&&... ) - { + if( in.empty() || ( in.peek_char( 0 ) != Open ) ) { + return false; } - }; - - template< typename Tag > - struct raw_string_state_apply< true, false, Tag > - { - template< template< typename... > class Action, - template< typename... > class Control, - typename State, - typename Input, - typename... States > - static void success( const State& s, const Input& in, States&&... st ) - { - Control< Tag >::template apply< Action >( s.iter, in, st... ); + for( std::size_t i = 1; i < in.size( i + 1 ); ++i ) { + switch( const auto c = in.peek_char( i ) ) { + case Open: + marker_size = i + 1; + in.bump_in_this_line( marker_size ); + (void)eol::match( in ); + return true; + case Marker: + break; + default: + return false; + } } - }; + return false; + } + }; - template< typename Tag > - struct raw_string_state_apply< false, true, Tag > - { - template< template< typename... > class Action, - template< typename... > class Control, - typename State, - typename Input, - typename... States > - static void success( const State&, const Input& in, States&&... st ) - { - Control< Tag >::template apply0< Action >( in, st... ); - } - }; + template< char Open, char Marker > + inline constexpr bool skip_control< raw_string_open< Open, Marker > > = true; + + template< char Marker, char Close > + struct at_raw_string_close + { + using analyze_t = analysis::generic< analysis::rule_type::opt >; - template< typename Tag, typename Iterator > - struct raw_string_state + template< apply_mode A, + rewind_mode, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, const std::size_t& marker_size, States&&... /*unused*/ ) noexcept( noexcept( in.size( 0 ) ) ) { - template< typename Input, typename... States > - raw_string_state( const Input&, States&&... ) - { + if( in.size( marker_size ) < marker_size ) { + return false; } - - template< apply_mode A, - rewind_mode, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - void success( Input& in, States&&... st ) const - { - constexpr char use_action = ( A == apply_mode::ACTION ) && ( !is_nothing< Action, Tag >::value ); - constexpr char use_apply_void = use_action && internal::has_apply< Action< Tag >, void, typename Input::action_t, States... >::value; - constexpr char use_apply_bool = use_action && internal::has_apply< Action< Tag >, bool, typename Input::action_t, States... >::value; - constexpr char use_apply0_void = use_action && internal::has_apply0< Action< Tag >, void, States... >::value; - constexpr char use_apply0_bool = use_action && internal::has_apply0< Action< Tag >, bool, States... >::value; - static_assert( use_apply_void + use_apply_bool + use_apply0_void + use_apply0_bool < 2, "more than one apply or apply0 defined" ); - static_assert( !use_action || use_apply_bool || use_apply_void || use_apply0_bool || use_apply0_void, "actions not disabled but no apply or apply0 found" ); - static_assert( use_apply_bool + use_apply0_bool == 0, "actions with bool result not supported in raw_string" ); - raw_string_state_apply< use_apply_void, use_apply0_void, Tag >::template success< Action, Control >( *this, in, st... ); - in.bump_in_this_line( marker_size ); + if( in.peek_char( 0 ) != Close ) { + return false; } - - raw_string_state( const raw_string_state& ) = delete; - void operator=( const raw_string_state& ) = delete; - - Iterator iter; - std::size_t marker_size = 0; - }; - - template< char Open, char Marker > - struct raw_string_open - { - using analyze_t = analysis::generic< analysis::rule_type::ANY >; - - template< apply_mode A, - rewind_mode, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename State > - static bool match( Input& in, State& ls ) - { - if( in.empty() || ( in.peek_char( 0 ) != Open ) ) { + if( in.peek_char( marker_size - 1 ) != Close ) { + return false; + } + for( std::size_t i = 0; i < ( marker_size - 2 ); ++i ) { + if( in.peek_char( i + 1 ) != Marker ) { return false; } - for( std::size_t i = 1; i < in.size( i + 1 ); ++i ) { - switch( const auto c = in.peek_char( i ) ) { - case Open: - ls.marker_size = i + 1; - in.bump( ls.marker_size ); - eol::match( in ); - ls.iter = in.iterator(); - return true; - case Marker: - break; - default: - return false; - } - } - return false; } - }; + return true; + } + }; - template< char Open, char Marker > - struct skip_control< raw_string_open< Open, Marker > > : std::true_type - { - }; + template< char Marker, char Close > + inline constexpr bool skip_control< at_raw_string_close< Marker, Close > > = true; + + template< typename Cond, typename... Rules > + struct raw_string_until; + + template< typename Cond > + struct raw_string_until< Cond > + { + using analyze_t = analysis::generic< analysis::rule_type::seq, star< not_at< Cond >, not_at< eof >, bytes< 1 > >, Cond >; - template< char Marker, char Close > - struct at_raw_string_close + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, const std::size_t& marker_size, States&&... st ) { - using analyze_t = analysis::generic< analysis::rule_type::ANY >; - - template< apply_mode A, - rewind_mode, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename State > - static bool match( Input& in, const State& ls ) - { - if( in.size( ls.marker_size ) < ls.marker_size ) { - return false; - } - if( in.peek_char( 0 ) != Close ) { - return false; - } - if( in.peek_char( ls.marker_size - 1 ) != Close ) { + auto m = in.template mark< M >(); + + while( !Control< Cond >::template match< A, rewind_mode::required, Action, Control >( in, marker_size, st... ) ) { + if( in.empty() ) { return false; } - for( std::size_t i = 0; i < ls.marker_size - 2; ++i ) { - if( in.peek_char( i + 1 ) != Marker ) { - return false; - } - } - return true; + in.bump(); } - }; + return m( true ); + } + }; - template< char Marker, char Close > - struct skip_control< at_raw_string_close< Marker, Close > > : std::true_type - { - }; - - } // namespace internal - - // raw_string matches Lua-style long literals. - // - // The following description was taken from the Lua documentation - // (see http://www.lua.org/docs.html): - // - // - An "opening long bracket of level n" is defined as an opening square - // bracket followed by n equal signs followed by another opening square - // bracket. So, an opening long bracket of level 0 is written as `[[`, - // an opening long bracket of level 1 is written as `[=[`, and so on. - // - A "closing long bracket" is defined similarly; for instance, a closing - // long bracket of level 4 is written as `]====]`. - // - A "long literal" starts with an opening long bracket of any level and - // ends at the first closing long bracket of the same level. It can - // contain any text except a closing bracket of the same level. - // - Literals in this bracketed form can run for several lines, do not - // interpret any escape sequences, and ignore long brackets of any other - // level. - // - For convenience, when the opening long bracket is immediately followed - // by a newline, the newline is not included in the string. - // - // Note that unlike Lua's long literal, a raw_string is customizable to use - // other characters than `[`, `=` and `]` for matching. Also note that Lua - // introduced newline-specific replacements in Lua 5.2, which we do not - // support on the grammar level. - - template< char Open, char Marker, char Close, typename... Contents > - struct raw_string + template< typename Cond, typename... Rules > + struct raw_string_until { - // This is used as a tag to bind an action to the content. - using content = internal::raw_string_tag< Open, Marker, Close, Contents... >; - - // This is used internally. - using open = internal::raw_string_open< Open, Marker >; - - // This is used for error-reporting when a raw string is not closed properly. - using close = internal::until< internal::at_raw_string_close< Marker, Close >, Contents... >; - - using analyze_t = analysis::generic< analysis::rule_type::SEQ, open, internal::must< close > >; + using analyze_t = analysis::generic< analysis::rule_type::seq, star< not_at< Cond >, not_at< eof >, Rules... >, Cond >; template< apply_mode A, rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, + template< typename... > + class Action, + template< typename... > + class Control, typename Input, typename... States > - static bool match( Input& in, States&&... st ) + [[nodiscard]] static bool match( Input& in, const std::size_t& marker_size, States&&... st ) { - using Iterator = typename Input::iterator_t; - internal::raw_string_state< content, Iterator > s( const_cast< const Input& >( in ), st... ); + auto m = in.template mark< M >(); + using m_t = decltype( m ); - if( Control< internal::seq< open, internal::must< close > > >::template match< A, M, Action, Control >( in, s ) ) { - s.template success< A, M, Action, Control >( in, st... ); - return true; + while( !Control< Cond >::template match< A, rewind_mode::required, Action, Control >( in, marker_size, st... ) ) { + if( in.empty() || !( Control< Rules >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) && ... ) ) { + return false; + } } - return false; + return m( true ); } }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Cond, typename... Rules > + inline constexpr bool skip_control< raw_string_until< Cond, Rules... > > = true; + + } // namespace internal + + // raw_string matches Lua-style long literals. + // + // The following description was taken from the Lua documentation + // (see http://www.lua.org/docs.html): + // + // - An "opening long bracket of level n" is defined as an opening square + // bracket followed by n equal signs followed by another opening square + // bracket. So, an opening long bracket of level 0 is written as `[[`, + // an opening long bracket of level 1 is written as `[=[`, and so on. + // - A "closing long bracket" is defined similarly; for instance, a closing + // long bracket of level 4 is written as `]====]`. + // - A "long literal" starts with an opening long bracket of any level and + // ends at the first closing long bracket of the same level. It can + // contain any text except a closing bracket of the same level. + // - Literals in this bracketed form can run for several lines, do not + // interpret any escape sequences, and ignore long brackets of any other + // level. + // - For convenience, when the opening long bracket is eagerly followed + // by a newline, the newline is not included in the string. + // + // Note that unlike Lua's long literal, a raw_string is customizable to use + // other characters than `[`, `=` and `]` for matching. Also note that Lua + // introduced newline-specific replacements in Lua 5.2, which we do not + // support on the grammar level. + + template< char Open, char Marker, char Close, typename... Contents > + struct raw_string + { + // This is used for binding the apply()-method and for error-reporting + // when a raw string is not closed properly or has invalid content. + struct content + : internal::raw_string_until< internal::at_raw_string_close< Marker, Close >, Contents... > + { + }; + + using analyze_t = typename internal::seq< internal::bytes< 1 >, content, internal::bytes< 1 > >::analyze_t; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + std::size_t marker_size; + if( internal::raw_string_open< Open, Marker >::template match< A, M, Action, Control >( in, marker_size, st... ) ) { + // TODO: Do not rely on must<> + (void)internal::must< content >::template match< A, M, Action, Control >( in, marker_size, st... ); + in.bump_in_this_line( marker_size ); + return true; + } + return false; + } + }; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/contrib/remove_first_state.hpp b/include/tao/json/external/pegtl/contrib/remove_first_state.hpp new file mode 100644 index 00000000..fd47d6f5 --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/remove_first_state.hpp @@ -0,0 +1,86 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_CONTRIB_REMOVE_FIRST_STATE_HPP +#define TAO_JSON_PEGTL_CONTRIB_REMOVE_FIRST_STATE_HPP + +#include "../apply_mode.hpp" +#include "../config.hpp" +#include "../rewind_mode.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + // NOTE: The naming of the following classes might still change. + + template< typename Rule, template< typename... > class Control > + struct remove_first_state_after_match + : Control< Rule > + { + template< typename Input, typename State, typename... States > + static void start( const Input& in, State&& /*unused*/, States&&... st ) noexcept( noexcept( Control< Rule >::start( in, st... ) ) ) + { + Control< Rule >::start( in, st... ); + } + + template< typename Input, typename State, typename... States > + static void success( const Input& in, State&& /*unused*/, States&&... st ) noexcept( noexcept( Control< Rule >::success( in, st... ) ) ) + { + Control< Rule >::success( in, st... ); + } + + template< typename Input, typename State, typename... States > + static void failure( const Input& in, State&& /*unused*/, States&&... st ) noexcept( noexcept( Control< Rule >::failure( in, st... ) ) ) + { + Control< Rule >::failure( in, st... ); + } + + template< typename Input, typename State, typename... States > + static void raise( const Input& in, State&& /*unused*/, States&&... st ) + { + Control< Rule >::raise( in, st... ); + } + + template< template< typename... > class Action, + typename Iterator, + typename Input, + typename State, + typename... States > + static auto apply( const Iterator& begin, const Input& in, State&& /*unused*/, States&&... st ) noexcept( noexcept( Control< Rule >::template apply< Action >( begin, in, st... ) ) ) + -> decltype( Control< Rule >::template apply< Action >( begin, in, st... ) ) + { + return Control< Rule >::template apply< Action >( begin, in, st... ); + } + + template< template< typename... > class Action, + typename Input, + typename State, + typename... States > + static auto apply0( const Input& in, State&& /*unused*/, States&&... st ) noexcept( noexcept( Control< Rule >::template apply0< Action >( in, st... ) ) ) + -> decltype( Control< Rule >::template apply0< Action >( in, st... ) ) + { + return Control< Rule >::template apply0< Action >( in, st... ); + } + }; + + template< typename Rule, template< typename... > class Control > + struct remove_self_and_first_state + : Control< Rule > + { + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class, + typename Input, + typename State, + typename... States > + [[nodiscard]] static bool match( Input& in, State&& /*unused*/, States&&... st ) + { + return Control< Rule >::template match< A, M, Action, Control >( in, st... ); + } + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/contrib/rep_one_min_max.hpp b/include/tao/json/external/pegtl/contrib/rep_one_min_max.hpp index a88d66ea..8d7e6b4e 100644 --- a/include/tao/json/external/pegtl/contrib/rep_one_min_max.hpp +++ b/include/tao/json/external/pegtl/contrib/rep_one_min_max.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_REP_ONE_MIN_MAX_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_REP_ONE_MIN_MAX_HPP +#ifndef TAO_JSON_PEGTL_CONTRIB_REP_ONE_MIN_MAX_HPP +#define TAO_JSON_PEGTL_CONTRIB_REP_ONE_MIN_MAX_HPP #include @@ -13,60 +13,50 @@ #include "../internal/bump_help.hpp" #include "../internal/skip_control.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + namespace internal { - namespace internal + template< unsigned Min, unsigned Max, char C > + struct rep_one_min_max { - template< unsigned Min, unsigned Max, char C > - struct rep_one_min_max - { - using analyze_t = analysis::counted< analysis::rule_type::ANY, Min >; + using analyze_t = analysis::counted< analysis::rule_type::any, Min >; - static_assert( Min <= Max, "invalid rep_one_min_max rule (maximum number of repetitions smaller than minimum)" ); + static_assert( Min <= Max ); - template< typename Input > - static bool match( Input& in ) - { - const auto size = in.size( Max + 1 ); - if( size < Min ) { - return false; - } - std::size_t i = 0; - while( ( i < size ) && ( in.peek_char( i ) == C ) ) { - ++i; - } - if( ( Min <= i ) && ( i <= Max ) ) { - bump_help< result_on_found::SUCCESS, Input, char, C >( in, i ); - return true; - } + template< typename Input > + [[nodiscard]] static bool match( Input& in ) + { + const auto size = in.size( Max + 1 ); + if( size < Min ) { return false; } - }; + std::size_t i = 0; + while( ( i < size ) && ( in.peek_char( i ) == C ) ) { + ++i; + } + if( ( Min <= i ) && ( i <= Max ) ) { + bump_help< result_on_found::success, Input, char, C >( in, i ); + return true; + } + return false; + } + }; - template< unsigned Min, unsigned Max, char C > - struct skip_control< rep_one_min_max< Min, Max, C > > : std::true_type - { - }; + template< unsigned Min, unsigned Max, char C > + inline constexpr bool skip_control< rep_one_min_max< Min, Max, C > > = true; - } // namespace internal + } // namespace internal - inline namespace ascii + inline namespace ascii + { + template< unsigned Min, unsigned Max, char C > + struct rep_one_min_max : internal::rep_one_min_max< Min, Max, C > { - template< unsigned Min, unsigned Max, char C > - struct rep_one_min_max : internal::rep_one_min_max< Min, Max, C > - { - }; - - struct ellipsis : internal::rep_one_min_max< 3, 3, '.' > - { - }; - - } // namespace ascii + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + } // namespace ascii -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/contrib/rep_string.hpp b/include/tao/json/external/pegtl/contrib/rep_string.hpp new file mode 100644 index 00000000..74525ca5 --- /dev/null +++ b/include/tao/json/external/pegtl/contrib/rep_string.hpp @@ -0,0 +1,44 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_CONTRIB_REP_STRING_HPP +#define TAO_JSON_PEGTL_CONTRIB_REP_STRING_HPP + +#include + +#include "../config.hpp" +#include "../internal/string.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + namespace internal + { + template< std::size_t, typename, char... > + struct make_rep_string; + + template< char... Ss, char... Cs > + struct make_rep_string< 0, string< Ss... >, Cs... > + { + using type = string< Ss... >; + }; + + template< std::size_t N, char... Ss, char... Cs > + struct make_rep_string< N, string< Ss... >, Cs... > + : make_rep_string< N - 1, string< Ss..., Cs... >, Cs... > + { + }; + + } // namespace internal + + inline namespace ascii + { + template< std::size_t N, char... Cs > + struct rep_string + : internal::make_rep_string< N, internal::string<>, Cs... >::type + {}; + + } // namespace ascii + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/contrib/to_string.hpp b/include/tao/json/external/pegtl/contrib/to_string.hpp index 4472713b..3835d4e1 100644 --- a/include/tao/json/external/pegtl/contrib/to_string.hpp +++ b/include/tao/json/external/pegtl/contrib/to_string.hpp @@ -1,42 +1,38 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_TO_STRING_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_TO_STRING_HPP +#ifndef TAO_JSON_PEGTL_CONTRIB_TO_STRING_HPP +#define TAO_JSON_PEGTL_CONTRIB_TO_STRING_HPP #include #include "../config.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + namespace internal { - namespace internal - { - template< typename > - struct to_string; + template< typename > + struct to_string; - template< template< char... > class X, char... Cs > - struct to_string< X< Cs... > > + template< template< char... > class X, char... Cs > + struct to_string< X< Cs... > > + { + [[nodiscard]] static std::string get() { - static std::string get() - { - const char s[] = { Cs..., 0 }; - return std::string( s, sizeof...( Cs ) ); - } - }; + const char s[] = { Cs..., 0 }; + return std::string( s, sizeof...( Cs ) ); + } + }; - } // namespace internal + } // namespace internal - template< typename T > - std::string to_string() - { - return internal::to_string< T >::get(); - } - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename T > + [[nodiscard]] std::string to_string() + { + return internal::to_string< T >::get(); + } -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/contrib/tracer.hpp b/include/tao/json/external/pegtl/contrib/tracer.hpp index 24558470..56faeba9 100644 --- a/include/tao/json/external/pegtl/contrib/tracer.hpp +++ b/include/tao/json/external/pegtl/contrib/tracer.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_TRACER_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_TRACER_HPP +#ifndef TAO_JSON_PEGTL_CONTRIB_TRACER_HPP +#define TAO_JSON_PEGTL_CONTRIB_TRACER_HPP #include #include @@ -15,97 +15,144 @@ #include "../internal/demangle.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + namespace internal { - struct trace_state + template< typename Input > + void print_current( const Input& in ) { - unsigned rule = 0; - unsigned line = 0; - std::vector< unsigned > stack; - }; + if( in.empty() ) { + std::cerr << ""; + } + else { + const auto c = in.peek_uint8(); + switch( c ) { + case 0: + std::cerr << " = "; + break; + case 9: + std::cerr << " = "; + break; + case 10: + std::cerr << " = "; + break; + case 13: + std::cerr << " = "; + break; + default: + if( isprint( c ) ) { + std::cerr << '\'' << c << "' = "; + } + } + std::cerr << "(char)" << unsigned( c ); + } + } + + } // namespace internal + struct trace_state + { + unsigned rule = 0; + unsigned line = 0; + std::vector< unsigned > stack; + }; + + template< template< typename... > class Base > + struct trace + { template< typename Rule > - struct tracer - : normal< Rule > + struct control + : Base< Rule > { template< typename Input, typename... States > - static void start( const Input& in, States&&... ) + static void start( const Input& in, States&&... st ) { - std::cerr << in.position() << " start " << internal::demangle< Rule >() << std::endl; + std::cerr << in.position() << " start " << internal::demangle< Rule >() << "; current "; + print_current( in ); + std::cerr << std::endl; + Base< Rule >::start( in, st... ); } - template< typename Input > - static void start( const Input& in, trace_state& ts ) + template< typename Input, typename... States > + static void start( const Input& in, trace_state& ts, States&&... st ) { - std::cerr << std::setw( 6 ) << ++ts.line << " " << std::setw( 6 ) << ++ts.rule << " " << in.position() << " start " << internal::demangle< Rule >() << std::endl; + std::cerr << std::setw( 6 ) << ++ts.line << " " << std::setw( 6 ) << ++ts.rule << " "; + start( in, st... ); ts.stack.push_back( ts.rule ); } template< typename Input, typename... States > - static void success( const Input& in, States&&... ) + static void success( const Input& in, States&&... st ) { - std::cerr << in.position() << " success " << internal::demangle< Rule >() << std::endl; + std::cerr << in.position() << " success " << internal::demangle< Rule >() << "; next "; + print_current( in ); + std::cerr << std::endl; + Base< Rule >::success( in, st... ); } - template< typename Input > - static void success( const Input& in, trace_state& ts ) + template< typename Input, typename... States > + static void success( const Input& in, trace_state& ts, States&&... st ) { assert( !ts.stack.empty() ); - std::cerr << std::setw( 6 ) << ++ts.line << " " << std::setw( 6 ) << ts.stack.back() << " " << in.position() << " success " << internal::demangle< Rule >() << std::endl; + std::cerr << std::setw( 6 ) << ++ts.line << " " << std::setw( 6 ) << ts.stack.back() << " "; + success( in, st... ); ts.stack.pop_back(); } template< typename Input, typename... States > - static void failure( const Input& in, States&&... ) + static void failure( const Input& in, States&&... st ) { std::cerr << in.position() << " failure " << internal::demangle< Rule >() << std::endl; + Base< Rule >::failure( in, st... ); } - template< typename Input > - static void failure( const Input& in, trace_state& ts ) + template< typename Input, typename... States > + static void failure( const Input& in, trace_state& ts, States&&... st ) { assert( !ts.stack.empty() ); - std::cerr << std::setw( 6 ) << ++ts.line << " " << std::setw( 6 ) << ts.stack.back() << " " << in.position() << " failure " << internal::demangle< Rule >() << std::endl; + std::cerr << std::setw( 6 ) << ++ts.line << " " << std::setw( 6 ) << ts.stack.back() << " "; + failure( in, st... ); ts.stack.pop_back(); } - template< template< typename... > class Action, typename Input, typename... States > - static void apply0( const Input&, States&&... st ) + template< template< typename... > class Action, typename Iterator, typename Input, typename... States > + static auto apply( const Iterator& begin, const Input& in, States&&... st ) + -> decltype( Base< Rule >::template apply< Action >( begin, in, st... ) ) { - std::cerr << "apply0 " << internal::demangle< Action< Rule > >() << std::endl; - Action< Rule >::apply0( st... ); + std::cerr << in.position() << " apply " << internal::demangle< Rule >() << std::endl; + return Base< Rule >::template apply< Action >( begin, in, st... ); } - template< template< typename... > class Action, typename Input > - static void apply0( const Input&, trace_state& ts ) + template< template< typename... > class Action, typename Iterator, typename Input, typename... States > + static auto apply( const Iterator& begin, const Input& in, trace_state& ts, States&&... st ) + -> decltype( apply< Action >( begin, in, st... ) ) { - std::cerr << std::setw( 6 ) << ++ts.line << " " << internal::demangle< Action< Rule > >() << "::apply0()" << std::endl; - Action< Rule >::apply0( ts ); + std::cerr << std::setw( 6 ) << ++ts.line << " "; + return apply< Action >( begin, in, st... ); } - template< template< typename... > class Action, typename Iterator, typename Input, typename... States > - static void apply( const Iterator& begin, const Input& in, States&&... st ) + template< template< typename... > class Action, typename Input, typename... States > + static auto apply0( const Input& in, States&&... st ) + -> decltype( Base< Rule >::template apply0< Action >( in, st... ) ) { - std::cerr << "apply " << internal::demangle< Action< Rule > >() << std::endl; - using action_t = typename Input::action_t; - const action_t action_input( begin, in ); - Action< Rule >::apply( action_input, st... ); + std::cerr << in.position() << " apply0 " << internal::demangle< Rule >() << std::endl; + return Base< Rule >::template apply0< Action >( in, st... ); } - template< template< typename... > class Action, typename Iterator, typename Input > - static void apply( const Iterator& begin, const Input& in, trace_state& ts ) + template< template< typename... > class Action, typename Input, typename... States > + static auto apply0( const Input& in, trace_state& ts, States&&... st ) + -> decltype( apply0< Action >( in, st... ) ) { - std::cerr << std::setw( 6 ) << ++ts.line << " " << internal::demangle< Action< Rule > >() << "::apply()" << std::endl; - using action_t = typename Input::action_t; - const action_t action_input( begin, in ); - Action< Rule >::apply( action_input, ts ); + std::cerr << std::setw( 6 ) << ++ts.line << " "; + return apply0< Action >( in, st... ); } }; + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Rule > + using tracer = trace< normal >::control< Rule >; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/contrib/unescape.hpp b/include/tao/json/external/pegtl/contrib/unescape.hpp index ff86c6f3..76abe5e7 100644 --- a/include/tao/json/external/pegtl/contrib/unescape.hpp +++ b/include/tao/json/external/pegtl/contrib/unescape.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_UNESCAPE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_UNESCAPE_HPP +#ifndef TAO_JSON_PEGTL_CONTRIB_UNESCAPE_HPP +#define TAO_JSON_PEGTL_CONTRIB_UNESCAPE_HPP #include #include @@ -11,193 +11,189 @@ #include "../config.hpp" #include "../parse_error.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::unescape { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + // Utility functions for the unescape actions. + + [[nodiscard]] inline bool utf8_append_utf32( std::string& string, const unsigned utf32 ) { - namespace unescape - { - struct state - { - std::string unescaped; - }; - - // Utility functions for the unescape actions. - - inline bool utf8_append_utf32( std::string& string, const unsigned utf32 ) - { - if( utf32 <= 0x7f ) { - string += char( utf32 & 0xff ); - return true; - } - if( utf32 <= 0x7ff ) { - char tmp[] = { char( ( ( utf32 & 0x7c0 ) >> 6 ) | 0xc0 ), - char( ( ( utf32 & 0x03f ) ) | 0x80 ) }; - string.append( tmp, sizeof( tmp ) ); - return true; - } - if( utf32 <= 0xffff ) { - char tmp[] = { char( ( ( utf32 & 0xf000 ) >> 12 ) | 0xe0 ), - char( ( ( utf32 & 0x0fc0 ) >> 6 ) | 0x80 ), - char( ( ( utf32 & 0x003f ) ) | 0x80 ) }; - string.append( tmp, sizeof( tmp ) ); - return true; - } - if( utf32 <= 0x10ffff ) { - char tmp[] = { char( ( ( utf32 & 0x1c0000 ) >> 18 ) | 0xf0 ), - char( ( ( utf32 & 0x03f000 ) >> 12 ) | 0x80 ), - char( ( ( utf32 & 0x000fc0 ) >> 6 ) | 0x80 ), - char( ( ( utf32 & 0x00003f ) ) | 0x80 ) }; - string.append( tmp, sizeof( tmp ) ); - return true; - } + if( utf32 <= 0x7f ) { + string += char( utf32 & 0xff ); + return true; + } + if( utf32 <= 0x7ff ) { + char tmp[] = { char( ( ( utf32 & 0x7c0 ) >> 6 ) | 0xc0 ), + char( ( ( utf32 & 0x03f ) ) | 0x80 ) }; + string.append( tmp, sizeof( tmp ) ); + return true; + } + if( utf32 <= 0xffff ) { + if( utf32 >= 0xd800 && utf32 <= 0xdfff ) { + // nope, this is a UTF-16 surrogate return false; } - - // This function MUST only be called for characters matching tao::TAOCPP_JSON_PEGTL_NAMESPACE::ascii::xdigit! - template< typename I > - I unhex_char( const char c ) - { - switch( c ) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return I( c - '0' ); - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - return I( c - 'a' + 10 ); - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - return I( c - 'A' + 10 ); - } + char tmp[] = { char( ( ( utf32 & 0xf000 ) >> 12 ) | 0xe0 ), + char( ( ( utf32 & 0x0fc0 ) >> 6 ) | 0x80 ), + char( ( ( utf32 & 0x003f ) ) | 0x80 ) }; + string.append( tmp, sizeof( tmp ) ); + return true; + } + if( utf32 <= 0x10ffff ) { + char tmp[] = { char( ( ( utf32 & 0x1c0000 ) >> 18 ) | 0xf0 ), + char( ( ( utf32 & 0x03f000 ) >> 12 ) | 0x80 ), + char( ( ( utf32 & 0x000fc0 ) >> 6 ) | 0x80 ), + char( ( ( utf32 & 0x00003f ) ) | 0x80 ) }; + string.append( tmp, sizeof( tmp ) ); + return true; + } + return false; + } + + // This function MUST only be called for characters matching TAO_JSON_PEGTL_NAMESPACE::ascii::xdigit! + template< typename I > + [[nodiscard]] I unhex_char( const char c ) + { + switch( c ) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return I( c - '0' ); + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + return I( c - 'a' + 10 ); + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + return I( c - 'A' + 10 ); + default: // LCOV_EXCL_LINE throw std::runtime_error( "invalid character in unhex" ); // LCOV_EXCL_LINE - } + } + } - template< typename I > - I unhex_string( const char* begin, const char* const end ) - { - I r = 0; - while( begin != end ) { - r <<= 4; - r += unhex_char< I >( *begin++ ); - } - return r; - } + template< typename I > + [[nodiscard]] I unhex_string( const char* begin, const char* end ) + { + I r = 0; + while( begin != end ) { + r <<= 4; + r += unhex_char< I >( *begin++ ); + } + return r; + } - // Actions for common unescape situations. + // Actions for common unescape situations. - struct append_all - { - template< typename Input, typename State > - static void apply( const Input& in, State& st ) - { - st.unescaped.append( in.begin(), in.size() ); - } - }; - - // This action MUST be called for a character matching T which MUST be tao::TAOCPP_JSON_PEGTL_NAMESPACE::one< ... >. - template< typename T, char... Rs > - struct unescape_c - { - template< typename Input, typename State > - static void apply( const Input& in, State& st ) - { - assert( in.size() == 1 ); - st.unescaped += apply_one( *in.begin(), static_cast< const T* >( nullptr ) ); - } + struct append_all + { + template< typename Input > + static void apply( const Input& in, std::string& s ) + { + s.append( in.begin(), in.size() ); + } + }; - template< char... Qs > - static char apply_one( const char c, const one< Qs... >* ) - { - static_assert( sizeof...( Qs ) == sizeof...( Rs ), "size mismatch between escaped characters and their mappings" ); - return apply_two( c, { Qs... }, { Rs... } ); - } + // This action MUST be called for a character matching T which MUST be TAO_JSON_PEGTL_NAMESPACE::one< ... >. + template< typename T, char... Rs > + struct unescape_c + { + template< typename Input > + static void apply( const Input& in, std::string& s ) + { + assert( in.size() == 1 ); + s += apply_one( in, static_cast< const T* >( nullptr ) ); + } - static char apply_two( const char c, const std::initializer_list< char >& q, const std::initializer_list< char >& r ) - { - for( std::size_t i = 0; i < q.size(); ++i ) { - if( *( q.begin() + i ) == c ) { - return *( r.begin() + i ); - } - } - throw std::runtime_error( "invalid character in unescape" ); // LCOV_EXCL_LINE + template< typename Input, char... Qs > + [[nodiscard]] static char apply_one( const Input& in, const one< Qs... >* /*unused*/ ) + { + static_assert( sizeof...( Qs ) == sizeof...( Rs ), "size mismatch between escaped characters and their mappings" ); + return apply_two( in, { Qs... }, { Rs... } ); + } + + template< typename Input > + [[nodiscard]] static char apply_two( const Input& in, const std::initializer_list< char >& q, const std::initializer_list< char >& r ) + { + const char c = *in.begin(); + for( std::size_t i = 0; i < q.size(); ++i ) { + if( *( q.begin() + i ) == c ) { + return *( r.begin() + i ); } - }; - - // See src/example/pegtl/unescape.cpp for why the following two actions - // skip the first input character. They also MUST be called - // with non-empty matched inputs! - - struct unescape_u - { - template< typename Input, typename State > - static void apply( const Input& in, State& st ) - { - assert( !in.empty() ); // First character MUST be present, usually 'u' or 'U'. - if( !utf8_append_utf32( st.unescaped, unhex_string< unsigned >( in.begin() + 1, in.end() ) ) ) { - throw parse_error( "invalid escaped unicode code point", in ); + } + throw parse_error( "invalid character in unescape", in ); // LCOV_EXCL_LINE + } + }; + + // See src/example/pegtl/unescape.cpp for why the following two actions + // skip the first input character. They also MUST be called + // with non-empty matched inputs! + + struct unescape_u + { + template< typename Input > + static void apply( const Input& in, std::string& s ) + { + assert( !in.empty() ); // First character MUST be present, usually 'u' or 'U'. + if( !utf8_append_utf32( s, unhex_string< unsigned >( in.begin() + 1, in.end() ) ) ) { + throw parse_error( "invalid escaped unicode code point", in ); + } + } + }; + + struct unescape_x + { + template< typename Input > + static void apply( const Input& in, std::string& s ) + { + assert( !in.empty() ); // First character MUST be present, usually 'x'. + s += unhex_string< char >( in.begin() + 1, in.end() ); + } + }; + + // The unescape_j action is similar to unescape_u, however unlike + // unescape_u it + // (a) assumes exactly 4 hexdigits per escape sequence, + // (b) accepts multiple consecutive escaped 16-bit values. + // When applied to more than one escape sequence, unescape_j + // translates UTF-16 surrogate pairs in the input into a single + // UTF-8 sequence in s, as required for JSON by RFC 8259. + + struct unescape_j + { + template< typename Input > + static void apply( const Input& in, std::string& s ) + { + assert( ( ( in.size() + 1 ) % 6 ) == 0 ); // Expects multiple "\\u1234", starting with the first "u". + for( const char* b = in.begin() + 1; b < in.end(); b += 6 ) { + const auto c = unhex_string< unsigned >( b, b + 4 ); + if( ( 0xd800 <= c ) && ( c <= 0xdbff ) && ( b + 6 < in.end() ) ) { + const auto d = unhex_string< unsigned >( b + 6, b + 10 ); + if( ( 0xdc00 <= d ) && ( d <= 0xdfff ) ) { + b += 6; + (void)utf8_append_utf32( s, ( ( ( c & 0x03ff ) << 10 ) | ( d & 0x03ff ) ) + 0x10000 ); + continue; } } - }; - - struct unescape_x - { - template< typename Input, typename State > - static void apply( const Input& in, State& st ) - { - assert( !in.empty() ); // First character MUST be present, usually 'x'. - st.unescaped += unhex_string< char >( in.begin() + 1, in.end() ); + if( !utf8_append_utf32( s, c ) ) { + throw parse_error( "invalid escaped unicode code point", in ); } - }; - - // The unescape_j action is similar to unescape_u, however unlike - // unescape_u it - // (a) assumes exactly 4 hexdigits per escape sequence, - // (b) accepts multiple consecutive escaped 16-bit values. - // When applied to more than one escape sequence, unescape_j - // translates UTF-16 surrogate pairs in the input into a single - // UTF-8 sequence in st.unescaped, as required for JSON by RFC 7159. - - struct unescape_j - { - template< typename Input, typename State > - static void apply( const Input& in, State& st ) - { - assert( ( ( in.size() + 1 ) % 6 ) == 0 ); // Expects multiple "\\u1234", starting with the first "u". - for( const char* b = in.begin() + 1; b < in.end(); b += 6 ) { - const auto c = unhex_string< unsigned >( b, b + 4 ); - if( ( 0xd800 <= c ) && ( c <= 0xdbff ) && ( b + 6 < in.end() ) ) { - const auto d = unhex_string< unsigned >( b + 6, b + 10 ); - if( ( 0xdc00 <= d ) && ( d <= 0xdfff ) ) { - b += 6; - utf8_append_utf32( st.unescaped, ( ( ( c & 0x03ff ) << 10 ) | ( d & 0x03ff ) ) + 0x10000 ); - continue; - } - } - utf8_append_utf32( st.unescaped, c ); - } - } - }; - - } // namespace unescape - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + } + } + }; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::unescape #endif diff --git a/include/tao/json/external/pegtl/contrib/uri.hpp b/include/tao/json/external/pegtl/contrib/uri.hpp index 31e1cde5..4a0700b6 100644 --- a/include/tao/json/external/pegtl/contrib/uri.hpp +++ b/include/tao/json/external/pegtl/contrib/uri.hpp @@ -1,8 +1,10 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_URI_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_CONTRIB_URI_HPP +#ifndef TAO_JSON_PEGTL_CONTRIB_URI_HPP +#define TAO_JSON_PEGTL_CONTRIB_URI_HPP + +#include #include "../ascii.hpp" #include "../config.hpp" @@ -10,107 +12,95 @@ #include "../utf8.hpp" #include "abnf.hpp" +#include "integer.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::uri { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace uri - { - // URI grammar according to RFC 3986. - - // This grammar is a direct PEG translation of the original URI grammar. - // It should be considered experimental -- in case of any issues, in particular - // missing rules for attached actions, please contact the developers. - - // Note that this grammar has multiple top-level rules. - - using namespace abnf; + // URI grammar according to RFC 3986. - using dot = one< '.' >; - using colon = one< ':' >; + // This grammar is a direct PEG translation of the original URI grammar. + // It should be considered experimental -- in case of any issues, in particular + // missing rules for attached actions, please contact the developers. - // clang-format off - struct dec_octet : sor< one< '0' >, - rep_min_max< 1, 2, DIGIT >, - seq< one< '1' >, DIGIT, DIGIT >, - seq< one< '2' >, range< '0', '4' >, DIGIT >, - seq< string< '2', '5' >, range< '0', '5' > > > {}; + // Note that this grammar has multiple top-level rules. - struct IPv4address : seq< dec_octet, dot, dec_octet, dot, dec_octet, dot, dec_octet > {}; + using dot = one< '.' >; + using colon = one< ':' >; - struct h16 : rep_min_max< 1, 4, HEXDIG > {}; - struct ls32 : sor< seq< h16, colon, h16 >, IPv4address > {}; + // clang-format off + struct dec_octet : integer::maximum_rule< std::uint8_t > {}; - struct dcolon : two< ':' > {}; + struct IPv4address : seq< dec_octet, dot, dec_octet, dot, dec_octet, dot, dec_octet > {}; - struct IPv6address : sor< seq< rep< 6, h16, colon >, ls32 >, - seq< dcolon, rep< 5, h16, colon >, ls32 >, - seq< opt< h16 >, dcolon, rep< 4, h16, colon >, ls32 >, - seq< opt< h16, opt< colon, h16 > >, dcolon, rep< 3, h16, colon >, ls32 >, - seq< opt< h16, rep_opt< 2, colon, h16 > >, dcolon, rep< 2, h16, colon >, ls32 >, - seq< opt< h16, rep_opt< 3, colon, h16 > >, dcolon, h16, colon, ls32 >, - seq< opt< h16, rep_opt< 4, colon, h16 > >, dcolon, ls32 >, - seq< opt< h16, rep_opt< 5, colon, h16 > >, dcolon, h16 >, - seq< opt< h16, rep_opt< 6, colon, h16 > >, dcolon > > {}; + struct h16 : rep_min_max< 1, 4, abnf::HEXDIG > {}; + struct ls32 : sor< seq< h16, colon, h16 >, IPv4address > {}; - struct gen_delims : one< ':', '/', '?', '#', '[', ']', '@' > {}; - struct sub_delims : one< '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=' > {}; + struct dcolon : two< ':' > {}; - struct unreserved : sor< ALPHA, DIGIT, one< '-', '.', '_', '~' > > {}; - struct reserved : sor< gen_delims, sub_delims > {}; + struct IPv6address : sor< seq< rep< 6, h16, colon >, ls32 >, + seq< dcolon, rep< 5, h16, colon >, ls32 >, + seq< opt< h16 >, dcolon, rep< 4, h16, colon >, ls32 >, + seq< opt< h16, opt< colon, h16 > >, dcolon, rep< 3, h16, colon >, ls32 >, + seq< opt< h16, rep_opt< 2, colon, h16 > >, dcolon, rep< 2, h16, colon >, ls32 >, + seq< opt< h16, rep_opt< 3, colon, h16 > >, dcolon, h16, colon, ls32 >, + seq< opt< h16, rep_opt< 4, colon, h16 > >, dcolon, ls32 >, + seq< opt< h16, rep_opt< 5, colon, h16 > >, dcolon, h16 >, + seq< opt< h16, rep_opt< 6, colon, h16 > >, dcolon > > {}; - struct IPvFuture : if_must< one< 'v' >, plus< HEXDIG >, dot, plus< sor< unreserved, sub_delims, colon > > > {}; + struct gen_delims : one< ':', '/', '?', '#', '[', ']', '@' > {}; + struct sub_delims : one< '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=' > {}; - struct IP_literal : if_must< one< '[' >, sor< IPvFuture, IPv6address >, one< ']' > > {}; + struct unreserved : sor< abnf::ALPHA, abnf::DIGIT, one< '-', '.', '_', '~' > > {}; + struct reserved : sor< gen_delims, sub_delims > {}; - struct pct_encoded : if_must< one< '%' >, HEXDIG, HEXDIG > {}; - struct pchar : sor< unreserved, pct_encoded, sub_delims, one< ':', '@' > > {}; + struct IPvFuture : if_must< one< 'v', 'V' >, plus< abnf::HEXDIG >, dot, plus< sor< unreserved, sub_delims, colon > > > {}; - struct query : star< sor< pchar, one< '/', '?' > > > {}; - struct fragment : star< sor< pchar, one< '/', '?' > > > {}; + struct IP_literal : if_must< one< '[' >, sor< IPvFuture, IPv6address >, one< ']' > > {}; - struct segment : star< pchar > {}; - struct segment_nz : plus< pchar > {}; - struct segment_nz_nc : plus< sor< unreserved, pct_encoded, sub_delims, one< '@' > > > {}; // non-zero-length segment without any colon ":" + struct pct_encoded : if_must< one< '%' >, abnf::HEXDIG, abnf::HEXDIG > {}; + struct pchar : sor< unreserved, pct_encoded, sub_delims, one< ':', '@' > > {}; - struct path_abempty : star< one< '/' >, segment > {}; - struct path_absolute : seq< one< '/' >, opt< segment_nz, star< one< '/' >, segment > > > {}; - struct path_noscheme : seq< segment_nz_nc, star< one< '/' >, segment > > {}; - struct path_rootless : seq< segment_nz, star< one< '/' >, segment > > {}; - struct path_empty : success {}; + struct query : star< sor< pchar, one< '/', '?' > > > {}; + struct fragment : star< sor< pchar, one< '/', '?' > > > {}; - struct path : sor< path_noscheme, // begins with a non-colon segment - path_rootless, // begins with a segment - path_absolute, // begins with "/" but not "//" - path_abempty > {}; // begins with "/" or is empty + struct segment : star< pchar > {}; + struct segment_nz : plus< pchar > {}; + struct segment_nz_nc : plus< sor< unreserved, pct_encoded, sub_delims, one< '@' > > > {}; // non-zero-length segment without any colon ":" - struct reg_name : star< sor< unreserved, pct_encoded, sub_delims > > {}; + struct path_abempty : star< one< '/' >, segment > {}; + struct path_absolute : seq< one< '/' >, opt< segment_nz, star< one< '/' >, segment > > > {}; + struct path_noscheme : seq< segment_nz_nc, star< one< '/' >, segment > > {}; + struct path_rootless : seq< segment_nz, star< one< '/' >, segment > > {}; + struct path_empty : success {}; - struct port : star< DIGIT > {}; - struct host : sor< IP_literal, IPv4address, reg_name > {}; - struct userinfo : star< sor< unreserved, pct_encoded, sub_delims, colon > > {}; - struct authority : seq< opt< userinfo, one< '@' > >, host, opt< colon, port > > {}; + struct path : sor< path_noscheme, // begins with a non-colon segment + path_rootless, // begins with a segment + path_absolute, // begins with "/" but not "//" + path_abempty > {}; // begins with "/" or is empty - struct scheme : seq< ALPHA, star< sor< ALPHA, DIGIT, one< '+', '-', '.' > > > > {}; + struct reg_name : star< sor< unreserved, pct_encoded, sub_delims > > {}; - using dslash = two< '/' >; - using opt_query = opt< if_must< one< '?' >, query > >; - using opt_fragment = opt< if_must< one< '#' >, fragment > >; + struct port : star< abnf::DIGIT > {}; + struct host : sor< IP_literal, IPv4address, reg_name > {}; + struct userinfo : star< sor< unreserved, pct_encoded, sub_delims, colon > > {}; + struct opt_userinfo : opt< userinfo, one< '@' > > {}; + struct authority : seq< opt_userinfo, host, opt< colon, port > > {}; - struct hier_part : sor< if_must< dslash, authority, path_abempty >, path_rootless, path_absolute, path_empty > {}; - struct relative_part : sor< if_must< dslash, authority, path_abempty >, path_noscheme, path_absolute, path_empty > {}; - struct relative_ref : seq< relative_part, opt_query, opt_fragment > {}; + struct scheme : seq< abnf::ALPHA, star< sor< abnf::ALPHA, abnf::DIGIT, one< '+', '-', '.' > > > > {}; - struct URI : seq< scheme, one< ':' >, hier_part, opt_query, opt_fragment > {}; - struct URI_reference : sor< URI, relative_ref > {}; - struct absolute_URI : seq< scheme, one< ':' >, hier_part, opt_query > {}; - // clang-format on + using dslash = two< '/' >; + using opt_query = opt_must< one< '?' >, query >; + using opt_fragment = opt_must< one< '#' >, fragment >; - } // namespace uri + struct hier_part : sor< if_must< dslash, authority, path_abempty >, path_rootless, path_absolute, path_empty > {}; + struct relative_part : sor< if_must< dslash, authority, path_abempty >, path_noscheme, path_absolute, path_empty > {}; + struct relative_ref : seq< relative_part, opt_query, opt_fragment > {}; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct URI : seq< scheme, one< ':' >, hier_part, opt_query, opt_fragment > {}; + struct URI_reference : sor< URI, relative_ref > {}; + struct absolute_URI : seq< scheme, one< ':' >, hier_part, opt_query > {}; + // clang-format on -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::uri #endif diff --git a/include/tao/json/external/pegtl/cstream_input.hpp b/include/tao/json/external/pegtl/cstream_input.hpp index a2852ddc..f330f08e 100644 --- a/include/tao/json/external/pegtl/cstream_input.hpp +++ b/include/tao/json/external/pegtl/cstream_input.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_CSTREAM_INPUT_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_CSTREAM_INPUT_HPP +#ifndef TAO_JSON_PEGTL_CSTREAM_INPUT_HPP +#define TAO_JSON_PEGTL_CSTREAM_INPUT_HPP #include @@ -12,23 +12,22 @@ #include "internal/cstream_reader.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Eol = eol::lf_crlf, std::size_t Chunk = 64 > + struct cstream_input + : buffer_input< internal::cstream_reader, Eol, std::string, Chunk > { - template< typename Eol = eol::lf_crlf > - struct cstream_input - : buffer_input< internal::cstream_reader, Eol > + template< typename T > + cstream_input( std::FILE* in_stream, const std::size_t in_maximum, T&& in_source ) + : buffer_input< internal::cstream_reader, Eol, std::string, Chunk >( std::forward< T >( in_source ), in_maximum, in_stream ) { - template< typename T > - cstream_input( std::FILE* in_stream, const std::size_t in_maximum, T&& in_source ) - : buffer_input< internal::cstream_reader, Eol >( std::forward< T >( in_source ), in_maximum, in_stream ) - { - } - }; + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename... Ts > + cstream_input( Ts&&... )->cstream_input<>; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/disable_action.hpp b/include/tao/json/external/pegtl/disable_action.hpp new file mode 100644 index 00000000..c7dad5bb --- /dev/null +++ b/include/tao/json/external/pegtl/disable_action.hpp @@ -0,0 +1,35 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_DISABLE_ACTION_HPP +#define TAO_JSON_PEGTL_DISABLE_ACTION_HPP + +#include "apply_mode.hpp" +#include "config.hpp" +#include "match.hpp" +#include "nothing.hpp" +#include "rewind_mode.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + struct disable_action + : maybe_nothing + { + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + return TAO_JSON_PEGTL_NAMESPACE::match< Rule, apply_mode::nothing, M, Action, Control >( in, st... ); + } + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/discard_input.hpp b/include/tao/json/external/pegtl/discard_input.hpp new file mode 100644 index 00000000..ccb205c0 --- /dev/null +++ b/include/tao/json/external/pegtl/discard_input.hpp @@ -0,0 +1,37 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_DISCARD_INPUT_HPP +#define TAO_JSON_PEGTL_DISCARD_INPUT_HPP + +#include "apply_mode.hpp" +#include "config.hpp" +#include "match.hpp" +#include "nothing.hpp" +#include "rewind_mode.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + struct discard_input + : maybe_nothing + { + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + const bool result = TAO_JSON_PEGTL_NAMESPACE::match< Rule, A, M, Action, Control >( in, st... ); + in.discard(); + return result; + } + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/discard_input_on_failure.hpp b/include/tao/json/external/pegtl/discard_input_on_failure.hpp new file mode 100644 index 00000000..11c5f9c9 --- /dev/null +++ b/include/tao/json/external/pegtl/discard_input_on_failure.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_DISCARD_INPUT_ON_FAILURE_HPP +#define TAO_JSON_PEGTL_DISCARD_INPUT_ON_FAILURE_HPP + +#include "apply_mode.hpp" +#include "config.hpp" +#include "match.hpp" +#include "nothing.hpp" +#include "rewind_mode.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + struct discard_input_on_failure + : maybe_nothing + { + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + const bool result = TAO_JSON_PEGTL_NAMESPACE::match< Rule, A, M, Action, Control >( in, st... ); + if( !result ) { + in.discard(); + } + return result; + } + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/discard_input_on_success.hpp b/include/tao/json/external/pegtl/discard_input_on_success.hpp new file mode 100644 index 00000000..cb00f5d9 --- /dev/null +++ b/include/tao/json/external/pegtl/discard_input_on_success.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_DISCARD_INPUT_ON_SUCCESS_HPP +#define TAO_JSON_PEGTL_DISCARD_INPUT_ON_SUCCESS_HPP + +#include "apply_mode.hpp" +#include "config.hpp" +#include "match.hpp" +#include "nothing.hpp" +#include "rewind_mode.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + struct discard_input_on_success + : maybe_nothing + { + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + const bool result = TAO_JSON_PEGTL_NAMESPACE::match< Rule, A, M, Action, Control >( in, st... ); + if( result ) { + in.discard(); + } + return result; + } + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/enable_action.hpp b/include/tao/json/external/pegtl/enable_action.hpp new file mode 100644 index 00000000..75134981 --- /dev/null +++ b/include/tao/json/external/pegtl/enable_action.hpp @@ -0,0 +1,35 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_ENABLE_ACTION_HPP +#define TAO_JSON_PEGTL_ENABLE_ACTION_HPP + +#include "apply_mode.hpp" +#include "config.hpp" +#include "match.hpp" +#include "nothing.hpp" +#include "rewind_mode.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + struct enable_action + : maybe_nothing + { + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + return TAO_JSON_PEGTL_NAMESPACE::match< Rule, apply_mode::action, M, Action, Control >( in, st... ); + } + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/eol.hpp b/include/tao/json/external/pegtl/eol.hpp index efc1fc6a..c69ded1b 100644 --- a/include/tao/json/external/pegtl/eol.hpp +++ b/include/tao/json/external/pegtl/eol.hpp @@ -1,23 +1,12 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_EOL_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_EOL_HPP - -#include -#include +#ifndef TAO_JSON_PEGTL_EOL_HPP +#define TAO_JSON_PEGTL_EOL_HPP #include "config.hpp" -namespace tao -{ - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - using eol_pair = std::pair< bool, std::size_t >; - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +#include "internal/eol.hpp" #include "internal/cr_crlf_eol.hpp" #include "internal/cr_eol.hpp" @@ -25,30 +14,24 @@ namespace tao #include "internal/lf_crlf_eol.hpp" #include "internal/lf_eol.hpp" -#include "internal/eol.hpp" - -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + inline namespace ascii { - inline namespace ascii + // this is both a rule and a pseudo-namespace for eol::cr, ... + struct eol : internal::eol { - // this is both a rule and a pseudo-namespace for eol::cr, ... - struct eol : internal::eol - { - // clang-format off - struct cr : internal::cr_eol {}; - struct cr_crlf : internal::cr_crlf_eol {}; - struct crlf : internal::crlf_eol {}; - struct lf : internal::lf_eol {}; - struct lf_crlf : internal::lf_crlf_eol {}; - // clang-format on - }; - - } // namespace ascii - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + // clang-format off + struct cr : internal::cr_eol {}; + struct cr_crlf : internal::cr_crlf_eol {}; + struct crlf : internal::crlf_eol {}; + struct lf : internal::lf_eol {}; + struct lf_crlf : internal::lf_crlf_eol {}; + // clang-format on + }; + + } // namespace ascii + +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/eol_pair.hpp b/include/tao/json/external/pegtl/eol_pair.hpp new file mode 100644 index 00000000..97e3f904 --- /dev/null +++ b/include/tao/json/external/pegtl/eol_pair.hpp @@ -0,0 +1,18 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_EOL_PAIR_HPP +#define TAO_JSON_PEGTL_EOL_PAIR_HPP + +#include +#include + +#include "config.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + using eol_pair = std::pair< bool, std::size_t >; + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/file_input.hpp b/include/tao/json/external/pegtl/file_input.hpp index de8f32d7..2543e412 100644 --- a/include/tao/json/external/pegtl/file_input.hpp +++ b/include/tao/json/external/pegtl/file_input.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_FILE_INPUT_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_FILE_INPUT_HPP +#ifndef TAO_JSON_PEGTL_FILE_INPUT_HPP +#define TAO_JSON_PEGTL_FILE_INPUT_HPP #include "config.hpp" #include "eol.hpp" @@ -12,26 +12,33 @@ #include // Required for _POSIX_MAPPED_FILES #endif -#if defined( _POSIX_MAPPED_FILES ) +#if defined( _POSIX_MAPPED_FILES ) || defined( _WIN32 ) #include "mmap_input.hpp" #else #include "read_input.hpp" #endif -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE +#if defined( _POSIX_MAPPED_FILES ) || defined( _WIN32 ) + template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf > + struct file_input + : mmap_input< P, Eol > { -#if defined( _POSIX_MAPPED_FILES ) - template< tracking_mode P = tracking_mode::IMMEDIATE, typename Eol = eol::lf_crlf > - using file_input = mmap_input< P, Eol >; + using mmap_input< P, Eol >::mmap_input; + }; #else - template< tracking_mode P = tracking_mode::IMMEDIATE, typename Eol = eol::lf_crlf > - using file_input = read_input< P, Eol >; + template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf > + struct file_input + : read_input< P, Eol > + { + using read_input< P, Eol >::read_input; + }; #endif - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename... Ts > + explicit file_input( Ts&&... )->file_input<>; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/input_error.hpp b/include/tao/json/external/pegtl/input_error.hpp deleted file mode 100644 index 9c56a3d3..00000000 --- a/include/tao/json/external/pegtl/input_error.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INPUT_ERROR_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INPUT_ERROR_HPP - -#include -#include -#include - -#include "config.hpp" - -namespace tao -{ - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - struct input_error - : std::runtime_error - { - input_error( const std::string& message, const int in_errorno ) - : std::runtime_error( message ), - errorno( in_errorno ) - { - } - - int errorno; - }; - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao - -#define TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( MESSAGE ) \ - do { \ - const int errorno = errno; \ - std::ostringstream oss; \ - oss << "pegtl: " << MESSAGE << " errno " << errorno; \ - throw tao::TAOCPP_JSON_PEGTL_NAMESPACE::input_error( oss.str(), errorno ); \ - } while( false ) - -#endif diff --git a/include/tao/json/external/pegtl/internal/action.hpp b/include/tao/json/external/pegtl/internal/action.hpp index d93599e4..6f3a6c94 100644 --- a/include/tao/json/external/pegtl/internal/action.hpp +++ b/include/tao/json/external/pegtl/internal/action.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ACTION_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ACTION_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_ACTION_HPP +#define TAO_JSON_PEGTL_INTERNAL_ACTION_HPP #include "../config.hpp" @@ -15,38 +15,30 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< template< typename... > class Action, typename... Rules > + struct action { - namespace internal + using analyze_t = analysis::generic< analysis::rule_type::seq, Rules... >; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) { - template< template< typename... > class Action, typename... Rules > - struct action - { - using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rules... >; - - template< apply_mode A, - rewind_mode M, - template< typename... > class, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - return duseltronik< seq< Rules... >, A, M, Action, Control >::match( in, st... ); - } - }; - - template< template< typename... > class Action, typename... Rules > - struct skip_control< action< Action, Rules... > > : std::true_type - { - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + return duseltronik< seq< Rules... >, A, M, Action, Control >::match( in, st... ); + } + }; + + template< template< typename... > class Action, typename... Rules > + inline constexpr bool skip_control< action< Action, Rules... > > = true; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/action_input.hpp b/include/tao/json/external/pegtl/internal/action_input.hpp index 589cf216..d4efaac4 100644 --- a/include/tao/json/external/pegtl/internal/action_input.hpp +++ b/include/tao/json/external/pegtl/internal/action_input.hpp @@ -1,108 +1,107 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ACTION_INPUT_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ACTION_INPUT_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_ACTION_INPUT_HPP +#define TAO_JSON_PEGTL_INTERNAL_ACTION_INPUT_HPP #include +#include #include +#include #include "iterator.hpp" #include "../config.hpp" #include "../position.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Input > + class action_input { - namespace internal + public: + using input_t = Input; + using iterator_t = typename Input::iterator_t; + + action_input( const iterator_t& in_begin, const Input& in_input ) noexcept + : m_begin( in_begin ), + m_input( in_input ) { - inline const char* begin_c_ptr( const char* p ) noexcept - { - return p; - } + } + + action_input( const action_input& ) = delete; + action_input( action_input&& ) = delete; + + ~action_input() = default; + + action_input& operator=( const action_input& ) = delete; + action_input& operator=( action_input&& ) = delete; + + [[nodiscard]] const iterator_t& iterator() const noexcept + { + return m_begin; + } - inline const char* begin_c_ptr( const iterator& it ) noexcept - { - return it.data; + [[nodiscard]] const Input& input() const noexcept + { + return m_input; + } + + [[nodiscard]] const char* begin() const noexcept + { + if constexpr( std::is_same_v< iterator_t, const char* > ) { + return iterator(); + } + else { + return iterator().data; } + } + + [[nodiscard]] const char* end() const noexcept + { + return input().current(); + } + + [[nodiscard]] bool empty() const noexcept + { + return begin() == end(); + } + + [[nodiscard]] std::size_t size() const noexcept + { + return std::size_t( end() - begin() ); + } + + [[nodiscard]] std::string string() const + { + return std::string( begin(), size() ); + } + + [[nodiscard]] std::string_view string_view() const noexcept + { + return std::string_view( begin(), size() ); + } + + [[nodiscard]] char peek_char( const std::size_t offset = 0 ) const noexcept + { + return begin()[ offset ]; + } + + [[nodiscard]] std::uint8_t peek_uint8( const std::size_t offset = 0 ) const noexcept + { + return static_cast< std::uint8_t >( peek_char( offset ) ); + } + + [[nodiscard]] TAO_JSON_PEGTL_NAMESPACE::position position() const + { + return input().position( iterator() ); // NOTE: Not efficient with lazy inputs. + } + + protected: + const iterator_t m_begin; + const Input& m_input; + }; - template< typename Input > - class action_input - { - public: - using input_t = Input; - using iterator_t = typename Input::iterator_t; - - action_input( const iterator_t& in_begin, const Input& in_input ) noexcept - : m_begin( in_begin ), - m_input( in_input ) - { - } - - action_input( const action_input& ) = delete; - action_input& operator=( const action_input& ) = delete; - - const iterator_t& iterator() const noexcept - { - return m_begin; - } - - const Input& input() const noexcept - { - return m_input; - } - - const char* begin() const noexcept - { - return begin_c_ptr( iterator() ); - } - - const char* end() const noexcept - { - return input().current(); - } - - bool empty() const noexcept - { - return begin() == end(); - } - - std::size_t size() const noexcept - { - return std::size_t( end() - begin() ); - } - - std::string string() const - { - return std::string( begin(), end() ); - } - - char peek_char( const std::size_t offset = 0 ) const noexcept - { - return begin()[ offset ]; - } - - unsigned char peek_byte( const std::size_t offset = 0 ) const noexcept - { - return static_cast< unsigned char >( peek_char( offset ) ); - } - - TAOCPP_JSON_PEGTL_NAMESPACE::position position() const noexcept - { - return input().position( iterator() ); // NOTE: Not efficient with LAZY inputs. - } - - protected: - const iterator_t m_begin; - const Input& m_input; - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/alnum.hpp b/include/tao/json/external/pegtl/internal/alnum.hpp index c8d0738d..7a9821ba 100644 --- a/include/tao/json/external/pegtl/internal/alnum.hpp +++ b/include/tao/json/external/pegtl/internal/alnum.hpp @@ -1,26 +1,18 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ALNUM_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ALNUM_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_ALNUM_HPP +#define TAO_JSON_PEGTL_INTERNAL_ALNUM_HPP #include "../config.hpp" #include "peek_char.hpp" #include "ranges.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - using alnum = ranges< peek_char, 'a', 'z', 'A', 'Z', '0', '9' >; + using alnum = ranges< peek_char, 'a', 'z', 'A', 'Z', '0', '9' >; - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/alpha.hpp b/include/tao/json/external/pegtl/internal/alpha.hpp index a12b8021..fd102025 100644 --- a/include/tao/json/external/pegtl/internal/alpha.hpp +++ b/include/tao/json/external/pegtl/internal/alpha.hpp @@ -1,26 +1,18 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ALPHA_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ALPHA_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_ALPHA_HPP +#define TAO_JSON_PEGTL_INTERNAL_ALPHA_HPP #include "../config.hpp" #include "peek_char.hpp" #include "ranges.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - using alpha = ranges< peek_char, 'a', 'z', 'A', 'Z' >; + using alpha = ranges< peek_char, 'a', 'z', 'A', 'Z' >; - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/always_false.hpp b/include/tao/json/external/pegtl/internal/always_false.hpp new file mode 100644 index 00000000..0193a46d --- /dev/null +++ b/include/tao/json/external/pegtl/internal/always_false.hpp @@ -0,0 +1,21 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_INTERNAL_ALWAYS_FALSE_HPP +#define TAO_JSON_PEGTL_INTERNAL_ALWAYS_FALSE_HPP + +#include "../config.hpp" + +#include + +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ + template< typename... > + struct always_false + : std::false_type + { + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/json/external/pegtl/internal/any.hpp b/include/tao/json/external/pegtl/internal/any.hpp index 8f44b78b..d8174609 100644 --- a/include/tao/json/external/pegtl/internal/any.hpp +++ b/include/tao/json/external/pegtl/internal/any.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ANY_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ANY_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_ANY_HPP +#define TAO_JSON_PEGTL_INTERNAL_ANY_HPP #include "../config.hpp" @@ -11,58 +11,48 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< typename Peek > - struct any; - - template<> - struct any< peek_char > - { - using analyze_t = analysis::generic< analysis::rule_type::ANY >; + template< typename Peek > + struct any; - template< typename Input > - static bool match( Input& in ) - { - if( !in.empty() ) { - in.bump(); - return true; - } - return false; - } - }; + template<> + struct any< peek_char > + { + using analyze_t = analysis::generic< analysis::rule_type::any >; - template< typename Peek > - struct any - { - using analyze_t = analysis::generic< analysis::rule_type::ANY >; + template< typename Input > + [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.empty() ) ) + { + if( !in.empty() ) { + in.bump(); + return true; + } + return false; + } + }; + + template< typename Peek > + struct any + { + using analyze_t = analysis::generic< analysis::rule_type::any >; - template< typename Input > - static bool match( Input& in ) - { - if( !in.empty() ) { - if( const auto t = Peek::peek( in ) ) { - in.bump( t.size ); - return true; - } - } - return false; + template< typename Input > + [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( Peek::max_input_size ) ) ) + { + if( const std::size_t s = in.size( Peek::max_input_size ); s >= Peek::min_input_size ) { + if( const auto t = Peek::peek( in, s ) ) { + in.bump( t.size ); + return true; } - }; - - template< typename Peek > - struct skip_control< any< Peek > > : std::true_type - { - }; - - } // namespace internal + } + return false; + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Peek > + inline constexpr bool skip_control< any< Peek > > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/apply.hpp b/include/tao/json/external/pegtl/internal/apply.hpp index d23c2dc9..392bd6c1 100644 --- a/include/tao/json/external/pegtl/internal/apply.hpp +++ b/include/tao/json/external/pegtl/internal/apply.hpp @@ -1,79 +1,53 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_APPLY_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_APPLY_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_APPLY_HPP +#define TAO_JSON_PEGTL_INTERNAL_APPLY_HPP #include "../config.hpp" +#include "apply_single.hpp" #include "skip_control.hpp" -#include "trivial.hpp" #include "../analysis/counted.hpp" +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename... Actions > + struct apply { - namespace internal + using analyze_t = analysis::counted< analysis::rule_type::any, 0 >; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) { - template< apply_mode A, typename... Actions > - struct apply_impl; - - template< typename... Actions > - struct apply_impl< apply_mode::ACTION, Actions... > - { - template< typename Input, typename... States > - static bool match( Input& in, States&&... st ) - { - using action_t = typename Input::action_t; - const action_t i2( in.iterator(), in ); // No data -- range is from begin to begin. -#ifdef __cpp_fold_expressions - ( Actions::apply( i2, st... ), ... ); -#else - using swallow = bool[]; - (void)swallow{ ( Actions::apply( i2, st... ), true )..., true }; + if constexpr( ( A == apply_mode::action ) && ( sizeof...( Actions ) > 0 ) ) { + using action_t = typename Input::action_t; + const action_t i2( in.iterator(), in ); // No data -- range is from begin to begin. + return ( apply_single< Actions >::match( i2, st... ) && ... ); + } + else { +#if defined( _MSC_VER ) + (void)in; + (void)( (void)st, ... ); #endif - return true; - } - }; - - template< typename... Actions > - struct apply_impl< apply_mode::NOTHING, Actions... > - { - template< typename Input, typename... States > - static bool match( Input&, States&&... ) - { - return true; - } - }; - - template< typename... Actions > - struct apply - { - using analyze_t = analysis::counted< analysis::rule_type::ANY, 0 >; - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - return apply_impl< A, Actions... >::match( in, st... ); - } - }; - - template< typename... Actions > - struct skip_control< apply< Actions... > > : std::true_type - { - }; - - } // namespace internal + return true; + } + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename... Actions > + inline constexpr bool skip_control< apply< Actions... > > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/apply0.hpp b/include/tao/json/external/pegtl/internal/apply0.hpp index c85c7532..37a1eb6c 100644 --- a/include/tao/json/external/pegtl/internal/apply0.hpp +++ b/include/tao/json/external/pegtl/internal/apply0.hpp @@ -1,77 +1,50 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_APPLY0_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_APPLY0_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_APPLY0_HPP +#define TAO_JSON_PEGTL_INTERNAL_APPLY0_HPP #include "../config.hpp" +#include "apply0_single.hpp" #include "skip_control.hpp" -#include "trivial.hpp" #include "../analysis/counted.hpp" +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename... Actions > + struct apply0 { - namespace internal + using analyze_t = analysis::counted< analysis::rule_type::any, 0 >; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& /*unused*/, States&&... st ) { - template< apply_mode A, typename... Actions > - struct apply0_impl; - - template< typename... Actions > - struct apply0_impl< apply_mode::ACTION, Actions... > - { - template< typename... States > - static bool match( States&&... st ) - { -#ifdef __cpp_fold_expressions - ( Actions::apply0( st... ), ... ); -#else - using swallow = bool[]; - (void)swallow{ ( Actions::apply0( st... ), true )..., true }; + if constexpr( A == apply_mode::action ) { + return ( apply0_single< Actions >::match( st... ) && ... ); + } + else { +#if defined( _MSC_VER ) + (void)( (void)st, ... ); #endif - return true; - } - }; - - template< typename... Actions > - struct apply0_impl< apply_mode::NOTHING, Actions... > - { - template< typename... States > - static bool match( States&&... ) - { - return true; - } - }; - - template< typename... Actions > - struct apply0 - { - using analyze_t = analysis::counted< analysis::rule_type::ANY, 0 >; - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input&, States&&... st ) - { - return apply0_impl< A, Actions... >::match( st... ); - } - }; - - template< typename... Actions > - struct skip_control< apply0< Actions... > > : std::true_type - { - }; - - } // namespace internal + return true; + } + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename... Actions > + inline constexpr bool skip_control< apply0< Actions... > > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/apply0_single.hpp b/include/tao/json/external/pegtl/internal/apply0_single.hpp new file mode 100644 index 00000000..3d875bca --- /dev/null +++ b/include/tao/json/external/pegtl/internal/apply0_single.hpp @@ -0,0 +1,34 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_INTERNAL_APPLY0_SINGLE_HPP +#define TAO_JSON_PEGTL_INTERNAL_APPLY0_SINGLE_HPP + +#include "../config.hpp" + +#include + +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ + template< typename Action > + struct apply0_single + { + template< typename... States > + [[nodiscard]] static auto match( States&&... st ) noexcept( noexcept( Action::apply0( st... ) ) ) + -> std::enable_if_t< std::is_same_v< decltype( Action::apply0( st... ) ), void >, bool > + { + Action::apply0( st... ); + return true; + } + + template< typename... States > + [[nodiscard]] static auto match( States&&... st ) noexcept( noexcept( Action::apply0( st... ) ) ) + -> std::enable_if_t< std::is_same_v< decltype( Action::apply0( st... ) ), bool >, bool > + { + return Action::apply0( st... ); + } + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/json/external/pegtl/internal/apply_single.hpp b/include/tao/json/external/pegtl/internal/apply_single.hpp new file mode 100644 index 00000000..f3f1a483 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/apply_single.hpp @@ -0,0 +1,34 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_INTERNAL_APPLY_SINGLE_HPP +#define TAO_JSON_PEGTL_INTERNAL_APPLY_SINGLE_HPP + +#include "../config.hpp" + +#include + +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ + template< typename Action > + struct apply_single + { + template< typename Input, typename... States > + [[nodiscard]] static auto match( const Input& in, States&&... st ) noexcept( noexcept( Action::apply( in, st... ) ) ) + -> std::enable_if_t< std::is_same_v< decltype( Action::apply( in, st... ) ), void >, bool > + { + Action::apply( in, st... ); + return true; + } + + template< typename Input, typename... States > + [[nodiscard]] static auto match( const Input& in, States&&... st ) noexcept( noexcept( Action::apply( in, st... ) ) ) + -> std::enable_if_t< std::is_same_v< decltype( Action::apply( in, st... ) ), bool >, bool > + { + return Action::apply( in, st... ); + } + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/json/external/pegtl/internal/at.hpp b/include/tao/json/external/pegtl/internal/at.hpp index ecf49384..9fbe045e 100644 --- a/include/tao/json/external/pegtl/internal/at.hpp +++ b/include/tao/json/external/pegtl/internal/at.hpp @@ -1,12 +1,11 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_AT_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_AT_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_AT_HPP +#define TAO_JSON_PEGTL_INTERNAL_AT_HPP #include "../config.hpp" -#include "rule_conjunction.hpp" #include "skip_control.hpp" #include "trivial.hpp" @@ -15,48 +14,40 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename... Rules > + struct at; + + template<> + struct at<> + : trivial< true > + { + }; + + template< typename... Rules > + struct at { - namespace internal + using analyze_t = analysis::generic< analysis::rule_type::opt, Rules... >; + + template< apply_mode, + rewind_mode, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) { - template< typename... Rules > - struct at; - - template<> - struct at<> - : trivial< true > - { - }; - - template< typename... Rules > - struct at - { - using analyze_t = analysis::generic< analysis::rule_type::OPT, Rules... >; - - template< apply_mode, - rewind_mode, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - const auto m = in.template mark< rewind_mode::REQUIRED >(); - return rule_conjunction< Rules... >::template match< apply_mode::NOTHING, rewind_mode::ACTIVE, Action, Control >( in, st... ); - } - }; - - template< typename... Rules > - struct skip_control< at< Rules... > > : std::true_type - { - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + const auto m = in.template mark< rewind_mode::required >(); + return ( Control< Rules >::template match< apply_mode::nothing, rewind_mode::active, Action, Control >( in, st... ) && ... ); + } + }; + + template< typename... Rules > + inline constexpr bool skip_control< at< Rules... > > = true; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/bof.hpp b/include/tao/json/external/pegtl/internal/bof.hpp index 0dc54ea4..2b868709 100644 --- a/include/tao/json/external/pegtl/internal/bof.hpp +++ b/include/tao/json/external/pegtl/internal/bof.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BOF_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BOF_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_BOF_HPP +#define TAO_JSON_PEGTL_INTERNAL_BOF_HPP #include "../config.hpp" @@ -10,32 +10,22 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct bof { - namespace internal - { - struct bof - { - using analyze_t = analysis::generic< analysis::rule_type::OPT >; - - template< typename Input > - static bool match( Input& in ) noexcept - { - return in.byte() == 0; - } - }; + using analyze_t = analysis::generic< analysis::rule_type::opt >; - template<> - struct skip_control< bof > : std::true_type - { - }; - - } // namespace internal + template< typename Input > + [[nodiscard]] static bool match( Input& in ) noexcept + { + return in.byte() == 0; + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template<> + inline constexpr bool skip_control< bof > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/bol.hpp b/include/tao/json/external/pegtl/internal/bol.hpp index fa60d229..cbbb7a6d 100644 --- a/include/tao/json/external/pegtl/internal/bol.hpp +++ b/include/tao/json/external/pegtl/internal/bol.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BOL_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BOL_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_BOL_HPP +#define TAO_JSON_PEGTL_INTERNAL_BOL_HPP #include "../config.hpp" @@ -10,32 +10,22 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct bol { - namespace internal - { - struct bol - { - using analyze_t = analysis::generic< analysis::rule_type::OPT >; - - template< typename Input > - static bool match( Input& in ) noexcept - { - return in.byte_in_line() == 0; - } - }; + using analyze_t = analysis::generic< analysis::rule_type::opt >; - template<> - struct skip_control< bol > : std::true_type - { - }; - - } // namespace internal + template< typename Input > + [[nodiscard]] static bool match( Input& in ) noexcept + { + return in.byte_in_line() == 0; + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template<> + inline constexpr bool skip_control< bol > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/bump.hpp b/include/tao/json/external/pegtl/internal/bump.hpp new file mode 100644 index 00000000..86462712 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/bump.hpp @@ -0,0 +1,45 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_INTERNAL_BUMP_HPP +#define TAO_JSON_PEGTL_INTERNAL_BUMP_HPP + +#include "../config.hpp" + +#include "iterator.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ + inline void bump( iterator& iter, const std::size_t count, const int ch ) noexcept + { + for( std::size_t i = 0; i < count; ++i ) { + if( iter.data[ i ] == ch ) { + ++iter.line; + iter.byte_in_line = 0; + } + else { + ++iter.byte_in_line; + } + } + iter.byte += count; + iter.data += count; + } + + inline void bump_in_this_line( iterator& iter, const std::size_t count ) noexcept + { + iter.data += count; + iter.byte += count; + iter.byte_in_line += count; + } + + inline void bump_to_next_line( iterator& iter, const std::size_t count ) noexcept + { + ++iter.line; + iter.byte += count; + iter.byte_in_line = 0; + iter.data += count; + } + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/json/external/pegtl/internal/bump_help.hpp b/include/tao/json/external/pegtl/internal/bump_help.hpp index 2e3fe922..6bb89e42 100644 --- a/include/tao/json/external/pegtl/internal/bump_help.hpp +++ b/include/tao/json/external/pegtl/internal/bump_help.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BUMP_UTIL_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BUMP_UTIL_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_BUMP_HELP_HPP +#define TAO_JSON_PEGTL_INTERNAL_BUMP_HELP_HPP #include #include @@ -11,54 +11,19 @@ #include "result_on_found.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< result_on_found R, typename Input, typename Char, Char... Cs > + void bump_help( Input& in, const std::size_t count ) noexcept { - namespace internal - { - template< bool > - struct bump_impl; - - template<> - struct bump_impl< true > - { - template< typename Input > - static void bump( Input& in, const std::size_t count ) noexcept - { - in.bump( count ); - } - }; - - template<> - struct bump_impl< false > - { - template< typename Input > - static void bump( Input& in, const std::size_t count ) noexcept - { - in.bump_in_this_line( count ); - } - }; - - template< bool... > - struct bool_list - { - }; - - template< bool... Bs > - using bool_and = std::is_same< bool_list< Bs..., true >, bool_list< true, Bs... > >; - - template< result_on_found R, typename Input, typename Char, Char... Cs > - void bump_help( Input& in, const std::size_t count ) noexcept - { - using eol_t = typename Input::eol_t; - bump_impl< bool_and< ( Cs != eol_t::ch )... >::value != bool( R ) >::bump( in, count ); - } - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + if constexpr( ( ( Cs != Input::eol_t::ch ) && ... ) != bool( R ) ) { + in.bump( count ); + } + else { + in.bump_in_this_line( count ); + } + } + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/bump_impl.hpp b/include/tao/json/external/pegtl/internal/bump_impl.hpp deleted file mode 100644 index 85e45c0d..00000000 --- a/include/tao/json/external/pegtl/internal/bump_impl.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BUMP_IMPL_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BUMP_IMPL_HPP - -#include "../config.hpp" - -#include "iterator.hpp" - -namespace tao -{ - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - inline void bump( iterator& iter, const std::size_t count, const int ch ) noexcept - { - for( std::size_t i = 0; i < count; ++i ) { - if( iter.data[ i ] == ch ) { - ++iter.line; - iter.byte_in_line = 0; - } - else { - ++iter.byte_in_line; - } - } - iter.byte += count; - iter.data += count; - } - - inline void bump_in_this_line( iterator& iter, const std::size_t count ) noexcept - { - iter.data += count; - iter.byte += count; - iter.byte_in_line += count; - } - - inline void bump_to_next_line( iterator& iter, const std::size_t count ) noexcept - { - ++iter.line; - iter.byte += count; - iter.byte_in_line = 0; - iter.data += count; - } - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao - -#endif diff --git a/include/tao/json/external/pegtl/internal/bytes.hpp b/include/tao/json/external/pegtl/internal/bytes.hpp index e1b1dac0..72d37b97 100644 --- a/include/tao/json/external/pegtl/internal/bytes.hpp +++ b/include/tao/json/external/pegtl/internal/bytes.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BYTES_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_BYTES_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_BYTES_HPP +#define TAO_JSON_PEGTL_INTERNAL_BYTES_HPP #include "../config.hpp" @@ -10,37 +10,27 @@ #include "../analysis/counted.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< unsigned Num > + struct bytes { - namespace internal + using analyze_t = analysis::counted< analysis::rule_type::any, Num >; + + template< typename Input > + [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( 0 ) ) ) { - template< unsigned Num > - struct bytes - { - using analyze_t = analysis::counted< analysis::rule_type::ANY, Num >; - - template< typename Input > - static bool match( Input& in ) - { - if( in.size( Num ) >= Num ) { - in.bump( Num ); - return true; - } - return false; - } - }; - - template< unsigned Num > - struct skip_control< bytes< Num > > : std::true_type - { - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + if( in.size( Num ) >= Num ) { + in.bump( Num ); + return true; + } + return false; + } + }; + + template< unsigned Num > + inline constexpr bool skip_control< bytes< Num > > = true; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/control.hpp b/include/tao/json/external/pegtl/internal/control.hpp index ee104de7..3e80d98e 100644 --- a/include/tao/json/external/pegtl/internal/control.hpp +++ b/include/tao/json/external/pegtl/internal/control.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CONTROL_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CONTROL_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_CONTROL_HPP +#define TAO_JSON_PEGTL_INTERNAL_CONTROL_HPP #include "../config.hpp" @@ -15,38 +15,30 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< template< typename... > class Control, typename... Rules > + struct control { - namespace internal + using analyze_t = analysis::generic< analysis::rule_type::seq, Rules... >; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) { - template< template< typename... > class Control, typename... Rules > - struct control - { - using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rules... >; - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - return duseltronik< seq< Rules... >, A, M, Action, Control >::match( in, st... ); - } - }; - - template< template< typename... > class Control, typename... Rules > - struct skip_control< control< Control, Rules... > > : std::true_type - { - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + return duseltronik< seq< Rules... >, A, M, Action, Control >::match( in, st... ); + } + }; + + template< template< typename... > class Control, typename... Rules > + inline constexpr bool skip_control< control< Control, Rules... > > = true; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/cr_crlf_eol.hpp b/include/tao/json/external/pegtl/internal/cr_crlf_eol.hpp index 428a30a2..167aead1 100644 --- a/include/tao/json/external/pegtl/internal/cr_crlf_eol.hpp +++ b/include/tao/json/external/pegtl/internal/cr_crlf_eol.hpp @@ -1,39 +1,32 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CR_CRLF_EOL_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CR_CRLF_EOL_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_CR_CRLF_EOL_HPP +#define TAO_JSON_PEGTL_INTERNAL_CR_CRLF_EOL_HPP #include "../config.hpp" +#include "../eol_pair.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct cr_crlf_eol { - namespace internal - { - struct cr_crlf_eol - { - static constexpr int ch = '\r'; + static constexpr int ch = '\r'; - template< typename Input > - static eol_pair match( Input& in ) - { - eol_pair p = { false, in.size( 2 ) }; - if( p.second ) { - if( in.peek_char() == '\r' ) { - in.bump_to_next_line( 1 + ( ( p.second > 1 ) && ( in.peek_char( 1 ) == '\n' ) ) ); - p.first = true; - } - } - return p; + template< typename Input > + [[nodiscard]] static eol_pair match( Input& in ) noexcept( noexcept( in.size( 2 ) ) ) + { + eol_pair p = { false, in.size( 2 ) }; + if( p.second ) { + if( in.peek_char() == '\r' ) { + in.bump_to_next_line( 1 + ( ( p.second > 1 ) && ( in.peek_char( 1 ) == '\n' ) ) ); + p.first = true; } - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + } + return p; + } + }; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/cr_eol.hpp b/include/tao/json/external/pegtl/internal/cr_eol.hpp index 18396fac..3726f434 100644 --- a/include/tao/json/external/pegtl/internal/cr_eol.hpp +++ b/include/tao/json/external/pegtl/internal/cr_eol.hpp @@ -1,39 +1,32 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CR_EOL_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CR_EOL_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_CR_EOL_HPP +#define TAO_JSON_PEGTL_INTERNAL_CR_EOL_HPP #include "../config.hpp" +#include "../eol_pair.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct cr_eol { - namespace internal - { - struct cr_eol - { - static constexpr int ch = '\r'; + static constexpr int ch = '\r'; - template< typename Input > - static eol_pair match( Input& in ) - { - eol_pair p = { false, in.size( 1 ) }; - if( p.second ) { - if( in.peek_char() == '\r' ) { - in.bump_to_next_line(); - p.first = true; - } - } - return p; + template< typename Input > + [[nodiscard]] static eol_pair match( Input& in ) noexcept( noexcept( in.size( 1 ) ) ) + { + eol_pair p = { false, in.size( 1 ) }; + if( p.second ) { + if( in.peek_char() == '\r' ) { + in.bump_to_next_line(); + p.first = true; } - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + } + return p; + } + }; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/crlf_eol.hpp b/include/tao/json/external/pegtl/internal/crlf_eol.hpp index 3b010ff4..6d00310a 100644 --- a/include/tao/json/external/pegtl/internal/crlf_eol.hpp +++ b/include/tao/json/external/pegtl/internal/crlf_eol.hpp @@ -1,39 +1,32 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CRLF_EOL_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CRLF_EOL_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_CRLF_EOL_HPP +#define TAO_JSON_PEGTL_INTERNAL_CRLF_EOL_HPP #include "../config.hpp" +#include "../eol_pair.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct crlf_eol { - namespace internal - { - struct crlf_eol - { - static constexpr int ch = '\n'; + static constexpr int ch = '\n'; - template< typename Input > - static eol_pair match( Input& in ) - { - eol_pair p = { false, in.size( 2 ) }; - if( p.second > 1 ) { - if( ( in.peek_char() == '\r' ) && ( in.peek_char( 1 ) == '\n' ) ) { - in.bump_to_next_line( 2 ); - p.first = true; - } - } - return p; + template< typename Input > + [[nodiscard]] static eol_pair match( Input& in ) noexcept( noexcept( in.size( 2 ) ) ) + { + eol_pair p = { false, in.size( 2 ) }; + if( p.second > 1 ) { + if( ( in.peek_char() == '\r' ) && ( in.peek_char( 1 ) == '\n' ) ) { + in.bump_to_next_line( 2 ); + p.first = true; } - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + } + return p; + } + }; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/cstream_reader.hpp b/include/tao/json/external/pegtl/internal/cstream_reader.hpp index 6e350049..9e639dbe 100644 --- a/include/tao/json/external/pegtl/internal/cstream_reader.hpp +++ b/include/tao/json/external/pegtl/internal/cstream_reader.hpp @@ -1,48 +1,49 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CSTREAM_READER_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CSTREAM_READER_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_CSTREAM_READER_HPP +#define TAO_JSON_PEGTL_INTERNAL_CSTREAM_READER_HPP +#include #include #include +#include + #include "../config.hpp" -#include "../input_error.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct cstream_reader { - namespace internal + explicit cstream_reader( std::FILE* s ) noexcept + : m_cstream( s ) + { + assert( m_cstream != nullptr ); + } + + [[nodiscard]] std::size_t operator()( char* buffer, const std::size_t length ) { - struct cstream_reader - { - explicit cstream_reader( std::FILE* s ) noexcept - : m_cstream( s ) - { - } - - std::size_t operator()( char* buffer, const std::size_t length ) - { - if( const auto r = std::fread( buffer, 1, length, m_cstream ) ) { - return r; - } - if( std::feof( m_cstream ) != 0 ) { - return 0; - } - // Please contact us if you know how to provoke the following exception. - // The example on cppreference.com doesn't work, at least not on macOS. - TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "error in fread() from cstream" ); // LCOV_EXCL_LINE - } - - std::FILE* m_cstream; - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + if( const auto r = std::fread( buffer, 1, length, m_cstream ) ) { + return r; + } + if( std::feof( m_cstream ) != 0 ) { + return 0; + } + + // Please contact us if you know how to provoke the following exception. + // The example on cppreference.com doesn't work, at least not on macOS. + + // LCOV_EXCL_START + const auto ec = std::ferror( m_cstream ); + assert( ec != 0 ); + throw std::system_error( ec, std::system_category(), "fread() failed" ); + // LCOV_EXCL_STOP + } + + std::FILE* m_cstream; + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/cstring_reader.hpp b/include/tao/json/external/pegtl/internal/cstring_reader.hpp index 584ab766..3dbf8e03 100644 --- a/include/tao/json/external/pegtl/internal/cstring_reader.hpp +++ b/include/tao/json/external/pegtl/internal/cstring_reader.hpp @@ -1,49 +1,40 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CSTRING_READER_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_CSTRING_READER_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_CSTRING_READER_HPP +#define TAO_JSON_PEGTL_INTERNAL_CSTRING_READER_HPP #include #include #include "../config.hpp" -#include "../input_error.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct cstring_reader { - namespace internal + explicit cstring_reader( const char* zero_terminated ) noexcept + : m_cstring( zero_terminated ) { - struct cstring_reader - { - explicit cstring_reader( const char* zero_terminated ) noexcept - : m_cstring( zero_terminated ) - { - assert( m_cstring ); - } - - std::size_t operator()( char* buffer, const std::size_t length ) noexcept - { - std::size_t i = 0; - char c; - - while( ( i < length ) && ( ( c = m_cstring[ i ] ) != 0 ) ) { - *buffer++ = c; - ++i; - } - m_cstring += i; - return i; - } - - const char* m_cstring; - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + assert( m_cstring != nullptr ); + } + + [[nodiscard]] std::size_t operator()( char* buffer, const std::size_t length ) noexcept + { + std::size_t i = 0; + char c; + + while( ( i < length ) && ( ( c = m_cstring[ i ] ) != 0 ) ) { + *buffer++ = c; + ++i; + } + m_cstring += i; + return i; + } + + const char* m_cstring; + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/demangle.hpp b/include/tao/json/external/pegtl/internal/demangle.hpp index 6358487b..6562e779 100644 --- a/include/tao/json/external/pegtl/internal/demangle.hpp +++ b/include/tao/json/external/pegtl/internal/demangle.hpp @@ -1,44 +1,140 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DEMANGLE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DEMANGLE_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_DEMANGLE_HPP +#define TAO_JSON_PEGTL_INTERNAL_DEMANGLE_HPP -#include -#include +#include +#include #include "../config.hpp" -#if defined( __GLIBCXX__ ) -#include "demangle_cxxabi.hpp" -#elif defined( __has_include ) -// clang-format off -#if __has_include( ) -// clang-format on -#include "demangle_cxxabi.hpp" +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ +#if defined( __clang__ ) + +#if defined( _LIBCPP_VERSION ) + + template< typename T > + [[nodiscard]] constexpr std::string_view demangle() noexcept + { + constexpr const std::string_view sv = __PRETTY_FUNCTION__; + constexpr const auto begin = sv.find( '=' ); + static_assert( begin != std::string_view::npos ); + return sv.substr( begin + 2, sv.size() - begin - 3 ); + } + #else -#include "demangle_nop.hpp" + + // When using libstdc++ with clang, std::string_view::find is not constexpr :( + template< char C > + constexpr const char* find( const char* p, std::size_t n ) noexcept + { + while( n ) { + if( *p == C ) { + return p; + } + ++p; + --n; + } + return nullptr; + } + + template< typename T > + [[nodiscard]] constexpr std::string_view demangle() noexcept + { + constexpr const std::string_view sv = __PRETTY_FUNCTION__; + constexpr const auto begin = find< '=' >( sv.data(), sv.size() ); + static_assert( begin != nullptr ); + return { begin + 2, sv.data() + sv.size() - begin - 3 }; + } + #endif + +#elif defined( __GNUC__ ) + +#if( __GNUC__ == 7 ) + + // GCC 7 wrongly sometimes disallows __PRETTY_FUNCTION__ in constexpr functions, + // therefore we drop the 'constexpr' and hope for the best. + template< typename T > + [[nodiscard]] std::string_view demangle() noexcept + { + const std::string_view sv = __PRETTY_FUNCTION__; + const auto begin = sv.find( '=' ); + const auto tmp = sv.substr( begin + 2 ); + const auto end = tmp.rfind( ';' ); + return tmp.substr( 0, end ); + } + +#elif( __GNUC__ == 9 ) && ( __GNUC_MINOR__ < 3 ) + + // GCC 9.1 and 9.2 have a bug that leads to truncated __PRETTY_FUNCTION__ names, + // see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91155 + template< typename T > + [[nodiscard]] constexpr std::string_view demangle() noexcept + { + // fallback: requires RTTI, no demangling + return typeid( T ).name(); + } + #else -#include "demangle_nop.hpp" + + template< typename T > + [[nodiscard]] constexpr std::string_view demangle() noexcept + { + constexpr std::string_view sv = __PRETTY_FUNCTION__; + constexpr const auto begin = sv.find( '=' ); + static_assert( begin != std::string_view::npos ); + constexpr const auto tmp = sv.substr( begin + 2 ); + constexpr const auto end = tmp.rfind( ';' ); + static_assert( end != std::string_view::npos ); + return tmp.substr( 0, end ); + } + #endif -namespace tao -{ - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< typename T > - std::string demangle() - { - return demangle( typeid( T ).name() ); - } +#elif defined( _MSC_VER ) + +#if( _MSC_VER < 1920 ) + + template< typename T > + [[nodiscard]] constexpr std::string_view demangle() noexcept + { + const std::string_view sv = __FUNCSIG__; + const auto begin = sv.find( "demangle<" ); + const auto tmp = sv.substr( begin + 9 ); + const auto end = tmp.rfind( '>' ); + return tmp.substr( 0, end ); + } + +#else - } // namespace internal + template< typename T > + [[nodiscard]] constexpr std::string_view demangle() noexcept + { + constexpr std::string_view sv = __FUNCSIG__; + constexpr auto begin = sv.find( "demangle<" ); + static_assert( begin != std::string_view::npos ); + constexpr auto tmp = sv.substr( begin + 9 ); + constexpr auto end = tmp.rfind( '>' ); + static_assert( end != std::string_view::npos ); + return tmp.substr( 0, end ); + } - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE +#endif + +#else + + template< typename T > + [[nodiscard]] constexpr std::string_view demangle() noexcept + { + // fallback: requires RTTI, no demangling + return typeid( T ).name(); + } + +#endif -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/demangle_cxxabi.hpp b/include/tao/json/external/pegtl/internal/demangle_cxxabi.hpp deleted file mode 100644 index d5708e55..00000000 --- a/include/tao/json/external/pegtl/internal/demangle_cxxabi.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DEMANGLE_CXXABI_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DEMANGLE_CXXABI_HPP - -#include -#include -#include -#include - -#include "../config.hpp" - -#include "demangle_sanitise.hpp" - -namespace tao -{ - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - inline std::string demangle( const char* symbol ) - { - const std::unique_ptr< char, decltype( &std::free ) > demangled( abi::__cxa_demangle( symbol, nullptr, nullptr, nullptr ), &std::free ); - if( !demangled ) { - return symbol; - } - std::string result( demangled.get() ); -#ifdef TAOCPP_JSON_PEGTL_PRETTY_DEMANGLE - demangle_sanitise_chars( result ); // LCOV_EXCL_LINE -#endif - return result; - } - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao - -#endif diff --git a/include/tao/json/external/pegtl/internal/demangle_nop.hpp b/include/tao/json/external/pegtl/internal/demangle_nop.hpp deleted file mode 100644 index 00f1fe89..00000000 --- a/include/tao/json/external/pegtl/internal/demangle_nop.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DEMANGLE_NOP_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DEMANGLE_NOP_HPP - -#include - -#include "../config.hpp" - -namespace tao -{ - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - inline std::string demangle( const char* symbol ) - { - return symbol; - } - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao - -#endif diff --git a/include/tao/json/external/pegtl/internal/demangle_sanitise.hpp b/include/tao/json/external/pegtl/internal/demangle_sanitise.hpp deleted file mode 100644 index 30b27534..00000000 --- a/include/tao/json/external/pegtl/internal/demangle_sanitise.hpp +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DEMANGLE_SANITISE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DEMANGLE_SANITISE_HPP - -#include - -#include "../config.hpp" - -namespace tao -{ - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - inline void demangle_sanitise_chars( std::string& s ) - { - std::string::size_type p; - while( ( p = s.find( "(char)" ) ) != std::string::npos ) { - int c = 0; - std::string::size_type q; - for( q = p + 6; ( q < s.size() ) && ( s[ q ] >= '0' ) && ( s[ q ] <= '9' ); ++q ) { - c *= 10; - c += s[ q ] - '0'; - } - if( c == '\'' ) { - s.replace( p, q - p, "'\\''" ); - } - else if( c == '\\' ) { - s.replace( p, q - p, "'\\\\'" ); - } - else if( ( c < 32 ) || ( c > 126 ) ) { - s.replace( p, 6, std::string() ); - } - else { - s.replace( p, q - p, std::string( 1, '\'' ) + char( c ) + '\'' ); - } - } - } - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao - -#endif diff --git a/include/tao/json/external/pegtl/internal/disable.hpp b/include/tao/json/external/pegtl/internal/disable.hpp index 8ddcf6ec..f756dddf 100644 --- a/include/tao/json/external/pegtl/internal/disable.hpp +++ b/include/tao/json/external/pegtl/internal/disable.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DISABLE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DISABLE_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_DISABLE_HPP +#define TAO_JSON_PEGTL_INTERNAL_DISABLE_HPP #include "../config.hpp" @@ -15,38 +15,30 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename... Rules > + struct disable { - namespace internal + using analyze_t = analysis::generic< analysis::rule_type::seq, Rules... >; + + template< apply_mode, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) { - template< typename... Rules > - struct disable - { - using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rules... >; - - template< apply_mode, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - return duseltronik< seq< Rules... >, apply_mode::NOTHING, M, Action, Control >::match( in, st... ); - } - }; - - template< typename... Rules > - struct skip_control< disable< Rules... > > : std::true_type - { - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + return duseltronik< seq< Rules... >, apply_mode::nothing, M, Action, Control >::match( in, st... ); + } + }; + + template< typename... Rules > + inline constexpr bool skip_control< disable< Rules... > > = true; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/discard.hpp b/include/tao/json/external/pegtl/internal/discard.hpp index 9069ed67..38bd4e94 100644 --- a/include/tao/json/external/pegtl/internal/discard.hpp +++ b/include/tao/json/external/pegtl/internal/discard.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DISCARD_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DISCARD_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_DISCARD_HPP +#define TAO_JSON_PEGTL_INTERNAL_DISCARD_HPP #include "../config.hpp" @@ -10,33 +10,24 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct discard { - namespace internal - { - struct discard - { - using analyze_t = analysis::generic< analysis::rule_type::OPT >; - - template< typename Input > - static bool match( Input& in ) - { - in.discard(); - return true; - } - }; + using analyze_t = analysis::generic< analysis::rule_type::opt >; - template<> - struct skip_control< discard > : std::true_type - { - }; - - } // namespace internal + template< typename Input > + [[nodiscard]] static bool match( Input& in ) noexcept + { + static_assert( noexcept( in.discard() ) ); + in.discard(); + return true; + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template<> + inline constexpr bool skip_control< discard > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/dusel_mode.hpp b/include/tao/json/external/pegtl/internal/dusel_mode.hpp index a30aba5a..5d22837a 100644 --- a/include/tao/json/external/pegtl/internal/dusel_mode.hpp +++ b/include/tao/json/external/pegtl/internal/dusel_mode.hpp @@ -1,27 +1,23 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DUSEL_MODE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DUSEL_MODE_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_DUSEL_MODE_HPP +#define TAO_JSON_PEGTL_INTERNAL_DUSEL_MODE_HPP #include "../config.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + enum class dusel_mode : char { - enum class dusel_mode : char - { - NOTHING = 0, - CONTROL = 1, - CONTROL_AND_APPLY_VOID = 2, - CONTROL_AND_APPLY_BOOL = 3, - CONTROL_AND_APPLY0_VOID = 4, - CONTROL_AND_APPLY0_BOOL = 5 - }; + nothing = 0, + control = 1, + control_and_apply_void = 2, + control_and_apply_bool = 3, + control_and_apply0_void = 4, + control_and_apply0_bool = 5 + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/duseltronik.hpp b/include/tao/json/external/pegtl/internal/duseltronik.hpp index 48d8e291..7a02519a 100644 --- a/include/tao/json/external/pegtl/internal/duseltronik.hpp +++ b/include/tao/json/external/pegtl/internal/duseltronik.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DUSELTRONIK_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_DUSELTRONIK_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_DUSELTRONIK_HPP +#define TAO_JSON_PEGTL_INTERNAL_DUSELTRONIK_HPP #include "../apply_mode.hpp" #include "../config.hpp" @@ -10,158 +10,178 @@ #include "dusel_mode.hpp" -namespace tao +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4702 ) +#endif + +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + dusel_mode = dusel_mode::nothing > + struct duseltronik; + + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control > + struct duseltronik< Rule, A, M, Action, Control, dusel_mode::nothing > { - namespace internal + template< typename Input, typename... States > + [[nodiscard]] static auto match( Input& in, States&&... st ) + -> decltype( Rule::template match< A, M, Action, Control >( in, st... ) ) { - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - dusel_mode = dusel_mode::NOTHING > - struct duseltronik; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control > - struct duseltronik< Rule, A, M, Action, Control, dusel_mode::NOTHING > - { - template< typename Input, typename... States > - static auto match( Input& in, States&&... st ) -> decltype( Rule::template match< A, M, Action, Control >( in, st... ), true ) - { - return Rule::template match< A, M, Action, Control >( in, st... ); - } + return Rule::template match< A, M, Action, Control >( in, st... ); + } - // NOTE: The additional "int = 0" is a work-around for missing expression SFINAE in VS2015. + template< typename Input, typename... States, int = 1 > + [[nodiscard]] static auto match( Input& in, States&&... /*unused*/ ) + -> decltype( Rule::match( in ) ) + { + return Rule::match( in ); + } + }; + + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control > + struct duseltronik< Rule, A, M, Action, Control, dusel_mode::control > + { + template< typename Input, typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + Control< Rule >::start( static_cast< const Input& >( in ), st... ); + + if( duseltronik< Rule, A, M, Action, Control, dusel_mode::nothing >::match( in, st... ) ) { + Control< Rule >::success( static_cast< const Input& >( in ), st... ); + return true; + } + Control< Rule >::failure( static_cast< const Input& >( in ), st... ); + return false; + } + }; + + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control > + struct duseltronik< Rule, A, M, Action, Control, dusel_mode::control_and_apply_void > + { + template< typename Input, typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< rewind_mode::required >(); + + Control< Rule >::start( static_cast< const Input& >( in ), st... ); + + if( duseltronik< Rule, A, rewind_mode::active, Action, Control, dusel_mode::nothing >::match( in, st... ) ) { + Control< Rule >::template apply< Action >( m.iterator(), static_cast< const Input& >( in ), st... ); + Control< Rule >::success( static_cast< const Input& >( in ), st... ); + return m( true ); + } + Control< Rule >::failure( static_cast< const Input& >( in ), st... ); + return false; + } + }; + + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control > + struct duseltronik< Rule, A, M, Action, Control, dusel_mode::control_and_apply_bool > + { + template< typename Input, typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< rewind_mode::required >(); - template< typename Input, typename... States, int = 0 > - static auto match( Input& in, States&&... ) -> decltype( Rule::match( in ), true ) - { - return Rule::match( in ); - } - }; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control > - struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL > - { - template< typename Input, typename... States > - static bool match( Input& in, States&&... st ) - { - Control< Rule >::start( const_cast< const Input& >( in ), st... ); - - if( duseltronik< Rule, A, M, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) { - Control< Rule >::success( const_cast< const Input& >( in ), st... ); - return true; - } - Control< Rule >::failure( const_cast< const Input& >( in ), st... ); - return false; - } - }; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control > - struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY_VOID > - { - template< typename Input, typename... States > - static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< rewind_mode::REQUIRED >(); - - Control< Rule >::start( const_cast< const Input& >( in ), st... ); - - if( duseltronik< Rule, A, rewind_mode::ACTIVE, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) { - Control< Rule >::template apply< Action >( m.iterator(), const_cast< const Input& >( in ), st... ); - Control< Rule >::success( const_cast< const Input& >( in ), st... ); - return m( true ); - } - Control< Rule >::failure( const_cast< const Input& >( in ), st... ); - return false; - } - }; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control > - struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY_BOOL > - { - template< typename Input, typename... States > - static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< rewind_mode::REQUIRED >(); - - Control< Rule >::start( const_cast< const Input& >( in ), st... ); - - if( duseltronik< Rule, A, rewind_mode::ACTIVE, Action, Control, dusel_mode::NOTHING >::match( in, st... ) && Control< Rule >::template apply< Action >( m.iterator(), const_cast< const Input& >( in ), st... ) ) { - Control< Rule >::success( const_cast< const Input& >( in ), st... ); - return m( true ); - } - return false; - } - }; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control > - struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY0_VOID > - { - template< typename Input, typename... States > - static bool match( Input& in, States&&... st ) - { - Control< Rule >::start( const_cast< const Input& >( in ), st... ); - - if( duseltronik< Rule, A, M, Action, Control, dusel_mode::NOTHING >::match( in, st... ) ) { - Control< Rule >::template apply0< Action >( const_cast< const Input& >( in ), st... ); - Control< Rule >::success( const_cast< const Input& >( in ), st... ); - return true; - } - Control< Rule >::failure( const_cast< const Input& >( in ), st... ); - return false; - } - }; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control > - struct duseltronik< Rule, A, M, Action, Control, dusel_mode::CONTROL_AND_APPLY0_BOOL > - { - template< typename Input, typename... States > - static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< rewind_mode::REQUIRED >(); - - Control< Rule >::start( const_cast< const Input& >( in ), st... ); - - if( duseltronik< Rule, A, rewind_mode::ACTIVE, Action, Control, dusel_mode::NOTHING >::match( in, st... ) && Control< Rule >::template apply0< Action >( const_cast< const Input& >( in ), st... ) ) { - Control< Rule >::success( const_cast< const Input& >( in ), st... ); - return m( true ); - } - Control< Rule >::failure( const_cast< const Input& >( in ), st... ); - return false; + Control< Rule >::start( static_cast< const Input& >( in ), st... ); + + if( duseltronik< Rule, A, rewind_mode::active, Action, Control, dusel_mode::nothing >::match( in, st... ) ) { + if( Control< Rule >::template apply< Action >( m.iterator(), static_cast< const Input& >( in ), st... ) ) { + Control< Rule >::success( static_cast< const Input& >( in ), st... ); + return m( true ); } - }; + } + Control< Rule >::failure( static_cast< const Input& >( in ), st... ); + return false; + } + }; + + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control > + struct duseltronik< Rule, A, M, Action, Control, dusel_mode::control_and_apply0_void > + { + template< typename Input, typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + Control< Rule >::start( static_cast< const Input& >( in ), st... ); + + if( duseltronik< Rule, A, M, Action, Control, dusel_mode::nothing >::match( in, st... ) ) { + Control< Rule >::template apply0< Action >( static_cast< const Input& >( in ), st... ); + Control< Rule >::success( static_cast< const Input& >( in ), st... ); + return true; + } + Control< Rule >::failure( static_cast< const Input& >( in ), st... ); + return false; + } + }; + + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control > + struct duseltronik< Rule, A, M, Action, Control, dusel_mode::control_and_apply0_bool > + { + template< typename Input, typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< rewind_mode::required >(); - } // namespace internal + Control< Rule >::start( static_cast< const Input& >( in ), st... ); - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + if( duseltronik< Rule, A, rewind_mode::active, Action, Control, dusel_mode::nothing >::match( in, st... ) ) { + if( Control< Rule >::template apply0< Action >( static_cast< const Input& >( in ), st... ) ) { + Control< Rule >::success( static_cast< const Input& >( in ), st... ); + return m( true ); + } + } + Control< Rule >::failure( static_cast< const Input& >( in ), st... ); + return false; + } + }; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif #endif diff --git a/include/tao/json/external/pegtl/internal/enable.hpp b/include/tao/json/external/pegtl/internal/enable.hpp index c4fd0012..f21084bb 100644 --- a/include/tao/json/external/pegtl/internal/enable.hpp +++ b/include/tao/json/external/pegtl/internal/enable.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ENABLE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ENABLE_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_ENABLE_HPP +#define TAO_JSON_PEGTL_INTERNAL_ENABLE_HPP #include "../config.hpp" @@ -15,38 +15,30 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename... Rules > + struct enable { - namespace internal + using analyze_t = analysis::generic< analysis::rule_type::seq, Rules... >; + + template< apply_mode, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) { - template< typename... Rules > - struct enable - { - using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rules... >; - - template< apply_mode, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - return duseltronik< seq< Rules... >, apply_mode::ACTION, M, Action, Control >::match( in, st... ); - } - }; - - template< typename... Rules > - struct skip_control< enable< Rules... > > : std::true_type - { - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + return duseltronik< seq< Rules... >, apply_mode::action, M, Action, Control >::match( in, st... ); + } + }; + + template< typename... Rules > + inline constexpr bool skip_control< enable< Rules... > > = true; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/endian.hpp b/include/tao/json/external/pegtl/internal/endian.hpp new file mode 100644 index 00000000..1d30df5a --- /dev/null +++ b/include/tao/json/external/pegtl/internal/endian.hpp @@ -0,0 +1,62 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_INTERNAL_ENDIAN_HPP +#define TAO_JSON_PEGTL_INTERNAL_ENDIAN_HPP + +#include +#include + +#include "../config.hpp" + +#if defined( _WIN32 ) && !defined( __MINGW32__ ) +#include "endian_win.hpp" +#else +#include "endian_gcc.hpp" +#endif + +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ + template< typename N > + [[nodiscard]] N h_to_be( const N n ) noexcept + { + return N( to_and_from_be< sizeof( N ) >::convert( n ) ); + } + + template< typename N > + [[nodiscard]] N be_to_h( const N n ) noexcept + { + return h_to_be( n ); + } + + template< typename N > + [[nodiscard]] N be_to_h( const void* p ) noexcept + { + N n; + std::memcpy( &n, p, sizeof( n ) ); + return internal::be_to_h( n ); + } + + template< typename N > + [[nodiscard]] N h_to_le( const N n ) noexcept + { + return N( to_and_from_le< sizeof( N ) >::convert( n ) ); + } + + template< typename N > + [[nodiscard]] N le_to_h( const N n ) noexcept + { + return h_to_le( n ); + } + + template< typename N > + [[nodiscard]] N le_to_h( const void* p ) noexcept + { + N n; + std::memcpy( &n, p, sizeof( n ) ); + return internal::le_to_h( n ); + } + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/json/external/pegtl/internal/endian_gcc.hpp b/include/tao/json/external/pegtl/internal/endian_gcc.hpp new file mode 100644 index 00000000..01677898 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/endian_gcc.hpp @@ -0,0 +1,206 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_INTERNAL_ENDIAN_GCC_HPP +#define TAO_JSON_PEGTL_INTERNAL_ENDIAN_GCC_HPP + +#include +#include + +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ +#if !defined( __BYTE_ORDER__ ) +#error No byte order defined! +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + + template< std::size_t S > + struct to_and_from_be + { + template< typename T > + [[nodiscard]] static T convert( const T n ) noexcept + { + return n; + } + }; + + template< std::size_t S > + struct to_and_from_le; + + template<> + struct to_and_from_le< 1 > + { + [[nodiscard]] static std::uint8_t convert( const std::uint8_t n ) noexcept + { + return n; + } + + [[nodiscard]] static std::int8_t convert( const std::int8_t n ) noexcept + { + return n; + } + }; + + template<> + struct to_and_from_le< 2 > + { + [[nodiscard]] static std::int16_t convert( const std::int16_t n ) noexcept + { + return static_cast< std::int16_t >( __builtin_bswap16( static_cast< std::uint16_t >( n ) ) ); + } + + [[nodiscard]] static std::uint16_t convert( const std::uint16_t n ) noexcept + { + return __builtin_bswap16( n ); + } + }; + + template<> + struct to_and_from_le< 4 > + { + [[nodiscard]] static float convert( float n ) noexcept + { + std::uint32_t u; + std::memcpy( &u, &n, 4 ); + u = convert( u ); + std::memcpy( &n, &u, 4 ); + return n; + } + + [[nodiscard]] static std::int32_t convert( const std::int32_t n ) noexcept + { + return static_cast< std::int32_t >( __builtin_bswap32( static_cast< std::uint32_t >( n ) ) ); + } + + [[nodiscard]] static std::uint32_t convert( const std::uint32_t n ) noexcept + { + return __builtin_bswap32( n ); + } + }; + + template<> + struct to_and_from_le< 8 > + { + [[nodiscard]] static double convert( double n ) noexcept + { + std::uint64_t u; + std::memcpy( &u, &n, 8 ); + u = convert( u ); + std::memcpy( &n, &u, 8 ); + return n; + } + + [[nodiscard]] static std::int64_t convert( const std::int64_t n ) noexcept + { + return static_cast< std::int64_t >( __builtin_bswap64( static_cast< std::uint64_t >( n ) ) ); + } + + [[nodiscard]] static std::uint64_t convert( const std::uint64_t n ) noexcept + { + return __builtin_bswap64( n ); + } + }; + +#define TAO_JSON_PEGTL_NATIVE_ORDER be +#define TAO_JSON_PEGTL_NATIVE_UTF16 utf16_be +#define TAO_JSON_PEGTL_NATIVE_UTF32 utf32_be + +#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + + template< std::size_t S > + struct to_and_from_le + { + template< typename T > + [[nodiscard]] static T convert( const T n ) noexcept + { + return n; + } + }; + + template< std::size_t S > + struct to_and_from_be; + + template<> + struct to_and_from_be< 1 > + { + [[nodiscard]] static std::int8_t convert( const std::int8_t n ) noexcept + { + return n; + } + + [[nodiscard]] static std::uint8_t convert( const std::uint8_t n ) noexcept + { + return n; + } + }; + + template<> + struct to_and_from_be< 2 > + { + [[nodiscard]] static std::int16_t convert( const std::int16_t n ) noexcept + { + return static_cast< std::int16_t >( __builtin_bswap16( static_cast< std::uint16_t >( n ) ) ); + } + + [[nodiscard]] static std::uint16_t convert( const std::uint16_t n ) noexcept + { + return __builtin_bswap16( n ); + } + }; + + template<> + struct to_and_from_be< 4 > + { + [[nodiscard]] static float convert( float n ) noexcept + { + std::uint32_t u; + std::memcpy( &u, &n, 4 ); + u = convert( u ); + std::memcpy( &n, &u, 4 ); + return n; + } + + [[nodiscard]] static std::int32_t convert( const std::int32_t n ) noexcept + { + return static_cast< std::int32_t >( __builtin_bswap32( static_cast< std::uint32_t >( n ) ) ); + } + + [[nodiscard]] static std::uint32_t convert( const std::uint32_t n ) noexcept + { + return __builtin_bswap32( n ); + } + }; + + template<> + struct to_and_from_be< 8 > + { + [[nodiscard]] static double convert( double n ) noexcept + { + std::uint64_t u; + std::memcpy( &u, &n, 8 ); + u = convert( u ); + std::memcpy( &n, &u, 8 ); + return n; + } + + [[nodiscard]] static std::int64_t convert( const std::int64_t n ) noexcept + { + return static_cast< std::int64_t >( __builtin_bswap64( static_cast< std::uint64_t >( n ) ) ); + } + + [[nodiscard]] static std::uint64_t convert( const std::uint64_t n ) noexcept + { + return __builtin_bswap64( n ); + } + }; + +#define TAO_JSON_PEGTL_NATIVE_ORDER le +#define TAO_JSON_PEGTL_NATIVE_UTF16 utf16_le +#define TAO_JSON_PEGTL_NATIVE_UTF32 utf32_le + +#else +#error Unknown host byte order! +#endif + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/json/external/pegtl/internal/endian_win.hpp b/include/tao/json/external/pegtl/internal/endian_win.hpp new file mode 100644 index 00000000..4ca5ad77 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/endian_win.hpp @@ -0,0 +1,106 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_INTERNAL_ENDIAN_WIN_HPP +#define TAO_JSON_PEGTL_INTERNAL_ENDIAN_WIN_HPP + +#include +#include +#include + +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ + template< std::size_t S > + struct to_and_from_le + { + template< typename T > + [[nodiscard]] static T convert( const T t ) noexcept + { + return t; + } + }; + + template< std::size_t S > + struct to_and_from_be; + + template<> + struct to_and_from_be< 1 > + { + [[nodiscard]] static std::int8_t convert( const std::int8_t n ) noexcept + { + return n; + } + + [[nodiscard]] static std::uint8_t convert( const std::uint8_t n ) noexcept + { + return n; + } + }; + + template<> + struct to_and_from_be< 2 > + { + [[nodiscard]] static std::int16_t convert( const std::int16_t n ) noexcept + { + return std::int16_t( _byteswap_ushort( std::uint16_t( n ) ) ); + } + + [[nodiscard]] static std::uint16_t convert( const std::uint16_t n ) noexcept + { + return _byteswap_ushort( n ); + } + }; + + template<> + struct to_and_from_be< 4 > + { + [[nodiscard]] static float convert( float n ) noexcept + { + std::uint32_t u; + std::memcpy( &u, &n, 4 ); + u = convert( u ); + std::memcpy( &n, &u, 4 ); + return n; + } + + [[nodiscard]] static std::int32_t convert( const std::int32_t n ) noexcept + { + return std::int32_t( _byteswap_ulong( std::uint32_t( n ) ) ); + } + + [[nodiscard]] static std::uint32_t convert( const std::uint32_t n ) noexcept + { + return _byteswap_ulong( n ); + } + }; + + template<> + struct to_and_from_be< 8 > + { + [[nodiscard]] static double convert( double n ) noexcept + { + std::uint64_t u; + std::memcpy( &u, &n, 8 ); + u = convert( u ); + std::memcpy( &n, &u, 8 ); + return n; + } + + [[nodiscard]] static std::int64_t convert( const std::int64_t n ) noexcept + { + return std::int64_t( _byteswap_uint64( std::uint64_t( n ) ) ); + } + + [[nodiscard]] static std::uint64_t convert( const std::uint64_t n ) noexcept + { + return _byteswap_uint64( n ); + } + }; + +#define TAO_JSON_PEGTL_NATIVE_ORDER le +#define TAO_JSON_PEGTL_NATIVE_UTF16 utf16_le +#define TAO_JSON_PEGTL_NATIVE_UTF32 utf32_le + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/json/external/pegtl/internal/eof.hpp b/include/tao/json/external/pegtl/internal/eof.hpp index 97ab487b..a567efe8 100644 --- a/include/tao/json/external/pegtl/internal/eof.hpp +++ b/include/tao/json/external/pegtl/internal/eof.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_EOF_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_EOF_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_EOF_HPP +#define TAO_JSON_PEGTL_INTERNAL_EOF_HPP #include "../config.hpp" @@ -10,32 +10,22 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct eof { - namespace internal - { - struct eof - { - using analyze_t = analysis::generic< analysis::rule_type::OPT >; - - template< typename Input > - static bool match( Input& in ) - { - return in.empty(); - } - }; + using analyze_t = analysis::generic< analysis::rule_type::opt >; - template<> - struct skip_control< eof > : std::true_type - { - }; - - } // namespace internal + template< typename Input > + [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.empty() ) ) + { + return in.empty(); + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template<> + inline constexpr bool skip_control< eof > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/eol.hpp b/include/tao/json/external/pegtl/internal/eol.hpp index b603edf0..e7478907 100644 --- a/include/tao/json/external/pegtl/internal/eol.hpp +++ b/include/tao/json/external/pegtl/internal/eol.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_EOL_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_EOL_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_EOL_HPP +#define TAO_JSON_PEGTL_INTERNAL_EOL_HPP #include "../config.hpp" @@ -10,33 +10,22 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct eol { - namespace internal - { - struct eol - { - using analyze_t = analysis::generic< analysis::rule_type::ANY >; - - template< typename Input > - static bool match( Input& in ) - { - using eol_t = typename Input::eol_t; - return eol_t::match( in ).first; - } - }; + using analyze_t = analysis::generic< analysis::rule_type::any >; - template<> - struct skip_control< eol > : std::true_type - { - }; - - } // namespace internal + template< typename Input > + [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( Input::eol_t::match( in ) ) ) + { + return Input::eol_t::match( in ).first; + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template<> + inline constexpr bool skip_control< eol > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/eolf.hpp b/include/tao/json/external/pegtl/internal/eolf.hpp index 1e7cf99d..c708a379 100644 --- a/include/tao/json/external/pegtl/internal/eolf.hpp +++ b/include/tao/json/external/pegtl/internal/eolf.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_EOLF_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_EOLF_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_EOLF_HPP +#define TAO_JSON_PEGTL_INTERNAL_EOLF_HPP #include "../config.hpp" @@ -10,34 +10,23 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct eolf { - namespace internal - { - struct eolf - { - using analyze_t = analysis::generic< analysis::rule_type::OPT >; - - template< typename Input > - static bool match( Input& in ) - { - using eol_t = typename Input::eol_t; - const auto p = eol_t::match( in ); - return p.first || ( !p.second ); - } - }; + using analyze_t = analysis::generic< analysis::rule_type::opt >; - template<> - struct skip_control< eolf > : std::true_type - { - }; - - } // namespace internal + template< typename Input > + [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( Input::eol_t::match( in ) ) ) + { + const auto p = Input::eol_t::match( in ); + return p.first || ( !p.second ); + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template<> + inline constexpr bool skip_control< eolf > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/file_mapper.hpp b/include/tao/json/external/pegtl/internal/file_mapper.hpp deleted file mode 100644 index 96dc37fc..00000000 --- a/include/tao/json/external/pegtl/internal/file_mapper.hpp +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_FILE_MAPPER_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_FILE_MAPPER_HPP - -#include -#include - -#include "../config.hpp" - -#include "file_opener.hpp" - -#include "../input_error.hpp" - -namespace tao -{ - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - class file_mapper - { - public: - explicit file_mapper( const char* filename ) - : file_mapper( file_opener( filename ) ) - { - } - - explicit file_mapper( const file_opener& reader ) - : m_size( reader.size() ), - m_data( static_cast< const char* >(::mmap( nullptr, m_size, PROT_READ, MAP_PRIVATE, reader.m_fd, 0 ) ) ) - { - if( m_size && ( intptr_t( m_data ) == -1 ) ) { - TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "unable to mmap() file " << reader.m_source << " descriptor " << reader.m_fd ); - } - } - - ~file_mapper() noexcept - { - ::munmap( const_cast< char* >( m_data ), m_size ); // Legacy C interface requires pointer-to-mutable but does not write through the pointer. - } - - file_mapper( const file_mapper& ) = delete; - void operator=( const file_mapper& ) = delete; - - bool empty() const noexcept - { - return m_size == 0; - } - - std::size_t size() const noexcept - { - return m_size; - } - - using iterator = const char*; - using const_iterator = const char*; - - iterator data() const noexcept - { - return m_data; - } - - iterator begin() const noexcept - { - return m_data; - } - - iterator end() const noexcept - { - return m_data + m_size; - } - - std::string string() const - { - return std::string( m_data, m_size ); - } - - private: - const std::size_t m_size; - const char* const m_data; - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao - -#endif diff --git a/include/tao/json/external/pegtl/internal/file_mapper_posix.hpp b/include/tao/json/external/pegtl/internal/file_mapper_posix.hpp new file mode 100644 index 00000000..5d37f4d0 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/file_mapper_posix.hpp @@ -0,0 +1,83 @@ +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_INTERNAL_FILE_MAPPER_POSIX_HPP +#define TAO_JSON_PEGTL_INTERNAL_FILE_MAPPER_POSIX_HPP + +#include +#include + +#include + +#include "../config.hpp" + +#include "file_opener.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ + class file_mapper + { + public: + explicit file_mapper( const char* filename ) + : file_mapper( file_opener( filename ) ) + { + } + + explicit file_mapper( const file_opener& reader ) + : m_size( reader.size() ), + m_data( static_cast< const char* >( ::mmap( nullptr, m_size, PROT_READ, MAP_PRIVATE, reader.m_fd, 0 ) ) ) + { + if( ( m_size != 0 ) && ( intptr_t( m_data ) == -1 ) ) { + const auto ec = errno; + throw std::system_error( ec, std::system_category(), reader.m_source ); + } + } + + file_mapper( const file_mapper& ) = delete; + file_mapper( file_mapper&& ) = delete; + + ~file_mapper() noexcept + { + // Legacy C interface requires pointer-to-mutable but does not write through the pointer. + ::munmap( const_cast< char* >( m_data ), m_size ); + } + + void operator=( const file_mapper& ) = delete; + void operator=( file_mapper&& ) = delete; + + [[nodiscard]] bool empty() const noexcept + { + return m_size == 0; + } + + [[nodiscard]] std::size_t size() const noexcept + { + return m_size; + } + + using iterator = const char*; + using const_iterator = const char*; + + [[nodiscard]] iterator data() const noexcept + { + return m_data; + } + + [[nodiscard]] iterator begin() const noexcept + { + return m_data; + } + + [[nodiscard]] iterator end() const noexcept + { + return m_data + m_size; + } + + private: + const std::size_t m_size; + const char* const m_data; + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/json/external/pegtl/internal/file_mapper_win32.hpp b/include/tao/json/external/pegtl/internal/file_mapper_win32.hpp new file mode 100644 index 00000000..41880e0f --- /dev/null +++ b/include/tao/json/external/pegtl/internal/file_mapper_win32.hpp @@ -0,0 +1,219 @@ +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_INTERNAL_FILE_MAPPER_WIN32_HPP +#define TAO_JSON_PEGTL_INTERNAL_FILE_MAPPER_WIN32_HPP + +#if !defined( NOMINMAX ) +#define NOMINMAX +#define TAO_JSON_PEGTL_NOMINMAX_WAS_DEFINED +#endif + +#if !defined( WIN32_LEAN_AND_MEAN ) +#define WIN32_LEAN_AND_MEAN +#define TAO_JSON_PEGTL_WIN32_LEAN_AND_MEAN_WAS_DEFINED +#endif + +#include + +#if defined( TAO_JSON_PEGTL_NOMINMAX_WAS_DEFINED ) +#undef NOMINMAX +#undef TAO_JSON_PEGTL_NOMINMAX_WAS_DEFINED +#endif + +#if defined( TAO_JSON_PEGTL_WIN32_LEAN_AND_MEAN_WAS_DEFINED ) +#undef WIN32_LEAN_AND_MEAN +#undef TAO_JSON_PEGTL_WIN32_LEAN_AND_MEAN_WAS_DEFINED +#endif + +#include + +#include "../config.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ + struct win32_file_opener + { + explicit win32_file_opener( const char* filename ) + : m_source( filename ), + m_handle( open() ) + { + } + + win32_file_opener( const win32_file_opener& ) = delete; + win32_file_opener( win32_file_opener&& ) = delete; + + ~win32_file_opener() noexcept + { + ::CloseHandle( m_handle ); + } + + void operator=( const win32_file_opener& ) = delete; + void operator=( win32_file_opener&& ) = delete; + + [[nodiscard]] std::size_t size() const + { + LARGE_INTEGER size; + if( !::GetFileSizeEx( m_handle, &size ) ) { + const auto ec = ::GetLastError(); + throw std::system_error( ec, std::system_category(), std::string( "GetFileSizeEx(): " ) + m_source ); + } + return std::size_t( size.QuadPart ); + } + + const char* const m_source; + const HANDLE m_handle; + + private: + [[nodiscard]] HANDLE open() const + { + SetLastError( 0 ); + std::wstring ws( m_source, m_source + strlen( m_source ) ); + +#if( _WIN32_WINNT >= 0x0602 ) + const HANDLE handle = ::CreateFile2( ws.c_str(), + GENERIC_READ, + FILE_SHARE_READ, + OPEN_EXISTING, + nullptr ); + if( handle != INVALID_HANDLE_VALUE ) { + return handle; + } + const auto ec = ::GetLastError(); + throw std::system_error( ec, std::system_category(), std::string( "CreateFile2(): " ) + m_source ); +#else + const HANDLE handle = ::CreateFileW( ws.c_str(), + GENERIC_READ, + FILE_SHARE_READ, + nullptr, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + nullptr ); + if( handle != INVALID_HANDLE_VALUE ) { + return handle; + } + const auto ec = ::GetLastError(); + throw std::system_error( ec, std::system_category(), std::string( "CreateFileW(): " ) + m_source ); +#endif + } + }; + + struct win32_file_mapper + { + explicit win32_file_mapper( const char* filename ) + : win32_file_mapper( win32_file_opener( filename ) ) + { + } + + explicit win32_file_mapper( const win32_file_opener& reader ) + : m_size( reader.size() ), + m_handle( open( reader ) ) + { + } + + win32_file_mapper( const win32_file_mapper& ) = delete; + win32_file_mapper( win32_file_mapper&& ) = delete; + + ~win32_file_mapper() noexcept + { + ::CloseHandle( m_handle ); + } + + void operator=( const win32_file_mapper& ) = delete; + void operator=( win32_file_mapper&& ) = delete; + + const size_t m_size; + const HANDLE m_handle; + + private: + [[nodiscard]] HANDLE open( const win32_file_opener& reader ) const + { + const uint64_t file_size = reader.size(); + SetLastError( 0 ); + // Use `CreateFileMappingW` because a) we're not specifying a + // mapping name, so the character type is of no consequence, and + // b) it's defined in `memoryapi.h`, unlike + // `CreateFileMappingA`(?!) + const HANDLE handle = ::CreateFileMappingW( reader.m_handle, + nullptr, + PAGE_READONLY, + DWORD( file_size >> 32 ), + DWORD( file_size & 0xffffffff ), + nullptr ); + if( handle != NULL || file_size == 0 ) { + return handle; + } + const auto ec = ::GetLastError(); + throw std::system_error( ec, std::system_category(), std::string( "CreateFileMappingW(): " ) + reader.m_source ); + } + }; + + class file_mapper + { + public: + explicit file_mapper( const char* filename ) + : file_mapper( win32_file_mapper( filename ) ) + { + } + + explicit file_mapper( const win32_file_mapper& mapper ) + : m_size( mapper.m_size ), + m_data( static_cast< const char* >( ::MapViewOfFile( mapper.m_handle, + FILE_MAP_READ, + 0, + 0, + 0 ) ) ) + { + if( ( m_size != 0 ) && ( intptr_t( m_data ) == 0 ) ) { + const auto ec = ::GetLastError(); + throw std::system_error( ec, std::system_category(), "MapViewOfFile()" ); + } + } + + file_mapper( const file_mapper& ) = delete; + file_mapper( file_mapper&& ) = delete; + + ~file_mapper() noexcept + { + ::UnmapViewOfFile( LPCVOID( m_data ) ); + } + + void operator=( const file_mapper& ) = delete; + void operator=( file_mapper&& ) = delete; + + [[nodiscard]] bool empty() const noexcept + { + return m_size == 0; + } + + [[nodiscard]] std::size_t size() const noexcept + { + return m_size; + } + + using iterator = const char*; + using const_iterator = const char*; + + [[nodiscard]] iterator data() const noexcept + { + return m_data; + } + + [[nodiscard]] iterator begin() const noexcept + { + return m_data; + } + + [[nodiscard]] iterator end() const noexcept + { + return m_data + m_size; + } + + private: + const std::size_t m_size; + const char* const m_data; + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/json/external/pegtl/internal/file_opener.hpp b/include/tao/json/external/pegtl/internal/file_opener.hpp index 8a65b9de..00209086 100644 --- a/include/tao/json/external/pegtl/internal/file_opener.hpp +++ b/include/tao/json/external/pegtl/internal/file_opener.hpp @@ -1,70 +1,72 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_FILE_OPENER_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_FILE_OPENER_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_FILE_OPENER_HPP +#define TAO_JSON_PEGTL_INTERNAL_FILE_OPENER_HPP #include #include #include #include +#include #include #include "../config.hpp" -#include "../input_error.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct file_opener { - namespace internal + explicit file_opener( const char* filename ) + : m_source( filename ), + m_fd( open() ) { - struct file_opener - { - explicit file_opener( const char* filename ) - : m_source( filename ), - m_fd( open() ) - { - } + } - ~file_opener() noexcept - { - ::close( m_fd ); - } + file_opener( const file_opener& ) = delete; + file_opener( file_opener&& ) = delete; - file_opener( const file_opener& ) = delete; - void operator=( const file_opener& ) = delete; - - std::size_t size() const - { - struct stat st; - errno = 0; - if(::fstat( m_fd, &st ) < 0 ) { - TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "unable to fstat() file " << m_source << " descriptor " << m_fd ); - } - return std::size_t( st.st_size ); - } + ~file_opener() noexcept + { + ::close( m_fd ); + } - const char* const m_source; - const int m_fd; + void operator=( const file_opener& ) = delete; + void operator=( file_opener&& ) = delete; - private: - int open() const - { - errno = 0; - const int fd = ::open( m_source, O_RDONLY ); - if( fd >= 0 ) { - return fd; - } - TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "unable to open() file " << m_source << " for reading" ); - } - }; + [[nodiscard]] std::size_t size() const + { + struct stat st; + errno = 0; + if( ::fstat( m_fd, &st ) < 0 ) { + const auto ec = errno; + throw std::system_error( ec, std::system_category(), m_source ); + } + return std::size_t( st.st_size ); + } - } // namespace internal + const char* const m_source; + const int m_fd; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + private: + [[nodiscard]] int open() const + { + errno = 0; + const int fd = ::open( m_source, + O_RDONLY +#if defined( O_CLOEXEC ) + | O_CLOEXEC +#endif + ); + if( fd >= 0 ) { + return fd; + } + const auto ec = errno; + throw std::system_error( ec, std::system_category(), m_source ); + } + }; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/file_reader.hpp b/include/tao/json/external/pegtl/internal/file_reader.hpp index d2e25277..92bfd5c5 100644 --- a/include/tao/json/external/pegtl/internal/file_reader.hpp +++ b/include/tao/json/external/pegtl/internal/file_reader.hpp @@ -1,96 +1,114 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_FILE_READER_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_FILE_READER_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_FILE_READER_HPP +#define TAO_JSON_PEGTL_INTERNAL_FILE_READER_HPP #include #include #include +#include #include #include "../config.hpp" -#include "../input_error.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + [[nodiscard]] inline std::FILE* file_open( const char* filename ) { - namespace internal + errno = 0; +#if defined( _MSC_VER ) + std::FILE* file; + if( ::fopen_s( &file, filename, "rb" ) == 0 ) +#elif defined( __MINGW32__ ) + if( auto* file = std::fopen( filename, "rb" ) ) +#else + if( auto* file = std::fopen( filename, "rbe" ) ) +#endif { - struct file_close - { - void operator()( FILE* f ) const - { - std::fclose( f ); - } - }; + return file; + } + const auto ec = errno; + throw std::system_error( ec, std::system_category(), filename ); + } - class file_reader - { - public: - explicit file_reader( const char* filename ) - : m_source( filename ), - m_file( open() ) - { - } + struct file_close + { + void operator()( FILE* f ) const noexcept + { + std::fclose( f ); + } + }; + + class file_reader + { + public: + explicit file_reader( const char* filename ) + : m_source( filename ), + m_file( file_open( m_source ) ) + { + } - file_reader( const file_reader& ) = delete; - void operator=( const file_reader& ) = delete; + file_reader( FILE* file, const char* filename ) noexcept + : m_source( filename ), + m_file( file ) + { + } - std::size_t size() const - { - errno = 0; - if( std::fseek( m_file.get(), 0, SEEK_END ) != 0 ) { - TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "unable to fseek() to end of file " << m_source ); // LCOV_EXCL_LINE - } - errno = 0; - const auto s = std::ftell( m_file.get() ); - if( s < 0 ) { - TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "unable to ftell() file size of file " << m_source ); // LCOV_EXCL_LINE - } - errno = 0; - if( std::fseek( m_file.get(), 0, SEEK_SET ) != 0 ) { - TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "unable to fseek() to beginning of file " << m_source ); // LCOV_EXCL_LINE - } - return std::size_t( s ); - } + file_reader( const file_reader& ) = delete; + file_reader( file_reader&& ) = delete; - std::string read() const - { - std::string nrv; - nrv.resize( size() ); - errno = 0; - if( ( nrv.size() != 0 ) && ( std::fread( &nrv[ 0 ], nrv.size(), 1, m_file.get() ) != 1 ) ) { - TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "unable to fread() file " << m_source << " size " << nrv.size() ); // LCOV_EXCL_LINE - } - return nrv; - } + ~file_reader() = default; - private: - const char* const m_source; - const std::unique_ptr< std::FILE, file_close > m_file; + void operator=( const file_reader& ) = delete; + void operator=( file_reader&& ) = delete; - std::FILE* open() const - { - errno = 0; -#if defined( _MSC_VER ) - std::FILE* file; - if(::fopen_s( &file, m_source, "rb" ) == 0 ) -#else - if( auto* file = std::fopen( m_source, "rb" ) ) -#endif - { - return file; - } - TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "unable to fopen() file " << m_source << " for reading" ); - } - }; + [[nodiscard]] std::size_t size() const + { + errno = 0; + if( std::fseek( m_file.get(), 0, SEEK_END ) != 0 ) { + // LCOV_EXCL_START + const auto ec = errno; + throw std::system_error( ec, std::system_category(), m_source ); + // LCOV_EXCL_STOP + } + errno = 0; + const auto s = std::ftell( m_file.get() ); + if( s < 0 ) { + // LCOV_EXCL_START + const auto ec = errno; + throw std::system_error( ec, std::system_category(), m_source ); + // LCOV_EXCL_STOP + } + errno = 0; + if( std::fseek( m_file.get(), 0, SEEK_SET ) != 0 ) { + // LCOV_EXCL_START + const auto ec = errno; + throw std::system_error( ec, std::system_category(), m_source ); + // LCOV_EXCL_STOP + } + return std::size_t( s ); + } - } // namespace internal + [[nodiscard]] std::string read() const + { + std::string nrv; + nrv.resize( size() ); + errno = 0; + if( !nrv.empty() && ( std::fread( &nrv[ 0 ], nrv.size(), 1, m_file.get() ) != 1 ) ) { + // LCOV_EXCL_START + const auto ec = errno; + throw std::system_error( ec, std::system_category(), m_source ); + // LCOV_EXCL_STOP + } + return nrv; + } - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + private: + const char* const m_source; + const std::unique_ptr< std::FILE, file_close > m_file; + }; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/has_apply.hpp b/include/tao/json/external/pegtl/internal/has_apply.hpp index 47bc99af..93adec68 100644 --- a/include/tao/json/external/pegtl/internal/has_apply.hpp +++ b/include/tao/json/external/pegtl/internal/has_apply.hpp @@ -1,33 +1,25 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_HAS_APPLY_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_HAS_APPLY_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_HAS_APPLY_HPP +#define TAO_JSON_PEGTL_INTERNAL_HAS_APPLY_HPP #include #include "../config.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< typename, typename, typename... > - struct has_apply : std::false_type - { - }; + template< typename, typename, template< typename... > class, typename... > + struct has_apply + : std::false_type + {}; - template< typename A, typename... S > - struct has_apply< A, decltype( A::apply( std::declval< S >()... ) ), S... > : std::true_type - { - }; + template< typename C, template< typename... > class Action, typename... S > + struct has_apply< C, decltype( C::template apply< Action >( std::declval< S >()... ) ), Action, S... > + : std::true_type + {}; - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/has_apply0.hpp b/include/tao/json/external/pegtl/internal/has_apply0.hpp index 35a15eae..2c67c871 100644 --- a/include/tao/json/external/pegtl/internal/has_apply0.hpp +++ b/include/tao/json/external/pegtl/internal/has_apply0.hpp @@ -1,33 +1,25 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_HAS_APPLY0_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_HAS_APPLY0_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_HAS_APPLY0_HPP +#define TAO_JSON_PEGTL_INTERNAL_HAS_APPLY0_HPP #include #include "../config.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< typename, typename, typename... > - struct has_apply0 : std::false_type - { - }; + template< typename, typename, template< typename... > class, typename... > + struct has_apply0 + : std::false_type + {}; - template< typename A, typename... S > - struct has_apply0< A, decltype( A::apply0( std::declval< S >()... ) ), S... > : std::true_type - { - }; + template< typename C, template< typename... > class Action, typename... S > + struct has_apply0< C, decltype( C::template apply0< Action >( std::declval< S >()... ) ), Action, S... > + : std::true_type + {}; - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/has_match.hpp b/include/tao/json/external/pegtl/internal/has_match.hpp new file mode 100644 index 00000000..017901b8 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/has_match.hpp @@ -0,0 +1,56 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_INTERNAL_HAS_MATCH_HPP +#define TAO_JSON_PEGTL_INTERNAL_HAS_MATCH_HPP + +#include +#include + +#include "../apply_mode.hpp" +#include "../config.hpp" +#include "../rewind_mode.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ + template< typename, + typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + struct has_match + : std::false_type + {}; + + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + struct has_match< decltype( (void)Action< Rule >::template match< Rule, A, M, Action, Control >( std::declval< Input& >(), std::declval< States&& >()... ), void() ), Rule, A, M, Action, Control, Input, States... > + : std::true_type + {}; + + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + inline constexpr bool has_match_v = has_match< void, Rule, A, M, Action, Control, Input, States... >::value; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/json/external/pegtl/internal/identifier.hpp b/include/tao/json/external/pegtl/internal/identifier.hpp index 8eed3a40..4e69b9f6 100644 --- a/include/tao/json/external/pegtl/internal/identifier.hpp +++ b/include/tao/json/external/pegtl/internal/identifier.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IDENTIFIER_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IDENTIFIER_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_IDENTIFIER_HPP +#define TAO_JSON_PEGTL_INTERNAL_IDENTIFIER_HPP #include "../config.hpp" @@ -11,20 +11,12 @@ #include "seq.hpp" #include "star.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - using identifier_first = ranges< peek_char, 'a', 'z', 'A', 'Z', '_' >; - using identifier_other = ranges< peek_char, 'a', 'z', 'A', 'Z', '0', '9', '_' >; - using identifier = seq< identifier_first, star< identifier_other > >; + using identifier_first = ranges< peek_char, 'a', 'z', 'A', 'Z', '_' >; + using identifier_other = ranges< peek_char, 'a', 'z', 'A', 'Z', '0', '9', '_' >; + using identifier = seq< identifier_first, star< identifier_other > >; - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/if_apply.hpp b/include/tao/json/external/pegtl/internal/if_apply.hpp index bbfbdde3..a8a4eb0a 100644 --- a/include/tao/json/external/pegtl/internal/if_apply.hpp +++ b/include/tao/json/external/pegtl/internal/if_apply.hpp @@ -1,90 +1,53 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IF_APPLY_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IF_APPLY_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_IF_APPLY_HPP +#define TAO_JSON_PEGTL_INTERNAL_IF_APPLY_HPP #include "../config.hpp" +#include "apply_single.hpp" #include "skip_control.hpp" -namespace tao +#include "../analysis/counted.hpp" +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Rule, typename... Actions > + struct if_apply { - namespace internal + using analyze_t = typename Rule::analyze_t; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) { - template< apply_mode A, typename Rule, typename... Actions > - struct if_apply_impl; - - template< typename Rule, typename... Actions > - struct if_apply_impl< apply_mode::ACTION, Rule, Actions... > - { - template< rewind_mode, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - using action_t = typename Input::action_t; - - auto m = in.template mark< rewind_mode::REQUIRED >(); - - if( Control< Rule >::template match< apply_mode::ACTION, rewind_mode::ACTIVE, Action, Control >( in, st... ) ) { - const action_t i2( m.iterator(), in ); -#ifdef __cpp_fold_expressions - ( Actions::apply( i2, st... ), ... ); -#else - using swallow = bool[]; - (void)swallow{ ( Actions::apply( i2, st... ), true )..., true }; -#endif - return m( true ); - } - return false; - } - }; - - template< typename Rule, typename... Actions > - struct if_apply_impl< apply_mode::NOTHING, Rule, Actions... > - { - template< rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - return Control< Rule >::template match< apply_mode::NOTHING, M, Action, Control >( in, st... ); + if constexpr( ( A == apply_mode::action ) && ( sizeof...( Actions ) != 0 ) ) { + using action_t = typename Input::action_t; + auto m = in.template mark< rewind_mode::required >(); + if( Control< Rule >::template match< apply_mode::action, rewind_mode::active, Action, Control >( in, st... ) ) { + const action_t i2( m.iterator(), in ); + return m( ( apply_single< Actions >::match( i2, st... ) && ... ) ); } - }; - - template< typename Rule, typename... Actions > - struct if_apply - { - using analyze_t = typename Rule::analyze_t; - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - return if_apply_impl< A, Rule, Actions... >::template match< M, Action, Control >( in, st... ); - } - }; - - template< typename Rule, typename... Actions > - struct skip_control< if_apply< Rule, Actions... > > : std::true_type - { - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + return false; + } + else { + return Control< Rule >::template match< A, M, Action, Control >( in, st... ); + } + } + }; + + template< typename Rule, typename... Actions > + inline constexpr bool skip_control< if_apply< Rule, Actions... > > = true; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/if_must.hpp b/include/tao/json/external/pegtl/internal/if_must.hpp index bf5d0839..067d4d51 100644 --- a/include/tao/json/external/pegtl/internal/if_must.hpp +++ b/include/tao/json/external/pegtl/internal/if_must.hpp @@ -1,27 +1,48 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IF_MUST_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IF_MUST_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_IF_MUST_HPP +#define TAO_JSON_PEGTL_INTERNAL_IF_MUST_HPP #include "../config.hpp" #include "must.hpp" -#include "seq.hpp" +#include "skip_control.hpp" +#include "trivial.hpp" -namespace tao +#include "../apply_mode.hpp" +#include "../rewind_mode.hpp" + +#include "../analysis/counted.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< bool Default, typename Cond, typename... Rules > + struct if_must { - namespace internal + using analyze_t = analysis::counted< analysis::rule_type::seq, Default ? 0 : 1, Cond, must< Rules... > >; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) { - template< typename Cond, typename... Thens > - using if_must = seq< Cond, must< Thens... > >; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + if( Control< Cond >::template match< A, M, Action, Control >( in, st... ) ) { + (void)( Control< must< Rules > >::template match< A, M, Action, Control >( in, st... ) && ... ); + return true; + } + return Default; + } + }; + + template< bool Default, typename Cond, typename... Rules > + inline constexpr bool skip_control< if_must< Default, Cond, Rules... > > = true; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/if_must_else.hpp b/include/tao/json/external/pegtl/internal/if_must_else.hpp index f3433de6..0832772c 100644 --- a/include/tao/json/external/pegtl/internal/if_must_else.hpp +++ b/include/tao/json/external/pegtl/internal/if_must_else.hpp @@ -1,27 +1,19 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IF_MUST_ELSE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IF_MUST_ELSE_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_IF_MUST_ELSE_HPP +#define TAO_JSON_PEGTL_INTERNAL_IF_MUST_ELSE_HPP #include "../config.hpp" #include "if_then_else.hpp" #include "must.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< typename Cond, typename Then, typename Else > - using if_must_else = if_then_else< Cond, must< Then >, must< Else > >; + template< typename Cond, typename Then, typename Else > + using if_must_else = if_then_else< Cond, must< Then >, must< Else > >; - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/if_then_else.hpp b/include/tao/json/external/pegtl/internal/if_then_else.hpp index 4f5dfa19..26c2623d 100644 --- a/include/tao/json/external/pegtl/internal/if_then_else.hpp +++ b/include/tao/json/external/pegtl/internal/if_then_else.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IF_THEN_ELSE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_IF_THEN_ELSE_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_IF_THEN_ELSE_HPP +#define TAO_JSON_PEGTL_INTERNAL_IF_THEN_ELSE_HPP #include "../config.hpp" @@ -16,44 +16,36 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Cond, typename Then, typename Else > + struct if_then_else { - namespace internal + using analyze_t = analysis::generic< analysis::rule_type::sor, seq< Cond, Then >, seq< not_at< Cond >, Else > >; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) { - template< typename Cond, typename Then, typename Else > - struct if_then_else - { - using analyze_t = analysis::generic< analysis::rule_type::SOR, seq< Cond, Then >, seq< not_at< Cond >, Else > >; - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< M >(); - using m_t = decltype( m ); - - if( Control< Cond >::template match< A, rewind_mode::REQUIRED, Action, Control >( in, st... ) ) { - return m( Control< Then >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) ); - } - return m( Control< Else >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) ); - } - }; - - template< typename Cond, typename Then, typename Else > - struct skip_control< if_then_else< Cond, Then, Else > > : std::true_type - { - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + auto m = in.template mark< M >(); + using m_t = decltype( m ); + + if( Control< Cond >::template match< A, rewind_mode::required, Action, Control >( in, st... ) ) { + return m( Control< Then >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) ); + } + return m( Control< Else >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) ); + } + }; + + template< typename Cond, typename Then, typename Else > + inline constexpr bool skip_control< if_then_else< Cond, Then, Else > > = true; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/input_pair.hpp b/include/tao/json/external/pegtl/internal/input_pair.hpp index 36fe50d7..b97f177d 100644 --- a/include/tao/json/external/pegtl/internal/input_pair.hpp +++ b/include/tao/json/external/pegtl/internal/input_pair.hpp @@ -1,35 +1,29 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_INPUT_PAIR_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_INPUT_PAIR_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_INPUT_PAIR_HPP +#define TAO_JSON_PEGTL_INTERNAL_INPUT_PAIR_HPP + +#include #include "../config.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Data > + struct input_pair { - namespace internal - { - template< typename Data > - struct input_pair - { - Data data; - unsigned char size; - - using data_t = Data; + Data data; + std::uint8_t size; - explicit operator bool() const noexcept - { - return size > 0; - } - }; + using data_t = Data; - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + explicit operator bool() const noexcept + { + return size > 0; + } + }; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/integer_sequence.hpp b/include/tao/json/external/pegtl/internal/integer_sequence.hpp deleted file mode 100644 index 6ed887f4..00000000 --- a/include/tao/json/external/pegtl/internal/integer_sequence.hpp +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_INTEGER_SEQUENCE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_INTEGER_SEQUENCE_HPP - -#include -#include -#include - -#include "../config.hpp" - -namespace tao -{ - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< typename T, T... Ns > - struct integer_sequence - { - using value_type = T; - - static constexpr std::size_t size() noexcept - { - return sizeof...( Ns ); - } - }; - - template< std::size_t... Ns > - using index_sequence = integer_sequence< std::size_t, Ns... >; - - template< bool V, bool E > - struct generate_sequence; - - template<> - struct generate_sequence< false, true > - { - template< typename T, T M, T N, std::size_t S, T... Ns > - using f = integer_sequence< T, Ns... >; - }; - - template<> - struct generate_sequence< true, true > - { - template< typename T, T M, T N, std::size_t S, T... Ns > - using f = integer_sequence< T, Ns..., S >; - }; - - template<> - struct generate_sequence< false, false > - { - template< typename T, T M, T N, std::size_t S, T... Ns > - using f = typename generate_sequence< ( N & ( M / 2 ) ) != 0, ( M / 2 ) == 0 >::template f< T, M / 2, N, 2 * S, Ns..., ( Ns + S )... >; - }; - - template<> - struct generate_sequence< true, false > - { - template< typename T, T M, T N, std::size_t S, T... Ns > - using f = typename generate_sequence< ( N & ( M / 2 ) ) != 0, ( M / 2 ) == 0 >::template f< T, M / 2, N, 2 * S + 1, Ns..., ( Ns + S )..., 2 * S >; - }; - - template< typename T, T N > - struct memoize_sequence - { - static_assert( N < T( 1 << 20 ), "N too large" ); - using type = typename generate_sequence< false, false >::template f< T, ( N < T( 1 << 1 ) ) ? T( 1 << 1 ) : ( N < T( 1 << 2 ) ) ? T( 1 << 2 ) : ( N < T( 1 << 3 ) ) ? T( 1 << 3 ) : ( N < T( 1 << 4 ) ) ? T( 1 << 4 ) : ( N < T( 1 << 5 ) ) ? T( 1 << 5 ) : ( N < T( 1 << 6 ) ) ? T( 1 << 6 ) : ( N < T( 1 << 7 ) ) ? T( 1 << 7 ) : ( N < T( 1 << 8 ) ) ? T( 1 << 8 ) : ( N < T( 1 << 9 ) ) ? T( 1 << 9 ) : ( N < T( 1 << 10 ) ) ? T( 1 << 10 ) : T( 1 << 20 ), N, 0 >; - }; - - template< typename T, T N > - using make_integer_sequence = typename memoize_sequence< T, N >::type; - - template< std::size_t N > - using make_index_sequence = make_integer_sequence< std::size_t, N >; - - template< typename... Ts > - using index_sequence_for = make_index_sequence< sizeof...( Ts ) >; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao - -#endif diff --git a/include/tao/json/external/pegtl/internal/istream_reader.hpp b/include/tao/json/external/pegtl/internal/istream_reader.hpp index 55ec31b2..25f5b7af 100644 --- a/include/tao/json/external/pegtl/internal/istream_reader.hpp +++ b/include/tao/json/external/pegtl/internal/istream_reader.hpp @@ -1,47 +1,40 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ISTREAM_READER_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ISTREAM_READER_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_ISTREAM_READER_HPP +#define TAO_JSON_PEGTL_INTERNAL_ISTREAM_READER_HPP #include +#include #include "../config.hpp" -#include "../input_error.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct istream_reader { - namespace internal + explicit istream_reader( std::istream& s ) noexcept + : m_istream( s ) { - struct istream_reader - { - explicit istream_reader( std::istream& s ) noexcept - : m_istream( s ) - { - } - - std::size_t operator()( char* buffer, const std::size_t length ) - { - m_istream.read( buffer, std::streamsize( length ) ); - - if( const auto r = m_istream.gcount() ) { - return std::size_t( r ); - } - if( m_istream.eof() ) { - return 0; - } - TAOCPP_JSON_PEGTL_THROW_INPUT_ERROR( "error in istream.read()" ); - } - - std::istream& m_istream; - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + } + + [[nodiscard]] std::size_t operator()( char* buffer, const std::size_t length ) + { + m_istream.read( buffer, std::streamsize( length ) ); + + if( const auto r = m_istream.gcount() ) { + return std::size_t( r ); + } + if( m_istream.eof() ) { + return 0; + } + const auto ec = errno; + throw std::system_error( ec, std::system_category(), "std::istream::read() failed" ); + } + + std::istream& m_istream; + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/istring.hpp b/include/tao/json/external/pegtl/internal/istring.hpp index d0d33407..6f21c570 100644 --- a/include/tao/json/external/pegtl/internal/istring.hpp +++ b/include/tao/json/external/pegtl/internal/istring.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ISTRING_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ISTRING_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_ISTRING_HPP +#define TAO_JSON_PEGTL_INTERNAL_ISTRING_HPP #include @@ -15,93 +15,58 @@ #include "../analysis/counted.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< char C > - using is_alpha = std::integral_constant< bool, ( ( 'a' <= C ) && ( C <= 'z' ) ) || ( ( 'A' <= C ) && ( C <= 'Z' ) ) >; + template< char C > + inline constexpr bool is_alpha = ( ( 'a' <= C ) && ( C <= 'z' ) ) || ( ( 'A' <= C ) && ( C <= 'Z' ) ); - template< char C, bool A = is_alpha< C >::value > - struct ichar_equal; + template< char C > + [[nodiscard]] bool ichar_equal( const char c ) noexcept + { + if constexpr( is_alpha< C > ) { + return ( C | 0x20 ) == ( c | 0x20 ); + } + else { + return c == C; + } + } + + template< char... Cs > + [[nodiscard]] bool istring_equal( const char* r ) noexcept + { + return ( ichar_equal< Cs >( *r++ ) && ... ); + } - template< char C > - struct ichar_equal< C, true > - { - static bool match( const char c ) noexcept - { - return ( C | 0x20 ) == ( c | 0x20 ); - } - }; + template< char... Cs > + struct istring; - template< char C > - struct ichar_equal< C, false > - { - static bool match( const char c ) noexcept - { - return c == C; - } - }; + template<> + struct istring<> + : trivial< true > + { + }; - template< char... Cs > - struct istring_equal; + template< char... Cs > + struct istring + { + using analyze_t = analysis::counted< analysis::rule_type::any, sizeof...( Cs ) >; - template<> - struct istring_equal<> - { - static bool match( const char* ) noexcept - { + template< typename Input > + [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( 0 ) ) ) + { + if( in.size( sizeof...( Cs ) ) >= sizeof...( Cs ) ) { + if( istring_equal< Cs... >( in.current() ) ) { + bump_help< result_on_found::success, Input, char, Cs... >( in, sizeof...( Cs ) ); return true; } - }; - - template< char C, char... Cs > - struct istring_equal< C, Cs... > - { - static bool match( const char* r ) noexcept - { - return ichar_equal< C >::match( *r ) && istring_equal< Cs... >::match( r + 1 ); - } - }; - - template< char... Cs > - struct istring; - - template<> - struct istring<> - : trivial< true > - { - }; - - template< char... Cs > - struct istring - { - using analyze_t = analysis::counted< analysis::rule_type::ANY, sizeof...( Cs ) >; - - template< typename Input > - static bool match( Input& in ) - { - if( in.size( sizeof...( Cs ) ) >= sizeof...( Cs ) ) { - if( istring_equal< Cs... >::match( in.current() ) ) { - bump_help< result_on_found::SUCCESS, Input, char, Cs... >( in, sizeof...( Cs ) ); - return true; - } - } - return false; - } - }; - - template< char... Cs > - struct skip_control< istring< Cs... > > : std::true_type - { - }; - - } // namespace internal + } + return false; + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< char... Cs > + inline constexpr bool skip_control< istring< Cs... > > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/iterator.hpp b/include/tao/json/external/pegtl/internal/iterator.hpp index 70de7d4d..cc2c96f3 100644 --- a/include/tao/json/external/pegtl/internal/iterator.hpp +++ b/include/tao/json/external/pegtl/internal/iterator.hpp @@ -1,53 +1,52 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ITERATOR_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ITERATOR_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_ITERATOR_HPP +#define TAO_JSON_PEGTL_INTERNAL_ITERATOR_HPP #include #include "../config.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct iterator { - namespace internal + iterator() = default; + + explicit iterator( const char* in_data ) noexcept + : data( in_data ) { - struct iterator - { - iterator() noexcept = default; + } - explicit iterator( const char* in_data ) noexcept - : data( in_data ), - byte( 0 ), - line( 1 ), - byte_in_line( 0 ) - { - } + iterator( const char* in_data, const std::size_t in_byte, const std::size_t in_line, const std::size_t in_byte_in_line ) noexcept + : data( in_data ), + byte( in_byte ), + line( in_line ), + byte_in_line( in_byte_in_line ) + { + } - iterator( const char* in_data, const std::size_t in_byte, const std::size_t in_line, const std::size_t in_byte_in_line ) noexcept - : data( in_data ), - byte( in_byte ), - line( in_line ), - byte_in_line( in_byte_in_line ) - { - } + iterator( const iterator& ) = default; + iterator( iterator&& ) = default; - iterator( const iterator& ) = default; - iterator& operator=( const iterator& ) = default; + ~iterator() = default; - const char* data = nullptr; + iterator& operator=( const iterator& ) = default; + iterator& operator=( iterator&& ) = default; - std::size_t byte; - std::size_t line; - std::size_t byte_in_line; - }; + void reset() noexcept + { + *this = iterator(); + } - } // namespace internal + const char* data = nullptr; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + std::size_t byte = 0; + std::size_t line = 1; + std::size_t byte_in_line = 0; + }; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/lf_crlf_eol.hpp b/include/tao/json/external/pegtl/internal/lf_crlf_eol.hpp index a3089b96..aefef00a 100644 --- a/include/tao/json/external/pegtl/internal/lf_crlf_eol.hpp +++ b/include/tao/json/external/pegtl/internal/lf_crlf_eol.hpp @@ -1,44 +1,37 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LF_CRLF_EOL_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LF_CRLF_EOL_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_LF_CRLF_EOL_HPP +#define TAO_JSON_PEGTL_INTERNAL_LF_CRLF_EOL_HPP #include "../config.hpp" +#include "../eol_pair.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct lf_crlf_eol { - namespace internal - { - struct lf_crlf_eol - { - static constexpr int ch = '\n'; + static constexpr int ch = '\n'; - template< typename Input > - static eol_pair match( Input& in ) - { - eol_pair p = { false, in.size( 2 ) }; - if( p.second ) { - const auto a = in.peek_char(); - if( a == '\n' ) { - in.bump_to_next_line(); - p.first = true; - } - else if( ( a == '\r' ) && ( p.second > 1 ) && ( in.peek_char( 1 ) == '\n' ) ) { - in.bump_to_next_line( 2 ); - p.first = true; - } - } - return p; + template< typename Input > + [[nodiscard]] static eol_pair match( Input& in ) noexcept( noexcept( in.size( 2 ) ) ) + { + eol_pair p = { false, in.size( 2 ) }; + if( p.second ) { + const auto a = in.peek_char(); + if( a == '\n' ) { + in.bump_to_next_line(); + p.first = true; } - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + else if( ( a == '\r' ) && ( p.second > 1 ) && ( in.peek_char( 1 ) == '\n' ) ) { + in.bump_to_next_line( 2 ); + p.first = true; + } + } + return p; + } + }; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/lf_eol.hpp b/include/tao/json/external/pegtl/internal/lf_eol.hpp index 00485c70..6d8d418d 100644 --- a/include/tao/json/external/pegtl/internal/lf_eol.hpp +++ b/include/tao/json/external/pegtl/internal/lf_eol.hpp @@ -1,39 +1,32 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LF_EOL_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LF_EOL_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_LF_EOL_HPP +#define TAO_JSON_PEGTL_INTERNAL_LF_EOL_HPP #include "../config.hpp" +#include "../eol_pair.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct lf_eol { - namespace internal - { - struct lf_eol - { - static constexpr int ch = '\n'; + static constexpr int ch = '\n'; - template< typename Input > - static eol_pair match( Input& in ) - { - eol_pair p = { false, in.size( 1 ) }; - if( p.second ) { - if( in.peek_char() == '\n' ) { - in.bump_to_next_line(); - p.first = true; - } - } - return p; + template< typename Input > + [[nodiscard]] static eol_pair match( Input& in ) noexcept( noexcept( in.size( 1 ) ) ) + { + eol_pair p = { false, in.size( 1 ) }; + if( p.second ) { + if( in.peek_char() == '\n' ) { + in.bump_to_next_line(); + p.first = true; } - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + } + return p; + } + }; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/list.hpp b/include/tao/json/external/pegtl/internal/list.hpp index fddbc640..b9ef9353 100644 --- a/include/tao/json/external/pegtl/internal/list.hpp +++ b/include/tao/json/external/pegtl/internal/list.hpp @@ -1,27 +1,19 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LIST_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LIST_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_LIST_HPP +#define TAO_JSON_PEGTL_INTERNAL_LIST_HPP #include "../config.hpp" #include "seq.hpp" #include "star.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< typename Rule, typename Sep > - using list = seq< Rule, star< Sep, Rule > >; + template< typename Rule, typename Sep > + using list = seq< Rule, star< Sep, Rule > >; - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/list_must.hpp b/include/tao/json/external/pegtl/internal/list_must.hpp index c0f9123f..ce5a505e 100644 --- a/include/tao/json/external/pegtl/internal/list_must.hpp +++ b/include/tao/json/external/pegtl/internal/list_must.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LIST_MUST_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LIST_MUST_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_LIST_MUST_HPP +#define TAO_JSON_PEGTL_INTERNAL_LIST_MUST_HPP #include "../config.hpp" @@ -10,19 +10,11 @@ #include "seq.hpp" #include "star.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< typename Rule, typename Sep > - using list_must = seq< Rule, star< Sep, must< Rule > > >; + template< typename Rule, typename Sep > + using list_must = seq< Rule, star< Sep, must< Rule > > >; - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/list_tail.hpp b/include/tao/json/external/pegtl/internal/list_tail.hpp index 9576c8cb..24195a14 100644 --- a/include/tao/json/external/pegtl/internal/list_tail.hpp +++ b/include/tao/json/external/pegtl/internal/list_tail.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LIST_TAIL_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LIST_TAIL_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_LIST_TAIL_HPP +#define TAO_JSON_PEGTL_INTERNAL_LIST_TAIL_HPP #include "../config.hpp" @@ -10,19 +10,11 @@ #include "opt.hpp" #include "seq.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< typename Rule, typename Sep > - using list_tail = seq< list< Rule, Sep >, opt< Sep > >; + template< typename Rule, typename Sep > + using list_tail = seq< list< Rule, Sep >, opt< Sep > >; - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/list_tail_pad.hpp b/include/tao/json/external/pegtl/internal/list_tail_pad.hpp index 9d456d83..531c66a3 100644 --- a/include/tao/json/external/pegtl/internal/list_tail_pad.hpp +++ b/include/tao/json/external/pegtl/internal/list_tail_pad.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LIST_TAIL_PAD_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_LIST_TAIL_PAD_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_LIST_TAIL_PAD_HPP +#define TAO_JSON_PEGTL_INTERNAL_LIST_TAIL_PAD_HPP #include "../config.hpp" @@ -12,19 +12,11 @@ #include "seq.hpp" #include "star.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< typename Rule, typename Sep, typename Pad > - using list_tail_pad = seq< list< Rule, pad< Sep, Pad > >, opt< star< Pad >, Sep > >; + template< typename Rule, typename Sep, typename Pad > + using list_tail_pad = seq< list< Rule, pad< Sep, Pad > >, opt< star< Pad >, Sep > >; - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/marker.hpp b/include/tao/json/external/pegtl/internal/marker.hpp index b6252448..4e7812c3 100644 --- a/include/tao/json/external/pegtl/internal/marker.hpp +++ b/include/tao/json/external/pegtl/internal/marker.hpp @@ -1,93 +1,82 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_MARKER_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_MARKER_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_MARKER_HPP +#define TAO_JSON_PEGTL_INTERNAL_MARKER_HPP #include "../config.hpp" #include "../rewind_mode.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Iterator, rewind_mode M > + class marker { - namespace internal + public: + static constexpr rewind_mode next_rewind_mode = M; + + explicit marker( const Iterator& /*unused*/ ) noexcept + { + } + + marker( const marker& ) = delete; + marker( marker&& ) = delete; + + ~marker() = default; + + void operator=( const marker& ) = delete; + void operator=( marker&& ) = delete; + + [[nodiscard]] bool operator()( const bool result ) const noexcept + { + return result; + } + }; + + template< typename Iterator > + class marker< Iterator, rewind_mode::required > + { + public: + static constexpr rewind_mode next_rewind_mode = rewind_mode::active; + + explicit marker( Iterator& i ) noexcept + : m_saved( i ), + m_input( &i ) { - template< typename Iterator, rewind_mode M > - class marker - { - public: - static constexpr rewind_mode next_rewind_mode = M; - - explicit marker( const Iterator& ) noexcept - { - } - - marker( marker&& ) noexcept - { - } - - marker( const marker& ) = delete; - void operator=( const marker& ) = delete; - - bool operator()( const bool result ) const noexcept - { - return result; - } - }; - - template< typename Iterator > - class marker< Iterator, rewind_mode::REQUIRED > - { - public: - static constexpr rewind_mode next_rewind_mode = rewind_mode::ACTIVE; - - explicit marker( Iterator& i ) noexcept - : m_saved( i ), - m_input( &i ) - { - } - - marker( marker&& i ) noexcept - : m_saved( i.m_saved ), - m_input( i.m_input ) - { - i.m_input = nullptr; - } - - ~marker() noexcept - { - if( m_input != nullptr ) { - ( *m_input ) = m_saved; - } - } - - marker( const marker& ) = delete; - void operator=( const marker& ) = delete; - - bool operator()( const bool result ) noexcept - { - if( result ) { - m_input = nullptr; - return true; - } - return false; - } - - const Iterator& iterator() const noexcept - { - return m_saved; - } - - private: - const Iterator m_saved; - Iterator* m_input; - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + } + + marker( const marker& ) = delete; + marker( marker&& ) = delete; + + ~marker() noexcept + { + if( m_input != nullptr ) { + ( *m_input ) = m_saved; + } + } + + void operator=( const marker& ) = delete; + void operator=( marker&& ) = delete; + + [[nodiscard]] bool operator()( const bool result ) noexcept + { + if( result ) { + m_input = nullptr; + return true; + } + return false; + } + + [[nodiscard]] const Iterator& iterator() const noexcept + { + return m_saved; + } + + private: + const Iterator m_saved; + Iterator* m_input; + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/minus.hpp b/include/tao/json/external/pegtl/internal/minus.hpp deleted file mode 100644 index e4dab285..00000000 --- a/include/tao/json/external/pegtl/internal/minus.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_MINUS_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_MINUS_HPP - -#include "../config.hpp" - -#include "skip_control.hpp" - -#include "../apply_mode.hpp" -#include "../memory_input.hpp" -#include "../rewind_mode.hpp" - -namespace tao -{ - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - inline const char* source_pointer( const char* source ) noexcept - { - return source; - } - - inline const char* source_pointer( const std::string& source ) noexcept - { - return source.c_str(); - } - - template< typename R, typename S > - struct minus - { - using analyze_t = typename R::analyze_t; // NOTE: S is currently ignored for analyze(). - - template< apply_mode A, - rewind_mode, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< rewind_mode::REQUIRED >(); - - if( !Control< R >::template match< A, rewind_mode::ACTIVE, Action, Control >( in, st... ) ) { - return false; - } - memory_input< tracking_mode::LAZY, typename Input::eol_t, const char* > i2( m.iterator(), in.current(), source_pointer( in.source() ) ); - - if( !Control< S >::template match< apply_mode::NOTHING, rewind_mode::ACTIVE, Action, Control >( i2, st... ) ) { - return m( true ); - } - return m( !i2.empty() ); - } - }; - - template< typename R, typename S > - struct skip_control< minus< R, S > > : std::true_type - { - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao - -#endif diff --git a/include/tao/json/external/pegtl/internal/missing_apply.hpp b/include/tao/json/external/pegtl/internal/missing_apply.hpp new file mode 100644 index 00000000..5a5483c7 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/missing_apply.hpp @@ -0,0 +1,25 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_INTERNAL_MISSING_APPLY_HPP +#define TAO_JSON_PEGTL_INTERNAL_MISSING_APPLY_HPP + +#include "../config.hpp" +#include "../rewind_mode.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ + template< typename Control, + template< typename... > + class Action, + typename Input, + typename... States > + void missing_apply( Input& in, States&&... st ) + { + auto m = in.template mark< rewind_mode::required >(); + (void)Control::template apply< Action >( m.iterator(), in, st... ); + } + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/json/external/pegtl/internal/missing_apply0.hpp b/include/tao/json/external/pegtl/internal/missing_apply0.hpp new file mode 100644 index 00000000..de53e3e0 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/missing_apply0.hpp @@ -0,0 +1,23 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_INTERNAL_MISSING_APPLY0_HPP +#define TAO_JSON_PEGTL_INTERNAL_MISSING_APPLY0_HPP + +#include "../config.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ + template< typename Control, + template< typename... > + class Action, + typename Input, + typename... States > + void missing_apply0( Input& in, States&&... st ) + { + (void)Control::template apply0< Action >( in, st... ); + } + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/json/external/pegtl/internal/must.hpp b/include/tao/json/external/pegtl/internal/must.hpp index f3742eab..fd274aa4 100644 --- a/include/tao/json/external/pegtl/internal/must.hpp +++ b/include/tao/json/external/pegtl/internal/must.hpp @@ -1,13 +1,12 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_MUST_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_MUST_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_MUST_HPP +#define TAO_JSON_PEGTL_INTERNAL_MUST_HPP #include "../config.hpp" #include "raise.hpp" -#include "rule_conjunction.hpp" #include "skip_control.hpp" #include "../apply_mode.hpp" @@ -15,65 +14,59 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + // The general case applies must<> to each of the + // rules in the 'Rules' parameter pack individually. + + template< typename... Rules > + struct must { - namespace internal + using analyze_t = analysis::generic< analysis::rule_type::seq, Rules... >; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) { - // The general case applies must<> to each of the - // rules in the 'Rules' parameter pack individually. - - template< typename... Rules > - struct must - { - using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rules... >; - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - return rule_conjunction< must< Rules >... >::template match< A, M, Action, Control >( in, st... ); - } - }; - - // While in theory the implementation for a single rule could - // be simplified to must< Rule > = sor< Rule, raise< Rule > >, this - // would result in some unnecessary run-time overhead. + return ( Control< must< Rules > >::template match< A, M, Action, Control >( in, st... ) && ... ); + } + }; - template< typename Rule > - struct must< Rule > - { - using analyze_t = typename Rule::analyze_t; + // While in theory the implementation for a single rule could + // be simplified to must< Rule > = sor< Rule, raise< Rule > >, this + // would result in some unnecessary run-time overhead. - template< apply_mode A, - rewind_mode, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - if( !Control< Rule >::template match< A, rewind_mode::DONTCARE, Action, Control >( in, st... ) ) { - raise< Rule >::template match< A, rewind_mode::DONTCARE, Action, Control >( in, st... ); - } - return true; - } - }; - - template< typename... Rules > - struct skip_control< must< Rules... > > : std::true_type - { - }; - - } // namespace internal + template< typename Rule > + struct must< Rule > + { + using analyze_t = typename Rule::analyze_t; + + template< apply_mode A, + rewind_mode, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + if( !Control< Rule >::template match< A, rewind_mode::dontcare, Action, Control >( in, st... ) ) { + (void)raise< Rule >::template match< A, rewind_mode::dontcare, Action, Control >( in, st... ); + } + return true; + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename... Rules > + inline constexpr bool skip_control< must< Rules... > > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/not_at.hpp b/include/tao/json/external/pegtl/internal/not_at.hpp index 40c0caff..8db18427 100644 --- a/include/tao/json/external/pegtl/internal/not_at.hpp +++ b/include/tao/json/external/pegtl/internal/not_at.hpp @@ -1,12 +1,11 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_NOT_AT_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_NOT_AT_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_NOT_AT_HPP +#define TAO_JSON_PEGTL_INTERNAL_NOT_AT_HPP #include "../config.hpp" -#include "rule_conjunction.hpp" #include "skip_control.hpp" #include "trivial.hpp" @@ -15,48 +14,40 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename... Rules > + struct not_at; + + template<> + struct not_at<> + : trivial< false > + { + }; + + template< typename... Rules > + struct not_at { - namespace internal + using analyze_t = analysis::generic< analysis::rule_type::opt, Rules... >; + + template< apply_mode, + rewind_mode, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) { - template< typename... Rules > - struct not_at; - - template<> - struct not_at<> - : trivial< false > - { - }; - - template< typename... Rules > - struct not_at - { - using analyze_t = analysis::generic< analysis::rule_type::OPT, Rules... >; - - template< apply_mode, - rewind_mode, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - const auto m = in.template mark< rewind_mode::REQUIRED >(); - return !rule_conjunction< Rules... >::template match< apply_mode::NOTHING, rewind_mode::ACTIVE, Action, Control >( in, st... ); - } - }; - - template< typename... Rules > - struct skip_control< not_at< Rules... > > : std::true_type - { - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + const auto m = in.template mark< rewind_mode::required >(); + return !( Control< Rules >::template match< apply_mode::nothing, rewind_mode::active, Action, Control >( in, st... ) && ... ); + } + }; + + template< typename... Rules > + inline constexpr bool skip_control< not_at< Rules... > > = true; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/one.hpp b/include/tao/json/external/pegtl/internal/one.hpp index b3b4c3d2..98cd0514 100644 --- a/include/tao/json/external/pegtl/internal/one.hpp +++ b/include/tao/json/external/pegtl/internal/one.hpp @@ -1,11 +1,10 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ONE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_ONE_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_ONE_HPP +#define TAO_JSON_PEGTL_INTERNAL_ONE_HPP -#include -#include +#include #include "../config.hpp" @@ -15,67 +14,31 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< result_on_found R, typename Peek, typename Peek::data_t... Cs > + struct one { - namespace internal - { - template< typename Char > - bool contains( const Char c, const std::initializer_list< Char >& l ) noexcept - { - return std::find( l.begin(), l.end(), c ) != l.end(); - } - - template< result_on_found R, typename Peek, typename Peek::data_t... Cs > - struct one - { - using analyze_t = analysis::generic< analysis::rule_type::ANY >; - - template< typename Input > - static bool match( Input& in ) - { - if( !in.empty() ) { - if( const auto t = Peek::peek( in ) ) { - if( contains( t.data, { Cs... } ) == bool( R ) ) { - bump_help< R, Input, typename Peek::data_t, Cs... >( in, t.size ); - return true; - } - } - } - return false; - } - }; + using analyze_t = analysis::generic< analysis::rule_type::any >; - template< result_on_found R, typename Peek, typename Peek::data_t C > - struct one< R, Peek, C > - { - using analyze_t = analysis::generic< analysis::rule_type::ANY >; - - template< typename Input > - static bool match( Input& in ) - { - if( !in.empty() ) { - if( const auto t = Peek::peek( in ) ) { - if( ( t.data == C ) == bool( R ) ) { - bump_help< R, Input, typename Peek::data_t, C >( in, t.size ); - return true; - } - } + template< typename Input > + [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( Peek::max_input_size ) ) ) + { + if( const std::size_t s = in.size( Peek::max_input_size ); s >= Peek::min_input_size ) { + if( const auto t = Peek::peek( in, s ) ) { + if( ( ( t.data == Cs ) || ... ) == bool( R ) ) { + bump_help< R, Input, typename Peek::data_t, Cs... >( in, t.size ); + return true; } - return false; } - }; - - template< result_on_found R, typename Peek, typename Peek::data_t... Cs > - struct skip_control< one< R, Peek, Cs... > > : std::true_type - { - }; - - } // namespace internal + } + return false; + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< result_on_found R, typename Peek, typename Peek::data_t... Cs > + inline constexpr bool skip_control< one< R, Peek, Cs... > > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/opt.hpp b/include/tao/json/external/pegtl/internal/opt.hpp index 42d66f56..8cd60756 100644 --- a/include/tao/json/external/pegtl/internal/opt.hpp +++ b/include/tao/json/external/pegtl/internal/opt.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_OPT_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_OPT_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_OPT_HPP +#define TAO_JSON_PEGTL_INTERNAL_OPT_HPP #include @@ -18,50 +18,40 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< typename... Rules > - struct opt; - - template<> - struct opt<> - : trivial< true > - { - }; - - template< typename... Rules > - struct opt - { - using analyze_t = analysis::generic< analysis::rule_type::OPT, Rules... >; + template< typename... Rules > + struct opt; - template< apply_mode A, - rewind_mode, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - if( !in.empty() ) { - duseltronik< seq< Rules... >, A, rewind_mode::REQUIRED, Action, Control >::match( in, st... ); - } - return true; - } - }; - - template< typename... Rules > - struct skip_control< opt< Rules... > > : std::true_type - { - }; + template<> + struct opt<> + : trivial< true > + { + }; - } // namespace internal + template< typename... Rules > + struct opt + { + using analyze_t = analysis::generic< analysis::rule_type::opt, Rules... >; + + template< apply_mode A, + rewind_mode, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + (void)duseltronik< seq< Rules... >, A, rewind_mode::required, Action, Control >::match( in, st... ); + return true; + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename... Rules > + inline constexpr bool skip_control< opt< Rules... > > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/pad.hpp b/include/tao/json/external/pegtl/internal/pad.hpp index d5f9b9c8..18fed7c0 100644 --- a/include/tao/json/external/pegtl/internal/pad.hpp +++ b/include/tao/json/external/pegtl/internal/pad.hpp @@ -1,27 +1,19 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PAD_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PAD_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_PAD_HPP +#define TAO_JSON_PEGTL_INTERNAL_PAD_HPP #include "../config.hpp" #include "seq.hpp" #include "star.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< typename Rule, typename Pad1, typename Pad2 = Pad1 > - using pad = seq< star< Pad1 >, Rule, star< Pad2 > >; + template< typename Rule, typename Pad1, typename Pad2 = Pad1 > + using pad = seq< star< Pad1 >, Rule, star< Pad2 > >; - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/pad_opt.hpp b/include/tao/json/external/pegtl/internal/pad_opt.hpp index bf125ce1..933caed9 100644 --- a/include/tao/json/external/pegtl/internal/pad_opt.hpp +++ b/include/tao/json/external/pegtl/internal/pad_opt.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PAD_OPT_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PAD_OPT_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_PAD_OPT_HPP +#define TAO_JSON_PEGTL_INTERNAL_PAD_OPT_HPP #include "../config.hpp" @@ -10,19 +10,11 @@ #include "seq.hpp" #include "star.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< typename Rule, typename Pad > - using pad_opt = seq< star< Pad >, opt< Rule, star< Pad > > >; + template< typename Rule, typename Pad > + using pad_opt = seq< star< Pad >, opt< Rule, star< Pad > > >; - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/peek_char.hpp b/include/tao/json/external/pegtl/internal/peek_char.hpp index 348c6645..88b94512 100644 --- a/include/tao/json/external/pegtl/internal/peek_char.hpp +++ b/include/tao/json/external/pegtl/internal/peek_char.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PEEK_CHAR_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PEEK_CHAR_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_PEEK_CHAR_HPP +#define TAO_JSON_PEGTL_INTERNAL_PEEK_CHAR_HPP #include @@ -10,28 +10,23 @@ #include "input_pair.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct peek_char { - namespace internal - { - struct peek_char - { - using data_t = char; - using pair_t = input_pair< char >; - - template< typename Input > - static pair_t peek( Input& in, const std::size_t o = 0 ) - { - return { in.peek_char( o ), 1 }; - } - }; + using data_t = char; + using pair_t = input_pair< char >; - } // namespace internal + static constexpr std::size_t min_input_size = 1; + static constexpr std::size_t max_input_size = 1; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Input > + [[nodiscard]] static pair_t peek( const Input& in, const std::size_t /*unused*/ = 1 ) noexcept + { + return { in.peek_char(), 1 }; + } + }; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/peek_mask_uint.hpp b/include/tao/json/external/pegtl/internal/peek_mask_uint.hpp new file mode 100644 index 00000000..97248f0d --- /dev/null +++ b/include/tao/json/external/pegtl/internal/peek_mask_uint.hpp @@ -0,0 +1,54 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_INTERNAL_PEEK_MASK_UINT_HPP +#define TAO_JSON_PEGTL_INTERNAL_PEEK_MASK_UINT_HPP + +#include +#include + +#include "../config.hpp" + +#include "input_pair.hpp" +#include "read_uint.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ + template< typename R, typename R::type M > + struct peek_mask_uint_impl + { + using data_t = typename R::type; + using pair_t = input_pair< data_t >; + + static constexpr std::size_t min_input_size = sizeof( data_t ); + static constexpr std::size_t max_input_size = sizeof( data_t ); + + template< typename Input > + [[nodiscard]] static pair_t peek( const Input& in, const std::size_t /*unused*/ ) noexcept + { + const data_t data = R::read( in.current() ) & M; + return { data, sizeof( data_t ) }; + } + }; + + template< std::uint16_t M > + using peek_mask_uint16_be = peek_mask_uint_impl< read_uint16_be, M >; + + template< std::uint16_t M > + using peek_mask_uint16_le = peek_mask_uint_impl< read_uint16_le, M >; + + template< std::uint32_t M > + using peek_mask_uint32_be = peek_mask_uint_impl< read_uint32_be, M >; + + template< std::uint32_t M > + using peek_mask_uint32_le = peek_mask_uint_impl< read_uint32_le, M >; + + template< std::uint64_t M > + using peek_mask_uint64_be = peek_mask_uint_impl< read_uint64_be, M >; + + template< std::uint64_t M > + using peek_mask_uint64_le = peek_mask_uint_impl< read_uint64_le, M >; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/json/external/pegtl/internal/peek_mask_uint8.hpp b/include/tao/json/external/pegtl/internal/peek_mask_uint8.hpp new file mode 100644 index 00000000..c64d0913 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/peek_mask_uint8.hpp @@ -0,0 +1,34 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_INTERNAL_PEEK_MASK_UINT8_HPP +#define TAO_JSON_PEGTL_INTERNAL_PEEK_MASK_UINT8_HPP + +#include +#include + +#include "../config.hpp" + +#include "input_pair.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ + template< std::uint8_t M > + struct peek_mask_uint8 + { + using data_t = std::uint8_t; + using pair_t = input_pair< std::uint8_t >; + + static constexpr std::size_t min_input_size = 1; + static constexpr std::size_t max_input_size = 1; + + template< typename Input > + [[nodiscard]] static pair_t peek( const Input& in, const std::size_t /*unused*/ = 1 ) noexcept + { + return { std::uint8_t( in.peek_uint8() & M ), 1 }; + } + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/json/external/pegtl/internal/peek_uint.hpp b/include/tao/json/external/pegtl/internal/peek_uint.hpp new file mode 100644 index 00000000..95aaaabe --- /dev/null +++ b/include/tao/json/external/pegtl/internal/peek_uint.hpp @@ -0,0 +1,45 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_INTERNAL_PEEK_UINT_HPP +#define TAO_JSON_PEGTL_INTERNAL_PEEK_UINT_HPP + +#include +#include + +#include "../config.hpp" + +#include "input_pair.hpp" +#include "read_uint.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ + template< typename R > + struct peek_uint_impl + { + using data_t = typename R::type; + using pair_t = input_pair< data_t >; + + static constexpr std::size_t min_input_size = sizeof( data_t ); + static constexpr std::size_t max_input_size = sizeof( data_t ); + + template< typename Input > + [[nodiscard]] static pair_t peek( const Input& in, const std::size_t /*unused*/ ) noexcept + { + const data_t data = R::read( in.current() ); + return { data, sizeof( data_t ) }; + } + }; + + using peek_uint16_be = peek_uint_impl< read_uint16_be >; + using peek_uint16_le = peek_uint_impl< read_uint16_le >; + + using peek_uint32_be = peek_uint_impl< read_uint32_be >; + using peek_uint32_le = peek_uint_impl< read_uint32_le >; + + using peek_uint64_be = peek_uint_impl< read_uint64_be >; + using peek_uint64_le = peek_uint_impl< read_uint64_le >; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/json/external/pegtl/internal/peek_uint8.hpp b/include/tao/json/external/pegtl/internal/peek_uint8.hpp new file mode 100644 index 00000000..6f439b54 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/peek_uint8.hpp @@ -0,0 +1,33 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_INTERNAL_PEEK_UINT8_HPP +#define TAO_JSON_PEGTL_INTERNAL_PEEK_UINT8_HPP + +#include +#include + +#include "../config.hpp" + +#include "input_pair.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ + struct peek_uint8 + { + using data_t = std::uint8_t; + using pair_t = input_pair< std::uint8_t >; + + static constexpr std::size_t min_input_size = 1; + static constexpr std::size_t max_input_size = 1; + + template< typename Input > + [[nodiscard]] static pair_t peek( const Input& in, const std::size_t /*unused*/ = 1 ) noexcept + { + return { in.peek_uint8(), 1 }; + } + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/json/external/pegtl/internal/peek_utf16.hpp b/include/tao/json/external/pegtl/internal/peek_utf16.hpp index bcfa7c3a..c5172b45 100644 --- a/include/tao/json/external/pegtl/internal/peek_utf16.hpp +++ b/include/tao/json/external/pegtl/internal/peek_utf16.hpp @@ -1,54 +1,54 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PEEK_UTF16_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PEEK_UTF16_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_PEEK_UTF16_HPP +#define TAO_JSON_PEGTL_INTERNAL_PEEK_UTF16_HPP #include #include "../config.hpp" #include "input_pair.hpp" +#include "read_uint.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename R > + struct peek_utf16_impl { - namespace internal + using data_t = char32_t; + using pair_t = input_pair< char32_t >; + + using short_t = std::make_unsigned< char16_t >::type; + + static_assert( sizeof( short_t ) == 2 ); + static_assert( sizeof( char16_t ) == 2 ); + + static constexpr std::size_t min_input_size = 2; + static constexpr std::size_t max_input_size = 4; + + template< typename Input > + [[nodiscard]] static pair_t peek( const Input& in, const std::size_t s ) noexcept { - struct peek_utf16 - { - using data_t = char32_t; - using pair_t = input_pair< char32_t >; - - using short_t = std::make_unsigned< char16_t >::type; - - static_assert( sizeof( short_t ) == 2, "expected size 2 for 16bit value" ); - static_assert( sizeof( char16_t ) == 2, "expected size 2 for 16bit value" ); - - template< typename Input > - static pair_t peek( Input& in ) - { - const std::size_t s = in.size( 4 ); - if( s >= 2 ) { - const char32_t t = *reinterpret_cast< const short_t* >( in.current() ); - if( ( t < 0xd800 ) || ( t > 0xdbff ) || ( s < 4 ) ) { - return { t, 2 }; - } - const char32_t u = *reinterpret_cast< const short_t* >( in.current() + 2 ); - if( ( u < 0xdc00 ) || ( u > 0xdfff ) ) { - return { t, 2 }; - } - return { ( ( ( t & 0x03ff ) << 10 ) | ( u & 0x03ff ) ) + 0x10000, 4 }; - } - return { 0, 0 }; - } - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + const char32_t t = R::read( in.current() ); + if( ( t < 0xd800 ) || ( t > 0xdfff ) ) { + return { t, 2 }; + } + if( ( t >= 0xdc00 ) || ( s < 4 ) ) { + return { 0, 0 }; + } + const char32_t u = R::read( in.current() + 2 ); + if( ( u >= 0xdc00 ) && ( u <= 0xdfff ) ) { + const auto cp = ( ( ( t & 0x03ff ) << 10 ) | ( u & 0x03ff ) ) + 0x10000; + return { cp, 4 }; + } + return { 0, 0 }; + } + }; + + using peek_utf16_be = peek_utf16_impl< read_uint16_be >; + using peek_utf16_le = peek_utf16_impl< read_uint16_le >; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/peek_utf32.hpp b/include/tao/json/external/pegtl/internal/peek_utf32.hpp index cfcac3dc..32c2a721 100644 --- a/include/tao/json/external/pegtl/internal/peek_utf32.hpp +++ b/include/tao/json/external/pegtl/internal/peek_utf32.hpp @@ -1,46 +1,43 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PEEK_UTF32_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PEEK_UTF32_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_PEEK_UTF32_HPP +#define TAO_JSON_PEGTL_INTERNAL_PEEK_UTF32_HPP #include #include "../config.hpp" #include "input_pair.hpp" +#include "read_uint.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename R > + struct peek_utf32_impl { - namespace internal + using data_t = char32_t; + using pair_t = input_pair< char32_t >; + + static_assert( sizeof( char32_t ) == 4 ); + + static constexpr std::size_t min_input_size = 4; + static constexpr std::size_t max_input_size = 4; + + template< typename Input > + [[nodiscard]] static pair_t peek( const Input& in, const std::size_t /*unused*/ ) noexcept { - struct peek_utf32 - { - using data_t = char32_t; - using pair_t = input_pair< char32_t >; - - static_assert( sizeof( char32_t ) == 4, "expected size 4 for 32bit value" ); - - template< typename Input > - static pair_t peek( Input& in ) - { - const std::size_t s = in.size( 4 ); - if( s >= 4 ) { - const char32_t t = *reinterpret_cast< const char32_t* >( in.current() ); - if( ( 0 <= t ) && ( t <= 0x10ffff ) ) { - return { t, 4 }; - } - } - return { 0, 0 }; - } - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + const char32_t t = R::read( in.current() ); + if( ( t <= 0x10ffff ) && !( t >= 0xd800 && t <= 0xdfff ) ) { + return { t, 4 }; + } + return { 0, 0 }; + } + }; + + using peek_utf32_be = peek_utf32_impl< read_uint32_be >; + using peek_utf32_le = peek_utf32_impl< read_uint32_le >; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/peek_utf8.hpp b/include/tao/json/external/pegtl/internal/peek_utf8.hpp index 831288f1..f9d50d96 100644 --- a/include/tao/json/external/pegtl/internal/peek_utf8.hpp +++ b/include/tao/json/external/pegtl/internal/peek_utf8.hpp @@ -1,88 +1,90 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PEEK_UTF8_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PEEK_UTF8_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_PEEK_UTF8_HPP +#define TAO_JSON_PEGTL_INTERNAL_PEEK_UTF8_HPP #include "../config.hpp" #include "input_pair.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct peek_utf8 { - namespace internal + using data_t = char32_t; + using pair_t = input_pair< char32_t >; + + static constexpr std::size_t min_input_size = 1; + static constexpr std::size_t max_input_size = 4; + + template< typename Input > + [[nodiscard]] static pair_t peek( const Input& in, const std::size_t s ) noexcept { - struct peek_utf8 - { - using data_t = char32_t; - using pair_t = input_pair< char32_t >; + char32_t c0 = in.peek_uint8(); - template< typename Input > - static pair_t peek( Input& in ) - { - char32_t c0 = in.peek_byte(); + if( ( c0 & 0x80 ) == 0 ) { + return { c0, 1 }; + } + return peek_impl( in, c0, s ); + } - if( ( c0 & 0x80 ) == 0 ) { - return { c0, 1 }; - } - if( ( c0 & 0xE0 ) == 0xC0 ) { - if( in.size( 2 ) >= 2 ) { - const char32_t c1 = in.peek_byte( 1 ); - if( ( c1 & 0xC0 ) == 0x80 ) { - c0 &= 0x1F; - c0 <<= 6; - c0 |= ( c1 & 0x3F ); - if( c0 >= 0x80 ) { - return { c0, 2 }; - } - } + private: + template< typename Input > + [[nodiscard]] static pair_t peek_impl( const Input& in, char32_t c0, const std::size_t s ) noexcept + { + if( ( c0 & 0xE0 ) == 0xC0 ) { + if( s >= 2 ) { + const char32_t c1 = in.peek_uint8( 1 ); + if( ( c1 & 0xC0 ) == 0x80 ) { + c0 &= 0x1F; + c0 <<= 6; + c0 |= ( c1 & 0x3F ); + if( c0 >= 0x80 ) { + return { c0, 2 }; } } - else if( ( c0 & 0xF0 ) == 0xE0 ) { - if( in.size( 3 ) >= 3 ) { - const char32_t c1 = in.peek_byte( 1 ); - const char32_t c2 = in.peek_byte( 2 ); - if( ( ( c1 & 0xC0 ) == 0x80 ) && ( ( c2 & 0xC0 ) == 0x80 ) ) { - c0 &= 0x0F; - c0 <<= 6; - c0 |= ( c1 & 0x3F ); - c0 <<= 6; - c0 |= ( c2 & 0x3F ); - if( c0 >= 0x800 ) { - return { c0, 3 }; - } - } + } + } + else if( ( c0 & 0xF0 ) == 0xE0 ) { + if( s >= 3 ) { + const char32_t c1 = in.peek_uint8( 1 ); + const char32_t c2 = in.peek_uint8( 2 ); + if( ( ( c1 & 0xC0 ) == 0x80 ) && ( ( c2 & 0xC0 ) == 0x80 ) ) { + c0 &= 0x0F; + c0 <<= 6; + c0 |= ( c1 & 0x3F ); + c0 <<= 6; + c0 |= ( c2 & 0x3F ); + if( c0 >= 0x800 && !( c0 >= 0xD800 && c0 <= 0xDFFF ) ) { + return { c0, 3 }; } } - else if( ( c0 & 0xF8 ) == 0xF0 ) { - if( in.size( 4 ) >= 4 ) { - const char32_t c1 = in.peek_byte( 1 ); - const char32_t c2 = in.peek_byte( 2 ); - const char32_t c3 = in.peek_byte( 3 ); - if( ( ( c1 & 0xC0 ) == 0x80 ) && ( ( c2 & 0xC0 ) == 0x80 ) && ( ( c3 & 0xC0 ) == 0x80 ) ) { - c0 &= 0x07; - c0 <<= 6; - c0 |= ( c1 & 0x3F ); - c0 <<= 6; - c0 |= ( c2 & 0x3F ); - c0 <<= 6; - c0 |= ( c3 & 0x3F ); - if( c0 >= 0x10000 && c0 <= 0x10FFFF ) { - return { c0, 4 }; - } - } + } + } + else if( ( c0 & 0xF8 ) == 0xF0 ) { + if( s >= 4 ) { + const char32_t c1 = in.peek_uint8( 1 ); + const char32_t c2 = in.peek_uint8( 2 ); + const char32_t c3 = in.peek_uint8( 3 ); + if( ( ( c1 & 0xC0 ) == 0x80 ) && ( ( c2 & 0xC0 ) == 0x80 ) && ( ( c3 & 0xC0 ) == 0x80 ) ) { + c0 &= 0x07; + c0 <<= 6; + c0 |= ( c1 & 0x3F ); + c0 <<= 6; + c0 |= ( c2 & 0x3F ); + c0 <<= 6; + c0 |= ( c3 & 0x3F ); + if( c0 >= 0x10000 && c0 <= 0x10FFFF ) { + return { c0, 4 }; } } - return { 0, 0 }; } - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + } + return { 0, 0 }; + } + }; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/pegtl_string.hpp b/include/tao/json/external/pegtl/internal/pegtl_string.hpp index 1e9b48ff..894b9d71 100644 --- a/include/tao/json/external/pegtl/internal/pegtl_string.hpp +++ b/include/tao/json/external/pegtl/internal/pegtl_string.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_TAOCPP_JSON_PEGTL_STRING_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_TAOCPP_JSON_PEGTL_STRING_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_PEGTL_STRING_HPP +#define TAO_JSON_PEGTL_INTERNAL_PEGTL_STRING_HPP #include #include @@ -10,89 +10,81 @@ #include "../ascii.hpp" #include "../config.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + // Inspired by https://github.com/irrequietus/typestring + // Rewritten and reduced to what is needed for the PEGTL + // and to work with Visual Studio 2015. + + template< typename, typename, typename, typename, typename, typename, typename, typename > + struct string_join; + + template< template< char... > class S, char... C0s, char... C1s, char... C2s, char... C3s, char... C4s, char... C5s, char... C6s, char... C7s > + struct string_join< S< C0s... >, S< C1s... >, S< C2s... >, S< C3s... >, S< C4s... >, S< C5s... >, S< C6s... >, S< C7s... > > + { + using type = S< C0s..., C1s..., C2s..., C3s..., C4s..., C5s..., C6s..., C7s... >; + }; + + template< template< char... > class S, char, bool > + struct string_at + { + using type = S<>; + }; + + template< template< char... > class S, char C > + struct string_at< S, C, true > + { + using type = S< C >; + }; + + template< typename T, std::size_t S > + struct string_max_length { - // Inspired by https://github.com/irrequietus/typestring - // Rewritten and reduced to what is needed for the PEGTL - // and to work with Visual Studio 2015. - - namespace internal - { - template< typename, typename, typename, typename, typename, typename, typename, typename > - struct string_join; - - template< template< char... > class S, char... C0s, char... C1s, char... C2s, char... C3s, char... C4s, char... C5s, char... C6s, char... C7s > - struct string_join< S< C0s... >, S< C1s... >, S< C2s... >, S< C3s... >, S< C4s... >, S< C5s... >, S< C6s... >, S< C7s... > > - { - using type = S< C0s..., C1s..., C2s..., C3s..., C4s..., C5s..., C6s..., C7s... >; - }; - - template< template< char... > class S, char, bool > - struct string_at - { - using type = S<>; - }; - - template< template< char... > class S, char C > - struct string_at< S, C, true > - { - using type = S< C >; - }; - - template< typename T, std::size_t S > - struct string_max_length - { - static_assert( S <= 512, "String longer than 512 (excluding terminating \\0)!" ); - using type = T; - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao - -#define TAOCPP_JSON_PEGTL_INTERNAL_EMPTY() -#define TAOCPP_JSON_PEGTL_INTERNAL_DEFER( X ) X TAOCPP_JSON_PEGTL_INTERNAL_EMPTY() -#define TAOCPP_JSON_PEGTL_INTERNAL_EXPAND( ... ) __VA_ARGS__ - -#define TAOCPP_JSON_PEGTL_INTERNAL_STRING_AT( S, x, n ) \ - tao::TAOCPP_JSON_PEGTL_NAMESPACE::internal::string_at< S, ( 0##n < sizeof( x ) ) ? x[ 0##n ] : 0, ( 0##n < sizeof( x ) - 1 ) >::type - -#define TAOCPP_JSON_PEGTL_INTERNAL_JOIN_8( M, S, x, n ) \ - tao::TAOCPP_JSON_PEGTL_NAMESPACE::internal::string_join< TAOCPP_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##0 ), \ - TAOCPP_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##1 ), \ - TAOCPP_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##2 ), \ - TAOCPP_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##3 ), \ - TAOCPP_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##4 ), \ - TAOCPP_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##5 ), \ - TAOCPP_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##6 ), \ - TAOCPP_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##7 ) >::type - -#define TAOCPP_JSON_PEGTL_INTERNAL_STRING_8( S, x, n ) \ - TAOCPP_JSON_PEGTL_INTERNAL_JOIN_8( TAOCPP_JSON_PEGTL_INTERNAL_STRING_AT, S, x, n ) - -#define TAOCPP_JSON_PEGTL_INTERNAL_STRING_64( S, x, n ) \ - TAOCPP_JSON_PEGTL_INTERNAL_JOIN_8( TAOCPP_JSON_PEGTL_INTERNAL_STRING_8, S, x, n ) - -#define TAOCPP_JSON_PEGTL_INTERNAL_STRING_512( S, x, n ) \ - TAOCPP_JSON_PEGTL_INTERNAL_JOIN_8( TAOCPP_JSON_PEGTL_INTERNAL_STRING_64, S, x, n ) - -#define TAOCPP_JSON_PEGTL_INTERNAL_STRING( S, x ) \ - TAOCPP_JSON_PEGTL_INTERNAL_EXPAND( \ - TAOCPP_JSON_PEGTL_INTERNAL_EXPAND( \ - TAOCPP_JSON_PEGTL_INTERNAL_EXPAND( \ - tao::TAOCPP_JSON_PEGTL_NAMESPACE::internal::string_max_length< TAOCPP_JSON_PEGTL_INTERNAL_STRING_512( S, x, ), sizeof( x ) - 1 >::type ) ) ) - -#define TAOCPP_JSON_PEGTL_STRING( x ) \ - TAOCPP_JSON_PEGTL_INTERNAL_STRING( tao::TAOCPP_JSON_PEGTL_NAMESPACE::ascii::string, x ) - -#define TAOCPP_JSON_PEGTL_ISTRING( x ) \ - TAOCPP_JSON_PEGTL_INTERNAL_STRING( tao::TAOCPP_JSON_PEGTL_NAMESPACE::ascii::istring, x ) - -#define TAOCPP_JSON_PEGTL_KEYWORD( x ) \ - TAOCPP_JSON_PEGTL_INTERNAL_STRING( tao::TAOCPP_JSON_PEGTL_NAMESPACE::ascii::keyword, x ) + static_assert( S <= 512, "String longer than 512 (excluding terminating \\0)!" ); + using type = T; + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#define TAO_JSON_PEGTL_INTERNAL_EMPTY() +#define TAO_JSON_PEGTL_INTERNAL_DEFER( X ) X TAO_JSON_PEGTL_INTERNAL_EMPTY() +#define TAO_JSON_PEGTL_INTERNAL_EXPAND( ... ) __VA_ARGS__ + +#define TAO_JSON_PEGTL_INTERNAL_STRING_AT( S, x, n ) \ + TAO_JSON_PEGTL_NAMESPACE::internal::string_at< S, ( 0##n < ( sizeof( x ) / sizeof( char ) ) ) ? ( x )[ 0##n ] : 0, ( 0##n < ( sizeof( x ) / sizeof( char ) ) - 1 ) >::type + +#define TAO_JSON_PEGTL_INTERNAL_JOIN_8( M, S, x, n ) \ + TAO_JSON_PEGTL_NAMESPACE::internal::string_join< TAO_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##0 ), \ + TAO_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##1 ), \ + TAO_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##2 ), \ + TAO_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##3 ), \ + TAO_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##4 ), \ + TAO_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##5 ), \ + TAO_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##6 ), \ + TAO_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##7 ) >::type + +#define TAO_JSON_PEGTL_INTERNAL_STRING_8( S, x, n ) \ + TAO_JSON_PEGTL_INTERNAL_JOIN_8( TAO_JSON_PEGTL_INTERNAL_STRING_AT, S, x, n ) + +#define TAO_JSON_PEGTL_INTERNAL_STRING_64( S, x, n ) \ + TAO_JSON_PEGTL_INTERNAL_JOIN_8( TAO_JSON_PEGTL_INTERNAL_STRING_8, S, x, n ) + +#define TAO_JSON_PEGTL_INTERNAL_STRING_512( S, x, n ) \ + TAO_JSON_PEGTL_INTERNAL_JOIN_8( TAO_JSON_PEGTL_INTERNAL_STRING_64, S, x, n ) + +#define TAO_JSON_PEGTL_INTERNAL_STRING( S, x ) \ + TAO_JSON_PEGTL_INTERNAL_EXPAND( \ + TAO_JSON_PEGTL_INTERNAL_EXPAND( \ + TAO_JSON_PEGTL_INTERNAL_EXPAND( \ + TAO_JSON_PEGTL_NAMESPACE::internal::string_max_length< TAO_JSON_PEGTL_INTERNAL_STRING_512( S, x, ), sizeof( x ) - 1 >::type ) ) ) + +#define TAO_JSON_PEGTL_STRING( x ) \ + TAO_JSON_PEGTL_INTERNAL_STRING( TAO_JSON_PEGTL_NAMESPACE::ascii::string, x ) + +#define TAO_JSON_PEGTL_ISTRING( x ) \ + TAO_JSON_PEGTL_INTERNAL_STRING( TAO_JSON_PEGTL_NAMESPACE::ascii::istring, x ) + +#define TAO_JSON_PEGTL_KEYWORD( x ) \ + TAO_JSON_PEGTL_INTERNAL_STRING( TAO_JSON_PEGTL_NAMESPACE::ascii::keyword, x ) #endif diff --git a/include/tao/json/external/pegtl/internal/plus.hpp b/include/tao/json/external/pegtl/internal/plus.hpp index 03a87c81..0f5c0cd3 100644 --- a/include/tao/json/external/pegtl/internal/plus.hpp +++ b/include/tao/json/external/pegtl/internal/plus.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PLUS_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_PLUS_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_PLUS_HPP +#define TAO_JSON_PEGTL_INTERNAL_PLUS_HPP #include @@ -19,43 +19,35 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + // While plus<> could easily be implemented with + // seq< Rule, Rules ..., star< Rule, Rules ... > > we + // provide an explicit implementation to optimise away + // the otherwise created input mark. + + template< typename Rule, typename... Rules > + struct plus { - namespace internal + using analyze_t = analysis::generic< analysis::rule_type::seq, Rule, Rules..., opt< plus > >; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) { - // While plus<> could easily be implemented with - // seq< Rule, Rules ..., star< Rule, Rules ... > > we - // provide an explicit implementation to optimise away - // the otherwise created input mark. - - template< typename Rule, typename... Rules > - struct plus - { - using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rule, Rules..., opt< plus > >; - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - return duseltronik< seq< Rule, Rules... >, A, M, Action, Control >::match( in, st... ) && duseltronik< star< Rule, Rules... >, A, M, Action, Control >::match( in, st... ); - } - }; - - template< typename Rule, typename... Rules > - struct skip_control< plus< Rule, Rules... > > : std::true_type - { - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + return seq< Rule, Rules... >::template match< A, M, Action, Control >( in, st... ) && star< Rule, Rules... >::template match< A, M, Action, Control >( in, st... ); + } + }; + + template< typename Rule, typename... Rules > + inline constexpr bool skip_control< plus< Rule, Rules... > > = true; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/raise.hpp b/include/tao/json/external/pegtl/internal/raise.hpp index c1eb87ed..29d1c926 100644 --- a/include/tao/json/external/pegtl/internal/raise.hpp +++ b/include/tao/json/external/pegtl/internal/raise.hpp @@ -1,10 +1,11 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RAISE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RAISE_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_RAISE_HPP +#define TAO_JSON_PEGTL_INTERNAL_RAISE_HPP #include +#include #include #include "../config.hpp" @@ -15,43 +16,38 @@ #include "../apply_mode.hpp" #include "../rewind_mode.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename T > + struct raise { - namespace internal + using analyze_t = analysis::generic< analysis::rule_type::any >; + +#if defined( _MSC_VER ) +#pragma warning( push ) +#pragma warning( disable : 4702 ) +#endif + template< apply_mode, + rewind_mode, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) { - template< typename T > - struct raise - { - using analyze_t = analysis::generic< analysis::rule_type::ANY >; - - template< apply_mode, - rewind_mode, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - Control< T >::raise( const_cast< const Input& >( in ), st... ); + Control< T >::raise( static_cast< const Input& >( in ), st... ); + throw std::logic_error( "code should be unreachable: Control< T >::raise() did not throw an exception" ); // LCOV_EXCL_LINE #if defined( _MSC_VER ) - __assume( false ); // LCOV_EXCL_LINE -#else - std::abort(); // LCOV_EXCL_LINE +#pragma warning( pop ) #endif - } - }; - - template< typename T > - struct skip_control< raise< T > > : std::true_type - { - }; - - } // namespace internal + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename T > + inline constexpr bool skip_control< raise< T > > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/range.hpp b/include/tao/json/external/pegtl/internal/range.hpp index e88c90de..66f7d7c4 100644 --- a/include/tao/json/external/pegtl/internal/range.hpp +++ b/include/tao/json/external/pegtl/internal/range.hpp @@ -1,60 +1,51 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RANGE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RANGE_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_RANGE_HPP +#define TAO_JSON_PEGTL_INTERNAL_RANGE_HPP #include "../config.hpp" -#include "bump_help.hpp" #include "result_on_found.hpp" #include "skip_control.hpp" #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< result_on_found R, typename Peek, typename Peek::data_t Lo, typename Peek::data_t Hi > + struct range { - namespace internal + static_assert( Lo <= Hi, "invalid range detected" ); + + using analyze_t = analysis::generic< analysis::rule_type::any >; + + template< int Eol > + static constexpr bool can_match_eol = ( ( ( Lo <= Eol ) && ( Eol <= Hi ) ) == bool( R ) ); + + template< typename Input > + [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( Peek::max_input_size ) ) ) { - template< result_on_found R, typename Peek, typename Peek::data_t Lo, typename Peek::data_t Hi > - struct range - { - using analyze_t = analysis::generic< analysis::rule_type::ANY >; - - template< int Eol > - struct can_match_eol - { - static constexpr bool value = ( ( ( Lo <= Eol ) && ( Eol <= Hi ) ) == bool( R ) ); - }; - - template< typename Input > - static bool match( Input& in ) - { - using eol_t = typename Input::eol_t; - - if( !in.empty() ) { - if( const auto t = Peek::peek( in ) ) { - if( ( ( Lo <= t.data ) && ( t.data <= Hi ) ) == bool( R ) ) { - bump_impl< can_match_eol< eol_t::ch >::value >::bump( in, t.size ); - return true; - } + if( const std::size_t s = in.size( Peek::max_input_size ); s >= Peek::min_input_size ) { + if( const auto t = Peek::peek( in, s ) ) { + if( ( ( Lo <= t.data ) && ( t.data <= Hi ) ) == bool( R ) ) { + if constexpr( can_match_eol< Input::eol_t::ch > ) { + in.bump( t.size ); } + else { + in.bump_in_this_line( t.size ); + } + return true; } - return false; } - }; - - template< result_on_found R, typename Peek, typename Peek::data_t Lo, typename Peek::data_t Hi > - struct skip_control< range< R, Peek, Lo, Hi > > : std::true_type - { - }; - - } // namespace internal + } + return false; + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< result_on_found R, typename Peek, typename Peek::data_t Lo, typename Peek::data_t Hi > + inline constexpr bool skip_control< range< R, Peek, Lo, Hi > > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/ranges.hpp b/include/tao/json/external/pegtl/internal/ranges.hpp index 40dcc4b7..3bc33d12 100644 --- a/include/tao/json/external/pegtl/internal/ranges.hpp +++ b/include/tao/json/external/pegtl/internal/ranges.hpp @@ -1,102 +1,93 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RANGES_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RANGES_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_RANGES_HPP +#define TAO_JSON_PEGTL_INTERNAL_RANGES_HPP #include "../config.hpp" -#include "bump_help.hpp" #include "range.hpp" #include "skip_control.hpp" #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< int Eol, typename Char, Char... Cs > + struct ranges_impl; + + template< int Eol, typename Char > + struct ranges_impl< Eol, Char > { - namespace internal + static constexpr bool can_match_eol = false; + + [[nodiscard]] static bool match( const Char /*unused*/ ) noexcept { - template< int Eol, typename Char, Char... Cs > - struct ranges_impl; + return false; + } + }; - template< int Eol, typename Char > - struct ranges_impl< Eol, Char > - { - static constexpr bool can_match_eol = false; + template< int Eol, typename Char, Char Eq > + struct ranges_impl< Eol, Char, Eq > + { + static constexpr bool can_match_eol = ( Eq == Eol ); - static bool match( const Char ) noexcept - { - return false; - } - }; + [[nodiscard]] static bool match( const Char c ) noexcept + { + return c == Eq; + } + }; - template< int Eol, typename Char, Char Eq > - struct ranges_impl< Eol, Char, Eq > - { - static constexpr bool can_match_eol = ( Eq == Eol ); + template< int Eol, typename Char, Char Lo, Char Hi, Char... Cs > + struct ranges_impl< Eol, Char, Lo, Hi, Cs... > + { + static_assert( Lo <= Hi, "invalid range detected" ); - static bool match( const Char c ) noexcept - { - return c == Eq; - } - }; + static constexpr bool can_match_eol = ( ( ( Lo <= Eol ) && ( Eol <= Hi ) ) || ranges_impl< Eol, Char, Cs... >::can_match_eol ); - template< int Eol, typename Char, Char Lo, Char Hi, Char... Cs > - struct ranges_impl< Eol, Char, Lo, Hi, Cs... > - { - static constexpr bool can_match_eol = ( ( ( Lo <= Eol ) && ( Eol <= Hi ) ) || ranges_impl< Eol, Char, Cs... >::can_match_eol ); + [[nodiscard]] static bool match( const Char c ) noexcept + { + return ( ( Lo <= c ) && ( c <= Hi ) ) || ranges_impl< Eol, Char, Cs... >::match( c ); + } + }; - static bool match( const Char c ) noexcept - { - return ( ( Lo <= c ) && ( c <= Hi ) ) || ranges_impl< Eol, Char, Cs... >::match( c ); - } - }; - - template< typename Peek, typename Peek::data_t... Cs > - struct ranges - { - using analyze_t = analysis::generic< analysis::rule_type::ANY >; - - template< int Eol > - struct can_match_eol - { - static constexpr bool value = ranges_impl< Eol, typename Peek::data_t, Cs... >::can_match_eol; - }; - - template< typename Input > - static bool match( Input& in ) - { - using eol_t = typename Input::eol_t; - - if( !in.empty() ) { - if( const auto t = Peek::peek( in ) ) { - if( ranges_impl< eol_t::ch, typename Peek::data_t, Cs... >::match( t.data ) ) { - bump_impl< can_match_eol< eol_t::ch >::value >::bump( in, t.size ); - return true; - } + template< typename Peek, typename Peek::data_t... Cs > + struct ranges + { + using analyze_t = analysis::generic< analysis::rule_type::any >; + + template< int Eol > + static constexpr bool can_match_eol = ranges_impl< Eol, typename Peek::data_t, Cs... >::can_match_eol; + + template< typename Input > + [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( Peek::max_input_size ) ) ) + { + if( const std::size_t s = in.size( Peek::max_input_size ); s >= Peek::min_input_size ) { + if( const auto t = Peek::peek( in, s ) ) { + if( ranges_impl< Input::eol_t::ch, typename Peek::data_t, Cs... >::match( t.data ) ) { + if constexpr( can_match_eol< Input::eol_t::ch > ) { + in.bump( t.size ); + } + else { + in.bump_in_this_line( t.size ); } + return true; } - return false; } - }; - - template< typename Peek, typename Peek::data_t Lo, typename Peek::data_t Hi > - struct ranges< Peek, Lo, Hi > - : range< result_on_found::SUCCESS, Peek, Lo, Hi > - { - }; - - template< typename Peek, typename Peek::data_t... Cs > - struct skip_control< ranges< Peek, Cs... > > : std::true_type - { - }; - - } // namespace internal + } + return false; + } + }; + + template< typename Peek, typename Peek::data_t Lo, typename Peek::data_t Hi > + struct ranges< Peek, Lo, Hi > + : range< result_on_found::success, Peek, Lo, Hi > + { + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Peek, typename Peek::data_t... Cs > + inline constexpr bool skip_control< ranges< Peek, Cs... > > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/read_uint.hpp b/include/tao/json/external/pegtl/internal/read_uint.hpp new file mode 100644 index 00000000..817f5faa --- /dev/null +++ b/include/tao/json/external/pegtl/internal/read_uint.hpp @@ -0,0 +1,77 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_INTERNAL_READ_UINT_HPP +#define TAO_JSON_PEGTL_INTERNAL_READ_UINT_HPP + +#include + +#include "../config.hpp" + +#include "endian.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ + struct read_uint16_be + { + using type = std::uint16_t; + + [[nodiscard]] static std::uint16_t read( const void* d ) noexcept + { + return be_to_h< std::uint16_t >( d ); + } + }; + + struct read_uint16_le + { + using type = std::uint16_t; + + [[nodiscard]] static std::uint16_t read( const void* d ) noexcept + { + return le_to_h< std::uint16_t >( d ); + } + }; + + struct read_uint32_be + { + using type = std::uint32_t; + + [[nodiscard]] static std::uint32_t read( const void* d ) noexcept + { + return be_to_h< std::uint32_t >( d ); + } + }; + + struct read_uint32_le + { + using type = std::uint32_t; + + [[nodiscard]] static std::uint32_t read( const void* d ) noexcept + { + return le_to_h< std::uint32_t >( d ); + } + }; + + struct read_uint64_be + { + using type = std::uint64_t; + + [[nodiscard]] static std::uint64_t read( const void* d ) noexcept + { + return be_to_h< std::uint64_t >( d ); + } + }; + + struct read_uint64_le + { + using type = std::uint64_t; + + [[nodiscard]] static std::uint64_t read( const void* d ) noexcept + { + return le_to_h< std::uint64_t >( d ); + } + }; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/json/external/pegtl/internal/rematch.hpp b/include/tao/json/external/pegtl/internal/rematch.hpp new file mode 100644 index 00000000..5f99f266 --- /dev/null +++ b/include/tao/json/external/pegtl/internal/rematch.hpp @@ -0,0 +1,69 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_INTERNAL_REMATCH_HPP +#define TAO_JSON_PEGTL_INTERNAL_REMATCH_HPP + +#include "../config.hpp" + +#include "skip_control.hpp" + +#include "../apply_mode.hpp" +#include "../memory_input.hpp" +#include "../rewind_mode.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::internal +{ + template< typename Head, typename... Rules > + struct rematch; + + template< typename Head > + struct rematch< Head > + { + using analyze_t = typename Head::analyze_t; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + return Control< Head >::template match< A, M, Action, Control >( in, st... ); + } + }; + + template< typename Head, typename Rule, typename... Rules > + struct rematch< Head, Rule, Rules... > + { + using analyze_t = typename Head::analyze_t; // NOTE: Rule and Rules are ignored for analyze(). + + template< apply_mode A, + rewind_mode, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< rewind_mode::required >(); + + if( Control< Head >::template match< A, rewind_mode::active, Action, Control >( in, st... ) ) { + memory_input< Input::tracking_mode_v, typename Input::eol_t, typename Input::source_t > i2( m.iterator(), in.current(), in.source() ); + return m( ( Control< Rule >::template match< A, rewind_mode::active, Action, Control >( i2, st... ) && ... && ( i2.restart( m ), Control< Rules >::template match< A, rewind_mode::active, Action, Control >( i2, st... ) ) ) ); + } + return false; + } + }; + + template< typename Head, typename... Rules > + inline constexpr bool skip_control< rematch< Head, Rules... > > = true; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal + +#endif diff --git a/include/tao/json/external/pegtl/internal/rep.hpp b/include/tao/json/external/pegtl/internal/rep.hpp index 255de231..607e896c 100644 --- a/include/tao/json/external/pegtl/internal/rep.hpp +++ b/include/tao/json/external/pegtl/internal/rep.hpp @@ -1,12 +1,11 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REP_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REP_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_REP_HPP +#define TAO_JSON_PEGTL_INTERNAL_REP_HPP #include "../config.hpp" -#include "rule_conjunction.hpp" #include "skip_control.hpp" #include "trivial.hpp" @@ -15,61 +14,53 @@ #include "../analysis/counted.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< unsigned Num, typename... Rules > - struct rep; - - template< unsigned Num > - struct rep< Num > - : trivial< true > - { - }; + template< unsigned Num, typename... Rules > + struct rep; - template< typename Rule, typename... Rules > - struct rep< 0, Rule, Rules... > - : trivial< true > - { - }; + template< unsigned Num > + struct rep< Num > + : trivial< true > + { + }; - template< unsigned Num, typename... Rules > - struct rep - { - using analyze_t = analysis::counted< analysis::rule_type::SEQ, Num, Rules... >; + template< typename Rule, typename... Rules > + struct rep< 0, Rule, Rules... > + : trivial< true > + { + }; - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< M >(); - using m_t = decltype( m ); + template< unsigned Num, typename... Rules > + struct rep + { + using analyze_t = analysis::counted< analysis::rule_type::seq, Num, Rules... >; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< M >(); + using m_t = decltype( m ); - for( unsigned i = 0; i != Num; ++i ) { - if( !rule_conjunction< Rules... >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) ) { - return false; - } - } - return m( true ); + for( unsigned i = 0; i != Num; ++i ) { + if( !( Control< Rules >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) && ... ) ) { + return false; } - }; - - template< unsigned Num, typename... Rules > - struct skip_control< rep< Num, Rules... > > : std::true_type - { - }; - - } // namespace internal + } + return m( true ); + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< unsigned Num, typename... Rules > + inline constexpr bool skip_control< rep< Num, Rules... > > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/rep_min.hpp b/include/tao/json/external/pegtl/internal/rep_min.hpp index 04ede5be..c279bae8 100644 --- a/include/tao/json/external/pegtl/internal/rep_min.hpp +++ b/include/tao/json/external/pegtl/internal/rep_min.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REP_MIN_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REP_MIN_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_REP_MIN_HPP +#define TAO_JSON_PEGTL_INTERNAL_REP_MIN_HPP #include "../config.hpp" @@ -10,19 +10,11 @@ #include "seq.hpp" #include "star.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< unsigned Min, typename Rule, typename... Rules > - using rep_min = seq< rep< Min, Rule, Rules... >, star< Rule, Rules... > >; + template< unsigned Min, typename Rule, typename... Rules > + using rep_min = seq< rep< Min, Rule, Rules... >, star< Rule, Rules... > >; - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/rep_min_max.hpp b/include/tao/json/external/pegtl/internal/rep_min_max.hpp index 343df844..b244c87e 100644 --- a/include/tao/json/external/pegtl/internal/rep_min_max.hpp +++ b/include/tao/json/external/pegtl/internal/rep_min_max.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REP_MIN_MAX_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REP_MIN_MAX_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_REP_MIN_MAX_HPP +#define TAO_JSON_PEGTL_INTERNAL_REP_MIN_MAX_HPP #include @@ -10,7 +10,6 @@ #include "duseltronik.hpp" #include "not_at.hpp" -#include "rule_conjunction.hpp" #include "seq.hpp" #include "skip_control.hpp" #include "trivial.hpp" @@ -20,69 +19,61 @@ #include "../analysis/counted.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< unsigned Min, unsigned Max, typename... Rules > + struct rep_min_max; + + template< unsigned Min, unsigned Max > + struct rep_min_max< Min, Max > + : trivial< false > { - namespace internal - { - template< unsigned Min, unsigned Max, typename... Rules > - struct rep_min_max; - - template< unsigned Min, unsigned Max > - struct rep_min_max< Min, Max > - : trivial< false > - { - static_assert( Min <= Max, "invalid rep_min_max rule (maximum number of repetitions smaller than minimum)" ); - }; - - template< typename Rule, typename... Rules > - struct rep_min_max< 0, 0, Rule, Rules... > - : not_at< Rule, Rules... > - { - }; - - template< unsigned Min, unsigned Max, typename... Rules > - struct rep_min_max - { - using analyze_t = analysis::counted< analysis::rule_type::SEQ, Min, Rules... >; - - static_assert( Min <= Max, "invalid rep_min_max rule (maximum number of repetitions smaller than minimum)" ); - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< M >(); - using m_t = decltype( m ); - - for( unsigned i = 0; i != Min; ++i ) { - if( !rule_conjunction< Rules... >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) ) { - return false; - } - } - for( unsigned i = Min; i != Max; ++i ) { - if( !duseltronik< seq< Rules... >, A, rewind_mode::REQUIRED, Action, Control >::match( in, st... ) ) { - return m( true ); - } - } - return m( duseltronik< not_at< Rules... >, A, m_t::next_rewind_mode, Action, Control >::match( in, st... ) ); // NOTE that not_at<> will always rewind. - } - }; + static_assert( Min <= Max ); + }; - template< unsigned Min, unsigned Max, typename... Rules > - struct skip_control< rep_min_max< Min, Max, Rules... > > : std::true_type - { - }; + template< typename Rule, typename... Rules > + struct rep_min_max< 0, 0, Rule, Rules... > + : not_at< Rule, Rules... > + { + }; - } // namespace internal + template< unsigned Min, unsigned Max, typename... Rules > + struct rep_min_max + { + using analyze_t = analysis::counted< analysis::rule_type::seq, Min, Rules... >; + + static_assert( Min <= Max ); + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< M >(); + using m_t = decltype( m ); + + for( unsigned i = 0; i != Min; ++i ) { + if( !( Control< Rules >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) && ... ) ) { + return false; + } + } + for( unsigned i = Min; i != Max; ++i ) { + if( !duseltronik< seq< Rules... >, A, rewind_mode::required, Action, Control >::match( in, st... ) ) { + return m( true ); + } + } + return m( duseltronik< not_at< Rules... >, A, m_t::next_rewind_mode, Action, Control >::match( in, st... ) ); // NOTE that not_at<> will always rewind. + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< unsigned Min, unsigned Max, typename... Rules > + inline constexpr bool skip_control< rep_min_max< Min, Max, Rules... > > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/rep_opt.hpp b/include/tao/json/external/pegtl/internal/rep_opt.hpp index 00e31a27..4e56902c 100644 --- a/include/tao/json/external/pegtl/internal/rep_opt.hpp +++ b/include/tao/json/external/pegtl/internal/rep_opt.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REP_OPT_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REP_OPT_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_REP_OPT_HPP +#define TAO_JSON_PEGTL_INTERNAL_REP_OPT_HPP #include "../config.hpp" @@ -15,40 +15,32 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< unsigned Max, typename... Rules > + struct rep_opt { - namespace internal + using analyze_t = analysis::generic< analysis::rule_type::opt, Rules... >; + + template< apply_mode A, + rewind_mode, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) { - template< unsigned Max, typename... Rules > - struct rep_opt - { - using analyze_t = analysis::generic< analysis::rule_type::OPT, Rules... >; - - template< apply_mode A, - rewind_mode, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - for( unsigned i = 0; ( i != Max ) && duseltronik< seq< Rules... >, A, rewind_mode::REQUIRED, Action, Control >::match( in, st... ); ++i ) { - } - return true; - } - }; - - template< unsigned Max, typename... Rules > - struct skip_control< rep_opt< Max, Rules... > > : std::true_type - { - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + for( unsigned i = 0; ( i != Max ) && duseltronik< seq< Rules... >, A, rewind_mode::required, Action, Control >::match( in, st... ); ++i ) { + } + return true; + } + }; + + template< unsigned Max, typename... Rules > + inline constexpr bool skip_control< rep_opt< Max, Rules... > > = true; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/require.hpp b/include/tao/json/external/pegtl/internal/require.hpp index 9c2b696b..21cb17e1 100644 --- a/include/tao/json/external/pegtl/internal/require.hpp +++ b/include/tao/json/external/pegtl/internal/require.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REQUIRE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_REQUIRE_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_REQUIRE_HPP +#define TAO_JSON_PEGTL_INTERNAL_REQUIRE_HPP #include "../config.hpp" @@ -11,42 +11,32 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< unsigned Amount > - struct require; - - template<> - struct require< 0 > - : trivial< true > - { - }; - - template< unsigned Amount > - struct require - { - using analyze_t = analysis::generic< analysis::rule_type::OPT >; + template< unsigned Amount > + struct require; - template< typename Input > - static bool match( Input& in ) - { - return in.size( Amount ) >= Amount; - } - }; + template<> + struct require< 0 > + : trivial< true > + { + }; - template< unsigned Amount > - struct skip_control< require< Amount > > : std::true_type - { - }; + template< unsigned Amount > + struct require + { + using analyze_t = analysis::generic< analysis::rule_type::opt >; - } // namespace internal + template< typename Input > + [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( 0 ) ) ) + { + return in.size( Amount ) >= Amount; + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< unsigned Amount > + inline constexpr bool skip_control< require< Amount > > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/result_on_found.hpp b/include/tao/json/external/pegtl/internal/result_on_found.hpp index cc2fe927..a6b8c241 100644 --- a/include/tao/json/external/pegtl/internal/result_on_found.hpp +++ b/include/tao/json/external/pegtl/internal/result_on_found.hpp @@ -1,27 +1,19 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RESULT_ON_FOUND_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RESULT_ON_FOUND_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_RESULT_ON_FOUND_HPP +#define TAO_JSON_PEGTL_INTERNAL_RESULT_ON_FOUND_HPP #include "../config.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + enum class result_on_found : bool { - namespace internal - { - enum class result_on_found : bool - { - SUCCESS = true, - FAILURE = false - }; + success = true, + failure = false + }; - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/rule_conjunction.hpp b/include/tao/json/external/pegtl/internal/rule_conjunction.hpp deleted file mode 100644 index d1e0cda2..00000000 --- a/include/tao/json/external/pegtl/internal/rule_conjunction.hpp +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RULE_CONJUNCTION_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RULE_CONJUNCTION_HPP - -#include "../apply_mode.hpp" -#include "../config.hpp" -#include "../rewind_mode.hpp" - -namespace tao -{ - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< typename... Rules > - struct rule_conjunction; - - template<> - struct rule_conjunction<> - { - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input&, States&&... ) - { - return true; - } - }; - - template< typename... Rules > - struct rule_conjunction - { - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { -#ifdef __cpp_fold_expressions - return ( Control< Rules >::template match< A, M, Action, Control >( in, st... ) && ... ); -#else - bool result = true; - using swallow = bool[]; - (void)swallow{ result = result && Control< Rules >::template match< A, M, Action, Control >( in, st... )... }; - return result; -#endif - } - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao - -#endif diff --git a/include/tao/json/external/pegtl/internal/rules.hpp b/include/tao/json/external/pegtl/internal/rules.hpp index 7fa41c9f..3ff9eec8 100644 --- a/include/tao/json/external/pegtl/internal/rules.hpp +++ b/include/tao/json/external/pegtl/internal/rules.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RULES_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_RULES_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_RULES_HPP +#define TAO_JSON_PEGTL_INTERNAL_RULES_HPP #include "action.hpp" #include "alnum.hpp" @@ -31,7 +31,6 @@ #include "list_must.hpp" #include "list_tail.hpp" #include "list_tail_pad.hpp" -#include "minus.hpp" #include "must.hpp" #include "not_at.hpp" #include "one.hpp" @@ -42,6 +41,7 @@ #include "raise.hpp" #include "range.hpp" #include "ranges.hpp" +#include "rematch.hpp" #include "rep.hpp" #include "rep_min.hpp" #include "rep_min_max.hpp" diff --git a/include/tao/json/external/pegtl/internal/seq.hpp b/include/tao/json/external/pegtl/internal/seq.hpp index 142d4109..8528fec5 100644 --- a/include/tao/json/external/pegtl/internal/seq.hpp +++ b/include/tao/json/external/pegtl/internal/seq.hpp @@ -1,12 +1,11 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_SEQ_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_SEQ_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_SEQ_HPP +#define TAO_JSON_PEGTL_INTERNAL_SEQ_HPP #include "../config.hpp" -#include "rule_conjunction.hpp" #include "skip_control.hpp" #include "trivial.hpp" @@ -15,66 +14,60 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< typename... Rules > - struct seq; - - template<> - struct seq<> - : trivial< true > - { - }; - - template< typename Rule > - struct seq< Rule > - { - using analyze_t = typename Rule::analyze_t; - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - return Control< Rule >::template match< A, M, Action, Control >( in, st... ); - } - }; - - template< typename... Rules > - struct seq - { - using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rules... >; + template< typename... Rules > + struct seq; - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< M >(); - using m_t = decltype( m ); - return m( rule_conjunction< Rules... >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) ); - } - }; + template<> + struct seq<> + : trivial< true > + { + }; - template< typename... Rules > - struct skip_control< seq< Rules... > > : std::true_type - { - }; + template< typename Rule > + struct seq< Rule > + { + using analyze_t = typename Rule::analyze_t; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + return Control< Rule >::template match< A, M, Action, Control >( in, st... ); + } + }; - } // namespace internal + template< typename... Rules > + struct seq + { + using analyze_t = analysis::generic< analysis::rule_type::seq, Rules... >; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< M >(); + using m_t = decltype( m ); + return m( ( Control< Rules >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) && ... ) ); + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename... Rules > + inline constexpr bool skip_control< seq< Rules... > > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/skip_control.hpp b/include/tao/json/external/pegtl/internal/skip_control.hpp index 4c1f71fb..7b3d6098 100644 --- a/include/tao/json/external/pegtl/internal/skip_control.hpp +++ b/include/tao/json/external/pegtl/internal/skip_control.hpp @@ -1,35 +1,25 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_SKIP_CONTROL_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_SKIP_CONTROL_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_SKIP_CONTROL_HPP +#define TAO_JSON_PEGTL_INTERNAL_SKIP_CONTROL_HPP #include #include "../config.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - // This class is a simple tagging mechanism. - // By default, skip_control< Rule >::value - // is 'false'. Each internal (!) rule that should - // be hidden from the control and action class' - // callbacks simply specializes skip_control<> - // to return 'true' for the above expression. + // This class is a simple tagging mechanism. + // By default, skip_control< Rule > is 'false'. + // Each internal (!) rule that should be hidden + // from the control and action class' callbacks + // simply specializes skip_control<> to return + // 'true' for the above expression. - template< typename Rule > - struct skip_control : std::false_type - { - }; + template< typename Rule > + inline constexpr bool skip_control = false; - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/sor.hpp b/include/tao/json/external/pegtl/internal/sor.hpp index 684107f1..66ca2016 100644 --- a/include/tao/json/external/pegtl/internal/sor.hpp +++ b/include/tao/json/external/pegtl/internal/sor.hpp @@ -1,74 +1,60 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_SOR_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_SOR_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_SOR_HPP +#define TAO_JSON_PEGTL_INTERNAL_SOR_HPP + +#include #include "../config.hpp" #include "skip_control.hpp" +#include "trivial.hpp" #include "../apply_mode.hpp" #include "../rewind_mode.hpp" #include "../analysis/generic.hpp" -#include "integer_sequence.hpp" - -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< typename... Rules > - struct sor; - - template<> - struct sor<> - : trivial< false > - { - }; - - template< typename... Rules > - struct sor - : sor< index_sequence_for< Rules... >, Rules... > - { - }; + template< typename... Rules > + struct sor; - template< std::size_t... Indices, typename... Rules > - struct sor< index_sequence< Indices... >, Rules... > - { - using analyze_t = analysis::generic< analysis::rule_type::SOR, Rules... >; - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { -#ifdef __cpp_fold_expressions - return ( Control< Rules >::template match < A, ( Indices == ( sizeof...( Rules ) - 1 ) ) ? M : rewind_mode::REQUIRED, Action, Control > ( in, st... ) || ... ); -#else - bool result = false; - using swallow = bool[]; - (void)swallow{ result = result || Control< Rules >::template match < A, ( Indices == ( sizeof...( Rules ) - 1 ) ) ? M : rewind_mode::REQUIRED, Action, Control > ( in, st... )... }; - return result; -#endif - } - }; + template<> + struct sor<> + : trivial< false > + { + }; - template< typename... Rules > - struct skip_control< sor< Rules... > > : std::true_type - { - }; + template< typename... Rules > + struct sor + : sor< std::index_sequence_for< Rules... >, Rules... > + { + }; - } // namespace internal + template< std::size_t... Indices, typename... Rules > + struct sor< std::index_sequence< Indices... >, Rules... > + { + using analyze_t = analysis::generic< analysis::rule_type::sor, Rules... >; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + return ( Control< Rules >::template match< A, ( ( Indices == ( sizeof...( Rules ) - 1 ) ) ? M : rewind_mode::required ), Action, Control >( in, st... ) || ... ); + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename... Rules > + inline constexpr bool skip_control< sor< Rules... > > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/star.hpp b/include/tao/json/external/pegtl/internal/star.hpp index da771cee..53795b94 100644 --- a/include/tao/json/external/pegtl/internal/star.hpp +++ b/include/tao/json/external/pegtl/internal/star.hpp @@ -1,14 +1,13 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_STAR_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_STAR_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_STAR_HPP +#define TAO_JSON_PEGTL_INTERNAL_STAR_HPP #include #include "../config.hpp" -#include "duseltronik.hpp" #include "seq.hpp" #include "skip_control.hpp" @@ -17,40 +16,32 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Rule, typename... Rules > + struct star { - namespace internal + using analyze_t = analysis::generic< analysis::rule_type::opt, Rule, Rules..., star >; + + template< apply_mode A, + rewind_mode, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) { - template< typename Rule, typename... Rules > - struct star - { - using analyze_t = analysis::generic< analysis::rule_type::OPT, Rule, Rules..., star >; - - template< apply_mode A, - rewind_mode, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - while( duseltronik< seq< Rule, Rules... >, A, rewind_mode::REQUIRED, Action, Control >::match( in, st... ) ) { - } - return true; - } - }; - - template< typename Rule, typename... Rules > - struct skip_control< star< Rule, Rules... > > : std::true_type - { - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + while( seq< Rule, Rules... >::template match< A, rewind_mode::required, Action, Control >( in, st... ) ) { + } + return true; + } + }; + + template< typename Rule, typename... Rules > + inline constexpr bool skip_control< star< Rule, Rules... > > = true; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/star_must.hpp b/include/tao/json/external/pegtl/internal/star_must.hpp index 19584b98..eddec9f5 100644 --- a/include/tao/json/external/pegtl/internal/star_must.hpp +++ b/include/tao/json/external/pegtl/internal/star_must.hpp @@ -1,27 +1,19 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_STAR_MUST_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_STAR_MUST_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_STAR_MUST_HPP +#define TAO_JSON_PEGTL_INTERNAL_STAR_MUST_HPP #include "../config.hpp" #include "if_must.hpp" #include "star.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< typename Cond, typename... Rules > - using star_must = star< if_must< Cond, Rules... > >; + template< typename Cond, typename... Rules > + using star_must = star< if_must< false, Cond, Rules... > >; - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/state.hpp b/include/tao/json/external/pegtl/internal/state.hpp index 92bfd3b9..b87b8c9f 100644 --- a/include/tao/json/external/pegtl/internal/state.hpp +++ b/include/tao/json/external/pegtl/internal/state.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_STATE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_STATE_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_STATE_HPP +#define TAO_JSON_PEGTL_INTERNAL_STATE_HPP #include "../config.hpp" @@ -15,69 +15,35 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename State, typename... Rules > + struct state { - namespace internal + using analyze_t = analysis::generic< analysis::rule_type::seq, Rules... >; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) { - template< typename State, typename... Rules > - struct state - { - using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rules... >; - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static auto success( State& s, const Input& in, States&&... st ) -> decltype( s.template success< A, M, Action, Control >( in, st... ), void() ) - { - s.template success< A, M, Action, Control >( in, st... ); - } - - // NOTE: The additional "int = 0" is a work-around for missing expression SFINAE in VS2015. - - template< apply_mode, - rewind_mode, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States, - int = 0 > - static auto success( State& s, const Input& in, States&&... st ) -> decltype( s.success( in, st... ), void() ) - { - s.success( in, st... ); - } - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - State s( const_cast< const Input& >( in ), st... ); - - if( duseltronik< seq< Rules... >, A, M, Action, Control >::match( in, s ) ) { - success< A, M, Action, Control >( s, in, st... ); - return true; - } - return false; - } - }; - - template< typename State, typename... Rules > - struct skip_control< state< State, Rules... > > : std::true_type - { - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + State s( static_cast< const Input& >( in ), st... ); + if( duseltronik< seq< Rules... >, A, M, Action, Control >::match( in, s ) ) { + s.success( static_cast< const Input& >( in ), st... ); + return true; + } + return false; + } + }; + + template< typename State, typename... Rules > + inline constexpr bool skip_control< state< State, Rules... > > = true; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/string.hpp b/include/tao/json/external/pegtl/internal/string.hpp index 3ca15f04..229a1584 100644 --- a/include/tao/json/external/pegtl/internal/string.hpp +++ b/include/tao/json/external/pegtl/internal/string.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_STRING_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_STRING_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_STRING_HPP +#define TAO_JSON_PEGTL_INTERNAL_STRING_HPP #include #include @@ -16,53 +16,43 @@ #include "../analysis/counted.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + [[nodiscard]] inline bool unsafe_equals( const char* s, const std::initializer_list< char >& l ) noexcept { - namespace internal - { - inline bool unsafe_equals( const char* s, const std::initializer_list< char >& l ) noexcept - { - return std::memcmp( s, &*l.begin(), l.size() ) == 0; - } + return std::memcmp( s, &*l.begin(), l.size() ) == 0; + } - template< char... Cs > - struct string; + template< char... Cs > + struct string; - template<> - struct string<> - : trivial< true > - { - }; + template<> + struct string<> + : trivial< true > + { + }; - template< char... Cs > - struct string - { - using analyze_t = analysis::counted< analysis::rule_type::ANY, sizeof...( Cs ) >; + template< char... Cs > + struct string + { + using analyze_t = analysis::counted< analysis::rule_type::any, sizeof...( Cs ) >; - template< typename Input > - static bool match( Input& in ) - { - if( in.size( sizeof...( Cs ) ) >= sizeof...( Cs ) ) { - if( unsafe_equals( in.current(), { Cs... } ) ) { - bump_help< result_on_found::SUCCESS, Input, char, Cs... >( in, sizeof...( Cs ) ); - return true; - } - } - return false; + template< typename Input > + [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( 0 ) ) ) + { + if( in.size( sizeof...( Cs ) ) >= sizeof...( Cs ) ) { + if( unsafe_equals( in.current(), { Cs... } ) ) { + bump_help< result_on_found::success, Input, char, Cs... >( in, sizeof...( Cs ) ); + return true; } - }; - - template< char... Cs > - struct skip_control< string< Cs... > > : std::true_type - { - }; - - } // namespace internal + } + return false; + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< char... Cs > + inline constexpr bool skip_control< string< Cs... > > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/trivial.hpp b/include/tao/json/external/pegtl/internal/trivial.hpp index 3e4de6e3..9be855cd 100644 --- a/include/tao/json/external/pegtl/internal/trivial.hpp +++ b/include/tao/json/external/pegtl/internal/trivial.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_TRIVIAL_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_TRIVIAL_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_TRIVIAL_HPP +#define TAO_JSON_PEGTL_INTERNAL_TRIVIAL_HPP #include "../config.hpp" @@ -10,33 +10,23 @@ #include "../analysis/counted.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< bool Result > + struct trivial { - namespace internal - { - template< bool Result > - struct trivial - { - using analyze_t = analysis::counted< analysis::rule_type::ANY, unsigned( !Result ) >; - - template< typename Input > - static bool match( Input& ) noexcept - { - return Result; - } - }; + using analyze_t = analysis::counted< analysis::rule_type::any, unsigned( !Result ) >; - template< bool Result > - struct skip_control< trivial< Result > > : std::true_type - { - }; - - } // namespace internal + template< typename Input > + [[nodiscard]] static bool match( Input& /*unused*/ ) noexcept + { + return Result; + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< bool Result > + inline constexpr bool skip_control< trivial< Result > > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/try_catch_type.hpp b/include/tao/json/external/pegtl/internal/try_catch_type.hpp index c04e094e..1ecf3ebd 100644 --- a/include/tao/json/external/pegtl/internal/try_catch_type.hpp +++ b/include/tao/json/external/pegtl/internal/try_catch_type.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_TRY_CATCH_TYPE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_TRY_CATCH_TYPE_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_TRY_CATCH_TYPE_HPP +#define TAO_JSON_PEGTL_INTERNAL_TRY_CATCH_TYPE_HPP #include @@ -18,55 +18,47 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace internal - { - template< typename Exception, typename... Rules > - struct try_catch_type; - - template< typename Exception > - struct try_catch_type< Exception > - : trivial< true > - { - }; - - template< typename Exception, typename... Rules > - struct try_catch_type - { - using analyze_t = analysis::generic< analysis::rule_type::SEQ, Rules... >; - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< M >(); - using m_t = decltype( m ); - - try { - return m( duseltronik< seq< Rules... >, A, m_t::next_rewind_mode, Action, Control >::match( in, st... ) ); - } - catch( const Exception& ) { - return false; - } - } - }; + template< typename Exception, typename... Rules > + struct try_catch_type; - template< typename Exception, typename... Rules > - struct skip_control< try_catch_type< Exception, Rules... > > : std::true_type - { - }; - - } // namespace internal - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Exception > + struct try_catch_type< Exception > + : trivial< true > + { + }; -} // namespace tao + template< typename Exception, typename... Rules > + struct try_catch_type + { + using analyze_t = analysis::generic< analysis::rule_type::seq, Rules... >; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< M >(); + using m_t = decltype( m ); + + try { + return m( duseltronik< seq< Rules... >, A, m_t::next_rewind_mode, Action, Control >::match( in, st... ) ); + } + catch( const Exception& ) { + return false; + } + } + }; + + template< typename Exception, typename... Rules > + inline constexpr bool skip_control< try_catch_type< Exception, Rules... > > = true; + +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/internal/until.hpp b/include/tao/json/external/pegtl/internal/until.hpp index e2563d34..e847585b 100644 --- a/include/tao/json/external/pegtl/internal/until.hpp +++ b/include/tao/json/external/pegtl/internal/until.hpp @@ -1,15 +1,14 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_UNTIL_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_INTERNAL_UNTIL_HPP +#ifndef TAO_JSON_PEGTL_INTERNAL_UNTIL_HPP +#define TAO_JSON_PEGTL_INTERNAL_UNTIL_HPP #include "../config.hpp" #include "bytes.hpp" #include "eof.hpp" #include "not_at.hpp" -#include "rule_conjunction.hpp" #include "skip_control.hpp" #include "star.hpp" @@ -18,74 +17,68 @@ #include "../analysis/generic.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::internal { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Cond, typename... Rules > + struct until; + + template< typename Cond > + struct until< Cond > { - namespace internal + using analyze_t = analysis::generic< analysis::rule_type::seq, star< not_at< Cond >, not_at< eof >, bytes< 1 > >, Cond >; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) { - template< typename Cond, typename... Rules > - struct until; - - template< typename Cond > - struct until< Cond > - { - using analyze_t = analysis::generic< analysis::rule_type::SEQ, star< not_at< Cond >, not_at< eof >, bytes< 1 > >, Cond >; - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< M >(); + auto m = in.template mark< M >(); - while( !Control< Cond >::template match< A, rewind_mode::REQUIRED, Action, Control >( in, st... ) ) { - if( in.empty() ) { - return false; - } - in.bump(); - } - return m( true ); + while( !Control< Cond >::template match< A, rewind_mode::required, Action, Control >( in, st... ) ) { + if( in.empty() ) { + return false; } - }; - - template< typename Cond, typename... Rules > - struct until - { - using analyze_t = analysis::generic< analysis::rule_type::SEQ, star< not_at< Cond >, not_at< eof >, Rules... >, Cond >; - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< M >(); - using m_t = decltype( m ); + in.bump(); + } + return m( true ); + } + }; + + template< typename Cond, typename... Rules > + struct until + { + using analyze_t = analysis::generic< analysis::rule_type::seq, star< not_at< Cond >, not_at< eof >, Rules... >, Cond >; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + auto m = in.template mark< M >(); + using m_t = decltype( m ); - while( !Control< Cond >::template match< A, rewind_mode::REQUIRED, Action, Control >( in, st... ) ) { - if( in.empty() || ( !rule_conjunction< Rules... >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) ) ) { - return false; - } - } - return m( true ); + while( !Control< Cond >::template match< A, rewind_mode::required, Action, Control >( in, st... ) ) { + if( !( Control< Rules >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) && ... ) ) { + return false; } - }; - - template< typename Cond, typename... Rules > - struct skip_control< until< Cond, Rules... > > : std::true_type - { - }; - - } // namespace internal + } + return m( true ); + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Cond, typename... Rules > + inline constexpr bool skip_control< until< Cond, Rules... > > = true; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE::internal #endif diff --git a/include/tao/json/external/pegtl/istream_input.hpp b/include/tao/json/external/pegtl/istream_input.hpp index 745603c7..5bd0be99 100644 --- a/include/tao/json/external/pegtl/istream_input.hpp +++ b/include/tao/json/external/pegtl/istream_input.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_ISTREAM_INPUT_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_ISTREAM_INPUT_HPP +#ifndef TAO_JSON_PEGTL_ISTREAM_INPUT_HPP +#define TAO_JSON_PEGTL_ISTREAM_INPUT_HPP #include @@ -12,23 +12,22 @@ #include "internal/istream_reader.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Eol = eol::lf_crlf, std::size_t Chunk = 64 > + struct istream_input + : buffer_input< internal::istream_reader, Eol, std::string, Chunk > { - template< typename Eol = eol::lf_crlf > - struct istream_input - : buffer_input< internal::istream_reader, Eol > + template< typename T > + istream_input( std::istream& in_stream, const std::size_t in_maximum, T&& in_source ) + : buffer_input< internal::istream_reader, Eol, std::string, Chunk >( std::forward< T >( in_source ), in_maximum, in_stream ) { - template< typename T > - istream_input( std::istream& in_stream, const std::size_t in_maximum, T&& in_source ) - : buffer_input< internal::istream_reader, Eol >( std::forward< T >( in_source ), in_maximum, in_stream ) - { - } - }; + } + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename... Ts > + istream_input( Ts&&... )->istream_input<>; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/match.hpp b/include/tao/json/external/pegtl/match.hpp new file mode 100644 index 00000000..2652bb92 --- /dev/null +++ b/include/tao/json/external/pegtl/match.hpp @@ -0,0 +1,73 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_MATCH_HPP +#define TAO_JSON_PEGTL_MATCH_HPP + +#include + +#include "apply_mode.hpp" +#include "config.hpp" +#include "nothing.hpp" +#include "require_apply.hpp" +#include "require_apply0.hpp" +#include "rewind_mode.hpp" + +#include "internal/dusel_mode.hpp" +#include "internal/duseltronik.hpp" +#include "internal/has_apply.hpp" +#include "internal/has_apply0.hpp" +#include "internal/missing_apply.hpp" +#include "internal/missing_apply0.hpp" +#include "internal/skip_control.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + template< typename Rule, + apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] bool match( Input& in, States&&... st ) + { + constexpr bool enable_control = !internal::skip_control< Rule >; + constexpr bool enable_action = enable_control && ( A == apply_mode::action ); + + using iterator_t = typename Input::iterator_t; + constexpr bool has_apply_void = enable_action && internal::has_apply< Control< Rule >, void, Action, const iterator_t&, const Input&, States... >::value; + constexpr bool has_apply_bool = enable_action && internal::has_apply< Control< Rule >, bool, Action, const iterator_t&, const Input&, States... >::value; + constexpr bool has_apply = has_apply_void || has_apply_bool; + + constexpr bool has_apply0_void = enable_action && internal::has_apply0< Control< Rule >, void, Action, const Input&, States... >::value; + constexpr bool has_apply0_bool = enable_action && internal::has_apply0< Control< Rule >, bool, Action, const Input&, States... >::value; + constexpr bool has_apply0 = has_apply0_void || has_apply0_bool; + + static_assert( !( has_apply && has_apply0 ), "both apply() and apply0() defined" ); + + constexpr bool is_nothing = std::is_base_of_v< nothing< Rule >, Action< Rule > >; + static_assert( !( has_apply && is_nothing ), "unexpected apply() defined" ); + static_assert( !( has_apply0 && is_nothing ), "unexpected apply0() defined" ); + + if constexpr( !has_apply && std::is_base_of_v< require_apply, Action< Rule > > ) { + internal::missing_apply< Control< Rule >, Action >( in, st... ); + } + + if constexpr( !has_apply0 && std::is_base_of_v< require_apply0, Action< Rule > > ) { + internal::missing_apply0< Control< Rule >, Action >( in, st... ); + } + + constexpr bool validate_nothing = std::is_base_of_v< maybe_nothing, Action< void > >; + constexpr bool is_maybe_nothing = std::is_base_of_v< maybe_nothing, Action< Rule > >; + static_assert( !enable_action || !validate_nothing || is_nothing || is_maybe_nothing || has_apply || has_apply0, "either apply() or apply0() must be defined" ); + + constexpr auto mode = static_cast< internal::dusel_mode >( enable_control + has_apply_void + 2 * has_apply_bool + 3 * has_apply0_void + 4 * has_apply0_bool ); + return internal::duseltronik< Rule, A, M, Action, Control, mode >::match( in, st... ); + } + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/memory_input.hpp b/include/tao/json/external/pegtl/memory_input.hpp index d16f572f..d2b5f44c 100644 --- a/include/tao/json/external/pegtl/memory_input.hpp +++ b/include/tao/json/external/pegtl/memory_input.hpp @@ -1,285 +1,381 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_MEMORY_INPUT_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_MEMORY_INPUT_HPP +#ifndef TAO_JSON_PEGTL_MEMORY_INPUT_HPP +#define TAO_JSON_PEGTL_MEMORY_INPUT_HPP #include +#include #include #include +#include #include #include #include "config.hpp" #include "eol.hpp" +#include "normal.hpp" +#include "nothing.hpp" #include "position.hpp" #include "tracking_mode.hpp" #include "internal/action_input.hpp" -#include "internal/bump_impl.hpp" +#include "internal/at.hpp" +#include "internal/bump.hpp" +#include "internal/eolf.hpp" #include "internal/iterator.hpp" #include "internal/marker.hpp" +#include "internal/until.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + namespace internal { - namespace internal + template< tracking_mode, typename Eol, typename Source > + class memory_input_base; + + template< typename Eol, typename Source > + class memory_input_base< tracking_mode::eager, Eol, Source > { - template< tracking_mode, typename Eol, typename Source > - class memory_input_base; + public: + using iterator_t = internal::iterator; - template< typename Eol, typename Source > - class memory_input_base< tracking_mode::IMMEDIATE, Eol, Source > + template< typename T > + memory_input_base( const iterator_t& in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) + : m_begin( in_begin.data ), + m_current( in_begin ), + m_end( in_end ), + m_source( std::forward< T >( in_source ) ) { - public: - using iterator_t = internal::iterator; - - template< typename T > - memory_input_base( const iterator_t& in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value ) - : m_current( in_begin ), - m_end( in_end ), - m_source( std::forward< T >( in_source ) ) - { - } - - template< typename T > - memory_input_base( const char* in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value ) - : m_current( in_begin ), - m_end( in_end ), - m_source( std::forward< T >( in_source ) ) - { - } - - memory_input_base( const memory_input_base& ) = delete; - memory_input_base operator=( const memory_input_base& ) = delete; - - const char* current() const noexcept - { - return m_current.data; - } - - const char* end( const std::size_t = 0 ) const noexcept - { - return m_end; - } - - std::size_t byte() const noexcept - { - return m_current.byte; - } - - std::size_t line() const noexcept - { - return m_current.line; - } - - std::size_t byte_in_line() const noexcept - { - return m_current.byte_in_line; - } - - void bump( const std::size_t in_count = 1 ) noexcept - { - internal::bump( m_current, in_count, Eol::ch ); - } - - void bump_in_this_line( const std::size_t in_count = 1 ) noexcept - { - internal::bump_in_this_line( m_current, in_count ); - } - - void bump_to_next_line( const std::size_t in_count = 1 ) noexcept - { - internal::bump_to_next_line( m_current, in_count ); - } - - TAOCPP_JSON_PEGTL_NAMESPACE::position position( const iterator_t& it ) const - { - return TAOCPP_JSON_PEGTL_NAMESPACE::position( it, m_source ); - } - - protected: - iterator_t m_current; - const char* const m_end; - const Source m_source; - }; - - template< typename Eol, typename Source > - class memory_input_base< tracking_mode::LAZY, Eol, Source > + } + + template< typename T > + memory_input_base( const char* in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) + : m_begin( in_begin ), + m_current( in_begin ), + m_end( in_end ), + m_source( std::forward< T >( in_source ) ) { - public: - using iterator_t = const char*; - - template< typename T > - memory_input_base( const internal::iterator& in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value ) - : m_begin( in_begin ), - m_current( in_begin.data ), - m_end( in_end ), - m_source( std::forward< T >( in_source ) ) - { - } - - template< typename T > - memory_input_base( const char* in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value ) - : m_begin( in_begin ), - m_current( in_begin ), - m_end( in_end ), - m_source( std::forward< T >( in_source ) ) - { - } - - memory_input_base( const memory_input_base& ) = delete; - memory_input_base operator=( const memory_input_base& ) = delete; - - const char* current() const noexcept - { - return m_current; - } - - const char* end( const std::size_t = 0 ) const noexcept - { - return m_end; - } - - std::size_t byte() const noexcept - { - return std::size_t( current() - m_begin.data ); - } - - void bump( const std::size_t in_count = 1 ) noexcept - { - m_current += in_count; - } - - void bump_in_this_line( const std::size_t in_count = 1 ) noexcept - { - m_current += in_count; - } - - void bump_to_next_line( const std::size_t in_count = 1 ) noexcept - { - m_current += in_count; - } - - TAOCPP_JSON_PEGTL_NAMESPACE::position position( const iterator_t it ) const - { - internal::iterator c( m_begin ); - internal::bump( c, std::size_t( it - m_begin.data ), Eol::ch ); - return TAOCPP_JSON_PEGTL_NAMESPACE::position( c, m_source ); - } - - protected: - const internal::iterator m_begin; - iterator_t m_current; - const char* const m_end; - const Source m_source; - }; - - } // namespace internal - - template< tracking_mode P = tracking_mode::IMMEDIATE, typename Eol = eol::lf_crlf, typename Source = std::string > - class memory_input - : public internal::memory_input_base< P, Eol, Source > - { - public: - static constexpr tracking_mode tracking_mode_v = P; + } - using eol_t = Eol; - using source_t = Source; + memory_input_base( const memory_input_base& ) = delete; + memory_input_base( memory_input_base&& ) = delete; - using typename internal::memory_input_base< P, Eol, Source >::iterator_t; + ~memory_input_base() = default; - using action_t = internal::action_input< memory_input >; + memory_input_base operator=( const memory_input_base& ) = delete; + memory_input_base operator=( memory_input_base&& ) = delete; - using internal::memory_input_base< P, Eol, Source >::memory_input_base; + [[nodiscard]] const char* current() const noexcept + { + return m_current.data; + } - template< typename T > - memory_input( const char* in_begin, const std::size_t in_size, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value ) - : memory_input( in_begin, in_begin + in_size, std::forward< T >( in_source ) ) + [[nodiscard]] const char* begin() const noexcept { + return m_begin; } - template< typename T > - memory_input( const std::string& in_string, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value ) - : memory_input( in_string.data(), in_string.size(), std::forward< T >( in_source ) ) + [[nodiscard]] const char* end( const std::size_t /*unused*/ = 0 ) const noexcept { + return m_end; } - template< typename T > - memory_input( const char* in_begin, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value ) - : memory_input( in_begin, std::strlen( in_begin ), std::forward< T >( in_source ) ) + [[nodiscard]] std::size_t byte() const noexcept { + return m_current.byte; } - template< typename T > - memory_input( const char* in_begin, const char* in_end, T&& in_source, const std::size_t in_byte, const std::size_t in_line, const std::size_t in_byte_in_line ) noexcept( std::is_nothrow_constructible< Source, T&& >::value ) - : memory_input( { in_begin, in_byte, in_line, in_byte_in_line }, in_end, std::forward< T >( in_source ) ) + [[nodiscard]] std::size_t line() const noexcept + { + return m_current.line; + } + + [[nodiscard]] std::size_t byte_in_line() const noexcept + { + return m_current.byte_in_line; + } + + void bump( const std::size_t in_count = 1 ) noexcept + { + internal::bump( m_current, in_count, Eol::ch ); + } + + void bump_in_this_line( const std::size_t in_count = 1 ) noexcept + { + internal::bump_in_this_line( m_current, in_count ); + } + + void bump_to_next_line( const std::size_t in_count = 1 ) noexcept { + internal::bump_to_next_line( m_current, in_count ); } - memory_input( const memory_input& ) = delete; - memory_input operator=( const memory_input& ) = delete; + [[nodiscard]] TAO_JSON_PEGTL_NAMESPACE::position position( const iterator_t& it ) const + { + return TAO_JSON_PEGTL_NAMESPACE::position( it, m_source ); + } - const Source& source() const noexcept + void restart( const std::size_t in_byte = 0, const std::size_t in_line = 1, const std::size_t in_byte_in_line = 0 ) { - return this->m_source; + m_current.data = m_begin; + m_current.byte = in_byte; + m_current.line = in_line; + m_current.byte_in_line = in_byte_in_line; } - bool empty() const noexcept + template< rewind_mode M > + void restart( const internal::marker< iterator_t, M >& m ) { - return this->current() == this->end(); + m_current.data = m.iterator().data; + m_current.byte = m.iterator().byte; + m_current.line = m.iterator().line; + m_current.byte_in_line = m.iterator().byte_in_line; } - std::size_t size( const std::size_t = 0 ) const noexcept + protected: + const char* const m_begin; + iterator_t m_current; + const char* const m_end; + const Source m_source; + }; + + template< typename Eol, typename Source > + class memory_input_base< tracking_mode::lazy, Eol, Source > + { + public: + using iterator_t = const char*; + + template< typename T > + memory_input_base( const internal::iterator& in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) + : m_begin( in_begin ), + m_current( in_begin.data ), + m_end( in_end ), + m_source( std::forward< T >( in_source ) ) { - return std::size_t( this->end() - this->current() ); } - char peek_char( const std::size_t offset = 0 ) const noexcept + template< typename T > + memory_input_base( const char* in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) + : m_begin( in_begin ), + m_current( in_begin ), + m_end( in_end ), + m_source( std::forward< T >( in_source ) ) { - return this->current()[ offset ]; } - unsigned char peek_byte( const std::size_t offset = 0 ) const noexcept + memory_input_base( const memory_input_base& ) = delete; + memory_input_base( memory_input_base&& ) = delete; + + ~memory_input_base() = default; + + memory_input_base operator=( const memory_input_base& ) = delete; + memory_input_base operator=( memory_input_base&& ) = delete; + + [[nodiscard]] const char* current() const noexcept + { + return m_current; + } + + [[nodiscard]] const char* begin() const noexcept + { + return m_begin.data; + } + + [[nodiscard]] const char* end( const std::size_t /*unused*/ = 0 ) const noexcept { - return static_cast< unsigned char >( peek_char( offset ) ); + return m_end; } - iterator_t& iterator() noexcept + [[nodiscard]] std::size_t byte() const noexcept { - return this->m_current; + return std::size_t( current() - m_begin.data ); } - const iterator_t& iterator() const noexcept + void bump( const std::size_t in_count = 1 ) noexcept { - return this->m_current; + m_current += in_count; } - using internal::memory_input_base< P, Eol, Source >::position; + void bump_in_this_line( const std::size_t in_count = 1 ) noexcept + { + m_current += in_count; + } - TAOCPP_JSON_PEGTL_NAMESPACE::position position() const + void bump_to_next_line( const std::size_t in_count = 1 ) noexcept { - return position( iterator() ); + m_current += in_count; } - void discard() const noexcept + [[nodiscard]] TAO_JSON_PEGTL_NAMESPACE::position position( const iterator_t it ) const { + internal::iterator c( m_begin ); + internal::bump( c, std::size_t( it - m_begin.data ), Eol::ch ); + return TAO_JSON_PEGTL_NAMESPACE::position( c, m_source ); } - void require( const std::size_t ) const noexcept + void restart() { + m_current = m_begin.data; } template< rewind_mode M > - internal::marker< iterator_t, M > mark() noexcept + void restart( const internal::marker< iterator_t, M >& m ) { - return internal::marker< iterator_t, M >( iterator() ); + m_current = m.iterator(); } + + protected: + const internal::iterator m_begin; + iterator_t m_current; + const char* const m_end; + const Source m_source; }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + } // namespace internal + + template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf, typename Source = std::string > + class memory_input + : public internal::memory_input_base< P, Eol, Source > + { + public: + static constexpr tracking_mode tracking_mode_v = P; + + using eol_t = Eol; + using source_t = Source; + + using typename internal::memory_input_base< P, Eol, Source >::iterator_t; + + using action_t = internal::action_input< memory_input >; + + using internal::memory_input_base< P, Eol, Source >::memory_input_base; + + template< typename T > + memory_input( const char* in_begin, const std::size_t in_size, T&& in_source ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) + : memory_input( in_begin, in_begin + in_size, std::forward< T >( in_source ) ) + { + } + + template< typename T > + memory_input( const std::string& in_string, T&& in_source ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) + : memory_input( in_string.data(), in_string.size(), std::forward< T >( in_source ) ) + { + } + + template< typename T > + memory_input( const std::string_view in_string, T&& in_source ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) + : memory_input( in_string.data(), in_string.size(), std::forward< T >( in_source ) ) + { + } + + template< typename T > + memory_input( std::string&&, T&& ) = delete; + + template< typename T > + memory_input( const char* in_begin, T&& in_source ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) + : memory_input( in_begin, std::strlen( in_begin ), std::forward< T >( in_source ) ) + { + } + + template< typename T > + memory_input( const char* in_begin, const char* in_end, T&& in_source, const std::size_t in_byte, const std::size_t in_line, const std::size_t in_byte_in_line ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) + : memory_input( { in_begin, in_byte, in_line, in_byte_in_line }, in_end, std::forward< T >( in_source ) ) + { + } + + memory_input( const memory_input& ) = delete; + memory_input( memory_input&& ) = delete; + + ~memory_input() = default; + + memory_input operator=( const memory_input& ) = delete; + memory_input operator=( memory_input&& ) = delete; + + [[nodiscard]] const Source& source() const noexcept + { + return this->m_source; + } + + [[nodiscard]] bool empty() const noexcept + { + return this->current() == this->end(); + } + + [[nodiscard]] std::size_t size( const std::size_t /*unused*/ = 0 ) const noexcept + { + return std::size_t( this->end() - this->current() ); + } + + [[nodiscard]] char peek_char( const std::size_t offset = 0 ) const noexcept + { + return this->current()[ offset ]; + } + + [[nodiscard]] std::uint8_t peek_uint8( const std::size_t offset = 0 ) const noexcept + { + return static_cast< std::uint8_t >( peek_char( offset ) ); + } + + [[nodiscard]] iterator_t& iterator() noexcept + { + return this->m_current; + } + + [[nodiscard]] const iterator_t& iterator() const noexcept + { + return this->m_current; + } + + using internal::memory_input_base< P, Eol, Source >::position; + + [[nodiscard]] TAO_JSON_PEGTL_NAMESPACE::position position() const + { + return position( iterator() ); + } + + void discard() const noexcept + { + } + + void require( const std::size_t /*unused*/ ) const noexcept + { + } + + template< rewind_mode M > + [[nodiscard]] internal::marker< iterator_t, M > mark() noexcept + { + return internal::marker< iterator_t, M >( iterator() ); + } + + [[nodiscard]] const char* at( const TAO_JSON_PEGTL_NAMESPACE::position& p ) const noexcept + { + return this->begin() + p.byte; + } + + [[nodiscard]] const char* begin_of_line( const TAO_JSON_PEGTL_NAMESPACE::position& p ) const noexcept + { + return at( p ) - p.byte_in_line; + } + + [[nodiscard]] const char* end_of_line( const TAO_JSON_PEGTL_NAMESPACE::position& p ) const noexcept + { + using input_t = memory_input< tracking_mode::lazy, Eol, const char* >; + input_t in( at( p ), this->end(), "" ); + using grammar = internal::until< internal::at< internal::eolf > >; + (void)normal< grammar >::match< apply_mode::nothing, rewind_mode::dontcare, nothing, normal >( in ); + return in.current(); + } + + [[nodiscard]] std::string_view line_at( const TAO_JSON_PEGTL_NAMESPACE::position& p ) const noexcept + { + const char* b = begin_of_line( p ); + return std::string_view( b, end_of_line( p ) - b ); + } + }; + + template< typename... Ts > + memory_input( Ts&&... )->memory_input<>; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/mmap_input.hpp b/include/tao/json/external/pegtl/mmap_input.hpp index 25dc9c85..766df579 100644 --- a/include/tao/json/external/pegtl/mmap_input.hpp +++ b/include/tao/json/external/pegtl/mmap_input.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_MMAP_INPUT_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_MMAP_INPUT_HPP +#ifndef TAO_JSON_PEGTL_MMAP_INPUT_HPP +#define TAO_JSON_PEGTL_MMAP_INPUT_HPP #include #include @@ -12,44 +12,68 @@ #include "memory_input.hpp" #include "tracking_mode.hpp" -#include "internal/file_mapper.hpp" +#if defined( __unix__ ) || ( defined( __APPLE__ ) && defined( __MACH__ ) ) +#include // Required for _POSIX_MAPPED_FILES +#endif + +#if defined( _POSIX_MAPPED_FILES ) +#include "internal/file_mapper_posix.hpp" +#elif defined( _WIN32 ) +#include "internal/file_mapper_win32.hpp" +#else +#endif -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + namespace internal { - namespace internal - { - struct mmap_holder - { - const std::string filename; - const file_mapper data; - - template< typename T > - mmap_holder( T&& in_filename ) - : filename( std::forward< T >( in_filename ) ), - data( filename.c_str() ) - { - } - }; - - } // namespace internal - - template< tracking_mode P = tracking_mode::IMMEDIATE, typename Eol = eol::lf_crlf > - struct mmap_input - : private internal::mmap_holder, - public memory_input< P, Eol, const char* > + struct mmap_holder { + const std::string filename; + const file_mapper data; + template< typename T > - explicit mmap_input( T&& in_filename ) - : internal::mmap_holder( std::forward< T >( in_filename ) ), - memory_input< P, Eol, const char* >( data.begin(), data.end(), filename.c_str() ) + explicit mmap_holder( T&& in_filename ) + : filename( std::forward< T >( in_filename ) ), + data( filename.c_str() ) { } + + mmap_holder( const mmap_holder& ) = delete; + mmap_holder( mmap_holder&& ) = delete; + + ~mmap_holder() = default; + + void operator=( const mmap_holder& ) = delete; + void operator=( mmap_holder&& ) = delete; }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + } // namespace internal + + template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf > + struct mmap_input + : private internal::mmap_holder, + public memory_input< P, Eol, const char* > + { + template< typename T > + explicit mmap_input( T&& in_filename ) + : internal::mmap_holder( std::forward< T >( in_filename ) ), + memory_input< P, Eol, const char* >( data.begin(), data.end(), filename.c_str() ) + { + } + + mmap_input( const mmap_input& ) = delete; + mmap_input( mmap_input&& ) = delete; + + ~mmap_input() = default; + + void operator=( const mmap_input& ) = delete; + void operator=( mmap_input&& ) = delete; + }; + + template< typename... Ts > + explicit mmap_input( Ts&&... )->mmap_input<>; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/normal.hpp b/include/tao/json/external/pegtl/normal.hpp index 2209d93f..71f7545f 100644 --- a/include/tao/json/external/pegtl/normal.hpp +++ b/include/tao/json/external/pegtl/normal.hpp @@ -1,89 +1,87 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_NORMAL_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_NORMAL_HPP +#ifndef TAO_JSON_PEGTL_NORMAL_HPP +#define TAO_JSON_PEGTL_NORMAL_HPP +#include +#include #include #include "apply_mode.hpp" #include "config.hpp" -#include "nothing.hpp" +#include "match.hpp" #include "parse_error.hpp" #include "rewind_mode.hpp" #include "internal/demangle.hpp" -#include "internal/dusel_mode.hpp" -#include "internal/duseltronik.hpp" -#include "internal/has_apply.hpp" -#include "internal/has_apply0.hpp" -#include "internal/skip_control.hpp" +#include "internal/has_match.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Rule > + struct normal { - template< typename Rule > - struct normal + template< typename Input, typename... States > + static void start( const Input& /*unused*/, States&&... /*unused*/ ) noexcept { - template< typename Input, typename... States > - static void start( const Input&, States&&... ) noexcept - { - } + } - template< typename Input, typename... States > - static void success( const Input&, States&&... ) noexcept - { - } + template< typename Input, typename... States > + static void success( const Input& /*unused*/, States&&... /*unused*/ ) noexcept + { + } - template< typename Input, typename... States > - static void failure( const Input&, States&&... ) noexcept - { - } + template< typename Input, typename... States > + static void failure( const Input& /*unused*/, States&&... /*unused*/ ) noexcept + { + } - template< typename Input, typename... States > - static void raise( const Input& in, States&&... ) - { - throw parse_error( "parse error matching " + internal::demangle< Rule >(), in ); - } + template< typename Input, typename... States > + static void raise( const Input& in, States&&... /*unused*/ ) + { + throw parse_error( "parse error matching " + std::string( internal::demangle< Rule >() ), in ); + } - template< template< typename... > class Action, typename Input, typename... States > - static auto apply0( const Input&, States&&... st ) -> decltype( Action< Rule >::apply0( st... ) ) - { - return Action< Rule >::apply0( st... ); - } + template< template< typename... > class Action, + typename Iterator, + typename Input, + typename... States > + static auto apply( const Iterator& begin, const Input& in, States&&... st ) noexcept( noexcept( Action< Rule >::apply( std::declval< const typename Input::action_t& >(), st... ) ) ) + -> decltype( Action< Rule >::apply( std::declval< const typename Input::action_t& >(), st... ) ) + { + const typename Input::action_t action_input( begin, in ); + return Action< Rule >::apply( action_input, st... ); + } - template< template< typename... > class Action, typename Iterator, typename Input, typename... States > - static auto apply( const Iterator& begin, const Input& in, States&&... st ) -> decltype( Action< Rule >::apply( std::declval< typename Input::action_t >(), st... ) ) - { - using action_t = typename Input::action_t; - const action_t action_input( begin, in ); - return Action< Rule >::apply( action_input, st... ); - } + template< template< typename... > class Action, + typename Input, + typename... States > + static auto apply0( const Input& /*unused*/, States&&... st ) noexcept( noexcept( Action< Rule >::apply0( st... ) ) ) + -> decltype( Action< Rule >::apply0( st... ) ) + { + return Action< Rule >::apply0( st... ); + } - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - constexpr char use_control = !internal::skip_control< Rule >::value; - constexpr char use_action = use_control && ( A == apply_mode::ACTION ) && ( !is_nothing< Action, Rule >::value ); - constexpr char use_apply_void = use_action && internal::has_apply< Action< Rule >, void, typename Input::action_t, States... >::value; - constexpr char use_apply_bool = use_action && internal::has_apply< Action< Rule >, bool, typename Input::action_t, States... >::value; - constexpr char use_apply0_void = use_action && internal::has_apply0< Action< Rule >, void, States... >::value; - constexpr char use_apply0_bool = use_action && internal::has_apply0< Action< Rule >, bool, States... >::value; - static_assert( use_apply_void + use_apply_bool + use_apply0_void + use_apply0_bool < 2, "more than one apply or apply0 defined" ); - static_assert( !use_action || use_apply_bool || use_apply_void || use_apply0_bool || use_apply0_void, "actions not disabled but no apply or apply0 found" ); - constexpr dusel_mode mode = static_cast< dusel_mode >( use_control + use_apply_void + 2 * use_apply_bool + 3 * use_apply0_void + 4 * use_apply0_bool ); - return internal::duseltronik< Rule, A, M, Action, Control, mode >::match( in, st... ); + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + if constexpr( internal::has_match_v< Rule, A, M, Action, Control, Input, States... > ) { + return Action< Rule >::template match< Rule, A, M, Action, Control >( in, st... ); } - }; - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + else { + return TAO_JSON_PEGTL_NAMESPACE::match< Rule, A, M, Action, Control >( in, st... ); + } + } + }; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/nothing.hpp b/include/tao/json/external/pegtl/nothing.hpp index 61aee1d8..85d56033 100644 --- a/include/tao/json/external/pegtl/nothing.hpp +++ b/include/tao/json/external/pegtl/nothing.hpp @@ -1,27 +1,20 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_NOTHING_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_NOTHING_HPP - -#include +#ifndef TAO_JSON_PEGTL_NOTHING_HPP +#define TAO_JSON_PEGTL_NOTHING_HPP #include "config.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Rule > + struct nothing { - template< typename Rule > - struct nothing - { - }; - - template< template< typename... > class Action, typename Rule > - using is_nothing = std::is_base_of< nothing< Rule >, Action< Rule > >; + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + using maybe_nothing = nothing< void >; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/parse.hpp b/include/tao/json/external/pegtl/parse.hpp index b1f7d0b5..9a777eb8 100644 --- a/include/tao/json/external/pegtl/parse.hpp +++ b/include/tao/json/external/pegtl/parse.hpp @@ -1,8 +1,10 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_PARSE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_PARSE_HPP +#ifndef TAO_JSON_PEGTL_PARSE_HPP +#define TAO_JSON_PEGTL_PARSE_HPP + +#include #include "apply_mode.hpp" #include "config.hpp" @@ -11,43 +13,41 @@ #include "parse_error.hpp" #include "rewind_mode.hpp" -namespace tao +#include "internal/action_input.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + template< typename Rule, + template< typename... > class Action = nothing, + template< typename... > class Control = normal, + apply_mode A = apply_mode::action, + rewind_mode M = rewind_mode::required, + typename Input, + typename... States > + bool parse( Input&& in, States&&... st ) { - template< typename Rule, - template< typename... > class Action = nothing, - template< typename... > class Control = normal, - apply_mode A = apply_mode::ACTION, - rewind_mode M = rewind_mode::REQUIRED, - typename Input, - typename... States > - bool parse( Input&& in, States&&... st ) - { - return Control< Rule >::template match< A, M, Action, Control >( in, st... ); - } + return Control< Rule >::template match< A, M, Action, Control >( in, st... ); + } - template< typename Rule, - template< typename... > class Action = nothing, - template< typename... > class Control = normal, - apply_mode A = apply_mode::ACTION, - rewind_mode M = rewind_mode::REQUIRED, - typename Outer, - typename Input, - typename... States > - bool parse_nested( const Outer& oi, Input&& in, States&&... st ) - { - try { - return parse< Rule, Action, Control, A, M >( in, st... ); - } - catch( parse_error& e ) { - e.positions.push_back( oi.position() ); - throw; - } + template< typename Rule, + template< typename... > class Action = nothing, + template< typename... > class Control = normal, + apply_mode A = apply_mode::action, + rewind_mode M = rewind_mode::required, + typename Outer, + typename Input, + typename... States > + bool parse_nested( const Outer& oi, Input&& in, States&&... st ) + { + try { + return parse< Rule, Action, Control, A, M >( in, st... ); } + catch( parse_error& e ) { + e.positions.push_back( oi.position() ); + throw; + } + } - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/parse_error.hpp b/include/tao/json/external/pegtl/parse_error.hpp index eee75c00..c139155f 100644 --- a/include/tao/json/external/pegtl/parse_error.hpp +++ b/include/tao/json/external/pegtl/parse_error.hpp @@ -1,45 +1,69 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_PARSE_ERROR_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_PARSE_ERROR_HPP +#ifndef TAO_JSON_PEGTL_PARSE_ERROR_HPP +#define TAO_JSON_PEGTL_PARSE_ERROR_HPP +#include +#include #include +#include +#include #include #include "config.hpp" #include "position.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct parse_error + : std::runtime_error { - struct parse_error - : public std::runtime_error + template< typename Msg > + parse_error( Msg&& msg, std::vector< position > in_positions ) + : std::runtime_error( std::forward< Msg >( msg ) ), + positions( std::move( in_positions ) ) { - parse_error( const std::string& msg, std::vector< position >&& in_positions ) - : std::runtime_error( msg ), - positions( std::move( in_positions ) ) - { - } - - template< typename Input > - parse_error( const std::string& msg, const Input& in ) - : parse_error( msg, in.position() ) - { - } - - parse_error( const std::string& msg, const position& pos ) - : std::runtime_error( to_string( pos ) + ": " + msg ), - positions( 1, pos ) - { - } - - std::vector< position > positions; - }; - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + } + + template< typename Msg > + parse_error( Msg&& msg, const position& pos ) + : std::runtime_error( std::forward< Msg >( msg ) ), + positions( 1, pos ) + { + } + + template< typename Msg > + parse_error( Msg&& msg, position&& pos ) + : std::runtime_error( std::forward< Msg >( msg ) ) + { + positions.emplace_back( std::move( pos ) ); + } + + template< typename Msg, typename Input > + parse_error( Msg&& msg, const Input& in ) + : parse_error( std::forward< Msg >( msg ), in.position() ) + { + } + + std::vector< position > positions; + }; + + inline std::ostream& operator<<( std::ostream& o, const parse_error& e ) + { + for( auto it = e.positions.rbegin(); it != e.positions.rend(); ++it ) { + o << *it << ": "; + } + return o << e.what(); + } + + [[nodiscard]] inline std::string to_string( const parse_error& e ) + { + std::ostringstream o; + o << e; + return o.str(); + } + +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/position.hpp b/include/tao/json/external/pegtl/position.hpp index 72ac1e33..a362741f 100644 --- a/include/tao/json/external/pegtl/position.hpp +++ b/include/tao/json/external/pegtl/position.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_POSITION_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_POSITION_HPP +#ifndef TAO_JSON_PEGTL_POSITION_HPP +#define TAO_JSON_PEGTL_POSITION_HPP #include #include @@ -14,41 +14,62 @@ #include "internal/iterator.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + struct position { - struct position + position() = delete; + + position( position&& p ) noexcept + : byte( p.byte ), + line( p.line ), + byte_in_line( p.byte_in_line ), + source( std::move( p.source ) ) { - template< typename T > - position( const internal::iterator& in_iter, T&& in_source ) - : byte( in_iter.byte ), - line( in_iter.line ), - byte_in_line( in_iter.byte_in_line ), - source( std::forward< T >( in_source ) ) - { - } - - std::size_t byte; - std::size_t line; - std::size_t byte_in_line; - std::string source; - }; - - inline std::ostream& operator<<( std::ostream& o, const position& p ) + } + + position( const position& ) = default; + + position& operator=( position&& p ) noexcept { - return o << p.source << ':' << p.line << ':' << p.byte_in_line << '(' << p.byte << ')'; + byte = p.byte; + line = p.line; + byte_in_line = p.byte_in_line; + source = std::move( p.source ); + return *this; } - inline std::string to_string( const position& p ) + position& operator=( const position& ) = default; + + template< typename T > + position( const internal::iterator& in_iter, T&& in_source ) + : byte( in_iter.byte ), + line( in_iter.line ), + byte_in_line( in_iter.byte_in_line ), + source( std::forward< T >( in_source ) ) { - std::ostringstream o; - o << p; - return o.str(); } - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + ~position() = default; + + std::size_t byte; + std::size_t line; + std::size_t byte_in_line; + std::string source; + }; + + inline std::ostream& operator<<( std::ostream& o, const position& p ) + { + return o << p.source << ':' << p.line << ':' << p.byte_in_line << '(' << p.byte << ')'; + } + + [[nodiscard]] inline std::string to_string( const position& p ) + { + std::ostringstream o; + o << p; + return o.str(); + } -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/read_input.hpp b/include/tao/json/external/pegtl/read_input.hpp index bc6b4fe8..9e69d1b4 100644 --- a/include/tao/json/external/pegtl/read_input.hpp +++ b/include/tao/json/external/pegtl/read_input.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_READ_INPUT_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_READ_INPUT_HPP +#ifndef TAO_JSON_PEGTL_READ_INPUT_HPP +#define TAO_JSON_PEGTL_READ_INPUT_HPP #include @@ -13,40 +13,62 @@ #include "internal/file_reader.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + namespace internal { - namespace internal + struct filename_holder { - struct filename_holder - { - const std::string filename; - - template< typename T > - explicit filename_holder( T&& in_filename ) - : filename( std::forward< T >( in_filename ) ) - { - } - }; + const std::string filename; - } // namespace internal - - template< tracking_mode P = tracking_mode::IMMEDIATE, typename Eol = eol::lf_crlf > - struct read_input - : private internal::filename_holder, - public string_input< P, Eol, const char* > - { template< typename T > - explicit read_input( T&& in_filename ) - : internal::filename_holder( std::forward< T >( in_filename ) ), - string_input< P, Eol, const char* >( internal::file_reader( filename.c_str() ).read(), filename.c_str() ) + explicit filename_holder( T&& in_filename ) + : filename( std::forward< T >( in_filename ) ) { } + + filename_holder( const filename_holder& ) = delete; + filename_holder( filename_holder&& ) = delete; + + ~filename_holder() = default; + + void operator=( const filename_holder& ) = delete; + void operator=( filename_holder&& ) = delete; }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + } // namespace internal + + template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf > + struct read_input + : private internal::filename_holder, + public string_input< P, Eol, const char* > + { + template< typename T > + explicit read_input( T&& in_filename ) + : internal::filename_holder( std::forward< T >( in_filename ) ), + string_input< P, Eol, const char* >( internal::file_reader( filename.c_str() ).read(), filename.c_str() ) + { + } + + template< typename T > + read_input( FILE* in_file, T&& in_filename ) + : internal::filename_holder( std::forward< T >( in_filename ) ), + string_input< P, Eol, const char* >( internal::file_reader( in_file, filename.c_str() ).read(), filename.c_str() ) + { + } + + read_input( const read_input& ) = delete; + read_input( read_input&& ) = delete; + + ~read_input() = default; + + void operator=( const read_input& ) = delete; + void operator=( read_input&& ) = delete; + }; + + template< typename... Ts > + explicit read_input( Ts&&... )->read_input<>; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/require_apply.hpp b/include/tao/json/external/pegtl/require_apply.hpp new file mode 100644 index 00000000..fd9f15a9 --- /dev/null +++ b/include/tao/json/external/pegtl/require_apply.hpp @@ -0,0 +1,16 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_REQUIRE_APPLY_HPP +#define TAO_JSON_PEGTL_REQUIRE_APPLY_HPP + +#include "config.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + struct require_apply + {}; + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/require_apply0.hpp b/include/tao/json/external/pegtl/require_apply0.hpp new file mode 100644 index 00000000..41d8112f --- /dev/null +++ b/include/tao/json/external/pegtl/require_apply0.hpp @@ -0,0 +1,16 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_REQUIRE_APPLY0_HPP +#define TAO_JSON_PEGTL_REQUIRE_APPLY0_HPP + +#include "config.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + struct require_apply0 + {}; + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/rewind_mode.hpp b/include/tao/json/external/pegtl/rewind_mode.hpp index 96cd4f58..f97096a9 100644 --- a/include/tao/json/external/pegtl/rewind_mode.hpp +++ b/include/tao/json/external/pegtl/rewind_mode.hpp @@ -1,24 +1,20 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_REWIND_MODE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_REWIND_MODE_HPP +#ifndef TAO_JSON_PEGTL_REWIND_MODE_HPP +#define TAO_JSON_PEGTL_REWIND_MODE_HPP #include "config.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + enum class rewind_mode : char { - enum class rewind_mode : char - { - ACTIVE, - REQUIRED, - DONTCARE - }; + active, + required, + dontcare + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/rules.hpp b/include/tao/json/external/pegtl/rules.hpp index 210524cd..1029450b 100644 --- a/include/tao/json/external/pegtl/rules.hpp +++ b/include/tao/json/external/pegtl/rules.hpp @@ -1,69 +1,67 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_RULES_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_RULES_HPP +#ifndef TAO_JSON_PEGTL_RULES_HPP +#define TAO_JSON_PEGTL_RULES_HPP #include "config.hpp" #include "parse_error.hpp" #include "internal/rules.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - // clang-format off - template< typename... Actions > struct apply : internal::apply< Actions... > {}; - template< typename... Actions > struct apply0 : internal::apply0< Actions... > {}; - template< template< typename... > class Action, typename... Rules > struct action : internal::action< Action, Rules... > {}; - template< typename... Rules > struct at : internal::at< Rules... > {}; - struct bof : internal::bof {}; - struct bol : internal::bol {}; - template< unsigned Num > struct bytes : internal::bytes< Num > {}; - template< template< typename... > class Control, typename... Rules > struct control : internal::control< Control, Rules... > {}; - template< typename... Rules > struct disable : internal::disable< Rules... > {}; - struct discard : internal::discard {}; - template< typename... Rules > struct enable : internal::enable< Rules... > {}; - struct eof : internal::eof {}; - struct failure : internal::trivial< false > {}; - template< typename Rule, typename... Actions > struct if_apply : internal::if_apply< Rule, Actions... > {}; - template< typename Cond, typename... Thens > struct if_must : internal::if_must< Cond, Thens... > {}; - template< typename Cond, typename Then, typename Else > struct if_must_else : internal::if_must_else< Cond, Then, Else > {}; - template< typename Cond, typename Then, typename Else > struct if_then_else : internal::if_then_else< Cond, Then, Else > {}; - template< typename Rule, typename Sep, typename Pad = void > struct list : internal::list< Rule, internal::pad< Sep, Pad > > {}; - template< typename Rule, typename Sep > struct list< Rule, Sep, void > : internal::list< Rule, Sep > {}; - template< typename Rule, typename Sep, typename Pad = void > struct list_must : internal::list_must< Rule, internal::pad< Sep, Pad > > {}; - template< typename Rule, typename Sep > struct list_must< Rule, Sep, void > : internal::list_must< Rule, Sep > {}; - template< typename Rule, typename Sep, typename Pad = void > struct list_tail : internal::list_tail_pad< Rule, Sep, Pad > {}; - template< typename Rule, typename Sep > struct list_tail< Rule, Sep, void > : internal::list_tail< Rule, Sep > {}; - template< typename M, typename S > struct minus : internal::minus< M, S > {}; - template< typename... Rules > struct must : internal::must< Rules... > {}; - template< typename... Rules > struct not_at : internal::not_at< Rules... > {}; - template< typename... Rules > struct opt : internal::opt< Rules... > {}; - template< typename Rule, typename Pad1, typename Pad2 = Pad1 > struct pad : internal::pad< Rule, Pad1, Pad2 > {}; - template< typename Rule, typename Pad > struct pad_opt : internal::pad_opt< Rule, Pad > {}; - template< typename Rule, typename... Rules > struct plus : internal::plus< Rule, Rules... > {}; - template< typename Exception > struct raise : internal::raise< Exception > {}; - template< unsigned Num, typename... Rules > struct rep : internal::rep< Num, Rules... > {}; - template< unsigned Max, typename... Rules > struct rep_max : internal::rep_min_max< 0, Max, Rules... > {}; - template< unsigned Min, typename Rule, typename... Rules > struct rep_min : internal::rep_min< Min, Rule, Rules... > {}; - template< unsigned Min, unsigned Max, typename... Rules > struct rep_min_max : internal::rep_min_max< Min, Max, Rules... > {}; - template< unsigned Max, typename... Rules > struct rep_opt : internal::rep_opt< Max, Rules... > {}; - template< unsigned Amount > struct require : internal::require< Amount > {}; - template< typename... Rules > struct seq : internal::seq< Rules... > {}; - template< typename... Rules > struct sor : internal::sor< Rules... > {}; - template< typename Rule, typename... Rules > struct star : internal::star< Rule, Rules... > {}; - template< typename Cond, typename... Rules > struct star_must : internal::star_must< Cond, Rules... > {}; - template< typename State, typename... Rules > struct state : internal::state< State, Rules... > {}; - struct success : internal::trivial< true > {}; - template< typename... Rules > struct try_catch : internal::try_catch_type< parse_error, Rules... > {}; - template< typename Exception, typename... Rules > struct try_catch_type : internal::try_catch_type< Exception, Rules... > {}; - template< typename Cond, typename... Rules > struct until : internal::until< Cond, Rules... > {}; - // clang-format on + // clang-format off + template< typename... Actions > struct apply : internal::apply< Actions... > {}; + template< typename... Actions > struct apply0 : internal::apply0< Actions... > {}; + template< template< typename... > class Action, typename... Rules > struct action : internal::action< Action, Rules... > {}; + template< typename... Rules > struct at : internal::at< Rules... > {}; + struct bof : internal::bof {}; + struct bol : internal::bol {}; + template< unsigned Num > struct bytes : internal::bytes< Num > {}; + template< template< typename... > class Control, typename... Rules > struct control : internal::control< Control, Rules... > {}; + template< typename... Rules > struct disable : internal::disable< Rules... > {}; + struct discard : internal::discard {}; + template< typename... Rules > struct enable : internal::enable< Rules... > {}; + struct eof : internal::eof {}; + struct failure : internal::trivial< false > {}; + template< typename Rule, typename... Actions > struct if_apply : internal::if_apply< Rule, Actions... > {}; + template< typename Cond, typename... Thens > struct if_must : internal::if_must< false, Cond, Thens... > {}; + template< typename Cond, typename Then, typename Else > struct if_must_else : internal::if_must_else< Cond, Then, Else > {}; + template< typename Cond, typename Then, typename Else > struct if_then_else : internal::if_then_else< Cond, Then, Else > {}; + template< typename Rule, typename Sep, typename Pad = void > struct list : internal::list< Rule, internal::pad< Sep, Pad > > {}; + template< typename Rule, typename Sep > struct list< Rule, Sep, void > : internal::list< Rule, Sep > {}; + template< typename Rule, typename Sep, typename Pad = void > struct list_must : internal::list_must< Rule, internal::pad< Sep, Pad > > {}; + template< typename Rule, typename Sep > struct list_must< Rule, Sep, void > : internal::list_must< Rule, Sep > {}; + template< typename Rule, typename Sep, typename Pad = void > struct list_tail : internal::list_tail_pad< Rule, Sep, Pad > {}; + template< typename Rule, typename Sep > struct list_tail< Rule, Sep, void > : internal::list_tail< Rule, Sep > {}; + template< typename M, typename S > struct minus : internal::rematch< M, internal::not_at< S, internal::eof > > {}; + template< typename... Rules > struct must : internal::must< Rules... > {}; + template< typename... Rules > struct not_at : internal::not_at< Rules... > {}; + template< typename... Rules > struct opt : internal::opt< Rules... > {}; + template< typename Cond, typename... Rules > struct opt_must : internal::if_must< true, Cond, Rules... > {}; + template< typename Rule, typename Pad1, typename Pad2 = Pad1 > struct pad : internal::pad< Rule, Pad1, Pad2 > {}; + template< typename Rule, typename Pad > struct pad_opt : internal::pad_opt< Rule, Pad > {}; + template< typename Rule, typename... Rules > struct plus : internal::plus< Rule, Rules... > {}; + template< typename Exception > struct raise : internal::raise< Exception > {}; + template< typename Head, typename... Rules > struct rematch : internal::rematch< Head, Rules... > {}; + template< unsigned Num, typename... Rules > struct rep : internal::rep< Num, Rules... > {}; + template< unsigned Max, typename... Rules > struct rep_max : internal::rep_min_max< 0, Max, Rules... > {}; + template< unsigned Min, typename Rule, typename... Rules > struct rep_min : internal::rep_min< Min, Rule, Rules... > {}; + template< unsigned Min, unsigned Max, typename... Rules > struct rep_min_max : internal::rep_min_max< Min, Max, Rules... > {}; + template< unsigned Max, typename... Rules > struct rep_opt : internal::rep_opt< Max, Rules... > {}; + template< unsigned Amount > struct require : internal::require< Amount > {}; + template< typename... Rules > struct seq : internal::seq< Rules... > {}; + template< typename... Rules > struct sor : internal::sor< Rules... > {}; + template< typename Rule, typename... Rules > struct star : internal::star< Rule, Rules... > {}; + template< typename Cond, typename... Rules > struct star_must : internal::star_must< Cond, Rules... > {}; + template< typename State, typename... Rules > struct state : internal::state< State, Rules... > {}; + struct success : internal::trivial< true > {}; + template< typename... Rules > struct try_catch : internal::try_catch_type< parse_error, Rules... > {}; + template< typename Exception, typename... Rules > struct try_catch_type : internal::try_catch_type< Exception, Rules... > {}; + template< typename Cond, typename... Rules > struct until : internal::until< Cond, Rules... > {}; + // clang-format on - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/string_input.hpp b/include/tao/json/external/pegtl/string_input.hpp index 831e91d3..503be5e8 100644 --- a/include/tao/json/external/pegtl/string_input.hpp +++ b/include/tao/json/external/pegtl/string_input.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_STRING_INPUT_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_STRING_INPUT_HPP +#ifndef TAO_JSON_PEGTL_STRING_INPUT_HPP +#define TAO_JSON_PEGTL_STRING_INPUT_HPP #include #include @@ -12,40 +12,55 @@ #include "memory_input.hpp" #include "tracking_mode.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + namespace internal { - namespace internal + struct string_holder { - struct string_holder + const std::string data; + + template< typename T > + explicit string_holder( T&& in_data ) + : data( std::forward< T >( in_data ) ) { - const std::string data; + } - template< typename T > - explicit string_holder( T&& in_data ) - : data( std::forward< T >( in_data ) ) - { - } - }; + string_holder( const string_holder& ) = delete; + string_holder( string_holder&& ) = delete; - } // namespace internal + ~string_holder() = default; - template< tracking_mode P = tracking_mode::IMMEDIATE, typename Eol = eol::lf_crlf, typename Source = std::string > - struct string_input - : private internal::string_holder, - public memory_input< P, Eol, Source > - { - template< typename T, typename... Ts > - explicit string_input( T&& in_data, Ts&&... ts ) - : internal::string_holder( std::forward< T >( in_data ) ), - memory_input< P, Eol, Source >( data.data(), data.size(), std::forward< Ts >( ts )... ) - { - } + void operator=( const string_holder& ) = delete; + void operator=( string_holder&& ) = delete; }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE + } // namespace internal + + template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf, typename Source = std::string > + struct string_input + : private internal::string_holder, + public memory_input< P, Eol, Source > + { + template< typename V, typename T, typename... Ts > + explicit string_input( V&& in_data, T&& in_source, Ts&&... ts ) + : internal::string_holder( std::forward< V >( in_data ) ), + memory_input< P, Eol, Source >( data.data(), data.size(), std::forward< T >( in_source ), std::forward< Ts >( ts )... ) + { + } + + string_input( const string_input& ) = delete; + string_input( string_input&& ) = delete; + + ~string_input() = default; + + void operator=( const string_input& ) = delete; + void operator=( string_input&& ) = delete; + }; + + template< typename... Ts > + explicit string_input( Ts&&... )->string_input<>; -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/tracking_mode.hpp b/include/tao/json/external/pegtl/tracking_mode.hpp index eea30426..cda9fe2b 100644 --- a/include/tao/json/external/pegtl/tracking_mode.hpp +++ b/include/tao/json/external/pegtl/tracking_mode.hpp @@ -1,23 +1,19 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_TRACKING_MODE_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_TRACKING_MODE_HPP +#ifndef TAO_JSON_PEGTL_TRACKING_MODE_HPP +#define TAO_JSON_PEGTL_TRACKING_MODE_HPP #include "config.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + enum class tracking_mode : bool { - enum class tracking_mode : bool - { - IMMEDIATE, - LAZY - }; + eager, + lazy + }; - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/uint16.hpp b/include/tao/json/external/pegtl/uint16.hpp new file mode 100644 index 00000000..64c47a1b --- /dev/null +++ b/include/tao/json/external/pegtl/uint16.hpp @@ -0,0 +1,62 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_UINT16_HPP +#define TAO_JSON_PEGTL_UINT16_HPP + +#include "config.hpp" + +#include "internal/peek_mask_uint.hpp" +#include "internal/peek_uint.hpp" +#include "internal/result_on_found.hpp" +#include "internal/rules.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + namespace uint16_be + { + // clang-format off + struct any : internal::any< internal::peek_uint16_be > {}; + + template< std::uint16_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_uint16_be, Cs... > {}; + template< std::uint16_t Lo, std::uint16_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_uint16_be, Lo, Hi > {}; + template< std::uint16_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_uint16_be, Cs... > {}; + template< std::uint16_t Lo, std::uint16_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_uint16_be, Lo, Hi > {}; + template< std::uint16_t... Cs > struct ranges : internal::ranges< internal::peek_uint16_be, Cs... > {}; + template< std::uint16_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_uint16_be, Cs >... > {}; + + template< std::uint16_t M, std::uint16_t... Cs > struct mask_not_one : internal::one< internal::result_on_found::failure, internal::peek_mask_uint16_be< M >, Cs... > {}; + template< std::uint16_t M, std::uint16_t Lo, std::uint16_t Hi > struct mask_not_range : internal::range< internal::result_on_found::failure, internal::peek_mask_uint16_be< M >, Lo, Hi > {}; + template< std::uint16_t M, std::uint16_t... Cs > struct mask_one : internal::one< internal::result_on_found::success, internal::peek_mask_uint16_be< M >, Cs... > {}; + template< std::uint16_t M, std::uint16_t Lo, std::uint16_t Hi > struct mask_range : internal::range< internal::result_on_found::success, internal::peek_mask_uint16_be< M >, Lo, Hi > {}; + template< std::uint16_t M, std::uint16_t... Cs > struct mask_ranges : internal::ranges< internal::peek_mask_uint16_be< M >, Cs... > {}; + template< std::uint16_t M, std::uint16_t... Cs > struct mask_string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_mask_uint16_be< M >, Cs >... > {}; + // clang-format on + + } // namespace uint16_be + + namespace uint16_le + { + // clang-format off + struct any : internal::any< internal::peek_uint16_le > {}; + + template< std::uint16_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_uint16_le, Cs... > {}; + template< std::uint16_t Lo, std::uint16_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_uint16_le, Lo, Hi > {}; + template< std::uint16_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_uint16_le, Cs... > {}; + template< std::uint16_t Lo, std::uint16_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_uint16_le, Lo, Hi > {}; + template< std::uint16_t... Cs > struct ranges : internal::ranges< internal::peek_uint16_le, Cs... > {}; + template< std::uint16_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_uint16_le, Cs >... > {}; + + template< std::uint16_t M, std::uint16_t... Cs > struct mask_not_one : internal::one< internal::result_on_found::failure, internal::peek_mask_uint16_le< M >, Cs... > {}; + template< std::uint16_t M, std::uint16_t Lo, std::uint16_t Hi > struct mask_not_range : internal::range< internal::result_on_found::failure, internal::peek_mask_uint16_le< M >, Lo, Hi > {}; + template< std::uint16_t M, std::uint16_t... Cs > struct mask_one : internal::one< internal::result_on_found::success, internal::peek_mask_uint16_le< M >, Cs... > {}; + template< std::uint16_t M, std::uint16_t Lo, std::uint16_t Hi > struct mask_range : internal::range< internal::result_on_found::success, internal::peek_mask_uint16_le< M >, Lo, Hi > {}; + template< std::uint16_t M, std::uint16_t... Cs > struct mask_ranges : internal::ranges< internal::peek_mask_uint16_le< M >, Cs... > {}; + template< std::uint16_t M, std::uint16_t... Cs > struct mask_string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_mask_uint16_le< M >, Cs >... > {}; + // clang-format on + + } // namespace uint16_le + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/uint32.hpp b/include/tao/json/external/pegtl/uint32.hpp new file mode 100644 index 00000000..6345c463 --- /dev/null +++ b/include/tao/json/external/pegtl/uint32.hpp @@ -0,0 +1,62 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_UINT32_HPP +#define TAO_JSON_PEGTL_UINT32_HPP + +#include "config.hpp" + +#include "internal/peek_mask_uint.hpp" +#include "internal/peek_uint.hpp" +#include "internal/result_on_found.hpp" +#include "internal/rules.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + namespace uint32_be + { + // clang-format off + struct any : internal::any< internal::peek_uint32_be > {}; + + template< std::uint32_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_uint32_be, Cs... > {}; + template< std::uint32_t Lo, std::uint32_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_uint32_be, Lo, Hi > {}; + template< std::uint32_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_uint32_be, Cs... > {}; + template< std::uint32_t Lo, std::uint32_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_uint32_be, Lo, Hi > {}; + template< std::uint32_t... Cs > struct ranges : internal::ranges< internal::peek_uint32_be, Cs... > {}; + template< std::uint32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_uint32_be, Cs >... > {}; + + template< std::uint32_t M, std::uint32_t... Cs > struct mask_not_one : internal::one< internal::result_on_found::failure, internal::peek_mask_uint32_be< M >, Cs... > {}; + template< std::uint32_t M, std::uint32_t Lo, std::uint32_t Hi > struct mask_not_range : internal::range< internal::result_on_found::failure, internal::peek_mask_uint32_be< M >, Lo, Hi > {}; + template< std::uint32_t M, std::uint32_t... Cs > struct mask_one : internal::one< internal::result_on_found::success, internal::peek_mask_uint32_be< M >, Cs... > {}; + template< std::uint32_t M, std::uint32_t Lo, std::uint32_t Hi > struct mask_range : internal::range< internal::result_on_found::success, internal::peek_mask_uint32_be< M >, Lo, Hi > {}; + template< std::uint32_t M, std::uint32_t... Cs > struct mask_ranges : internal::ranges< internal::peek_mask_uint32_be< M >, Cs... > {}; + template< std::uint32_t M, std::uint32_t... Cs > struct mask_string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_mask_uint32_be< M >, Cs >... > {}; + // clang-format on + + } // namespace uint32_be + + namespace uint32_le + { + // clang-format off + struct any : internal::any< internal::peek_uint32_le > {}; + + template< std::uint32_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_uint32_le, Cs... > {}; + template< std::uint32_t Lo, std::uint32_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_uint32_le, Lo, Hi > {}; + template< std::uint32_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_uint32_le, Cs... > {}; + template< std::uint32_t Lo, std::uint32_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_uint32_le, Lo, Hi > {}; + template< std::uint32_t... Cs > struct ranges : internal::ranges< internal::peek_uint32_le, Cs... > {}; + template< std::uint32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_uint32_le, Cs >... > {}; + + template< std::uint32_t M, std::uint32_t... Cs > struct mask_not_one : internal::one< internal::result_on_found::failure, internal::peek_mask_uint32_le< M >, Cs... > {}; + template< std::uint32_t M, std::uint32_t Lo, std::uint32_t Hi > struct mask_not_range : internal::range< internal::result_on_found::failure, internal::peek_mask_uint32_le< M >, Lo, Hi > {}; + template< std::uint32_t M, std::uint32_t... Cs > struct mask_one : internal::one< internal::result_on_found::success, internal::peek_mask_uint32_le< M >, Cs... > {}; + template< std::uint32_t M, std::uint32_t Lo, std::uint32_t Hi > struct mask_range : internal::range< internal::result_on_found::success, internal::peek_mask_uint32_le< M >, Lo, Hi > {}; + template< std::uint32_t M, std::uint32_t... Cs > struct mask_ranges : internal::ranges< internal::peek_mask_uint32_le< M >, Cs... > {}; + template< std::uint32_t M, std::uint32_t... Cs > struct mask_string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_mask_uint32_le< M >, Cs >... > {}; + // clang-format on + + } // namespace uint32_le + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/uint64.hpp b/include/tao/json/external/pegtl/uint64.hpp new file mode 100644 index 00000000..64f358af --- /dev/null +++ b/include/tao/json/external/pegtl/uint64.hpp @@ -0,0 +1,63 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_UINT64_HPP +#define TAO_JSON_PEGTL_UINT64_HPP + +#include "config.hpp" + +#include "internal/peek_mask_uint.hpp" +#include "internal/peek_uint.hpp" +#include "internal/result_on_found.hpp" +#include "internal/rules.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE +{ + namespace uint64_be + { + // clang-format off + struct any : internal::any< internal::peek_uint64_be > {}; + + template< std::uint64_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_uint64_be, Cs... > {}; + template< std::uint64_t Lo, std::uint64_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_uint64_be, Lo, Hi > {}; + template< std::uint64_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_uint64_be, Cs... > {}; + template< std::uint64_t Lo, std::uint64_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_uint64_be, Lo, Hi > {}; + template< std::uint64_t... Cs > struct ranges : internal::ranges< internal::peek_uint64_be, Cs... > {}; + template< std::uint64_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_uint64_be, Cs >... > {}; + + + template< std::uint64_t M, std::uint64_t... Cs > struct mask_not_one : internal::one< internal::result_on_found::failure, internal::peek_mask_uint64_be< M >, Cs... > {}; + template< std::uint64_t M, std::uint64_t Lo, std::uint64_t Hi > struct mask_not_range : internal::range< internal::result_on_found::failure, internal::peek_mask_uint64_be< M >, Lo, Hi > {}; + template< std::uint64_t M, std::uint64_t... Cs > struct mask_one : internal::one< internal::result_on_found::success, internal::peek_mask_uint64_be< M >, Cs... > {}; + template< std::uint64_t M, std::uint64_t Lo, std::uint64_t Hi > struct mask_range : internal::range< internal::result_on_found::success, internal::peek_mask_uint64_be< M >, Lo, Hi > {}; + template< std::uint64_t M, std::uint64_t... Cs > struct mask_ranges : internal::ranges< internal::peek_mask_uint64_be< M >, Cs... > {}; + template< std::uint64_t M, std::uint64_t... Cs > struct mask_string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_mask_uint64_be< M >, Cs >... > {}; + // clang-format on + + } // namespace uint64_be + + namespace uint64_le + { + // clang-format off + struct any : internal::any< internal::peek_uint64_le > {}; + + template< std::uint64_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_uint64_le, Cs... > {}; + template< std::uint64_t Lo, std::uint64_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_uint64_le, Lo, Hi > {}; + template< std::uint64_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_uint64_le, Cs... > {}; + template< std::uint64_t Lo, std::uint64_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_uint64_le, Lo, Hi > {}; + template< std::uint64_t... Cs > struct ranges : internal::ranges< internal::peek_uint64_le, Cs... > {}; + template< std::uint64_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_uint64_le, Cs >... > {}; + + template< std::uint64_t M, std::uint64_t... Cs > struct mask_not_one : internal::one< internal::result_on_found::failure, internal::peek_mask_uint64_le< M >, Cs... > {}; + template< std::uint64_t M, std::uint64_t Lo, std::uint64_t Hi > struct mask_not_range : internal::range< internal::result_on_found::failure, internal::peek_mask_uint64_le< M >, Lo, Hi > {}; + template< std::uint64_t M, std::uint64_t... Cs > struct mask_one : internal::one< internal::result_on_found::success, internal::peek_mask_uint64_le< M >, Cs... > {}; + template< std::uint64_t M, std::uint64_t Lo, std::uint64_t Hi > struct mask_range : internal::range< internal::result_on_found::success, internal::peek_mask_uint64_le< M >, Lo, Hi > {}; + template< std::uint64_t M, std::uint64_t... Cs > struct mask_ranges : internal::ranges< internal::peek_mask_uint64_le< M >, Cs... > {}; + template< std::uint64_t M, std::uint64_t... Cs > struct mask_string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_mask_uint64_le< M >, Cs >... > {}; + // clang-format on + + } // namespace uint64_le + +} // namespace TAO_JSON_PEGTL_NAMESPACE + +#endif diff --git a/include/tao/json/external/pegtl/uint8.hpp b/include/tao/json/external/pegtl/uint8.hpp new file mode 100644 index 00000000..35a8375d --- /dev/null +++ b/include/tao/json/external/pegtl/uint8.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ + +#ifndef TAO_JSON_PEGTL_UINT8_HPP +#define TAO_JSON_PEGTL_UINT8_HPP + +#include "config.hpp" + +#include "internal/peek_mask_uint8.hpp" +#include "internal/peek_uint8.hpp" +#include "internal/result_on_found.hpp" +#include "internal/rules.hpp" + +namespace TAO_JSON_PEGTL_NAMESPACE::uint8 +{ + // clang-format off + struct any : internal::any< internal::peek_uint8 > {}; + + template< std::uint8_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_uint8, Cs... > {}; + template< std::uint8_t Lo, std::uint8_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_uint8, Lo, Hi > {}; + template< std::uint8_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_uint8, Cs... > {}; + template< std::uint8_t Lo, std::uint8_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_uint8, Lo, Hi > {}; + template< std::uint8_t... Cs > struct ranges : internal::ranges< internal::peek_uint8, Cs... > {}; + template< std::uint8_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_uint8, Cs >... > {}; + + template< std::uint8_t M, std::uint8_t... Cs > struct mask_not_one : internal::one< internal::result_on_found::failure, internal::peek_mask_uint8< M >, Cs... > {}; + template< std::uint8_t M, std::uint8_t Lo, std::uint8_t Hi > struct mask_not_range : internal::range< internal::result_on_found::failure, internal::peek_mask_uint8< M >, Lo, Hi > {}; + template< std::uint8_t M, std::uint8_t... Cs > struct mask_one : internal::one< internal::result_on_found::success, internal::peek_mask_uint8< M >, Cs... > {}; + template< std::uint8_t M, std::uint8_t Lo, std::uint8_t Hi > struct mask_range : internal::range< internal::result_on_found::success, internal::peek_mask_uint8< M >, Lo, Hi > {}; + template< std::uint8_t M, std::uint8_t... Cs > struct mask_ranges : internal::ranges< internal::peek_mask_uint8< M >, Cs... > {}; + template< std::uint8_t M, std::uint8_t... Cs > struct mask_string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_mask_uint8< M >, Cs >... > {}; + // clang-format on + +} // namespace TAO_JSON_PEGTL_NAMESPACE::uint8 + +#endif diff --git a/include/tao/json/external/pegtl/utf16.hpp b/include/tao/json/external/pegtl/utf16.hpp index da03f2eb..29f969f4 100644 --- a/include/tao/json/external/pegtl/utf16.hpp +++ b/include/tao/json/external/pegtl/utf16.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_UTF16_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_UTF16_HPP +#ifndef TAO_JSON_PEGTL_UTF16_HPP +#define TAO_JSON_PEGTL_UTF16_HPP #include "config.hpp" @@ -10,27 +10,40 @@ #include "internal/result_on_found.hpp" #include "internal/rules.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + namespace utf16_be { - namespace utf16 - { - // clang-format off - struct any : internal::any< internal::peek_utf16 > {}; - struct bom : internal::one< internal::result_on_found::SUCCESS, internal::peek_utf16, 0xfeff > {}; - template< char32_t... Cs > struct not_one : internal::one< internal::result_on_found::FAILURE, internal::peek_utf16, Cs... > {}; - template< char32_t Lo, char32_t Hi > struct not_range : internal::range< internal::result_on_found::FAILURE, internal::peek_utf16, Lo, Hi > {}; - template< char32_t... Cs > struct one : internal::one< internal::result_on_found::SUCCESS, internal::peek_utf16, Cs... > {}; - template< char32_t Lo, char32_t Hi > struct range : internal::range< internal::result_on_found::SUCCESS, internal::peek_utf16, Lo, Hi > {}; - template< char32_t... Cs > struct ranges : internal::ranges< internal::peek_utf16, Cs... > {}; - template< char32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::SUCCESS, internal::peek_utf16, Cs >... > {}; - // clang-format on - - } // namespace utf16 - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + // clang-format off + struct any : internal::any< internal::peek_utf16_be > {}; + struct bom : internal::one< internal::result_on_found::success, internal::peek_utf16_be, 0xfeff > {}; + template< char32_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_utf16_be, Cs... > {}; + template< char32_t Lo, char32_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_utf16_be, Lo, Hi > {}; + template< char32_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_utf16_be, Cs... > {}; + template< char32_t Lo, char32_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_utf16_be, Lo, Hi > {}; + template< char32_t... Cs > struct ranges : internal::ranges< internal::peek_utf16_be, Cs... > {}; + template< char32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_utf16_be, Cs >... > {}; + // clang-format on + + } // namespace utf16_be + + namespace utf16_le + { + // clang-format off + struct any : internal::any< internal::peek_utf16_le > {}; + struct bom : internal::one< internal::result_on_found::success, internal::peek_utf16_le, 0xfeff > {}; + template< char32_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_utf16_le, Cs... > {}; + template< char32_t Lo, char32_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_utf16_le, Lo, Hi > {}; + template< char32_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_utf16_le, Cs... > {}; + template< char32_t Lo, char32_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_utf16_le, Lo, Hi > {}; + template< char32_t... Cs > struct ranges : internal::ranges< internal::peek_utf16_le, Cs... > {}; + template< char32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_utf16_le, Cs >... > {}; + // clang-format on + + } // namespace utf16_le + + namespace utf16 = TAO_JSON_PEGTL_NATIVE_UTF16; + +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/utf32.hpp b/include/tao/json/external/pegtl/utf32.hpp index 3029d6aa..e6d54879 100644 --- a/include/tao/json/external/pegtl/utf32.hpp +++ b/include/tao/json/external/pegtl/utf32.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_UTF32_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_UTF32_HPP +#ifndef TAO_JSON_PEGTL_UTF32_HPP +#define TAO_JSON_PEGTL_UTF32_HPP #include "config.hpp" @@ -10,27 +10,40 @@ #include "internal/result_on_found.hpp" #include "internal/rules.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE { - namespace TAOCPP_JSON_PEGTL_NAMESPACE + namespace utf32_be { - namespace utf32 - { - // clang-format off - struct any : internal::any< internal::peek_utf32 > {}; - struct bom : internal::one< internal::result_on_found::SUCCESS, internal::peek_utf32, 0xfeff > {}; - template< char32_t... Cs > struct not_one : internal::one< internal::result_on_found::FAILURE, internal::peek_utf32, Cs... > {}; - template< char32_t Lo, char32_t Hi > struct not_range : internal::range< internal::result_on_found::FAILURE, internal::peek_utf32, Lo, Hi > {}; - template< char32_t... Cs > struct one : internal::one< internal::result_on_found::SUCCESS, internal::peek_utf32, Cs... > {}; - template< char32_t Lo, char32_t Hi > struct range : internal::range< internal::result_on_found::SUCCESS, internal::peek_utf32, Lo, Hi > {}; - template< char32_t... Cs > struct ranges : internal::ranges< internal::peek_utf32, Cs... > {}; - template< char32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::SUCCESS, internal::peek_utf32, Cs >... > {}; - // clang-format on - - } // namespace utf32 - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + // clang-format off + struct any : internal::any< internal::peek_utf32_be > {}; + struct bom : internal::one< internal::result_on_found::success, internal::peek_utf32_be, 0xfeff > {}; + template< char32_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_utf32_be, Cs... > {}; + template< char32_t Lo, char32_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_utf32_be, Lo, Hi > {}; + template< char32_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_utf32_be, Cs... > {}; + template< char32_t Lo, char32_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_utf32_be, Lo, Hi > {}; + template< char32_t... Cs > struct ranges : internal::ranges< internal::peek_utf32_be, Cs... > {}; + template< char32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_utf32_be, Cs >... > {}; + // clang-format on + + } // namespace utf32_be + + namespace utf32_le + { + // clang-format off + struct any : internal::any< internal::peek_utf32_le > {}; + struct bom : internal::one< internal::result_on_found::success, internal::peek_utf32_le, 0xfeff > {}; + template< char32_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_utf32_le, Cs... > {}; + template< char32_t Lo, char32_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_utf32_le, Lo, Hi > {}; + template< char32_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_utf32_le, Cs... > {}; + template< char32_t Lo, char32_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_utf32_le, Lo, Hi > {}; + template< char32_t... Cs > struct ranges : internal::ranges< internal::peek_utf32_le, Cs... > {}; + template< char32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_utf32_le, Cs >... > {}; + // clang-format on + + } // namespace utf32_le + + namespace utf32 = TAO_JSON_PEGTL_NATIVE_UTF32; + +} // namespace TAO_JSON_PEGTL_NAMESPACE #endif diff --git a/include/tao/json/external/pegtl/utf8.hpp b/include/tao/json/external/pegtl/utf8.hpp index 5f91e3ca..9589f5b0 100644 --- a/include/tao/json/external/pegtl/utf8.hpp +++ b/include/tao/json/external/pegtl/utf8.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2014-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_UTF8_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_UTF8_HPP +#ifndef TAO_JSON_PEGTL_UTF8_HPP +#define TAO_JSON_PEGTL_UTF8_HPP #include "config.hpp" @@ -10,27 +10,19 @@ #include "internal/result_on_found.hpp" #include "internal/rules.hpp" -namespace tao +namespace TAO_JSON_PEGTL_NAMESPACE::utf8 { - namespace TAOCPP_JSON_PEGTL_NAMESPACE - { - namespace utf8 - { - // clang-format off - struct any : internal::any< internal::peek_utf8 > {}; - struct bom : internal::one< internal::result_on_found::SUCCESS, internal::peek_utf8, 0xfeff > {}; - template< char32_t... Cs > struct not_one : internal::one< internal::result_on_found::FAILURE, internal::peek_utf8, Cs... > {}; - template< char32_t Lo, char32_t Hi > struct not_range : internal::range< internal::result_on_found::FAILURE, internal::peek_utf8, Lo, Hi > {}; - template< char32_t... Cs > struct one : internal::one< internal::result_on_found::SUCCESS, internal::peek_utf8, Cs... > {}; - template< char32_t Lo, char32_t Hi > struct range : internal::range< internal::result_on_found::SUCCESS, internal::peek_utf8, Lo, Hi > {}; - template< char32_t... Cs > struct ranges : internal::ranges< internal::peek_utf8, Cs... > {}; - template< char32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::SUCCESS, internal::peek_utf8, Cs >... > {}; - // clang-format on - - } // namespace utf8 - - } // namespace TAOCPP_JSON_PEGTL_NAMESPACE - -} // namespace tao + // clang-format off + struct any : internal::any< internal::peek_utf8 > {}; + struct bom : internal::one< internal::result_on_found::success, internal::peek_utf8, 0xfeff > {}; + template< char32_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_utf8, Cs... > {}; + template< char32_t Lo, char32_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_utf8, Lo, Hi > {}; + template< char32_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_utf8, Cs... > {}; + template< char32_t Lo, char32_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_utf8, Lo, Hi > {}; + template< char32_t... Cs > struct ranges : internal::ranges< internal::peek_utf8, Cs... > {}; + template< char32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_utf8, Cs >... > {}; + // clang-format on + +} // namespace TAO_JSON_PEGTL_NAMESPACE::utf8 #endif diff --git a/include/tao/json/external/pegtl/version.hpp b/include/tao/json/external/pegtl/version.hpp index a269f4c3..9baf0bb9 100644 --- a/include/tao/json/external/pegtl/version.hpp +++ b/include/tao/json/external/pegtl/version.hpp @@ -1,13 +1,13 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ -#ifndef TAOCPP_JSON_PEGTL_INCLUDE_VERSION_HPP -#define TAOCPP_JSON_PEGTL_INCLUDE_VERSION_HPP +#ifndef TAO_JSON_PEGTL_VERSION_HPP +#define TAO_JSON_PEGTL_VERSION_HPP -#define TAOCPP_JSON_PEGTL_VERSION "2.2.0" +#define TAO_JSON_PEGTL_VERSION "3.0.0" -#define TAOCPP_JSON_PEGTL_VERSION_MAJOR 2 -#define TAOCPP_JSON_PEGTL_VERSION_MINOR 2 -#define TAOCPP_JSON_PEGTL_VERSION_PATCH 0 +#define TAO_JSON_PEGTL_VERSION_MAJOR 3 +#define TAO_JSON_PEGTL_VERSION_MINOR 0 +#define TAO_JSON_PEGTL_VERSION_PATCH 0 #endif diff --git a/include/tao/json/external/ryu.hpp b/include/tao/json/external/ryu.hpp new file mode 100644 index 00000000..f3c01e22 --- /dev/null +++ b/include/tao/json/external/ryu.hpp @@ -0,0 +1,1216 @@ +// This header include/tao/json/external/ryu.hpp contains +// modified portions of the ulfjack/ryu library from +// https://github.com/ulfjack/ryu +// which is licensed as follows: + +// Copyright 2018 Ulf Adams +// +// The contents of this file may be used under the terms of the Apache License, +// Version 2.0. +// +// (See accompanying file LICENSE-Apache or copy at +// http://www.apache.org/licenses/LICENSE-2.0) +// +// Alternatively, the contents of this file may be used under the terms of +// the Boost Software License, Version 1.0. +// (See accompanying file LICENSE-Boost or copy at +// https://www.boost.org/LICENSE_1_0.txt) +// +// Unless required by applicable law or agreed to in writing, this software +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. + +#ifndef TAO_JSON_EXTERNAL_RYU_HPP +#define TAO_JSON_EXTERNAL_RYU_HPP + +// Runtime compiler options: +// -DRYU_ONLY_64_BIT_OPS Avoid using uint128_t or 64-bit intrinsics. Slower, +// depending on your compiler. +// + +// ABSL avoids uint128_t on Win32 even if __SIZEOF_INT128__ is defined. +// Let's do the same for now. +#if defined( __SIZEOF_INT128__ ) && !defined( _MSC_VER ) && !defined( RYU_ONLY_64_BIT_OPS ) +#define HAS_UINT128 +#elif defined( _MSC_VER ) && !defined( RYU_ONLY_64_BIT_OPS ) && defined( _M_X64 ) && !defined( __clang__ ) // https://bugs.llvm.org/show_bug.cgi?id=37755 +#define HAS_64_BIT_INTRINSICS +#include +#endif + +#include +#include +#include +#include + +#include "itoa.hpp" + +namespace tao::json::ryu +{ + // Returns e == 0 ? 1 : ceil(log_2(5^e)). + inline uint32_t pow5bits( const std::int32_t e ) + { + // This function has only been tested for 0 <= e <= 1500. + assert( e >= 0 ); + assert( e <= 1500 ); + return ( ( std::uint32_t( e ) * 1217359 ) >> 19 ) + 1; + } + + // Returns floor(log_10(2^e)). + inline std::int32_t log10Pow2( const std::int32_t e ) + { + // This function has only been tested for 0 <= e <= 1500. + assert( e >= 0 ); + assert( e <= 1500 ); + return std::int32_t( ( uint32_t( e ) * 78913 ) >> 18 ); + } + + // Returns floor(log_10(5^e)). + inline std::int32_t log10Pow5( const std::int32_t e ) + { + // This function has only been tested for 0 <= e <= 1500. + assert( e >= 0 ); + assert( e <= 1500 ); + return std::int32_t( ( std::uint32_t( e ) * 732923 ) >> 20 ); + } + +#if defined( HAS_UINT128 ) + + using uint128_t = __uint128_t; + +#elif defined( HAS_64_BIT_INTRINSICS ) + + inline std::uint64_t umul128( const std::uint64_t a, const std::uint64_t b, std::uint64_t& productHi ) + { + return _umul128( a, b, &productHi ); + } + + inline std::uint64_t shiftright128( const std::uint64_t lo, const std::uint64_t hi, const std::uint32_t dist ) + { + // For the __shiftright128 intrinsic, the shift value is always + // modulo 64. + // In the current implementation of the double-precision version + // of Ryu, the shift value is always < 64. (In the case + // RYU_OPTIMIZE_SIZE == 0, the shift value is in the range [50,58]. + // Otherwise in the range [2,59].) + // Check this here in case a future change requires larger shift + // values. In this case this function needs to be adjusted. + assert( dist < 64 ); + return __shiftright128( lo, hi, std::uint8_t( dist ) ); + } + +#else + + static inline std::uint64_t umul128( const std::uint64_t a, const std::uint64_t b, std::uint64_t& productHi ) + { + // The casts here help MSVC to avoid calls to the __allmul library function. + const std::uint32_t aLo = (std::uint32_t)a; + const std::uint32_t aHi = ( std::uint32_t )( a >> 32 ); + const std::uint32_t bLo = (std::uint32_t)b; + const std::uint32_t bHi = ( std::uint32_t )( b >> 32 ); + + const std::uint64_t b00 = (std::uint64_t)aLo * bLo; + const std::uint64_t b01 = (std::uint64_t)aLo * bHi; + const std::uint64_t b10 = (std::uint64_t)aHi * bLo; + const std::uint64_t b11 = (std::uint64_t)aHi * bHi; + + const std::uint64_t midSum = b01 + b10; + const std::uint64_t midCarry = midSum < b01; + + const std::uint64_t productLo = b00 + ( midSum << 32 ); + const std::uint64_t productLoCarry = productLo < b00; + + productHi = b11 + ( midSum >> 32 ) + ( midCarry << 32 ) + productLoCarry; + return productLo; + } + + static inline std::uint64_t shiftright128( const std::uint64_t lo, const std::uint64_t hi, const std::uint32_t dist ) + { + // We don't need to handle the case dist >= 64 here (see above). + assert( dist > 0 ); + assert( dist < 64 ); + return ( hi << ( 64 - dist ) ) | ( lo >> dist ); + } + +#endif + + // A table of all two-digit numbers. This is used to speed up decimal digit + // generation by copying pairs of digits into the final output. + // static const char digit_table[ 200 ] = { + // '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9' + // }; + // NOTE: Now uses itoa::s_pairs to prevent having the same data twice. + + // These tables are generated by PrintDoubleLookupTable. + static const std::uint64_t pow5_inv_split[ 292 ][ 2 ] = { + { 1u, 288230376151711744u }, + { 3689348814741910324u, 230584300921369395u }, + { 2951479051793528259u, 184467440737095516u }, + { 17118578500402463900u, 147573952589676412u }, + { 12632330341676300947u, 236118324143482260u }, + { 10105864273341040758u, 188894659314785808u }, + { 15463389048156653253u, 151115727451828646u }, + { 17362724847566824558u, 241785163922925834u }, + { 17579528692795369969u, 193428131138340667u }, + { 6684925324752475329u, 154742504910672534u }, + { 18074578149087781173u, 247588007857076054u }, + { 18149011334012135262u, 198070406285660843u }, + { 3451162622983977240u, 158456325028528675u }, + { 5521860196774363583u, 253530120045645880u }, + { 4417488157419490867u, 202824096036516704u }, + { 7223339340677503017u, 162259276829213363u }, + { 7867994130342094503u, 259614842926741381u }, + { 2605046489531765280u, 207691874341393105u }, + { 2084037191625412224u, 166153499473114484u }, + { 10713157136084480204u, 265845599156983174u }, + { 12259874523609494487u, 212676479325586539u }, + { 13497248433629505913u, 170141183460469231u }, + { 14216899864323388813u, 272225893536750770u }, + { 11373519891458711051u, 217780714829400616u }, + { 5409467098425058518u, 174224571863520493u }, + { 4965798542738183305u, 278759314981632789u }, + { 7661987648932456967u, 223007451985306231u }, + { 2440241304404055250u, 178405961588244985u }, + { 3904386087046488400u, 285449538541191976u }, + { 17880904128604832013u, 228359630832953580u }, + { 14304723302883865611u, 182687704666362864u }, + { 15133127457049002812u, 146150163733090291u }, + { 16834306301794583852u, 233840261972944466u }, + { 9778096226693756759u, 187072209578355573u }, + { 15201174610838826053u, 149657767662684458u }, + { 2185786488890659746u, 239452428260295134u }, + { 5437978005854438120u, 191561942608236107u }, + { 15418428848909281466u, 153249554086588885u }, + { 6222742084545298729u, 245199286538542217u }, + { 16046240111861969953u, 196159429230833773u }, + { 1768945645263844993u, 156927543384667019u }, + { 10209010661905972635u, 251084069415467230u }, + { 8167208529524778108u, 200867255532373784u }, + { 10223115638361732810u, 160693804425899027u }, + { 1599589762411131202u, 257110087081438444u }, + { 4969020624670815285u, 205688069665150755u }, + { 3975216499736652228u, 164550455732120604u }, + { 13739044029062464211u, 263280729171392966u }, + { 7301886408508061046u, 210624583337114373u }, + { 13220206756290269483u, 168499666669691498u }, + { 17462981995322520850u, 269599466671506397u }, + { 6591687966774196033u, 215679573337205118u }, + { 12652048002903177473u, 172543658669764094u }, + { 9175230360419352987u, 276069853871622551u }, + { 3650835473593572067u, 220855883097298041u }, + { 17678063637842498946u, 176684706477838432u }, + { 13527506561580357021u, 282695530364541492u }, + { 3443307619780464970u, 226156424291633194u }, + { 6443994910566282300u, 180925139433306555u }, + { 5155195928453025840u, 144740111546645244u }, + { 15627011115008661990u, 231584178474632390u }, + { 12501608892006929592u, 185267342779705912u }, + { 2622589484121723027u, 148213874223764730u }, + { 4196143174594756843u, 237142198758023568u }, + { 10735612169159626121u, 189713759006418854u }, + { 12277838550069611220u, 151771007205135083u }, + { 15955192865369467629u, 242833611528216133u }, + { 1696107848069843133u, 194266889222572907u }, + { 12424932722681605476u, 155413511378058325u }, + { 1433148282581017146u, 248661618204893321u }, + { 15903913885032455010u, 198929294563914656u }, + { 9033782293284053685u, 159143435651131725u }, + { 14454051669254485895u, 254629497041810760u }, + { 11563241335403588716u, 203703597633448608u }, + { 16629290697806691620u, 162962878106758886u }, + { 781423413297334329u, 260740604970814219u }, + { 4314487545379777786u, 208592483976651375u }, + { 3451590036303822229u, 166873987181321100u }, + { 5522544058086115566u, 266998379490113760u }, + { 4418035246468892453u, 213598703592091008u }, + { 10913125826658934609u, 170878962873672806u }, + { 10082303693170474728u, 273406340597876490u }, + { 8065842954536379782u, 218725072478301192u }, + { 17520720807854834795u, 174980057982640953u }, + { 5897060404116273733u, 279968092772225526u }, + { 1028299508551108663u, 223974474217780421u }, + { 15580034865808528224u, 179179579374224336u }, + { 17549358155809824511u, 286687326998758938u }, + { 2971440080422128639u, 229349861599007151u }, + { 17134547323305344204u, 183479889279205720u }, + { 13707637858644275364u, 146783911423364576u }, + { 14553522944347019935u, 234854258277383322u }, + { 4264120725993795302u, 187883406621906658u }, + { 10789994210278856888u, 150306725297525326u }, + { 9885293106962350374u, 240490760476040522u }, + { 529536856086059653u, 192392608380832418u }, + { 7802327114352668369u, 153914086704665934u }, + { 1415676938738538420u, 246262538727465495u }, + { 1132541550990830736u, 197010030981972396u }, + { 15663428499760305882u, 157608024785577916u }, + { 17682787970132668764u, 252172839656924666u }, + { 10456881561364224688u, 201738271725539733u }, + { 15744202878575200397u, 161390617380431786u }, + { 17812026976236499989u, 258224987808690858u }, + { 3181575136763469022u, 206579990246952687u }, + { 13613306553636506187u, 165263992197562149u }, + { 10713244041592678929u, 264422387516099439u }, + { 12259944048016053467u, 211537910012879551u }, + { 6118606423670932450u, 169230328010303641u }, + { 2411072648389671274u, 270768524816485826u }, + { 16686253377679378312u, 216614819853188660u }, + { 13349002702143502650u, 173291855882550928u }, + { 17669055508687693916u, 277266969412081485u }, + { 14135244406950155133u, 221813575529665188u }, + { 240149081334393137u, 177450860423732151u }, + { 11452284974360759988u, 283921376677971441u }, + { 5472479164746697667u, 227137101342377153u }, + { 11756680961281178780u, 181709681073901722u }, + { 2026647139541122378u, 145367744859121378u }, + { 18000030682233437097u, 232588391774594204u }, + { 18089373360528660001u, 186070713419675363u }, + { 3403452244197197031u, 148856570735740291u }, + { 16513570034941246220u, 238170513177184465u }, + { 13210856027952996976u, 190536410541747572u }, + { 3189987192878576934u, 152429128433398058u }, + { 1414630693863812771u, 243886605493436893u }, + { 8510402184574870864u, 195109284394749514u }, + { 10497670562401807014u, 156087427515799611u }, + { 9417575270359070576u, 249739884025279378u }, + { 14912757845771077107u, 199791907220223502u }, + { 4551508647133041040u, 159833525776178802u }, + { 10971762650154775986u, 255733641241886083u }, + { 16156107749607641435u, 204586912993508866u }, + { 9235537384944202825u, 163669530394807093u }, + { 11087511001168814197u, 261871248631691349u }, + { 12559357615676961681u, 209496998905353079u }, + { 13736834907283479668u, 167597599124282463u }, + { 18289587036911657145u, 268156158598851941u }, + { 10942320814787415393u, 214524926879081553u }, + { 16132554281313752961u, 171619941503265242u }, + { 11054691591134363444u, 274591906405224388u }, + { 16222450902391311402u, 219673525124179510u }, + { 12977960721913049122u, 175738820099343608u }, + { 17075388340318968271u, 281182112158949773u }, + { 2592264228029443648u, 224945689727159819u }, + { 5763160197165465241u, 179956551781727855u }, + { 9221056315464744386u, 287930482850764568u }, + { 14755542681855616155u, 230344386280611654u }, + { 15493782960226403247u, 184275509024489323u }, + { 1326979923955391628u, 147420407219591459u }, + { 9501865507812447252u, 235872651551346334u }, + { 11290841220991868125u, 188698121241077067u }, + { 1653975347309673853u, 150958496992861654u }, + { 10025058185179298811u, 241533595188578646u }, + { 4330697733401528726u, 193226876150862917u }, + { 14532604630946953951u, 154581500920690333u }, + { 1116074521063664381u, 247330401473104534u }, + { 4582208431592841828u, 197864321178483627u }, + { 14733813189500004432u, 158291456942786901u }, + { 16195403473716186445u, 253266331108459042u }, + { 5577625149489128510u, 202613064886767234u }, + { 8151448934333213131u, 162090451909413787u }, + { 16731667109675051333u, 259344723055062059u }, + { 17074682502481951390u, 207475778444049647u }, + { 6281048372501740465u, 165980622755239718u }, + { 6360328581260874421u, 265568996408383549u }, + { 8777611679750609860u, 212455197126706839u }, + { 10711438158542398211u, 169964157701365471u }, + { 9759603424184016492u, 271942652322184754u }, + { 11497031554089123517u, 217554121857747803u }, + { 16576322872755119460u, 174043297486198242u }, + { 11764721337440549842u, 278469275977917188u }, + { 16790474699436260520u, 222775420782333750u }, + { 13432379759549008416u, 178220336625867000u }, + { 3045063541568861850u, 285152538601387201u }, + { 17193446092222730773u, 228122030881109760u }, + { 13754756873778184618u, 182497624704887808u }, + { 18382503128506368341u, 145998099763910246u }, + { 3586563302416817083u, 233596959622256395u }, + { 2869250641933453667u, 186877567697805116u }, + { 17052795772514404226u, 149502054158244092u }, + { 12527077977055405469u, 239203286653190548u }, + { 17400360011128145022u, 191362629322552438u }, + { 2852241564676785048u, 153090103458041951u }, + { 15631632947708587046u, 244944165532867121u }, + { 8815957543424959314u, 195955332426293697u }, + { 18120812478965698421u, 156764265941034957u }, + { 14235904707377476180u, 250822825505655932u }, + { 4010026136418160298u, 200658260404524746u }, + { 17965416168102169531u, 160526608323619796u }, + { 2919224165770098987u, 256842573317791675u }, + { 2335379332616079190u, 205474058654233340u }, + { 1868303466092863352u, 164379246923386672u }, + { 6678634360490491686u, 263006795077418675u }, + { 5342907488392393349u, 210405436061934940u }, + { 4274325990713914679u, 168324348849547952u }, + { 10528270399884173809u, 269318958159276723u }, + { 15801313949391159694u, 215455166527421378u }, + { 1573004715287196786u, 172364133221937103u }, + { 17274202803427156150u, 275782613155099364u }, + { 17508711057483635243u, 220626090524079491u }, + { 10317620031244997871u, 176500872419263593u }, + { 12818843235250086271u, 282401395870821749u }, + { 13944423402941979340u, 225921116696657399u }, + { 14844887537095493795u, 180736893357325919u }, + { 15565258844418305359u, 144589514685860735u }, + { 6457670077359736959u, 231343223497377177u }, + { 16234182506113520537u, 185074578797901741u }, + { 9297997190148906106u, 148059663038321393u }, + { 11187446689496339446u, 236895460861314229u }, + { 12639306166338981880u, 189516368689051383u }, + { 17490142562555006151u, 151613094951241106u }, + { 2158786396894637579u, 242580951921985771u }, + { 16484424376483351356u, 194064761537588616u }, + { 9498190686444770762u, 155251809230070893u }, + { 11507756283569722895u, 248402894768113429u }, + { 12895553841597688639u, 198722315814490743u }, + { 17695140702761971558u, 158977852651592594u }, + { 17244178680193423523u, 254364564242548151u }, + { 10105994129412828495u, 203491651394038521u }, + { 4395446488788352473u, 162793321115230817u }, + { 10722063196803274280u, 260469313784369307u }, + { 1198952927958798777u, 208375451027495446u }, + { 15716557601334680315u, 166700360821996356u }, + { 17767794532651667857u, 266720577315194170u }, + { 14214235626121334286u, 213376461852155336u }, + { 7682039686155157106u, 170701169481724269u }, + { 1223217053622520399u, 273121871170758831u }, + { 15735968901865657612u, 218497496936607064u }, + { 16278123936234436413u, 174797997549285651u }, + { 219556594781725998u, 279676796078857043u }, + { 7554342905309201445u, 223741436863085634u }, + { 9732823138989271479u, 178993149490468507u }, + { 815121763415193074u, 286389039184749612u }, + { 11720143854957885429u, 229111231347799689u }, + { 13065463898708218666u, 183288985078239751u }, + { 6763022304224664610u, 146631188062591801u }, + { 3442138057275642729u, 234609900900146882u }, + { 13821756890046245153u, 187687920720117505u }, + { 11057405512036996122u, 150150336576094004u }, + { 6623802375033462826u, 240240538521750407u }, + { 16367088344252501231u, 192192430817400325u }, + { 13093670675402000985u, 153753944653920260u }, + { 2503129006933649959u, 246006311446272417u }, + { 13070549649772650937u, 196805049157017933u }, + { 17835137349301941396u, 157444039325614346u }, + { 2710778055689733971u, 251910462920982955u }, + { 2168622444551787177u, 201528370336786364u }, + { 5424246770383340065u, 161222696269429091u }, + { 1300097203129523457u, 257956314031086546u }, + { 15797473021471260058u, 206365051224869236u }, + { 8948629602435097724u, 165092040979895389u }, + { 3249760919670425388u, 264147265567832623u }, + { 9978506365220160957u, 211317812454266098u }, + { 15361502721659949412u, 169054249963412878u }, + { 2442311466204457120u, 270486799941460606u }, + { 16711244431931206989u, 216389439953168484u }, + { 17058344360286875914u, 173111551962534787u }, + { 12535955717491360170u, 276978483140055660u }, + { 10028764573993088136u, 221582786512044528u }, + { 15401709288678291155u, 177266229209635622u }, + { 9885339602917624555u, 283625966735416996u }, + { 4218922867592189321u, 226900773388333597u }, + { 14443184738299482427u, 181520618710666877u }, + { 4175850161155765295u, 145216494968533502u }, + { 10370709072591134795u, 232346391949653603u }, + { 15675264887556728482u, 185877113559722882u }, + { 5161514280561562140u, 148701690847778306u }, + { 879725219414678777u, 237922705356445290u }, + { 703780175531743021u, 190338164285156232u }, + { 11631070584651125387u, 152270531428124985u }, + { 162968861732249003u, 243632850284999977u }, + { 11198421533611530172u, 194906280227999981u }, + { 5269388412147313814u, 155925024182399985u }, + { 8431021459435702103u, 249480038691839976u }, + { 3055468352806651359u, 199584030953471981u }, + { 17201769941212962380u, 159667224762777584u }, + { 16454785461715008838u, 255467559620444135u }, + { 13163828369372007071u, 204374047696355308u }, + { 17909760324981426303u, 163499238157084246u }, + { 2830174816776909822u, 261598781051334795u }, + { 2264139853421527858u, 209279024841067836u }, + { 16568707141704863579u, 167423219872854268u }, + { 4373838538276319787u, 267877151796566830u }, + { 3499070830621055830u, 214301721437253464u }, + { 6488605479238754987u, 171441377149802771u }, + { 3003071137298187333u, 274306203439684434u }, + { 6091805724580460189u, 219444962751747547u }, + { 15941491023890099121u, 175555970201398037u }, + { 10748990379256517301u, 280889552322236860u }, + { 8599192303405213841u, 224711641857789488u }, + { 14258051472207991719u, 179769313486231590u }, + }; + + static const std::uint64_t pow5_split[ 326 ][ 2 ] = { + { 0u, 72057594037927936u }, + { 0u, 90071992547409920u }, + { 0u, 112589990684262400u }, + { 0u, 140737488355328000u }, + { 0u, 87960930222080000u }, + { 0u, 109951162777600000u }, + { 0u, 137438953472000000u }, + { 0u, 85899345920000000u }, + { 0u, 107374182400000000u }, + { 0u, 134217728000000000u }, + { 0u, 83886080000000000u }, + { 0u, 104857600000000000u }, + { 0u, 131072000000000000u }, + { 0u, 81920000000000000u }, + { 0u, 102400000000000000u }, + { 0u, 128000000000000000u }, + { 0u, 80000000000000000u }, + { 0u, 100000000000000000u }, + { 0u, 125000000000000000u }, + { 0u, 78125000000000000u }, + { 0u, 97656250000000000u }, + { 0u, 122070312500000000u }, + { 0u, 76293945312500000u }, + { 0u, 95367431640625000u }, + { 0u, 119209289550781250u }, + { 4611686018427387904u, 74505805969238281u }, + { 10376293541461622784u, 93132257461547851u }, + { 8358680908399640576u, 116415321826934814u }, + { 612489549322387456u, 72759576141834259u }, + { 14600669991935148032u, 90949470177292823u }, + { 13639151471491547136u, 113686837721616029u }, + { 3213881284082270208u, 142108547152020037u }, + { 4314518811765112832u, 88817841970012523u }, + { 781462496279003136u, 111022302462515654u }, + { 10200200157203529728u, 138777878078144567u }, + { 13292654125893287936u, 86736173798840354u }, + { 7392445620511834112u, 108420217248550443u }, + { 4628871007212404736u, 135525271560688054u }, + { 16728102434789916672u, 84703294725430033u }, + { 7075069988205232128u, 105879118406787542u }, + { 18067209522111315968u, 132348898008484427u }, + { 8986162942105878528u, 82718061255302767u }, + { 6621017659204960256u, 103397576569128459u }, + { 3664586055578812416u, 129246970711410574u }, + { 16125424340018921472u, 80779356694631608u }, + { 1710036351314100224u, 100974195868289511u }, + { 15972603494424788992u, 126217744835361888u }, + { 9982877184015493120u, 78886090522101180u }, + { 12478596480019366400u, 98607613152626475u }, + { 10986559581596820096u, 123259516440783094u }, + { 2254913720070624656u, 77037197775489434u }, + { 12042014186943056628u, 96296497219361792u }, + { 15052517733678820785u, 120370621524202240u }, + { 9407823583549262990u, 75231638452626400u }, + { 11759779479436578738u, 94039548065783000u }, + { 14699724349295723422u, 117549435082228750u }, + { 4575641699882439235u, 73468396926392969u }, + { 10331238143280436948u, 91835496157991211u }, + { 8302361660673158281u, 114794370197489014u }, + { 1154580038986672043u, 143492962746861268u }, + { 9944984561221445835u, 89683101716788292u }, + { 12431230701526807293u, 112103877145985365u }, + { 1703980321626345405u, 140129846432481707u }, + { 17205888765512323542u, 87581154020301066u }, + { 12283988920035628619u, 109476442525376333u }, + { 1519928094762372062u, 136845553156720417u }, + { 12479170105294952299u, 85528470722950260u }, + { 15598962631618690374u, 106910588403687825u }, + { 5663645234241199255u, 133638235504609782u }, + { 17374836326682913246u, 83523897190381113u }, + { 7883487353071477846u, 104404871487976392u }, + { 9854359191339347308u, 130506089359970490u }, + { 10770660513014479971u, 81566305849981556u }, + { 13463325641268099964u, 101957882312476945u }, + { 2994098996302961243u, 127447352890596182u }, + { 15706369927971514489u, 79654595556622613u }, + { 5797904354682229399u, 99568244445778267u }, + { 2635694424925398845u, 124460305557222834u }, + { 6258995034005762182u, 77787690973264271u }, + { 3212057774079814824u, 97234613716580339u }, + { 17850130272881932242u, 121543267145725423u }, + { 18073860448192289507u, 75964541966078389u }, + { 8757267504958198172u, 94955677457597987u }, + { 6334898362770359811u, 118694596821997484u }, + { 13182683513586250689u, 74184123013748427u }, + { 11866668373555425458u, 92730153767185534u }, + { 5609963430089506015u, 115912692208981918u }, + { 17341285199088104971u, 72445432630613698u }, + { 12453234462005355406u, 90556790788267123u }, + { 10954857059079306353u, 113195988485333904u }, + { 13693571323849132942u, 141494985606667380u }, + { 17781854114260483896u, 88434366004167112u }, + { 3780573569116053255u, 110542957505208891u }, + { 114030942967678664u, 138178696881511114u }, + { 4682955357782187069u, 86361685550944446u }, + { 15077066234082509644u, 107952106938680557u }, + { 5011274737320973344u, 134940133673350697u }, + { 14661261756894078100u, 84337583545844185u }, + { 4491519140835433913u, 105421979432305232u }, + { 5614398926044292391u, 131777474290381540u }, + { 12732371365632458552u, 82360921431488462u }, + { 6692092170185797382u, 102951151789360578u }, + { 17588487249587022536u, 128688939736700722u }, + { 15604490549419276989u, 80430587335437951u }, + { 14893927168346708332u, 100538234169297439u }, + { 14005722942005997511u, 125672792711621799u }, + { 15671105866394830300u, 78545495444763624u }, + { 1142138259283986260u, 98181869305954531u }, + { 15262730879387146537u, 122727336632443163u }, + { 7233363790403272633u, 76704585395276977u }, + { 13653390756431478696u, 95880731744096221u }, + { 3231680390257184658u, 119850914680120277u }, + { 4325643253124434363u, 74906821675075173u }, + { 10018740084832930858u, 93633527093843966u }, + { 3300053069186387764u, 117041908867304958u }, + { 15897591223523656064u, 73151193042065598u }, + { 10648616992549794273u, 91438991302581998u }, + { 4087399203832467033u, 114298739128227498u }, + { 14332621041645359599u, 142873423910284372u }, + { 18181260187883125557u, 89295889943927732u }, + { 4279831161144355331u, 111619862429909666u }, + { 14573160988285219972u, 139524828037387082u }, + { 13719911636105650386u, 87203017523366926u }, + { 7926517508277287175u, 109003771904208658u }, + { 684774848491833161u, 136254714880260823u }, + { 7345513307948477581u, 85159196800163014u }, + { 18405263671790372785u, 106448996000203767u }, + { 18394893571310578077u, 133061245000254709u }, + { 13802651491282805250u, 83163278125159193u }, + { 3418256308821342851u, 103954097656448992u }, + { 4272820386026678563u, 129942622070561240u }, + { 2670512741266674102u, 81214138794100775u }, + { 17173198981865506339u, 101517673492625968u }, + { 3019754653622331308u, 126897091865782461u }, + { 4193189667727651020u, 79310682416114038u }, + { 14464859121514339583u, 99138353020142547u }, + { 13469387883465536574u, 123922941275178184u }, + { 8418367427165960359u, 77451838296986365u }, + { 15134645302384838353u, 96814797871232956u }, + { 471562554271496325u, 121018497339041196u }, + { 9518098633274461011u, 75636560836900747u }, + { 7285937273165688360u, 94545701046125934u }, + { 18330793628311886258u, 118182126307657417u }, + { 4539216990053847055u, 73863828942285886u }, + { 14897393274422084627u, 92329786177857357u }, + { 4786683537745442072u, 115412232722321697u }, + { 14520892257159371055u, 72132645451451060u }, + { 18151115321449213818u, 90165806814313825u }, + { 8853836096529353561u, 112707258517892282u }, + { 1843923083806916143u, 140884073147365353u }, + { 12681666973447792349u, 88052545717103345u }, + { 2017025661527576725u, 110065682146379182u }, + { 11744654113764246714u, 137582102682973977u }, + { 422879793461572340u, 85988814176858736u }, + { 528599741826965425u, 107486017721073420u }, + { 660749677283706782u, 134357522151341775u }, + { 7330497575943398595u, 83973451344588609u }, + { 13774807988356636147u, 104966814180735761u }, + { 3383451930163631472u, 131208517725919702u }, + { 15949715511634433382u, 82005323578699813u }, + { 6102086334260878016u, 102506654473374767u }, + { 3015921899398709616u, 128133318091718459u }, + { 18025852251620051174u, 80083323807324036u }, + { 4085571240815512351u, 100104154759155046u }, + { 14330336087874166247u, 125130193448943807u }, + { 15873989082562435760u, 78206370905589879u }, + { 15230800334775656796u, 97757963631987349u }, + { 5203442363187407284u, 122197454539984187u }, + { 946308467778435600u, 76373409087490117u }, + { 5794571603150432404u, 95466761359362646u }, + { 16466586540792816313u, 119333451699203307u }, + { 7985773578781816244u, 74583407312002067u }, + { 5370530955049882401u, 93229259140002584u }, + { 6713163693812353001u, 116536573925003230u }, + { 18030785363914884337u, 72835358703127018u }, + { 13315109668038829614u, 91044198378908773u }, + { 2808829029766373305u, 113805247973635967u }, + { 17346094342490130344u, 142256559967044958u }, + { 6229622945628943561u, 88910349979403099u }, + { 3175342663608791547u, 111137937474253874u }, + { 13192550366365765242u, 138922421842817342u }, + { 3633657960551215372u, 86826513651760839u }, + { 18377130505971182927u, 108533142064701048u }, + { 4524669058754427043u, 135666427580876311u }, + { 9745447189362598758u, 84791517238047694u }, + { 2958436949848472639u, 105989396547559618u }, + { 12921418224165366607u, 132486745684449522u }, + { 12687572408530742033u, 82804216052780951u }, + { 11247779492236039638u, 103505270065976189u }, + { 224666310012885835u, 129381587582470237u }, + { 2446259452971747599u, 80863492239043898u }, + { 12281196353069460307u, 101079365298804872u }, + { 15351495441336825384u, 126349206623506090u }, + { 14206370669262903769u, 78968254139691306u }, + { 8534591299723853903u, 98710317674614133u }, + { 15279925143082205283u, 123387897093267666u }, + { 14161639232853766206u, 77117435683292291u }, + { 13090363022639819853u, 96396794604115364u }, + { 16362953778299774816u, 120495993255144205u }, + { 12532689120651053212u, 75309995784465128u }, + { 15665861400813816515u, 94137494730581410u }, + { 10358954714162494836u, 117671868413226763u }, + { 4168503687137865320u, 73544917758266727u }, + { 598943590494943747u, 91931147197833409u }, + { 5360365506546067587u, 114913933997291761u }, + { 11312142901609972388u, 143642417496614701u }, + { 9375932322719926695u, 89776510935384188u }, + { 11719915403399908368u, 112220638669230235u }, + { 10038208235822497557u, 140275798336537794u }, + { 10885566165816448877u, 87672373960336121u }, + { 18218643725697949000u, 109590467450420151u }, + { 18161618638695048346u, 136988084313025189u }, + { 13656854658398099168u, 85617552695640743u }, + { 12459382304570236056u, 107021940869550929u }, + { 1739169825430631358u, 133777426086938662u }, + { 14922039196176308311u, 83610891304336663u }, + { 14040862976792997485u, 104513614130420829u }, + { 3716020665709083144u, 130642017663026037u }, + { 4628355925281870917u, 81651261039391273u }, + { 10397130925029726550u, 102064076299239091u }, + { 8384727637859770284u, 127580095374048864u }, + { 5240454773662356427u, 79737559608780540u }, + { 6550568467077945534u, 99671949510975675u }, + { 3576524565420044014u, 124589936888719594u }, + { 6847013871814915412u, 77868710555449746u }, + { 17782139376623420074u, 97335888194312182u }, + { 13004302183924499284u, 121669860242890228u }, + { 17351060901807587860u, 76043662651806392u }, + { 3242082053549933210u, 95054578314757991u }, + { 17887660622219580224u, 118818222893447488u }, + { 11179787888887237640u, 74261389308404680u }, + { 13974734861109047050u, 92826736635505850u }, + { 8245046539531533005u, 116033420794382313u }, + { 16682369133275677888u, 72520887996488945u }, + { 7017903361312433648u, 90651109995611182u }, + { 17995751238495317868u, 113313887494513977u }, + { 8659630992836983623u, 141642359368142472u }, + { 5412269370523114764u, 88526474605089045u }, + { 11377022731581281359u, 110658093256361306u }, + { 4997906377621825891u, 138322616570451633u }, + { 14652906532082110942u, 86451635356532270u }, + { 9092761128247862869u, 108064544195665338u }, + { 2142579373455052779u, 135080680244581673u }, + { 12868327154477877747u, 84425425152863545u }, + { 2250350887815183471u, 105531781441079432u }, + { 2812938609768979339u, 131914726801349290u }, + { 6369772649532999991u, 82446704250843306u }, + { 17185587848771025797u, 103058380313554132u }, + { 3035240737254230630u, 128822975391942666u }, + { 6508711479211282048u, 80514359619964166u }, + { 17359261385868878368u, 100642949524955207u }, + { 17087390713908710056u, 125803686906194009u }, + { 3762090168551861929u, 78627304316371256u }, + { 4702612710689827411u, 98284130395464070u }, + { 15101637925217060072u, 122855162994330087u }, + { 16356052730901744401u, 76784476871456304u }, + { 1998321839917628885u, 95980596089320381u }, + { 7109588318324424010u, 119975745111650476u }, + { 13666864735807540814u, 74984840694781547u }, + { 12471894901332038114u, 93731050868476934u }, + { 6366496589810271835u, 117163813585596168u }, + { 3979060368631419896u, 73227383490997605u }, + { 9585511479216662775u, 91534229363747006u }, + { 2758517312166052660u, 114417786704683758u }, + { 12671518677062341634u, 143022233380854697u }, + { 1002170145522881665u, 89388895863034186u }, + { 10476084718758377889u, 111736119828792732u }, + { 13095105898447972362u, 139670149785990915u }, + { 5878598177316288774u, 87293843616244322u }, + { 16571619758500136775u, 109117304520305402u }, + { 11491152661270395161u, 136396630650381753u }, + { 264441385652915120u, 85247894156488596u }, + { 330551732066143900u, 106559867695610745u }, + { 5024875683510067779u, 133199834619513431u }, + { 10058076329834874218u, 83249896637195894u }, + { 3349223375438816964u, 104062370796494868u }, + { 4186529219298521205u, 130077963495618585u }, + { 14145795808130045513u, 81298727184761615u }, + { 13070558741735168987u, 101623408980952019u }, + { 11726512408741573330u, 127029261226190024u }, + { 7329070255463483331u, 79393288266368765u }, + { 13773023837756742068u, 99241610332960956u }, + { 17216279797195927585u, 124052012916201195u }, + { 8454331864033760789u, 77532508072625747u }, + { 5956228811614813082u, 96915635090782184u }, + { 7445286014518516353u, 121144543863477730u }, + { 9264989777501460624u, 75715339914673581u }, + { 16192923240304213684u, 94644174893341976u }, + { 1794409976670715490u, 118305218616677471u }, + { 8039035263060279037u, 73940761635423419u }, + { 5437108060397960892u, 92425952044279274u }, + { 16019757112352226923u, 115532440055349092u }, + { 788976158365366019u, 72207775034593183u }, + { 14821278253238871236u, 90259718793241478u }, + { 9303225779693813237u, 112824648491551848u }, + { 11629032224617266546u, 141030810614439810u }, + { 11879831158813179495u, 88144256634024881u }, + { 1014730893234310657u, 110180320792531102u }, + { 10491785653397664129u, 137725400990663877u }, + { 8863209042587234033u, 86078375619164923u }, + { 6467325284806654637u, 107597969523956154u }, + { 17307528642863094104u, 134497461904945192u }, + { 10817205401789433815u, 84060913690590745u }, + { 18133192770664180173u, 105076142113238431u }, + { 18054804944902837312u, 131345177641548039u }, + { 18201782118205355176u, 82090736025967524u }, + { 4305483574047142354u, 102613420032459406u }, + { 14605226504413703751u, 128266775040574257u }, + { 2210737537617482988u, 80166734400358911u }, + { 16598479977304017447u, 100208418000448638u }, + { 11524727934775246001u, 125260522500560798u }, + { 2591268940807140847u, 78287826562850499u }, + { 17074144231291089770u, 97859783203563123u }, + { 16730994270686474309u, 122324729004453904u }, + { 10456871419179046443u, 76452955627783690u }, + { 3847717237119032246u, 95566194534729613u }, + { 9421332564826178211u, 119457743168412016u }, + { 5888332853016361382u, 74661089480257510u }, + { 16583788103125227536u, 93326361850321887u }, + { 16118049110479146516u, 116657952312902359u }, + { 16991309721690548428u, 72911220195563974u }, + { 12015765115258409727u, 91139025244454968u }, + { 15019706394073012159u, 113923781555568710u }, + { 9551260955736489391u, 142404726944460888u }, + { 5969538097335305869u, 89002954340288055u }, + { 2850236603241744433u, 111253692925360069u }, + }; + +#define TAO_RYU_DOUBLE_MANTISSA_BITS 52 +#define TAO_RYU_DOUBLE_EXPONENT_BITS 11 + +#define TAO_RYU_DOUBLE_POW5_INV_BITCOUNT 122 +#define TAO_RYU_DOUBLE_POW5_BITCOUNT 121 + + inline std::int32_t pow5Factor( std::uint64_t value ) + { + for( std::int32_t count = 0; value > 0; ++count ) { + if( value % 5 != 0 ) { + return count; + } + value /= 5; + } + return 0; + } + + // Returns true if value is divisible by 5^p. + inline bool multipleOfPowerOf5( const std::uint64_t value, const std::int32_t p ) + { + // I tried a case distinction on p, but there was no performance difference. + return pow5Factor( value ) >= p; + } + + // We need a 64x128-bit multiplication and a subsequent 128-bit shift. + // Multiplication: + // The 64-bit factor is variable and passed in, the 128-bit factor comes + // from a lookup table. We know that the 64-bit factor only has 55 + // significant bits (i.e., the 9 topmost bits are zeros). The 128-bit + // factor only has 124 significant bits (i.e., the 4 topmost bits are + // zeros). + // Shift: + // In principle, the multiplication result requires 55+124=179 bits to + // represent. However, we then shift this value to the right by j, which is + // at least j >= 115, so the result is guaranteed to fit into 179-115=64 + // bits. This means that we only need the topmost 64 significant bits of + // the 64x128-bit multiplication. + // + // There are several ways to do this: + // 1. Best case: the compiler exposes a 128-bit type. + // We perform two 64x64-bit multiplications, add the higher 64 bits of the + // lower result to the higher result, and shift by j-64 bits. + // + // We explicitly cast from 64-bit to 128-bit, so the compiler can tell + // that these are only 64-bit inputs, and can map these to the best + // possible sequence of assembly instructions. + // x86-64 machines happen to have matching assembly instructions for + // 64x64-bit multiplications and 128-bit shifts. + // + // 2. Second best case: the compiler exposes intrinsics for the x86-64 assembly + // instructions mentioned in 1. + // + // 3. We only have 64x64 bit instructions that return the lower 64 bits of + // the result, i.e., we have to use plain C. + // Our inputs are less than the full width, so we have three options: + // a. Ignore this fact and just implement the intrinsics manually. + // b. Split both into 31-bit pieces, which guarantees no internal overflow, + // but requires extra work upfront (unless we change the lookup table). + // c. Split only the first factor into 31-bit pieces, which also guarantees + // no internal overflow, but requires extra work since the intermediate + // results are not perfectly aligned. +#if defined( HAS_UINT128 ) + + // Best case: use 128-bit type. + inline std::uint64_t mulShift( const std::uint64_t m, const std::uint64_t* const mul, const std::int32_t j ) + { + const uint128_t b0 = ( (uint128_t)m ) * mul[ 0 ]; + const uint128_t b2 = ( (uint128_t)m ) * mul[ 1 ]; + return ( std::uint64_t )( ( ( b0 >> 64 ) + b2 ) >> ( j - 64 ) ); + } + + inline std::uint64_t mulShiftAll( const std::uint64_t m, const std::uint64_t* const mul, const std::int32_t j, std::uint64_t* const vp, std::uint64_t* const vm, const std::uint32_t mmShift ) + { + // m <<= 2; + // uint128_t b0 = ((uint128_t) m) * mul[0]; // 0 + // uint128_t b2 = ((uint128_t) m) * mul[1]; // 64 + // + // uint128_t hi = (b0 >> 64) + b2; + // uint128_t lo = b0 & 0xffffffffffffffffull; + // uint128_t factor = (((uint128_t) mul[1]) << 64) + mul[0]; + // uint128_t vpLo = lo + (factor << 1); + // *vp = (uint64_t) ((hi + (vpLo >> 64)) >> (j - 64)); + // uint128_t vmLo = lo - (factor << mmShift); + // *vm = (uint64_t) ((hi + (vmLo >> 64) - (((uint128_t) 1ull) << 64)) >> (j - 64)); + // return (uint64_t) (hi >> (j - 64)); + *vp = mulShift( 4 * m + 2, mul, j ); + *vm = mulShift( 4 * m - 1 - mmShift, mul, j ); + return mulShift( 4 * m, mul, j ); + } + +#elif defined( HAS_64_BIT_INTRINSICS ) + + inline std::uint64_t mulShift( const std::uint64_t m, const std::uint64_t* const mul, const std::int32_t j ) + { + // m is maximum 55 bits + std::uint64_t high1; // 128 + const std::uint64_t low1 = umul128( m, mul[ 1 ], high1 ); // 64 + std::uint64_t high0; // 64 + umul128( m, mul[ 0 ], high0 ); // 0 + const std::uint64_t sum = high0 + low1; + if( sum < high0 ) { + ++high1; // overflow into high1 + } + return shiftright128( sum, high1, j - 64 ); + } + + inline std::uint64_t mulShiftAll( const std::uint64_t m, const std::uint64_t* const mul, const std::int32_t j, std::uint64_t* const vp, std::uint64_t* const vm, const std::uint32_t mmShift ) + { + *vp = mulShift( 4 * m + 2, mul, j ); + *vm = mulShift( 4 * m - 1 - mmShift, mul, j ); + return mulShift( 4 * m, mul, j ); + } + +#else // !defined( HAS_UINT128 ) && !defined( HAS_64_BIT_INTRINSICS ) + + static inline std::uint64_t mulShiftAll( std::uint64_t m, const std::uint64_t* const mul, const std::int32_t j, std::uint64_t* const vp, std::uint64_t* const vm, const std::uint32_t mmShift ) + { + m <<= 1; + // m is maximum 55 bits + std::uint64_t tmp; + const std::uint64_t lo = umul128( m, mul[ 0 ], tmp ); + std::uint64_t hi; + const std::uint64_t mid = tmp + umul128( m, mul[ 1 ], hi ); + hi += mid < tmp; // overflow into hi + + const std::uint64_t lo2 = lo + mul[ 0 ]; + const std::uint64_t mid2 = mid + mul[ 1 ] + ( lo2 < lo ); + const std::uint64_t hi2 = hi + ( mid2 < mid ); + *vp = shiftright128( mid2, hi2, j - 64 - 1 ); + + if( mmShift == 1 ) { + const std::uint64_t lo3 = lo - mul[ 0 ]; + const std::uint64_t mid3 = mid - mul[ 1 ] - ( lo3 > lo ); + const std::uint64_t hi3 = hi - ( mid3 > mid ); + *vm = shiftright128( mid3, hi3, j - 64 - 1 ); + } + else { + const std::uint64_t lo3 = lo + lo; + const std::uint64_t mid3 = mid + mid + ( lo3 < lo ); + const std::uint64_t hi3 = hi + hi + ( mid3 < mid ); + const std::uint64_t lo4 = lo3 - mul[ 0 ]; + const std::uint64_t mid4 = mid3 - mul[ 1 ] - ( lo4 > lo3 ); + const std::uint64_t hi4 = hi3 - ( mid4 > mid3 ); + *vm = shiftright128( mid4, hi4, j - 64 ); + } + return shiftright128( mid, hi, j - 64 - 1 ); + } + +#endif + + inline std::uint32_t decimalLength( const std::uint64_t v ) + { + // This is slightly faster than a loop. + // The average output length is 16.38 digits, so we check high-to-low. + // Function precondition: v is not an 18, 19, or 20-digit number. + // (17 digits are sufficient for round-tripping.) + assert( v < 100000000000000000L ); + if( v >= 10000000000000000L ) { + return 17; + } + if( v >= 1000000000000000L ) { + return 16; + } + if( v >= 100000000000000L ) { + return 15; + } + if( v >= 10000000000000L ) { + return 14; + } + if( v >= 1000000000000L ) { + return 13; + } + if( v >= 100000000000L ) { + return 12; + } + if( v >= 10000000000L ) { + return 11; + } + if( v >= 1000000000L ) { + return 10; + } + if( v >= 100000000L ) { + return 9; + } + if( v >= 10000000L ) { + return 8; + } + if( v >= 1000000L ) { + return 7; + } + if( v >= 100000L ) { + return 6; + } + if( v >= 10000L ) { + return 5; + } + if( v >= 1000L ) { + return 4; + } + if( v >= 100L ) { + return 3; + } + if( v >= 10L ) { + return 2; + } + return 1; + } + + inline std::uint32_t d2s_simplistic_step5( std::uint64_t output, std::int32_t exp, const std::int32_t olength, char* result ) + { + // TODO: Use digit_table? + + if( exp <= 0 ) { + std::memcpy( result, "0.", 2 ); + std::memset( result + 2, '0', -exp ); + const auto* end = itoa::u64toa( output, result + 2 - exp ); + return static_cast< std::uint32_t >( end - result ); + } + else if( exp >= olength ) { + itoa::u64toa( output, result ); // Return value MUST be result + olength + std::memset( result + olength, '0', exp + 2 - olength ); + result[ exp ] = '.'; + return exp + 2; + } + else { // ( exp > 0 ) && ( exp < olength ) + for( std::int32_t i = 0; i < olength - exp; ++i ) { + const std::uint32_t c = output % 10; + output /= 10; + result[ olength - i ] = char( '0' + c ); + } + result[ exp ] = '.'; + for( std::int32_t i = 0; i < exp; ++i ) { + const std::uint32_t c = output % 10; + output /= 10; + result[ exp - i - 1 ] = char( '0' + c ); + } + return olength + 1; + } + } + + inline std::uint32_t d2s_scientific_step5( std::uint64_t output, std::int32_t exp, const std::uint32_t olength, char* result ) + { + int index = olength; + + if( olength > 1 ) { + itoa::u64toa( output, result + 1 ); + result[ 0 ] = result[ 1 ]; + result[ 1 ] = '.'; + ++index; + } + else { + result[ 0 ] = char( '0' + output ); + } + if( exp ) { + result[ index++ ] = 'e'; + const auto end = itoa::i32toa( exp, result + index ); + return static_cast< std::uint32_t >( end - result ); + } + return index; + } + + inline std::uint32_t d2s_finite( const double f, char* result ) + { + // Step 1: Decode the floating-point number, and unify normalized and subnormal cases. + const std::uint32_t mantissaBits = TAO_RYU_DOUBLE_MANTISSA_BITS; + const std::uint32_t exponentBits = TAO_RYU_DOUBLE_EXPONENT_BITS; + const std::uint32_t offset = ( 1u << ( exponentBits - 1 ) ) - 1; + + std::uint64_t bits; + // This only works on little-endian architectures. + std::memcpy( &bits, &f, sizeof( double ) ); // TODO: Fix for big-endian! + + // Decode bits into sign, mantissa, and exponent. + const bool sign = ( ( bits >> ( mantissaBits + exponentBits ) ) & 1 ) != 0; + const std::uint64_t ieeeMantissa = bits & ( ( 1ull << mantissaBits ) - 1 ); + const std::uint32_t ieeeExponent = std::uint32_t( ( bits >> mantissaBits ) & ( ( 1u << exponentBits ) - 1 ) ); + + std::int32_t e2; + std::uint64_t m2; + + // NOTE: For taocpp/json this function assumes that f is finite! + // if (ieeeExponent == ((1u << exponentBits) - 1u)) { + // std::strcpy( result, (ieeeMantissa != 0) ? "NaN" : ( sign ? "-Infinity" : "Infinity" ) ); + // return std::strlen( result ); + // } else if (ieeeExponent == 0) { + // Case distinction; exit early for the easy cases. + if( ieeeExponent == 0 ) { + if( ieeeMantissa == 0 ) { + const std::uint32_t size = sign ? 4 : 3; + std::memcpy( result, &( "-0.0"[ 4 - size ] ), size ); + return size; + } + // We subtract 2 so that the bounds computation has 2 additional bits. + e2 = 1 - offset - mantissaBits - 2; + m2 = ieeeMantissa; + } + else { + e2 = ieeeExponent - offset - mantissaBits - 2; + m2 = ( 1ull << mantissaBits ) | ieeeMantissa; + } + const bool acceptBounds = ( m2 & 1 ) == 0; + + // Step 2: Determine the interval of legal decimal representations. + const std::uint64_t mv = 4 * m2; + // Implicit bool -> int conversion. True is 1, false is 0. + const std::uint32_t mmShift = ( m2 != ( 1ull << mantissaBits ) ) || ( ieeeExponent <= 1 ); + // We would compute mp and mm like this: + // std::uint64_t mp = 4 * m2 + 2; + // std::uint64_t mm = mv - 1 - mmShift; + + // Step 3: Convert to a decimal power base using 128-bit arithmetic. + std::uint64_t vr, vp, vm; + std::int32_t e10; + + bool vmIsTrailingZeros = false; + bool vrIsTrailingZeros = false; + + if( e2 >= 0 ) { + // I tried special-casing q == 0, but there was no effect on performance. + // This expression is slightly faster than max(0, log10Pow2(e2) - 1). + const std::int32_t q = log10Pow2( e2 ) - ( e2 > 3 ); + e10 = q; + const std::int32_t k = TAO_RYU_DOUBLE_POW5_INV_BITCOUNT + pow5bits( q ) - 1; + const std::int32_t i = -e2 + q + k; + vr = mulShiftAll( m2, pow5_inv_split[ q ], i, &vp, &vm, mmShift ); + if( q <= 21 ) { + // Only one of mp, mv, and mm can be a multiple of 5, if any. + if( mv % 5 == 0 ) { + vrIsTrailingZeros = multipleOfPowerOf5( mv, q ); + } + else { + if( acceptBounds ) { + // Same as min(e2 + (~mm & 1), pow5Factor(mm)) >= q + // <=> e2 + (~mm & 1) >= q && pow5Factor(mm) >= q + // <=> true && pow5Factor(mm) >= q, since e2 >= q. + vmIsTrailingZeros = multipleOfPowerOf5( mv - 1 - mmShift, q ); + } + else { + // Same as min(e2 + 1, pow5Factor(mp)) >= q. + vp -= multipleOfPowerOf5( mv + 2, q ); + } + } + } + } + else { + // This expression is slightly faster than max(0, log10Pow5(-e2) - 1). + const std::int32_t q = log10Pow5( -e2 ) - ( -e2 > 1 ); + e10 = q + e2; + const std::int32_t i = -e2 - q; + const std::int32_t k = pow5bits( i ) - TAO_RYU_DOUBLE_POW5_BITCOUNT; + const std::int32_t j = q - k; + vr = mulShiftAll( m2, pow5_split[ i ], j, &vp, &vm, mmShift ); + if( q <= 1 ) { + vrIsTrailingZeros = ( ~( std::uint32_t( mv ) ) & 1 ) >= std::uint32_t( q ); + if( acceptBounds ) { + vmIsTrailingZeros = ( ~( std::uint32_t( mv - 1 - mmShift ) ) & 1 ) >= std::uint32_t( q ); + } + else { + --vp; + } + } + else if( q < 63 ) { // TODO(ulfjack): Use a tighter bound here. + // We need to compute min(ntz(mv), pow5Factor(mv) - e2) >= q-1 + // <=> ntz(mv) >= q-1 && pow5Factor(mv) - e2 >= q-1 + // <=> ntz(mv) >= q-1 + // <=> (mv & ((1 << (q-1)) - 1)) == 0 + // We also need to make sure that the left shift does not overflow. + vrIsTrailingZeros = ( mv & ( ( 1ull << ( q - 1 ) ) - 1 ) ) == 0; + } + } + // Step 4: Find the shortest decimal representation in the interval of legal representations. + std::uint32_t removed = 0; + uint8_t lastRemovedDigit = 0; + std::uint64_t output; + // On average, we remove ~2 digits. + if( vmIsTrailingZeros || vrIsTrailingZeros ) { + // General case, which happens rarely (<1%). + while( vp / 10 > vm / 10 ) { +#ifdef __clang__ + // https://bugs.llvm.org/show_bug.cgi?id=23106 + // The compiler does not realize that vm % 10 can be computed from vm / 10 + // as vm - (vm / 10) * 10. + vmIsTrailingZeros &= vm - ( vm / 10 ) * 10 == 0; +#else + vmIsTrailingZeros &= vm % 10 == 0; +#endif + vrIsTrailingZeros &= lastRemovedDigit == 0; + lastRemovedDigit = std::uint8_t( vr % 10 ); + vr /= 10; + vp /= 10; + vm /= 10; + ++removed; + } + if( vmIsTrailingZeros ) { + while( vm % 10 == 0 ) { + vrIsTrailingZeros &= lastRemovedDigit == 0; + lastRemovedDigit = std::uint8_t( vr % 10 ); + vr /= 10; + vp /= 10; + vm /= 10; + ++removed; + } + } + if( vrIsTrailingZeros && ( lastRemovedDigit == 5 ) && ( vr % 2 == 0 ) ) { + // Round down not up if the number ends in X50000. + lastRemovedDigit = 4; + } + // We need to take vr+1 if vr is outside bounds or we need to round up. + output = vr + ( ( vr == vm && ( !acceptBounds || !vmIsTrailingZeros ) ) || ( lastRemovedDigit >= 5 ) ); + } + else { + // Specialized for the common case (>99%). + while( vp / 10 > vm / 10 ) { + lastRemovedDigit = std::uint8_t( vr % 10 ); + vr /= 10; + vp /= 10; + vm /= 10; + ++removed; + } + // We need to take vr+1 if vr is outside bounds or we need to round up. + output = vr + ( ( vr == vm ) || ( lastRemovedDigit >= 5 ) ); + } + // Step 5: Print the decimal representation. + + if( sign ) { + *result++ = '-'; + } + // The average output length is 16.38 digits. + const std::uint32_t olength = decimalLength( output ); + const std::int32_t exp = e10 + olength + removed; + + if( ( -6 < exp ) && ( exp < 22 ) ) { + return d2s_simplistic_step5( output, exp, olength, result ) + std::uint32_t( sign ); + } + else { + return d2s_scientific_step5( output, exp - 1, olength, result ) + std::uint32_t( sign ); + } + } + + inline void d2s_stream( std::ostream& o, const double f ) + { + char b[ 28 ]; + const auto s = d2s_finite( f, b ); + o.write( b, s ); + } + +} // namespace tao::json::ryu + +#endif diff --git a/include/tao/json/external/string_view.hpp b/include/tao/json/external/string_view.hpp deleted file mode 100644 index 13ac077a..00000000 --- a/include/tao/json/external/string_view.hpp +++ /dev/null @@ -1,565 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_INCLUDE_STRING_VIEW_HPP -#define TAOCPP_INCLUDE_STRING_VIEW_HPP - -#ifndef TAOCPP_USE_STD_STRING_VIEW -#if __cplusplus >= 201703L -#define TAOCPP_USE_STD_STRING_VIEW -#endif -#endif - -#ifndef TAOCPP_USE_STD_STRING_VIEW -#ifndef TAOCPP_USE_TS_STRING_VIEW -#if( __cplusplus >= 201402L ) && ( ( __GNUC__ > 4 ) || ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 9 ) ) -#define TAOCPP_USE_TS_STRING_VIEW -#endif -#endif -#endif - -#if defined( TAOCPP_USE_STD_STRING_VIEW ) -#include -#elif defined( TAOCPP_USE_TS_STRING_VIEW ) -#include -#else -#include "../internal/identity.hpp" -#include -#include -#include -#include -#include -#endif - -namespace tao -{ - -#if defined( TAOCPP_USE_STD_STRING_VIEW ) - using std::basic_string_view; -#elif defined( TAOCPP_USE_TS_STRING_VIEW ) - using std::experimental::basic_string_view; -#else - - // this is C++17's std::string_view - // * based on N4659, except: - // * additional ctor for basic_string to compensate for missing basic_string::operator basic_string_view - // * additional noexcept specifiers have been added in a few places - // * dropped some constexpr specifiers which are not possible in C++11 - // * user-defined literals have suffix '_sv' instead of 'sv' - // * inefficient implementation of operator<< - // * no std::hash-specializations - // * implementations of find-methods is based on N3921 - template< class charT, class traits = std::char_traits< charT > > - class basic_string_view - { - public: - // types - using traits_type = traits; - using value_type = charT; - using pointer = value_type*; - using const_pointer = const value_type*; - using reference = value_type&; - using const_reference = const value_type&; - using const_iterator = const value_type*; - using iterator = const_iterator; - using const_reverse_iterator = std::reverse_iterator< const_iterator >; - using reverse_iterator = const_reverse_iterator; - using size_type = size_t; - using difference_type = ptrdiff_t; - - static constexpr size_type npos = size_type( -1 ); - - // 24.4.2.1, construction and assignment - constexpr basic_string_view() noexcept - : data_( nullptr ), size_( 0 ) - { - } - - constexpr basic_string_view( const charT* str ) // TODO: noexcept? - : data_( str ), size_( traits::length( str ) ) - { - } - - constexpr basic_string_view( const charT* str, size_type len ) noexcept - : data_( str ), size_( len ) - { - } - - // this is a work-around for missing operator basic_string_view in std::string - constexpr basic_string_view( const std::basic_string< charT, traits >& str ) noexcept - : data_( str.data() ), size_( str.size() ) - { - } - - constexpr basic_string_view( const basic_string_view& ) noexcept = default; - /*constexpr*/ basic_string_view& operator=( const basic_string_view& ) noexcept = default; - - // 24.4.2.2, iterator support - constexpr const_iterator begin() const noexcept - { - return data_; - } - - constexpr const_iterator end() const noexcept - { - return begin() + size(); - } - - constexpr const_iterator cbegin() const noexcept - { - return begin(); - } - - constexpr const_iterator cend() const noexcept - { - return begin() + size(); - } - - constexpr const_reverse_iterator rbegin() const noexcept - { - return const_reverse_iterator( end() ); - } - - constexpr const_reverse_iterator rend() const noexcept - { - return const_reverse_iterator( begin() ); - } - - constexpr const_reverse_iterator crbegin() const noexcept - { - return const_reverse_iterator( end() ); - } - - constexpr const_reverse_iterator crend() const noexcept - { - return const_reverse_iterator( begin() ); - } - - // 24.4.2.3, capacity - constexpr size_type size() const noexcept - { - return size_; - } - - constexpr size_type length() const noexcept - { - return size_; - } - - constexpr size_type max_size() const noexcept - { - return npos - 1; - } - - constexpr bool empty() const noexcept - { - return size_ == 0; - } - - // 24.4.2.4, element access - constexpr const_reference operator[]( size_type pos ) const noexcept - { - return data_[ pos ]; - } - - constexpr const_reference at( size_type pos ) const - { - return ( pos >= size() ) ? throw std::out_of_range( "index out of range in tao::basic_string_view::at" ) : data_[ pos ]; - } - - constexpr const_reference front() const noexcept - { - return data_[ 0 ]; - } - - constexpr const_reference back() const noexcept - { - return data_[ size() - 1 ]; - } - - constexpr const_pointer data() const noexcept - { - return data_; - } - - // 24.4.2.5, modifiers - /*constexpr*/ void remove_prefix( size_type n ) noexcept - { - data_ += n; - size_ -= n; - } - - /*constexpr*/ void remove_suffix( size_type n ) noexcept - { - size_ -= n; - } - - /*constexpr*/ void swap( basic_string_view& s ) noexcept - { - std::swap( data_, s.data_ ); - std::swap( size_, s.size_ ); - } - - // 24.4.2.6, string operations - size_type copy( charT* s, size_type n, size_type pos = 0 ) const - { - if( pos > size() ) { - throw std::out_of_range( "index out of range in tao::basic_string_view::copy" ); - } - const size_type rlen = std::min( n, size() - pos ); - traits::copy( s, data() + pos, rlen ); - return rlen; - } - - constexpr basic_string_view substr( size_type pos = 0, size_type n = npos ) const - { - return ( pos > size() ) ? throw std::out_of_range( "index out of range in tao::basic_string_view::substr" ) : basic_string_view( data() + pos, std::min( n, size() - pos ) ); - } - - /*constexpr*/ int compare( basic_string_view s ) const noexcept - { - const size_type rlen = std::min( size(), s.size() ); - const int result = traits::compare( data(), s.data(), rlen ); - if( result == 0 && size() != s.size() ) { - return ( size() < s.size() ) ? -1 : 1; - } - return result; - } - - constexpr int compare( size_type pos1, size_type n1, basic_string_view s ) const - { - return substr( pos1, n1 ).compare( s ); - } - - constexpr int compare( size_type pos1, size_type n1, basic_string_view s, size_type pos2, size_type n2 ) const - { - return substr( pos1, n1 ).compare( s.substr( pos2, n2 ) ); - } - - constexpr int compare( const charT* s ) const - { - return compare( basic_string_view( s ) ); - } - - constexpr int compare( size_type pos1, size_type n1, const charT* s ) const - { - return substr( pos1, n1 ).compare( basic_string_view( s ) ); - } - - constexpr int compare( size_type pos1, size_type n1, const charT* s, size_type n2 ) const - { - return substr( pos1, n1 ).compare( basic_string_view( s, n2 ) ); - } - - /*constexpr*/ size_type find( basic_string_view s, size_type pos = 0 ) const noexcept - { - if( pos > size() - s.size() ) { - return npos; - } - const auto iter = std::search( begin() + pos, end(), s.begin(), s.end() ); - return iter == end() ? npos : iter - begin(); - } - - constexpr size_type find( charT c, size_type pos = 0 ) const noexcept - { - return find( basic_string_view( &c, 1 ), pos ); - } - - constexpr size_type find( const charT* s, size_type pos, size_type n ) const noexcept - { - return find( basic_string_view( s, n ), pos ); - } - - constexpr size_type find( const charT* s, size_type pos = 0 ) const - { - return find( basic_string_view( s ), pos ); - } - - /*constexpr*/ size_type rfind( basic_string_view s, size_type pos = npos ) const noexcept - { - if( pos > size() - s.size() ) { - return npos; - } - const auto iter = std::find_end( begin() + pos, end(), s.begin(), s.end() ); - return iter == end() ? npos : iter - begin(); - } - - constexpr size_type rfind( charT c, size_type pos = npos ) const noexcept - { - return rfind( basic_string_view( &c, 1 ), pos ); - } - - constexpr size_type rfind( const charT* s, size_type pos, size_type n ) const noexcept - { - return rfind( basic_string_view( s, n ), pos ); - } - - constexpr size_type rfind( const charT* s, size_type pos = npos ) const - { - return rfind( basic_string_view( s ), pos ); - } - - /*constexpr*/ size_type find_first_of( basic_string_view s, size_type pos = 0 ) const noexcept - { - if( pos > size() - 1 ) { - return npos; - } - const auto iter = std::find_first_of( begin() + pos, end(), s.begin(), s.end() ); - return iter == end() ? npos : iter - begin(); - } - - constexpr size_type find_first_of( charT c, size_type pos = 0 ) const noexcept - { - return find_first_of( basic_string_view( &c, 1 ), pos ); - } - - constexpr size_type find_first_of( const charT* s, size_type pos, size_type n ) const noexcept - { - return find_first_of( basic_string_view( s, n ), pos ); - } - - constexpr size_type find_first_of( const charT* s, size_type pos = 0 ) const - { - return find_first_of( basic_string_view( s ), pos ); - } - - /*constexpr*/ size_type find_last_of( basic_string_view s, size_type pos = npos ) const noexcept - { - if( pos > size() - 1 ) { - return npos; - } - const auto iter = std::find_first_of( rbegin() + pos, rend(), s.begin(), s.end() ); - return iter == rend() ? npos : iter.base() - 1 - begin(); - } - - constexpr size_type find_last_of( charT c, size_type pos = npos ) const noexcept - { - return find_last_of( basic_string_view( &c, 1 ), pos ); - } - - constexpr size_type find_last_of( const charT* s, size_type pos, size_type n ) const noexcept - { - return find_last_of( basic_string_view( s, n ), pos ); - } - - constexpr size_type find_last_of( const charT* s, size_type pos = npos ) const - { - return find_last_of( basic_string_view( s ), pos ); - } - - /*constexpr*/ size_type find_first_not_of( basic_string_view s, size_type pos = 0 ) const noexcept - { - if( pos > size() - 1 ) { - return npos; - } - const auto iter = std::find_if( begin() + pos, end(), [&]( char c ) { - return std::find( s.begin(), s.end(), c ) == s.end(); - } ); - return iter == end() ? npos : iter - begin(); - } - - constexpr size_type find_first_not_of( charT c, size_type pos = 0 ) const noexcept - { - return find_first_not_of( basic_string_view( &c, 1 ), pos ); - } - - constexpr size_type find_first_not_of( const charT* s, size_type pos, size_type n ) const noexcept - { - return find_first_not_of( basic_string_view( s, n ), pos ); - } - - constexpr size_type find_first_not_of( const charT* s, size_type pos = 0 ) const - { - return find_first_not_of( basic_string_view( s ), pos ); - } - - /*constexpr*/ size_type find_last_not_of( basic_string_view s, size_type pos = npos ) const noexcept - { - if( pos > size() - 1 ) { - return npos; - } - const auto iter = std::find_if( rbegin() + pos, rend(), [&]( char c ) { - return std::find( s.begin(), s.end(), c ) == s.end(); - } ); - return iter == rend() ? npos : iter.base() - 1 - begin(); - } - - constexpr size_type find_last_not_of( charT c, size_type pos = npos ) const noexcept - { - return find_last_not_of( basic_string_view( &c, 1 ), pos ); - } - - constexpr size_type find_last_not_of( const charT* s, size_type pos, size_type n ) const noexcept - { - return find_first_not_of( basic_string_view( s, n ), pos ); - } - - constexpr size_type find_last_not_of( const charT* s, size_type pos = npos ) const - { - return find_last_not_of( basic_string_view( s ), pos ); - } - - private: - const_pointer data_; - size_type size_; - }; - - // 24.4.3, non-member comparison functions - template< class charT, class traits > - constexpr bool operator==( basic_string_view< charT, traits > x, basic_string_view< charT, traits > y ) noexcept - { - return x.compare( y ) == 0; - } - - template< class charT, class traits > - constexpr bool operator==( basic_string_view< charT, traits > x, internal::identity< basic_string_view< charT, traits > > y ) noexcept - { - return x.compare( y ) == 0; - } - - template< class charT, class traits > - constexpr bool operator==( internal::identity< basic_string_view< charT, traits > > x, basic_string_view< charT, traits > y ) noexcept - { - return x.compare( y ) == 0; - } - - template< class charT, class traits > - constexpr bool operator!=( basic_string_view< charT, traits > x, basic_string_view< charT, traits > y ) noexcept - { - return x.compare( y ) != 0; - } - - template< class charT, class traits > - constexpr bool operator!=( basic_string_view< charT, traits > x, internal::identity< basic_string_view< charT, traits > > y ) noexcept - { - return x.compare( y ) != 0; - } - - template< class charT, class traits > - constexpr bool operator!=( internal::identity< basic_string_view< charT, traits > > x, basic_string_view< charT, traits > y ) noexcept - { - return x.compare( y ) != 0; - } - - template< class charT, class traits > - constexpr bool operator<( basic_string_view< charT, traits > x, basic_string_view< charT, traits > y ) noexcept - { - return x.compare( y ) < 0; - } - - template< class charT, class traits > - constexpr bool operator<( basic_string_view< charT, traits > x, internal::identity< basic_string_view< charT, traits > > y ) noexcept - { - return x.compare( y ) < 0; - } - - template< class charT, class traits > - constexpr bool operator<( internal::identity< basic_string_view< charT, traits > > x, basic_string_view< charT, traits > y ) noexcept - { - return x.compare( y ) < 0; - } - - template< class charT, class traits > - constexpr bool operator>( basic_string_view< charT, traits > x, basic_string_view< charT, traits > y ) noexcept - { - return x.compare( y ) > 0; - } - - template< class charT, class traits > - constexpr bool operator>( basic_string_view< charT, traits > x, internal::identity< basic_string_view< charT, traits > > y ) noexcept - { - return x.compare( y ) > 0; - } - - template< class charT, class traits > - constexpr bool operator>( internal::identity< basic_string_view< charT, traits > > x, basic_string_view< charT, traits > y ) noexcept - { - return x.compare( y ) > 0; - } - - template< class charT, class traits > - constexpr bool operator<=( basic_string_view< charT, traits > x, basic_string_view< charT, traits > y ) noexcept - { - return x.compare( y ) <= 0; - } - - template< class charT, class traits > - constexpr bool operator<=( basic_string_view< charT, traits > x, internal::identity< basic_string_view< charT, traits > > y ) noexcept - { - return x.compare( y ) <= 0; - } - - template< class charT, class traits > - constexpr bool operator<=( internal::identity< basic_string_view< charT, traits > > x, basic_string_view< charT, traits > y ) noexcept - { - return x.compare( y ) <= 0; - } - - template< class charT, class traits > - constexpr bool operator>=( basic_string_view< charT, traits > x, basic_string_view< charT, traits > y ) noexcept - { - return x.compare( y ) >= 0; - } - - template< class charT, class traits > - constexpr bool operator>=( basic_string_view< charT, traits > x, internal::identity< basic_string_view< charT, traits > > y ) noexcept - { - return x.compare( y ) >= 0; - } - - template< class charT, class traits > - constexpr bool operator>=( internal::identity< basic_string_view< charT, traits > > x, basic_string_view< charT, traits > y ) noexcept - { - return x.compare( y ) >= 0; - } - - // 24.4.4, inserters and extractors - template< class charT, class traits > - std::basic_ostream< charT, traits >& operator<<( std::basic_ostream< charT, traits >& os, basic_string_view< charT, traits > str ) - { - // TODO: This is easy, but also inefficient. - return os << std::string( str.begin(), str.end() ); - } - -// TODO: 24.4.5, hash support - -#endif - - using string_view = basic_string_view< char >; - using u16string_view = basic_string_view< char16_t >; - using u32string_view = basic_string_view< char32_t >; - using wstring_view = basic_string_view< wchar_t >; - - inline namespace literals - { - inline namespace string_view_literals - { - // 24.4.6, suffix for basic_string_view literals - // NOTE: We are not the real STL, we use '_sv' instead of 'sv' as the suffix - constexpr string_view operator"" _sv( const char* str, size_t len ) noexcept - { - return string_view( str, len ); - } - - constexpr u16string_view operator"" _sv( const char16_t* str, size_t len ) noexcept - { - return u16string_view( str, len ); - } - - constexpr u32string_view operator"" _sv( const char32_t* str, size_t len ) noexcept - { - return u32string_view( str, len ); - } - - constexpr wstring_view operator"" _sv( const wchar_t* str, size_t len ) noexcept - { - return wstring_view( str, len ); - } - - } // namespace string_view_literals - - } // namespace literals - -} // namespace tao - -#endif diff --git a/include/tao/json/forward.hpp b/include/tao/json/forward.hpp new file mode 100644 index 00000000..1b0478f8 --- /dev/null +++ b/include/tao/json/forward.hpp @@ -0,0 +1,44 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_FORWARD_HPP +#define TAO_JSON_FORWARD_HPP + +namespace tao::json +{ + namespace events + { + class virtual_base; + + } // namespace events + + template< typename T, typename = void > + struct traits + {}; + + template< template< typename... > class Traits > + class basic_value; + + using value = basic_value< traits >; + + using producer_t = void ( * )( events::virtual_base&, const void* ); + + namespace internal + { + struct opaque_ptr_t + { + const void* data; + producer_t producer; + }; + + template< template< typename... > class Traits > + struct single; + + template< template< typename... > class Traits > + struct pair; + + } // namespace internal + +} // namespace tao::json + +#endif diff --git a/include/tao/json/from_file.hpp b/include/tao/json/from_file.hpp new file mode 100644 index 00000000..3f3c15ca --- /dev/null +++ b/include/tao/json/from_file.hpp @@ -0,0 +1,32 @@ +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_FROM_FILE_HPP +#define TAO_JSON_FROM_FILE_HPP + +#include +#include + +#include "events/from_file.hpp" +#include "events/to_value.hpp" +#include "events/transformer.hpp" + +namespace tao::json +{ + template< template< typename... > class Traits, template< typename... > class... Transformers > + [[nodiscard]] basic_value< Traits > basic_from_file( const std::string& filename ) + { + events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; + events::from_file( consumer, filename ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers > + [[nodiscard]] value from_file( const std::string& filename ) + { + return basic_from_file< traits, Transformers... >( filename ); + } + +} // namespace tao::json + +#endif diff --git a/include/tao/json/from_input.hpp b/include/tao/json/from_input.hpp new file mode 100644 index 00000000..c1093e12 --- /dev/null +++ b/include/tao/json/from_input.hpp @@ -0,0 +1,32 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_FROM_INPUT_HPP +#define TAO_JSON_FROM_INPUT_HPP + +#include +#include + +#include "events/from_input.hpp" +#include "events/to_value.hpp" +#include "events/transformer.hpp" + +namespace tao::json +{ + template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] basic_value< Traits > basic_from_input( Ts&&... ts ) + { + events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; + events::from_input( consumer, std::forward< Ts >( ts )... ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] value from_input( Ts&&... ts ) + { + return basic_from_input< traits, Transformers... >( std::forward< Ts >( ts )... ); + } + +} // namespace tao::json + +#endif diff --git a/include/tao/json/from_stream.hpp b/include/tao/json/from_stream.hpp index 5372ca3e..b1d0fd2f 100644 --- a/include/tao/json/from_stream.hpp +++ b/include/tao/json/from_stream.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_FROM_STREAM_HPP -#define TAOCPP_JSON_INCLUDE_FROM_STREAM_HPP +#ifndef TAO_JSON_FROM_STREAM_HPP +#define TAO_JSON_FROM_STREAM_HPP #include #include @@ -12,38 +12,34 @@ #include "events/to_value.hpp" #include "events/transformer.hpp" -namespace tao +namespace tao::json { - namespace json + template< template< typename... > class Traits, template< typename... > class... Transformers > + [[nodiscard]] basic_value< Traits > basic_from_stream( std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) { - template< template< typename... > class Traits, template< typename... > class... Transformers > - basic_value< Traits > basic_from_stream( std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) - { - events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; - events::from_stream( consumer, stream, source, maximum_buffer_size ); - return std::move( consumer.value ); - } - - template< template< typename... > class Traits, template< typename... > class... Transformers > - basic_value< Traits > basic_from_stream( std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) - { - return basic_from_stream< Traits, Transformers... >( stream, source.c_str(), maximum_buffer_size ); - } - - template< template< typename... > class... Transformers > - value from_stream( std::istream& stream, const char* source, const std::size_t maximum_buffer_size = 4000 ) - { - return basic_from_stream< traits, Transformers... >( stream, source, maximum_buffer_size ); - } - - template< template< typename... > class... Transformers > - value from_stream( std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) - { - return basic_from_stream< traits, Transformers... >( stream, source.c_str(), maximum_buffer_size ); - } - - } // namespace json - -} // namespace tao + events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; + events::from_stream( consumer, stream, source, maximum_buffer_size ); + return std::move( consumer.value ); + } + + template< template< typename... > class Traits, template< typename... > class... Transformers > + [[nodiscard]] basic_value< Traits > basic_from_stream( std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) + { + return basic_from_stream< Traits, Transformers... >( stream, source.c_str(), maximum_buffer_size ); + } + + template< template< typename... > class... Transformers > + [[nodiscard]] value from_stream( std::istream& stream, const char* source, const std::size_t maximum_buffer_size = 4000 ) + { + return basic_from_stream< traits, Transformers... >( stream, source, maximum_buffer_size ); + } + + template< template< typename... > class... Transformers > + [[nodiscard]] value from_stream( std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) + { + return basic_from_stream< traits, Transformers... >( stream, source.c_str(), maximum_buffer_size ); + } + +} // namespace tao::json #endif diff --git a/include/tao/json/from_string.hpp b/include/tao/json/from_string.hpp index 43193fa6..e2538a0e 100644 --- a/include/tao/json/from_string.hpp +++ b/include/tao/json/from_string.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_FROM_STRING_HPP -#define TAOCPP_JSON_INCLUDE_FROM_STRING_HPP +#ifndef TAO_JSON_FROM_STRING_HPP +#define TAO_JSON_FROM_STRING_HPP #include #include @@ -11,35 +11,31 @@ #include "events/to_value.hpp" #include "events/transformer.hpp" -namespace tao +namespace tao::json { - namespace json + template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] basic_value< Traits > basic_from_string( Ts&&... ts ) { - template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > - basic_value< Traits > basic_from_string( Ts&&... ts ) - { - events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; - events::from_string( consumer, std::forward< Ts >( ts )... ); - return std::move( consumer.value ); - } + events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; + events::from_string( consumer, std::forward< Ts >( ts )... ); + return std::move( consumer.value ); + } - template< template< typename... > class... Transformers, typename... Ts > - value from_string( Ts&&... ts ) - { - return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); - } + template< template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] value from_string( Ts&&... ts ) + { + return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); + } - inline namespace literals + inline namespace literals + { + [[nodiscard]] inline value operator"" _json( const char* data, const std::size_t size ) { - inline value operator"" _json( const char* data, const std::size_t size ) - { - return json::from_string( data, size, "literal" ); - } - - } // namespace literals + return json::from_string( data, size, "literal" ); + } - } // namespace json + } // namespace literals -} // namespace tao +} // namespace tao::json #endif diff --git a/include/tao/json/internal/action.hpp b/include/tao/json/internal/action.hpp index 059e7c36..9638f272 100644 --- a/include/tao/json/internal/action.hpp +++ b/include/tao/json/internal/action.hpp @@ -1,242 +1,268 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_ACTION_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_ACTION_HPP +#ifndef TAO_JSON_INTERNAL_ACTION_HPP +#define TAO_JSON_INTERNAL_ACTION_HPP + +#include +#include #include "../external/pegtl/nothing.hpp" -#include "errors.hpp" #include "grammar.hpp" - #include "number_state.hpp" +#include "unescape_action.hpp" -namespace tao +namespace tao::json::internal { - namespace json - { - namespace internal - { - template< typename Rule > - struct action - : json_pegtl::nothing< Rule > - { - }; - - template<> - struct action< rules::null > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.null(); - } - }; - - template<> - struct action< rules::true_ > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.boolean( true ); - } - }; - - template<> - struct action< rules::false_ > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.boolean( false ); - } - }; - - template<> - struct action< rules::array::begin > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.begin_array(); - } - }; - - template<> - struct action< rules::array::element > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.element(); - } - }; - - template<> - struct action< rules::array::end > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.end_array(); - } - }; - - template<> - struct action< rules::object::begin > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.begin_object(); - } - }; - - template<> - struct action< rules::object::element > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.member(); - } - }; - - template<> - struct action< rules::object::end > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.end_object(); - } - }; - - template<> - struct action< rules::zero< false > > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.number( std::uint64_t( 0 ) ); - } - }; - - template<> - struct action< rules::zero< true > > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.number( std::int64_t( 0 ) ); - } - }; - - template<> - struct action< rules::esign > - { - template< typename Input, bool NEG > - static void apply( const Input& in, number_state< NEG >& result ) - { - result.eneg = ( in.peek_char() == '-' ); - } - }; - - template<> - struct action< rules::idigits > - { - template< typename Input, bool NEG > - static void apply( const Input& in, number_state< NEG >& result ) - { - const auto s = in.size(); - - if( s == 1 && in.peek_char() == '0' ) { - return; - } - - if( s > ( 1 << 20 ) ) { - throw std::runtime_error( "JSON number with 1 megabyte digits" ); - } - - const auto c = std::min( s, max_mantissa_digits ); - std::memcpy( result.mantissa, in.begin(), c ); - result.exponent10 += static_cast< typename number_state< NEG >::exponent10_t >( s - c ); - result.msize = static_cast< typename number_state< NEG >::msize_t >( c ); - - for( std::size_t i = c; i < s; ++i ) { - if( in.peek_char( i ) != '0' ) { - result.drop = true; - return; - } - } + template< typename Rule > + struct action + : pegtl::nothing< Rule > + {}; + + template<> + struct action< rules::null > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.null(); + } + }; + + template<> + struct action< rules::true_ > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.boolean( true ); + } + }; + + template<> + struct action< rules::false_ > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.boolean( false ); + } + }; + + template<> + struct action< rules::array::begin > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.begin_array(); + } + }; + + template<> + struct action< rules::array::element > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.element(); + } + }; + + template<> + struct action< rules::array::end > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.end_array(); + } + }; + + template<> + struct action< rules::object::begin > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.begin_object(); + } + }; + + template<> + struct action< rules::object::element > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.member(); + } + }; + + template<> + struct action< rules::object::end > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.end_object(); + } + }; + + template<> + struct action< rules::zero< false > > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.number( std::uint64_t( 0 ) ); + } + }; + + template<> + struct action< rules::zero< true > > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.number( std::int64_t( 0 ) ); + } + }; + + template<> + struct action< rules::esign > + { + template< typename Input, bool NEG > + static void apply( const Input& in, number_state< NEG >& result ) + { + result.eneg = ( in.peek_char() == '-' ); + } + }; + + template<> + struct action< rules::idigits > + { + template< typename Input, bool NEG > + static void apply( const Input& in, number_state< NEG >& result ) + { + const auto s = in.size(); + + if( s == 1 && in.peek_char() == '0' ) { + return; + } + + if( s > ( 1 << 20 ) ) { + throw pegtl::parse_error( "JSON number with 1 megabyte digits", in ); + } + + const auto c = ( std::min )( s, max_mantissa_digits ); + std::memcpy( result.mantissa, in.begin(), c ); + result.exponent10 += static_cast< typename number_state< NEG >::exponent10_t >( s - c ); + result.msize = static_cast< typename number_state< NEG >::msize_t >( c ); + + for( std::size_t i = c; i < s; ++i ) { + if( in.peek_char( i ) != '0' ) { + result.drop = true; + return; } - }; - - template<> - struct action< rules::fdigits > - { - template< typename Input, bool NEG > - static void apply( const Input& in, number_state< NEG >& result ) - { - result.isfp = true; - - const auto* b = in.begin(); - const auto* e = in.end(); - - while( ( e > b ) && ( e[ -1 ] == '0' ) ) { - --e; - } - if( !result.msize ) { - while( ( b < e ) && ( b[ 0 ] == '0' ) ) { - ++b; - --result.exponent10; - } - } - const auto c = std::min( std::size_t( e - b ), max_mantissa_digits - result.msize ); - std::memcpy( result.mantissa + result.msize, b, c ); - result.exponent10 -= static_cast< typename number_state< NEG >::exponent10_t >( c ); - result.msize += static_cast< typename number_state< NEG >::msize_t >( c ); - - for( const auto* r = b + c; r < e; ++r ) { - if( *r != '0' ) { - result.drop = true; - return; - } - } + } + } + }; + + template<> + struct action< rules::fdigits > + { + template< typename Input, bool NEG > + static void apply( const Input& in, number_state< NEG >& result ) + { + result.isfp = true; + + const auto* b = in.begin(); + const auto* e = in.end(); + + while( ( e > b ) && ( e[ -1 ] == '0' ) ) { + --e; + } + if( !result.msize ) { + while( ( b < e ) && ( b[ 0 ] == '0' ) ) { + ++b; + --result.exponent10; } - }; - - template<> - struct action< rules::edigits > - { - template< typename Input, bool NEG > - static void apply( const Input& in, number_state< NEG >& result ) - { - result.isfp = true; - - const char* b = in.begin(); - - while( ( b < in.end() ) && ( b[ 0 ] == '0' ) ) { - ++b; - } - if( ( in.end() - b ) > 9 ) { - throw std::runtime_error( "JSON exponent has more than 9 significant digits" ); - } - int exponent10 = 0; - - while( b < in.end() ) { - exponent10 = ( exponent10 * 10 ) + ( b[ 0 ] - '0' ); - ++b; - } - result.exponent10 += ( result.eneg ? -exponent10 : exponent10 ); + } + const auto c = ( std::min )( std::size_t( e - b ), max_mantissa_digits - result.msize ); + std::memcpy( result.mantissa + result.msize, b, c ); + result.exponent10 -= static_cast< typename number_state< NEG >::exponent10_t >( c ); + result.msize += static_cast< typename number_state< NEG >::msize_t >( c ); + + for( const auto* r = b + c; r < e; ++r ) { + if( *r != '0' ) { + result.drop = true; + return; } - }; + } + } + }; - } // namespace internal + template<> + struct action< rules::edigits > + { + template< typename Input, bool NEG > + static void apply( const Input& in, number_state< NEG >& result ) + { + result.isfp = true; + + const char* b = in.begin(); + + while( ( b < in.end() ) && ( b[ 0 ] == '0' ) ) { + ++b; + } + if( ( in.end() - b ) > 9 ) { + throw pegtl::parse_error( "JSON exponent has more than 9 significant digits", in ); + } + int exponent10 = 0; + + while( b < in.end() ) { + exponent10 = ( exponent10 * 10 ) + ( b[ 0 ] - '0' ); + ++b; + } + result.exponent10 += ( result.eneg ? -exponent10 : exponent10 ); + } + }; + + template< bool NEG > + struct action< rules::number< NEG > > + : pegtl::change_states< number_state< NEG > > + { + template< typename Input, typename Consumer > + static void success( const Input& /*unused*/, number_state< NEG >& state, Consumer& consumer ) + { + state.success( consumer ); + } + }; + + template<> + struct action< rules::string::content > + : pegtl::change_action_and_states< unescape_action, std::string > + { + template< typename Input, typename Consumer > + static void success( const Input& /*unused*/, std::string& unescaped, Consumer& consumer ) + { + consumer.string( std::move( unescaped ) ); + } + }; - } // namespace json + template<> + struct action< rules::key::content > + : pegtl::change_action_and_states< unescape_action, std::string > + { + template< typename Input, typename Consumer > + static void success( const Input& /*unused*/, std::string& unescaped, Consumer& consumer ) + { + consumer.key( std::move( unescaped ) ); + } + }; -} // namespace tao +} // namespace tao::json::internal #endif diff --git a/include/tao/json/internal/base64.hpp b/include/tao/json/internal/base64.hpp index f4403f00..64130b05 100644 --- a/include/tao/json/internal/base64.hpp +++ b/include/tao/json/internal/base64.hpp @@ -1,63 +1,55 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_BASE64_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_BASE64_HPP +#ifndef TAO_JSON_INTERNAL_BASE64_HPP +#define TAO_JSON_INTERNAL_BASE64_HPP -#include -#include +#include +#include -namespace tao +namespace tao::json::internal { - namespace json + template< typename T > + [[nodiscard]] std::string base64( const T& v ) { - namespace internal - { - template< typename T > - std::string base64( const T& v ) - { - static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - std::string s; - s.reserve( ( v.size() + 2 ) / 3 * 4 ); - - unsigned cycle = 0; - unsigned encode = 0; - for( const auto c : v ) { - encode <<= 8; - encode += static_cast< unsigned char >( c ); - s += table[ ( encode >> ( ++cycle * 2 ) ) & 0x3f ]; - if( cycle == 3 ) { - cycle = 0; - s += table[ encode & 0x3f ]; - } - } - - switch( cycle ) { - case 0: - break; - - case 1: - s += table[ ( encode << 4 ) & 0x3f ]; - s += "=="; - break; - - case 2: - s += table[ ( encode << 2 ) & 0x3f ]; - s += '='; - break; - - default: - assert( !"code should be unreachable" ); // LCOV_EXCL_LINE - } - - return s; + static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + std::string s; + s.reserve( ( v.size() + 2 ) / 3 * 4 ); + + unsigned cycle = 0; + unsigned encode = 0; + for( const auto c : v ) { + encode <<= 8; + encode += static_cast< unsigned char >( c ); + s += table[ ( encode >> ( ++cycle * 2 ) ) & 0x3f ]; + if( cycle == 3 ) { + cycle = 0; + s += table[ encode & 0x3f ]; } + } - } // namespace internal + switch( cycle ) { + case 0: + break; - } // namespace json + case 1: + s += table[ ( encode << 4 ) & 0x3f ]; + s += "=="; + break; -} // namespace tao + case 2: + s += table[ ( encode << 2 ) & 0x3f ]; + s += '='; + break; + + default: + throw std::logic_error( "code should be unreachable" ); // LCOV_EXCL_LINE + } + + return s; + } + +} // namespace tao::json::internal #endif diff --git a/include/tao/json/internal/base64url.hpp b/include/tao/json/internal/base64url.hpp index 725e8bf6..5649ba0f 100644 --- a/include/tao/json/internal/base64url.hpp +++ b/include/tao/json/internal/base64url.hpp @@ -1,61 +1,53 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_BASE64URL_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_BASE64URL_HPP +#ifndef TAO_JSON_INTERNAL_BASE64URL_HPP +#define TAO_JSON_INTERNAL_BASE64URL_HPP -#include -#include +#include +#include -namespace tao +namespace tao::json::internal { - namespace json + template< typename T > + [[nodiscard]] std::string base64url( const T& v ) { - namespace internal - { - template< typename T > - inline std::string base64url( const T& v ) - { - static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - - std::string s; - s.reserve( ( v.size() + 2 ) / 3 * 4 ); - - unsigned cycle = 0; - unsigned encode = 0; - for( const auto c : v ) { - encode <<= 8; - encode += static_cast< unsigned char >( c ); - s += table[ ( encode >> ( ++cycle * 2 ) ) & 0x3f ]; - if( cycle == 3 ) { - cycle = 0; - s += table[ encode & 0x3f ]; - } - } - - switch( cycle ) { - case 0: - break; - - case 1: - s += table[ ( encode << 4 ) & 0x3f ]; - break; - - case 2: - s += table[ ( encode << 2 ) & 0x3f ]; - break; - - default: - assert( !"code should be unreachable" ); // LCOV_EXCL_LINE - } - - return s; + static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + + std::string s; + s.reserve( ( v.size() + 2 ) / 3 * 4 ); + + unsigned cycle = 0; + unsigned encode = 0; + for( const auto c : v ) { + encode <<= 8; + encode += static_cast< unsigned char >( c ); + s += table[ ( encode >> ( ++cycle * 2 ) ) & 0x3f ]; + if( cycle == 3 ) { + cycle = 0; + s += table[ encode & 0x3f ]; } + } - } // namespace internal + switch( cycle ) { + case 0: + break; - } // namespace json + case 1: + s += table[ ( encode << 4 ) & 0x3f ]; + break; -} // namespace tao + case 2: + s += table[ ( encode << 2 ) & 0x3f ]; + break; + + default: + throw std::logic_error( "code should be unreachable" ); // LCOV_EXCL_LINE + } + + return s; + } + +} // namespace tao::json::internal #endif diff --git a/include/tao/json/internal/control.hpp b/include/tao/json/internal/control.hpp deleted file mode 100644 index 8fbbe8fe..00000000 --- a/include/tao/json/internal/control.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_CONTROL_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_CONTROL_HPP - -#include "../external/pegtl/contrib/changes.hpp" - -#include "errors.hpp" - -#include "unescape_action.hpp" - -#include "key_state.hpp" -#include "number_state.hpp" -#include "string_state.hpp" - -namespace tao -{ - namespace json - { - namespace internal - { - template< typename Rule > - struct control - : errors< Rule > - { - }; - - template< bool NEG > - struct control< rules::number< NEG > > - : json_pegtl::change_state< rules::number< NEG >, number_state< NEG >, errors > - { - }; - - template<> - struct control< rules::string::content > - : json_pegtl::change_state_and_action< rules::string::content, string_state, unescape_action, errors > - { - }; - - template<> - struct control< rules::key::content > - : json_pegtl::change_state_and_action< rules::key::content, key_state, unescape_action, errors > - { - }; - - } // namespace internal - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/internal/endian.hpp b/include/tao/json/internal/endian.hpp index 72709865..7448fb41 100644 --- a/include/tao/json/internal/endian.hpp +++ b/include/tao/json/internal/endian.hpp @@ -1,70 +1,60 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_ENDIAN_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_ENDIAN_HPP +#ifndef TAO_JSON_INTERNAL_ENDIAN_HPP +#define TAO_JSON_INTERNAL_ENDIAN_HPP #include #include -// TODO: Where to put this header? - #if defined( _WIN32 ) && !defined( __MINGW32__ ) #include "endian_win.hpp" #else #include "endian_gcc.hpp" #endif -namespace tao +namespace tao::json::internal { - namespace json + template< typename N > + [[nodiscard]] N h_to_be( const N n ) noexcept { - namespace internal - { - template< typename N > - N h_to_be( const N n ) noexcept - { - return N( to_and_from_be< sizeof( N ) >::convert( n ) ); - } - - template< typename N > - N be_to_h( const N n ) noexcept - { - return h_to_be( n ); - } + return N( to_and_from_be< sizeof( N ) >::convert( n ) ); + } - template< typename N > - N be_to_h( const void* p ) noexcept - { - N n; - std::memcpy( &n, p, sizeof( n ) ); - return internal::be_to_h( n ); - } - - template< typename N > - N h_to_le( const N n ) noexcept - { - return N( to_and_from_le< sizeof( N ) >::convert( n ) ); - } + template< typename N > + [[nodiscard]] N be_to_h( const N n ) noexcept + { + return h_to_be( n ); + } - template< typename N > - N le_to_h( const N n ) noexcept - { - return h_to_le( n ); - } + template< typename N > + [[nodiscard]] N be_to_h( const void* p ) noexcept + { + N n; + std::memcpy( &n, p, sizeof( n ) ); + return internal::be_to_h( n ); + } - template< typename N > - N le_to_h( const void* p ) noexcept - { - N n; - std::memcpy( &n, p, sizeof( n ) ); - return internal::le_to_h( n ); - } + template< typename N > + [[nodiscard]] N h_to_le( const N n ) noexcept + { + return N( to_and_from_le< sizeof( N ) >::convert( n ) ); + } - } // namespace internal + template< typename N > + [[nodiscard]] N le_to_h( const N n ) noexcept + { + return h_to_le( n ); + } - } // namespace json + template< typename N > + [[nodiscard]] N le_to_h( const void* p ) noexcept + { + N n; + std::memcpy( &n, p, sizeof( n ) ); + return internal::le_to_h( n ); + } -} // namespace tao +} // namespace tao::json::internal #endif diff --git a/include/tao/json/internal/endian_gcc.hpp b/include/tao/json/internal/endian_gcc.hpp index 63ae3bfd..b1cdb9d2 100644 --- a/include/tao/json/internal/endian_gcc.hpp +++ b/include/tao/json/internal/endian_gcc.hpp @@ -1,202 +1,198 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_ENDIAN_GCC_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_ENDIAN_GCC_HPP +#ifndef TAO_JSON_INTERNAL_ENDIAN_GCC_HPP +#define TAO_JSON_INTERNAL_ENDIAN_GCC_HPP -namespace tao +#include +#include + +namespace tao::json::internal { - namespace json - { - namespace internal - { #if not defined( __BYTE_ORDER__ ) #error TODO -- what? #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - template< unsigned S > - struct to_and_from_be - { - template< typename T > - static T convert( const T n ) noexcept - { - return n; - } - }; - - template< unsigned S > - struct to_and_from_le; - - template<> - struct to_and_from_le< 1 > - { - static std::uint8_t convert( const std::uint8_t n ) noexcept - { - return n; - } - - static std::int8_t convert( const std::int8_t n ) noexcept - { - return n; - } - }; - - template<> - struct to_and_from_le< 2 > - { - static std::int16_t convert( const std::int16_t n ) noexcept - { - return __builtin_bswap16( n ); - } - - static std::uint16_t convert( const std::uint16_t n ) noexcept - { - return __builtin_bswap16( n ); - } - }; - - template<> - struct to_and_from_le< 4 > - { - static float convert( float n ) noexcept - { - std::uint32_t u; - std::memcpy( &u, &n, 4 ); - u = convert( u ); - std::memcpy( &n, &u, 4 ); - return n; - } - - static std::int32_t convert( const std::int32_t n ) noexcept - { - return __builtin_bswap32( n ); - } - - static std::uint32_t convert( const std::uint32_t n ) noexcept - { - return __builtin_bswap32( n ); - } - }; - - template<> - struct to_and_from_le< 8 > - { - static double convert( double n ) noexcept - { - std::uint64_t u; - std::memcpy( &u, &n, 8 ); - u = convert( u ); - std::memcpy( &n, &u, 8 ); - return n; - } - - static std::int64_t convert( const std::int64_t n ) noexcept - { - return __builtin_bswap64( n ); - } - - static std::uint64_t convert( const std::uint64_t n ) noexcept - { - return __builtin_bswap64( n ); - } - }; + template< unsigned S > + struct to_and_from_be + { + template< typename T > + [[nodiscard]] static T convert( const T n ) noexcept + { + return n; + } + }; + + template< unsigned S > + struct to_and_from_le; + + template<> + struct to_and_from_le< 1 > + { + [[nodiscard]] static std::uint8_t convert( const std::uint8_t n ) noexcept + { + return n; + } + + [[nodiscard]] static std::int8_t convert( const std::int8_t n ) noexcept + { + return n; + } + }; + + template<> + struct to_and_from_le< 2 > + { + [[nodiscard]] static std::int16_t convert( const std::int16_t n ) noexcept + { + return __builtin_bswap16( n ); + } + + [[nodiscard]] static std::uint16_t convert( const std::uint16_t n ) noexcept + { + return __builtin_bswap16( n ); + } + }; + + template<> + struct to_and_from_le< 4 > + { + [[nodiscard]] static float convert( float n ) noexcept + { + std::uint32_t u; + std::memcpy( &u, &n, 4 ); + u = convert( u ); + std::memcpy( &n, &u, 4 ); + return n; + } + + [[nodiscard]] static std::int32_t convert( const std::int32_t n ) noexcept + { + return __builtin_bswap32( n ); + } + + [[nodiscard]] static std::uint32_t convert( const std::uint32_t n ) noexcept + { + return __builtin_bswap32( n ); + } + }; + + template<> + struct to_and_from_le< 8 > + { + [[nodiscard]] static double convert( double n ) noexcept + { + std::uint64_t u; + std::memcpy( &u, &n, 8 ); + u = convert( u ); + std::memcpy( &n, &u, 8 ); + return n; + } + + [[nodiscard]] static std::int64_t convert( const std::int64_t n ) noexcept + { + return __builtin_bswap64( n ); + } + + [[nodiscard]] static std::uint64_t convert( const std::uint64_t n ) noexcept + { + return __builtin_bswap64( n ); + } + }; #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - template< unsigned S > - struct to_and_from_le - { - template< typename T > - static T convert( const T n ) noexcept - { - return n; - } - }; - - template< unsigned S > - struct to_and_from_be; - - template<> - struct to_and_from_be< 1 > - { - static std::int8_t convert( const std::int8_t n ) noexcept - { - return n; - } - - static std::uint8_t convert( const std::uint8_t n ) noexcept - { - return n; - } - }; - - template<> - struct to_and_from_be< 2 > - { - static std::int16_t convert( const std::int16_t n ) noexcept - { - return __builtin_bswap16( n ); - } - - static std::uint16_t convert( const std::uint16_t n ) noexcept - { - return __builtin_bswap16( n ); - } - }; - - template<> - struct to_and_from_be< 4 > - { - static float convert( float n ) noexcept - { - std::uint32_t u; - std::memcpy( &u, &n, 4 ); - u = convert( u ); - std::memcpy( &n, &u, 4 ); - return n; - } - - static std::int32_t convert( const std::int32_t n ) noexcept - { - return __builtin_bswap32( n ); - } - - static std::uint32_t convert( const std::uint32_t n ) noexcept - { - return __builtin_bswap32( n ); - } - }; - - template<> - struct to_and_from_be< 8 > - { - static double convert( double n ) noexcept - { - std::uint64_t u; - std::memcpy( &u, &n, 8 ); - u = convert( u ); - std::memcpy( &n, &u, 8 ); - return n; - } - - static std::uint64_t convert( const std::uint64_t n ) noexcept - { - return __builtin_bswap64( n ); - } - - static std::int64_t convert( const std::int64_t n ) noexcept - { - return __builtin_bswap64( n ); - } - }; + template< unsigned S > + struct to_and_from_le + { + template< typename T > + [[nodiscard]] static T convert( const T n ) noexcept + { + return n; + } + }; + + template< unsigned S > + struct to_and_from_be; + + template<> + struct to_and_from_be< 1 > + { + [[nodiscard]] static std::int8_t convert( const std::int8_t n ) noexcept + { + return n; + } + + [[nodiscard]] static std::uint8_t convert( const std::uint8_t n ) noexcept + { + return n; + } + }; + + template<> + struct to_and_from_be< 2 > + { + [[nodiscard]] static std::int16_t convert( const std::int16_t n ) noexcept + { + return __builtin_bswap16( n ); + } + + [[nodiscard]] static std::uint16_t convert( const std::uint16_t n ) noexcept + { + return __builtin_bswap16( n ); + } + }; + + template<> + struct to_and_from_be< 4 > + { + [[nodiscard]] static float convert( float n ) noexcept + { + std::uint32_t u; + std::memcpy( &u, &n, 4 ); + u = convert( u ); + std::memcpy( &n, &u, 4 ); + return n; + } + + [[nodiscard]] static std::int32_t convert( const std::int32_t n ) noexcept + { + return __builtin_bswap32( n ); + } + + [[nodiscard]] static std::uint32_t convert( const std::uint32_t n ) noexcept + { + return __builtin_bswap32( n ); + } + }; + + template<> + struct to_and_from_be< 8 > + { + [[nodiscard]] static double convert( double n ) noexcept + { + std::uint64_t u; + std::memcpy( &u, &n, 8 ); + u = convert( u ); + std::memcpy( &n, &u, 8 ); + return n; + } + + [[nodiscard]] static std::uint64_t convert( const std::uint64_t n ) noexcept + { + return __builtin_bswap64( n ); + } + + [[nodiscard]] static std::int64_t convert( const std::int64_t n ) noexcept + { + return __builtin_bswap64( n ); + } + }; #else #error Unknown host byte order! #endif - } // namespace internal - - } // namespace json -} // namespace tao +} // namespace tao::json::internal #endif diff --git a/include/tao/json/internal/endian_win.hpp b/include/tao/json/internal/endian_win.hpp index 38bc9932..bb0856ea 100644 --- a/include/tao/json/internal/endian_win.hpp +++ b/include/tao/json/internal/endian_win.hpp @@ -1,91 +1,103 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_ENDIAN_WIN_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_ENDIAN_WIN_HPP +#ifndef TAO_JSON_INTERNAL_ENDIAN_WIN_HPP +#define TAO_JSON_INTERNAL_ENDIAN_WIN_HPP #include #include #include // TODO: Or is intrin.h the 'more correct' header for the _byteswap_foo() functions? -namespace tao +namespace tao::json::internal { - namespace json + template< unsigned S > + struct to_and_from_le { - namespace internal + template< typename T > + [[nodiscard]] static T convert( const T t ) noexcept { - template< unsigned S > - struct to_and_from_le - { - template< typename T > - static T convert( const T t ) noexcept - { - return t; - } - }; - - template< unsigned S > - struct to_and_from_be; - - template<> - struct to_and_from_be< 1 > - { - static std::uint8_t convert( const std::uint8_t n ) noexcept - { - return n; - } - }; - - template<> - struct to_and_from_be< 2 > - { - static std::uint16_t convert( const std::uint16_t n ) noexcept - { - return _byteswap_ushort( n ); - } - }; - - template<> - struct to_and_from_be< 4 > - { - static float convert( float n ) noexcept - { - std::uint32_t u; - std::memcpy( &u, &n, 4 ); - u = convert( u ); - std::memcpy( &n, &u, 4 ); - return n; - } - - static std::uint32_t convert( const std::uint32_t n ) noexcept - { - return _byteswap_ulong( n ); - } - }; - - template<> - struct to_and_from_be< 8 > - { - static double convert( double n ) noexcept - { - std::uint64_t u; - std::memcpy( &u, &n, 8 ); - u = convert( u ); - std::memcpy( &n, &u, 8 ); - return n; - } - - static std::uint64_t convert( const std::uint64_t n ) noexcept - { - return _byteswap_uint64( n ); - } - }; - - } // namespace internal - - } // namespace json - -} // namespace tao + return t; + } + }; + + template< unsigned S > + struct to_and_from_be; + + template<> + struct to_and_from_be< 1 > + { + [[nodiscard]] static std::int8_t convert( const std::int8_t n ) noexcept + { + return n; + } + + [[nodiscard]] static std::uint8_t convert( const std::uint8_t n ) noexcept + { + return n; + } + }; + + template<> + struct to_and_from_be< 2 > + { + [[nodiscard]] static std::int16_t convert( const std::int16_t n ) noexcept + { + return std::int16_t( _byteswap_ushort( std::uint16_t( n ) ) ); + } + + [[nodiscard]] static std::uint16_t convert( const std::uint16_t n ) noexcept + { + return _byteswap_ushort( n ); + } + }; + + template<> + struct to_and_from_be< 4 > + { + [[nodiscard]] static float convert( float n ) noexcept + { + std::uint32_t u; + std::memcpy( &u, &n, 4 ); + u = convert( u ); + std::memcpy( &n, &u, 4 ); + return n; + } + + [[nodiscard]] static std::int32_t convert( const std::int32_t n ) noexcept + { + return std::int32_t( _byteswap_ulong( std::uint32_t( n ) ) ); + } + + [[nodiscard]] static std::uint32_t convert( const std::uint32_t n ) noexcept + { + return _byteswap_ulong( n ); + } + }; + + template<> + struct to_and_from_be< 8 > + { + [[nodiscard]] static double convert( double n ) noexcept + { + std::uint64_t u; + std::memcpy( &u, &n, 8 ); + u = convert( u ); + std::memcpy( &n, &u, 8 ); + return n; + } + + [[nodiscard]] static std::int64_t convert( const std::int64_t n ) noexcept + { + return std::int64_t( _byteswap_uint64( std::uint64_t( n ) ) ); + } + + [[nodiscard]] static std::uint64_t convert( const std::uint64_t n ) noexcept + { + return _byteswap_uint64( n ); + } + }; + +} // namespace tao::json::internal #endif diff --git a/include/tao/json/internal/errors.hpp b/include/tao/json/internal/errors.hpp index 1d795ad0..6071a91d 100644 --- a/include/tao/json/internal/errors.hpp +++ b/include/tao/json/internal/errors.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_ERRORS_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_ERRORS_HPP +#ifndef TAO_JSON_INTERNAL_ERRORS_HPP +#define TAO_JSON_INTERNAL_ERRORS_HPP #include @@ -11,88 +11,75 @@ #include "grammar.hpp" -#if defined( _MSC_VER ) -#define WEAK_PREFIX __declspec( selectany ) -#define WEAK_SUFFIX -#else -#define WEAK_PREFIX -#define WEAK_SUFFIX __attribute__( ( weak ) ) -#endif - -namespace tao +namespace tao::json::internal { - namespace json + template< typename Rule > + struct errors + : pegtl::normal< Rule > { - namespace internal - { - template< typename Rule > - struct errors - : json_pegtl::normal< Rule > - { - static const std::string error_message; - - template< typename Input, typename... States > - static void raise( const Input& in, States&&... ) - { - throw json_pegtl::parse_error( error_message, in ); - } - - template< template< typename... > class Action, typename Input, typename... States > - static void apply0( const Input& in, States&&... st ) - { - try { - Action< Rule >::apply0( st... ); - } - catch( const json_pegtl::parse_error& ) { - throw; - } - catch( const std::exception& e ) { - throw json_pegtl::parse_error( e.what(), in ); - } - } - - template< template< typename... > class Action, typename Iterator, typename Input, typename... States > - static void apply( const Iterator& begin, const Input& in, States&&... st ) - { - try { - using action_t = typename Input::action_t; - const action_t action_input( begin, in ); - Action< Rule >::apply( action_input, st... ); - } - catch( const json_pegtl::parse_error& ) { - throw; - } - catch( const std::exception& e ) { - throw json_pegtl::parse_error( e.what(), in ); - } - } - }; - - // clang-format off - template<> WEAK_PREFIX const std::string errors< rules::text >::error_message WEAK_SUFFIX = "no valid JSON"; + static const std::string error_message; - template<> WEAK_PREFIX const std::string errors< rules::end_array >::error_message WEAK_SUFFIX = "incomplete array, expected ']'"; - template<> WEAK_PREFIX const std::string errors< rules::end_object >::error_message WEAK_SUFFIX = "incomplete object, expected '}'"; - template<> WEAK_PREFIX const std::string errors< rules::member >::error_message WEAK_SUFFIX = "expected member"; - template<> WEAK_PREFIX const std::string errors< rules::name_separator >::error_message WEAK_SUFFIX = "expected ':'"; - template<> WEAK_PREFIX const std::string errors< rules::array_element >::error_message WEAK_SUFFIX = "expected value"; - template<> WEAK_PREFIX const std::string errors< rules::value >::error_message WEAK_SUFFIX = "expected value"; - - template<> WEAK_PREFIX const std::string errors< rules::edigits >::error_message WEAK_SUFFIX = "expected at least one exponent digit"; - template<> WEAK_PREFIX const std::string errors< rules::fdigits >::error_message WEAK_SUFFIX = "expected at least one fraction digit"; - template<> WEAK_PREFIX const std::string errors< rules::xdigit >::error_message WEAK_SUFFIX = "incomplete universal character name"; - template<> WEAK_PREFIX const std::string errors< rules::escaped >::error_message WEAK_SUFFIX = "unknown escape sequence"; - template<> WEAK_PREFIX const std::string errors< rules::chars >::error_message WEAK_SUFFIX = "invalid character in string"; - template<> WEAK_PREFIX const std::string errors< rules::string::content >::error_message WEAK_SUFFIX = "unterminated string"; - template<> WEAK_PREFIX const std::string errors< rules::key::content >::error_message WEAK_SUFFIX = "unterminated key"; - - template<> WEAK_PREFIX const std::string errors< json_pegtl::eof >::error_message WEAK_SUFFIX = "unexpected character after JSON value"; - // clang-format on - - } // namespace internal - - } // namespace json + template< typename Input, typename... States > + static void raise( const Input& in, States&&... /*unused*/ ) + { + throw pegtl::parse_error( error_message, in ); + } -} // namespace tao + template< template< typename... > class Action, typename Iterator, typename Input, typename... States > + static auto apply( const Iterator& begin, const Input& in, States&&... st ) + -> decltype( Action< Rule >::apply( std::declval< const typename Input::action_t& >(), st... ) ) + { + try { + using action_t = typename Input::action_t; + const action_t action_input( begin, in ); + return Action< Rule >::apply( action_input, st... ); + } + catch( const pegtl::parse_error& ) { + throw; + } + catch( const std::exception& e ) { + throw pegtl::parse_error( e.what(), in ); + } + } + + template< template< typename... > class Action, typename Input, typename... States > + static auto apply0( const Input& in, States&&... st ) + -> decltype( Action< Rule >::apply0( st... ) ) + { + try { + return Action< Rule >::apply0( st... ); + } + catch( const pegtl::parse_error& ) { + throw; + } + catch( const std::exception& e ) { + throw pegtl::parse_error( e.what(), in ); + } + } + }; + + // clang-format off + template<> inline const std::string errors< rules::text >::error_message = "no valid JSON"; + + template<> inline const std::string errors< rules::end_array >::error_message = "incomplete array, expected ']'"; + template<> inline const std::string errors< rules::end_object >::error_message = "incomplete object, expected '}'"; + template<> inline const std::string errors< rules::member >::error_message = "expected member"; + template<> inline const std::string errors< rules::name_separator >::error_message = "expected ':'"; + template<> inline const std::string errors< rules::array_element >::error_message = "expected value"; + template<> inline const std::string errors< rules::value >::error_message = "expected value"; + template<> inline const std::string errors< rules::sor_value >::error_message = "expected value"; + + template<> inline const std::string errors< rules::edigits >::error_message = "expected at least one exponent digit"; + template<> inline const std::string errors< rules::fdigits >::error_message = "expected at least one fraction digit"; + template<> inline const std::string errors< rules::xdigit >::error_message = "incomplete universal character name"; + template<> inline const std::string errors< rules::escaped >::error_message = "unknown escape sequence"; + template<> inline const std::string errors< rules::unescaped >::error_message = "invalid unescaped character"; + template<> inline const std::string errors< rules::string::content >::error_message = "unterminated string"; + template<> inline const std::string errors< rules::key::content >::error_message = "unterminated key"; + + template<> inline const std::string errors< pegtl::eof >::error_message = "unexpected character after JSON value"; + // clang-format on + +} // namespace tao::json::internal #endif diff --git a/include/tao/json/internal/escape.hpp b/include/tao/json/internal/escape.hpp index 6e254740..a6e68729 100644 --- a/include/tao/json/internal/escape.hpp +++ b/include/tao/json/internal/escape.hpp @@ -1,77 +1,77 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_ESCAPE_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_ESCAPE_HPP +#ifndef TAO_JSON_INTERNAL_ESCAPE_HPP +#define TAO_JSON_INTERNAL_ESCAPE_HPP #include +#include +#include +#include -#include "../external/string_view.hpp" - -namespace tao +namespace tao::json::internal { - namespace json + inline void escape( std::ostream& os, const std::string_view s ) { - namespace internal - { - inline void escape( std::ostream& os, const tao::string_view s ) - { - static const char* h = "0123456789abcdef"; + static const char* h = "0123456789abcdef"; - const char* p = s.data(); - const char* l = p; - const char* const e = s.data() + s.size(); - while( p != e ) { - const unsigned char c = *p; - if( c == '\\' ) { - os.write( l, p - l ); - l = ++p; - os << "\\\\"; - } - else if( c == '"' ) { - os.write( l, p - l ); - l = ++p; - os << "\\\""; - } - else if( c < 32 ) { - os.write( l, p - l ); - l = ++p; - switch( c ) { - case '\b': - os << "\\b"; - break; - case '\f': - os << "\\f"; - break; - case '\n': - os << "\\n"; - break; - case '\r': - os << "\\r"; - break; - case '\t': - os << "\\t"; - break; - default: - os << "\\u00" << h[ ( c & 0xf0 ) >> 4 ] << h[ c & 0x0f ]; - } - } - else if( c == 127 ) { - os.write( l, p - l ); - l = ++p; - os << "\\u007f"; - } - else { - ++p; - } + const char* p = s.data(); + const char* l = p; + const char* const e = s.data() + s.size(); + while( p != e ) { + const unsigned char c = *p; + if( c == '\\' ) { + os.write( l, p - l ); + l = ++p; + os << "\\\\"; + } + else if( c == '"' ) { + os.write( l, p - l ); + l = ++p; + os << "\\\""; + } + else if( c < 32 ) { + os.write( l, p - l ); + l = ++p; + switch( c ) { + case '\b': + os << "\\b"; + break; + case '\f': + os << "\\f"; + break; + case '\n': + os << "\\n"; + break; + case '\r': + os << "\\r"; + break; + case '\t': + os << "\\t"; + break; + default: + os << "\\u00" << h[ ( c & 0xf0 ) >> 4 ] << h[ c & 0x0f ]; } + } + else if( c == 127 ) { os.write( l, p - l ); + l = ++p; + os << "\\u007f"; } + else { + ++p; + } + } + os.write( l, p - l ); + } - } // namespace internal - - } // namespace json + [[nodiscard]] inline std::string escape( const std::string_view s ) + { + std::ostringstream o; + escape( o, s ); + return o.str(); + } -} // namespace tao +} // namespace tao::json::internal #endif diff --git a/include/tao/json/internal/format.hpp b/include/tao/json/internal/format.hpp new file mode 100644 index 00000000..3bf72725 --- /dev/null +++ b/include/tao/json/internal/format.hpp @@ -0,0 +1,59 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_INTERNAL_FORMAT_HPP +#define TAO_JSON_INTERNAL_FORMAT_HPP + +#include +#include +#include + +#include "escape.hpp" + +#include "../forward.hpp" +#include "../message_extension.hpp" +#include "../type.hpp" + +#include "../external/pegtl/internal/demangle.hpp" + +namespace tao::json::internal +{ + inline void to_stream( std::ostream& os, const bool v ) + { + os << ( v ? "true" : "false" ); + } + + inline void to_stream( std::ostream& os, const type t ) + { + os << to_string( t ); + } + + template< typename T > + void to_stream( std::ostream& os, const T& t ) + { + os << t; + } + + template< std::size_t N > + void to_stream( std::ostream& os, const char ( &t )[ N ] ) + { + os.write( t, N - 1 ); + } + + template< typename... Ts > + void format_to( std::ostream& oss, const Ts&... ts ) + { + ( internal::to_stream( oss, ts ), ... ); + } + + template< typename... Ts > + [[nodiscard]] std::string format( const Ts&... ts ) + { + std::ostringstream oss; + format_to( oss, ts... ); + return oss.str(); + } + +} // namespace tao::json::internal + +#endif diff --git a/include/tao/json/internal/get_by_enum.hpp b/include/tao/json/internal/get_by_enum.hpp deleted file mode 100644 index 49758d77..00000000 --- a/include/tao/json/internal/get_by_enum.hpp +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_GET_BY_ENUM_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_GET_BY_ENUM_HPP - -#include - -#include "../type.hpp" - -#include "value_union.hpp" - -namespace tao -{ - namespace json - { - namespace internal - { - template< type > - struct get_by_enum; - - template<> - struct get_by_enum< type::NULL_ > - { - template< typename T > - static null_t get( const value_union< T >& ) noexcept - { - return null; - } - }; - - template<> - struct get_by_enum< type::BOOLEAN > - { - template< typename T > - static bool get( const value_union< T >& u ) noexcept - { - return u.b; - } - }; - - template<> - struct get_by_enum< type::SIGNED > - { - template< typename T > - static std::int64_t get( const value_union< T >& u ) noexcept - { - return u.i; - } - }; - - template<> - struct get_by_enum< type::UNSIGNED > - { - template< typename T > - static std::uint64_t get( const value_union< T >& u ) noexcept - { - return u.u; - } - }; - - template<> - struct get_by_enum< type::DOUBLE > - { - template< typename T > - static double get( const value_union< T >& u ) noexcept - { - return u.d; - } - }; - - template<> - struct get_by_enum< type::STRING > - { - template< typename T > - static std::string& get( value_union< T >& u ) noexcept - { - return u.s; - } - - template< typename T > - static const std::string& get( const value_union< T >& u ) noexcept - { - return u.s; - } - }; - - template<> - struct get_by_enum< type::STRING_VIEW > - { - template< typename T > - static tao::string_view get( const value_union< T >& u ) noexcept - { - return u.sv; - } - }; - - template<> - struct get_by_enum< type::BINARY > - { - template< typename T > - static std::vector< tao::byte >& get( value_union< T >& u ) noexcept - { - return u.x; - } - - template< typename T > - static const std::vector< tao::byte >& get( const value_union< T >& u ) noexcept - { - return u.x; - } - }; - - template<> - struct get_by_enum< type::BINARY_VIEW > - { - template< typename T > - static tao::byte_view get( const value_union< T >& u ) noexcept - { - return u.xv; - } - }; - - template<> - struct get_by_enum< type::ARRAY > - { - template< typename T > - static std::vector< T >& get( value_union< T >& u ) noexcept - { - return u.a; - } - - template< typename T > - static const std::vector< T >& get( const value_union< T >& u ) noexcept - { - return u.a; - } - }; - - template<> - struct get_by_enum< type::OBJECT > - { - template< typename T > - static std::map< std::string, T >& get( value_union< T >& u ) noexcept - { - return u.o; - } - - template< typename T > - static const std::map< std::string, T >& get( const value_union< T >& u ) noexcept - { - return u.o; - } - }; - - template<> - struct get_by_enum< type::RAW_PTR > - { - template< typename T > - static const T* get( const value_union< T >& u ) noexcept - { - return u.p; - } - }; - - } // namespace internal - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/internal/grammar.hpp b/include/tao/json/internal/grammar.hpp index 193e2339..b5919ae6 100644 --- a/include/tao/json/internal/grammar.hpp +++ b/include/tao/json/internal/grammar.hpp @@ -1,238 +1,229 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_GRAMMAR_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_GRAMMAR_HPP +#ifndef TAO_JSON_INTERNAL_GRAMMAR_HPP +#define TAO_JSON_INTERNAL_GRAMMAR_HPP #include "../external/pegtl.hpp" #include "../external/pegtl/contrib/abnf.hpp" -namespace tao +namespace tao::json::internal { - namespace json + // clang-format off + namespace rules { - namespace internal - { - // clang-format off - namespace rules - { - using namespace json_pegtl; + using namespace pegtl; - struct ws : one< ' ', '\t', '\n', '\r' > {}; + struct ws : one< ' ', '\t', '\n', '\r' > {}; - template< typename R, typename P = ws > - using padr = json_pegtl::internal::seq< R, json_pegtl::internal::star< P > >; + template< typename R, typename P = ws > + using padr = pegtl::internal::seq< R, pegtl::internal::star< P > >; - struct begin_array : padr< one< '[' > > {}; - struct begin_object : padr< one< '{' > > {}; - struct end_array : one< ']' > {}; - struct end_object : one< '}' > {}; - struct name_separator : pad< one< ':' >, ws > {}; - struct value_separator : padr< one< ',' > > {}; - struct element_separator : padr< one< ',' > > {}; + struct begin_array : padr< one< '[' > > {}; + struct begin_object : padr< one< '{' > > {}; + struct end_array : one< ']' > {}; + struct end_object : one< '}' > {}; + struct name_separator : pad< one< ':' >, ws > {}; + struct value_separator : padr< one< ',' > > {}; + struct element_separator : padr< one< ',' > > {}; - struct false_ : TAOCPP_JSON_PEGTL_STRING( "false" ) {}; - struct null : TAOCPP_JSON_PEGTL_STRING( "null" ) {}; - struct true_ : TAOCPP_JSON_PEGTL_STRING( "true" ) {}; + struct false_ : pegtl::string< 'f', 'a', 'l', 's', 'e' > {}; + struct null : pegtl::string< 'n', 'u', 'l', 'l' > {}; + struct true_ : pegtl::string< 't', 'r', 'u', 'e' > {}; - struct digits : plus< abnf::DIGIT > {}; + struct digits : plus< abnf::DIGIT > {}; - struct esign : one< '-', '+' > {}; + struct esign : one< '-', '+' > {}; - struct edigits : digits {}; - struct fdigits : digits {}; - struct idigits : digits {}; + struct edigits : digits {}; + struct fdigits : digits {}; + struct idigits : digits {}; - struct exp : seq< one< 'e', 'E' >, opt< esign >, must< edigits > > {}; - struct frac : if_must< one< '.' >, fdigits > {}; + struct exp : seq< one< 'e', 'E' >, opt< esign >, must< edigits > > {}; + struct frac : if_must< one< '.' >, fdigits > {}; - template< bool NEG > - struct number : seq< idigits, opt< frac >, opt< exp > > {}; + template< bool NEG > + struct number : seq< idigits, opt< frac >, opt< exp > > {}; - struct xdigit : abnf::HEXDIG {}; - struct escaped_unicode : list< seq< one< 'u' >, rep< 4, must< xdigit > > >, one< '\\' > > {}; + struct xdigit : abnf::HEXDIG {}; + struct escaped_unicode : list< seq< one< 'u' >, rep< 4, must< xdigit > > >, one< '\\' > > {}; - struct escaped_char : one< '"', '\\', '/', 'b', 'f', 'n', 'r', 't' > {}; - struct escaped : sor< escaped_char, escaped_unicode > {}; + struct escaped_char : one< '"', '\\', '/', 'b', 'f', 'n', 'r', 't' > {}; + struct escaped : sor< escaped_char, escaped_unicode > {}; - struct unescaped - { - using analyze_t = json_pegtl::analysis::generic< json_pegtl::analysis::rule_type::ANY >; - - template< typename Input > - static bool match( Input& in ) - { - bool result = false; + struct unescaped + { + using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; - while( !in.empty() ) { - if( const auto t = json_pegtl::internal::peek_utf8::peek( in ) ) { - if( ( 0x20 <= t.data ) && ( t.data <= 0x10ffff ) && ( t.data != '\\' ) && ( t.data != '"' ) ) { - in.bump_in_this_line( t.size ); - result = true; - continue; - } - } - return result; - } - throw json_pegtl::parse_error( "invalid character in string", in ); - } - }; - - struct chars : if_then_else< one< '\\' >, must< escaped >, unescaped > {}; - - struct string_content : until< at< one< '"' > >, must< chars > > {}; - struct string : seq< one< '"' >, must< string_content >, any > - { - using content = string_content; - }; - - struct key_content : string_content {}; - struct key : seq< one< '"' >, must< key_content >, any > - { - using content = key_content; - }; - - struct value; - - struct array_element; - struct array_content : opt< list_must< array_element, element_separator > > {}; - struct array : seq< begin_array, array_content, must< end_array > > - { - using begin = begin_array; - using end = end_array; - using element = array_element; - using content = array_content; - }; - - struct member : if_must< key, name_separator, value > {}; - struct object_content : opt< list_must< member, value_separator > > {}; - struct object : seq< begin_object, object_content, must< end_object > > - { - using begin = begin_object; - using end = end_object; - using element = member; - using content = object_content; - }; - - template< bool NEG > - struct zero {}; - - struct sor_value - { - using analyze_t = json_pegtl::analysis::generic< json_pegtl::analysis::rule_type::SOR, string, number< false >, object, array, false_, true_, null >; - - template< bool NEG, - apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match_zero( Input& in, States&&... st ) - { - if( in.size( 2 ) > 1 ) { - switch( in.peek_char( 1 ) ) { - case '.': - case 'e': - case 'E': - return Control< number< NEG > >::template match< A, M, Action, Control >( in, st... ); - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - throw json_pegtl::parse_error( "invalid leading zero", in ); - } + template< typename Input > + [[nodiscard]] static bool match( Input& in ) + { + bool result = false; + + while( const std::size_t s = in.size( 4 ) ) { + if( const auto t = pegtl::internal::peek_utf8::peek( in, s ) ) { + if( ( 0x20 <= t.data ) && ( t.data != '\\' ) && ( t.data != '"' ) ) { + in.bump_in_this_line( t.size ); + result = true; + continue; } - in.bump_in_this_line(); - Control< zero< NEG > >::template apply0< Action >( in, st... ); - return true; } + break; + } + return result; + } + }; - template< bool NEG, - apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match_number( Input& in, States&&... st ) - { - if( in.peek_char() == '0' ) { - if( !match_zero< NEG, A, rewind_mode::DONTCARE, Action, Control >( in, st... ) ) { - throw json_pegtl::parse_error( "incomplete number", in ); - } - return true; - } - else { - return Control< number< NEG > >::template match< A, M, Action, Control >( in, st... ); - } - } + struct chars : if_must_else< one< '\\' >, escaped, unescaped > {}; - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match_impl( Input& in, States&&... st ) - { - switch( in.peek_char() ) { - case '"': return Control< string >::template match< A, M, Action, Control >( in, st... ); - case '{': return Control< object >::template match< A, M, Action, Control >( in, st... ); - case '[': return Control< array >::template match< A, M, Action, Control >( in, st... ); - case 'n': return Control< null >::template match< A, M, Action, Control >( in, st... ); - case 't': return Control< true_ >::template match< A, M, Action, Control >( in, st... ); - case 'f': return Control< false_ >::template match< A, M, Action, Control >( in, st... ); - - case '-': - in.bump_in_this_line(); - if( in.empty() || !match_number< true, A, rewind_mode::DONTCARE, Action, Control >( in, st... ) ) { - throw json_pegtl::parse_error( "incomplete number", in ); - } - return true; - - default: - return match_number< false, A, M, Action, Control >( in, st... ); - } - } + struct string_content : until< at< one< '"' > >, chars > {}; + struct string : seq< one< '"' >, must< string_content >, any > + { + using content = string_content; + }; - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - if( in.size( 2 ) && match_impl< A, M, Action, Control >( in, st... ) ) { - in.discard(); - return true; - } - return false; - } - }; + struct key_content : string_content {}; + struct key : seq< one< '"' >, must< key_content >, any > + { + using content = key_content; + }; - struct value : padr< sor_value > {}; - struct array_element : value {}; + struct value; - struct text : seq< star< ws >, value > {}; + struct array_element; + struct array_content : opt< list_must< array_element, element_separator > > {}; + struct array : seq< begin_array, array_content, must< end_array > > + { + using begin = begin_array; + using end = end_array; + using element = array_element; + using content = array_content; + }; + + struct member : if_must< key, name_separator, value > {}; + struct object_content : opt< list_must< member, value_separator > > {}; + struct object : seq< begin_object, object_content, must< end_object > > + { + using begin = begin_object; + using end = end_object; + using element = member; + using content = object_content; + }; + + template< bool NEG > + struct zero {}; + + struct sor_value + { + using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::sor, string, number< false >, object, array, false_, true_, null >; + + template< bool NEG, + apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match_zero( Input& in, States&&... st ) + { + if( in.size( 2 ) > 1 ) { + switch( in.peek_char( 1 ) ) { + case '.': + case 'e': + case 'E': + return Control< number< NEG > >::template match< A, M, Action, Control >( in, st... ); + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + throw pegtl::parse_error( "invalid leading zero", in ); + } + } + in.bump_in_this_line(); + Control< zero< NEG > >::template apply0< Action >( in, st... ); + return true; + } + + template< bool NEG, + apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match_number( Input& in, States&&... st ) + { + if( in.peek_char() == '0' ) { + if( !match_zero< NEG, A, rewind_mode::dontcare, Action, Control >( in, st... ) ) { + throw pegtl::parse_error( "incomplete number", in ); + } + return true; + } + return Control< number< NEG > >::template match< A, M, Action, Control >( in, st... ); + } + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match_impl( Input& in, States&&... st ) + { + switch( in.peek_char() ) { + case '"': return Control< string >::template match< A, M, Action, Control >( in, st... ); + case '{': return Control< object >::template match< A, M, Action, Control >( in, st... ); + case '[': return Control< array >::template match< A, M, Action, Control >( in, st... ); + case 'n': return Control< null >::template match< A, M, Action, Control >( in, st... ); + case 't': return Control< true_ >::template match< A, M, Action, Control >( in, st... ); + case 'f': return Control< false_ >::template match< A, M, Action, Control >( in, st... ); + + case '-': + in.bump_in_this_line(); + if( in.empty() || !match_number< true, A, rewind_mode::dontcare, Action, Control >( in, st... ) ) { + throw pegtl::parse_error( "incomplete number", in ); + } + return true; + + default: + return match_number< false, A, M, Action, Control >( in, st... ); + } + } + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + if( in.size( 2 ) && match_impl< A, M, Action, Control >( in, st... ) ) { + in.discard(); + return true; + } + return false; + } + }; - } // namespace rules + struct value : padr< sor_value > {}; + struct array_element : value {}; - struct grammar : json_pegtl::must< rules::text, json_pegtl::eof > {}; - // clang-format on + struct text : seq< star< ws >, value > {}; - } // namespace internal + } // namespace rules - } // namespace json + struct grammar : pegtl::must< rules::text, pegtl::eof > {}; + struct embedded : pegtl::must< rules::sor_value > {}; + // clang-format on -} // namespace tao +} // namespace tao::json::internal #endif diff --git a/include/tao/json/internal/hexdump.hpp b/include/tao/json/internal/hexdump.hpp index 3634ece4..5e87e76c 100644 --- a/include/tao/json/internal/hexdump.hpp +++ b/include/tao/json/internal/hexdump.hpp @@ -1,39 +1,31 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_HEXDUMP_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_HEXDUMP_HPP +#ifndef TAO_JSON_INTERNAL_HEXDUMP_HPP +#define TAO_JSON_INTERNAL_HEXDUMP_HPP #include -namespace tao +namespace tao::json::internal { - namespace json + template< typename T > + void hexdump( std::ostream& os, const T& v ) { - namespace internal - { - template< typename T > - void hexdump( std::ostream& os, const T& v ) - { - static const char h[] = "0123456789ABCDEF"; - for( const auto b : v ) { - os.put( h[ static_cast< unsigned char >( b ) >> 4 ] ); - os.put( h[ static_cast< unsigned char >( b ) & 0xF ] ); - } - } - - template< typename T > - std::string hexdump( const T& v ) - { - std::ostringstream os; - internal::hexdump( os, v ); - return os.str(); - } - - } // namespace internal - - } // namespace json + static const char h[] = "0123456789ABCDEF"; + for( const auto b : v ) { + os.put( h[ static_cast< unsigned char >( b ) >> 4 ] ); + os.put( h[ static_cast< unsigned char >( b ) & 0xF ] ); + } + } + + template< typename T > + [[nodiscard]] std::string hexdump( const T& v ) + { + std::ostringstream os; + internal::hexdump( os, v ); + return os.str(); + } -} // namespace tao +} // namespace tao::json::internal #endif diff --git a/include/tao/json/internal/identity.hpp b/include/tao/json/internal/identity.hpp index 20e7f614..2f470e75 100644 --- a/include/tao/json/internal/identity.hpp +++ b/include/tao/json/internal/identity.hpp @@ -1,20 +1,22 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_INCLUDE_INTERNAL_IDENTITY_HPP -#define TAOCPP_INCLUDE_INTERNAL_IDENTITY_HPP +#ifndef TAO_JSON_INTERNAL_IDENTITY_HPP +#define TAO_JSON_INTERNAL_IDENTITY_HPP #include -namespace tao +namespace tao::internal { - namespace internal + template< typename T > + struct identity { - template< typename T > - using identity = typename std::decay< T >::type; + using type = T; + }; - } // namespace internal + template< typename T > + using identity_t = typename identity< T >::type; -} // namespace tao +} // namespace tao::internal #endif diff --git a/include/tao/json/internal/jaxn/action.hpp b/include/tao/json/internal/jaxn/action.hpp deleted file mode 100644 index 4ad31cb2..00000000 --- a/include/tao/json/internal/jaxn/action.hpp +++ /dev/null @@ -1,335 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_ACTION_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_ACTION_HPP - -#include "../../external/pegtl/nothing.hpp" -#include "../../external/string_view.hpp" - -#include "errors.hpp" -#include "grammar.hpp" - -#include "../number_state.hpp" - -namespace tao -{ - namespace json - { - namespace internal - { - namespace jaxn - { - template< typename Rule > - struct action - : json_pegtl::nothing< Rule > - { - }; - - template<> - struct action< rules::null > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.null(); - } - }; - - template<> - struct action< rules::true_ > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.boolean( true ); - } - }; - - template<> - struct action< rules::false_ > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.boolean( false ); - } - }; - - template<> - struct action< rules::identifier > - { - template< typename Input, typename Consumer > - static void apply( const Input& in, Consumer& consumer ) - { - consumer.key( tao::string_view( in.begin(), in.size() ) ); - } - }; - - template< bool NEG > - struct action< rules::hexnum< NEG > > - { - static char unhex( const char c ) - { - if( ( '0' <= c ) && ( c <= '9' ) ) { - return c - '0'; - } - if( ( 'a' <= c ) && ( c <= 'f' ) ) { - return c - 'a' + 10; - } - if( ( 'A' <= c ) && ( c <= 'F' ) ) { - return c - 'A' + 10; - } - // LCOV_EXCL_START - assert( false ); - return false; - // LCOV_EXCL_STOP - } - - template< typename Input, typename Consumer > - static void apply( const Input& in, Consumer& consumer ) - { - std::uint64_t value = 0; - for( char c : in ) { - if( value & 0xF000000000000000 ) { - throw std::runtime_error( "JAXN hexadecimal number too large" ); - } - value <<= 4; - value += unhex( c ); - } - if( NEG ) { - if( value < 9223372036854775808ull ) { - consumer.number( -static_cast< std::int64_t >( value ) ); - } - else if( value == 9223372036854775808ull ) { - consumer.number( static_cast< std::int64_t >( -9223372036854775807ll - 1 ) ); - } - else { - throw std::runtime_error( "JAXN hexadecimal number too large to negate" ); - } - } - else { - consumer.number( value ); - } - } - }; - - template<> - struct action< rules::array::begin > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.begin_array(); - } - }; - - template<> - struct action< rules::array::element > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.element(); - } - }; - - template<> - struct action< rules::array::end > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.end_array(); - } - }; - - template<> - struct action< rules::object::begin > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.begin_object(); - } - }; - - template<> - struct action< rules::object::element > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.member(); - } - }; - - template<> - struct action< rules::object::end > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.end_object(); - } - }; - - template<> - struct action< rules::zero< false > > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.number( std::uint64_t( 0 ) ); - } - }; - - template<> - struct action< rules::zero< true > > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.number( std::int64_t( 0 ) ); - } - }; - - template<> - struct action< rules::nan > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.number( NAN ); - } - }; - - template<> - struct action< rules::infinity< false > > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.number( INFINITY ); - } - }; - - template<> - struct action< rules::infinity< true > > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.number( -INFINITY ); - } - }; - - template<> - struct action< rules::esign > - { - template< typename Input, bool NEG > - static void apply( const Input& in, number_state< NEG >& result ) - { - result.eneg = ( in.peek_char() == '-' ); - } - }; - - template<> - struct action< rules::idigits > - { - template< typename Input, bool NEG > - static void apply( const Input& in, number_state< NEG >& result ) - { - const auto s = in.size(); - - if( s == 1 && in.peek_char() == '0' ) { - return; - } - - if( s > ( 1 << 20 ) ) { - throw std::runtime_error( "JSON number with 1 megabyte digits" ); - } - - const auto c = std::min( s, max_mantissa_digits ); - std::memcpy( result.mantissa, in.begin(), c ); - result.exponent10 += static_cast< typename number_state< NEG >::exponent10_t >( s - c ); - result.msize = static_cast< typename number_state< NEG >::msize_t >( c ); - - for( std::size_t i = c; i < s; ++i ) { - if( in.peek_char( i ) != '0' ) { - result.drop = true; - return; - } - } - } - }; - - template<> - struct action< rules::fdigits > - { - template< typename Input, bool NEG > - static void apply( const Input& in, number_state< NEG >& result ) - { - result.isfp = true; - - const auto* b = in.begin(); - const auto* e = in.end(); - - while( ( e > b ) && ( e[ -1 ] == '0' ) ) { - --e; - } - if( !result.msize ) { - while( ( b < e ) && ( b[ 0 ] == '0' ) ) { - ++b; - --result.exponent10; - } - } - const auto c = std::min( std::size_t( e - b ), max_mantissa_digits - result.msize ); - std::memcpy( result.mantissa + result.msize, b, c ); - result.exponent10 -= static_cast< typename number_state< NEG >::exponent10_t >( c ); - result.msize += static_cast< typename number_state< NEG >::msize_t >( c ); - - for( const auto* r = b + c; r < e; ++r ) { - if( *r != '0' ) { - result.drop = true; - return; - } - } - } - }; - - template<> - struct action< rules::edigits > - { - template< typename Input, bool NEG > - static void apply( const Input& in, number_state< NEG >& result ) - { - result.isfp = true; - - const char* b = in.begin(); - - while( ( b < in.end() ) && ( b[ 0 ] == '0' ) ) { - ++b; - } - if( ( in.end() - b ) > 9 ) { - throw std::runtime_error( "JSON exponent has more than 9 significant digits" ); - } - int exponent10 = 0; - - while( b < in.end() ) { - exponent10 = ( exponent10 * 10 ) + ( b[ 0 ] - '0' ); - ++b; - } - result.exponent10 += ( result.eneg ? -exponent10 : exponent10 ); - } - }; - - } // namespace jaxn - - } // namespace internal - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/internal/jaxn/binary_state.hpp b/include/tao/json/internal/jaxn/binary_state.hpp deleted file mode 100644 index f5776bfa..00000000 --- a/include/tao/json/internal/jaxn/binary_state.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_BINARY_STATE_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_BINARY_STATE_HPP - -#include -#include - -#include "../../external/byte.hpp" - -namespace tao -{ - namespace json - { - namespace internal - { - namespace jaxn - { - struct binary_state - { - binary_state() = default; - binary_state( const binary_state& ) = delete; - void operator=( const binary_state& ) = delete; - - template< typename Consumer > - void success( Consumer& consumer ) - { - consumer.binary( std::move( value ) ); - } - - std::vector< tao::byte > value; - }; - - } // namespace jaxn - - } // namespace internal - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/internal/jaxn/bunescape_action.hpp b/include/tao/json/internal/jaxn/bunescape_action.hpp deleted file mode 100644 index 45cbbeac..00000000 --- a/include/tao/json/internal/jaxn/bunescape_action.hpp +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_BUNESCAPE_ACTION_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_BUNESCAPE_ACTION_HPP - -#include "../../external/pegtl/contrib/unescape.hpp" -#include "../../external/pegtl/nothing.hpp" - -#include "grammar.hpp" - -namespace tao -{ - namespace json - { - namespace internal - { - namespace jaxn - { - template< typename Rule > - struct bunescape_action : json_pegtl::nothing< Rule > - { - }; - - template<> - struct bunescape_action< rules::bescaped_char > - { - template< typename Input, typename State > - static void apply( const Input& in, State& st ) - { - switch( *in.begin() ) { - case '"': - st.value.push_back( tao::byte( '"' ) ); - break; - - case '\'': - st.value.push_back( tao::byte( '\'' ) ); - break; - - case '\\': - st.value.push_back( tao::byte( '\\' ) ); - break; - - case '/': - st.value.push_back( tao::byte( '/' ) ); - break; - - case 'b': - st.value.push_back( tao::byte( '\b' ) ); - break; - - case 'f': - st.value.push_back( tao::byte( '\f' ) ); - break; - - case 'n': - st.value.push_back( tao::byte( '\n' ) ); - break; - - case 'r': - st.value.push_back( tao::byte( '\r' ) ); - break; - - case 't': - st.value.push_back( tao::byte( '\t' ) ); - break; - - case 'v': - st.value.push_back( tao::byte( '\v' ) ); - break; - - case '0': - st.value.push_back( tao::byte( '\0' ) ); - break; - - default: - throw std::runtime_error( "invalid character in unescape" ); // LCOV_EXCL_LINE - } - } - }; - - template<> - struct bunescape_action< rules::bescaped_hexcode > - { - template< typename Input, typename State > - static void apply( const Input& in, State& st ) - { - assert( !in.empty() ); // First character MUST be present, usually 'x'. - st.value.push_back( static_cast< tao::byte >( json_pegtl::unescape::unhex_string< char >( in.begin() + 1, in.end() ) ) ); - } - }; - - template< char D > - struct bunescape_action< rules::bunescaped< D > > - { - template< typename Input, typename State > - static void apply( const Input& in, State& st ) - { - const auto begin = reinterpret_cast< const tao::byte* >( in.begin() ); - const auto end = begin + in.size(); - st.value.insert( st.value.end(), begin, end ); - } - }; - - template<> - struct bunescape_action< rules::bbyte > - { - template< typename Input, typename State > - static void apply( const Input& in, State& st ) - { - st.value.push_back( static_cast< tao::byte >( json_pegtl::unescape::unhex_string< char >( in.begin(), in.end() ) ) ); - } - }; - - } // namespace jaxn - - } // namespace internal - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/internal/jaxn/control.hpp b/include/tao/json/internal/jaxn/control.hpp deleted file mode 100644 index a36128a7..00000000 --- a/include/tao/json/internal/jaxn/control.hpp +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_CONTROL_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_CONTROL_HPP - -#include "../../external/pegtl/contrib/changes.hpp" - -#include "binary_state.hpp" -#include "bunescape_action.hpp" -#include "errors.hpp" -#include "unescape_action.hpp" - -#include "../key_state.hpp" -#include "../number_state.hpp" -#include "../string_state.hpp" - -namespace tao -{ - namespace json - { - namespace internal - { - namespace jaxn - { - template< typename Rule > - struct control - : errors< Rule > - { - }; - - template< bool NEG > - struct control< rules::number< NEG > > - : json_pegtl::change_state< rules::number< NEG >, number_state< NEG >, errors > - { - }; - - template<> - struct control< rules::string > - : json_pegtl::change_state_and_action< rules::string, string_state, unescape_action, errors > - { - }; - - template<> - struct control< rules::key > - : json_pegtl::change_state_and_action< rules::key, key_state, unescape_action, errors > - { - }; - - template<> - struct control< rules::binary > - : json_pegtl::change_state_and_action< rules::binary, binary_state, bunescape_action, errors > - { - }; - - } // namespace jaxn - - } // namespace internal - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/internal/jaxn/errors.hpp b/include/tao/json/internal/jaxn/errors.hpp deleted file mode 100644 index b8c8b3f6..00000000 --- a/include/tao/json/internal/jaxn/errors.hpp +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_ERRORS_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_ERRORS_HPP - -#include - -#include "../../external/pegtl/normal.hpp" -#include "../../external/pegtl/parse_error.hpp" - -#include "grammar.hpp" - -#if defined( _MSC_VER ) -#define WEAK_PREFIX __declspec( selectany ) -#define WEAK_SUFFIX -#else -#define WEAK_PREFIX -#define WEAK_SUFFIX __attribute__( ( weak ) ) -#endif - -namespace tao -{ - namespace json - { - namespace internal - { - namespace jaxn - { - template< typename Rule > - struct errors - : json_pegtl::normal< Rule > - { - static const std::string error_message; - - template< typename Input, typename... States > - static void raise( const Input& in, States&&... ) - { - throw json_pegtl::parse_error( error_message, in ); - } - - template< template< typename... > class Action, typename Input, typename... States > - static void apply0( const Input& in, States&&... st ) - { - try { - Action< Rule >::apply0( st... ); - } - catch( const json_pegtl::parse_error& ) { - throw; - } - catch( const std::exception& e ) { - throw json_pegtl::parse_error( e.what(), in ); - } - } - - template< template< typename... > class Action, typename Iterator, typename Input, typename... States > - static void apply( const Iterator& begin, const Input& in, States&&... st ) - { - try { - using action_t = typename Input::action_t; - const action_t action_input( begin, in ); - Action< Rule >::apply( action_input, st... ); - } - catch( const json_pegtl::parse_error& ) { - throw; - } - catch( const std::exception& e ) { - throw json_pegtl::parse_error( e.what(), in ); - } - } - }; - - // clang-format off - template<> WEAK_PREFIX const std::string errors< rules::text >::error_message WEAK_SUFFIX = "no valid JAXN"; - - template<> WEAK_PREFIX const std::string errors< rules::comment >::error_message WEAK_SUFFIX = "expected '*' or '/'"; - template<> WEAK_PREFIX const std::string errors< rules::line_comment_char >::error_message WEAK_SUFFIX = "invalid character in line comment"; - template<> WEAK_PREFIX const std::string errors< rules::block_comment_char >::error_message WEAK_SUFFIX = "invalid character in block comment"; - template<> WEAK_PREFIX const std::string errors< rules::end_block_comment >::error_message WEAK_SUFFIX = "unterminated multi-line comment"; - - template<> WEAK_PREFIX const std::string errors< rules::end_array >::error_message WEAK_SUFFIX = "incomplete array, expected value or ']'"; - template<> WEAK_PREFIX const std::string errors< rules::end_object >::error_message WEAK_SUFFIX = "incomplete object, expected key or '}'"; - template<> WEAK_PREFIX const std::string errors< rules::name_separator >::error_message WEAK_SUFFIX = "expected ':'"; - template<> WEAK_PREFIX const std::string errors< rules::value >::error_message WEAK_SUFFIX = "expected value"; - - template<> WEAK_PREFIX const std::string errors< rules::edigits >::error_message WEAK_SUFFIX = "expected at least one exponent digit"; - template<> WEAK_PREFIX const std::string errors< rules::fdigits >::error_message WEAK_SUFFIX = "expected at least one fraction digit"; - template<> WEAK_PREFIX const std::string errors< rules::nan >::error_message WEAK_SUFFIX = "invalid numeric literal"; - template<> WEAK_PREFIX const std::string errors< rules::infinity< false > >::error_message WEAK_SUFFIX = "invalid numeric literal"; - template<> WEAK_PREFIX const std::string errors< rules::infinity< true > >::error_message WEAK_SUFFIX = "invalid numeric literal"; - template<> WEAK_PREFIX const std::string errors< rules::hexnum< false > >::error_message WEAK_SUFFIX = "expected at least one hexadecimal digit"; - template<> WEAK_PREFIX const std::string errors< rules::hexnum< true > >::error_message WEAK_SUFFIX = "expected at least one hexadecimal digit"; - - template<> WEAK_PREFIX const std::string errors< rules::xdigit >::error_message WEAK_SUFFIX = "incomplete universal character name"; - template<> WEAK_PREFIX const std::string errors< rules::escaped >::error_message WEAK_SUFFIX = "unknown escape sequence in string"; - template<> WEAK_PREFIX const std::string errors< rules::chars< '"' > >::error_message WEAK_SUFFIX = "invalid character in string"; - template<> WEAK_PREFIX const std::string errors< rules::chars< '\'' > >::error_message WEAK_SUFFIX = "invalid character in string"; - template<> WEAK_PREFIX const std::string errors< rules::qstring_content< '"' > >::error_message WEAK_SUFFIX = "unterminated string"; - template<> WEAK_PREFIX const std::string errors< rules::qstring_content< '\'' > >::error_message WEAK_SUFFIX = "unterminated string"; - template<> WEAK_PREFIX const std::string errors< rules::string_fragment >::error_message WEAK_SUFFIX = "expected string"; - - template<> WEAK_PREFIX const std::string errors< rules::bescaped >::error_message WEAK_SUFFIX = "unknown escape sequence in binary string"; - template<> WEAK_PREFIX const std::string errors< rules::bchars< '"' > >::error_message WEAK_SUFFIX = "invalid character in binary string"; - template<> WEAK_PREFIX const std::string errors< rules::bchars< '\'' > >::error_message WEAK_SUFFIX = "invalid character in binary string"; - template<> WEAK_PREFIX const std::string errors< rules::bqstring_content< '"' > >::error_message WEAK_SUFFIX = "unterminated binary string"; - template<> WEAK_PREFIX const std::string errors< rules::bqstring_content< '\'' > >::error_message WEAK_SUFFIX = "unterminated binary string"; - template<> WEAK_PREFIX const std::string errors< rules::bvalue >::error_message WEAK_SUFFIX = "expected binary"; - template<> WEAK_PREFIX const std::string errors< rules::bpart >::error_message WEAK_SUFFIX = "expected a pair of hexadecimal digits"; - - template<> WEAK_PREFIX const std::string errors< json_pegtl::eof >::error_message WEAK_SUFFIX = "unexpected character after JAXN value"; - // clang-format on - - } // namespace jaxn - - } // namespace internal - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/internal/jaxn/grammar.hpp b/include/tao/json/internal/jaxn/grammar.hpp deleted file mode 100644 index 88ef5c42..00000000 --- a/include/tao/json/internal/jaxn/grammar.hpp +++ /dev/null @@ -1,357 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_GRAMMAR_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_GRAMMAR_HPP - -#include "../../external/pegtl.hpp" -#include "../../external/pegtl/contrib/abnf.hpp" - -namespace tao -{ - namespace json - { - namespace internal - { - namespace jaxn - { - // clang-format off - namespace rules - { - using namespace json_pegtl; - - struct line_comment_char : sor< one< '\t' >, utf8::range< 0x20, 0x10FFFF > > {}; - struct line_comment : seq< one< '/' >, until< eolf, must< line_comment_char > > > {}; - - struct block_comment_char : sor< one< '\t' >, utf8::range< 0x20, 0x10FFFF >, eol > {}; - struct end_block_comment : until< json_pegtl::string< '*', '/' >, must< block_comment_char > > {}; - struct block_comment : if_must< one< '*' >, end_block_comment > {}; - - struct comment : sor< line_comment, block_comment > {}; - - struct ws : sor< one< ' ', '\t', '\n', '\r' >, seq< one< '#' >, until< eolf > >, if_must< one< '/' >, comment > > {}; - - template< typename R, typename P = ws > - using padr = json_pegtl::internal::seq< R, json_pegtl::internal::star< P > >; - - struct begin_array : padr< one< '[' > > {}; - struct begin_object : padr< one< '{' > > {}; - struct end_array : one< ']' > {}; - struct end_object : one< '}' > {}; - struct name_separator : pad< one< ':' >, ws > {}; - struct value_separator : padr< one< ',' > > {}; - struct element_separator : padr< one< ',' > > {}; - struct value_concat : pad< one< '+' >, ws > {}; - - struct false_ : TAOCPP_JSON_PEGTL_STRING( "false" ) {}; - struct null : TAOCPP_JSON_PEGTL_STRING( "null" ) {}; - struct true_ : TAOCPP_JSON_PEGTL_STRING( "true" ) {}; - - struct nan : TAOCPP_JSON_PEGTL_STRING( "NaN" ) {}; - - template< bool NEG > - struct infinity : TAOCPP_JSON_PEGTL_STRING( "Infinity" ) {}; - - template< bool NEG > - struct hexnum : plus< abnf::HEXDIG > {}; - - struct digits : plus< abnf::DIGIT > {}; - - struct esign : one< '-', '+' > {}; - - struct edigits : digits {}; - struct fdigits : digits {}; - struct idigits : digits {}; - - struct exp : seq< one< 'e', 'E' >, opt< esign >, must< edigits > > {}; - struct frac0 : seq< one< '.' >, opt< fdigits > > {}; - struct frac1 : if_must< one< '.' >, fdigits > {}; - - template< bool NEG > - struct number : seq< sor< seq< idigits, opt< frac0 > >, frac1 >, opt< exp > > {}; - - struct xdigit : abnf::HEXDIG {}; - struct escaped_unicode_code_point_content : seq< one< '{' >, plus< xdigit > > {}; - struct escaped_unicode_code_point : seq< one< 'u' >, escaped_unicode_code_point_content, one< '}' > > {}; - struct escaped_unicode : list< seq< one< 'u' >, rep< 4, xdigit > >, one< '\\' > > {}; - - struct escaped_char : one< '"', '\'', '\\', '/', 'b', 'f', 'n', 'r', 't', 'v', '0' > {}; - struct escaped : sor< escaped_char, escaped_unicode_code_point, escaped_unicode > {}; - - template< char D > - struct unescaped - { - using analyze_t = json_pegtl::analysis::generic< json_pegtl::analysis::rule_type::ANY >; - - template< typename Input > - static bool match( Input& in ) - { - bool result = false; - - while( !in.empty() ) { - if( const auto t = json_pegtl::internal::peek_utf8::peek( in ) ) { - if( ( 0x20 <= t.data ) && ( t.data <= 0x10FFFF ) && ( t.data != '\\' ) && ( t.data != D ) ) { - in.bump_in_this_line( t.size ); - result = true; - continue; - } - } - return result; - } - throw json_pegtl::parse_error( "invalid character in string", in ); - } - }; - - template< char D > - struct chars : if_then_else< one< '\\' >, must< escaped >, unescaped< D > > {}; - - template< char D > - struct qstring_content : until< at< one< D > >, must< chars< D > > > {}; - - template< char D > - struct qstring : seq< one< D >, must< qstring_content< D > >, any > {}; - - struct string_fragment : sor< qstring< '"' >, qstring< '\'' > > {}; - - struct string : list_must< string_fragment, value_concat > {}; - - struct binary_prefix : one< '$' > {}; - - struct bescaped_hexcode : seq< one< 'x' >, rep< 2, must< xdigit > > > {}; - - struct bescaped_char : one< '"', '\'', '\\', '/', 'b', 'f', 'n', 'r', 't', 'v', '0' > {}; - struct bescaped : sor< bescaped_char, bescaped_hexcode > {}; - - template< char D > - struct bunescaped - { - using analyze_t = json_pegtl::analysis::generic< json_pegtl::analysis::rule_type::ANY >; - - template< typename Input > - static bool match( Input& in ) - { - bool result = false; - - while( !in.empty() ) { - const auto t = in.peek_char(); - if( ( 0x20 <= t ) && ( t <= 0x7E ) && ( t != '\\' ) && ( t != D ) ) { - in.bump_in_this_line( 1 ); - result = true; - continue; - } - return result; - } - throw json_pegtl::parse_error( "invalid character in binary string", in ); - } - }; - - template< char D > - struct bchars : if_then_else< one< '\\' >, must< bescaped >, bunescaped< D > > {}; - - template< char D > - struct bqstring_content : until< at< one< D > >, must< bchars< D > > > {}; - - template< char D > - struct bqstring : seq< one< D >, must< bqstring_content< D > >, any > {}; - - struct bstring : sor< bqstring< '"' >, bqstring< '\'' > > {}; - - struct bbyte : rep< 2, abnf::HEXDIG > {}; - - struct bpart : plus< bbyte > {}; - - struct bdirect : list_must< bpart, one< '.' > > {}; - - struct bvalue : seq< binary_prefix, opt< sor< bstring, bdirect > > > {}; - - struct binary : list_must< bvalue, value_concat > {}; - - struct value; - - struct array_element; - struct array_content : opt< list_tail< array_element, element_separator > > {}; - struct array : seq< begin_array, array_content, must< end_array > > - { - using begin = begin_array; - using end = end_array; - using element = array_element; - using content = array_content; - }; - - struct key : string {}; - - struct identifier_first : ranges< 'a', 'z', 'A', 'Z', '_', '_', '$' > {}; - struct identifier_other : ranges< 'a', 'z', 'A', 'Z', '0', '9', '_', '_', '$' > {}; - struct identifier : seq< identifier_first, star< identifier_other > > {}; - - struct mkey : sor< key, identifier > {}; - struct member : if_must< mkey, name_separator, value > {}; - struct object_content : opt< list_tail< member, value_separator > > {}; - struct object : seq< begin_object, object_content, must< end_object > > - { - using begin = begin_object; - using end = end_object; - using element = member; - using content = object_content; - }; - - template< bool NEG > - struct zero {}; - - struct sor_value - { - using analyze_t = json_pegtl::analysis::generic< json_pegtl::analysis::rule_type::SOR, string, number< false >, object, array, false_, true_, null >; - - template< typename Rule, - apply_mode A, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match_must( Input& in, States&&... st ) - { - return Control< must< Rule > >::template match< A, rewind_mode::DONTCARE, Action, Control >( in, st... ); - } - - template< bool NEG, - apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match_zero( Input& in, States&&... st ) - { - if( in.size( 2 ) > 1 ) { - switch( in.peek_char( 1 ) ) { - case '.': - case 'e': - case 'E': - return Control< number< NEG > >::template match< A, M, Action, Control >( in, st... ); - - case 'x': - case 'X': - in.bump_in_this_line( 2 ); - return Control< must< hexnum< NEG > > >::template match< A, M, Action, Control >( in, st... ); - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - throw json_pegtl::parse_error( "invalid leading zero", in ); - } - } - in.bump_in_this_line(); - Control< zero< NEG > >::template apply0< Action >( in, st... ); - return true; - } - - template< bool NEG, - apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match_number( Input& in, States&&... st ) - { - switch( in.peek_char() ) { - case 'N': - return Control< must< nan > >::template match< A, M, Action, Control >( in, st... ); - - case 'I': - return Control< must< infinity< NEG > > >::template match< A, M, Action, Control >( in, st... ); - - case '0': - if( !match_zero< NEG, A, rewind_mode::DONTCARE, Action, Control >( in, st... ) ) { - throw json_pegtl::parse_error( "incomplete number", in ); - } - return true; - - default: - return Control< number< NEG > >::template match< A, M, Action, Control >( in, st... ); - } - } - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match_impl( Input& in, States&&... st ) - { - switch( in.peek_char() ) { - case '{': return Control< object >::template match< A, M, Action, Control >( in, st... ); - case '[': return Control< array >::template match< A, M, Action, Control >( in, st... ); - case 'n': return Control< null >::template match< A, M, Action, Control >( in, st... ); - case 't': return Control< true_ >::template match< A, M, Action, Control >( in, st... ); - case 'f': return Control< false_ >::template match< A, M, Action, Control >( in, st... ); - - case '"': - case '\'': - return Control< string >::template match< A, M, Action, Control >( in, st... ); - - case '$': - return Control< binary >::template match< A, M, Action, Control >( in, st... ); - - case '+': - in.bump_in_this_line(); - if( in.empty() || !match_number< false, A, rewind_mode::DONTCARE, Action, Control >( in, st... ) ) { - throw json_pegtl::parse_error( "incomplete number", in ); - } - return true; - - case '-': - in.bump_in_this_line(); - if( in.empty() || !match_number< true, A, rewind_mode::DONTCARE, Action, Control >( in, st... ) ) { - throw json_pegtl::parse_error( "incomplete number", in ); - } - return true; - - default: - return match_number< false, A, M, Action, Control >( in, st... ); - } - } - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - static bool match( Input& in, States&&... st ) - { - if( in.size( 2 ) && match_impl< A, M, Action, Control >( in, st... ) ) { - in.discard(); - return true; - } - return false; - } - }; - - struct value : padr< sor_value > {}; - struct array_element : value {}; - - struct text : seq< star< ws >, value > {}; - - } // namespace rules - - struct grammar : json_pegtl::must< rules::text, json_pegtl::eof > {}; - // clang-format on - - } // namespace jaxn - - } // namespace internal - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/internal/jaxn/unescape_action.hpp b/include/tao/json/internal/jaxn/unescape_action.hpp deleted file mode 100644 index 401e3172..00000000 --- a/include/tao/json/internal/jaxn/unescape_action.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_UNESCAPE_ACTION_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_JAXN_UNESCAPE_ACTION_HPP - -#include "../../external/pegtl/contrib/unescape.hpp" -#include "../../external/pegtl/nothing.hpp" - -#include "grammar.hpp" - -namespace tao -{ - namespace json - { - namespace internal - { - namespace jaxn - { - // clang-format off - template< typename Rule > struct unescape_action : json_pegtl::nothing< Rule > {}; - - template<> struct unescape_action< rules::escaped_char > : json_pegtl::unescape::unescape_c< rules::escaped_char, '"', '\'', '\\', '/', '\b', '\f', '\n', '\r', '\t', '\v', '\0' > {}; - template<> struct unescape_action< rules::escaped_unicode > : json_pegtl::unescape::unescape_j {}; - template<> struct unescape_action< rules::escaped_unicode_code_point_content > : json_pegtl::unescape::unescape_u {}; - - template< char D > struct unescape_action< rules::unescaped< D > > : json_pegtl::unescape::append_all {}; - // clang-format on - - } // namespace jaxn - - } // namespace internal - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/internal/key_state.hpp b/include/tao/json/internal/key_state.hpp deleted file mode 100644 index ca2b7131..00000000 --- a/include/tao/json/internal/key_state.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_KEY_STATE_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_KEY_STATE_HPP - -#include -#include - -namespace tao -{ - namespace json - { - namespace internal - { - struct key_state - { - key_state() = default; - key_state( const key_state& ) = delete; - void operator=( const key_state& ) = delete; - - template< typename Consumer > - void success( Consumer& consumer ) - { - consumer.key( std::move( unescaped ) ); - } - - std::string unescaped; - }; - - } // namespace internal - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/internal/number_state.hpp b/include/tao/json/internal/number_state.hpp index 844f2ee8..07dfc829 100644 --- a/include/tao/json/internal/number_state.hpp +++ b/include/tao/json/internal/number_state.hpp @@ -1,86 +1,80 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_NUMBER_STATE_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_NUMBER_STATE_HPP +#ifndef TAO_JSON_INTERNAL_NUMBER_STATE_HPP +#define TAO_JSON_INTERNAL_NUMBER_STATE_HPP #include #include #include -#include #include #include "../external/double.hpp" -namespace tao +namespace tao::json::internal { - namespace json + static const std::size_t max_mantissa_digits = 772; + + template< bool NEG > + struct number_state { - namespace internal - { - static const std::size_t max_mantissa_digits = 772; + using exponent10_t = std::int32_t; + using msize_t = std::uint16_t; - template< bool NEG > - struct number_state - { - using exponent10_t = int32_t; - using msize_t = uint16_t; + number_state() = default; - number_state() - { - } + number_state( const number_state& ) = delete; + number_state( number_state&& ) = delete; - number_state( const number_state& ) = delete; - void operator=( const number_state& ) = delete; + ~number_state() = default; - exponent10_t exponent10 = 0; - msize_t msize = 0; // Excluding sign. - bool isfp = false; - bool eneg = false; - bool drop = false; - char mantissa[ max_mantissa_digits + 1 ]; + void operator=( const number_state& ) = delete; + void operator=( number_state&& ) = delete; - template< typename Consumer > - void success( Consumer& consumer ) - { - if( !isfp && msize <= 20 ) { - mantissa[ msize ] = 0; - char* p; - errno = 0; - const std::uint64_t ull = std::strtoull( mantissa, &p, 10 ); - if( ( errno != ERANGE ) && ( p == mantissa + msize ) ) { - if( NEG ) { - if( ull < 9223372036854775808ull ) { - consumer.number( -static_cast< std::int64_t >( ull ) ); - return; - } - else if( ull == 9223372036854775808ull ) { - consumer.number( static_cast< std::int64_t >( -9223372036854775807ll - 1 ) ); - return; - } - } - else { - consumer.number( ull ); - return; - } + exponent10_t exponent10 = 0; + msize_t msize = 0; // Excluding sign. + bool isfp = false; + bool eneg = false; + bool drop = false; + char mantissa[ max_mantissa_digits + 1 ]; + + template< typename Consumer > + void success( Consumer& consumer ) + { + if( !isfp && msize <= 20 ) { + mantissa[ msize ] = 0; + char* p; + errno = 0; + const std::uint64_t ull = std::strtoull( mantissa, &p, 10 ); + if( ( errno != ERANGE ) && ( p == mantissa + msize ) ) { + if constexpr( NEG ) { + if( ull < 9223372036854775808ULL ) { + consumer.number( -static_cast< std::int64_t >( ull ) ); + return; + } + if( ull == 9223372036854775808ULL ) { + consumer.number( static_cast< std::int64_t >( -9223372036854775807LL - 1 ) ); + return; } } - if( drop ) { - mantissa[ msize++ ] = '1'; - --exponent10; - } - const auto d = json_double_conversion::Strtod( json_double_conversion::Vector< const char >( mantissa, msize ), exponent10 ); - if( !std::isfinite( d ) ) { - throw std::runtime_error( "invalid double value" ); + else { + consumer.number( ull ); + return; } - consumer.number( NEG ? -d : d ); } - }; - - } // namespace internal - - } // namespace json + } + if( drop ) { + mantissa[ msize++ ] = '1'; + --exponent10; + } + const auto d = double_conversion::Strtod( double_conversion::Vector< const char >( mantissa, msize ), exponent10 ); + if( !std::isfinite( d ) ) { + throw std::runtime_error( "invalid double value" ); + } + consumer.number( NEG ? -d : d ); + } + }; -} // namespace tao +} // namespace tao::json::internal #endif diff --git a/include/tao/json/internal/number_traits.hpp b/include/tao/json/internal/number_traits.hpp new file mode 100644 index 00000000..4025386b --- /dev/null +++ b/include/tao/json/internal/number_traits.hpp @@ -0,0 +1,267 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_INTERNAL_NUMBER_TRAITS_HPP +#define TAO_JSON_INTERNAL_NUMBER_TRAITS_HPP + +#include +#include + +#include "../forward.hpp" +#include "../message_extension.hpp" +#include "../type.hpp" + +#include "format.hpp" + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4702 ) +#endif + +namespace tao::json::internal +{ + template< typename T > + struct number_trait + { + template< template< typename... > class Traits > + [[nodiscard]] static T as( const basic_value< Traits >& v ) + { + switch( v.type() ) { + case type::SIGNED: + return static_cast< T >( v.get_signed() ); + case type::UNSIGNED: + return static_cast< T >( v.get_unsigned() ); + case type::DOUBLE: + return static_cast< T >( v.get_double() ); + default: + throw std::logic_error( internal::format( "invalid json type '", v.type(), "' for conversion to number", json::message_extension( v ) ) ); + } + } + }; + + template< typename T > + struct signed_trait + : number_trait< T > + { + template< template< typename... > class, typename Parts > + [[nodiscard]] static T consume( Parts& parser ) + { + return static_cast< T >( parser.number_signed() ); + } + + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, const T i ) + { + c.number( std::int64_t( i ) ); + } + + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const T i ) noexcept + { + v.set_signed( i ); + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const T rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::SIGNED: + return p.get_signed() == rhs; + case type::UNSIGNED: + return ( rhs >= 0 ) && ( p.get_unsigned() == static_cast< std::uint64_t >( rhs ) ); + case type::DOUBLE: + return p.get_double() == rhs; + default: + return false; + } + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const T rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::SIGNED: + return p.get_signed() < rhs; + case type::UNSIGNED: + return ( rhs >= 0 ) && ( p.get_unsigned() < static_cast< std::uint64_t >( rhs ) ); + case type::DOUBLE: + return p.get_double() < rhs; + default: + return p.type() < type::SIGNED; + } + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const T rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::SIGNED: + return p.get_signed() > rhs; + case type::UNSIGNED: + return ( rhs < 0 ) || ( p.get_unsigned() > static_cast< std::uint64_t >( rhs ) ); + case type::DOUBLE: + return p.get_double() > rhs; + default: + return p.type() > type::SIGNED; + } + } + }; + + template< typename T > + struct unsigned_trait + : number_trait< T > + { + template< template< typename... > class, typename Parts > + [[nodiscard]] static T consume( Parts& parser ) + { + return static_cast< T >( parser.number_unsigned() ); + } + + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, const T i ) + { + c.number( std::uint64_t( i ) ); + } + + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const T i ) noexcept + { + v.set_unsigned( i ); + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const T rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::SIGNED: { + const auto v = p.get_signed(); + return ( v >= 0 ) && ( static_cast< std::uint64_t >( v ) == rhs ); + } + case type::UNSIGNED: + return p.get_unsigned() == rhs; + case type::DOUBLE: + return p.get_double() == rhs; + default: + return false; + } + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const T rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::SIGNED: { + const auto v = p.get_signed(); + return ( v < 0 ) || ( static_cast< std::uint64_t >( v ) < rhs ); + } + case type::UNSIGNED: + return p.get_unsigned() < rhs; + case type::DOUBLE: + return p.get_double() < rhs; + default: + return p.type() < type::UNSIGNED; + } + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const T rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::SIGNED: { + const auto v = p.get_signed(); + return ( v >= 0 ) && ( static_cast< std::uint64_t >( v ) > rhs ); + } + case type::UNSIGNED: + return p.get_unsigned() > rhs; + case type::DOUBLE: + return p.get_double() > rhs; + default: + return p.type() > type::UNSIGNED; + } + } + }; + + template< typename T > + struct float_trait + : number_trait< T > + { + template< template< typename... > class, typename Parts > + [[nodiscard]] static T consume( Parts& parser ) + { + return static_cast< T >( parser.number_double() ); + } + + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, const T f ) + { + c.number( double( f ) ); + } + + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const T f ) noexcept + { + v.set_double( f ); + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const T rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::SIGNED: + return p.get_signed() == rhs; + case type::UNSIGNED: + return p.get_unsigned() == rhs; + case type::DOUBLE: + return p.get_double() == rhs; // TODO: Is it ok for overall semantics that NaN != NaN? + default: + return false; + } + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const T rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::SIGNED: + return p.get_signed() < rhs; + case type::UNSIGNED: + return p.get_unsigned() < rhs; + case type::DOUBLE: + return p.get_double() < rhs; + default: + return p.type() < type::DOUBLE; + } + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const T rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::SIGNED: + return p.get_signed() > rhs; + case type::UNSIGNED: + return p.get_unsigned() > rhs; + case type::DOUBLE: + return p.get_double() > rhs; + default: + return p.type() > type::DOUBLE; + } + } + }; + +} // namespace tao::json::internal + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + +#endif diff --git a/include/tao/json/internal/pair.hpp b/include/tao/json/internal/pair.hpp new file mode 100644 index 00000000..1f15f8e2 --- /dev/null +++ b/include/tao/json/internal/pair.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_INTERNAL_PAIR_HPP +#define TAO_JSON_INTERNAL_PAIR_HPP + +#include +#include +#include + +#include "../forward.hpp" + +namespace tao::json::internal +{ + template< template< typename... > class Traits > + struct pair + { + mutable std::string key; + mutable basic_value< Traits > value; + + template< typename U > + pair( U&& v ) + : key( Traits< std::decay_t< U > >::template default_key< Traits >::as_string() ), + value( std::forward< U >( v ) ) + {} + + template< typename U > + pair( U&& k, basic_value< Traits >&& v ) + : key( std::forward< U >( k ) ), + value( std::move( v ) ) + {} + + template< typename U > + pair( U&& k, const basic_value< Traits >& v ) + : key( std::forward< U >( k ) ), + value( v ) + {} + }; + +} // namespace tao::json::internal + +#endif diff --git a/include/tao/json/internal/parse_util.hpp b/include/tao/json/internal/parse_util.hpp new file mode 100644 index 00000000..26961fe8 --- /dev/null +++ b/include/tao/json/internal/parse_util.hpp @@ -0,0 +1,112 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_INTERNAL_PARSE_UTIL_HPP +#define TAO_JSON_INTERNAL_PARSE_UTIL_HPP + +#include + +#include "../external/pegtl/parse_error.hpp" +#include "../utf8.hpp" + +#include "endian.hpp" +#include "format.hpp" + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4702 ) +#endif + +namespace tao::json::internal +{ + template< typename Input > + void throw_on_empty( Input& in ) + { + if( in.empty() ) { + throw pegtl::parse_error( format( "unexpected end of input" ), in ); + } + } + + template< typename Input > + void throw_on_empty( Input& in, const std::size_t required ) + { + const auto available = in.size( required ); + if( available < required ) { + throw pegtl::parse_error( format( "unexpected end of input -- required ", required, " available ", available ), in ); + } + } + + template< typename Input > + [[nodiscard]] std::uint8_t peek_uint8( Input& in ) + { + throw_on_empty( in ); + return in.peek_uint8(); + } + + template< typename Input > + [[nodiscard]] char peek_char( Input& in ) + { + throw_on_empty( in ); + return in.peek_char(); + } + + template< typename Input > + [[nodiscard]] char read_char_unsafe( Input& in ) + { + const auto r = in.peek_char(); + in.bump_in_this_line( 1 ); + return r; + } + + template< typename Input > + [[nodiscard]] char read_char( Input& in ) + { + throw_on_empty( in ); + return read_char_unsafe( in ); + } + + template< utf8_mode U, typename Result, typename Input > + [[nodiscard]] Result read_string( Input& in, const std::size_t size ) + { + using value_t = typename Result::value_type; + json::internal::throw_on_empty( in, size ); + const auto* pointer = reinterpret_cast< const value_t* >( in.current() ); + const Result result( pointer, size ); + json::internal::consume_utf8_throws< U >( in, size ); + return result; + } + + template< typename Result, typename Number = Result, typename Input > + [[nodiscard]] Result read_big_endian_number( Input& in, const std::size_t extra = 0 ) + { + throw_on_empty( in, extra + sizeof( Number ) ); + const auto result = static_cast< Result >( be_to_h< Number >( in.current() + extra ) ); + in.bump_in_this_line( extra + sizeof( Number ) ); + return result; + } + + template< typename Integer > + [[nodiscard]] Integer hex_char_to_integer( const char c ) noexcept + { + if( ( '0' <= c ) && ( c <= '9' ) ) { + return static_cast< Integer >( c - '0' ); + } + if( ( 'a' <= c ) && ( c <= 'f' ) ) { + return static_cast< Integer >( c - 'a' + 10 ); + } + if( ( 'A' <= c ) && ( c <= 'F' ) ) { + return static_cast< Integer >( c - 'A' + 10 ); + } + // LCOV_EXCL_START + assert( false ); + return 0; + // LCOV_EXCL_STOP + } + +} // namespace tao::json::internal + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + +#endif diff --git a/include/tao/json/internal/sha256.hpp b/include/tao/json/internal/sha256.hpp index 2920ffca..03bcd467 100644 --- a/include/tao/json/internal/sha256.hpp +++ b/include/tao/json/internal/sha256.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_SHA256_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_SHA256_HPP +#ifndef TAO_JSON_INTERNAL_SHA256_HPP +#define TAO_JSON_INTERNAL_SHA256_HPP // Implements RFC 6234, SHA-256 @@ -11,208 +11,208 @@ #include #include -#define DBL_INT_ADD( a, b, c ) \ - if( a > 0xffffffff - ( c ) ) \ - ++b; \ - a += c; - // RFC 6234, 3.d; see also http://stackoverflow.com/a/4209604/2073257 -#define ROR( x, N ) ( ( x >> N ) | ( x << ( 32 - N ) ) ) +#define ROR( x, N ) ( ( ( x ) >> ( N ) ) | ( ( x ) << ( 32 - ( N ) ) ) ) // RFC 6234, 5.1 -#define CH( x, y, z ) ( ( x & y ) ^ ( ~x & z ) ) -#define MAJ( x, y, z ) ( ( x & y ) ^ ( x & z ) ^ ( y & z ) ) +#define CH( x, y, z ) ( ( ( x ) & ( y ) ) ^ ( ~( x ) & ( z ) ) ) +#define MAJ( x, y, z ) ( ( ( x ) & ( y ) ) ^ ( ( x ) & ( z ) ) ^ ( ( y ) & ( z ) ) ) #define BSIG0( x ) ( ROR( x, 2 ) ^ ROR( x, 13 ) ^ ROR( x, 22 ) ) #define BSIG1( x ) ( ROR( x, 6 ) ^ ROR( x, 11 ) ^ ROR( x, 25 ) ) -#define SSIG0( x ) ( ROR( x, 7 ) ^ ROR( x, 18 ) ^ ( x >> 3 ) ) -#define SSIG1( x ) ( ROR( x, 17 ) ^ ROR( x, 19 ) ^ ( x >> 10 ) ) +#define SSIG0( x ) ( ROR( x, 7 ) ^ ROR( x, 18 ) ^ ( ( x ) >> 3 ) ) +#define SSIG1( x ) ( ROR( x, 17 ) ^ ROR( x, 19 ) ^ ( ( x ) >> 10 ) ) -namespace tao +namespace tao::json::internal { - namespace json + // RFC 6234, 5.1 + // clang-format off + static std::uint32_t K[ 64 ] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + }; + // clang-format on + + class sha256 { - namespace internal + private: + unsigned char M[ 64 ]; + std::uint64_t size; + + std::uint32_t H[ 8 ]; + + // RFC 6234, 6.2 + void process() noexcept { - // RFC 6234, 5.1 - // clang-format off - static std::uint32_t K[ 64 ] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 - }; - // clang-format on - - class sha256 - { - private: - unsigned char M[ 64 ]; - std::size_t size; - - std::uint32_t H[ 8 ]; - - // RFC 6234, 6.2 - void process() noexcept - { - std::uint32_t W[ 64 ]; - - // step 1 - for( std::size_t t = 0, i = 0; t != 16; ++t, i += 4 ) { - W[ t ] = ( M[ i ] << 24 ) | ( M[ i + 1 ] << 16 ) | ( M[ i + 2 ] << 8 ) | ( M[ i + 3 ] ); - } - for( std::size_t t = 16; t != 64; ++t ) { - W[ t ] = SSIG1( W[ t - 2 ] ) + W[ t - 7 ] + SSIG0( W[ t - 15 ] ) + W[ t - 16 ]; - } - - // step 2 - std::uint32_t a, b, c, d, e, f, g, h; - a = H[ 0 ]; - b = H[ 1 ]; - c = H[ 2 ]; - d = H[ 3 ]; - e = H[ 4 ]; - f = H[ 5 ]; - g = H[ 6 ]; - h = H[ 7 ]; - - // step 3 - for( std::size_t t = 0; t != 64; ++t ) { - const std::uint32_t T1 = h + BSIG1( e ) + CH( e, f, g ) + K[ t ] + W[ t ]; - const std::uint32_t T2 = BSIG0( a ) + MAJ( a, b, c ); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - } - - // step 4 - H[ 0 ] += a; - H[ 1 ] += b; - H[ 2 ] += c; - H[ 3 ] += d; - H[ 4 ] += e; - H[ 5 ] += f; - H[ 6 ] += g; - H[ 7 ] += h; - } + std::uint32_t W[ 64 ]; + + // step 1 + for( std::size_t t = 0, i = 0; t != 16; ++t, i += 4 ) { + W[ t ] = ( M[ i ] << 24 ) | ( M[ i + 1 ] << 16 ) | ( M[ i + 2 ] << 8 ) | ( M[ i + 3 ] ); + } + for( std::size_t t = 16; t != 64; ++t ) { + W[ t ] = SSIG1( W[ t - 2 ] ) + W[ t - 7 ] + SSIG0( W[ t - 15 ] ) + W[ t - 16 ]; + } + + // step 2 + std::uint32_t a, b, c, d, e, f, g, h; + a = H[ 0 ]; + b = H[ 1 ]; + c = H[ 2 ]; + d = H[ 3 ]; + e = H[ 4 ]; + f = H[ 5 ]; + g = H[ 6 ]; + h = H[ 7 ]; + + // step 3 + for( std::size_t t = 0; t != 64; ++t ) { + const std::uint32_t T1 = h + BSIG1( e ) + CH( e, f, g ) + K[ t ] + W[ t ]; + const std::uint32_t T2 = BSIG0( a ) + MAJ( a, b, c ); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + // step 4 + H[ 0 ] += a; + H[ 1 ] += b; + H[ 2 ] += c; + H[ 3 ] += d; + H[ 4 ] += e; + H[ 5 ] += f; + H[ 6 ] += g; + H[ 7 ] += h; + } + + public: + sha256() noexcept + { + reset(); + } - public: - sha256() noexcept - { - reset(); - } + sha256( const sha256& ) = delete; + sha256( sha256&& ) = delete; - sha256( const sha256& ) = delete; - void operator=( const sha256& ) = delete; - - void reset() noexcept - { - size = 0; - - // RFC 6234, 6.1 - H[ 0 ] = 0x6a09e667; - H[ 1 ] = 0xbb67ae85; - H[ 2 ] = 0x3c6ef372; - H[ 3 ] = 0xa54ff53a; - H[ 4 ] = 0x510e527f; - H[ 5 ] = 0x9b05688c; - H[ 6 ] = 0x1f83d9ab; - H[ 7 ] = 0x5be0cd19; - } + ~sha256() = default; - void feed( const unsigned char c ) noexcept - { - M[ size++ % 64 ] = c; - if( ( size % 64 ) == 0 ) { - process(); - } - } + void operator=( const sha256& ) = delete; + void operator=( sha256&& ) = delete; - void feed( const void* p, std::size_t s ) noexcept - { - const unsigned char* q = static_cast< const unsigned char* >( p ); - while( s-- ) { - feed( *q++ ); - } - } + void reset() noexcept + { + size = 0; + + // RFC 6234, 6.1 + H[ 0 ] = 0x6a09e667; + H[ 1 ] = 0xbb67ae85; + H[ 2 ] = 0x3c6ef372; + H[ 3 ] = 0xa54ff53a; + H[ 4 ] = 0x510e527f; + H[ 5 ] = 0x9b05688c; + H[ 6 ] = 0x1f83d9ab; + H[ 7 ] = 0x5be0cd19; + } + + void feed( const unsigned char c ) noexcept + { + M[ size++ % 64 ] = c; + if( ( size % 64 ) == 0 ) { + process(); + } + } - void feed( const std::string& v ) noexcept - { - feed( v.data(), v.size() ); - } + void feed( const void* p, std::size_t s ) noexcept + { + auto* q = static_cast< const unsigned char* >( p ); + while( s != 0 ) { + feed( *q++ ); + --s; + } + } + + void feed( const std::string_view v ) noexcept + { + feed( v.data(), v.size() ); + } - // RFC 6234, 4.1 - void store_unsafe( unsigned char* buffer ) noexcept - { - std::size_t i = size % 64; - if( i < 56 ) { - M[ i++ ] = 0x80; - while( i < 56 ) { - M[ i++ ] = 0x00; - } - } - else { - M[ i++ ] = 0x80; - while( i < 64 ) { - M[ i++ ] = 0x00; - } - process(); - std::memset( M, 0, 56 ); - } - - size *= 8; - - M[ 63 ] = size; - M[ 62 ] = size >> 8; - M[ 61 ] = size >> 16; - M[ 60 ] = size >> 24; - M[ 59 ] = size >> 32; - M[ 58 ] = size >> 40; - M[ 57 ] = size >> 48; - M[ 56 ] = size >> 56; - - process(); - - for( std::size_t j = 0; j < 4; ++j ) { - buffer[ j ] = ( H[ 0 ] >> ( 24 - j * 8 ) ) & 0xff; - buffer[ j + 4 ] = ( H[ 1 ] >> ( 24 - j * 8 ) ) & 0xff; - buffer[ j + 8 ] = ( H[ 2 ] >> ( 24 - j * 8 ) ) & 0xff; - buffer[ j + 12 ] = ( H[ 3 ] >> ( 24 - j * 8 ) ) & 0xff; - buffer[ j + 16 ] = ( H[ 4 ] >> ( 24 - j * 8 ) ) & 0xff; - buffer[ j + 20 ] = ( H[ 5 ] >> ( 24 - j * 8 ) ) & 0xff; - buffer[ j + 24 ] = ( H[ 6 ] >> ( 24 - j * 8 ) ) & 0xff; - buffer[ j + 28 ] = ( H[ 7 ] >> ( 24 - j * 8 ) ) & 0xff; - } + // RFC 6234, 4.1 + void store_unsafe( unsigned char* buffer ) noexcept + { + std::size_t i = size % 64; + if( i < 56 ) { + M[ i++ ] = 0x80; +#if defined( __GNUC__ ) && ( __GNUC__ >= 9 ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Waggressive-loop-optimizations" +#endif + while( i < 56 ) { + M[ i++ ] = 0x00; } - - std::string get() - { - unsigned char result[ 32 ]; - store_unsafe( result ); - return std::string( reinterpret_cast< const char* >( result ), 32 ); +#if defined( __GNUC__ ) && ( __GNUC__ >= 9 ) +#pragma GCC diagnostic pop +#endif + } + else { + M[ i++ ] = 0x80; + while( i < 64 ) { + M[ i++ ] = 0x00; } - }; - - } // namespace internal - - } // namespace json + process(); + std::memset( M, 0, 56 ); + } + + size *= 8; + + M[ 63 ] = static_cast< unsigned char >( size ); + M[ 62 ] = static_cast< unsigned char >( size >> 8 ); + M[ 61 ] = static_cast< unsigned char >( size >> 16 ); + M[ 60 ] = static_cast< unsigned char >( size >> 24 ); + M[ 59 ] = static_cast< unsigned char >( size >> 32 ); + M[ 58 ] = static_cast< unsigned char >( size >> 40 ); + M[ 57 ] = static_cast< unsigned char >( size >> 48 ); + M[ 56 ] = static_cast< unsigned char >( size >> 56 ); + + process(); + + for( std::size_t j = 0; j < 4; ++j ) { + buffer[ j ] = ( H[ 0 ] >> ( 24 - j * 8 ) ) & 0xff; + buffer[ j + 4 ] = ( H[ 1 ] >> ( 24 - j * 8 ) ) & 0xff; + buffer[ j + 8 ] = ( H[ 2 ] >> ( 24 - j * 8 ) ) & 0xff; + buffer[ j + 12 ] = ( H[ 3 ] >> ( 24 - j * 8 ) ) & 0xff; + buffer[ j + 16 ] = ( H[ 4 ] >> ( 24 - j * 8 ) ) & 0xff; + buffer[ j + 20 ] = ( H[ 5 ] >> ( 24 - j * 8 ) ) & 0xff; + buffer[ j + 24 ] = ( H[ 6 ] >> ( 24 - j * 8 ) ) & 0xff; + buffer[ j + 28 ] = ( H[ 7 ] >> ( 24 - j * 8 ) ) & 0xff; + } + } + + [[nodiscard]] std::string get() + { + std::string result( 32, '\0' ); + store_unsafe( reinterpret_cast< unsigned char* >( result.data() ) ); + return result; + } + }; -} // namespace tao +} // namespace tao::json::internal #endif diff --git a/include/tao/json/internal/single.hpp b/include/tao/json/internal/single.hpp new file mode 100644 index 00000000..f56818c6 --- /dev/null +++ b/include/tao/json/internal/single.hpp @@ -0,0 +1,40 @@ +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_INTERNAL_SINGLE_HPP +#define TAO_JSON_INTERNAL_SINGLE_HPP + +#include + +#include "../forward.hpp" + +#include "pair.hpp" + +namespace tao::json::internal +{ + template< template< typename... > class Traits > + struct single + { + mutable basic_value< Traits > value; + + template< typename U > + single( U&& v ) + : value( std::forward< U >( v ) ) + {} + + single( std::initializer_list< pair< Traits > >&& l ) + : value( std::move( l ) ) + {} + + single( const std::initializer_list< pair< Traits > >& l ) + : value( l ) + {} + + single( std::initializer_list< pair< Traits > >& l ) + : value( l ) + {} + }; + +} // namespace tao::json::internal + +#endif diff --git a/include/tao/json/internal/string_state.hpp b/include/tao/json/internal/string_state.hpp deleted file mode 100644 index f7156627..00000000 --- a/include/tao/json/internal/string_state.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_STRING_STATE_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_STRING_STATE_HPP - -#include -#include - -namespace tao -{ - namespace json - { - namespace internal - { - struct string_state - { - string_state() = default; - string_state( const string_state& ) = delete; - void operator=( const string_state& ) = delete; - - template< typename Consumer > - void success( Consumer& consumer ) - { - consumer.string( std::move( unescaped ) ); - } - - std::string unescaped; - }; - - } // namespace internal - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/internal/string_t.hpp b/include/tao/json/internal/string_t.hpp new file mode 100644 index 00000000..ba6c931c --- /dev/null +++ b/include/tao/json/internal/string_t.hpp @@ -0,0 +1,35 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_INTERNAL_STRING_T_HPP +#define TAO_JSON_INTERNAL_STRING_T_HPP + +#include +#include + +#include "../external/pegtl/internal/pegtl_string.hpp" + +namespace tao::json::internal +{ + template< char... Cs > + struct string_t + : pegtl::string< Cs... > + { + static constexpr const char value[] = { Cs..., 0 }; + + [[nodiscard]] static constexpr std::string_view as_string_view() noexcept + { + return std::string_view( value, sizeof...( Cs ) ); + } + + [[nodiscard]] static std::string as_string() + { + return std::string( value, sizeof...( Cs ) ); + } + }; + +} // namespace tao::json::internal + +#define TAO_JSON_STRING_T( VaLue ) TAO_JSON_PEGTL_INTERNAL_STRING( tao::json::internal::string_t, VaLue ) + +#endif diff --git a/include/tao/json/internal/throw.hpp b/include/tao/json/internal/throw.hpp deleted file mode 100644 index c4caf5a7..00000000 --- a/include/tao/json/internal/throw.hpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_THROW_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_THROW_HPP - -#include -#include - -#include "../type.hpp" - -#define TAOCPP_JSON_THROW_TYPE_ERROR( TyPe ) \ - do { \ - throw std::logic_error( std::string( "invalid json type '" ) + to_string( TyPe ) + '\'' ); \ - } while( false ) - -#define TAOCPP_JSON_CHECK_TYPE_ERROR( HaVe, NeeD ) \ - do { \ - if( ( HaVe ) != ( NeeD ) ) { \ - TAOCPP_JSON_THROW_TYPE_ERROR( HaVe ); \ - } \ - } while( false ) - -#endif diff --git a/include/tao/json/internal/type_traits.hpp b/include/tao/json/internal/type_traits.hpp new file mode 100644 index 00000000..d34c9caa --- /dev/null +++ b/include/tao/json/internal/type_traits.hpp @@ -0,0 +1,113 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_INTERNAL_TYPE_TRAITS_HPP +#define TAO_JSON_INTERNAL_TYPE_TRAITS_HPP + +#include +#include + +#include "../forward.hpp" + +namespace tao::json::internal +{ + template< typename... Ts > + struct type_list + { + static constexpr std::size_t size = sizeof...( Ts ); + }; + + template< typename... > + struct merge_type_lists_t; + + template< typename... Ts > + struct merge_type_lists_t< type_list< Ts... > > + { + using list = type_list< Ts... >; + }; + + template< typename... Vs, typename... Ws, typename... Rs > + struct merge_type_lists_t< type_list< Vs... >, type_list< Ws... >, Rs... > + : merge_type_lists_t< type_list< Vs..., Ws... >, Rs... > + {}; + + template< typename... Ts > + using merge_type_lists = typename merge_type_lists_t< Ts... >::list; + + struct type_info_less + { + [[nodiscard]] bool operator()( const std::type_info* l, const std::type_info* r ) const + { + return l->before( *r ); + } + }; + + template< typename... > + inline constexpr bool has_as_impl = false; + + template< typename Trait, typename... Args > + inline constexpr bool has_as_impl< decltype( (void)Trait::as( std::declval< Args >()... ), void() ), Trait, Args... > = true; + + template< typename Trait, typename Value, typename... With > + inline constexpr bool has_as = has_as_impl< void, Trait, const Value&, With&... >; + + template< typename, template< typename... > typename, typename, typename... > + inline constexpr bool has_as_type_impl = false; + + template< template< typename... > typename Traits, typename T, typename... Args > + inline constexpr bool has_as_type_impl< decltype( (void)Traits< T >::template as_type< Traits, T >( std::declval< Args >()... ), void() ), Traits, T, Args... > = true; + + template< template< typename... > typename Traits, typename T, typename Value, typename... With > + inline constexpr bool has_as_type = has_as_type_impl< void, Traits, T, const Value&, With&... >; + + template< typename... > + inline constexpr bool has_to_impl = false; + + template< typename Trait, typename... Args > + inline constexpr bool has_to_impl< decltype( Trait::to( std::declval< Args >()... ), void() ), Trait, Args... > = true; + + template< typename Trait, typename Value, typename... With > + inline constexpr bool has_to = has_to_impl< void, Trait, const Value&, With&... >; + + template< template< typename... > class, typename, typename, typename = void > + inline constexpr bool has_consume_one = false; + + template< template< typename... > class Traits, typename P, typename U > + inline constexpr bool has_consume_one< Traits, P, U, decltype( (void)Traits< U >::template consume< Traits >( std::declval< P& >() ), void() ) > = true; + + template< template< typename... > class, typename, typename, typename = void > + inline constexpr bool has_consume_two = false; + + template< template< typename... > class Traits, typename P, typename U > + inline constexpr bool has_consume_two< Traits, P, U, decltype( (void)Traits< U >::template consume< Traits >( std::declval< P& >(), std::declval< U& >() ), void() ) > = true; + + template< template< typename... > class Traits, typename T, typename = void > + inline constexpr bool has_is_nothing = false; + + template< template< typename... > class Traits, typename T > + inline constexpr bool has_is_nothing< Traits, T, decltype( (void)Traits< T >::template is_nothing< Traits >( std::declval< const T& >() ), void() ) > = true; + + template< template< typename... > class Traits, typename T > + [[nodiscard]] std::enable_if_t< has_is_nothing< Traits, T >, bool > is_nothing( const T& t ) noexcept( noexcept( Traits< T >::template is_nothing< Traits >( t ) ) ) + { + return Traits< T >::template is_nothing< Traits >( t ); + } + + template< template< typename... > class Traits, typename T > + [[nodiscard]] std::enable_if_t< !has_is_nothing< Traits, T >, bool > is_nothing( const T& /*unused*/ ) noexcept + { + return false; + } + + template< template< typename... > class Traits, typename T, typename = void > + inline constexpr bool has_enable_implicit_constructor = false; + + template< template< typename... > class Traits, typename T > + inline constexpr bool has_enable_implicit_constructor< Traits, T, decltype( Traits< T >::enable_implicit_constructor, void() ) > = true; + + template< template< typename... > class Traits, typename T > + inline constexpr bool enable_implicit_constructor = Traits< std::conditional_t< has_enable_implicit_constructor< Traits, T >, T, void > >::enable_implicit_constructor; + +} // namespace tao::json::internal + +#endif diff --git a/include/tao/json/internal/unescape_action.hpp b/include/tao/json/internal/unescape_action.hpp index 1f32f5cf..b74fc30b 100644 --- a/include/tao/json/internal/unescape_action.hpp +++ b/include/tao/json/internal/unescape_action.hpp @@ -1,32 +1,24 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_UNESCAPE_ACTION_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_UNESCAPE_ACTION_HPP +#ifndef TAO_JSON_INTERNAL_UNESCAPE_ACTION_HPP +#define TAO_JSON_INTERNAL_UNESCAPE_ACTION_HPP #include "../external/pegtl/contrib/unescape.hpp" #include "../external/pegtl/nothing.hpp" #include "grammar.hpp" -namespace tao +namespace tao::json::internal { - namespace json - { - namespace internal - { - // clang-format off - template< typename Rule > struct unescape_action : json_pegtl::nothing< Rule > {}; + // clang-format off + template< typename Rule > struct unescape_action : pegtl::nothing< Rule > {}; - template<> struct unescape_action< rules::escaped_unicode > : json_pegtl::unescape::unescape_j {}; - template<> struct unescape_action< rules::escaped_char > : json_pegtl::unescape::unescape_c< rules::escaped_char, '"', '\\', '/', '\b', '\f', '\n', '\r', '\t' > {}; - template<> struct unescape_action< rules::unescaped > : json_pegtl::unescape::append_all {}; - // clang-format on + template<> struct unescape_action< rules::escaped_unicode > : pegtl::unescape::unescape_j {}; + template<> struct unescape_action< rules::escaped_char > : pegtl::unescape::unescape_c< rules::escaped_char, '"', '\\', '/', '\b', '\f', '\n', '\r', '\t' > {}; + template<> struct unescape_action< rules::unescaped > : pegtl::unescape::append_all {}; + // clang-format on - } // namespace internal - - } // namespace json - -} // namespace tao +} // namespace tao::json::internal #endif diff --git a/include/tao/json/internal/uri_fragment.hpp b/include/tao/json/internal/uri_fragment.hpp index a42b825c..acedcbba 100644 --- a/include/tao/json/internal/uri_fragment.hpp +++ b/include/tao/json/internal/uri_fragment.hpp @@ -1,188 +1,182 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_URI_FRAGMENT_HPP -#define TAOCPP_JSON_INCLUDE_URI_FRAGMENT_HPP - -#include "../pointer.hpp" +#ifndef TAO_JSON_INTERNAL_URI_FRAGMENT_HPP +#define TAO_JSON_INTERNAL_URI_FRAGMENT_HPP #include +#include + +#include "../pointer.hpp" -namespace tao +namespace tao::json::internal { - namespace json + // clang-format off + const bool allowed_uri_fragment_characters[] = { + false, false, false, false, false, false, false, false, // 0 + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, // 16 + false, false, false, false, false, false, false, false, + false, true, false, false, true, false, true, true, // 32 + true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, // 48 + true, true, true, true, false, true, false, true, + true, true, true, true, true, true, true, true, // 64 + true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, // 80 + true, true, true, false, false, false, false, true, + false, true, true, true, true, true, true, true, // 96 + true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, // 112 + true, true, true, false, false, false, true, false, + false, false, false, false, false, false, false, false, // 128 + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false + }; + // clang-format on + + [[nodiscard]] inline char xdigit_value( const char c ) { - namespace internal - { - // clang-format off - const bool allowed_uri_fragment_characters[] = { - false, false, false, false, false, false, false, false, // 0 - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, // 16 - false, false, false, false, false, false, false, false, - false, true, false, false, true, false, true, true, // 32 - true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, // 48 - true, true, true, true, false, true, false, true, - true, true, true, true, true, true, true, true, // 64 - true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, // 80 - true, true, true, false, false, false, false, true, - false, true, true, true, true, true, true, true, // 96 - true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, // 112 - true, true, true, false, false, false, true, false, - false, false, false, false, false, false, false, false, // 128 - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false - }; - // clang-format on - - inline char xdigit_value( const char c ) - { - // clang-format off - switch ( c ) { - case '0': return 0; - case '1': return 1; - case '2': return 2; - case '3': return 3; - case '4': return 4; - case '5': return 5; - case '6': return 6; - case '7': return 7; - case '8': return 8; - case '9': return 9; - case 'a': case 'A': return 10; - case 'b': case 'B': return 11; - case 'c': case 'C': return 12; - case 'd': case 'D': return 13; - case 'e': case 'E': return 14; - case 'f': case 'F': return 15; - } - // clang-format on - throw std::invalid_argument( "invalid URI Fragment escape sequence, '%' must be followed by two hexadecimal digits" ); + // clang-format off + switch ( c ) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + case 'a': case 'A': return 10; + case 'b': case 'B': return 11; + case 'c': case 'C': return 12; + case 'd': case 'D': return 13; + case 'e': case 'E': return 14; + case 'f': case 'F': return 15; + default: + throw std::invalid_argument( "invalid URI Fragment escape sequence, '%' must be followed by two hexadecimal digits" ); + } + // clang-format on + } + + [[nodiscard]] inline pointer uri_fragment_to_pointer( const std::string_view v ) + { + pointer result; + if( v.empty() || v[ 0 ] != '#' ) { + throw std::invalid_argument( "invalid URI Fragment value, must begin with '#'" ); + } + if( v.size() > 1 ) { + const char* p = v.data() + 1; + const char* const e = v.data() + v.size(); + if( *p++ != '/' ) { + throw std::invalid_argument( "invalid JSON Pointer value, must be empty or begin with '/'" ); } - - inline pointer uri_fragment_to_pointer( const std::string& v ) - { - pointer result; - if( v.empty() || v[ 0 ] != '#' ) { - throw std::invalid_argument( "invalid URI Fragment value, must begin with '#'" ); - } - if( v.size() > 1 ) { - const char* p = v.data() + 1; - const char* const e = v.data() + v.size(); - if( *p++ != '/' ) { - throw std::invalid_argument( "invalid JSON Pointer value, must be empty or begin with '/'" ); - } - std::string token; - while( p != e ) { - const char c = *p++; - switch( c ) { - // clang-format off - case '!': case '$': case '&': case '\'': case '(': case ')': case '*': case '+': case ',': case '-': case '.': - case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - case ':': case ';': case '=': case '?': case '@': - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': - case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': - case '_': - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': - case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': - // clang-format on - token += c; + std::string token; + while( p != e ) { + const char c = *p++; + switch( c ) { + // clang-format off + case '!': case '$': case '&': case '\'': case '(': case ')': case '*': case '+': case ',': case '-': case '.': + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': + case ':': case ';': case '=': case '?': case '@': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': + case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': + case '_': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': + case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': + // clang-format on + token += c; + continue; + + case '%': + if( p != e ) { + const char h1 = xdigit_value( *p++ ); + if( p != e ) { + const char h2 = xdigit_value( *p++ ); + token += static_cast< char >( h1 * 16 + h2 ); continue; + } + } + throw std::invalid_argument( "invalid URI Fragment escape sequence, '%' must be followed by two hexadecimal digits" ); + + case '~': + if( p != e ) { + switch( *p++ ) { + case '0': + token += '~'; + continue; + case '1': + token += '/'; + continue; + } + } + throw std::invalid_argument( "invalid JSON Pointer escape sequence, '~' must be followed by '0' or '1'" ); - case '%': - if( p != e ) { - const char h1 = xdigit_value( *p++ ); - if( p != e ) { - const char h2 = xdigit_value( *p++ ); - token += h1 * 16 + h2; - continue; - } - } - throw std::invalid_argument( "invalid URI Fragment escape sequence, '%' must be followed by two hexadecimal digits" ); - - case '~': - if( p != e ) { - switch( *p++ ) { - case '0': - token += '~'; - continue; - case '1': - token += '/'; - continue; - } - } - throw std::invalid_argument( "invalid JSON Pointer escape sequence, '~' must be followed by '0' or '1'" ); - - case '/': - result += std::move( token ); - token.clear(); - continue; + case '/': + result += std::move( token ); + token.clear(); + continue; - default: - throw std::invalid_argument( "invalid URI Fragment character" ); - } - } - result += std::move( token ); + default: + throw std::invalid_argument( "invalid URI Fragment character" ); } - return result; } + result += std::move( token ); + } + return result; + } - inline std::string tokens_to_uri_fragment( std::vector< token >::const_iterator it, const std::vector< token >::const_iterator& end ) - { - static const char* hex = "0123456789ABCDEF"; - - std::string result = "#"; - while( it != end ) { - result += '/'; - for( const unsigned char c : it->key() ) { - switch( c ) { - case '~': - result += "~0"; - break; - case '/': - result += "~1"; - break; - default: - if( allowed_uri_fragment_characters[ c ] ) { - result += c; - } - else { - result += '%'; - result += hex[ c >> 4 ]; - result += hex[ c & 15 ]; - } + [[nodiscard]] inline std::string tokens_to_uri_fragment( std::vector< token >::const_iterator it, const std::vector< token >::const_iterator& end ) + { + static const char* hex = "0123456789ABCDEF"; + + std::string result = "#"; + while( it != end ) { + result += '/'; + for( const unsigned char c : it->key() ) { + switch( c ) { + case '~': + result += "~0"; + break; + case '/': + result += "~1"; + break; + default: + if( allowed_uri_fragment_characters[ c ] ) { + result += c; + } + else { + result += '%'; + result += hex[ c >> 4 ]; + result += hex[ c & 15 ]; } - } - ++it; } - return result; - } - - inline std::string to_uri_fragment( const pointer& p ) - { - return tokens_to_uri_fragment( p.begin(), p.end() ); } + ++it; + } + return result; + } - } // namespace internal - - } // namespace json + [[nodiscard]] inline std::string to_uri_fragment( const pointer& p ) + { + return tokens_to_uri_fragment( p.begin(), p.end() ); + } -} // namespace tao +} // namespace tao::json::internal #endif diff --git a/include/tao/json/internal/value_union.hpp b/include/tao/json/internal/value_union.hpp deleted file mode 100644 index f8ff94a0..00000000 --- a/include/tao/json/internal/value_union.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_INTERNAL_VALUE_UNION_HPP -#define TAOCPP_JSON_INCLUDE_INTERNAL_VALUE_UNION_HPP - -#include -#include -#include -#include - -#include "../byte_view.hpp" - -#include "../external/byte.hpp" -#include "../external/string_view.hpp" - -namespace tao -{ - namespace json - { - namespace internal - { - template< typename T > - union value_union - { - value_union() noexcept - { - } - - value_union( const value_union& ) = delete; - void operator=( const value_union& ) = delete; - - ~value_union() noexcept - { - } - - bool b; - - std::int64_t i; - std::uint64_t u; - double d; - - std::string s; - tao::string_view sv; - - std::vector< tao::byte > x; - tao::byte_view xv; - - std::vector< T > a; - - std::map< std::string, T > o; - - const T* p; - }; - - } // namespace internal - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/jaxn.hpp b/include/tao/json/jaxn.hpp index 2a7fc9c7..10f40034 100644 --- a/include/tao/json/jaxn.hpp +++ b/include/tao/json/jaxn.hpp @@ -1,13 +1,18 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_JAXN_HPP -#define TAOCPP_JSON_INCLUDE_JAXN_HPP +#ifndef TAO_JSON_JAXN_HPP +#define TAO_JSON_JAXN_HPP #include "../json.hpp" +#include "jaxn/consume_file.hpp" +#include "jaxn/consume_string.hpp" +#include "jaxn/from_file.hpp" +#include "jaxn/from_input.hpp" #include "jaxn/from_stream.hpp" #include "jaxn/from_string.hpp" +#include "jaxn/parts_parser.hpp" #include "jaxn/to_stream.hpp" #include "jaxn/to_string.hpp" diff --git a/include/tao/json/jaxn/consume_file.hpp b/include/tao/json/jaxn/consume_file.hpp new file mode 100644 index 00000000..1bf9a5bd --- /dev/null +++ b/include/tao/json/jaxn/consume_file.hpp @@ -0,0 +1,34 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_JAXN_CONSUME_FILE_HPP +#define TAO_JSON_JAXN_CONSUME_FILE_HPP + +#include + +#include "../external/pegtl/file_input.hpp" + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "parts_parser.hpp" + +namespace tao::json::jaxn +{ + template< typename T, template< typename... > class Traits = traits, typename F > + [[nodiscard]] T consume_file( F&& filename ) + { + jaxn::basic_parts_parser< pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); + return json::consume< T, Traits >( pp ); + } + + template< template< typename... > class Traits = traits, typename F, typename T > + void consume_file( F&& filename, T& t ) + { + jaxn::basic_parts_parser< pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); + json::consume< Traits >( pp, t ); + } + +} // namespace tao::json::jaxn + +#endif diff --git a/include/tao/json/jaxn/consume_string.hpp b/include/tao/json/jaxn/consume_string.hpp new file mode 100644 index 00000000..3051d0ec --- /dev/null +++ b/include/tao/json/jaxn/consume_string.hpp @@ -0,0 +1,32 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_JAXN_CONSUME_STRING_HPP +#define TAO_JSON_JAXN_CONSUME_STRING_HPP + +#include "../external/pegtl/string_input.hpp" + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "parts_parser.hpp" + +namespace tao::json::jaxn +{ + template< typename T, template< typename... > class Traits = traits, typename F > + [[nodiscard]] T consume_string( F&& string ) + { + jaxn::basic_parts_parser< pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); + return json::consume< T, Traits >( pp ); + } + + template< template< typename... > class Traits = traits, typename F, typename T > + void consume_string( F&& string, T& t ) + { + jaxn::basic_parts_parser< pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); + json::consume< Traits >( pp, t ); + } + +} // namespace tao::json::jaxn + +#endif diff --git a/include/tao/json/jaxn/events/from_file.hpp b/include/tao/json/jaxn/events/from_file.hpp new file mode 100644 index 00000000..f645b594 --- /dev/null +++ b/include/tao/json/jaxn/events/from_file.hpp @@ -0,0 +1,28 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_JAXN_EVENTS_FROM_FILE_HPP +#define TAO_JSON_JAXN_EVENTS_FROM_FILE_HPP + +#include + +#include "../internal/action.hpp" +#include "../internal/errors.hpp" +#include "../internal/grammar.hpp" + +#include "../../external/pegtl/file_input.hpp" + +namespace tao::json::jaxn::events +{ + // Events producer to parse a file containing a JAXN string representation. + + template< typename T, typename Consumer > + void from_file( Consumer& consumer, T&& filename ) + { + pegtl::file_input< pegtl::tracking_mode::lazy > in( std::forward< T >( filename ) ); + pegtl::parse< internal::grammar, internal::action, internal::errors >( in, consumer ); + } + +} // namespace tao::json::jaxn::events + +#endif diff --git a/include/tao/json/jaxn/events/from_input.hpp b/include/tao/json/jaxn/events/from_input.hpp new file mode 100644 index 00000000..bb27cedc --- /dev/null +++ b/include/tao/json/jaxn/events/from_input.hpp @@ -0,0 +1,45 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_JAXN_EVENTS_FROM_INPUT_HPP +#define TAO_JSON_JAXN_EVENTS_FROM_INPUT_HPP + +#include + +#include "../../external/pegtl/parse.hpp" + +#include "../internal/action.hpp" +#include "../internal/errors.hpp" +#include "../internal/grammar.hpp" + +namespace tao::json::jaxn::events +{ + // Events producers that parse a JAXN string representation from a PEGTL input (or something compatible). + + template< typename Consumer, typename Input > + void from_input( Consumer& consumer, Input&& in ) + { + pegtl::parse< internal::grammar, internal::action, internal::errors >( std::forward< Input >( in ), consumer ); + } + + template< typename Consumer, typename Input > + void from_input_embedded( Consumer& consumer, Input&& in ) + { + pegtl::parse< internal::embedded, internal::action, internal::errors >( std::forward< Input >( in ), consumer ); + } + + template< typename Consumer, typename Outer, typename Input > + void from_input_nested( Consumer& consumer, const Outer& oi, Input&& in ) + { + pegtl::parse_nested< internal::grammar, internal::action, internal::errors >( oi, std::forward< Input >( in ), consumer ); + } + + template< typename Consumer, typename Outer, typename Input > + void from_input_embedded_nested( Consumer& consumer, const Outer& oi, Input&& in ) + { + pegtl::parse_nested< internal::embedded, internal::action, internal::errors >( oi, std::forward< Input >( in ), consumer ); + } + +} // namespace tao::json::jaxn::events + +#endif diff --git a/include/tao/json/jaxn/events/from_stream.hpp b/include/tao/json/jaxn/events/from_stream.hpp new file mode 100644 index 00000000..2c5984dd --- /dev/null +++ b/include/tao/json/jaxn/events/from_stream.hpp @@ -0,0 +1,33 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_JAXN_EVENTS_FROM_STREAM_HPP +#define TAO_JSON_JAXN_EVENTS_FROM_STREAM_HPP + +#include + +#include "../../external/pegtl/internal/istream_reader.hpp" +#include "../../external/pegtl/parse.hpp" + +#include "../internal/action.hpp" +#include "../internal/errors.hpp" +#include "../internal/grammar.hpp" + +namespace tao::json::jaxn::events +{ + template< typename Consumer > + void from_stream( Consumer& consumer, std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) + { + pegtl::istream_input in( stream, maximum_buffer_size, source ? source : "tao::json::events::jaxn::from_stream" ); + pegtl::parse< internal::grammar, internal::action, internal::errors >( in, consumer ); + } + + template< typename Consumer > + void from_stream( Consumer& consumer, std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) + { + from_stream( consumer, stream, source.c_str(), maximum_buffer_size ); + } + +} // namespace tao::json::jaxn::events + +#endif diff --git a/include/tao/json/jaxn/events/from_string.hpp b/include/tao/json/jaxn/events/from_string.hpp new file mode 100644 index 00000000..ee20ca75 --- /dev/null +++ b/include/tao/json/jaxn/events/from_string.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_JAXN_EVENTS_FROM_STRING_HPP +#define TAO_JSON_JAXN_EVENTS_FROM_STRING_HPP + +#include +#include + +#include "../../external/pegtl/memory_input.hpp" + +#include "from_input.hpp" + +namespace tao::json::jaxn::events +{ + // Events producer to parse a JAXN string representation. + + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) + { + pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::jaxn::events::from_string", byte, line, column ); + jaxn::events::from_input( consumer, std::move( in ) ); + } + + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) + { + jaxn::events::from_string( consumer, data, size, source.c_str(), byte, line, column ); + } + + template< typename Consumer, typename... Ts > + void from_string( Consumer& consumer, const std::string_view data, Ts&&... ts ) + { + jaxn::events::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); + } + +} // namespace tao::json::jaxn::events + +#endif diff --git a/include/tao/json/jaxn/events/to_pretty_stream.hpp b/include/tao/json/jaxn/events/to_pretty_stream.hpp new file mode 100644 index 00000000..cff8895d --- /dev/null +++ b/include/tao/json/jaxn/events/to_pretty_stream.hpp @@ -0,0 +1,69 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_JAXN_EVENTS_TO_PRETTY_STREAM_HPP +#define TAO_JSON_JAXN_EVENTS_TO_PRETTY_STREAM_HPP + +#include "../../internal/hexdump.hpp" + +#include "../../external/ryu.hpp" + +#include "../../events/to_pretty_stream.hpp" + +#include "../is_identifier.hpp" + +namespace tao::json::jaxn::events +{ + // Events consumer to build a JAXN string representation. + + struct to_pretty_stream + : json::events::to_pretty_stream + { + using json::events::to_pretty_stream::to_pretty_stream; + + using json::events::to_pretty_stream::number; + + void number( const double v ) + { + next(); + if( !std::isfinite( v ) ) { + if( std::isnan( v ) ) { + os.write( "NaN", 3 ); + } + else if( v < 0 ) { + os.write( "-Infinity", 9 ); + } + else { + os.write( "Infinity", 8 ); + } + } + else { + ryu::d2s_stream( os, v ); + } + } + + void binary( const tao::binary_view v ) + { + next(); + os.put( '$' ); + json::internal::hexdump( os, v ); + } + + void key( const std::string_view v ) + { + if( jaxn::is_identifier( v ) ) { + next(); + os.write( v.data(), v.size() ); + } + else { + string( v ); + } + os.write( ": ", 2 ); + first = true; + after_key = true; + } + }; + +} // namespace tao::json::jaxn::events + +#endif diff --git a/include/tao/json/jaxn/events/to_stream.hpp b/include/tao/json/jaxn/events/to_stream.hpp new file mode 100644 index 00000000..0fd96ff7 --- /dev/null +++ b/include/tao/json/jaxn/events/to_stream.hpp @@ -0,0 +1,67 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_JAXN_EVENTS_TO_STREAM_HPP +#define TAO_JSON_JAXN_EVENTS_TO_STREAM_HPP + +#include "../../events/to_stream.hpp" + +#include "../../external/ryu.hpp" + +#include "../../internal/hexdump.hpp" + +#include "../is_identifier.hpp" + +namespace tao::json::jaxn::events +{ + // Events consumer to build a JAXN string representation. + + struct to_stream + : json::events::to_stream + { + using json::events::to_stream::number; + using json::events::to_stream::to_stream; + + void number( const double v ) + { + next(); + if( !std::isfinite( v ) ) { + if( std::isnan( v ) ) { + os << "NaN"; + } + else if( v < 0 ) { + os << "-Infinity"; + } + else { + os << "Infinity"; + } + } + else { + ryu::d2s_stream( os, v ); + } + } + + void key( const std::string_view v ) + { + if( jaxn::is_identifier( v ) ) { + next(); + os.write( v.data(), v.size() ); + } + else { + string( v ); + } + os.put( ':' ); + first = true; + } + + void binary( const tao::binary_view v ) + { + next(); + os.put( '$' ); + json::internal::hexdump( os, v ); + } + }; + +} // namespace tao::json::jaxn::events + +#endif diff --git a/include/tao/json/jaxn/events/to_string.hpp b/include/tao/json/jaxn/events/to_string.hpp new file mode 100644 index 00000000..124c57da --- /dev/null +++ b/include/tao/json/jaxn/events/to_string.hpp @@ -0,0 +1,33 @@ +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_JAXN_EVENTS_TO_STRING_HPP +#define TAO_JSON_JAXN_EVENTS_TO_STRING_HPP + +#include +#include + +#include "to_stream.hpp" + +namespace tao::json::jaxn::events +{ + // Events consumer to build a JAXN string representation. + + struct to_string + : to_stream + { + std::ostringstream oss; + + to_string() + : to_stream( oss ) + {} + + [[nodiscard]] std::string value() const + { + return oss.str(); + } + }; + +} // namespace tao::json::jaxn::events + +#endif diff --git a/include/tao/json/jaxn/from_file.hpp b/include/tao/json/jaxn/from_file.hpp new file mode 100644 index 00000000..1406244a --- /dev/null +++ b/include/tao/json/jaxn/from_file.hpp @@ -0,0 +1,33 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_JAXN_FROM_FILE_HPP +#define TAO_JSON_JAXN_FROM_FILE_HPP + +#include +#include + +#include "../events/to_value.hpp" +#include "../events/transformer.hpp" + +#include "events/from_file.hpp" + +namespace tao::json::jaxn +{ + template< template< typename... > class Traits, template< typename... > class... Transformers > + [[nodiscard]] basic_value< Traits > basic_from_file( const std::string& filename ) + { + json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; + events::from_file( consumer, filename ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers > + [[nodiscard]] value from_file( const std::string& filename ) + { + return basic_from_file< traits, Transformers... >( filename ); + } + +} // namespace tao::json::jaxn + +#endif diff --git a/include/tao/json/jaxn/from_input.hpp b/include/tao/json/jaxn/from_input.hpp new file mode 100644 index 00000000..f17f2143 --- /dev/null +++ b/include/tao/json/jaxn/from_input.hpp @@ -0,0 +1,33 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_JAXN_FROM_INPUT_HPP +#define TAO_JSON_JAXN_FROM_INPUT_HPP + +#include +#include + +#include "../events/to_value.hpp" +#include "../events/transformer.hpp" + +#include "events/from_input.hpp" + +namespace tao::json::jaxn +{ + template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] basic_value< Traits > basic_from_input( Ts&&... ts ) + { + json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; + jaxn::events::from_input( consumer, std::forward< Ts >( ts )... ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] value from_input( Ts&&... ts ) + { + return basic_from_input< traits, Transformers... >( std::forward< Ts >( ts )... ); + } + +} // namespace tao::json::jaxn + +#endif diff --git a/include/tao/json/jaxn/from_stream.hpp b/include/tao/json/jaxn/from_stream.hpp index 32888ff9..615b657b 100644 --- a/include/tao/json/jaxn/from_stream.hpp +++ b/include/tao/json/jaxn/from_stream.hpp @@ -1,54 +1,48 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_JAXN_FROM_STREAM_HPP -#define TAOCPP_JSON_INCLUDE_JAXN_FROM_STREAM_HPP +#ifndef TAO_JSON_JAXN_FROM_STREAM_HPP +#define TAO_JSON_JAXN_FROM_STREAM_HPP #include #include #include -#include "../events/to_stream.hpp" +#include "../value.hpp" + +#include "../events/to_value.hpp" #include "../events/transformer.hpp" -#include "../events/jaxn/from_stream.hpp" +#include "events/from_stream.hpp" -namespace tao +namespace tao::json::jaxn { - namespace json + template< template< typename... > class Traits, template< typename... > class... Transformers > + [[nodiscard]] basic_value< Traits > basic_from_stream( std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) + { + json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; + events::from_stream( consumer, stream, source, maximum_buffer_size ); + return std::move( consumer.value ); + } + + template< template< typename... > class Traits, template< typename... > class... Transformers > + [[nodiscard]] basic_value< Traits > basic_from_stream( std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) + { + return basic_from_stream< Traits, Transformers... >( stream, source.c_str(), maximum_buffer_size ); + } + + template< template< typename... > class... Transformers > + [[nodiscard]] value from_stream( std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) + { + return basic_from_stream< traits, Transformers... >( stream, source, maximum_buffer_size ); + } + + template< template< typename... > class... Transformers > + [[nodiscard]] value from_stream( std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) { - namespace jaxn - { - template< template< typename... > class Traits, template< typename... > class... Transformers > - basic_value< Traits > basic_from_stream( std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) - { - events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; - events::jaxn::from_stream( consumer, stream, source, maximum_buffer_size ); - return std::move( consumer.value ); - } - - template< template< typename... > class Traits, template< typename... > class... Transformers > - basic_value< Traits > basic_from_stream( std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) - { - return basic_from_stream< Traits, Transformers... >( stream, source.c_str(), maximum_buffer_size ); - } - - template< template< typename... > class... Transformers > - value from_stream( std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) - { - return basic_from_stream< traits, Transformers... >( stream, source, maximum_buffer_size ); - } - - template< template< typename... > class... Transformers > - value from_stream( std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) - { - return basic_from_stream< traits, Transformers... >( stream, source.c_str(), maximum_buffer_size ); - } - - } // namespace jaxn - - } // namespace json - -} // namespace tao + return basic_from_stream< traits, Transformers... >( stream, source.c_str(), maximum_buffer_size ); + } + +} // namespace tao::json::jaxn #endif diff --git a/include/tao/json/jaxn/from_string.hpp b/include/tao/json/jaxn/from_string.hpp index 7d2f2c5d..cfc08a81 100644 --- a/include/tao/json/jaxn/from_string.hpp +++ b/include/tao/json/jaxn/from_string.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_JAXN_FROM_STRING_HPP -#define TAOCPP_JSON_INCLUDE_JAXN_FROM_STRING_HPP +#ifndef TAO_JSON_JAXN_FROM_STRING_HPP +#define TAO_JSON_JAXN_FROM_STRING_HPP #include #include @@ -10,41 +10,33 @@ #include "../events/to_value.hpp" #include "../events/transformer.hpp" -#include "../events/jaxn/from_string.hpp" +#include "events/from_string.hpp" -namespace tao +namespace tao::json::jaxn { - namespace json + template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] basic_value< Traits > basic_from_string( Ts&&... ts ) { - namespace jaxn + json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; + events::from_string( consumer, std::forward< Ts >( ts )... ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] value from_string( Ts&&... ts ) + { + return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); + } + + inline namespace literals + { + [[nodiscard]] inline value operator"" _jaxn( const char* data, const std::size_t size ) { - template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > - basic_value< Traits > basic_from_string( Ts&&... ts ) - { - events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; - events::jaxn::from_string( consumer, std::forward< Ts >( ts )... ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers, typename... Ts > - value from_string( Ts&&... ts ) - { - return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); - } - - inline namespace literals - { - inline value operator"" _jaxn( const char* data, const std::size_t size ) - { - return jaxn::from_string( data, size, "literal" ); - } - - } // namespace literals - - } // namespace jaxn - - } // namespace json - -} // namespace tao + return jaxn::from_string( data, size, "literal" ); + } + + } // namespace literals + +} // namespace tao::json::jaxn #endif diff --git a/include/tao/json/jaxn/internal/action.hpp b/include/tao/json/jaxn/internal/action.hpp new file mode 100644 index 00000000..f4f9fea1 --- /dev/null +++ b/include/tao/json/jaxn/internal/action.hpp @@ -0,0 +1,355 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_JAXN_INTERNAL_ACTION_HPP +#define TAO_JSON_JAXN_INTERNAL_ACTION_HPP + +#include +#include +#include +#include + +#include "../../external/pegtl/nothing.hpp" + +#include "../../internal/number_state.hpp" +#include "../../internal/parse_util.hpp" + +#include "bunescape_action.hpp" +#include "grammar.hpp" +#include "unescape_action.hpp" + +namespace tao::json::jaxn::internal +{ + template< typename Rule > + struct action + : pegtl::nothing< Rule > + {}; + + template<> + struct action< rules::null > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.null(); + } + }; + + template<> + struct action< rules::true_ > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.boolean( true ); + } + }; + + template<> + struct action< rules::false_ > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.boolean( false ); + } + }; + + template<> + struct action< rules::identifier > + { + template< typename Input, typename Consumer > + static void apply( const Input& in, Consumer& consumer ) + { + consumer.key( std::string_view( in.begin(), in.size() ) ); + } + }; + + template< bool NEG > + struct action< rules::hexnum< NEG > > + { + template< typename Input, typename Consumer > + static void apply( const Input& in, Consumer& consumer ) + { + std::uint64_t value = 0; + for( char c : in ) { + if( value & 0xF000000000000000 ) { + throw pegtl::parse_error( "JAXN hexadecimal number too large", in ); + } + value <<= 4; + value += json::internal::hex_char_to_integer< std::uint8_t >( c ); + } + if constexpr( NEG ) { + if( value < 9223372036854775808ULL ) { + consumer.number( -static_cast< std::int64_t >( value ) ); + } + else if( value == 9223372036854775808ULL ) { + consumer.number( static_cast< std::int64_t >( -9223372036854775807LL - 1 ) ); + } + else { + throw pegtl::parse_error( "JAXN hexadecimal number too large to negate", in ); + } + } + else { + consumer.number( value ); + } + } + }; + + template<> + struct action< rules::array::begin > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.begin_array(); + } + }; + + template<> + struct action< rules::array::element > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.element(); + } + }; + + template<> + struct action< rules::array::end > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.end_array(); + } + }; + + template<> + struct action< rules::object::begin > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.begin_object(); + } + }; + + template<> + struct action< rules::object::element > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.member(); + } + }; + + template<> + struct action< rules::object::end > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.end_object(); + } + }; + + template<> + struct action< rules::zero< false > > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.number( std::uint64_t( 0 ) ); + } + }; + + template<> + struct action< rules::zero< true > > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.number( std::int64_t( 0 ) ); + } + }; + + template<> + struct action< rules::nan > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.number( NAN ); + } + }; + + template<> + struct action< rules::infinity< false > > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.number( INFINITY ); + } + }; + + template<> + struct action< rules::infinity< true > > + { + template< typename Consumer > + static void apply0( Consumer& consumer ) + { + consumer.number( -INFINITY ); + } + }; + + template<> + struct action< rules::esign > + { + template< typename Input, bool NEG > + static void apply( const Input& in, json::internal::number_state< NEG >& result ) + { + result.eneg = ( in.peek_char() == '-' ); + } + }; + + template<> + struct action< rules::idigits > + { + template< typename Input, bool NEG > + static void apply( const Input& in, json::internal::number_state< NEG >& result ) + { + const auto s = in.size(); + + if( s == 1 && in.peek_char() == '0' ) { + return; + } + + if( s > ( 1 << 20 ) ) { + throw pegtl::parse_error( "JSON number with 1 megabyte digits", in ); + } + + const auto c = ( std::min )( s, json::internal::max_mantissa_digits ); + std::memcpy( result.mantissa, in.begin(), c ); + result.exponent10 += static_cast< typename json::internal::number_state< NEG >::exponent10_t >( s - c ); + result.msize = static_cast< typename json::internal::number_state< NEG >::msize_t >( c ); + + for( std::size_t i = c; i < s; ++i ) { + if( in.peek_char( i ) != '0' ) { + result.drop = true; + return; + } + } + } + }; + + template<> + struct action< rules::fdigits > + { + template< typename Input, bool NEG > + static void apply( const Input& in, json::internal::number_state< NEG >& result ) + { + result.isfp = true; + + const auto* b = in.begin(); + const auto* e = in.end(); + + while( ( e > b ) && ( e[ -1 ] == '0' ) ) { + --e; + } + if( !result.msize ) { + while( ( b < e ) && ( b[ 0 ] == '0' ) ) { + ++b; + --result.exponent10; + } + } + const auto c = ( std::min )( std::size_t( e - b ), json::internal::max_mantissa_digits - result.msize ); + std::memcpy( result.mantissa + result.msize, b, c ); + result.exponent10 -= static_cast< typename json::internal::number_state< NEG >::exponent10_t >( c ); + result.msize += static_cast< typename json::internal::number_state< NEG >::msize_t >( c ); + + for( const auto* r = b + c; r < e; ++r ) { + if( *r != '0' ) { + result.drop = true; + return; + } + } + } + }; + + template<> + struct action< rules::edigits > + { + template< typename Input, bool NEG > + static void apply( const Input& in, json::internal::number_state< NEG >& result ) + { + result.isfp = true; + + const char* b = in.begin(); + + while( ( b < in.end() ) && ( b[ 0 ] == '0' ) ) { + ++b; + } + if( ( in.end() - b ) > 9 ) { + throw pegtl::parse_error( "JSON exponent has more than 9 significant digits", in ); + } + int exponent10 = 0; + + while( b < in.end() ) { + exponent10 = ( exponent10 * 10 ) + ( b[ 0 ] - '0' ); + ++b; + } + result.exponent10 += ( result.eneg ? -exponent10 : exponent10 ); + } + }; + + template< bool NEG > + struct action< rules::number< NEG > > + : pegtl::change_states< tao::json::internal::number_state< NEG > > + { + template< typename Input, typename Consumer > + static void success( const Input& /*unused*/, tao::json::internal::number_state< NEG >& state, Consumer& consumer ) + { + state.success( consumer ); + } + }; + + template<> + struct action< rules::string > + : pegtl::change_action_and_states< unescape_action, std::string > + { + template< typename Input, typename Consumer > + static void success( const Input& /*unused*/, std::string& unescaped, Consumer& consumer ) + { + consumer.string( std::move( unescaped ) ); + } + }; + + template<> + struct action< rules::key > + : pegtl::change_action_and_states< unescape_action, std::string > + { + template< typename Input, typename Consumer > + static void success( const Input& /*unused*/, std::string& unescaped, Consumer& consumer ) + { + consumer.key( std::move( unescaped ) ); + } + }; + + template<> + struct action< rules::binary > + : pegtl::change_action_and_states< bunescape_action, std::vector< std::byte > > + { + template< typename Input, typename Consumer > + static void success( const Input& /*unused*/, std::vector< std::byte >& value, Consumer& consumer ) + { + consumer.binary( std::move( value ) ); + } + }; + +} // namespace tao::json::jaxn::internal + +#endif diff --git a/include/tao/json/jaxn/internal/bunescape_action.hpp b/include/tao/json/jaxn/internal/bunescape_action.hpp new file mode 100644 index 00000000..1cf981a5 --- /dev/null +++ b/include/tao/json/jaxn/internal/bunescape_action.hpp @@ -0,0 +1,114 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_JAXN_INTERNAL_BUNESCAPE_ACTION_HPP +#define TAO_JSON_JAXN_INTERNAL_BUNESCAPE_ACTION_HPP + +#include +#include + +#include "../../external/pegtl/contrib/unescape.hpp" +#include "../../external/pegtl/nothing.hpp" + +#include "grammar.hpp" + +namespace tao::json::jaxn::internal +{ + template< typename Rule > + struct bunescape_action + : pegtl::nothing< Rule > + {}; + + template<> + struct bunescape_action< rules::bescaped_char > + { + template< typename Input > + static void apply( const Input& in, std::vector< std::byte >& value ) + { + switch( *in.begin() ) { + case '"': + value.push_back( std::byte( '"' ) ); + break; + + case '\'': + value.push_back( std::byte( '\'' ) ); + break; + + case '\\': + value.push_back( std::byte( '\\' ) ); + break; + + case '/': + value.push_back( std::byte( '/' ) ); + break; + + case 'b': + value.push_back( std::byte( '\b' ) ); + break; + + case 'f': + value.push_back( std::byte( '\f' ) ); + break; + + case 'n': + value.push_back( std::byte( '\n' ) ); + break; + + case 'r': + value.push_back( std::byte( '\r' ) ); + break; + + case 't': + value.push_back( std::byte( '\t' ) ); + break; + + case 'v': + value.push_back( std::byte( '\v' ) ); + break; + + case '0': + value.push_back( std::byte( '\0' ) ); + break; + + default: + throw pegtl::parse_error( "invalid character in unescape", in ); // LCOV_EXCL_LINE + } + } + }; + + template<> + struct bunescape_action< rules::bescaped_hexcode > + { + template< typename Input > + static void apply( const Input& in, std::vector< std::byte >& value ) + { + assert( !in.empty() ); // First character MUST be present, usually 'x'. + value.push_back( static_cast< std::byte >( pegtl::unescape::unhex_string< char >( in.begin() + 1, in.end() ) ) ); + } + }; + + template< char D > + struct bunescape_action< rules::bunescaped< D > > + { + template< typename Input > + static void apply( const Input& in, std::vector< std::byte >& value ) + { + const auto begin = reinterpret_cast< const std::byte* >( in.begin() ); + const auto end = begin + in.size(); + value.insert( value.end(), begin, end ); + } + }; + + template<> + struct bunescape_action< rules::bbyte > + { + template< typename Input > + static void apply( const Input& in, std::vector< std::byte >& value ) + { + value.push_back( static_cast< std::byte >( pegtl::unescape::unhex_string< char >( in.begin(), in.end() ) ) ); + } + }; + +} // namespace tao::json::jaxn::internal + +#endif diff --git a/include/tao/json/jaxn/internal/errors.hpp b/include/tao/json/jaxn/internal/errors.hpp new file mode 100644 index 00000000..607a143e --- /dev/null +++ b/include/tao/json/jaxn/internal/errors.hpp @@ -0,0 +1,108 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_JAXN_INTERNAL_ERRORS_HPP +#define TAO_JSON_JAXN_INTERNAL_ERRORS_HPP + +#include + +#include "../../external/pegtl/normal.hpp" +#include "../../external/pegtl/parse_error.hpp" + +#include "grammar.hpp" + +namespace tao::json::jaxn::internal +{ + template< typename Rule > + struct errors + : pegtl::normal< Rule > + { + static const std::string error_message; + + template< typename Input, typename... States > + static void raise( const Input& in, States&&... /*unused*/ ) + { + throw pegtl::parse_error( error_message, in ); + } + + template< template< typename... > class Action, typename Iterator, typename Input, typename... States > + static auto apply( const Iterator& begin, const Input& in, States&&... st ) + -> decltype( Action< Rule >::apply( std::declval< const typename Input::action_t& >(), st... ) ) + { + try { + using action_t = typename Input::action_t; + const action_t action_input( begin, in ); + return Action< Rule >::apply( action_input, st... ); + } + catch( const pegtl::parse_error& ) { + throw; + } + catch( const std::exception& e ) { + throw pegtl::parse_error( e.what(), in ); + } + } + + template< template< typename... > class Action, typename Input, typename... States > + static auto apply0( const Input& in, States&&... st ) + -> decltype( Action< Rule >::apply0( st... ) ) + { + try { + return Action< Rule >::apply0( st... ); + } + catch( const pegtl::parse_error& ) { + throw; + } + catch( const std::exception& e ) { + throw pegtl::parse_error( e.what(), in ); + } + } + }; + + // clang-format off + template<> inline const std::string errors< rules::text >::error_message = "no valid JAXN"; + + template<> inline const std::string errors< rules::comment >::error_message = "expected '*' or '/'"; + template<> inline const std::string errors< rules::line_comment_char >::error_message = "invalid character in line comment"; + template<> inline const std::string errors< rules::block_comment_char >::error_message = "invalid character in block comment"; + template<> inline const std::string errors< rules::end_block_comment >::error_message = "unterminated multi-line comment"; + + template<> inline const std::string errors< rules::end_array >::error_message = "incomplete array, expected value or ']'"; + template<> inline const std::string errors< rules::end_object >::error_message = "incomplete object, expected key or '}'"; + template<> inline const std::string errors< rules::name_separator >::error_message = "expected ':'"; + template<> inline const std::string errors< rules::value >::error_message = "expected value"; + template<> inline const std::string errors< rules::sor_value >::error_message = "expected value"; + + template<> inline const std::string errors< rules::edigits >::error_message = "expected at least one exponent digit"; + template<> inline const std::string errors< rules::fdigits >::error_message = "expected at least one fraction digit"; + template<> inline const std::string errors< rules::nan >::error_message = "invalid numeric literal"; + template<> inline const std::string errors< rules::infinity< false > >::error_message = "invalid numeric literal"; + template<> inline const std::string errors< rules::infinity< true > >::error_message = "invalid numeric literal"; + template<> inline const std::string errors< rules::hexnum< false > >::error_message = "expected at least one hexadecimal digit"; + template<> inline const std::string errors< rules::hexnum< true > >::error_message = "expected at least one hexadecimal digit"; + + template<> inline const std::string errors< rules::xdigit >::error_message = "incomplete universal character name"; + template<> inline const std::string errors< rules::escaped >::error_message = "unknown escape sequence in string"; + template<> inline const std::string errors< rules::chars< '"' > >::error_message = "invalid character in string"; + template<> inline const std::string errors< rules::chars< '\'' > >::error_message = "invalid character in string"; + template<> inline const std::string errors< rules::qstring_content< '"' > >::error_message = "unterminated string"; + template<> inline const std::string errors< rules::qstring_content< '\'' > >::error_message = "unterminated string"; + template<> inline const std::string errors< rules::mchars< '"' > >::error_message = "invalid character in multiline string"; + template<> inline const std::string errors< rules::mchars< '\'' > >::error_message = "invalid character in multiline string"; + template<> inline const std::string errors< rules::mqstring_content< '"' > >::error_message = "unterminated multiline string"; + template<> inline const std::string errors< rules::mqstring_content< '\'' > >::error_message = "unterminated multiline string"; + template<> inline const std::string errors< rules::string_fragment >::error_message = "expected string"; + + template<> inline const std::string errors< rules::bescaped >::error_message = "unknown escape sequence in binary string"; + template<> inline const std::string errors< rules::bchars< '"' > >::error_message = "invalid character in binary string"; + template<> inline const std::string errors< rules::bchars< '\'' > >::error_message = "invalid character in binary string"; + template<> inline const std::string errors< rules::bqstring_content< '"' > >::error_message = "unterminated binary string"; + template<> inline const std::string errors< rules::bqstring_content< '\'' > >::error_message = "unterminated binary string"; + template<> inline const std::string errors< rules::bvalue >::error_message = "expected binary"; + template<> inline const std::string errors< rules::bpart >::error_message = "expected a pair of hexadecimal digits"; + + template<> inline const std::string errors< pegtl::eof >::error_message = "unexpected character after JAXN value"; + // clang-format on + +} // namespace tao::json::jaxn::internal + +#endif diff --git a/include/tao/json/jaxn/internal/grammar.hpp b/include/tao/json/jaxn/internal/grammar.hpp new file mode 100644 index 00000000..d0d55b70 --- /dev/null +++ b/include/tao/json/jaxn/internal/grammar.hpp @@ -0,0 +1,375 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_JAXN_INTERNAL_GRAMMAR_HPP +#define TAO_JSON_JAXN_INTERNAL_GRAMMAR_HPP + +#include + +#include "../../external/pegtl.hpp" +#include "../../external/pegtl/contrib/abnf.hpp" + +namespace tao::json::jaxn::internal +{ + // clang-format off + namespace rules + { + using namespace pegtl; + + struct line_comment_char : sor< one< '\t' >, utf8::ranges< 0x20, 0x7E, 0x80, 0x10FFFF > > {}; + struct line_comment : seq< one< '/' >, until< eolf, must< line_comment_char > > > {}; + + struct block_comment_char : sor< one< '\t' >, utf8::ranges< 0x20, 0x7E, 0x80, 0x10FFFF >, eol > {}; + struct end_block_comment : until< pegtl::string< '*', '/' >, must< block_comment_char > > {}; + struct block_comment : if_must< one< '*' >, end_block_comment > {}; + + struct comment : sor< line_comment, block_comment > {}; + + struct ws : sor< one< ' ', '\t', '\n', '\r' >, seq< one< '#' >, until< eolf > >, if_must< one< '/' >, comment > > {}; + + template< typename R, typename P = ws > + using padr = pegtl::internal::seq< R, pegtl::internal::star< P > >; + + struct begin_array : padr< one< '[' > > {}; + struct begin_object : padr< one< '{' > > {}; + struct end_array : one< ']' > {}; + struct end_object : one< '}' > {}; + struct name_separator : pad< one< ':' >, ws > {}; + struct value_separator : padr< one< ',' > > {}; + struct element_separator : padr< one< ',' > > {}; + struct value_concat : pad< one< '+' >, ws > {}; + + struct false_ : pegtl::string< 'f', 'a', 'l', 's', 'e' > {}; + struct null : pegtl::string< 'n', 'u', 'l', 'l' > {}; + struct true_ : pegtl::string< 't', 'r', 'u', 'e' > {}; + + struct nan : pegtl::string< 'N', 'a', 'N' > {}; + + template< bool NEG > + struct infinity : pegtl::string< 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y' > {}; + + template< bool NEG > + struct hexnum : plus< abnf::HEXDIG > {}; + + struct digits : plus< abnf::DIGIT > {}; + + struct esign : one< '-', '+' > {}; + + struct edigits : digits {}; + struct fdigits : digits {}; + struct idigits : digits {}; + + struct exp : seq< one< 'e', 'E' >, opt< esign >, must< edigits > > {}; + struct frac0 : seq< one< '.' >, opt< fdigits > > {}; + struct frac1 : if_must< one< '.' >, fdigits > {}; + + template< bool NEG > + struct number : seq< sor< seq< idigits, opt< frac0 > >, frac1 >, opt< exp > > {}; + + struct xdigit : abnf::HEXDIG {}; + struct escaped_unicode_code_point_content : seq< one< '{' >, plus< xdigit > > {}; + struct escaped_unicode_code_point : seq< one< 'u' >, escaped_unicode_code_point_content, one< '}' > > {}; + struct escaped_unicode : list< seq< one< 'u' >, rep< 4, xdigit > >, one< '\\' > > {}; + + struct escaped_char : one< '"', '\'', '\\', '/', 'b', 'f', 'n', 'r', 't', 'v', '0' > {}; + struct escaped : sor< escaped_char, escaped_unicode_code_point, escaped_unicode > {}; + + template< char D > + struct unescaped + { + using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; + + template< typename Input > + [[nodiscard]] static bool match( Input& in ) + { + bool result = false; + + while( const std::size_t s = in.size( 4 ) ) { + if( const auto t = pegtl::internal::peek_utf8::peek( in, s ) ) { + if( ( 0x20 <= t.data ) && ( t.data <= 0x10FFFF ) && ( t.data != '\\' ) && ( t.data != D ) && ( t.data != 0x7F ) ) { + in.bump_in_this_line( t.size ); + result = true; + continue; + } + } + return result; + } + throw pegtl::parse_error( "invalid character in string", in ); + } + }; + + template< char D > + struct chars : if_then_else< one< '\\' >, must< escaped >, unescaped< D > > {}; + + template< char D > + struct qstring_content : until< at< one< D > >, must< chars< D > > > {}; + + template< char D > + struct qstring : seq< one< D >, must< qstring_content< D > >, any > {}; + + template< char D > + struct mchars_non_eol + { + using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; + + template< typename Input > + [[nodiscard]] static bool match( Input& in ) + { + bool result = false; + + while( const std::size_t s = in.size( 4 ) ) { + if( const auto t = pegtl::internal::peek_utf8::peek( in, s ) ) { + if( ( ( 0x20 <= t.data ) && ( t.data <= 0x10FFFF ) && ( t.data != D ) && ( t.data != 0x7F ) ) || ( t.data == '\t' ) ) { + in.bump_in_this_line( t.size ); + result = true; + continue; + } + } + return result; + } + throw pegtl::parse_error( "invalid character in string", in ); + } + }; + + template< char D > + struct mchars : sor< mchars_non_eol< D >, one< D >, eol > {}; + + template< char D > + struct mqstring_content : until< at< three< D > >, must< mchars< D > > > {}; + + template< char D > + struct mqstring : seq< three< D >, opt< eol >, must< mqstring_content< D > >, any, any, any > {}; + + struct string_fragment : sor< mqstring< '"' >, mqstring< '\'' >, qstring< '"' >, qstring< '\'' > > {}; + + struct string : list_must< string_fragment, value_concat > {}; + + struct binary_prefix : one< '$' > {}; + + struct bescaped_hexcode : seq< one< 'x' >, rep< 2, must< xdigit > > > {}; + + struct bescaped_char : one< '"', '\'', '\\', '/', 'b', 'f', 'n', 'r', 't', 'v', '0' > {}; + struct bescaped : sor< bescaped_char, bescaped_hexcode > {}; + + template< char D > + struct bunescaped + { + using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; + + template< typename Input > + [[nodiscard]] static bool match( Input& in ) + { + bool result = false; + + while( !in.empty() ) { + const auto t = in.peek_char(); + if( ( 0x20 <= t ) && ( t <= 0x7E ) && ( t != '\\' ) && ( t != D ) ) { + in.bump_in_this_line( 1 ); + result = true; + continue; + } + return result; + } + throw pegtl::parse_error( "invalid character in binary string", in ); + } + }; + + template< char D > + struct bchars : if_then_else< one< '\\' >, must< bescaped >, bunescaped< D > > {}; + + template< char D > + struct bqstring_content : until< at< one< D > >, must< bchars< D > > > {}; + + template< char D > + struct bqstring : seq< one< D >, must< bqstring_content< D > >, any > {}; + + struct bstring : sor< bqstring< '"' >, bqstring< '\'' > > {}; + + struct bbyte : rep< 2, abnf::HEXDIG > {}; + + struct bpart : plus< bbyte > {}; + + struct bdirect : list_must< bpart, one< '.' > > {}; + + struct bvalue : seq< binary_prefix, opt< sor< bstring, bdirect > > > {}; + + struct binary : list_must< bvalue, value_concat > {}; + + struct value; + + struct array_element; + struct array_content : opt< list_tail< array_element, element_separator > > {}; + struct array : seq< begin_array, array_content, must< end_array > > + { + using begin = begin_array; + using end = end_array; + using element = array_element; + using content = array_content; + }; + + struct key : string {}; + + struct mkey : sor< key, identifier > {}; + struct member : if_must< mkey, name_separator, value > {}; + struct object_content : opt< list_tail< member, value_separator > > {}; + struct object : seq< begin_object, object_content, must< end_object > > + { + using begin = begin_object; + using end = end_object; + using element = member; + using content = object_content; + }; + + template< bool NEG > + struct zero : one< '0' > {}; + + struct sor_value + { + using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::sor, string, number< false >, object, array, false_, true_, null >; + + template< typename Rule, + apply_mode A, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match_must( Input& in, States&&... st ) + { + return Control< must< Rule > >::template match< A, rewind_mode::dontcare, Action, Control >( in, st... ); + } + + template< bool NEG, + apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match_zero( Input& in, States&&... st ) + { + if( in.size( 2 ) > 1 ) { + switch( in.peek_char( 1 ) ) { + case '.': + case 'e': + case 'E': + return Control< number< NEG > >::template match< A, M, Action, Control >( in, st... ); + + case 'x': + case 'X': + in.bump_in_this_line( 2 ); + return Control< must< hexnum< NEG > > >::template match< A, M, Action, Control >( in, st... ); + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + throw pegtl::parse_error( "invalid leading zero", in ); + } + } + return Control< zero< NEG > >::template match< A, M, Action, Control >( in, st... ); + } + + template< bool NEG, + apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match_number( Input& in, States&&... st ) + { + switch( in.peek_char() ) { + case 'N': + return Control< must< nan > >::template match< A, M, Action, Control >( in, st... ); + + case 'I': + return Control< must< infinity< NEG > > >::template match< A, M, Action, Control >( in, st... ); + + case '0': + if( !match_zero< NEG, A, rewind_mode::dontcare, Action, Control >( in, st... ) ) { + throw pegtl::parse_error( "incomplete number", in ); + } + return true; + + default: + return Control< number< NEG > >::template match< A, M, Action, Control >( in, st... ); + } + } + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match_impl( Input& in, States&&... st ) + { + switch( in.peek_char() ) { + case '{': return Control< object >::template match< A, M, Action, Control >( in, st... ); + case '[': return Control< array >::template match< A, M, Action, Control >( in, st... ); + case 'n': return Control< null >::template match< A, M, Action, Control >( in, st... ); + case 't': return Control< true_ >::template match< A, M, Action, Control >( in, st... ); + case 'f': return Control< false_ >::template match< A, M, Action, Control >( in, st... ); + + case '"': + case '\'': + return Control< string >::template match< A, M, Action, Control >( in, st... ); + + case '$': + return Control< binary >::template match< A, M, Action, Control >( in, st... ); + + case '+': + in.bump_in_this_line(); + if( in.empty() || !match_number< false, A, rewind_mode::dontcare, Action, Control >( in, st... ) ) { + throw pegtl::parse_error( "incomplete number", in ); + } + return true; + + case '-': + in.bump_in_this_line(); + if( in.empty() || !match_number< true, A, rewind_mode::dontcare, Action, Control >( in, st... ) ) { + throw pegtl::parse_error( "incomplete number", in ); + } + return true; + + default: + return match_number< false, A, M, Action, Control >( in, st... ); + } + } + + template< apply_mode A, + rewind_mode M, + template< typename... > class Action, + template< typename... > class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + if( in.size( 2 ) && match_impl< A, M, Action, Control >( in, st... ) ) { + in.discard(); + return true; + } + return false; + } + }; + + struct value : padr< sor_value > {}; + struct array_element : value {}; + + struct text : seq< star< ws >, value > {}; + + } // namespace rules + + struct grammar : pegtl::must< rules::text, pegtl::eof > {}; + struct embedded : pegtl::must< rules::sor_value > {}; + // clang-format on + +} // namespace tao::json::jaxn::internal + +#endif diff --git a/include/tao/json/jaxn/internal/integer.hpp b/include/tao/json/jaxn/internal/integer.hpp new file mode 100644 index 00000000..b4b72dbc --- /dev/null +++ b/include/tao/json/jaxn/internal/integer.hpp @@ -0,0 +1,256 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_JAXN_INTERNAL_INTEGER_HPP +#define TAO_JSON_JAXN_INTERNAL_INTEGER_HPP + +#include +#include +#include + +#include +#include + +#include "../../external/pegtl.hpp" +#include "../../external/pegtl/contrib/integer.hpp" + +#include "../../internal/parse_util.hpp" + +namespace tao::json::jaxn::internal::integer +{ + struct unsigned_rule + : pegtl::if_then_else< pegtl::one< '0' >, pegtl::if_then_else< pegtl::one< 'x' >, pegtl::plus< pegtl::xdigit >, pegtl::not_at< pegtl::digit > >, pegtl::plus< pegtl::digit > > + { + // Unsigned hex or dec integer, no leading zeros for dec. + }; + + struct signed_rule + : pegtl::seq< pegtl::opt< pegtl::one< '-', '+' > >, unsigned_rule > + { + // Signed hex or dec integer, no leading zeros for dec. + }; + + [[nodiscard]] constexpr bool is_hex_digit( const char c ) noexcept + { + // We don't use std::isxdigit() because it might + // return true for other values on MS platforms? + + return ( ( '0' <= c ) && ( c <= '9' ) ) || ( ( 'a' <= c ) && ( c <= 'f' ) ) || ( ( 'A' <= c ) && ( c <= 'F' ) ); + } + + template< typename Integer, Integer Maximum = ( std::numeric_limits< Integer >::max )() > + [[nodiscard]] constexpr bool accumulate_hex_digit( Integer& result, const char xdigit ) noexcept + { + // Assumes that xdigit is an xdigit as per is_hex_digit(); returns false on overflow. + + static_assert( std::is_integral_v< Integer > ); + + constexpr Integer cutoff = Maximum / 16; + constexpr Integer cutlim = Maximum % 16; + + const Integer c = json::internal::hex_char_to_integer< Integer >( xdigit ); + + if( ( result > cutoff ) || ( ( result == cutoff ) && ( c > cutlim ) ) ) { + return false; + } + result *= 16; + result += c; + return true; + } + + template< typename Integer, Integer Maximum = ( std::numeric_limits< Integer >::max )() > + [[nodiscard]] constexpr bool accumulate_hex_digits( Integer& result, const std::string_view input ) noexcept + { + // Assumes input is a non-empty sequence of hex-digits; returns false on overflow. + + for( const auto c : input ) { + if( !accumulate_hex_digit< Integer, Maximum >( result, c ) ) { + return false; + } + } + return true; + } + + template< typename Integer, Integer Maximum = ( std::numeric_limits< Integer >::max )() > + [[nodiscard]] constexpr bool convert_hex_positive( Integer& result, const std::string_view input ) noexcept + { + // Assumes result == 0 and that input is a non-empty sequence of hex-digits; returns false on overflow. + + static_assert( std::is_integral_v< Integer > ); + return accumulate_hex_digits< Integer, Maximum >( result, input ); + } + + template< typename Signed > + [[nodiscard]] constexpr bool convert_hex_negative( Signed& result, const std::string_view input ) noexcept + { + // Assumes result == 0 and that input is a non-empty sequence of hex-digits; returns false on overflow. + + static_assert( std::is_signed_v< Signed > ); + using Unsigned = std::make_unsigned_t< Signed >; + constexpr Unsigned maximum = static_cast< Unsigned >( ( std::numeric_limits< Signed >::max )() ) + 1; + Unsigned temporary = 0; + if( accumulate_hex_digits< Unsigned, maximum >( temporary, input ) ) { + result = static_cast< Signed >( ~temporary ) + 1; + return true; + } + return false; + } + + template< typename Unsigned, Unsigned Maximum = ( std::numeric_limits< Unsigned >::max )() > + [[nodiscard]] constexpr bool convert_hex_unsigned( Unsigned& result, const std::string_view input ) noexcept + { + // Assumes result == 0 and that input is a non-empty sequence of hex-digits; returns false on overflow. + + static_assert( std::is_unsigned_v< Unsigned > ); + return accumulate_hex_digits< Unsigned, Maximum >( result, input ); + } + + template< typename Signed > + [[nodiscard]] constexpr bool convert_hex_signed( Signed& result, const std::string_view input ) noexcept + { + // Assumes result == 0 and that input is an optional sign followed by a "0x" and a non-empty sequence of hex-digits; returns false on overflow. + + static_assert( std::is_signed_v< Signed > ); + if( input[ 0 ] == '-' ) { + return convert_hex_negative< Signed >( result, std::string_view( input.data() + 3, input.size() - 3 ) ); + } + const auto offset = unsigned( input[ 0 ] == '+' ) + 2; // The "0x" prefix has length 2. + return convert_hex_positive< Signed >( result, std::string_view( input.data() + offset, input.size() - offset ) ); + } + + using unsigned_dec_action = pegtl::integer::unsigned_action; + + struct unsigned_hex_action + { + // Assumes that 'in' contains a non-empty sequence of ASCII hex-digits with "0x" prefix. + + template< typename Input > + static auto apply( const Input& in, std::uint64_t& st ) + { + auto sv = in.string_view(); + sv.remove_prefix( 2 ); + if( !convert_hex_unsigned( st, sv ) ) { + throw pegtl::parse_error( "unsigned hex integer overflow", in ); + } + } + }; + + template< typename Rule > + struct unsigned_action_action + : pegtl::nothing< Rule > + { + }; + + template<> + struct unsigned_action_action< pegtl::plus< pegtl::digit > > + : unsigned_dec_action + { + }; + + template<> + struct unsigned_action_action< pegtl::plus< pegtl::xdigit > > + { + template< typename Input, typename Unsigned > + static void apply( const Input& in, Unsigned& st ) + { + if( !convert_hex_unsigned( st, in.string_view() ) ) { + throw pegtl::parse_error( "unsigned hex integer overflow", in ); + } + } + }; + + struct unsigned_rule_with_action + { + using analyze_t = unsigned_rule::analyze_t; + + template< pegtl::apply_mode, + pegtl::rewind_mode, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input > + [[nodiscard]] static auto match( Input& in, std::uint64_t& st ) + { + return pegtl::parse< unsigned_rule, unsigned_action_action >( in, st ); // Throws on overflow. + } + }; + + using signed_dec_action = pegtl::integer::signed_action; + + struct signed_hex_action + { + // Assumes that 'in' contains a non-empty sequence of ASCII hex-digits, + // with optional leading sign before the "0x" prefix; when there is a + // sign, in.size() must be >= 4. + + template< typename Input > + static auto apply( const Input& in, std::int64_t& st ) + { + if( !convert_hex_signed( st, in.string_view() ) ) { + throw pegtl::parse_error( "signed hex integer overflow", in ); + } + } + }; + + template< typename Rule > + struct signed_action_action + : pegtl::nothing< Rule > + { + }; + + template<> + struct signed_action_action< pegtl::one< '-', '+' > > + { + template< typename Input, typename Signed > + static void apply( const Input& in, bool& negative, Signed& /*unused*/ ) + { + negative = ( in.peek_char() == '-' ); // TODO: Optimise with custom rule to prevent building marker and action_input for single char? + } + }; + + template<> + struct signed_action_action< pegtl::plus< pegtl::digit > > + { + template< typename Input, typename Signed > + static void apply( const Input& in, const bool negative, Signed& st ) + { + if( !( negative ? pegtl::integer::internal::convert_negative< Signed >( st, in.string_view() ) : pegtl::integer::internal::convert_positive< Signed >( st, in.string_view() ) ) ) { + throw pegtl::parse_error( "signed dec integer overflow", in ); + } + } + }; + + template<> + struct signed_action_action< pegtl::plus< pegtl::xdigit > > + { + template< typename Input, typename Signed > + static void apply( const Input& in, const bool negative, Signed& st ) + { + if( !( negative ? convert_hex_negative< Signed >( st, in.string_view() ) : convert_hex_positive< Signed >( st, in.string_view() ) ) ) { + throw pegtl::parse_error( "signed hex integer overflow", in ); + } + } + }; + + struct signed_rule_with_action + { + using analyze_t = signed_rule::analyze_t; + + template< pegtl::apply_mode, + pegtl::rewind_mode, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input > + [[nodiscard]] static auto match( Input& in, std::int64_t& st ) + { + bool negative = false; // Superfluous initialisation. + return pegtl::parse< signed_rule, signed_action_action >( in, negative, st ); // Throws on overflow. + } + }; + +} // namespace tao::json::jaxn::internal::integer + +#endif diff --git a/include/tao/json/jaxn/internal/unescape_action.hpp b/include/tao/json/jaxn/internal/unescape_action.hpp new file mode 100644 index 00000000..48b46bb5 --- /dev/null +++ b/include/tao/json/jaxn/internal/unescape_action.hpp @@ -0,0 +1,28 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_JAXN_INTERNAL_UNESCAPE_ACTION_HPP +#define TAO_JSON_JAXN_INTERNAL_UNESCAPE_ACTION_HPP + +#include "../../external/pegtl/contrib/unescape.hpp" +#include "../../external/pegtl/nothing.hpp" + +#include "grammar.hpp" + +namespace tao::json::jaxn::internal +{ + // clang-format off + template< typename Rule > struct unescape_action : pegtl::nothing< Rule > {}; + + template<> struct unescape_action< rules::escaped_char > : pegtl::unescape::unescape_c< rules::escaped_char, '"', '\'', '\\', '/', '\b', '\f', '\n', '\r', '\t', '\v', '\0' > {}; + template<> struct unescape_action< rules::escaped_unicode > : pegtl::unescape::unescape_j {}; + template<> struct unescape_action< rules::escaped_unicode_code_point_content > : pegtl::unescape::unescape_u {}; + + template<> struct unescape_action< rules::identifier > : pegtl::unescape::append_all {}; // For parts_parser. + template< char D > struct unescape_action< rules::unescaped< D > > : pegtl::unescape::append_all {}; + template< char D > struct unescape_action< rules::mchars< D > > : pegtl::unescape::append_all {}; + // clang-format on + +} // namespace tao::json::jaxn::internal + +#endif diff --git a/include/tao/json/jaxn/is_identifier.hpp b/include/tao/json/jaxn/is_identifier.hpp index e8c15656..8268c575 100644 --- a/include/tao/json/jaxn/is_identifier.hpp +++ b/include/tao/json/jaxn/is_identifier.hpp @@ -1,35 +1,27 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_JAXN_IS_IDENTIFIER_HPP -#define TAOCPP_JSON_INCLUDE_JAXN_IS_IDENTIFIER_HPP +#ifndef TAO_JSON_JAXN_IS_IDENTIFIER_HPP +#define TAO_JSON_JAXN_IS_IDENTIFIER_HPP #include -#include +#include -namespace tao +namespace tao::json::jaxn { - namespace json + [[nodiscard]] inline bool is_identifier( const std::string_view v ) noexcept { - namespace jaxn - { - inline bool is_identifier( const tao::string_view v ) noexcept - { - if( v.empty() || std::isdigit( v[ 0 ] ) ) { - return false; - } - for( const auto c : v ) { - if( !std::isalnum( c ) && c != '_' ) { - return false; - } - } - return true; + if( v.empty() || std::isdigit( v[ 0 ] ) ) { + return false; + } + for( const auto c : v ) { + if( !std::isalnum( c ) && c != '_' ) { + return false; } + } + return true; + } - } // namespace jaxn - - } // namespace json - -} // namespace tao +} // namespace tao::json::jaxn #endif diff --git a/include/tao/json/jaxn/parse_file.hpp b/include/tao/json/jaxn/parse_file.hpp deleted file mode 100644 index d2c82834..00000000 --- a/include/tao/json/jaxn/parse_file.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_JAXN_PARSE_FILE_HPP -#define TAOCPP_JSON_INCLUDE_JAXN_PARSE_FILE_HPP - -#include -#include - -#include "../events/to_value.hpp" -#include "../events/transformer.hpp" - -#include "../events/jaxn/parse_file.hpp" - -namespace tao -{ - namespace json - { - namespace jaxn - { - template< template< typename... > class Traits, template< typename... > class... Transformers > - basic_value< Traits > basic_parse_file( const std::string& filename ) - { - events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; - events::jaxn::parse_file( consumer, filename ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers > - value parse_file( const std::string& filename ) - { - return basic_parse_file< traits, Transformers... >( filename ); - } - - } // namespace jaxn - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/jaxn/parts_parser.hpp b/include/tao/json/jaxn/parts_parser.hpp new file mode 100644 index 00000000..61240c32 --- /dev/null +++ b/include/tao/json/jaxn/parts_parser.hpp @@ -0,0 +1,263 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_JAXN_PARTS_PARSER_HPP +#define TAO_JSON_JAXN_PARTS_PARSER_HPP + +#include "../parts_parser.hpp" + +#include "internal/action.hpp" +#include "internal/bunescape_action.hpp" +#include "internal/grammar.hpp" +#include "internal/integer.hpp" +#include "internal/unescape_action.hpp" + +namespace tao::json::jaxn +{ + namespace internal + { + namespace rules + { + struct double_rule + { + using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match_impl( Input& in, States&&... st ) + { + switch( in.peek_char() ) { + case '+': + in.bump_in_this_line(); + if( in.empty() || !sor_value::match_number< false, A, rewind_mode::dontcare, Action, Control >( in, st... ) ) { + throw pegtl::parse_error( "incomplete number", in ); + } + return true; + + case '-': + in.bump_in_this_line(); + if( in.empty() || !sor_value::match_number< true, A, rewind_mode::dontcare, Action, Control >( in, st... ) ) { + throw pegtl::parse_error( "incomplete number", in ); + } + return true; + + default: + return sor_value::match_number< false, A, M, Action, Control >( in, st... ); + } + } + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + return in.size( 2 ) && match_impl< A, M, Action, Control >( in, st... ); + } + }; + + } // namespace rules + + template< typename Rule > + struct double_action + : action< Rule > + {}; + + template< bool NEG > + struct double_action< rules::number< NEG > > + : pegtl::change_states< json::internal::number_state< NEG > > + { + template< typename Input, typename Consumer > + static void success( const Input& /*unused*/, json::internal::number_state< NEG >& state, Consumer& consumer ) + { + state.success( consumer ); + } + }; + + } // namespace internal + + // TODO: Optimise some of the simpler cases? + + template< typename Input = pegtl::string_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, std::string > > + class basic_parts_parser + { + public: + template< typename... Ts > + explicit basic_parts_parser( Ts&&... ts ) + : m_input( std::forward< Ts >( ts )... ) + { + pegtl::parse< json::internal::rules::wss >( m_input ); + } + + [[nodiscard]] bool empty() // noexcept( noexcept( m_input.empty() ) ) + { + return m_input.empty(); + } + + [[nodiscard]] bool null() + { + return pegtl::parse< pegtl::seq< json::internal::rules::null, json::internal::rules::wss > >( m_input ); + } + + [[nodiscard]] bool boolean() + { + bool r; + pegtl::parse< pegtl::must< json::internal::rules::boolean, json::internal::rules::wss > >( m_input, r ); + return r; + } + + [[nodiscard]] double number_double() + { + json::internal::double_state_and_consumer st; + pegtl::parse< pegtl::must< internal::rules::double_rule, json::internal::rules::wss >, internal::double_action >( m_input, st ); + return st.converted; + } + + [[nodiscard]] std::int64_t number_signed() + { + std::int64_t st = 0; + pegtl::parse< pegtl::must< internal::integer::signed_rule_with_action, json::internal::rules::wss > >( m_input, st ); + return st; + } + + [[nodiscard]] std::uint64_t number_unsigned() + { + std::uint64_t st = 0; + pegtl::parse< pegtl::must< internal::integer::unsigned_rule_with_action, json::internal::rules::wss > >( m_input, st ); + return st; + } + + [[nodiscard]] std::string string() + { + std::string unescaped; + pegtl::parse< pegtl::must< internal::rules::string, json::internal::rules::wss >, internal::unescape_action >( m_input, unescaped ); + return unescaped; + } + + // TODO: std::string_view string_view() that only works for strings without escape sequences? + + [[nodiscard]] std::vector< std::byte > binary() + { + std::vector< std::byte > data; + pegtl::parse< pegtl::must< internal::rules::binary, json::internal::rules::wss >, internal::bunescape_action >( m_input, data ); + return data; + } + + [[nodiscard]] std::string key() + { + std::string unescaped; + pegtl::parse< pegtl::must< internal::rules::mkey, json::internal::rules::wss, pegtl::one< ':' >, json::internal::rules::wss >, internal::unescape_action >( m_input, unescaped ); + return unescaped; + } + + // TODO: std::string_view key_view() that only works for identifiers (and possibly strings without escape sequences)? + + protected: + template< char C > + void parse_single_must() + { + pegtl::parse< pegtl::must< pegtl::one< C >, json::internal::rules::wss > >( m_input ); + } + + template< char C > + bool parse_single_test() + { + return pegtl::parse< pegtl::seq< pegtl::one< C >, json::internal::rules::wss > >( m_input ); + } + + struct state_t + { + std::size_t i = 0; + static constexpr std::size_t* size = nullptr; + }; + + public: + [[nodiscard]] state_t begin_array() + { + parse_single_must< '[' >(); + return state_t(); + } + + void end_array( state_t& /*unused*/ ) + { + parse_single_must< ']' >(); + } + + void element( state_t& p ) + { + if( p.i++ ) { + parse_single_must< ',' >(); + } + } + + [[nodiscard]] bool element_or_end_array( state_t& p ) + { + if( parse_single_test< ']' >() ) { + return false; + } + element( p ); + return true; + } + + [[nodiscard]] state_t begin_object() + { + parse_single_must< '{' >(); + return state_t(); + } + + void end_object( state_t& /*unused*/ ) + { + parse_single_must< '}' >(); + } + + void member( state_t& p ) + { + if( p.i++ ) { + parse_single_must< ',' >(); + } + } + + [[nodiscard]] bool member_or_end_object( state_t& p ) + { + if( parse_single_test< '}' >() ) { + return false; + } + member( p ); + return true; + } + + void skip_value() + { + pegtl::parse< pegtl::must< pegtl::json::value > >( m_input ); // Includes right-padding. + } + + [[nodiscard]] auto mark() // noexcept( noexcept( m_input.template mark< pegtl::rewind_mode::required >() ) ) + { + return m_input.template mark< pegtl::rewind_mode::required >(); + } + + template< typename T > + void throw_parse_error( T&& t ) const + { + throw pegtl::parse_error( std::forward< T >( t ), m_input ); + } + + protected: + Input m_input; + }; + + using parts_parser = basic_parts_parser<>; + +} // namespace tao::json::jaxn + +#endif diff --git a/include/tao/json/jaxn/to_stream.hpp b/include/tao/json/jaxn/to_stream.hpp index 5bd4d19f..ba0a6a0c 100644 --- a/include/tao/json/jaxn/to_stream.hpp +++ b/include/tao/json/jaxn/to_stream.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_JAXN_TO_STREAM_HPP -#define TAOCPP_JSON_INCLUDE_JAXN_TO_STREAM_HPP +#ifndef TAO_JSON_JAXN_TO_STREAM_HPP +#define TAO_JSON_JAXN_TO_STREAM_HPP #include #include @@ -12,33 +12,25 @@ #include "../events/from_value.hpp" #include "../events/transformer.hpp" -#include "../events/jaxn/to_pretty_stream.hpp" -#include "../events/jaxn/to_stream.hpp" +#include "events/to_pretty_stream.hpp" +#include "events/to_stream.hpp" -namespace tao +namespace tao::json::jaxn { - namespace json + template< template< typename... > class... Transformers, template< typename... > class Traits > + void to_stream( std::ostream& os, const basic_value< Traits >& v ) { - namespace jaxn - { - template< template< typename... > class... Transformers, template< typename... > class Traits > - void to_stream( std::ostream& os, const basic_value< Traits >& v ) - { - events::transformer< events::jaxn::to_stream, Transformers... > consumer( os ); - events::from_value( consumer, v ); - } - - template< template< typename... > class... Transformers, template< typename... > class Traits > - void to_stream( std::ostream& os, const basic_value< Traits >& v, const std::size_t indent ) - { - events::transformer< events::jaxn::to_pretty_stream, Transformers... > consumer( os, indent ); - events::from_value( consumer, v ); - } - - } // namespace jaxn - - } // namespace json - -} // namespace tao + json::events::transformer< events::to_stream, Transformers... > consumer( os ); + json::events::from_value( consumer, v ); + } + + template< template< typename... > class... Transformers, template< typename... > class Traits > + void to_stream( std::ostream& os, const basic_value< Traits >& v, const std::size_t indent ) + { + json::events::transformer< events::to_pretty_stream, Transformers... > consumer( os, indent ); + json::events::from_value( consumer, v ); + } + +} // namespace tao::json::jaxn #endif diff --git a/include/tao/json/jaxn/to_string.hpp b/include/tao/json/jaxn/to_string.hpp index bff574b3..5b64c8cd 100644 --- a/include/tao/json/jaxn/to_string.hpp +++ b/include/tao/json/jaxn/to_string.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_JAXN_TO_STRING_HPP -#define TAOCPP_JSON_INCLUDE_JAXN_TO_STRING_HPP +#ifndef TAO_JSON_JAXN_TO_STRING_HPP +#define TAO_JSON_JAXN_TO_STRING_HPP #include @@ -10,32 +10,24 @@ #include "to_stream.hpp" -namespace tao +namespace tao::json::jaxn { - namespace json + template< template< typename... > class... Transformers, template< typename... > class Traits > + [[nodiscard]] std::string to_string( const basic_value< Traits >& v ) { - namespace jaxn - { - template< template< typename... > class... Transformers, template< typename... > class Traits > - std::string to_string( const basic_value< Traits >& v ) - { - std::ostringstream o; - jaxn::to_stream< Transformers... >( o, v ); - return o.str(); - } - - template< template< typename... > class... Transformers, template< typename... > class Traits > - std::string to_string( const basic_value< Traits >& v, const unsigned indent ) - { - std::ostringstream o; - jaxn::to_stream< Transformers... >( o, v, indent ); - return o.str(); - } - - } // namespace jaxn - - } // namespace json - -} // namespace tao + std::ostringstream o; + jaxn::to_stream< Transformers... >( o, v ); + return o.str(); + } + + template< template< typename... > class... Transformers, template< typename... > class Traits > + [[nodiscard]] std::string to_string( const basic_value< Traits >& v, const unsigned indent ) + { + std::ostringstream o; + jaxn::to_stream< Transformers... >( o, v, indent ); + return o.str(); + } + +} // namespace tao::json::jaxn #endif diff --git a/include/tao/json/message_extension.hpp b/include/tao/json/message_extension.hpp new file mode 100644 index 00000000..f524354b --- /dev/null +++ b/include/tao/json/message_extension.hpp @@ -0,0 +1,49 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_MESSAGE_EXTENSION_HPP +#define TAO_JSON_MESSAGE_EXTENSION_HPP + +#include +#include + +namespace tao::json +{ + template< typename T, typename = void > + struct message_extension + { + const T& m_v; + + explicit message_extension( const T& v ) noexcept + : m_v( v ) + {} + + friend std::ostream& operator<<( std::ostream& os, const message_extension& /*unused*/ ) noexcept + { + return os; + } + }; + + template< typename T > + struct message_extension< T, decltype( std::declval< const T& >().public_base().append_message_extension( std::declval< std::ostream& >() ), void() ) > + { + const T& m_v; + + explicit message_extension( const T& v ) noexcept + : m_v( v ) + {} + + friend std::ostream& operator<<( std::ostream& os, const message_extension& v ) + { + os << ' '; + v.m_v.public_base().append_message_extension( os ); + return os; + } + }; + + template< typename T > + message_extension( const T& )->message_extension< T >; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/msgpack.hpp b/include/tao/json/msgpack.hpp index 4a6fbf94..8e9c4f73 100644 --- a/include/tao/json/msgpack.hpp +++ b/include/tao/json/msgpack.hpp @@ -1,12 +1,17 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_MSGPACK_HPP -#define TAOCPP_JSON_INCLUDE_MSGPACK_HPP +#ifndef TAO_JSON_MSGPACK_HPP +#define TAO_JSON_MSGPACK_HPP #include "../json.hpp" +#include "msgpack/consume_file.hpp" +#include "msgpack/consume_string.hpp" +#include "msgpack/from_file.hpp" +#include "msgpack/from_input.hpp" #include "msgpack/from_string.hpp" +#include "msgpack/parts_parser.hpp" #include "msgpack/to_stream.hpp" #include "msgpack/to_string.hpp" diff --git a/include/tao/json/msgpack/consume_file.hpp b/include/tao/json/msgpack/consume_file.hpp new file mode 100644 index 00000000..3a8db14d --- /dev/null +++ b/include/tao/json/msgpack/consume_file.hpp @@ -0,0 +1,34 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_MSGPACK_CONSUME_FILE_HPP +#define TAO_JSON_MSGPACK_CONSUME_FILE_HPP + +#include + +#include "../external/pegtl/file_input.hpp" + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "parts_parser.hpp" + +namespace tao::json::msgpack +{ + template< typename T, template< typename... > class Traits = traits, typename F > + [[nodiscard]] T consume_file( F&& filename ) + { + msgpack::basic_parts_parser< utf8_mode::check, pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); + return json::consume< T, Traits >( pp ); + } + + template< template< typename... > class Traits = traits, typename F, typename T > + void consume_file( F&& filename, T& t ) + { + msgpack::basic_parts_parser< utf8_mode::check, pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); + json::consume< Traits >( pp, t ); + } + +} // namespace tao::json::msgpack + +#endif diff --git a/include/tao/json/msgpack/consume_string.hpp b/include/tao/json/msgpack/consume_string.hpp new file mode 100644 index 00000000..c27d62b8 --- /dev/null +++ b/include/tao/json/msgpack/consume_string.hpp @@ -0,0 +1,32 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_MSGPACK_CONSUME_STRING_HPP +#define TAO_JSON_MSGPACK_CONSUME_STRING_HPP + +#include "../external/pegtl/string_input.hpp" + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "parts_parser.hpp" + +namespace tao::json::msgpack +{ + template< typename T, template< typename... > class Traits = traits, typename F > + [[nodiscard]] T consume_string( F&& string ) + { + msgpack::basic_parts_parser< utf8_mode::check, pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); + return json::consume< T, Traits >( pp ); + } + + template< template< typename... > class Traits = traits, typename F, typename T > + void consume_string( F&& string, T& t ) + { + msgpack::basic_parts_parser< utf8_mode::check, pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); + json::consume< Traits >( pp, t ); + } + +} // namespace tao::json::msgpack + +#endif diff --git a/include/tao/json/msgpack/events/from_file.hpp b/include/tao/json/msgpack/events/from_file.hpp new file mode 100644 index 00000000..aed9475f --- /dev/null +++ b/include/tao/json/msgpack/events/from_file.hpp @@ -0,0 +1,27 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_MSGPACK_EVENTS_FROM_FILE_HPP +#define TAO_JSON_MSGPACK_EVENTS_FROM_FILE_HPP + +#include + +#include "../../external/pegtl/file_input.hpp" +#include "../../external/pegtl/parse.hpp" + +#include "../internal/grammar.hpp" + +namespace tao::json::msgpack::events +{ + // Events producer to parse a file containing a MSGPACK string representation. + + template< typename T, typename Consumer > + void from_file( Consumer& consumer, T&& filename ) + { + pegtl::file_input< pegtl::tracking_mode::lazy > in( std::forward< T >( filename ) ); + pegtl::parse< internal::grammar >( in, consumer ); + } + +} // namespace tao::json::msgpack::events + +#endif diff --git a/include/tao/json/msgpack/events/from_input.hpp b/include/tao/json/msgpack/events/from_input.hpp new file mode 100644 index 00000000..0e8be5aa --- /dev/null +++ b/include/tao/json/msgpack/events/from_input.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_MSGPACK_EVENTS_FROM_INPUT_HPP +#define TAO_JSON_MSGPACK_EVENTS_FROM_INPUT_HPP + +#include + +#include "../../external/pegtl/parse.hpp" + +#include "../internal/grammar.hpp" + +namespace tao::json::msgpack::events +{ + // Events producers that parse MSGPACK from a PEGTL input (or something compatible). + + template< typename Consumer, typename Input > + void from_input( Consumer& consumer, Input&& in ) + { + pegtl::parse< msgpack::internal::grammar >( std::forward< Input >( in ), consumer ); + } + + template< typename Consumer, typename Input > + void from_input_embedded( Consumer& consumer, Input&& in ) + { + pegtl::parse< msgpack::internal::embedded >( std::forward< Input >( in ), consumer ); + } + + template< typename Consumer, typename Outer, typename Input > + void from_input_nested( Consumer& consumer, const Outer& oi, Input&& in ) + { + pegtl::parse_nested< msgpack::internal::grammar >( oi, std::forward< Input >( in ), consumer ); + } + + template< typename Consumer, typename Outer, typename Input > + void from_input_embedded_nested( Consumer& consumer, const Outer& oi, Input&& in ) + { + pegtl::parse_nested< msgpack::internal::embedded >( oi, std::forward< Input >( in ), consumer ); + } + +} // namespace tao::json::msgpack::events + +#endif diff --git a/include/tao/json/msgpack/events/from_string.hpp b/include/tao/json/msgpack/events/from_string.hpp new file mode 100644 index 00000000..7bcdf1dd --- /dev/null +++ b/include/tao/json/msgpack/events/from_string.hpp @@ -0,0 +1,37 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_MSGPACK_EVENTS_FROM_STRING_HPP +#define TAO_JSON_MSGPACK_EVENTS_FROM_STRING_HPP + +#include +#include + +#include "../../external/pegtl/memory_input.hpp" + +#include "from_input.hpp" + +namespace tao::json::msgpack::events +{ + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t byte_in_line = 0 ) + { + pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::msgpack::from_string", byte, line, byte_in_line ); + msgpack::events::from_input( consumer, std::move( in ) ); + } + + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t byte_in_line = 0 ) + { + msgpack::events::from_string( consumer, data, size, source.c_str(), byte, line, byte_in_line ); + } + + template< typename Consumer, typename... Ts > + void from_string( Consumer& consumer, const std::string_view data, Ts&&... ts ) + { + msgpack::events::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); + } + +} // namespace tao::json::msgpack::events + +#endif diff --git a/include/tao/json/msgpack/events/to_stream.hpp b/include/tao/json/msgpack/events/to_stream.hpp new file mode 100644 index 00000000..b41906ac --- /dev/null +++ b/include/tao/json/msgpack/events/to_stream.hpp @@ -0,0 +1,214 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_MSGPACK_EVENTS_TO_STREAM_HPP +#define TAO_JSON_MSGPACK_EVENTS_TO_STREAM_HPP + +#include +#include +#include +#include +#include +#include +#include + +#include "../../binary_view.hpp" + +#include "../../internal/endian.hpp" + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4310 ) +#endif + +namespace tao::json::msgpack::events +{ + class to_stream + { + private: + std::ostream& os; + + public: + explicit to_stream( std::ostream& in_os ) noexcept + : os( in_os ) + {} + + void null() + { + os.put( char( 0xc0 ) ); + } + + void boolean( const bool v ) + { + os.put( char( 0xc2 ) + char( v ) ); + } + + template< typename Integer > + void number_impl( const unsigned char tag, const std::uint64_t v ) + { + os.put( char( tag ) ); + const Integer x = json::internal::h_to_be( Integer( v ) ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + + void number( const std::int64_t v ) + { + if( ( v >= -32 ) && ( v <= -1 ) ) { + const auto x = static_cast< std::int8_t >( v ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else if( ( v >= -128 ) && ( v <= 127 ) ) { + number_impl< std::uint8_t >( 0xd0, v ); + } + else if( ( v >= -32768 ) && ( v <= 32767 ) ) { + number_impl< std::uint16_t >( 0xd1, v ); + } + else if( ( v >= -2147483648LL ) && ( v <= 2147483647 ) ) { + number_impl< std::uint32_t >( 0xd2, v ); + } + else { + number_impl< std::uint64_t >( 0xd3, v ); + } + } + + void number( const std::uint64_t v ) + { + if( v <= 127 ) { + const auto x = static_cast< std::int8_t >( v ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else if( v <= 255 ) { + number_impl< std::uint8_t >( 0xcc, v ); + } + else if( v <= 65535 ) { + number_impl< std::uint16_t >( 0xcd, v ); + } + else if( v <= 4294967295UL ) { + number_impl< std::uint32_t >( 0xce, v ); + } + else { + number_impl< std::uint64_t >( 0xcf, v ); + } + } + + void number( const double v ) + { + os.put( char( 0xcb ) ); + const auto x = json::internal::h_to_be( v ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + + void string( const std::string_view v ) + { + if( v.size() <= 31 ) { + os.put( char( v.size() + 0xa0 ) ); + } + else if( v.size() <= 255 ) { + number_impl< std::uint8_t >( 0xd9, v.size() ); + } + else if( v.size() <= 65535 ) { + number_impl< std::uint16_t >( 0xda, v.size() ); + } + else if( v.size() <= 4294967295UL ) { + number_impl< std::uint32_t >( 0xdb, v.size() ); + } + else { + throw std::runtime_error( "string too long for msgpack" ); + } + os.write( v.data(), v.size() ); + } + + void binary( const tao::binary_view v ) + { + if( v.size() <= 255 ) { + number_impl< std::uint8_t >( 0xc4, v.size() ); + } + else if( v.size() <= 65535 ) { + number_impl< std::uint16_t >( 0xc5, v.size() ); + } + else if( v.size() <= 4294967295UL ) { + number_impl< std::uint32_t >( 0xc6, v.size() ); + } + else { + throw std::runtime_error( "binary too long for msgpack" ); + } + os.write( reinterpret_cast< const char* >( v.data() ), v.size() ); + } + + void begin_array() + { + throw std::runtime_error( "msgpack requires array size" ); + } + + void begin_array( const std::size_t size ) + { + if( size <= 15 ) { + os.put( char( 0x90 + size ) ); + } + else if( size <= 65535 ) { + number_impl< std::uint16_t >( 0xdc, size ); + } + else if( size <= 4294967295UL ) { + number_impl< std::uint32_t >( 0xdd, size ); + } + else { + throw std::runtime_error( "array too large for msgpack" ); + } + } + + void element() noexcept + {} + + void end_array() + { + assert( false ); // LCOV_EXCL_LINE + } + + void end_array( const std::size_t /*unused*/ ) noexcept + {} + + void begin_object() + { + throw std::runtime_error( "msgpack requires object size" ); + } + + void begin_object( const std::size_t size ) + { + if( size <= 15 ) { + os.put( char( 0x80 + size ) ); + } + else if( size <= 65535 ) { + number_impl< std::uint16_t >( 0xde, size ); + } + else if( size <= 4294967295UL ) { + number_impl< std::uint32_t >( 0xdf, size ); + } + else { + throw std::runtime_error( "array too large for msgpack" ); + } + } + + void key( const std::string_view v ) + { + string( v ); + } + + void member() noexcept + {} + + void end_object() + { + assert( false ); // LCOV_EXCL_LINE + } + + void end_object( const std::size_t /*unused*/ ) noexcept + {} + }; + +} // namespace tao::json::msgpack::events + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + +#endif diff --git a/include/tao/json/msgpack/events/to_string.hpp b/include/tao/json/msgpack/events/to_string.hpp new file mode 100644 index 00000000..4560838c --- /dev/null +++ b/include/tao/json/msgpack/events/to_string.hpp @@ -0,0 +1,31 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_MSGPACK_EVENTS_TO_STRING_HPP +#define TAO_JSON_MSGPACK_EVENTS_TO_STRING_HPP + +#include +#include + +#include "to_stream.hpp" + +namespace tao::json::msgpack::events +{ + struct to_string + : to_stream + { + std::ostringstream oss; + + to_string() + : to_stream( oss ) + {} + + [[nodiscard]] std::string value() const + { + return oss.str(); + } + }; + +} // namespace tao::json::msgpack::events + +#endif diff --git a/include/tao/json/msgpack/from_file.hpp b/include/tao/json/msgpack/from_file.hpp new file mode 100644 index 00000000..0ca12a54 --- /dev/null +++ b/include/tao/json/msgpack/from_file.hpp @@ -0,0 +1,33 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_MSGPACK_FROM_FILE_HPP +#define TAO_JSON_MSGPACK_FROM_FILE_HPP + +#include +#include + +#include "../events/to_value.hpp" +#include "../events/transformer.hpp" + +#include "events/from_file.hpp" + +namespace tao::json::msgpack +{ + template< template< typename... > class Traits, template< typename... > class... Transformers > + [[nodiscard]] basic_value< Traits > basic_from_file( const std::string& filename ) + { + json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; + events::from_file( consumer, filename ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers > + [[nodiscard]] value from_file( const std::string& filename ) + { + return basic_from_file< traits, Transformers... >( filename ); + } + +} // namespace tao::json::msgpack + +#endif diff --git a/include/tao/json/msgpack/from_input.hpp b/include/tao/json/msgpack/from_input.hpp new file mode 100644 index 00000000..9a8dd024 --- /dev/null +++ b/include/tao/json/msgpack/from_input.hpp @@ -0,0 +1,33 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_MSGPACK_FROM_INPUT_HPP +#define TAO_JSON_MSGPACK_FROM_INPUT_HPP + +#include +#include + +#include "../events/to_value.hpp" +#include "../events/transformer.hpp" + +#include "events/from_input.hpp" + +namespace tao::json::msgpack +{ + template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] basic_value< Traits > basic_from_input( Ts&&... ts ) + { + json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; + msgpack::events::from_input( consumer, std::forward< Ts >( ts )... ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] value from_input( Ts&&... ts ) + { + return basic_from_input< traits, Transformers... >( std::forward< Ts >( ts )... ); + } + +} // namespace tao::json::msgpack + +#endif diff --git a/include/tao/json/msgpack/from_string.hpp b/include/tao/json/msgpack/from_string.hpp index 6416b4a9..61f7da93 100644 --- a/include/tao/json/msgpack/from_string.hpp +++ b/include/tao/json/msgpack/from_string.hpp @@ -1,40 +1,32 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_MSGPACK_FROM_STRING_HPP -#define TAOCPP_JSON_INCLUDE_MSGPACK_FROM_STRING_HPP +#ifndef TAO_JSON_MSGPACK_FROM_STRING_HPP +#define TAO_JSON_MSGPACK_FROM_STRING_HPP #include #include "../events/to_value.hpp" #include "../events/transformer.hpp" -#include "../events/msgpack/from_string.hpp" +#include "events/from_string.hpp" -namespace tao +namespace tao::json::msgpack { - namespace json + template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] basic_value< Traits > basic_from_string( Ts&&... ts ) { - namespace msgpack - { - template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > - basic_value< Traits > basic_from_string( Ts&&... ts ) - { - events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; - events::msgpack::from_string( consumer, std::forward< Ts >( ts )... ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers, typename... Ts > - value from_string( Ts&&... ts ) - { - return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); - } - - } // namespace msgpack - - } // namespace json - -} // namespace tao + json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; + events::from_string( consumer, std::forward< Ts >( ts )... ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] value from_string( Ts&&... ts ) + { + return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); + } + +} // namespace tao::json::msgpack #endif diff --git a/include/tao/json/msgpack/internal/format.hpp b/include/tao/json/msgpack/internal/format.hpp new file mode 100644 index 00000000..6ad20b6c --- /dev/null +++ b/include/tao/json/msgpack/internal/format.hpp @@ -0,0 +1,57 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_MSGPACK_INTERNAL_FORMAT_HPP +#define TAO_JSON_MSGPACK_INTERNAL_FORMAT_HPP + +#include + +namespace tao::json::msgpack::internal +{ + enum class format : std::uint8_t + { + POSITIVE_MAX = 0x7f, + FIXMAP_MIN = 0x80, + FIXMAP_MAX = 0x8f, + FIXARRAY_MIN = 0x90, + FIXARRAY_MAX = 0x9f, + FIXSTR_MIN = 0xa0, + FIXSTR_MAX = 0xbf, + NIL = 0xc0, + UNUSED = 0xc1, + BOOL_FALSE = 0xc2, + BOOL_TRUE = 0xc3, + BIN8 = 0xc4, + BIN16 = 0xc5, + BIN32 = 0xc6, + EXT8 = 0xc7, + EXT16 = 0xc8, + EXT32 = 0xc9, + FLOAT32 = 0xca, + FLOAT64 = 0xcb, + UINT8 = 0xcc, + UINT16 = 0xcd, + UINT32 = 0xce, + UINT64 = 0xcf, + INT8 = 0xd0, + INT16 = 0xd1, + INT32 = 0xd2, + INT64 = 0xd3, + FIXEXT1 = 0xd4, + FIXEXT2 = 0xd5, + FIXEXT4 = 0xd6, + FIXEXT8 = 0xd7, + FIXEXT16 = 0xd8, + STR8 = 0xd9, + STR16 = 0xda, + STR32 = 0xdb, + ARRAY16 = 0xdc, + ARRAY32 = 0xdd, + MAP16 = 0xde, + MAP32 = 0xdf, + NEGATIVE_MIN = 0xe0 + }; + +} // namespace tao::json::msgpack::internal + +#endif diff --git a/include/tao/json/msgpack/internal/grammar.hpp b/include/tao/json/msgpack/internal/grammar.hpp new file mode 100644 index 00000000..2f159853 --- /dev/null +++ b/include/tao/json/msgpack/internal/grammar.hpp @@ -0,0 +1,249 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_MSGPACK_INTERNAL_GRAMMAR_HPP +#define TAO_JSON_MSGPACK_INTERNAL_GRAMMAR_HPP + +#include +#include +#include + +#include "../../binary_view.hpp" +#include "../../external/pegtl.hpp" +#include "../../internal/format.hpp" +#include "../../internal/parse_util.hpp" +#include "../../utf8.hpp" + +#include "format.hpp" + +namespace tao::json::msgpack::internal +{ + template< utf8_mode U, typename Input > + [[nodiscard]] std::string_view read_string( Input& in ) + { + const auto b = json::internal::peek_uint8( in ); + if( ( std::uint8_t( format::FIXSTR_MIN ) <= b ) && ( b <= std::uint8_t( format::FIXSTR_MAX ) ) ) { + in.bump_in_this_line(); + return json::internal::read_string< U, std::string_view >( in, b - std::uint8_t( format::FIXSTR_MIN ) ); + } + switch( format( b ) ) { + case format::STR8: + return json::internal::read_string< U, std::string_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint8_t >( in, 1 ) ); + case format::STR16: + return json::internal::read_string< U, std::string_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint16_t >( in, 1 ) ); + case format::STR32: + return json::internal::read_string< U, std::string_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint32_t >( in, 1 ) ); + default: + throw pegtl::parse_error( "unexpected key type", in ); + } + } + + template< utf8_mode V > + struct data + { + using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; + + template< pegtl::apply_mode A, + pegtl::rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename Consumer > + [[nodiscard]] static bool match( Input& in, Consumer& consumer ) + { + if( !in.empty() ) { + parse_unsafe( in, consumer ); + return true; + } + return false; + } + + private: + template< typename Input, typename Consumer > + static void parse_unsafe( Input& in, Consumer& consumer ) + { + const auto b = in.peek_uint8(); + if( b <= std::uint8_t( format::POSITIVE_MAX ) ) { + consumer.number( std::uint64_t( b ) ); + in.bump_in_this_line(); + return; + } + if( b >= std::uint8_t( format::NEGATIVE_MIN ) ) { + consumer.number( std::int64_t( std::int8_t( b ) ) ); + in.bump_in_this_line(); + return; + } + if( ( std::uint8_t( format::FIXMAP_MIN ) <= b ) && ( b <= std::uint8_t( format::FIXMAP_MAX ) ) ) { + in.bump_in_this_line(); + parse_object( in, consumer, b - std::uint8_t( format::FIXMAP_MIN ) ); + return; + } + if( ( std::uint8_t( format::FIXARRAY_MIN ) <= b ) && ( b <= std::uint8_t( format::FIXARRAY_MAX ) ) ) { + in.bump_in_this_line(); + parse_array( in, consumer, b - std::uint8_t( format::FIXARRAY_MIN ) ); + return; + } + if( ( std::uint8_t( format::FIXSTR_MIN ) <= b ) && ( b <= std::uint8_t( format::FIXSTR_MAX ) ) ) { + in.bump_in_this_line(); + consumer.string( json::internal::read_string< V, std::string_view >( in, b - std::uint8_t( format::FIXSTR_MIN ) ) ); + return; + } + switch( format( b ) ) { + case format::NIL: + consumer.null(); + in.bump_in_this_line(); + return; + case format::UNUSED: + throw pegtl::parse_error( "unused first byte 0xc1", in ); + case format::BOOL_TRUE: + consumer.boolean( true ); + in.bump_in_this_line(); + return; + case format::BOOL_FALSE: + consumer.boolean( false ); + in.bump_in_this_line(); + return; + case format::BIN8: + consumer.binary( json::internal::read_string< utf8_mode::trust, tao::binary_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint8_t >( in, 1 ) ) ); + return; + case format::BIN16: + consumer.binary( json::internal::read_string< utf8_mode::trust, tao::binary_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint16_t >( in, 1 ) ) ); + return; + case format::BIN32: + consumer.binary( json::internal::read_string< utf8_mode::trust, tao::binary_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint32_t >( in, 1 ) ) ); + return; + case format::EXT8: + discard( in, json::internal::read_big_endian_number< std::size_t, std::uint8_t >( in, 1 ) + 1 ); + return; + case format::EXT16: + discard( in, json::internal::read_big_endian_number< std::size_t, std::uint16_t >( in, 1 ) + 1 ); + return; + case format::EXT32: + discard( in, json::internal::read_big_endian_number< std::size_t, std::uint32_t >( in, 1 ) + 1 ); + return; + case format::FLOAT32: + consumer.number( json::internal::read_big_endian_number< double, float >( in, 1 ) ); + return; + case format::FLOAT64: + consumer.number( json::internal::read_big_endian_number< double >( in, 1 ) ); + return; + case format::UINT8: + consumer.number( json::internal::read_big_endian_number< std::uint64_t, std::uint8_t >( in, 1 ) ); + return; + case format::UINT16: + consumer.number( json::internal::read_big_endian_number< std::uint64_t, std::uint16_t >( in, 1 ) ); + return; + case format::UINT32: + consumer.number( json::internal::read_big_endian_number< std::uint64_t, std::uint32_t >( in, 1 ) ); + return; + case format::UINT64: + consumer.number( json::internal::read_big_endian_number< std::uint64_t >( in, 1 ) ); + return; + case format::INT8: + consumer.number( json::internal::read_big_endian_number< std::int64_t, std::int8_t >( in, 1 ) ); + return; + case format::INT16: + consumer.number( json::internal::read_big_endian_number< std::int64_t, std::int16_t >( in, 1 ) ); + return; + case format::INT32: + consumer.number( json::internal::read_big_endian_number< std::int64_t, std::int32_t >( in, 1 ) ); + return; + case format::INT64: + consumer.number( json::internal::read_big_endian_number< std::int64_t >( in, 1 ) ); + return; + case format::FIXEXT1: + discard( in, 3 ); + return; + case format::FIXEXT2: + discard( in, 4 ); + return; + case format::FIXEXT4: + discard( in, 6 ); + return; + case format::FIXEXT8: + discard( in, 10 ); + return; + case format::FIXEXT16: + discard( in, 18 ); + return; + case format::STR8: + consumer.string( json::internal::read_string< V, std::string_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint8_t >( in, 1 ) ) ); + return; + case format::STR16: + consumer.string( json::internal::read_string< V, std::string_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint16_t >( in, 1 ) ) ); + return; + case format::STR32: + consumer.string( json::internal::read_string< V, std::string_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint32_t >( in, 1 ) ) ); + return; + case format::ARRAY16: + parse_array( in, consumer, json::internal::read_big_endian_number< std::size_t, std::uint16_t >( in, 1 ) ); + return; + case format::ARRAY32: + parse_array( in, consumer, json::internal::read_big_endian_number< std::size_t, std::uint32_t >( in, 1 ) ); + return; + case format::MAP16: + parse_object( in, consumer, json::internal::read_big_endian_number< std::size_t, std::uint16_t >( in, 1 ) ); + return; + case format::MAP32: + parse_object( in, consumer, json::internal::read_big_endian_number< std::size_t, std::uint32_t >( in, 1 ) ); + return; + default: + // LCOV_EXCL_START + assert( false ); + // LCOV_EXCL_STOP + } + } + + template< typename Input > + static void discard( Input& in, const std::size_t count ) + { + json::internal::throw_on_empty( in, count ); + in.bump_in_this_line( count ); + } + + template< typename Input, typename Consumer > + static void parse_array( Input& in, Consumer& consumer, const std::size_t size ) + { + consumer.begin_array( size ); + for( std::size_t i = 0; i < size; ++i ) { + json::internal::throw_on_empty( in ); + parse_unsafe( in, consumer ); + consumer.element(); + } + consumer.end_array( size ); + } + + template< typename Input, typename Consumer > + static void parse_object( Input& in, Consumer& consumer, const std::size_t size ) + { + consumer.begin_object( size ); + for( std::size_t i = 0; i < size; ++i ) { + consumer.key( read_string< V >( in ) ); + json::internal::throw_on_empty( in ); + parse_unsafe( in, consumer ); + consumer.member(); + } + consumer.end_object( size ); + } + }; + + template< utf8_mode V > + struct basic_grammar + : pegtl::must< data< V >, pegtl::eof > + { + }; + + template< utf8_mode V > + struct basic_embedded + : pegtl::must< data< V > > + { + }; + + using grammar = basic_grammar< utf8_mode::check >; + using embedded = basic_embedded< utf8_mode::check >; + +} // namespace tao::json::msgpack::internal + +#endif diff --git a/include/tao/json/msgpack/parts_parser.hpp b/include/tao/json/msgpack/parts_parser.hpp new file mode 100644 index 00000000..4810bccf --- /dev/null +++ b/include/tao/json/msgpack/parts_parser.hpp @@ -0,0 +1,311 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_MSGPACK_PARTS_PARSER_HPP +#define TAO_JSON_MSGPACK_PARTS_PARSER_HPP + +#include +#include + +#include "../events/discard.hpp" +#include "../external/pegtl/string_input.hpp" +#include "../utf8.hpp" + +#include "internal/format.hpp" +#include "internal/grammar.hpp" + +namespace tao::json::msgpack +{ + namespace internal + { + template< typename Input > + [[nodiscard]] format peek_format( Input& in ) + { + return format( json::internal::peek_uint8( in ) ); + } + + template< typename Input > + [[nodiscard]] bool read_boolean( Input& in ) + { + const auto b = internal::peek_format( in ); + switch( b ) { + case internal::format::BOOL_TRUE: + case internal::format::BOOL_FALSE: + in.bump_in_this_line( 1 ); + return bool( b & 1 ); + default: + throw pegtl::parse_error( "expected boolean", in ); + } + std::abort(); + } + + template< typename Input > + [[nodiscard]] tao::binary_view read_binary( Input& in ) + { + switch( peek_format( in ) ) { + case format::BIN8: + return json::internal::read_string< utf8_mode::trust, tao::binary_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint8_t >( in, 1 ) ); + case format::BIN16: + return json::internal::read_string< utf8_mode::trust, tao::binary_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint16_t >( in, 1 ) ); + case format::BIN32: + return json::internal::read_string< utf8_mode::trust, tao::binary_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint32_t >( in, 1 ) ); + default: + throw pegtl::parse_error( "expected binary data", in ); + } + } + + [[nodiscard]] inline std::int64_t test_signed( const std::uint64_t i ) + { + if( ( i & ( std::uint64_t( 1 ) << 63 ) ) != 0 ) { + throw std::runtime_error( "integer overflow for signed" ); + } + return std::int64_t( i ); + } + + template< typename Input > + [[nodiscard]] std::int64_t read_signed( Input& in ) + { + const auto b = json::internal::peek_uint8( in ); + if( b <= std::uint8_t( format::POSITIVE_MAX ) ) { + in.bump_in_this_line(); + return std::int64_t( b ); + } + if( b >= std::uint8_t( format::NEGATIVE_MIN ) ) { + in.bump_in_this_line(); + return std::int64_t( std::int8_t( b ) ); + } + switch( format( b ) ) { + case format::UINT8: + return json::internal::read_big_endian_number< std::int64_t, std::uint8_t >( in, 1 ); + case format::UINT16: + return json::internal::read_big_endian_number< std::int64_t, std::uint16_t >( in, 1 ); + case format::UINT32: + return json::internal::read_big_endian_number< std::int64_t, std::uint32_t >( in, 1 ); + case format::UINT64: + return test_signed( json::internal::read_big_endian_number< std::uint64_t >( in, 1 ) ); + case format::INT8: + return json::internal::read_big_endian_number< std::int64_t, std::int8_t >( in, 1 ); + case format::INT16: + return json::internal::read_big_endian_number< std::int64_t, std::int16_t >( in, 1 ); + case format::INT32: + return json::internal::read_big_endian_number< std::int64_t, std::int32_t >( in, 1 ); + case format::INT64: + return json::internal::read_big_endian_number< std::int64_t >( in, 1 ); + default: + throw pegtl::parse_error( "expected signed number", in ); + } + } + + [[nodiscard]] inline std::uint64_t test_unsigned( const std::int64_t i ) + { + if( i < 0 ) { + throw std::runtime_error( "negative number for unsigned" ); + } + return std::uint64_t( i ); + } + + template< typename Input > + [[nodiscard]] std::uint64_t read_unsigned( Input& in ) + { + const auto b = json::internal::peek_uint8( in ); + if( b <= std::uint8_t( format::POSITIVE_MAX ) ) { + in.bump_in_this_line(); + return std::uint64_t( b ); + } + switch( format( b ) ) { + case format::UINT8: + return json::internal::read_big_endian_number< std::uint64_t, std::uint8_t >( in, 1 ); + case format::UINT16: + return json::internal::read_big_endian_number< std::uint64_t, std::uint16_t >( in, 1 ); + case format::UINT32: + return json::internal::read_big_endian_number< std::uint64_t, std::uint32_t >( in, 1 ); + case format::UINT64: + return json::internal::read_big_endian_number< std::uint64_t >( in, 1 ); + case format::INT8: + return test_unsigned( json::internal::read_big_endian_number< std::int64_t, std::int8_t >( in, 1 ) ); + case format::INT16: + return test_unsigned( json::internal::read_big_endian_number< std::int64_t, std::int16_t >( in, 1 ) ); + case format::INT32: + return test_unsigned( json::internal::read_big_endian_number< std::int64_t, std::int32_t >( in, 1 ) ); + case format::INT64: + return test_unsigned( json::internal::read_big_endian_number< std::int64_t >( in, 1 ) ); + default: + throw pegtl::parse_error( "expected positive number", in ); + } + } + + template< typename Input > + [[nodiscard]] double read_double( Input& in ) + { + switch( peek_format( in ) ) { + case format::FLOAT32: + return json::internal::read_big_endian_number< double, float >( in, 1 ); + case format::FLOAT64: + return json::internal::read_big_endian_number< double >( in, 1 ); + default: + throw pegtl::parse_error( "expected floating point number", in ); + } + } + + template< format Min, format Max, format S16, format S32, typename Input > + [[nodiscard]] std::size_t read_container_size( Input& in ) + { + const auto b = json::internal::peek_uint8( in ); + if( ( std::uint8_t( Min ) <= b ) && ( b <= std::uint8_t( Max ) ) ) { + in.bump_in_this_line(); + return state_t( b - std::uint8_t( Min ) ); + } + switch( format( b ) ) { + case S16: + return state_t( json::internal::read_big_endian_number< std::size_t, std::uint16_t >( in, 1 ) ); + case S32: + return state_t( json::internal::read_big_endian_number< std::size_t, std::uint32_t >( in, 1 ) ); + default: + throw pegtl::parse_error( "expected container", in ); + } + } + + } // namespace internal + + template< utf8_mode V = utf8_mode::check, typename Input = pegtl::string_input< pegtl::tracking_mode::lazy > > + class basic_parts_parser + { + public: + template< typename... Ts > + explicit basic_parts_parser( Ts&&... ts ) + : m_input( std::forward< Ts >( ts )... ) + {} + + [[nodiscard]] bool empty() + { + return m_input.empty(); + } + + [[nodiscard]] bool null() + { + if( internal::peek_format( m_input ) == internal::format::NIL ) { + m_input.bump_in_this_line( 1 ); + return true; + } + return false; + } + + [[nodiscard]] bool boolean() + { + return internal::read_boolean( m_input ); + } + + [[nodiscard]] std::string_view string() + { + return internal::read_string< V >( m_input ); + } + + [[nodiscard]] tao::binary_view binary() + { + return internal::read_binary( m_input ); + } + + [[nodiscard]] std::string_view key() + { + return internal::read_string< V >( m_input ); + } + + [[nodiscard]] std::int64_t number_signed() + { + return internal::read_signed( m_input ); + } + + [[nodiscard]] std::uint64_t number_unsigned() + { + return internal::read_unsigned( m_input ); + } + + [[nodiscard]] double number_double() + { + return internal::read_double( m_input ); + } + + struct state_t + { + explicit state_t( const std::size_t in_size ) + : size( in_size ) + {} + + std::size_t i = 0; + std::size_t size; + }; + + [[nodiscard]] state_t begin_array() + { + return state_t( internal::read_container_size< internal::format::FIXARRAY_MIN, internal::format::FIXARRAY_MAX, internal::format::ARRAY16, internal::format::ARRAY32 >( m_input ) ); + } + + [[nodiscard]] state_t begin_object() + { + return state_t( internal::read_container_size< internal::format::FIXMAP_MIN, internal::format::FIXMAP_MAX, internal::format::MAP16, internal::format::MAP32 >( m_input ) ); + } + + void end_array( state_t& p ) + { + if( p.size != p.i ) { + throw pegtl::parse_error( "array size mismatch", m_input ); + } + } + + void end_object( state_t& p ) + { + if( p.size != p.i ) { + throw pegtl::parse_error( "object size mismatch", m_input ); + } + } + + void element( state_t& p ) + { + if( p.i++ >= p.size ) { + throw pegtl::parse_error( "unexpected array end", m_input ); + } + } + + void member( state_t& p ) + { + if( p.i++ >= p.size ) { + throw pegtl::parse_error( "unexpected object end", m_input ); + } + } + + [[nodiscard]] bool element_or_end_array( state_t& p ) + { + return p.i++ < p.size; + } + + [[nodiscard]] bool member_or_end_object( state_t& p ) + { + return p.i++ < p.size; + } + + void skip_value() + { + json::events::discard consumer; // TODO: Optimise to not generate events (which requires preparing their - discarded - arguments)? + pegtl::parse< pegtl::must< internal::data< V > > >( m_input, consumer ); + } + + [[nodiscard]] auto mark() + { + return m_input.template mark< pegtl::rewind_mode::required >(); + } + + template< typename T > + void throw_parse_error( T&& t ) const + { + throw pegtl::parse_error( std::forward< T >( t ), m_input ); + } + + protected: + Input m_input; + }; + + using parts_parser = basic_parts_parser<>; + +} // namespace tao::json::msgpack + +#endif diff --git a/include/tao/json/msgpack/to_stream.hpp b/include/tao/json/msgpack/to_stream.hpp index dd16fb1e..2c12f122 100644 --- a/include/tao/json/msgpack/to_stream.hpp +++ b/include/tao/json/msgpack/to_stream.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_MSGPACK_TO_STREAM_HPP -#define TAOCPP_JSON_INCLUDE_MSGPACK_TO_STREAM_HPP +#ifndef TAO_JSON_MSGPACK_TO_STREAM_HPP +#define TAO_JSON_MSGPACK_TO_STREAM_HPP #include @@ -11,25 +11,17 @@ #include "../events/from_value.hpp" #include "../events/transformer.hpp" -#include "../events/msgpack/to_stream.hpp" +#include "events/to_stream.hpp" -namespace tao +namespace tao::json::msgpack { - namespace json + template< template< typename... > class... Transformers, template< typename... > class Traits > + void to_stream( std::ostream& os, const basic_value< Traits >& v ) { - namespace msgpack - { - template< template< typename... > class... Transformers, template< typename... > class Traits > - void to_stream( std::ostream& os, const basic_value< Traits >& v ) - { - events::transformer< events::msgpack::to_stream, Transformers... > consumer( os ); - events::from_value( consumer, v ); - } + json::events::transformer< events::to_stream, Transformers... > consumer( os ); + json::events::from_value( consumer, v ); + } - } // namespace msgpack - - } // namespace json - -} // namespace tao +} // namespace tao::json::msgpack #endif diff --git a/include/tao/json/msgpack/to_string.hpp b/include/tao/json/msgpack/to_string.hpp index feed0c2a..ad22e1ef 100644 --- a/include/tao/json/msgpack/to_string.hpp +++ b/include/tao/json/msgpack/to_string.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_MSGPACK_TO_STRING_HPP -#define TAOCPP_JSON_INCLUDE_MSGPACK_TO_STRING_HPP +#ifndef TAO_JSON_MSGPACK_TO_STRING_HPP +#define TAO_JSON_MSGPACK_TO_STRING_HPP #include @@ -11,26 +11,18 @@ #include "../events/from_value.hpp" #include "../events/transformer.hpp" -#include "../events/msgpack/to_string.hpp" +#include "events/to_string.hpp" -namespace tao +namespace tao::json::msgpack { - namespace json + template< template< typename... > class... Transformers, template< typename... > class Traits > + [[nodiscard]] std::string to_string( const basic_value< Traits >& v ) { - namespace msgpack - { - template< template< typename... > class... Transformers, template< typename... > class Traits > - std::string to_string( const basic_value< Traits >& v ) - { - events::transformer< events::msgpack::to_string, Transformers... > consumer; - events::from_value( consumer, v ); - return consumer.value(); - } + json::events::transformer< events::to_string, Transformers... > consumer; + json::events::from_value( consumer, v ); + return consumer.value(); + } - } // namespace msgpack - - } // namespace json - -} // namespace tao +} // namespace tao::json::msgpack #endif diff --git a/include/tao/json/operators.hpp b/include/tao/json/operators.hpp new file mode 100644 index 00000000..d09edbe7 --- /dev/null +++ b/include/tao/json/operators.hpp @@ -0,0 +1,494 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_OPERATORS_HPP +#define TAO_JSON_OPERATORS_HPP + +#include "basic_value.hpp" + +#include "internal/format.hpp" + +namespace tao::json +{ + template< template< typename... > class TraitsL, template< typename... > class TraitsR > + [[nodiscard]] bool operator==( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept + { + if( rhs.is_value_ptr() ) { + return lhs == rhs.skip_value_ptr(); + } + if( lhs.type() != rhs.type() ) { + switch( lhs.type() ) { + case type::VALUE_PTR: + return lhs.skip_value_ptr() == rhs; + + case type::SIGNED: + if( rhs.type() == type::UNSIGNED ) { + const auto v = lhs.get_signed(); + return ( v >= 0 ) && ( static_cast< std::uint64_t >( v ) == rhs.get_unsigned() ); + } + if( rhs.type() == type::DOUBLE ) { + return lhs.get_signed() == rhs.get_double(); + } + break; + + case type::UNSIGNED: + if( rhs.type() == type::SIGNED ) { + const auto v = rhs.get_signed(); + return ( v >= 0 ) && ( lhs.get_unsigned() == static_cast< std::uint64_t >( v ) ); + } + if( rhs.type() == type::DOUBLE ) { + return lhs.get_unsigned() == rhs.get_double(); + } + break; + + case type::DOUBLE: + if( rhs.type() == type::SIGNED ) { + return lhs.get_double() == rhs.get_signed(); + } + if( rhs.type() == type::UNSIGNED ) { + return lhs.get_double() == rhs.get_unsigned(); + } + break; + + case type::STRING: + if( rhs.type() == type::STRING_VIEW ) { + return lhs.get_string() == rhs.get_string_view(); + } + break; + + case type::STRING_VIEW: + if( rhs.type() == type::STRING ) { + return lhs.get_string_view() == rhs.get_string(); + } + break; + + case type::BINARY: + if( rhs.type() == type::BINARY_VIEW ) { + return tao::internal::binary_equal( lhs.get_binary(), rhs.get_binary_view() ); + } + break; + + case type::BINARY_VIEW: + if( rhs.type() == type::BINARY ) { + return tao::internal::binary_equal( lhs.get_binary_view(), rhs.get_binary() ); + } + break; + + case type::OPAQUE_PTR: + assert( lhs.type() != type::OPAQUE_PTR ); + break; + + default: + break; + } + assert( rhs.type() != type::OPAQUE_PTR ); + return false; + } + + switch( lhs.type() ) { + case type::UNINITIALIZED: + return true; + + case type::NULL_: + return true; + + case type::BOOLEAN: + return lhs.get_boolean() == rhs.get_boolean(); + + case type::SIGNED: + return lhs.get_signed() == rhs.get_signed(); + + case type::UNSIGNED: + return lhs.get_unsigned() == rhs.get_unsigned(); + + case type::DOUBLE: + return lhs.get_double() == rhs.get_double(); + + case type::STRING: + return lhs.get_string() == rhs.get_string(); + + case type::STRING_VIEW: + return lhs.get_string_view() == rhs.get_string_view(); + + case type::BINARY: + return lhs.get_binary() == rhs.get_binary(); + + case type::BINARY_VIEW: + return tao::internal::binary_equal( lhs.get_binary_view(), rhs.get_binary_view() ); + + case type::ARRAY: + return lhs.get_array() == rhs.get_array(); + + case type::OBJECT: + return lhs.get_object() == rhs.get_object(); + + case type::VALUE_PTR: + assert( lhs.type() != type::VALUE_PTR ); + break; // LCOV_EXCL_LINE + + case type::OPAQUE_PTR: + assert( lhs.type() != type::OPAQUE_PTR ); + break; // LCOV_EXCL_LINE + + case type::VALUELESS_BY_EXCEPTION: + assert( lhs.type() != type::VALUELESS_BY_EXCEPTION ); + break; // LCOV_EXCL_LINE + } + // LCOV_EXCL_START + assert( false ); + return false; + // LCOV_EXCL_STOP + } + + template< template< typename... > class Traits, int = 1 > // work-around for Visual C++ + [[nodiscard]] bool operator==( const basic_value< Traits >& lhs, tao::internal::identity_t< basic_value< Traits > > rhs ) noexcept + { + return lhs == rhs; + } + + template< template< typename... > class Traits, int = 2 > // work-around for Visual C++ + [[nodiscard]] bool operator==( tao::internal::identity_t< basic_value< Traits > > lhs, const basic_value< Traits >& rhs ) noexcept + { + return lhs == rhs; + } + + template< template< typename... > class Traits, typename T > + [[nodiscard]] bool operator==( const basic_value< Traits >& lhs, const std::optional< T >& rhs ) noexcept + { + static_assert( noexcept( Traits< std::optional< T > >::equal( lhs, rhs ) ), "equal must be noexcept" ); + return Traits< std::optional< T > >::equal( lhs, rhs ); + } + + template< typename T, template< typename... > class Traits > + [[nodiscard]] bool operator==( const std::optional< T >& lhs, const basic_value< Traits >& rhs ) noexcept + { + return rhs == lhs; + } + + template< template< typename... > class Traits, typename T > + [[nodiscard]] auto operator==( const basic_value< Traits >& lhs, const T& rhs ) noexcept -> decltype( Traits< std::decay_t< T > >::equal( lhs, rhs ) ) + { + using D = std::decay_t< T >; + static_assert( noexcept( Traits< D >::equal( lhs, rhs ) ), "equal must be noexcept" ); + return Traits< D >::equal( lhs, rhs ); + } + + template< typename T, template< typename... > class Traits > + [[nodiscard]] auto operator==( const T& lhs, const basic_value< Traits >& rhs ) noexcept -> decltype( Traits< std::decay_t< T > >::equal( rhs, lhs ) ) + { + return rhs == lhs; + } + + template< template< typename... > class TraitsL, template< typename... > class TraitsR > + [[nodiscard]] bool operator!=( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept + { + return !( lhs == rhs ); + } + + template< template< typename... > class Traits, typename T > + [[nodiscard]] bool operator!=( const basic_value< Traits >& lhs, const std::optional< T >& rhs ) noexcept + { + return !( lhs == rhs ); + } + + template< typename T, template< typename... > class Traits > + [[nodiscard]] bool operator!=( const std::optional< T >& lhs, const basic_value< Traits >& rhs ) noexcept + { + return !( rhs == lhs ); + } + + template< template< typename... > class Traits, typename T > + [[nodiscard]] bool operator!=( const basic_value< Traits >& lhs, const T& rhs ) noexcept + { + return !( lhs == rhs ); + } + + template< typename T, template< typename... > class Traits > + [[nodiscard]] bool operator!=( const T& lhs, const basic_value< Traits >& rhs ) noexcept + { + return !( lhs == rhs ); + } + + template< template< typename... > class TraitsL, template< typename... > class TraitsR > + [[nodiscard]] bool operator<( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept + { + if( rhs.is_value_ptr() ) { + return lhs < rhs.skip_value_ptr(); + } + if( lhs.type() != rhs.type() ) { + switch( lhs.type() ) { + case type::VALUE_PTR: + return lhs.skip_value_ptr() < rhs; + + case type::SIGNED: + if( rhs.type() == type::UNSIGNED ) { + const auto v = lhs.get_signed(); + return ( v < 0 ) || ( static_cast< std::uint64_t >( v ) < rhs.get_unsigned() ); + } + if( rhs.type() == type::DOUBLE ) { + return lhs.get_signed() < rhs.get_double(); + } + break; + + case type::UNSIGNED: + if( rhs.type() == type::SIGNED ) { + const auto v = rhs.get_signed(); + return ( v >= 0 ) && ( lhs.get_unsigned() < static_cast< std::uint64_t >( v ) ); + } + if( rhs.type() == type::DOUBLE ) { + return lhs.get_unsigned() < rhs.get_double(); + } + break; + + case type::DOUBLE: + if( rhs.type() == type::SIGNED ) { + return lhs.get_double() < rhs.get_signed(); + } + if( rhs.type() == type::UNSIGNED ) { + return lhs.get_double() < rhs.get_unsigned(); + } + break; + + case type::STRING: + if( rhs.type() == type::STRING_VIEW ) { + return lhs.get_string() < rhs.get_string_view(); + } + break; + + case type::STRING_VIEW: + if( rhs.type() == type::STRING ) { + return lhs.get_string_view() < rhs.get_string(); + } + break; + + case type::BINARY: + if( rhs.type() == type::BINARY_VIEW ) { + return tao::internal::binary_less( lhs.get_binary(), rhs.get_binary_view() ); + } + break; + + case type::BINARY_VIEW: + if( rhs.type() == type::BINARY ) { + return tao::internal::binary_less( lhs.get_binary_view(), rhs.get_binary() ); + } + break; + + case type::OPAQUE_PTR: + assert( lhs.type() != type::OPAQUE_PTR ); + break; + + default: + break; + } + assert( rhs.type() != type::OPAQUE_PTR ); + return lhs.type() < rhs.type(); + } + + switch( lhs.type() ) { + case type::UNINITIALIZED: + return false; + + case type::NULL_: + return false; + + case type::BOOLEAN: + return lhs.get_boolean() < rhs.get_boolean(); + + case type::SIGNED: + return lhs.get_signed() < rhs.get_signed(); + + case type::UNSIGNED: + return lhs.get_unsigned() < rhs.get_unsigned(); + + case type::DOUBLE: + return lhs.get_double() < rhs.get_double(); + + case type::STRING: + return lhs.get_string() < rhs.get_string(); + + case type::STRING_VIEW: + return lhs.get_string_view() < rhs.get_string_view(); + + case type::BINARY: + return lhs.get_binary() < rhs.get_binary(); + + case type::BINARY_VIEW: + return tao::internal::binary_less( lhs.get_binary_view(), rhs.get_binary_view() ); + + case type::ARRAY: + return lhs.get_array() < rhs.get_array(); + + case type::OBJECT: + return lhs.get_object() < rhs.get_object(); + + case type::VALUE_PTR: + assert( lhs.type() != type::VALUE_PTR ); + break; // LCOV_EXCL_LINE + + case type::OPAQUE_PTR: + assert( lhs.type() != type::OPAQUE_PTR ); + break; // LCOV_EXCL_LINE + + case type::VALUELESS_BY_EXCEPTION: + assert( lhs.type() != type::VALUELESS_BY_EXCEPTION ); + break; // LCOV_EXCL_LINE + } + // LCOV_EXCL_START + assert( false ); + return false; + // LCOV_EXCL_STOP + } + + template< template< typename... > class Traits, int = 1 > // work-around for Visual C++ + [[nodiscard]] bool operator<( const basic_value< Traits >& lhs, tao::internal::identity_t< basic_value< Traits > > rhs ) noexcept + { + return lhs < rhs; + } + + template< template< typename... > class Traits, int = 2 > // work-around for Visual C++ + [[nodiscard]] bool operator<( const tao::internal::identity_t< basic_value< Traits > > lhs, const basic_value< Traits >& rhs ) noexcept + { + return lhs < rhs; + } + + template< template< typename... > class Traits, typename T > + [[nodiscard]] bool operator<( const basic_value< Traits >& lhs, const std::optional< T >& rhs ) noexcept + { + static_assert( noexcept( Traits< std::optional< T > >::less_than( lhs, rhs ) ), "less_than must be noexcept" ); + return Traits< std::optional< T > >::less_than( lhs, rhs ); + } + + template< typename T, template< typename... > class Traits > + [[nodiscard]] bool operator<( const std::optional< T >& lhs, const basic_value< Traits >& rhs ) noexcept + { + static_assert( noexcept( Traits< std::optional< T > >::greater_than( rhs, lhs ) ), "greater_than must be noexcept" ); + return Traits< std::optional< T > >::greater_than( rhs, lhs ); + } + + template< template< typename... > class Traits, typename T > + [[nodiscard]] auto operator<( const basic_value< Traits >& lhs, const T& rhs ) noexcept -> decltype( Traits< std::decay_t< T > >::less_than( lhs, rhs ) ) + { + using D = std::decay_t< T >; + static_assert( noexcept( Traits< D >::less_than( lhs, rhs ) ), "less_than must be noexcept" ); + return Traits< D >::less_than( lhs, rhs ); + } + + template< typename T, template< typename... > class Traits > + [[nodiscard]] auto operator<( const T& lhs, const basic_value< Traits >& rhs ) noexcept -> decltype( Traits< std::decay_t< T > >::greater_than( rhs, lhs ) ) + { + using D = std::decay_t< T >; + static_assert( noexcept( Traits< D >::greater_than( rhs, lhs ) ), "greater_than must be noexcept" ); + return Traits< D >::greater_than( rhs, lhs ); + } + + template< template< typename... > class TraitsL, template< typename... > class TraitsR > + [[nodiscard]] bool operator>( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept + { + return rhs < lhs; + } + + template< template< typename... > class Traits > + [[nodiscard]] bool operator>( const basic_value< Traits >& lhs, tao::internal::identity_t< basic_value< Traits > > rhs ) noexcept + { + return rhs < lhs; + } + + template< template< typename... > class Traits > + [[nodiscard]] bool operator>( tao::internal::identity_t< basic_value< Traits > > lhs, const basic_value< Traits >& rhs ) noexcept + { + return rhs < lhs; + } + + template< template< typename... > class Traits, typename T > + [[nodiscard]] bool operator>( const basic_value< Traits >& lhs, const std::optional< T >& rhs ) noexcept + { + static_assert( noexcept( Traits< std::optional< T > >::greater_than( lhs, rhs ) ), "greater_than must be noexcept" ); + return Traits< std::optional< T > >::greater_than( lhs, rhs ); + } + + template< typename T, template< typename... > class Traits > + [[nodiscard]] bool operator>( const std::optional< T >& lhs, const basic_value< Traits >& rhs ) noexcept + { + static_assert( noexcept( Traits< std::optional< T > >::less_than( rhs, lhs ) ), "less_than must be noexcept" ); + return Traits< std::optional< T > >::less_than( rhs, lhs ); + } + + template< template< typename... > class Traits, typename T > + [[nodiscard]] auto operator>( const basic_value< Traits >& lhs, const T& rhs ) noexcept -> decltype( Traits< std::decay_t< T > >::greater_than( lhs, rhs ) ) + { + using D = std::decay_t< T >; + static_assert( noexcept( Traits< D >::greater_than( lhs, rhs ) ), "greater_than must be noexcept" ); + return Traits< D >::greater_than( lhs, rhs ); + } + + template< typename T, template< typename... > class Traits > + [[nodiscard]] auto operator>( const T& lhs, const basic_value< Traits >& rhs ) noexcept -> decltype( Traits< std::decay_t< T > >::less_than( rhs, lhs ) ) + { + using D = std::decay_t< T >; + static_assert( noexcept( Traits< D >::less_than( rhs, lhs ) ), "less_than must be noexcept" ); + return Traits< D >::less_than( rhs, lhs ); + } + + template< template< typename... > class TraitsL, template< typename... > class TraitsR > + [[nodiscard]] bool operator<=( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept + { + return !( lhs > rhs ); + } + + template< template< typename... > class Traits, typename T > + [[nodiscard]] bool operator<=( const basic_value< Traits >& lhs, const std::optional< T >& rhs ) noexcept + { + return !( lhs > rhs ); + } + + template< typename T, template< typename... > class Traits > + [[nodiscard]] bool operator<=( const std::optional< T >& lhs, const basic_value< Traits >& rhs ) noexcept + { + return !( lhs > rhs ); + } + + template< template< typename... > class Traits, typename T > + [[nodiscard]] bool operator<=( const basic_value< Traits >& lhs, const T& rhs ) noexcept + { + return !( lhs > rhs ); + } + + template< typename T, template< typename... > class Traits > + [[nodiscard]] bool operator<=( const T& lhs, const basic_value< Traits >& rhs ) noexcept + { + return !( lhs > rhs ); + } + + template< template< typename... > class TraitsL, template< typename... > class TraitsR > + [[nodiscard]] bool operator>=( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept + { + return !( lhs < rhs ); + } + + template< template< typename... > class Traits, typename T > + [[nodiscard]] bool operator>=( const basic_value< Traits >& lhs, const std::optional< T >& rhs ) noexcept + { + return !( lhs < rhs ); + } + + template< typename T, template< typename... > class Traits > + [[nodiscard]] bool operator>=( const std::optional< T >& lhs, const basic_value< Traits >& rhs ) noexcept + { + return !( lhs < rhs ); + } + + template< template< typename... > class Traits, typename T > + [[nodiscard]] bool operator>=( const basic_value< Traits >& lhs, const T& rhs ) noexcept + { + return !( lhs < rhs ); + } + + template< typename T, template< typename... > class Traits > + [[nodiscard]] bool operator>=( const T& lhs, const basic_value< Traits >& rhs ) noexcept + { + return !( lhs < rhs ); + } + +} // namespace tao::json + +#endif diff --git a/include/tao/json/pair.hpp b/include/tao/json/pair.hpp deleted file mode 100644 index 45e90647..00000000 --- a/include/tao/json/pair.hpp +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_PAIR_HPP -#define TAOCPP_JSON_INCLUDE_PAIR_HPP - -#include -#include -#include - -namespace tao -{ - namespace json - { - template< template< typename... > class Traits > - class basic_value; - - template< template< typename... > class Traits > - struct pair - { - mutable std::string key; - mutable basic_value< Traits > value; - - template< typename U > - pair( U&& v ) - : key( Traits< typename std::decay< U >::type >::default_key ), - value( std::forward< U >( v ) ) - { - } - - pair( std::string&& k, basic_value< Traits >&& v ) - : key( std::move( k ) ), value( std::move( v ) ) - { - } - - pair( std::string&& k, const basic_value< Traits >& v ) - : key( std::move( k ) ), value( v ) - { - } - - pair( const std::string& k, basic_value< Traits >&& v ) - : key( k ), value( std::move( v ) ) - { - } - - pair( const std::string& k, const basic_value< Traits >& v ) - : key( k ), value( v ) - { - } - - pair( const char* k, basic_value< Traits >&& v ) - : key( k ), value( std::move( v ) ) - { - } - - pair( const char* k, const basic_value< Traits >& v ) - : key( k ), value( v ) - { - } - }; - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/parse_file.hpp b/include/tao/json/parse_file.hpp deleted file mode 100644 index 01985390..00000000 --- a/include/tao/json/parse_file.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_PARSE_FILE_HPP -#define TAOCPP_JSON_INCLUDE_PARSE_FILE_HPP - -#include -#include - -#include "events/parse_file.hpp" -#include "events/to_value.hpp" -#include "events/transformer.hpp" - -namespace tao -{ - namespace json - { - template< template< typename... > class Traits, template< typename... > class... Transformers > - basic_value< Traits > basic_parse_file( const std::string& filename ) - { - events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; - events::parse_file( consumer, filename ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers > - value parse_file( const std::string& filename ) - { - return basic_parse_file< traits, Transformers... >( filename ); - } - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/parts_parser.hpp b/include/tao/json/parts_parser.hpp new file mode 100644 index 00000000..e6c37c8a --- /dev/null +++ b/include/tao/json/parts_parser.hpp @@ -0,0 +1,306 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_PARTS_PARSER_HPP +#define TAO_JSON_PARTS_PARSER_HPP + +#include "external/pegtl.hpp" +#include "external/pegtl/contrib/integer.hpp" +#include "external/pegtl/contrib/json.hpp" + +#include "internal/action.hpp" +#include "internal/format.hpp" +#include "internal/grammar.hpp" +#include "internal/number_state.hpp" +#include "internal/unescape_action.hpp" + +namespace tao::json +{ + namespace internal + { + namespace rules + { + struct wss + : pegtl::star< ws > + {}; + + struct boolean + { + using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; + + template< pegtl::apply_mode, + pegtl::rewind_mode, + template< typename... > + class, + template< typename... > + class, + typename Input > + [[nodiscard]] static bool match( Input& in, bool& st ) noexcept( noexcept( in.size( 5 ) ) ) + { + const auto s = in.size( 5 ); + if( s >= 5 ) { + if( std::memcmp( in.current(), "false", 5 ) == 0 ) { + in.bump_in_this_line( 5 ); + st = false; + return true; + } + } + if( s >= 4 ) { + if( std::memcmp( in.current(), "true", 4 ) == 0 ) { + in.bump_in_this_line( 4 ); + st = true; + return true; + } + } + return false; + } + }; + + struct double_rule + { + using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match_impl( Input& in, States&&... st ) + { + switch( in.peek_char() ) { + case '-': + in.bump_in_this_line(); + if( in.empty() || !sor_value::match_number< true, A, rewind_mode::dontcare, Action, Control >( in, st... ) ) { + throw pegtl::parse_error( "incomplete number", in ); + } + return true; + + default: + return sor_value::match_number< false, A, M, Action, Control >( in, st... ); + } + } + + template< apply_mode A, + rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename... States > + [[nodiscard]] static bool match( Input& in, States&&... st ) + { + return in.size( 2 ) && match_impl< A, M, Action, Control >( in, st... ); + } + }; + + } // namespace rules + + template< typename Rule > + struct double_action + : action< Rule > + {}; + + template< bool NEG > + struct double_action< rules::number< NEG > > + : pegtl::change_states< number_state< NEG > > + { + template< typename Input, typename Consumer > + static void success( const Input& /*unused*/, number_state< NEG >& state, Consumer& consumer ) + { + state.success( consumer ); + } + }; + + struct double_state_and_consumer + { + void number( const double d ) + { + converted = d; + } + + void number( const std::int64_t i ) + { + converted = double( i ); + } + + void number( const std::uint64_t u ) + { + converted = double( u ); + } + + double converted = 0.0; // TODO: Remove superfluous initialisation when we manage to shup up the warnings on all compilers. + }; + + } // namespace internal + + // TODO: Optimise some of the simpler cases? + + template< typename Input = pegtl::string_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, std::string > > + class basic_parts_parser + { + public: + template< typename... Ts > + explicit basic_parts_parser( Ts&&... ts ) + : m_input( std::forward< Ts >( ts )... ) + { + pegtl::parse< internal::rules::wss >( m_input ); + } + + [[nodiscard]] bool empty() + { + return m_input.empty(); + } + + [[nodiscard]] bool null() + { + return pegtl::parse< pegtl::seq< internal::rules::null, internal::rules::wss > >( m_input ); + } + + [[nodiscard]] bool boolean() + { + bool r; + pegtl::parse< pegtl::must< internal::rules::boolean, internal::rules::wss > >( m_input, r ); + return r; + } + + [[nodiscard]] double number_double() + { + internal::double_state_and_consumer st; + pegtl::parse< pegtl::must< internal::rules::double_rule, internal::rules::wss >, internal::double_action >( m_input, st ); + return st.converted; + } + + [[nodiscard]] std::int64_t number_signed() + { + std::int64_t st = 0; // TODO: Remove superfluous initialisation when we manage to shup up the warnings on all compilers. + pegtl::parse< pegtl::must< pegtl::integer::signed_rule_with_action, internal::rules::wss > >( m_input, st ); + return st; + } + + [[nodiscard]] std::uint64_t number_unsigned() + { + std::uint64_t st = 0; // TODO: Remove superfluous initialisation when we manage to shup up the warnings on all compilers. + pegtl::parse< pegtl::must< pegtl::integer::unsigned_rule_with_action, internal::rules::wss > >( m_input, st ); + return st; + } + + [[nodiscard]] std::string string() + { + std::string unescaped; + pegtl::parse< pegtl::must< internal::rules::string, internal::rules::wss >, internal::unescape_action >( m_input, unescaped ); + return unescaped; + } + + [[nodiscard]] std::vector< std::byte > binary() + { + throw std::runtime_error( "json format does not support binary" ); + } + + [[nodiscard]] std::string key() + { + std::string unescaped; + pegtl::parse< pegtl::must< internal::rules::string, internal::rules::wss, pegtl::one< ':' >, internal::rules::wss >, internal::unescape_action >( m_input, unescaped ); + return unescaped; + } + + template< char C > + void parse_single_must() + { + pegtl::parse< pegtl::must< pegtl::one< C >, internal::rules::wss > >( m_input ); + } + + template< char C > + [[nodiscard]] bool parse_single_test() + { + return pegtl::parse< pegtl::seq< pegtl::one< C >, internal::rules::wss > >( m_input ); + } + + struct state_t + { + std::size_t i = 0; + static constexpr std::size_t* size = nullptr; + }; + + [[nodiscard]] state_t begin_array() + { + parse_single_must< '[' >(); + return state_t(); + } + + void end_array( state_t& /*unused*/ ) + { + parse_single_must< ']' >(); + } + + void element( state_t& p ) + { + if( p.i++ ) { + parse_single_must< ',' >(); + } + } + + [[nodiscard]] bool element_or_end_array( state_t& p ) + { + if( parse_single_test< ']' >() ) { + return false; + } + element( p ); + return true; + } + + [[nodiscard]] state_t begin_object() + { + parse_single_must< '{' >(); + return state_t(); + } + + void end_object( state_t& /*unused*/ ) + { + parse_single_must< '}' >(); + } + + void member( state_t& p ) + { + if( p.i++ ) { + parse_single_must< ',' >(); + } + } + + [[nodiscard]] bool member_or_end_object( state_t& p ) + { + if( parse_single_test< '}' >() ) { + return false; + } + member( p ); + return true; + } + + void skip_value() + { + pegtl::parse< pegtl::must< pegtl::json::value > >( m_input ); // Includes standard JSON right-padding. + } + + [[nodiscard]] auto mark() + { + return m_input.template mark< pegtl::rewind_mode::required >(); + } + + template< typename T > + void throw_parse_error( T&& t ) const + { + throw pegtl::parse_error( std::forward< T >( t ), m_input ); + } + + protected: + Input m_input; + }; + + using parts_parser = basic_parts_parser<>; + +} // namespace tao::json + +#endif diff --git a/include/tao/json/patch.hpp b/include/tao/json/patch.hpp deleted file mode 100644 index 08483643..00000000 --- a/include/tao/json/patch.hpp +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_PATCH_HPP -#define TAOCPP_JSON_INCLUDE_PATCH_HPP - -#include -#include - -#include "pointer.hpp" -#include "value.hpp" - -namespace tao -{ - namespace json - { - template< template< typename... > class Traits > - void patch_inplace( basic_value< Traits >& v, const basic_value< Traits >& patch ) - { - for( const auto& entry : patch.get_array() ) { - const auto& op = entry.at( "op" ).get_string(); - const auto& path = entry.at( "path" ).get_string(); - const pointer path_pointer( path ); - if( op == "test" ) { - if( v.at( path_pointer ) != entry.at( "value" ) ) { - throw std::runtime_error( "test failed for: " + path ); - } - } - else if( op == "remove" ) { - v.erase( path_pointer ); - } - else if( op == "add" ) { - v.insert( path_pointer, entry.at( "value" ) ); - } - else if( op == "replace" ) { - v.at( path_pointer ) = entry.at( "value" ); - } - else if( op == "move" ) { - const pointer from( entry.at( "from" ).get_string() ); - auto t = std::move( v.at( from ) ); - v.erase( from ); - v.insert( path_pointer, std::move( t ) ); - } - else if( op == "copy" ) { - const pointer from( entry.at( "from" ).get_string() ); - v.insert( path_pointer, v.at( from ) ); - } - else { - throw std::runtime_error( "unknown patch operation: '" + op + '\'' ); - } - } - } - - template< template< typename... > class Traits > - void patch_inplace( basic_value< Traits >& v, basic_value< Traits >&& patch ) - { - for( const auto& entry : patch.get_array() ) { - const auto& op = entry.at( "op" ).get_string(); - const auto& path = entry.at( "path" ).get_string(); - const pointer path_pointer( path ); - if( op == "test" ) { - if( v.at( path_pointer ) != entry.at( "value" ) ) { - throw std::runtime_error( "test failed for: " + path ); - } - } - else if( op == "remove" ) { - v.erase( path_pointer ); - } - else if( op == "add" ) { - v.insert( path_pointer, std::move( entry.at( "value" ) ) ); - } - else if( op == "replace" ) { - v.at( path_pointer ) = std::move( entry.at( "value" ) ); - } - else if( op == "move" ) { - const pointer from( entry.at( "from" ).get_string() ); - auto t = std::move( v.at( from ) ); - v.erase( from ); - v.insert( path_pointer, std::move( t ) ); - } - else if( op == "copy" ) { - const pointer from( entry.at( "from" ).get_string() ); - v.insert( path_pointer, v.at( from ) ); - } - else { - throw std::runtime_error( "unknown patch operation: '" + op + '\'' ); - } - } - } - - template< template< typename... > class Traits > - basic_value< Traits > patch( basic_value< Traits > v, const basic_value< Traits >& patch ) - { - patch_inplace( v, patch ); - return v; - } - - template< template< typename... > class Traits > - basic_value< Traits > patch( basic_value< Traits > v, basic_value< Traits >&& patch ) - { - patch_inplace( v, std::move( patch ) ); - return v; - } - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/pointer.hpp b/include/tao/json/pointer.hpp index 8ff08257..38360a13 100644 --- a/include/tao/json/pointer.hpp +++ b/include/tao/json/pointer.hpp @@ -1,9 +1,11 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_POINTER_HPP -#define TAOCPP_JSON_INCLUDE_POINTER_HPP +#ifndef TAO_JSON_POINTER_HPP +#define TAO_JSON_POINTER_HPP +#include +#include #include #include #include @@ -12,296 +14,419 @@ #include "type.hpp" -#include "external/operators.hpp" +#include "external/pegtl.hpp" +#include "internal/format.hpp" -namespace tao +namespace tao::json { - namespace json + namespace internal { - namespace internal - { - std::size_t token_to_index( const std::string& key ); - - } // namespace internal + template< std::size_t = sizeof( std::size_t ) > + struct token_to_index; - // RFC 6901 - class token + template<> + struct token_to_index< 4 > { - private: - std::size_t m_index; - std::string m_key; - - public: - explicit token( const std::string& in_key ) - : m_index( internal::token_to_index( in_key ) ), - m_key( in_key ) - { - } - - explicit token( std::string&& in_key ) - : m_index( internal::token_to_index( in_key ) ), - m_key( std::move( in_key ) ) - { - } - - token( const token& ) = default; - token( token&& v ) noexcept - : m_index( v.m_index ), - m_key( std::move( v.m_key ) ) - { - } - - token& operator=( const token& ) = default; - token& operator=( token&& v ) noexcept + [[nodiscard]] static std::size_t convert( const std::string& key ) noexcept { - m_index = v.m_index; - m_key = std::move( v.m_key ); - return *this; - } - - const std::string& key() const - { - return m_key; - } - - std::size_t index() const - { - if( m_index == std::string::npos ) { - throw std::invalid_argument( "unable to resolve JSON Pointer, invalid token for array access '" + m_key + '\'' ); + if( !key.empty() && key.size() <= 10 ) { + if( key == "0" ) { + return 0; + } + if( ( key[ 0 ] != '0' ) && ( key.find_first_not_of( "0123456789" ) == std::string::npos ) ) { + if( key.size() < 10 || key < "4294967296" ) { + return static_cast< std::size_t >( std::stoul( key ) ); + } + } } - return m_index; - } - - friend bool operator==( const token& lhs, const token& rhs ) - { - return lhs.m_key == rhs.m_key; - } - - friend bool operator<( const token& lhs, const token& rhs ) - { - return lhs.m_key < rhs.m_key; + return std::string::npos; } }; - class pointer - : operators::totally_ordered< pointer > + template<> + struct token_to_index< 8 > { - private: - std::vector< token > m_tokens; - - static std::vector< token > parse( const std::string& v ) + [[nodiscard]] static std::size_t convert( const std::string& key ) noexcept { - std::vector< token > result; - if( !v.empty() ) { - const char* p = v.data(); - const char* const e = p + v.size(); - if( *p++ != '/' ) { - throw std::invalid_argument( "invalid JSON Pointer value, must be empty or begin with '/'" ); + if( !key.empty() && key.size() <= 20 ) { + if( key == "0" ) { + return 0; } - std::string token; - while( p != e ) { - const char c = *p++; - switch( c ) { - case '~': - if( p != e ) { - switch( *p++ ) { - case '0': - token += '~'; - continue; - case '1': - token += '/'; - continue; - } - } - throw std::invalid_argument( "invalid JSON Pointer escape sequence, '~' must be followed by '0' or '1'" ); - - case '/': - result.emplace_back( std::move( token ) ); - token.clear(); - continue; - - default: - token += c; + if( ( key[ 0 ] != '0' ) && ( key.find_first_not_of( "0123456789" ) == std::string::npos ) ) { + if( key.size() < 20 || key < "18446744073709551616" ) { + return static_cast< std::size_t >( std::stoull( key ) ); } } - result.emplace_back( std::move( token ) ); } - return result; + return std::string::npos; } + }; - public: - pointer() = default; + } // namespace internal - pointer( const pointer& ) = default; + // RFC 6901 + class token + { + private: + std::size_t m_index; + std::string m_key; + + public: + explicit token( const std::string& in_key ) + : m_index( internal::token_to_index<>::convert( in_key ) ), + m_key( in_key ) + {} + + explicit token( std::string&& in_key ) noexcept + : m_index( internal::token_to_index<>::convert( in_key ) ), + m_key( std::move( in_key ) ) + {} + + explicit token( const std::size_t in_index ) + : m_index( in_index ), + m_key( std::to_string( m_index ) ) + {} + + token( const token& ) = default; + token( token&& v ) noexcept + : m_index( v.m_index ), + m_key( std::move( v.m_key ) ) + {} + + ~token() = default; + + token& operator=( const token& ) = default; + token& operator=( token&& v ) noexcept + { + m_index = v.m_index; + m_key = std::move( v.m_key ); + return *this; + } - pointer( pointer&& p ) noexcept - : m_tokens( std::move( p.m_tokens ) ) - { - } + [[nodiscard]] bool has_index() const noexcept + { + return m_index != std::string::npos; + } - explicit pointer( const std::string& v ) - : m_tokens( parse( v ) ) - { + [[nodiscard]] const std::string& key() const noexcept + { + return m_key; + } + + [[nodiscard]] std::size_t index() const + { + if( !has_index() ) { + throw std::invalid_argument( internal::format( "unable to resolve json pointer with array, token '", m_key, "' is not an index" ) ); } + return m_index; + } - pointer& operator=( const pointer& ) = default; + [[nodiscard]] friend bool operator==( const token& lhs, const token& rhs ) noexcept + { + return lhs.m_key == rhs.m_key; + } - pointer& operator=( pointer&& p ) noexcept - { - m_tokens = std::move( p.m_tokens ); - return *this; - } + [[nodiscard]] friend bool operator<( const token& lhs, const token& rhs ) noexcept + { + return lhs.m_key < rhs.m_key; + } + }; - pointer& operator=( const std::string& v ) + namespace internal + { + // clang-format off + struct pointer_zero : pegtl::one< '0' > {}; + struct pointer_one : pegtl::one< '1' > {}; + struct pointer_tilde : pegtl::one< '~' > {}; + struct pointer_escaped : pegtl::sor< pointer_zero, pointer_one > {}; + struct pointer_slash : pegtl::one< '/' > {}; + struct pointer_char : pegtl::utf8::not_one< '/' > {}; + struct pointer_escape : pegtl::if_must< pointer_tilde, pointer_escaped > {}; + struct pointer_token : pegtl::star< pegtl::sor< pointer_escape, pointer_char > > {}; + struct pointer_rule : pegtl::until< pegtl::eof, pegtl::must< pointer_slash, pointer_token > > {}; + struct pointer_grammar : pegtl::must< pointer_rule > {}; + // clang-format on + + template< typename Rule > + struct pointer_action + : pegtl::nothing< Rule > + {}; + + template<> + struct pointer_action< pointer_zero > + { + static void apply0( std::vector< token >& /*unused*/, std::string& t ) { - m_tokens = parse( v ); - return *this; + t += '~'; } + }; - explicit operator bool() const noexcept + template<> + struct pointer_action< pointer_one > + { + static void apply0( std::vector< token >& /*unused*/, std::string& t ) { - return !m_tokens.empty(); + t += '/'; } + }; - std::vector< token >::const_iterator begin() const noexcept + template<> + struct pointer_action< pointer_char > + { + template< typename Input > + static void apply( const Input& in, std::vector< token >& /*unused*/, std::string& t ) { - return m_tokens.begin(); + t.append( in.begin(), in.size() ); } + }; - std::vector< token >::const_iterator end() const noexcept + template<> + struct pointer_action< pointer_token > + { + static void apply0( std::vector< token >& v, std::string& t ) { - return m_tokens.end(); + v.emplace_back( std::move( t ) ); + t.clear(); } + }; - void push_back( const std::string& v ) - { - m_tokens.push_back( token( v ) ); - } + } // namespace internal - void push_back( std::string&& v ) - { - m_tokens.push_back( token( std::move( v ) ) ); - } + class pointer + : public std::vector< token > + { + private: + void parse( const std::string& v ) + { + std::string t; + pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > in( v, "parse()" ); + pegtl::parse< internal::pointer_grammar, internal::pointer_action >( in, vector(), t ); + } - pointer& operator+=( const std::string& v ) - { - push_back( v ); - return *this; - } + public: + pointer() = default; + pointer( const pointer& ) = default; + pointer( pointer&& p ) = default; - pointer& operator+=( std::string&& v ) - { - push_back( std::move( v ) ); - return *this; - } + explicit pointer( const std::string& v ) + { + parse( v ); + } - friend bool operator==( const pointer& lhs, const pointer& rhs ) noexcept - { - return lhs.m_tokens == rhs.m_tokens; - } + pointer( const std::initializer_list< token >& l ) + : std::vector< token >( l ) + {} - friend bool operator<( const pointer& lhs, const pointer& rhs ) noexcept - { - return lhs.m_tokens < rhs.m_tokens; - } - }; + ~pointer() = default; + + pointer& operator=( const pointer& ) = default; + pointer& operator=( pointer&& p ) = default; - inline pointer operator+( const pointer& p, const std::string& v ) + pointer& operator=( const std::string& v ) { - pointer nrv( p ); - nrv += v; - return nrv; + clear(); + parse( v ); + return *this; } - inline pointer operator+( const pointer& p, std::string&& v ) + pointer& operator=( const std::initializer_list< token >& l ) { - pointer nrv( p ); - nrv += std::move( v ); - return nrv; + vector() = l; + return *this; } - namespace internal + [[nodiscard]] explicit operator bool() const noexcept { - inline std::size_t token_to_index( const std::string& key ) - { - if( !key.empty() && key.size() <= 20 ) { - if( key == "0" ) { - return 0; - } - else if( ( key[ 0 ] != '0' ) && ( key.find_first_not_of( "0123456789" ) == std::string::npos ) ) { - if( key.size() < 20 || key < "18446744073709551616" ) { - return std::stoull( key ); - } - } - } - return std::string::npos; - } + return !empty(); + } - inline std::string tokens_to_string( std::vector< token >::const_iterator it, const std::vector< token >::const_iterator& end ) - { - std::string result; - while( it != end ) { - result += '/'; - for( const char c : it->key() ) { - switch( c ) { - case '~': - result += "~0"; - break; - case '/': - result += "~1"; - break; - default: - result += c; - } - } - ++it; - } - return result; - } + void push_back() = delete; - inline std::string to_string( const pointer& p ) - { - return tokens_to_string( p.begin(), p.end() ); - } + void pop_back() + { + assert( !empty() ); + vector().pop_back(); + } - inline std::runtime_error invalid_type( const std::vector< token >::const_iterator& begin, const std::vector< token >::const_iterator& end ) - { - return std::runtime_error( "unable to resolve JSON Pointer '" + tokens_to_string( begin, end ) + "' -- value type is neither 'object' nor 'array'" ); + [[nodiscard]] bool is_prefix_of( const pointer& other ) const noexcept + { + if( other.size() >= size() ) { + return std::equal( begin(), end(), other.begin() ); } + return false; + } - template< typename T > - T& pointer_at( T* v, const std::vector< token >::const_iterator& begin, const std::vector< token >::const_iterator& end ) - { - auto it = begin; - while( it != end ) { - switch( v->type() ) { - case type::ARRAY: - v = &v->at( it->index() ); + [[nodiscard]] std::vector< token >& vector() noexcept + { + return static_cast< std::vector< token >& >( *this ); + } + + [[nodiscard]] const std::vector< token >& vector() const noexcept + { + return static_cast< const std::vector< token >& >( *this ); + } + }; + + [[nodiscard]] inline bool operator==( const pointer& lhs, const pointer& rhs ) noexcept + { + return lhs.vector() == rhs.vector(); + } + + [[nodiscard]] inline bool operator<( const pointer& lhs, const pointer& rhs ) noexcept + { + return lhs.vector() < rhs.vector(); + } + + [[nodiscard]] inline bool operator!=( const pointer& lhs, const pointer& rhs ) noexcept + { + return !( lhs == rhs ); + } + + [[nodiscard]] inline bool operator>( const pointer& lhs, const pointer& rhs ) noexcept + { + return rhs < lhs; + } + + [[nodiscard]] inline bool operator<=( const pointer& lhs, const pointer& rhs ) noexcept + { + return !( rhs < lhs ); + } + + [[nodiscard]] inline bool operator>=( const pointer& lhs, const pointer& rhs ) noexcept + { + return !( lhs < rhs ); + } + + inline pointer& operator+=( pointer& lhs, const std::string& rhs ) + { + lhs.emplace_back( rhs ); + return lhs; + } + + inline pointer& operator+=( pointer& lhs, std::string&& rhs ) + { + lhs.emplace_back( std::move( rhs ) ); + return lhs; + } + + inline pointer& operator+=( pointer& lhs, const std::size_t rhs ) + { + lhs.emplace_back( rhs ); + return lhs; + } + + [[nodiscard]] inline pointer operator+( const pointer& p, const std::string& v ) + { + pointer nrv( p ); + nrv += v; + return nrv; + } + + [[nodiscard]] inline pointer operator+( const pointer& p, std::string&& v ) + { + pointer nrv( p ); + nrv += std::move( v ); + return nrv; + } + + [[nodiscard]] inline pointer operator+( const pointer& p, const std::size_t i ) + { + pointer nrv( p ); + nrv += i; + return nrv; + } + + namespace internal + { + [[nodiscard]] inline std::string tokens_to_string( std::vector< token >::const_iterator it, const std::vector< token >::const_iterator& end ) + { + std::string result; + while( it != end ) { + result += '/'; + for( const char c : it->key() ) { + switch( c ) { + case '~': + result += "~0"; break; - case type::OBJECT: - v = &v->at( it->key() ); + case '/': + result += "~1"; break; default: - throw invalid_type( begin, std::next( it ) ); + result += c; } - ++it; } - return *v; + ++it; } + return result; + } - } // namespace internal + [[nodiscard]] inline std::runtime_error invalid_type( const std::vector< token >::const_iterator& begin, const std::vector< token >::const_iterator& end ) + { + return std::runtime_error( internal::format( "unable to resolve JSON Pointer '", tokens_to_string( begin, end ), "' -- value type is neither 'object' nor 'array'" ) ); + } - inline namespace literals + template< typename T > + [[nodiscard]] T& pointer_at( T* v, const std::vector< token >::const_iterator& begin, const std::vector< token >::const_iterator& end ) { - inline pointer operator"" _json_pointer( const char* data, const std::size_t size ) - { - return pointer( { data, size } ); + for( auto it = begin; it != end; ++it ) { + switch( v->type() ) { + case type::ARRAY: + v = &v->at( it->index() ); + break; + case type::OBJECT: + v = &v->at( it->key() ); + break; + default: + throw invalid_type( begin, std::next( it ) ); + } + } + return *v; + } + + template< typename T > + [[nodiscard]] T* pointer_find( T* v, const std::vector< token >::const_iterator& begin, const std::vector< token >::const_iterator& end ) + { + for( auto it = begin; v && ( it != end ); ++it ) { + switch( v->type() ) { + case type::ARRAY: + v = v->find( it->index() ); + break; + case type::OBJECT: + v = v->find( it->key() ); + break; + default: + throw invalid_type( begin, std::next( it ) ); + } } + return v; + } - } // namespace literals + } // namespace internal + + [[nodiscard]] inline std::string to_string( const pointer& p ) + { + return internal::tokens_to_string( p.begin(), p.end() ); + } + + [[nodiscard]] inline std::string to_string( pointer& p ) + { + return internal::tokens_to_string( p.begin(), p.end() ); + } + + [[nodiscard]] inline std::string to_string( pointer&& p ) + { + return internal::tokens_to_string( p.begin(), p.end() ); + } + + inline namespace literals + { + [[nodiscard]] inline pointer operator"" _json_pointer( const char* data, const std::size_t size ) + { + return pointer( { data, size } ); + } - } // namespace json + } // namespace literals -} // namespace tao +} // namespace tao::json #endif diff --git a/include/tao/json/produce.hpp b/include/tao/json/produce.hpp new file mode 100644 index 00000000..d3713f92 --- /dev/null +++ b/include/tao/json/produce.hpp @@ -0,0 +1,61 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_PRODUCE_HPP +#define TAO_JSON_PRODUCE_HPP + +#include +#include +#include +#include + +#include "forward.hpp" + +#include "events/produce.hpp" +#include "events/to_pretty_stream.hpp" +#include "events/to_stream.hpp" +#include "events/to_string.hpp" +#include "events/to_value.hpp" + +namespace tao::json::produce +{ + template< template< typename... > class Traits = traits, typename T > + [[nodiscard]] basic_value< Traits > to_value( T&& t ) + { + events::to_basic_value< Traits > consumer; + events::produce< Traits >( consumer, std::forward< T >( t ) ); + return std::move( consumer.value ); + } + + template< template< typename... > class Traits = traits, typename T > + void to_stream( std::ostream& os, const T& t ) + { + events::to_stream consumer( os ); + events::produce< Traits >( consumer, t ); + } + + template< template< typename... > class Traits = traits, typename T > + void to_stream( std::ostream& os, const T& t, const std::size_t indent ) + { + events::to_pretty_stream consumer( os, indent ); + events::produce< Traits >( consumer, t ); + } + + template< template< typename... > class Traits = traits, typename T, typename S > + void to_stream( std::ostream& os, const T& t, const std::size_t indent, S&& eol ) + { + events::to_pretty_stream consumer( os, indent, std::forward< S >( eol ) ); + events::produce< Traits >( consumer, t ); + } + + template< template< typename... > class Traits = traits, typename... Ts > + [[nodiscard]] std::string to_string( Ts&&... ts ) + { + std::ostringstream oss; + to_stream< Traits >( oss, std::forward< Ts >( ts )... ); + return oss.str(); + } + +} // namespace tao::json::produce + +#endif diff --git a/include/tao/json/reference.hpp b/include/tao/json/reference.hpp deleted file mode 100644 index 2301d6e6..00000000 --- a/include/tao/json/reference.hpp +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_REFERENCE_HPP -#define TAOCPP_JSON_INCLUDE_REFERENCE_HPP - -#include "internal/uri_fragment.hpp" - -#include "pointer.hpp" -#include "value.hpp" - -namespace tao -{ - namespace json - { - namespace internal - { - // JSON Reference, see draft ("work in progress") RFC at - // https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03 - - // NOTE: Currently, only URI fragments are supported. - // Remote references are ignored, i.e., left untouched. - - // JSON References are replaced with a RAW_PTR, - // which might lead to infinite loops if you try - // to traverse the value. Make sure you understand - // the consequences and handle the resulting value - // accordingly! - - // Self-references will throw an exception, as well as - // references into JSON Reference additional members - // (which shall be ignored as per the specification). - - template< template< typename... > class Traits > - void resolve_references( basic_value< Traits >& r, basic_value< Traits >& v ) - { - switch( v.type() ) { - case type::UNINITIALIZED: - return; - case type::DISCARDED: - throw std::logic_error( "attempt to use a discarded value" ); - case type::DESTROYED: - throw std::logic_error( "attempt to use a destroyed value" ); - case type::NULL_: - case type::BOOLEAN: - case type::SIGNED: - case type::UNSIGNED: - case type::DOUBLE: - case type::STRING: - case type::STRING_VIEW: - case type::BINARY: - case type::BINARY_VIEW: - return; - case type::ARRAY: - for( auto& e : v.unsafe_get_array() ) { - resolve_references( r, e ); - } - return; - case type::OBJECT: - for( auto& e : v.unsafe_get_object() ) { - resolve_references( r, e.second ); - } - if( const auto* ref = v.find( "$ref" ) ) { - ref = ref->skip_raw_ptr(); - // TODO: support is_string_view - if( ref->is_string() ) { - const std::string& s = ref->unsafe_get_string(); - if( !s.empty() && s[ 0 ] == '#' ) { - const pointer ptr = internal::uri_fragment_to_pointer( s ); - const auto* p = &r; - auto it = ptr.begin(); - while( it != ptr.end() ) { - switch( p->type() ) { - case type::ARRAY: - p = p->at( it->index() ).skip_raw_ptr(); - break; - case type::OBJECT: - if( const auto* t = p->find( "$ref" ) ) { - if( t->is_string() ) { - throw std::runtime_error( "invalid JSON Reference: referencing additional data members is invalid" ); - } - } - p = p->at( it->key() ).skip_raw_ptr(); - break; - default: - throw invalid_type( ptr.begin(), std::next( it ) ); - } - ++it; - } - if( p == &v ) { - throw std::runtime_error( "JSON Reference: invalid self reference" ); - } - v.assign_raw_ptr( p ); - resolve_references( r, v ); - return; - } - else { - // Ignore remote references for now... - // throw std::runtime_error( "JSON Reference: unsupported or invalid URI: " + s ); - } - } - } - return; - case type::RAW_PTR: - return; - } - throw std::logic_error( "invalid value for tao::json::type" ); // LCOV_EXCL_LINE - } - - } // namespace internal - - template< template< typename... > class Traits > - void resolve_references( basic_value< Traits >& r ) - { - internal::resolve_references( r, r ); - } - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/schema.hpp b/include/tao/json/schema.hpp deleted file mode 100644 index 1e7118a2..00000000 --- a/include/tao/json/schema.hpp +++ /dev/null @@ -1,1786 +0,0 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_SCHEMA_HPP -#define TAOCPP_JSON_INCLUDE_SCHEMA_HPP - -#include "events/compare.hpp" -#include "events/from_value.hpp" -#include "events/hash.hpp" -#include "pointer.hpp" -#include "reference.hpp" -#include "value.hpp" - -#include "external/pegtl/contrib/uri.hpp" -#include "external/pegtl/parse.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace tao -{ - namespace json - { - namespace internal - { - // TODO: Check if these grammars are correct. - struct local_part_label - : json_pegtl::plus< json_pegtl::sor< json_pegtl::alnum, json_pegtl::one< '!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', '=', '?', '^', '_', '`', '{', '|', '}', '~' > > > - { - }; - - struct local_part - : json_pegtl::list_must< local_part_label, json_pegtl::one< '.' > > - { - }; - - struct hostname_label - : json_pegtl::seq< json_pegtl::alnum, json_pegtl::rep_max< 62, json_pegtl::ranges< 'a', 'z', 'A', 'Z', '0', '9', '-' > > > - { - }; - - struct hostname - : json_pegtl::list_must< hostname_label, json_pegtl::one< '.' > > - { - }; - - struct email - : json_pegtl::seq< local_part, json_pegtl::one< '@' >, hostname > - { - }; - - template< typename Rule > - bool parse( const tao::string_view v ) - { - json_pegtl::memory_input<> in( v.data(), v.size(), "" ); - return json_pegtl::parse< json_pegtl::seq< Rule, json_pegtl::eof > >( in ); - } - - inline bool parse_date_time( const tao::string_view v ) - { - static std::regex re( "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:[0-5]\\d:[0-5]\\d(\\.\\d+)?(Z|[+-]\\d{2}:[0-5]\\d)$" ); - if( !std::regex_search( v.begin(), v.end(), re ) ) { - return false; - } - - const unsigned year = ( v[ 0 ] - '0' ) * 1000 + ( v[ 1 ] - '0' ) * 100 + ( v[ 2 ] - '0' ) * 10 + ( v[ 3 ] - '0' ); - const unsigned month = ( v[ 5 ] - '0' ) * 10 + ( v[ 6 ] - '0' ); - const unsigned day = ( v[ 8 ] - '0' ) * 10 + ( v[ 9 ] - '0' ); - - if( month == 0 || month > 12 ) { - return false; - } - if( day == 0 || day > 31 ) { - return false; - } - if( month == 2 ) { - const bool is_leap_year = ( year % 4 == 0 ) && ( year % 100 != 0 || year % 400 == 0 ); - if( day > ( is_leap_year ? 29 : 28 ) ) { - return false; - } - } - else if( day == 31 ) { - switch( month ) { - case 4: - case 6: - case 9: - case 11: - return false; - } - } - - const unsigned hour = ( v[ 11 ] - '0' ) * 10 + ( v[ 12 ] - '0' ); - if( hour >= 24 ) { - return false; - } - - if( *v.rbegin() != 'Z' ) { - const auto s = v.size(); - const unsigned tz_hour = ( v[ s - 5 ] - '0' ) * 10 + ( v[ s - 4 ] - '0' ); - if( tz_hour >= 24 ) { - return false; - } - } - - return true; - } - - enum schema_flags - { - NONE = 0, - - HAS_TYPE = 1 << 0, - NULL_ = 1 << 1, - BOOLEAN = 1 << 2, - INTEGER = 1 << 3, - NUMBER = 1 << 4, - STRING = 1 << 5, - ARRAY = 1 << 6, - OBJECT = 1 << 7, - - HAS_ENUM = 1 << 8, - - HAS_MULTIPLE_OF_UNSIGNED = 1 << 9, - HAS_MULTIPLE_OF_DOUBLE = 1 << 10, - HAS_MULTIPLE_OF = 3 << 9, - - HAS_MAXIMUM_SIGNED = 1 << 11, - HAS_MAXIMUM_UNSIGNED = 1 << 12, - HAS_MAXIMUM_DOUBLE = 3 << 11, - HAS_MAXIMUM = 3 << 11, - EXCLUSIVE_MAXIMUM = 1 << 13, - - HAS_MINIMUM_SIGNED = 1 << 14, - HAS_MINIMUM_UNSIGNED = 1 << 15, - HAS_MINIMUM_DOUBLE = 3 << 14, - HAS_MINIMUM = 3 << 14, - EXCLUSIVE_MINIMUM = 1 << 16, - - HAS_MAX_LENGTH = 1 << 17, - HAS_MIN_LENGTH = 1 << 18, - - HAS_MAX_ITEMS = 1 << 19, - HAS_MIN_ITEMS = 1 << 20, - HAS_UNIQUE_ITEMS = 1 << 21, - - HAS_MAX_PROPERTIES = 1 << 22, - HAS_MIN_PROPERTIES = 1 << 23, - NO_ADDITIONAL_PROPERTIES = 1 << 24, - HAS_DEPENDENCIES = 1 << 25 - }; - - enum class schema_format - { - NONE, - DATE_TIME, - EMAIL, - HOSTNAME, - IPV4, - IPV6, - URI - }; - - inline constexpr schema_flags operator|( const schema_flags lhs, const schema_flags rhs ) noexcept - { - return static_cast< schema_flags >( static_cast< std::underlying_type< schema_flags >::type >( lhs ) | static_cast< std::underlying_type< schema_flags >::type >( rhs ) ); - } - - union schema_limit - { - std::int64_t i; - std::uint64_t u; - double d; - }; - - template< template< typename... > class Traits > - class schema_container; - - template< template< typename... > class Traits > - struct schema_node - { - const schema_container< Traits >* m_container; - const basic_value< Traits >* m_value; - const basic_value< Traits >* m_all_of = nullptr; - const basic_value< Traits >* m_any_of = nullptr; - const basic_value< Traits >* m_one_of = nullptr; - const basic_value< Traits >* m_not = nullptr; - const basic_value< Traits >* m_items = nullptr; - const basic_value< Traits >* m_additional_items = nullptr; - const basic_value< Traits >* m_properties = nullptr; - const basic_value< Traits >* m_additional_properties = nullptr; - - std::map< std::string, std::set< std::string > > m_property_dependencies; - std::map< std::string, const basic_value< Traits >* > m_schema_dependencies; - - std::vector< std::pair< std::regex, const basic_value< Traits >* > > m_pattern_properties; - - std::set< const basic_value< Traits >* > m_referenced_pointers; - - // number - schema_limit m_multiple_of; - schema_limit m_maximum; - schema_limit m_minimum; - - // string - std::uint64_t m_max_length; - std::uint64_t m_min_length; - std::unique_ptr< std::regex > m_pattern; - - // array - std::uint64_t m_max_items; - std::uint64_t m_min_items; - - // object - std::uint64_t m_max_properties; - std::uint64_t m_min_properties; - std::set< std::string > m_required; - - schema_flags m_flags = schema_flags::NONE; - schema_format m_format = schema_format::NONE; - - void add_type( const schema_flags v ) - { - if( ( m_flags & v ) != 0 ) { - throw std::runtime_error( "invalid JSON Schema: duplicate primitive type" ); - } - m_flags = m_flags | v; - } - - void add_type( const std::string& v ) - { - if( !v.empty() ) { - switch( v[ 0 ] ) { - case 'n': - if( v == "number" ) { - return add_type( NUMBER ); - } - else if( v == "null" ) { - return add_type( NULL_ ); - } - break; - case 'b': - if( v == "boolean" ) { - return add_type( BOOLEAN ); - } - break; - case 'i': - if( v == "integer" ) { - return add_type( INTEGER ); - } - break; - case 's': - if( v == "string" ) { - return add_type( STRING ); - } - break; - case 'a': - if( v == "array" ) { - return add_type( ARRAY ); - } - break; - case 'o': - if( v == "object" ) { - return add_type( OBJECT ); - } - break; - } - } - throw std::runtime_error( "invalid JSON Schema: invalid primitive type '" + v + '\'' ); - } - - const basic_value< Traits >* find( const char* s ) const - { - const auto* p = m_value->unsafe_find( s ); - if( p != nullptr ) { - p = p->skip_raw_ptr(); - } - return p; - } - - schema_node( const schema_container< Traits >* c, const basic_value< Traits >& v ) - : m_container( c ), - m_value( &v ) - { - // general - if( !m_value->is_object() ) { - throw std::runtime_error( "invalid JSON Schema: a schema must be of type 'object'" ); - } - - // title - if( const auto* p = find( "title" ) ) { - if( !p->is_string() ) { - throw std::runtime_error( "invalid JSON Schema: \"title\" must be of type 'string'" ); - } - } - - // description - if( const auto* p = find( "description" ) ) { - if( !p->is_string() ) { - throw std::runtime_error( "invalid JSON Schema: \"description\" must be of type 'string'" ); - } - } - - // type - if( const auto* p = find( "type" ) ) { - switch( p->type() ) { - case type::STRING: - add_type( p->unsafe_get_string() ); - break; - case type::ARRAY: - for( const auto& e : p->unsafe_get_array() ) { - if( !e.is_string() ) { - throw std::runtime_error( "invalid JSON Schema: elements in array \"type\" must be of type 'string'" ); - } - add_type( e.unsafe_get_string() ); - } - break; - default: - throw std::runtime_error( "invalid JSON Schema: \"type\" must be of type 'string' or 'array'" ); - } - m_flags = m_flags | HAS_TYPE; - } - - // enum - if( const auto* p = find( "enum" ) ) { - if( !p->is_array() ) { - throw std::runtime_error( "invalid JSON Schema: \"enum\" must be of type 'array'" ); - } - m_flags = m_flags | HAS_ENUM; - } - - // allOf - if( const auto* p = find( "allOf" ) ) { - if( !p->is_array() ) { - throw std::runtime_error( "invalid JSON Schema: \"allOf\" must be of type 'array'" ); - } - if( p->empty() ) { - throw std::runtime_error( "invalid JSON Schema: \"allOf\" must have at least one element" ); - } - for( const auto& e : p->unsafe_get_array() ) { - m_referenced_pointers.insert( e.skip_raw_ptr() ); - } - m_all_of = p; - } - - // anyOf - if( const auto* p = find( "anyOf" ) ) { - if( !p->is_array() ) { - throw std::runtime_error( "invalid JSON Schema: \"anyOf\" must be of type 'array'" ); - } - if( p->empty() ) { - throw std::runtime_error( "invalid JSON Schema: \"anyOf\" must have at least one element" ); - } - for( const auto& e : p->unsafe_get_array() ) { - m_referenced_pointers.insert( e.skip_raw_ptr() ); - } - m_any_of = p; - } - - // oneOf - if( const auto* p = find( "oneOf" ) ) { - if( !p->is_array() ) { - throw std::runtime_error( "invalid JSON Schema: \"oneOf\" must be of type 'array'" ); - } - if( p->empty() ) { - throw std::runtime_error( "invalid JSON Schema: \"oneOf\" must have at least one element" ); - } - for( const auto& e : p->unsafe_get_array() ) { - m_referenced_pointers.insert( e.skip_raw_ptr() ); - } - m_one_of = p; - } - - // not - if( const auto* p = find( "not" ) ) { - m_referenced_pointers.insert( p ); - m_not = p; - } - - // definitions - if( const auto* p = find( "definitions" ) ) { - if( !p->is_object() ) { - throw std::runtime_error( "invalid JSON Schema: \"definitions\" must be of type 'object'" ); - } - for( const auto& e : p->unsafe_get_object() ) { - m_referenced_pointers.insert( e.second.skip_raw_ptr() ); - } - } - - // multipleOf - if( const auto* p = find( "multipleOf" ) ) { - switch( p->type() ) { - case type::SIGNED: { - const auto i = p->unsafe_get_signed(); - if( i <= 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"multipleOf\" must be strictly greater than zero" ); - } - m_multiple_of.u = i; - m_flags = m_flags | HAS_MULTIPLE_OF_UNSIGNED; - } break; - case type::UNSIGNED: { - const auto u = p->unsafe_get_unsigned(); - if( u == 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"multipleOf\" must be strictly greater than zero" ); - } - m_multiple_of.u = u; - m_flags = m_flags | HAS_MULTIPLE_OF_UNSIGNED; - } break; - case type::DOUBLE: { - const auto d = p->unsafe_get_double(); - if( d <= 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"multipleOf\" must be strictly greater than zero" ); - } - m_multiple_of.d = d; - m_flags = m_flags | HAS_MULTIPLE_OF_DOUBLE; - } break; - default: - throw std::runtime_error( "invalid JSON Schema: \"multipleOf\" must be of type 'number'" ); - } - } - - // maximum - if( const auto* p = find( "maximum" ) ) { - switch( p->type() ) { - case type::SIGNED: - m_maximum.i = p->unsafe_get_signed(); - m_flags = m_flags | HAS_MAXIMUM_SIGNED; - break; - case type::UNSIGNED: - m_maximum.u = p->unsafe_get_unsigned(); - m_flags = m_flags | HAS_MAXIMUM_UNSIGNED; - break; - case type::DOUBLE: - m_maximum.d = p->unsafe_get_double(); - m_flags = m_flags | HAS_MAXIMUM_DOUBLE; - break; - default: - throw std::runtime_error( "invalid JSON Schema: \"maximum\" must be of type 'number'" ); - } - } - - // exclusiveMaximum - if( const auto* p = find( "exclusiveMaximum" ) ) { - if( !p->is_boolean() ) { - throw std::runtime_error( "invalid JSON Schema: \"exclusiveMaximum\" must be of type 'boolean'" ); - } - if( ( m_flags & HAS_MAXIMUM ) == 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"exclusiveMaximum\" requires presence of \"maximum\"" ); - } - if( p->get_boolean() ) { - m_flags = m_flags | EXCLUSIVE_MAXIMUM; - } - } - - // minimum - if( const auto* p = find( "minimum" ) ) { - switch( p->type() ) { - case type::SIGNED: - m_minimum.i = p->unsafe_get_signed(); - m_flags = m_flags | HAS_MINIMUM_SIGNED; - break; - case type::UNSIGNED: - m_minimum.u = p->unsafe_get_unsigned(); - m_flags = m_flags | HAS_MINIMUM_UNSIGNED; - break; - case type::DOUBLE: - m_minimum.d = p->unsafe_get_double(); - m_flags = m_flags | HAS_MINIMUM_DOUBLE; - break; - default: - throw std::runtime_error( "invalid JSON Schema: \"minimum\" must be of type 'number'" ); - } - } - - // exclusiveMinimum - if( const auto* p = find( "exclusiveMinimum" ) ) { - if( !p->is_boolean() ) { - throw std::runtime_error( "invalid JSON Schema: \"exclusiveMinimum\" must be of type 'boolean'" ); - } - if( ( m_flags & HAS_MINIMUM ) == 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"exclusiveMinimum\" requires presence of \"minimum\"" ); - } - if( p->get_boolean() ) { - m_flags = m_flags | EXCLUSIVE_MINIMUM; - } - } - - // maxLength - if( const auto* p = find( "maxLength" ) ) { - switch( p->type() ) { - case type::SIGNED: { - const auto i = p->unsafe_get_signed(); - if( i < 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"maxLength\" must be greater than or equal to zero" ); - } - m_max_length = i; - m_flags = m_flags | HAS_MAX_LENGTH; - } break; - case type::UNSIGNED: - m_max_length = p->unsafe_get_unsigned(); - m_flags = m_flags | HAS_MAX_LENGTH; - break; - default: - throw std::runtime_error( "invalid JSON Schema: \"maxLength\" must be of type 'integer'" ); - } - } - - // minLength - if( const auto* p = find( "minLength" ) ) { - switch( p->type() ) { - case type::SIGNED: { - const auto i = p->unsafe_get_signed(); - if( i < 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"minLength\" must be greater than or equal to zero" ); - } - if( i > 0 ) { - m_min_length = i; - m_flags = m_flags | HAS_MIN_LENGTH; - } - } break; - case type::UNSIGNED: { - const auto u = p->unsafe_get_unsigned(); - if( u > 0 ) { - m_min_length = u; - m_flags = m_flags | HAS_MIN_LENGTH; - } - } break; - default: - throw std::runtime_error( "invalid JSON Schema: \"minLength\" must be of type 'integer'" ); - } - } - - // pattern - if( const auto* p = find( "pattern" ) ) { - if( !p->is_string() ) { - throw std::runtime_error( "invalid JSON Schema: \"pattern\" must be of type 'string'" ); - } - try { - m_pattern.reset( new std::regex( p->unsafe_get_string() ) ); - } - catch( const std::regex_error& e ) { - throw std::runtime_error( "invalid JSON Schema: \"pattern\" must be a regular expression: " + std::string( e.what() ) ); - } - } - - // format - // TODO: offer an option to disable "format" support? - if( const auto* p = find( "format" ) ) { - if( !p->is_string() ) { - throw std::runtime_error( "invalid JSON Schema: \"format\" must be of type 'string'" ); - } - const auto& s = p->unsafe_get_string(); - if( s == "date-time" ) { - m_format = schema_format::DATE_TIME; - } - else if( s == "email" ) { - m_format = schema_format::EMAIL; - } - else if( s == "hostname" ) { - m_format = schema_format::HOSTNAME; - } - else if( s == "ipv4" ) { - m_format = schema_format::IPV4; - } - else if( s == "ipv6" ) { - m_format = schema_format::IPV6; - } - else if( s == "uri" ) { - m_format = schema_format::URI; - } - // unknown "format" values are ignored - } - - // items - if( const auto* p = find( "items" ) ) { - if( p->is_array() ) { - for( const auto& e : p->unsafe_get_array() ) { - m_referenced_pointers.insert( e.skip_raw_ptr() ); - } - } - else if( p->is_object() ) { - m_referenced_pointers.insert( p ); - } - else { - throw std::runtime_error( "invalid JSON Schema: \"items\" must be of type 'object' or 'array'" ); - } - m_items = p; - } - - // additionalItems - if( const auto* p = find( "additionalItems" ) ) { - if( p->is_object() ) { - m_referenced_pointers.insert( p ); - } - else if( !p->is_boolean() ) { - throw std::runtime_error( "invalid JSON Schema: \"additionalItems\" must be of type 'boolean' or 'object'" ); - } - m_additional_items = p; - } - - // maxItems - if( const auto* p = find( "maxItems" ) ) { - switch( p->type() ) { - case type::SIGNED: { - const auto i = p->unsafe_get_signed(); - if( i < 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"maxItems\" must be greater than or equal to zero" ); - } - m_max_items = i; - m_flags = m_flags | HAS_MAX_ITEMS; - } break; - case type::UNSIGNED: - m_max_items = p->unsafe_get_unsigned(); - m_flags = m_flags | HAS_MAX_ITEMS; - break; - default: - throw std::runtime_error( "invalid JSON Schema: \"maxItems\" must be of type 'integer'" ); - } - } - - // minItems - if( const auto* p = find( "minItems" ) ) { - switch( p->type() ) { - case type::SIGNED: { - const auto i = p->unsafe_get_signed(); - if( i < 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"minItems\" must be greater than or equal to zero" ); - } - m_min_items = i; - m_flags = m_flags | HAS_MIN_ITEMS; - } break; - case type::UNSIGNED: - m_min_items = p->unsafe_get_unsigned(); - m_flags = m_flags | HAS_MIN_ITEMS; - break; - default: - throw std::runtime_error( "invalid JSON Schema: \"minItems\" must be of type 'integer'" ); - } - } - - // uniqueItems - if( const auto* p = find( "uniqueItems" ) ) { - if( p->get_boolean() ) { - m_flags = m_flags | HAS_UNIQUE_ITEMS; - } - } - - // maxProperties - if( const auto* p = find( "maxProperties" ) ) { - switch( p->type() ) { - case type::SIGNED: { - const auto i = p->unsafe_get_signed(); - if( i < 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"maxProperties\" must be greater than or equal to zero" ); - } - m_max_properties = i; - m_flags = m_flags | HAS_MAX_PROPERTIES; - } break; - case type::UNSIGNED: - m_max_properties = p->unsafe_get_unsigned(); - m_flags = m_flags | HAS_MAX_PROPERTIES; - break; - default: - throw std::runtime_error( "invalid JSON Schema: \"maxProperties\" must be of type 'integer'" ); - } - } - - // minProperties - if( const auto* p = find( "minProperties" ) ) { - switch( p->type() ) { - case type::SIGNED: { - const auto i = p->unsafe_get_signed(); - if( i < 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"minProperties\" must be greater than or equal to zero" ); - } - m_min_properties = i; - m_flags = m_flags | HAS_MIN_PROPERTIES; - } break; - case type::UNSIGNED: - m_min_properties = p->unsafe_get_unsigned(); - m_flags = m_flags | HAS_MIN_PROPERTIES; - break; - default: - throw std::runtime_error( "invalid JSON Schema: \"minProperties\" must be of type 'integer'" ); - } - } - - // required - if( const auto* p = find( "required" ) ) { - if( !p->is_array() ) { - throw std::runtime_error( "invalid JSON Schema: \"required\" must be of type 'array'" ); - } - if( p->empty() ) { - throw std::runtime_error( "invalid JSON Schema: \"required\" must have at least one element" ); - } - for( const auto& e : p->unsafe_get_array() ) { - if( !m_required.insert( e.get_string() ).second ) { - throw std::runtime_error( "invalid JSON Schema: duplicate required key" ); - } - } - } - - // properties - if( const auto* p = find( "properties" ) ) { - if( !p->is_object() ) { - throw std::runtime_error( "invalid JSON Schema: \"properties\" must be of type 'object'" ); - } - for( const auto& e : p->unsafe_get_object() ) { - m_referenced_pointers.insert( e.second.skip_raw_ptr() ); - } - m_properties = p; - } - - // patternProperties - if( const auto* p = find( "patternProperties" ) ) { - if( !p->is_object() ) { - throw std::runtime_error( "invalid JSON Schema: \"patternProperties\" must be of type 'object'" ); - } - for( const auto& e : p->unsafe_get_object() ) { - try { - m_pattern_properties.emplace_back( std::regex( e.first ), e.second.skip_raw_ptr() ); - } - catch( const std::regex_error& ex ) { - throw std::runtime_error( "invalid JSON Schema: keys in object \"patternProperties\" must be regular expressions: " + std::string( ex.what() ) ); - } - m_referenced_pointers.insert( e.second.skip_raw_ptr() ); - } - } - - // additionalProperties - if( const auto* p = find( "additionalProperties" ) ) { - const type t = p->type(); - if( t == type::OBJECT ) { - m_referenced_pointers.insert( p ); - } - else if( t != type::BOOLEAN ) { - throw std::runtime_error( "invalid JSON Schema: \"additionalProperties\" must be of type 'boolean' or 'object'" ); - } - m_additional_properties = p; - } - - // dependencies - if( const auto* p = find( "dependencies" ) ) { - if( !p->is_object() ) { - throw std::runtime_error( "invalid JSON Schema: \"dependencies\" must be of type 'object'" ); - } - for( const auto& e : p->unsafe_get_object() ) { - const auto* p2 = e.second.skip_raw_ptr(); - if( p2->is_object() ) { - m_schema_dependencies.emplace( e.first, p2 ); - m_referenced_pointers.insert( p2 ); - } - else if( p2->is_array() ) { - if( p2->empty() ) { - throw std::runtime_error( "invalid JSON Schema: values in object \"dependencies\" of type 'array' must have at least one element" ); - } - std::set< std::string > s; - for( const auto& r : p2->unsafe_get_array() ) { - if( !r.is_string() ) { - throw std::runtime_error( "invalid JSON Schema: values in object \"dependencies\" of type 'array' must contain elements of type 'string'" ); - } - if( !s.emplace( r.unsafe_get_string() ).second ) { - throw std::runtime_error( "invalid JSON Schema: values in object \"dependencies\" of type 'array' must contain unique elements of type 'string'" ); - } - } - m_property_dependencies.emplace( e.first, std::move( s ) ); - } - else { - throw std::runtime_error( "invalid JSON Schema: values in object \"dependencies\" must be of type 'object' or 'array'" ); - } - } - if( !p->empty() ) { - m_flags = m_flags | HAS_DEPENDENCIES; - } - } - - // default - if( const auto* p = find( "default" ) ) { - // TODO: the value should validate against the JSON Schema itself - } - } - - schema_node( const schema_node& ) = delete; - schema_node( schema_node&& ) = delete; - - void operator=( const schema_node& ) = delete; - void operator=( schema_node&& ) = delete; - - const std::set< const basic_value< Traits >* >& referenced_pointers() const noexcept - { - return m_referenced_pointers; - } - }; - - template< template< typename... > class Traits > - class schema_consumer - { - private: - const std::shared_ptr< const schema_container< Traits > > m_container; - const schema_node< Traits >* const m_node; - - std::vector< std::unique_ptr< events_compare< Traits > > > m_enum; - std::unique_ptr< events::hash > m_hash; - std::set< std::string > m_unique; - std::set< std::string > m_keys; - std::vector< std::size_t > m_count; - std::vector< std::unique_ptr< schema_consumer > > m_properties; - std::vector< std::unique_ptr< schema_consumer > > m_all_of; - std::vector< std::unique_ptr< schema_consumer > > m_any_of; - std::vector< std::unique_ptr< schema_consumer > > m_one_of; - std::map< std::string, std::unique_ptr< schema_consumer > > m_schema_dependencies; - std::unique_ptr< schema_consumer > m_not; - std::unique_ptr< schema_consumer > m_item; - bool m_match = true; - - void validate_type( const schema_flags t ) - { - if( !m_count.empty() ) { - return; - } - if( ( m_node->m_flags & HAS_TYPE ) == 0 ) { - return; - } - if( ( m_node->m_flags & t ) == 0 ) { - m_match = false; - } - } - - // note: lambda returns true if validation failure detected - template< typename F > - void validate_enum( F&& f ) - { - assert( m_match ); - if( m_node->m_flags & HAS_ENUM ) { - m_enum.erase( std::remove_if( m_enum.begin(), m_enum.end(), [&]( const std::unique_ptr< events_compare< Traits > >& p ) { return f( *p ); } ), m_enum.end() ); - if( m_enum.empty() ) { - m_match = false; - } - } - } - - template< typename F > - void validate_item( F&& f ) - { - if( m_item ) { - if( f( m_item ) ) { - m_match = false; - } - } - } - - template< typename F > - void validate_properties( F&& f ) - { - for( auto& p : m_properties ) { - if( f( p ) ) { - m_match = false; - break; - } - } - } - - template< typename F > - void validate_schema_dependencies( F&& f ) - { - auto it = m_schema_dependencies.begin(); - while( it != m_schema_dependencies.end() ) { - if( f( it->second ) ) { - it = m_schema_dependencies.erase( it ); - } - else { - ++it; - } - } - } - - template< typename F > - void validate_all_of( F&& f ) - { - for( auto& p : m_all_of ) { - if( f( p ) ) { - m_match = false; - break; - } - } - } - - template< typename F > - void validate_any_of( F&& f ) - { - if( !m_any_of.empty() ) { - m_any_of.erase( std::remove_if( m_any_of.begin(), m_any_of.end(), f ), m_any_of.end() ); - if( m_any_of.empty() ) { - m_match = false; - } - } - } - - template< typename F > - void validate_one_of( F&& f ) - { - if( !m_one_of.empty() ) { - m_one_of.erase( std::remove_if( m_one_of.begin(), m_one_of.end(), f ), m_one_of.end() ); - if( m_one_of.empty() ) { - m_match = false; - } - } - } - - template< typename F > - void validate_not( F&& f ) - { - if( m_not ) { - if( f( m_not ) ) { - m_not.reset(); - } - } - } - - // note: lambda returns true if validation failure detected - template< typename F > - void validate_collections( F&& f ) - { - assert( m_match ); - const auto f2 = [&]( const std::unique_ptr< schema_consumer >& p ) { return f( *p ); }; - if( m_match ) - validate_item( f2 ); - if( m_match ) - validate_properties( f2 ); - if( m_match ) - validate_all_of( f2 ); - if( m_match ) - validate_any_of( f2 ); - if( m_match ) - validate_one_of( f2 ); - if( m_match ) - validate_not( f2 ); - if( m_match ) - validate_schema_dependencies( f2 ); - } - - static bool is_multiple_of( const double v, const double d ) - { - const auto r = std::fmod( v, d ); - if( std::fabs( r ) < std::numeric_limits< double >::epsilon() ) { - return true; - } - if( std::fabs( r - d ) < std::numeric_limits< double >::epsilon() ) { - return true; - } - return false; - } - - void validate_multiple_of( const std::int64_t v ) - { - switch( m_node->m_flags & HAS_MULTIPLE_OF ) { - case HAS_MULTIPLE_OF_UNSIGNED: - if( v < 0 ) { - if( ( -v % m_node->m_multiple_of.u ) != 0 ) { - m_match = false; - } - } - else { - if( ( v % m_node->m_multiple_of.u ) != 0 ) { - m_match = false; - } - } - break; - case HAS_MULTIPLE_OF_DOUBLE: - if( !is_multiple_of( v, m_node->m_multiple_of.d ) ) { - m_match = false; - } - break; - } - } - - void validate_multiple_of( const std::uint64_t v ) - { - switch( m_node->m_flags & HAS_MULTIPLE_OF ) { - case HAS_MULTIPLE_OF_UNSIGNED: - if( ( v % m_node->m_multiple_of.u ) != 0 ) { - m_match = false; - } - break; - case HAS_MULTIPLE_OF_DOUBLE: - if( !is_multiple_of( v, m_node->m_multiple_of.d ) ) { - m_match = false; - } - break; - } - } - - void validate_multiple_of( const double v ) - { - switch( m_node->m_flags & HAS_MULTIPLE_OF ) { - case HAS_MULTIPLE_OF_UNSIGNED: - if( !is_multiple_of( v, m_node->m_multiple_of.u ) ) { - m_match = false; - } - break; - case HAS_MULTIPLE_OF_DOUBLE: - if( !is_multiple_of( v, m_node->m_multiple_of.d ) ) { - m_match = false; - } - break; - } - } - - void validate_number( const std::int64_t v ) - { - validate_multiple_of( v ); - switch( m_node->m_flags & ( HAS_MAXIMUM | EXCLUSIVE_MAXIMUM ) ) { - case HAS_MAXIMUM_SIGNED: - if( v > m_node->m_maximum.i ) { - m_match = false; - } - break; - case HAS_MAXIMUM_SIGNED | EXCLUSIVE_MAXIMUM: - if( v >= m_node->m_maximum.i ) { - m_match = false; - } - break; - case HAS_MAXIMUM_UNSIGNED: - if( v >= 0 && static_cast< std::uint64_t >( v ) > m_node->m_maximum.u ) { - m_match = false; - } - break; - case HAS_MAXIMUM_UNSIGNED | EXCLUSIVE_MAXIMUM: - if( v >= 0 && static_cast< std::uint64_t >( v ) >= m_node->m_maximum.u ) { - m_match = false; - } - break; - case HAS_MAXIMUM_DOUBLE: - if( v > m_node->m_maximum.d ) { - m_match = false; - } - break; - case HAS_MAXIMUM_DOUBLE | EXCLUSIVE_MAXIMUM: - if( v >= m_node->m_maximum.d ) { - m_match = false; - } - break; - } - switch( m_node->m_flags & ( HAS_MINIMUM | EXCLUSIVE_MINIMUM ) ) { - case HAS_MINIMUM_SIGNED: - if( v < m_node->m_minimum.i ) { - m_match = false; - } - break; - case HAS_MINIMUM_SIGNED | EXCLUSIVE_MINIMUM: - if( v <= m_node->m_minimum.i ) { - m_match = false; - } - break; - case HAS_MINIMUM_UNSIGNED: - if( v < 0 || static_cast< std::uint64_t >( v ) < m_node->m_minimum.u ) { - m_match = false; - } - break; - case HAS_MINIMUM_UNSIGNED | EXCLUSIVE_MINIMUM: - if( v < 0 || static_cast< std::uint64_t >( v ) <= m_node->m_minimum.u ) { - m_match = false; - } - break; - case HAS_MINIMUM_DOUBLE: - if( v < m_node->m_minimum.d ) { - m_match = false; - } - break; - case HAS_MINIMUM_DOUBLE | EXCLUSIVE_MINIMUM: - if( v <= m_node->m_minimum.d ) { - m_match = false; - } - break; - } - } - - void validate_number( const std::uint64_t v ) - { - validate_multiple_of( v ); - switch( m_node->m_flags & ( HAS_MAXIMUM | EXCLUSIVE_MAXIMUM ) ) { - case HAS_MAXIMUM_SIGNED: - if( m_node->m_maximum.i < 0 || v > static_cast< std::uint64_t >( m_node->m_maximum.i ) ) { - m_match = false; - } - break; - case HAS_MAXIMUM_SIGNED | EXCLUSIVE_MAXIMUM: - if( m_node->m_maximum.i < 0 || v >= static_cast< std::uint64_t >( m_node->m_maximum.i ) ) { - m_match = false; - } - break; - case HAS_MAXIMUM_UNSIGNED: - if( v > m_node->m_maximum.u ) { - m_match = false; - } - break; - case HAS_MAXIMUM_UNSIGNED | EXCLUSIVE_MAXIMUM: - if( v >= m_node->m_maximum.u ) { - m_match = false; - } - break; - case HAS_MAXIMUM_DOUBLE: - if( v > m_node->m_maximum.d ) { - m_match = false; - } - break; - case HAS_MAXIMUM_DOUBLE | EXCLUSIVE_MAXIMUM: - if( v >= m_node->m_maximum.d ) { - m_match = false; - } - break; - } - switch( m_node->m_flags & ( HAS_MINIMUM | EXCLUSIVE_MINIMUM ) ) { - case HAS_MINIMUM_SIGNED: - if( m_node->m_minimum.i >= 0 && v < static_cast< std::uint64_t >( m_node->m_minimum.i ) ) { - m_match = false; - } - break; - case HAS_MINIMUM_SIGNED | EXCLUSIVE_MINIMUM: - if( m_node->m_minimum.i >= 0 && v <= static_cast< std::uint64_t >( m_node->m_minimum.i ) ) { - m_match = false; - } - break; - case HAS_MINIMUM_UNSIGNED: - if( v < m_node->m_minimum.u ) { - m_match = false; - } - break; - case HAS_MINIMUM_UNSIGNED | EXCLUSIVE_MINIMUM: - if( v <= m_node->m_minimum.u ) { - m_match = false; - } - break; - case HAS_MINIMUM_DOUBLE: - if( v < m_node->m_minimum.d ) { - m_match = false; - } - break; - case HAS_MINIMUM_DOUBLE | EXCLUSIVE_MINIMUM: - if( v <= m_node->m_minimum.d ) { - m_match = false; - } - break; - } - } - - void validate_number( const double v ) - { - validate_multiple_of( v ); - switch( m_node->m_flags & ( HAS_MAXIMUM | EXCLUSIVE_MAXIMUM ) ) { - case HAS_MAXIMUM_SIGNED: - if( v > m_node->m_maximum.i ) { - m_match = false; - } - break; - case HAS_MAXIMUM_SIGNED | EXCLUSIVE_MAXIMUM: - if( v >= m_node->m_maximum.i ) { - m_match = false; - } - break; - case HAS_MAXIMUM_UNSIGNED: - if( v > m_node->m_maximum.u ) { - m_match = false; - } - break; - case HAS_MAXIMUM_UNSIGNED | EXCLUSIVE_MAXIMUM: - if( v >= m_node->m_maximum.u ) { - m_match = false; - } - break; - case HAS_MAXIMUM_DOUBLE: - if( v > m_node->m_maximum.d ) { - m_match = false; - } - break; - case HAS_MAXIMUM_DOUBLE | EXCLUSIVE_MAXIMUM: - if( v >= m_node->m_maximum.d ) { - m_match = false; - } - break; - } - switch( m_node->m_flags & ( HAS_MINIMUM | EXCLUSIVE_MINIMUM ) ) { - case HAS_MINIMUM_SIGNED: - if( v < m_node->m_minimum.i ) { - m_match = false; - } - break; - case HAS_MINIMUM_SIGNED | EXCLUSIVE_MINIMUM: - if( v <= m_node->m_minimum.i ) { - m_match = false; - } - break; - case HAS_MINIMUM_UNSIGNED: - if( v < m_node->m_minimum.u ) { - m_match = false; - } - break; - case HAS_MINIMUM_UNSIGNED | EXCLUSIVE_MINIMUM: - if( v <= m_node->m_minimum.u ) { - m_match = false; - } - break; - case HAS_MINIMUM_DOUBLE: - if( v < m_node->m_minimum.d ) { - m_match = false; - } - break; - case HAS_MINIMUM_DOUBLE | EXCLUSIVE_MINIMUM: - if( v <= m_node->m_minimum.d ) { - m_match = false; - } - break; - } - } - - void validate_string( const tao::string_view v ) - { - if( m_node->m_flags & HAS_MAX_LENGTH && v.size() > m_node->m_max_length ) { - m_match = false; - } - if( m_node->m_flags & HAS_MIN_LENGTH && v.size() < m_node->m_min_length ) { - m_match = false; - } - if( m_match && m_node->m_pattern ) { - if( !std::regex_search( v.begin(), v.end(), *m_node->m_pattern ) ) { - m_match = false; - } - } - if( m_match && m_node->m_format != schema_format::NONE ) { - switch( m_node->m_format ) { - case schema_format::DATE_TIME: - if( !internal::parse_date_time( v ) ) { - m_match = false; - } - break; - case schema_format::EMAIL: - if( ( v.size() > 255 ) || !internal::parse< internal::email >( v ) ) { - m_match = false; - } - break; - case schema_format::HOSTNAME: - if( ( v.size() > 255 ) || !internal::parse< internal::hostname >( v ) ) { - m_match = false; - } - break; - case schema_format::IPV4: - if( !internal::parse< json_pegtl::uri::IPv4address >( v ) ) { - m_match = false; - } - break; - case schema_format::IPV6: - if( !internal::parse< json_pegtl::uri::IPv6address >( v ) ) { - m_match = false; - } - break; - case schema_format::URI: - // TODO: What rule exactly should we apply here?? JSON Schema is not exactly the best spec I've ever read... - if( !internal::parse< json_pegtl::uri::URI >( v ) ) { - m_match = false; - } - break; - case schema_format::NONE:; - } - } - } - - void validate_elements( const std::size_t v ) - { - if( m_node->m_flags & HAS_MAX_ITEMS && v > m_node->m_max_items ) { - m_match = false; - } - if( m_node->m_flags & HAS_MIN_ITEMS && v < m_node->m_min_items ) { - m_match = false; - } - } - - void validate_members( const std::size_t v ) - { - if( m_node->m_flags & HAS_MAX_PROPERTIES && v > m_node->m_max_properties ) { - m_match = false; - } - if( m_node->m_flags & HAS_MIN_PROPERTIES && v < m_node->m_min_properties ) { - m_match = false; - } - } - - public: - schema_consumer( const std::shared_ptr< const schema_container< Traits > >& c, const schema_node< Traits >& n ) - : m_container( c ), - m_node( &n ) - { - if( m_node->m_flags & HAS_ENUM ) { - const auto& a = m_node->m_value->unsafe_at( "enum" ).unsafe_get_array(); - m_enum.reserve( a.size() ); - for( const auto& e : a ) { - m_enum.emplace_back( new events_compare< Traits >() ); - m_enum.back()->push( &e ); - } - } - if( const auto* p = m_node->m_all_of ) { - for( const auto& e : p->unsafe_get_array() ) { - m_all_of.push_back( m_container->consumer( e.skip_raw_ptr() ) ); - } - } - if( const auto* p = m_node->m_any_of ) { - for( const auto& e : p->unsafe_get_array() ) { - m_any_of.push_back( m_container->consumer( e.skip_raw_ptr() ) ); - } - } - if( const auto* p = m_node->m_one_of ) { - for( const auto& e : p->unsafe_get_array() ) { - m_one_of.push_back( m_container->consumer( e.skip_raw_ptr() ) ); - } - } - if( const auto* p = m_node->m_not ) { - m_not = m_container->consumer( p ); - } - for( const auto& e : m_node->m_schema_dependencies ) { - m_schema_dependencies.emplace( e.first, m_container->consumer( e.second ) ); - } - } - - schema_consumer( const schema_consumer& ) = delete; - schema_consumer( schema_consumer&& ) = delete; - - void operator=( const schema_consumer& ) = delete; - void operator=( schema_consumer&& ) = delete; - - bool finalize() - { - if( m_match && !m_all_of.empty() ) { - for( auto& e : m_all_of ) { - if( !e->finalize() ) { - m_match = false; - break; - } - } - } - if( m_match && !m_any_of.empty() ) { - m_any_of.erase( std::remove_if( m_any_of.begin(), m_any_of.end(), []( const std::unique_ptr< schema_consumer >& c ) { return !c->finalize(); } ), m_any_of.end() ); - if( m_any_of.empty() ) { - m_match = false; - } - } - if( m_match && !m_one_of.empty() ) { - m_one_of.erase( std::remove_if( m_one_of.begin(), m_one_of.end(), []( const std::unique_ptr< schema_consumer >& c ) { return !c->finalize(); } ), m_one_of.end() ); - if( m_one_of.size() != 1 ) { - m_match = false; - } - } - if( m_match && m_not && m_not->finalize() ) { - m_match = false; - } - if( m_match && m_node->m_flags & HAS_DEPENDENCIES ) { - for( const auto& e : m_node->m_schema_dependencies ) { - if( m_keys.count( e.first ) != 0 ) { - const auto it = m_schema_dependencies.find( e.first ); - if( it == m_schema_dependencies.end() ) { - m_match = false; - break; - } - if( !it->second->finalize() ) { - m_match = false; - break; - } - } - } - } - return m_match; - } - - bool match() const noexcept - { - return m_match; - } - - void null() - { - if( m_match ) - validate_type( NULL_ ); - if( m_match ) - validate_enum( []( events_compare< Traits >& c ) { c.null(); return ! c.match(); } ); - if( m_match ) - validate_collections( []( schema_consumer& c ) { c.null(); return ! c.match(); } ); - if( m_match && m_hash ) - m_hash->null(); - } - - void boolean( const bool v ) - { - if( m_match ) - validate_type( BOOLEAN ); - if( m_match ) - validate_enum( [=]( events_compare< Traits >& c ) { c.boolean( v ); return ! c.match(); } ); - if( m_match ) - validate_collections( [=]( schema_consumer& c ) { c.boolean( v ); return ! c.match(); } ); - if( m_match && m_hash ) - m_hash->boolean( v ); - } - - void number( const std::int64_t v ) - { - if( m_match ) - validate_type( INTEGER | NUMBER ); - if( m_match ) - validate_enum( [=]( events_compare< Traits >& c ) { c.number( v ); return ! c.match(); } ); - if( m_match ) - validate_collections( [=]( schema_consumer& c ) { c.number( v ); return ! c.match(); } ); - if( m_match && m_count.empty() ) - validate_number( v ); - if( m_match && m_hash ) - m_hash->number( v ); - } - - void number( const std::uint64_t v ) - { - if( m_match ) - validate_type( INTEGER | NUMBER ); - if( m_match ) - validate_enum( [=]( events_compare< Traits >& c ) { c.number( v ); return ! c.match(); } ); - if( m_match ) - validate_collections( [=]( schema_consumer& c ) { c.number( v ); return ! c.match(); } ); - if( m_match && m_count.empty() ) - validate_number( v ); - if( m_match && m_hash ) - m_hash->number( v ); - } - - void number( const double v ) - { - if( m_match ) - validate_type( NUMBER ); - if( m_match ) - validate_enum( [=]( events_compare< Traits >& c ) { c.number( v ); return ! c.match(); } ); - if( m_match ) - validate_collections( [=]( schema_consumer& c ) { c.number( v ); return ! c.match(); } ); - if( m_match && m_count.empty() ) - validate_number( v ); - if( m_match && m_hash ) - m_hash->number( v ); - } - - void string( const tao::string_view v ) - { - if( m_match ) - validate_type( STRING ); - if( m_match ) - validate_enum( [&]( events_compare< Traits >& c ) { c.string( v ); return ! c.match(); } ); - if( m_match ) - validate_collections( [&]( schema_consumer& c ) { c.string( v ); return ! c.match(); } ); - if( m_match && m_count.empty() ) - validate_string( v ); - if( m_match && m_hash ) - m_hash->string( v ); - } - - void binary( const tao::byte_view ) - { - // TODO: What? - } - - void begin_array( const std::size_t = 0 ) - { - if( m_match ) - validate_type( ARRAY ); - if( m_match ) - validate_enum( []( events_compare< Traits >& c ) { c.begin_array(); return ! c.match(); } ); - if( m_match ) - validate_collections( []( schema_consumer& c ) { c.begin_array(); return ! c.match(); } ); - if( m_match ) { - if( m_hash ) { - m_hash->begin_array(); - } - else if( m_count.empty() && ( ( m_node->m_flags & HAS_UNIQUE_ITEMS ) != 0 ) ) { - m_hash.reset( new events::hash ); - } - } - if( m_match && m_count.empty() ) { - if( const auto* p = m_node->m_items ) { - if( p->is_object() ) { - m_item = m_container->consumer( p ); - } - else { - const auto& a = p->unsafe_get_array(); - if( !a.empty() ) { - m_item = m_container->consumer( a[ 0 ].skip_raw_ptr() ); - } - } - } - if( !m_item ) { - if( const auto* p = m_node->m_additional_items ) { - if( p->is_object() ) { - m_item = m_container->consumer( p ); - } - } - } - } - m_count.push_back( 0 ); - } - - void element() - { - if( m_match ) - validate_enum( []( events_compare< Traits >& c ) { c.element(); return ! c.match(); } ); - if( m_match && m_item ) { - if( m_count.size() == 1 ) { - if( !m_item->finalize() ) { - m_match = false; - } - m_item.reset(); - } - } - if( m_match ) - validate_collections( []( schema_consumer& c ) { c.element(); return ! c.match(); } ); - if( m_match && m_hash ) { - if( m_count.size() == 1 ) { - if( !m_unique.emplace( m_hash->value() ).second ) { - m_match = false; - } - m_hash->reset(); - } - else { - m_hash->element(); - } - } - const auto next = ++m_count.back(); - if( m_match && ( m_count.size() == 1 ) ) { - if( const auto* p = m_node->m_items ) { - if( p->is_object() ) { - m_item = m_container->consumer( p ); - } - else { - const auto& a = p->unsafe_get_array(); - if( next < a.size() ) { - m_item = m_container->consumer( a[ next ].skip_raw_ptr() ); - } - } - } - if( !m_item ) { - if( const auto* p = m_node->m_additional_items ) { - if( p->is_object() ) { - m_item = m_container->consumer( p ); - } - } - } - } - } - - void end_array( const std::size_t = 0 ) - { - if( m_match ) - validate_enum( []( events_compare< Traits >& c ) { c.end_array(); return ! c.match(); } ); - if( m_match && m_item && ( m_count.size() == 1 ) ) { - if( !m_item->finalize() ) { - m_match = false; - } - m_item.reset(); - } - if( m_match && ( m_count.size() == 1 ) ) { - if( m_node->m_items && m_node->m_items->is_array() ) { - if( m_node->m_additional_items && m_node->m_additional_items->is_boolean() ) { - if( !m_node->m_additional_items->get_boolean() ) { - if( m_count.back() > m_node->m_items->unsafe_get_array().size() ) { - m_match = false; - } - } - } - } - } - if( m_match ) - validate_collections( []( schema_consumer& c ) { c.end_array(); return ! c.match(); } ); - if( m_match && m_hash ) - m_hash->end_array(); - if( m_match && ( m_count.size() == 1 ) ) - validate_elements( m_count.back() ); - m_count.pop_back(); - } - - void begin_object( const std::size_t = 0 ) - { - if( m_match ) - validate_type( OBJECT ); - if( m_match ) - validate_enum( []( events_compare< Traits >& c ) { c.begin_object(); return ! c.match(); } ); - if( m_match ) - validate_collections( []( schema_consumer& c ) { c.begin_object(); return ! c.match(); } ); - if( m_match && m_hash ) - m_hash->begin_object(); - m_count.push_back( 0 ); - } - - void key( const std::string& v ) - { - if( m_match ) - validate_enum( [&]( events_compare< Traits >& c ) { c.key( v ); return ! c.match(); } ); - if( m_match ) - validate_collections( [&]( schema_consumer& c ) { c.key( v ); return ! c.match(); } ); - if( m_match && m_hash ) - m_hash->key( v ); - if( m_match && ( m_count.size() == 1 ) && ( m_node->m_flags & HAS_DEPENDENCIES || !m_node->m_required.empty() ) ) { - if( !m_keys.insert( v ).second ) { - // duplicate keys immediately invalidate! - // TODO: throw? - m_match = false; - } - } - if( m_match && m_properties.empty() && ( m_count.size() == 1 ) ) { - if( const auto* p = m_node->m_properties ) { - const auto& o = p->unsafe_get_object(); - const auto it = o.find( v ); - if( it != o.end() ) { - m_properties.push_back( m_container->consumer( it->second.skip_raw_ptr() ) ); - } - } - for( const auto& e : m_node->m_pattern_properties ) { - if( std::regex_search( v, e.first ) ) { - m_properties.push_back( m_container->consumer( e.second ) ); - } - } - if( m_properties.empty() ) { - if( const auto* p = m_node->m_additional_properties ) { - if( p->is_boolean() ) { - if( !p->unsafe_get_boolean() ) { - m_match = false; - } - } - else { - m_properties.push_back( m_container->consumer( p ) ); - } - } - } - } - } - - void member() - { - if( m_match ) - validate_enum( []( events_compare< Traits >& c ) { c.member(); return ! c.match(); } ); - if( m_match && !m_properties.empty() && ( m_count.size() == 1 ) ) { - for( auto& e : m_properties ) { - if( !e->finalize() ) { - m_match = false; - break; - } - } - m_properties.clear(); - } - if( m_match ) - validate_collections( []( schema_consumer& c ) { c.member(); return ! c.match(); } ); - if( m_match && m_hash ) - m_hash->member(); - ++m_count.back(); - } - - void end_object( const std::size_t = 0 ) - { - if( m_match ) - validate_enum( []( events_compare< Traits >& c ) { c.end_object(); return ! c.match(); } ); - if( m_match ) - validate_collections( []( schema_consumer& c ) { c.end_object(); return ! c.match(); } ); - if( m_match && m_hash ) - m_hash->end_object(); - if( m_match && ( m_count.size() == 1 ) ) - validate_members( m_count.back() ); - if( m_match && ( m_count.size() == 1 ) && !m_node->m_required.empty() ) { - if( !std::includes( m_keys.begin(), m_keys.end(), m_node->m_required.begin(), m_node->m_required.end() ) ) { - m_match = false; - } - } - if( m_match && ( m_count.size() == 1 ) && m_node->m_flags & HAS_DEPENDENCIES ) { - for( const auto& e : m_node->m_property_dependencies ) { - if( m_keys.count( e.first ) != 0 ) { - if( !std::includes( m_keys.begin(), m_keys.end(), e.second.begin(), e.second.end() ) ) { - m_match = false; - break; - } - } - } - } - m_count.pop_back(); - } - }; - - template< template< typename... > class Traits > - class schema_container - : public std::enable_shared_from_this< schema_container< Traits > > - { - private: - basic_value< Traits > m_value; - - using nodes_t = std::map< const basic_value< Traits >*, std::unique_ptr< schema_node< Traits > > >; - nodes_t m_nodes; - - void make_node( const basic_value< Traits >* p ) - { - m_nodes.emplace( p, std::unique_ptr< schema_node< Traits > >( new schema_node< Traits >( this, *p ) ) ); - } - - public: - explicit schema_container( const basic_value< Traits >& v ) - : m_value( *v.skip_raw_ptr() ) - { - resolve_references( m_value ); - make_node( &m_value ); - while( true ) { - std::set< const basic_value< Traits >* > required; - for( const auto& e : m_nodes ) { - auto s = e.second->referenced_pointers(); - required.insert( s.begin(), s.end() ); - } - for( const auto& e : m_nodes ) { - required.erase( e.first ); - } - if( required.empty() ) { - break; - } - for( const auto& e : required ) { - make_node( e ); - } - } - } - - std::unique_ptr< schema_consumer< Traits > > consumer( const basic_value< Traits >* p ) const - { - const auto it = m_nodes.find( p ); - if( it == m_nodes.end() ) { - throw std::logic_error( "invalid node ptr, no schema registered" ); - } - return std::unique_ptr< schema_consumer< Traits > >( new schema_consumer< Traits >( this->shared_from_this(), *it->second ) ); - } - - std::unique_ptr< schema_consumer< Traits > > consumer() const - { - return consumer( &m_value ); - } - }; - - } // namespace internal - - template< template< typename... > class Traits > - class basic_schema - { - private: - const std::shared_ptr< const internal::schema_container< Traits > > m_container; - - public: - explicit basic_schema( const basic_value< Traits >& v ) - : m_container( std::make_shared< internal::schema_container< Traits > >( v ) ) - { - } - - std::unique_ptr< internal::schema_consumer< Traits > > consumer() const - { - return m_container->consumer(); - } - - bool validate( const basic_value< Traits >& v ) const - { - // TODO: Value validation should be implemented independently, - // as it could be more efficient than Events validation! - const auto c = consumer(); - events::from_value( *c, v ); - return c->finalize(); - } - }; - - using schema = basic_schema< traits >; - - template< template< typename... > class Traits > - basic_schema< Traits > make_schema( const basic_value< Traits >& v ) - { - return basic_schema< Traits >( v ); - } - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/self_contained.hpp b/include/tao/json/self_contained.hpp index 993d21d7..22673852 100644 --- a/include/tao/json/self_contained.hpp +++ b/include/tao/json/self_contained.hpp @@ -1,137 +1,143 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_SELF_CONTAINED_HPP -#define TAOCPP_JSON_INCLUDE_SELF_CONTAINED_HPP +#ifndef TAO_JSON_SELF_CONTAINED_HPP +#define TAO_JSON_SELF_CONTAINED_HPP + +#include "events/to_value.hpp" +#include "events/virtual_ref.hpp" #include "value.hpp" -namespace tao +namespace tao::json { - namespace json + // recursively checks for the existence + // of VALUE_PTR or OPAQUE_PTR nodes, STRING_VIEW or BINARY_VIEW, + // returns true is no such nodes were found. + + template< template< typename... > class Traits > + [[nodiscard]] bool is_self_contained( const basic_value< Traits >& v ) noexcept { - // recursively checks for the existence if RAW_PTR nodes, - // STRING_VIEW or BINARY_VIEW, - // returns true is no such nodes were found. - template< template< typename... > class Traits > - bool is_self_contained( const basic_value< Traits >& v ) noexcept - { - switch( v.type() ) { - case type::UNINITIALIZED: - return true; - - // LCOV_EXCL_START - case type::DISCARDED: - assert( v.type() != type::DISCARDED ); - return false; - - case type::DESTROYED: - assert( v.type() != type::DESTROYED ); - return false; - // LCOV_EXCL_STOP - - case type::NULL_: - case type::BOOLEAN: - case type::SIGNED: - case type::UNSIGNED: - case type::DOUBLE: - case type::STRING: - case type::BINARY: - return true; - - case type::STRING_VIEW: - case type::BINARY_VIEW: - return false; - - case type::ARRAY: - for( auto& e : v.unsafe_get_array() ) { - if( !is_self_contained( e ) ) { - return false; - } + switch( v.type() ) { + case type::UNINITIALIZED: + return true; + + case type::NULL_: + case type::BOOLEAN: + case type::SIGNED: + case type::UNSIGNED: + case type::DOUBLE: + case type::STRING: + case type::BINARY: + return true; + + case type::STRING_VIEW: + case type::BINARY_VIEW: + return false; + + case type::ARRAY: + for( auto& e : v.get_array() ) { + if( !is_self_contained( e ) ) { + return false; } - return true; + } + return true; - case type::OBJECT: - for( auto& e : v.unsafe_get_object() ) { - if( !is_self_contained( e.second ) ) { - return false; - } + case type::OBJECT: + for( auto& e : v.get_object() ) { + if( !is_self_contained( e.second ) ) { + return false; } - return true; + } + return true; - case type::RAW_PTR: - return false; - } - // LCOV_EXCL_START - assert( false ); - return false; - // LCOV_EXCL_STOP + case type::VALUE_PTR: + return false; + + case type::OPAQUE_PTR: + return false; + + case type::VALUELESS_BY_EXCEPTION: + return true; } + // LCOV_EXCL_START + assert( false ); + return false; + // LCOV_EXCL_STOP + } + + // Removes all VALUE_PTR and OPAQUE_PTR nodes, + // recursively, by copying/generating their content; + // replaces STRING_VIEW and BINARY_VIEW with STRING + // and BINARY, respectively, with a copy of the data. + + template< template< typename... > class Traits > + void make_self_contained( basic_value< Traits >& v ) + { + switch( v.type() ) { + case type::UNINITIALIZED: + return; + + case type::NULL_: + case type::BOOLEAN: + case type::SIGNED: + case type::UNSIGNED: + case type::DOUBLE: + case type::STRING: + case type::BINARY: + return; + + case type::STRING_VIEW: + v.emplace_string( v.get_string_view() ); + return; + + case type::BINARY_VIEW: { + const auto xv = v.get_binary_view(); + v.emplace_binary( xv.begin(), xv.end() ); + return; + } - // removes all RAW_PTR nodes, recursively, by copying their pointed-to content - // or replacing a nullptr RAW_PTR node with a null node. - // replaces STRING_VIEW and BINARY_VIEW with copies. - template< template< typename... > class Traits > - void make_self_contained( basic_value< Traits >& v ) - { - switch( v.type() ) { - case type::UNINITIALIZED: - return; - - case type::DISCARDED: - throw std::logic_error( "attempt to use a discarded value" ); - - case type::DESTROYED: - throw std::logic_error( "attempt to use a destroyed value" ); - - case type::NULL_: - case type::BOOLEAN: - case type::SIGNED: - case type::UNSIGNED: - case type::DOUBLE: - case type::STRING: - case type::BINARY: - return; - - case type::STRING_VIEW: { - const auto sv = v.unsafe_get_string_view(); - v.unsafe_emplace_string( sv.data(), sv.size() ); - return; + case type::ARRAY: + for( auto& e : v.get_array() ) { + make_self_contained( e ); } + return; - case type::BINARY_VIEW: { - const auto xv = v.unsafe_get_binary_view(); - v.unsafe_emplace_binary( xv.begin(), xv.end() ); - return; + case type::OBJECT: + for( auto& e : v.get_object() ) { + make_self_contained( e.second ); } - - case type::ARRAY: - for( auto& e : v.unsafe_get_array() ) { - make_self_contained( e ); - } - return; - - case type::OBJECT: - for( auto& e : v.unsafe_get_object() ) { - make_self_contained( e.second ); - } - return; - - case type::RAW_PTR: - if( const auto* p = v.unsafe_get_raw_ptr() ) { - v = *p; - make_self_contained( v ); - } - else { - v.unsafe_assign_null(); - } - return; + return; + + case type::VALUE_PTR: + v = *v.get_value_ptr(); + make_self_contained( v ); + return; + + case type::OPAQUE_PTR: { + const auto& q = v.get_opaque_ptr(); + events::to_basic_value< Traits > consumer; + events::virtual_ref< events::to_basic_value< Traits > > ref( consumer ); + q.producer( ref, q.data ); + consumer.value.public_base() = std::move( v.public_base() ); + v = std::move( consumer.value ); + return; } - throw std::logic_error( "invalid value for tao::json::type" ); // LCOV_EXCL_LINE + + case type::VALUELESS_BY_EXCEPTION: + return; } + throw std::logic_error( "invalid value for tao::json::type" ); // LCOV_EXCL_LINE + } - } // namespace json + template< template< typename... > class Traits > + [[nodiscard]] basic_value< Traits > self_contained_copy( const basic_value< Traits >& v ) + { + basic_value< Traits > r( &v ); + make_self_contained( r ); + return r; + } -} // namespace tao +} // namespace tao::json #endif diff --git a/include/tao/json/single.hpp b/include/tao/json/single.hpp deleted file mode 100644 index d3e681ca..00000000 --- a/include/tao/json/single.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAOCPP_JSON_INCLUDE_SINGLE_HPP -#define TAOCPP_JSON_INCLUDE_SINGLE_HPP - -#include - -#include "pair.hpp" - -namespace tao -{ - namespace json - { - template< template< typename... > class Traits > - class basic_value; - - template< template< typename... > class Traits > - struct single - { - mutable basic_value< Traits > value; - - template< typename U > - single( U&& v ) - : value( std::forward< U >( v ) ) - { - } - - single( std::initializer_list< pair< Traits > >&& l ) - : value( std::move( l ) ) - { - } - - single( const std::initializer_list< pair< Traits > >& l ) - : value( l ) - { - } - - single( std::initializer_list< pair< Traits > >& l ) - : value( l ) - { - } - }; - - } // namespace json - -} // namespace tao - -#endif diff --git a/include/tao/json/span.hpp b/include/tao/json/span.hpp new file mode 100644 index 00000000..bcdb61e2 --- /dev/null +++ b/include/tao/json/span.hpp @@ -0,0 +1,568 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_SPAN_HPP +#define TAO_JSON_SPAN_HPP + +#if !defined( TAO_JSON_USE_STD_SPAN ) && ( __cplusplus > 201703L ) && defined( __has_include ) +// clang-format off +#if __has_include() +// clang-format on +#define TAO_JSON_USE_STD_SPAN +#endif +#endif + +#if defined( TAO_JSON_USE_STD_SPAN ) + +#include + +namespace tao +{ + using std::dynamic_extent; + using std::span; + + using std::as_bytes; + using std::as_writable_bytes; + +} // namespace tao + +#else + +#include +#include +#include +#include +#include +#include +#include + +namespace tao +{ + inline constexpr std::size_t dynamic_extent = std::numeric_limits< std::size_t >::max(); + + template< typename ElementType, std::size_t Extent = dynamic_extent > + class span; + + namespace internal + { + template< typename > + struct is_span_impl + : std::false_type + {}; + + template< typename ElementType, std::size_t Extent > + struct is_span_impl< span< ElementType, Extent > > + : std::true_type + {}; + + template< typename T > + using is_span = is_span_impl< std::remove_cv_t< T > >; + + template< typename > + struct is_std_array_impl + : std::false_type + {}; + + template< typename T, std::size_t N > + struct is_std_array_impl< std::array< T, N > > + : std::true_type + {}; + + template< typename T > + using is_std_array = is_std_array_impl< std::remove_cv_t< T > >; + + template< typename T, typename ElementType > + using is_span_compatible_ptr = std::is_convertible< T ( * )[], ElementType ( * )[] >; + + template< typename, typename, typename = void > + struct is_span_compatible_container + : std::false_type + {}; + + template< typename Container, typename ElementType > + struct is_span_compatible_container< Container, + ElementType, + std::void_t< + std::enable_if_t< !is_span< Container >::value >, + std::enable_if_t< !is_std_array< Container >::value >, + std::enable_if_t< !std::is_array_v< Container > >, + decltype( std::data( std::declval< Container >() ) ), + decltype( std::size( std::declval< Container >() ) ), + std::enable_if_t< is_span_compatible_ptr< std::remove_pointer_t< decltype( std::data( std::declval< Container& >() ) ) >, ElementType >::value > > > + : std::true_type + {}; + + } // namespace internal + + template< typename ElementType, std::size_t Extent > + class span + { + public: + static_assert( !std::is_abstract_v< ElementType > ); + + using element_type = ElementType; + using value_type = std::remove_cv_t< ElementType >; + using index_type = std::size_t; + using difference_type = std::ptrdiff_t; + using pointer = element_type*; + using const_pointer = const element_type*; + using reference = element_type&; + using const_reference = const element_type&; + using iterator = pointer; + using const_iterator = const_pointer; + using reverse_iterator = std::reverse_iterator< iterator >; + using const_reverse_iterator = std::reverse_iterator< const_iterator >; + + static constexpr index_type extent = Extent; + + template< typename T = void, typename = std::enable_if_t< Extent == 0, T > > + constexpr span() noexcept + : m_data( nullptr ) + {} + + constexpr span( pointer ptr, index_type count ) noexcept + : m_data( ptr ) + { + assert( count == Extent ); + } + + constexpr span( pointer first, pointer last ) noexcept + : m_data( first ) + { + assert( std::distance( first, last ) == Extent ); + } + + constexpr span( element_type ( &arr )[ Extent ] ) noexcept + : m_data( arr ) + {} + + template< std::size_t N, typename = std::enable_if_t< ( N == Extent ) && tao::internal::is_span_compatible_ptr< value_type, ElementType >::value > > + constexpr span( std::array< value_type, N >& arr ) noexcept + : m_data( arr.data() ) + {} + + template< std::size_t N, typename = std::enable_if_t< ( N == Extent ) && tao::internal::is_span_compatible_ptr< const value_type, ElementType >::value > > + constexpr span( const std::array< value_type, N >& arr ) noexcept + : m_data( arr.data() ) + {} + + constexpr span( const span& other ) = default; + + template< typename OtherElementType, typename = std::enable_if_t< tao::internal::is_span_compatible_ptr< OtherElementType, ElementType >::value > > + constexpr span( const span< OtherElementType, Extent >& s ) noexcept + : m_data( s.data() ) + {} + + ~span() = default; + + constexpr span& operator=( const span& ) = default; + + constexpr index_type size() const noexcept + { + return Extent; + } + + constexpr index_type size_bytes() const noexcept + { + return Extent * sizeof( element_type ); + } + + [[nodiscard]] constexpr bool empty() const noexcept + { + return Extent == 0; + } + + constexpr reference operator[]( index_type idx ) const noexcept + { + assert( idx < Extent ); + return *( data() + idx ); + } + + constexpr reference front() const noexcept + { + assert( Extent != 0 ); + return *data(); + } + + constexpr reference back() const noexcept + { + assert( Extent != 0 ); + return *( data() + ( Extent - 1 ) ); + } + + constexpr pointer data() const noexcept + { + return m_data; + } + + constexpr iterator begin() const noexcept + { + return data(); + } + + constexpr const_iterator cbegin() const noexcept + { + return data(); + } + + constexpr iterator end() const noexcept + { + return data() + Extent; + } + + constexpr const_iterator cend() const noexcept + { + return data() + Extent; + } + + constexpr reverse_iterator rbegin() const noexcept + { + return reverse_iterator( end() ); + } + + constexpr reverse_iterator rend() const noexcept + { + return reverse_iterator( begin() ); + } + + constexpr const_reverse_iterator crbegin() const noexcept + { + return const_reverse_iterator( cend() ); + } + + constexpr const_reverse_iterator crend() const noexcept + { + return const_reverse_iterator( cbegin() ); + } + + friend constexpr iterator begin( span s ) noexcept + { + return s.begin(); + } + + friend constexpr iterator end( span s ) noexcept + { + return s.end(); + } + + template< std::size_t Count > + constexpr span< element_type, Count > first() const noexcept + { + static_assert( Count <= Extent ); + return { data(), Count }; + } + + template< std::size_t Count > + constexpr span< element_type, Count > last() const noexcept + { + static_assert( Count <= Extent ); + return { data() + ( Extent - Count ), Count }; + } + + template< std::size_t Offset, std::size_t Count = dynamic_extent > + constexpr auto subspan() const + -> span< element_type, ( ( Count != dynamic_extent ) ? Count : ( Extent - Offset ) ) > + { + static_assert( Offset <= Extent ); + static_assert( ( Count == dynamic_extent ) || ( Count <= ( Extent - Offset ) ) ); + return { data() + Offset, ( Count != dynamic_extent ) ? Count : ( Extent - Offset ) }; + } + + constexpr span< element_type, dynamic_extent > first( index_type count ) const + { + assert( count <= Extent ); + return { data(), count }; + } + + constexpr span< element_type, dynamic_extent > last( index_type count ) const + { + assert( count <= Extent ); + return { data() + Extent - count, count }; + } + + constexpr span< element_type, dynamic_extent > subspan( index_type offset, index_type count = dynamic_extent ) const + { + assert( offset <= Extent ); + assert( ( count == dynamic_extent ) || ( count <= ( Extent - offset ) ) ); + return { data() + offset, ( count != dynamic_extent ) ? count : ( Extent - offset ) }; + } + + private: + pointer m_data; + }; + + template< typename ElementType > + class span< ElementType, dynamic_extent > + { + public: + static_assert( !std::is_abstract_v< ElementType > ); + + using element_type = ElementType; + using value_type = std::remove_cv_t< ElementType >; + using index_type = std::size_t; + using difference_type = std::ptrdiff_t; + using pointer = element_type*; + using const_pointer = const element_type*; + using reference = element_type&; + using const_reference = const element_type&; + using iterator = pointer; + using const_iterator = const_pointer; + using reverse_iterator = std::reverse_iterator< iterator >; + using const_reverse_iterator = std::reverse_iterator< const_iterator >; + + static constexpr index_type extent = dynamic_extent; + + constexpr span() noexcept + : m_data( nullptr ), m_size( 0 ) + {} + + constexpr span( pointer ptr, index_type count ) noexcept + : m_data( ptr ), m_size( count ) + {} + + constexpr span( pointer first, pointer last ) noexcept + : m_data( first ), m_size( std::distance( first, last ) ) + {} + + template< std::size_t N > + constexpr span( element_type ( &arr )[ N ] ) noexcept + : m_data( arr ), m_size( N ) + {} + + template< std::size_t N, typename = std::enable_if_t< tao::internal::is_span_compatible_ptr< value_type, ElementType >::value > > + constexpr span( std::array< value_type, N >& arr ) noexcept + : m_data( arr.data() ), m_size( N ) + {} + + template< std::size_t N, typename = std::enable_if_t< tao::internal::is_span_compatible_ptr< const value_type, ElementType >::value > > + constexpr span( const std::array< value_type, N >& arr ) noexcept + : m_data( arr.data() ), m_size( N ) + {} + + template< typename Container, typename = std::enable_if_t< tao::internal::is_span_compatible_container< Container, ElementType >::value > > + constexpr span( Container& cont ) + : m_data( std::data( cont ) ), m_size( std::size( cont ) ) + {} + + template< typename Container, typename = std::enable_if_t< tao::internal::is_span_compatible_container< const Container, ElementType >::value > > + constexpr span( const Container& cont ) + : m_data( std::data( cont ) ), m_size( std::size( cont ) ) + {} + + constexpr span( const span& other ) = default; + + template< typename OtherElementType, std::size_t OtherExtent, typename = std::enable_if_t< tao::internal::is_span_compatible_ptr< OtherElementType, ElementType >::value > > + constexpr span( const span< OtherElementType, OtherExtent >& s ) noexcept + : m_data( s.data() ), m_size( s.size() ) + {} + + ~span() = default; + + constexpr span& operator=( const span& ) = default; + + constexpr index_type size() const noexcept + { + return m_size; + } + + constexpr index_type size_bytes() const noexcept + { + return size() * sizeof( element_type ); + } + + [[nodiscard]] constexpr bool empty() const noexcept + { + return size() == 0; + } + + constexpr reference operator[]( index_type idx ) const noexcept + { + assert( idx < size() ); + return *( data() + idx ); + } + + constexpr reference front() const noexcept + { + assert( !empty() ); + return *data(); + } + + constexpr reference back() const noexcept + { + assert( !empty() ); + return *( data() + ( size() - 1 ) ); + } + + constexpr pointer data() const noexcept + { + return m_data; + } + + constexpr iterator begin() const noexcept + { + return data(); + } + + constexpr const_iterator cbegin() const noexcept + { + return data(); + } + + constexpr iterator end() const noexcept + { + return data() + size(); + } + + constexpr const_iterator cend() const noexcept + { + return data() + size(); + } + + constexpr reverse_iterator rbegin() const noexcept + { + return reverse_iterator( end() ); + } + + constexpr reverse_iterator rend() const noexcept + { + return reverse_iterator( begin() ); + } + + constexpr const_reverse_iterator crbegin() const noexcept + { + return const_reverse_iterator( cend() ); + } + + constexpr const_reverse_iterator crend() const noexcept + { + return const_reverse_iterator( cbegin() ); + } + + friend constexpr iterator begin( span s ) noexcept + { + return s.begin(); + } + + friend constexpr iterator end( span s ) noexcept + { + return s.end(); + } + + template< std::size_t Count > + constexpr span< element_type, Count > first() const noexcept + { + assert( Count <= size() ); + return { data(), Count }; + } + + template< std::size_t Count > + constexpr span< element_type, Count > last() const noexcept + { + assert( Count <= size() ); + return { data() + ( size() - Count ), Count }; + } + + template< std::size_t Offset, std::size_t Count = dynamic_extent > + constexpr auto subspan() const + -> span< element_type, ( ( Count != dynamic_extent ) ? Count : dynamic_extent ) > + { + assert( Offset <= size() ); + assert( ( Count == dynamic_extent ) || ( Count <= ( size() - Offset ) ) ); + return { data() + Offset, ( Count != dynamic_extent ) ? Count : ( size() - Offset ) }; + } + + constexpr span< element_type, dynamic_extent > first( index_type count ) const + { + assert( count <= size() ); + return { data(), count }; + } + + constexpr span< element_type, dynamic_extent > last( index_type count ) const + { + assert( count <= size() ); + return { data() + size() - count, count }; + } + + constexpr span< element_type, dynamic_extent > subspan( index_type offset, index_type count = dynamic_extent ) const + { + assert( offset <= size() ); + assert( ( count == dynamic_extent ) || ( count <= ( size() - offset ) ) ); + return { data() + offset, ( count != dynamic_extent ) ? count : ( size() - offset ) }; + } + + private: + pointer m_data; + index_type m_size; + }; + + template< typename ElementType, std::size_t Extent > + auto as_bytes( span< ElementType, Extent > s ) noexcept + -> span< const std::byte, ( ( Extent == dynamic_extent ) ? dynamic_extent : ( sizeof( ElementType ) * Extent ) ) > + { + return { reinterpret_cast< const std::byte* >( s.data() ), s.size_bytes() }; + } + + template< typename ElementType, std::size_t Extent, typename = std::enable_if_t< !std::is_const_v< ElementType > > > + auto as_writable_bytes( span< ElementType, Extent > s ) noexcept + -> span< std::byte, ( ( Extent == dynamic_extent ) ? dynamic_extent : ( sizeof( ElementType ) * Extent ) ) > + { + return { reinterpret_cast< std::byte* >( s.data() ), s.size_bytes() }; + } + + // deduction guides + template< typename T, std::size_t N > + span( T ( & )[ N ] )->span< T, N >; + + template< typename T, std::size_t N > + span( std::array< T, N >& )->span< T, N >; + + template< typename T, std::size_t N > + span( const std::array< T, N >& )->span< const T, N >; + + template< typename Container > + span( Container& )->span< typename Container::value_type >; + + template< typename Container > + span( const Container& )->span< const typename Container::value_type >; + +} // namespace tao + +namespace std +{ +#if defined( __clang__ ) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmismatched-tags" +#endif + + template< typename ElementType, size_t Extent > + struct tuple_size< tao::span< ElementType, Extent > > + : integral_constant< size_t, Extent > + {}; + + template< typename ElementType > + struct tuple_size< tao::span< ElementType, tao::dynamic_extent > >; // not defined + + template< size_t I, typename ElementType, size_t Extent > + struct tuple_element< I, tao::span< ElementType, Extent > > + { + static_assert( ( Extent != tao::dynamic_extent ) && ( I < Extent ) ); + using type = ElementType; + }; + +#if defined( __clang__ ) +#pragma clang diagnostic pop +#endif + + // TODO: this is probably illegal. keep it? + template< size_t I, typename ElementType, size_t Extent > + constexpr ElementType& get( tao::span< ElementType, Extent > s ) noexcept + { + static_assert( ( Extent != tao::dynamic_extent ) && ( I < Extent ) ); + return s[ I ]; + } + +} // namespace std + +#endif + +#endif diff --git a/include/tao/json/stream.hpp b/include/tao/json/stream.hpp index 493f06ef..13fda705 100644 --- a/include/tao/json/stream.hpp +++ b/include/tao/json/stream.hpp @@ -1,39 +1,38 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_STREAM_HPP -#define TAOCPP_JSON_INCLUDE_STREAM_HPP +#ifndef TAO_JSON_STREAM_HPP +#define TAO_JSON_STREAM_HPP #include #include +#include #include "to_stream.hpp" #include "value.hpp" -namespace tao -{ - namespace json - { - // Use ostream << std::setw( n ) for pretty-printing with indent n. +#include "internal/format.hpp" - template< template< typename... > class Traits > - std::ostream& operator<<( std::ostream& o, const basic_value< Traits >& v ) - { - const auto w = o.width(); - - o.width( 0 ); +namespace tao::json +{ + // Use ostream << std::setw( n ) for pretty-printing with indent n. - if( w > 0 ) { - json::to_stream( o, v, w ); - } - else { - json::to_stream( o, v ); + template< template< typename... > class Traits > + std::ostream& operator<<( std::ostream& o, const basic_value< Traits >& v ) + { + const auto w = o.width( 0 ); + if( w > 0 ) { + if( w >= 256 ) { + throw std::runtime_error( internal::format( "indentation ", w, " larger than 255" ) ); } - return o; + json::to_stream( o, v, static_cast< std::size_t >( w ) ); } + else { + json::to_stream( o, v ); + } + return o; + } - } // namespace json - -} // namespace tao +} // namespace tao::json #endif diff --git a/include/tao/json/to_stream.hpp b/include/tao/json/to_stream.hpp index 3255635f..62b2dae5 100644 --- a/include/tao/json/to_stream.hpp +++ b/include/tao/json/to_stream.hpp @@ -1,11 +1,12 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_TO_STREAM_HPP -#define TAOCPP_JSON_INCLUDE_TO_STREAM_HPP +#ifndef TAO_JSON_TO_STREAM_HPP +#define TAO_JSON_TO_STREAM_HPP #include #include +#include #include "events/from_value.hpp" #include "events/to_pretty_stream.hpp" @@ -13,26 +14,29 @@ #include "events/transformer.hpp" #include "value.hpp" -namespace tao +namespace tao::json { - namespace json + template< template< typename... > class... Transformers, template< typename... > class Traits > + void to_stream( std::ostream& os, const basic_value< Traits >& v ) { - template< template< typename... > class... Transformers, template< typename... > class Traits > - void to_stream( std::ostream& os, const basic_value< Traits >& v ) - { - events::transformer< events::to_stream, Transformers... > consumer( os ); - events::from_value( consumer, v ); - } - - template< template< typename... > class... Transformers, template< typename... > class Traits > - void to_stream( std::ostream& os, const basic_value< Traits >& v, const std::size_t indent ) - { - events::transformer< events::to_pretty_stream, Transformers... > consumer( os, indent ); - events::from_value( consumer, v ); - } - - } // namespace json - -} // namespace tao + events::transformer< events::to_stream, Transformers... > consumer( os ); + events::from_value( consumer, v ); + } + + template< template< typename... > class... Transformers, template< typename... > class Traits > + void to_stream( std::ostream& os, const basic_value< Traits >& v, const std::size_t indent ) + { + events::transformer< events::to_pretty_stream, Transformers... > consumer( os, indent ); + events::from_value( consumer, v ); + } + + template< template< typename... > class... Transformers, template< typename... > class Traits, typename S > + void to_stream( std::ostream& os, const basic_value< Traits >& v, const std::size_t indent, S&& eol ) + { + events::transformer< events::to_pretty_stream, Transformers... > consumer( os, indent, std::forward< S >( eol ) ); + events::from_value( consumer, v ); + } + +} // namespace tao::json #endif diff --git a/include/tao/json/to_string.hpp b/include/tao/json/to_string.hpp index 3d4e123d..9dd8f5cf 100644 --- a/include/tao/json/to_string.hpp +++ b/include/tao/json/to_string.hpp @@ -1,27 +1,23 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_TO_STRING_HPP -#define TAOCPP_JSON_INCLUDE_TO_STRING_HPP +#ifndef TAO_JSON_TO_STRING_HPP +#define TAO_JSON_TO_STRING_HPP #include #include "to_stream.hpp" -namespace tao +namespace tao::json { - namespace json + template< template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] std::string to_string( Ts&&... ts ) { - template< template< typename... > class... Transformers, typename... Ts > - std::string to_string( Ts&&... ts ) - { - std::ostringstream o; - json::to_stream< Transformers... >( o, std::forward< Ts >( ts )... ); - return o.str(); - } + std::ostringstream o; + json::to_stream< Transformers... >( o, std::forward< Ts >( ts )... ); + return o.str(); + } - } // namespace json - -} // namespace tao +} // namespace tao::json #endif diff --git a/include/tao/json/traits.hpp b/include/tao/json/traits.hpp index b7492d7a..b19d6bb8 100644 --- a/include/tao/json/traits.hpp +++ b/include/tao/json/traits.hpp @@ -1,1091 +1,971 @@ -// Copyright (c) 2016-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_TRAITS_HPP -#define TAOCPP_JSON_INCLUDE_TRAITS_HPP +#ifndef TAO_JSON_TRAITS_HPP +#define TAO_JSON_TRAITS_HPP +#include #include +#include +#include #include +#include #include +#include #include -#include "byte_view.hpp" +#include "binary_view.hpp" +#include "consume.hpp" +#include "forward.hpp" #include "type.hpp" -#include "internal/throw.hpp" +#include "events/from_value.hpp" +#include "events/produce.hpp" -#include "external/byte.hpp" -#include "external/optional.hpp" -#include "external/string_view.hpp" +#include "internal/format.hpp" +#include "internal/identity.hpp" +#include "internal/number_traits.hpp" +#include "internal/string_t.hpp" +#include "internal/type_traits.hpp" -namespace tao +#include "external/pegtl/internal/pegtl_string.hpp" + +#define TAO_JSON_DEFAULT_KEY( x ) \ + template< template< typename... > class Traits > \ + using default_key = TAO_JSON_STRING_T( x ) + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4702 ) +#endif + +namespace tao::json { - namespace json + namespace internal { - template< template< typename... > class Traits > - class basic_value; + struct empty_base + {}; - // note: traits< ... >::assign() is always called with needs_discard(v) == false + } // namespace internal - template< typename T, typename = void > - struct traits; + // Traits< void > is special and configures the basic_value class template + template<> + struct traits< void > + { + static constexpr bool enable_implicit_constructor = true; - template<> - struct traits< null_t > - { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, null_t ) noexcept - { - v.unsafe_assign_null(); - } + template< typename > + using public_base = internal::empty_base; + }; - template< template< typename... > class Traits > - static bool equal( const basic_value< Traits >& lhs, null_t ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - return p->is_null(); - } - else { - return true; - } - } + template<> + struct traits< uninitialized_t > + { + static constexpr bool enable_implicit_constructor = true; - template< template< typename... > class Traits > - static bool less_than( const basic_value< Traits >& lhs, null_t ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - return p->type() < type::NULL_; - } - else { - return false; - } - } + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& /*unused*/, uninitialized_t /*unused*/ ) noexcept + {} - template< template< typename... > class Traits > - static bool greater_than( const basic_value< Traits >& lhs, null_t ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - return p->type() > type::NULL_; - } - else { - return false; - } - } - }; + template< template< typename... > class Traits > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, uninitialized_t /*unused*/ ) noexcept + { + return lhs.skip_value_ptr().is_uninitialized(); + } - template<> - struct traits< bool > + template< template< typename... > class Traits > + [[nodiscard]] static bool less_than( const basic_value< Traits >& /*unused*/, uninitialized_t /*unused*/ ) noexcept { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const bool b ) noexcept - { - v.unsafe_assign_bool( b ); - } + return false; // Because std::underlying_type_t< tao::json::type > is unsigned and type::uninitialized is 0. + } - template< template< typename... > class Traits > - static void extract( const basic_value< Traits >& v, bool& b ) - { - b = v.get_boolean(); - } + template< template< typename... > class Traits > + [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, uninitialized_t /*unused*/ ) noexcept + { + return lhs.skip_value_ptr().type() > type::UNINITIALIZED; + } + }; - template< template< typename... > class Traits > - static bool equal( const basic_value< Traits >& lhs, const bool rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - return p->is_boolean() && ( p->unsafe_get_boolean() == rhs ); - } - else { - return false; - } - } + template<> + struct traits< null_t > + { + static constexpr bool enable_implicit_constructor = true; - template< template< typename... > class Traits > - static bool less_than( const basic_value< Traits >& lhs, const bool rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - return ( p->type() < type::BOOLEAN ) || ( p->is_boolean() && ( p->unsafe_get_boolean() < rhs ) ); - } - else { - return type::NULL_ < type::BOOLEAN; - } - } + template< template< typename... > class Traits > + [[nodiscard]] static null_t as( const basic_value< Traits >& v ) + { + return v.get_null(); + } - template< template< typename... > class Traits > - static bool greater_than( const basic_value< Traits >& lhs, const bool rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - return ( p->type() > type::BOOLEAN ) || ( p->is_boolean() && ( p->unsafe_get_boolean() > rhs ) ); - } - else { - return type::NULL_ > type::BOOLEAN; - } - } - }; - - namespace internal - { - template< typename T > - struct number_trait - { - template< template< typename... > class Traits > - static void extract( const basic_value< Traits >& v, T& i ) - { - switch( v.type() ) { - case type::SIGNED: - i = v.unsafe_get_signed(); - break; - case type::UNSIGNED: - i = v.unsafe_get_unsigned(); - break; - case type::DOUBLE: - i = v.unsafe_get_double(); - break; - default: - TAOCPP_JSON_THROW_TYPE_ERROR( v.type() ); - } - } - }; - - template< typename T > - struct signed_trait - : number_trait< T > - { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const T i ) noexcept - { - v.unsafe_assign_signed( i ); - } + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, null_t /*unused*/ ) noexcept + { + v.set_null(); + } - template< template< typename... > class Traits > - static bool equal( const basic_value< Traits >& lhs, const T rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::SIGNED: - return p->unsafe_get_signed() == rhs; - case type::UNSIGNED: - return ( rhs >= 0 ) && ( p->unsafe_get_unsigned() == static_cast< std::uint64_t >( rhs ) ); - case type::DOUBLE: - return p->unsafe_get_double() == rhs; - default: - return false; - } - } - else { - return false; - } - } + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, const null_t /*unused*/ ) + { + c.null(); + } - template< template< typename... > class Traits > - static bool less_than( const basic_value< Traits >& lhs, const T rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::SIGNED: - return p->unsafe_get_signed() < rhs; - case type::UNSIGNED: - return ( rhs >= 0 ) && ( p->unsafe_get_unsigned() < static_cast< std::uint64_t >( rhs ) ); - case type::DOUBLE: - return p->unsafe_get_double() < rhs; - default: - return p->type() < type::SIGNED; - } - } - else { - return type::NULL_ < type::SIGNED; - } - } + template< template< typename... > class Traits > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, null_t /*unused*/ ) noexcept + { + return lhs.skip_value_ptr().is_null(); + } - template< template< typename... > class Traits > - static bool greater_than( const basic_value< Traits >& lhs, const T rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::SIGNED: - return p->unsafe_get_signed() > rhs; - case type::UNSIGNED: - return ( rhs < 0 ) || ( p->unsafe_get_unsigned() > static_cast< std::uint64_t >( rhs ) ); - case type::DOUBLE: - return p->unsafe_get_double() > rhs; - default: - return p->type() > type::SIGNED; - } - } - else { - return type::NULL_ > type::SIGNED; - } - } - }; - - template< typename T > - struct unsigned_trait - : number_trait< T > - { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const T i ) noexcept - { - v.unsafe_assign_unsigned( i ); - } + template< template< typename... > class Traits > + [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, null_t /*unused*/ ) noexcept + { + return lhs.skip_value_ptr().type() < type::NULL_; + } - template< template< typename... > class Traits > - static bool equal( const basic_value< Traits >& lhs, const T rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::SIGNED: { - const auto v = p->unsafe_get_signed(); - return ( v >= 0 ) && ( static_cast< std::uint64_t >( v ) == rhs ); - } - case type::UNSIGNED: - return p->unsafe_get_unsigned() == rhs; - case type::DOUBLE: - return p->unsafe_get_double() == rhs; - default: - return false; - } - } - else { - return false; - } - } + template< template< typename... > class Traits > + [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, null_t /*unused*/ ) noexcept + { + return lhs.skip_value_ptr().type() > type::NULL_; + } + }; - template< template< typename... > class Traits > - static bool less_than( const basic_value< Traits >& lhs, const T rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::SIGNED: { - const auto v = p->unsafe_get_signed(); - return ( v < 0 ) || ( static_cast< std::uint64_t >( v ) < rhs ); - } - case type::UNSIGNED: - return p->unsafe_get_unsigned() < rhs; - case type::DOUBLE: - return p->unsafe_get_double() < rhs; - default: - return p->type() < type::UNSIGNED; - } - } - else { - return type::NULL_ < type::UNSIGNED; - } - } + template<> + struct traits< bool > + { + template< template< typename... > class Traits > + [[nodiscard]] static bool as( const basic_value< Traits >& v ) + { + return v.get_boolean(); + } - template< template< typename... > class Traits > - static bool greater_than( const basic_value< Traits >& lhs, const T rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::SIGNED: { - const auto v = p->unsafe_get_signed(); - return ( v >= 0 ) && ( static_cast< std::uint64_t >( v ) > rhs ); - } - case type::UNSIGNED: - return p->unsafe_get_unsigned() > rhs; - case type::DOUBLE: - return p->unsafe_get_double() > rhs; - default: - return p->type() > type::UNSIGNED; - } - } - else { - return type::NULL_ > type::UNSIGNED; - } - } - }; - - template< typename T > - struct float_trait - : number_trait< T > - { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const T f ) noexcept - { - v.unsafe_assign_double( f ); - } + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const bool b ) noexcept + { + v.set_boolean( b ); + } - template< template< typename... > class Traits > - static bool equal( const basic_value< Traits >& lhs, const T rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::SIGNED: - return p->unsafe_get_signed() == rhs; - case type::UNSIGNED: - return p->unsafe_get_unsigned() == rhs; - case type::DOUBLE: - return p->unsafe_get_double() == rhs; - default: - return false; - } - } - else { - return false; - } - } + template< template< typename... > class, typename Producer > + [[nodiscard]] static bool consume( Producer& parser ) + { + return parser.boolean(); + } - template< template< typename... > class Traits > - static bool less_than( const basic_value< Traits >& lhs, const T rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::SIGNED: - return p->unsafe_get_signed() < rhs; - case type::UNSIGNED: - return p->unsafe_get_unsigned() < rhs; - case type::DOUBLE: - return p->unsafe_get_double() < rhs; - default: - return p->type() < type::DOUBLE; - } - } - else { - return type::NULL_ < type::DOUBLE; - } - } + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, const bool b ) + { + c.boolean( b ); + } - template< template< typename... > class Traits > - static bool greater_than( const basic_value< Traits >& lhs, const T rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::SIGNED: - return p->unsafe_get_signed() > rhs; - case type::UNSIGNED: - return p->unsafe_get_unsigned() > rhs; - case type::DOUBLE: - return p->unsafe_get_double() > rhs; - default: - return p->type() > type::DOUBLE; - } - } - else { - return type::NULL_ > type::DOUBLE; - } - } - }; + template< template< typename... > class Traits > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const bool rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + return p.is_boolean() && ( p.get_boolean() == rhs ); } - // clang-format off - template<> struct traits< signed char > : internal::signed_trait< signed char > {}; - template<> struct traits< signed short > : internal::signed_trait< signed short > {}; - template<> struct traits< signed int > : internal::signed_trait< signed int > {}; - template<> struct traits< signed long > : internal::signed_trait< signed long > {}; - template<> struct traits< signed long long > : internal::signed_trait< signed long long > {}; + template< template< typename... > class Traits > + [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const bool rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + return ( p.type() < type::BOOLEAN ) || ( p.is_boolean() && ( p.get_boolean() < rhs ) ); + } - template<> struct traits< unsigned char > : internal::unsigned_trait< unsigned char > {}; - template<> struct traits< unsigned short > : internal::unsigned_trait< unsigned short > {}; - template<> struct traits< unsigned int > : internal::unsigned_trait< unsigned int > {}; - template<> struct traits< unsigned long > : internal::unsigned_trait< unsigned long > {}; - template<> struct traits< unsigned long long > : internal::unsigned_trait< unsigned long long > {}; + template< template< typename... > class Traits > + [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const bool rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + return ( p.type() > type::BOOLEAN ) || ( p.is_boolean() && ( p.get_boolean() > rhs ) ); + } + }; + + // clang-format off + template<> struct traits< signed char > : internal::signed_trait< signed char > {}; + template<> struct traits< signed short > : internal::signed_trait< signed short > {}; + template<> struct traits< signed int > : internal::signed_trait< signed int > {}; + template<> struct traits< signed long > : internal::signed_trait< signed long > {}; + template<> struct traits< signed long long > : internal::signed_trait< signed long long > {}; + + template<> struct traits< unsigned char > : internal::unsigned_trait< unsigned char > {}; + template<> struct traits< unsigned short > : internal::unsigned_trait< unsigned short > {}; + template<> struct traits< unsigned int > : internal::unsigned_trait< unsigned int > {}; + template<> struct traits< unsigned long > : internal::unsigned_trait< unsigned long > {}; + template<> struct traits< unsigned long long > : internal::unsigned_trait< unsigned long long > {}; + + template<> struct traits< float > : internal::float_trait< float > {}; + template<> struct traits< double > : internal::float_trait< double > {}; + // clang-format on + + template<> + struct traits< empty_string_t > + { + static constexpr bool enable_implicit_constructor = true; - template<> struct traits< float > : internal::float_trait< float > {}; - template<> struct traits< double > : internal::float_trait< double > {}; - // clang-format on + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, empty_string_t /*unused*/ ) noexcept + { + v.emplace_string(); + } - template<> - struct traits< empty_binary_t > + template< template< typename... > class Traits > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, empty_string_t /*unused*/ ) noexcept { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, empty_binary_t ) noexcept - { - v.unsafe_emplace_binary(); + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::STRING: + return p.get_string().empty(); + case type::STRING_VIEW: + return p.get_string_view().empty(); + default: + return false; } + } - template< template< typename... > class Traits > - static bool equal( const basic_value< Traits >& lhs, empty_binary_t ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::BINARY: - return p->unsafe_get_binary().empty(); - case type::BINARY_VIEW: - return p->unsafe_get_binary_view().empty(); - default: - return false; - } - } - else { + template< template< typename... > class Traits > + [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, empty_string_t /*unused*/ ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::STRING: + case type::STRING_VIEW: return false; - } + default: + return p.type() < type::STRING; } + } - template< template< typename... > class Traits > - static bool less_than( const basic_value< Traits >& lhs, empty_binary_t ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::BINARY: - case type::BINARY_VIEW: - return false; - default: - return p->type() < type::BINARY; - } - } - else { - return type::NULL_ < type::BINARY; - } + template< template< typename... > class Traits > + [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, empty_string_t /*unused*/ ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::STRING: + return !p.get_string().empty(); + case type::STRING_VIEW: + return !p.get_string_view().empty(); + default: + return p.type() > type::STRING; } + } + }; - template< template< typename... > class Traits > - static bool greater_than( const basic_value< Traits >& lhs, empty_binary_t ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::BINARY: - return !p->unsafe_get_binary().empty(); - case type::BINARY_VIEW: - return !p->unsafe_get_binary_view().empty(); - default: - return p->type() > type::BINARY; - } - } - else { - return type::NULL_ > type::BINARY; - } - } - }; + template<> + struct traits< empty_binary_t > + { + static constexpr bool enable_implicit_constructor = true; - template<> - struct traits< empty_array_t > + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, empty_binary_t /*unused*/ ) noexcept { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, empty_array_t ) noexcept - { - v.unsafe_emplace_array(); - } + v.emplace_binary(); + } - template< template< typename... > class Traits > - static bool equal( const basic_value< Traits >& lhs, empty_array_t ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - return p->is_array() && p->unsafe_get_array().empty(); - } - else { + template< template< typename... > class Traits > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, empty_binary_t /*unused*/ ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::BINARY: + return p.get_binary().empty(); + case type::BINARY_VIEW: + return p.get_binary_view().empty(); + default: return false; - } } + } - template< template< typename... > class Traits > - static bool less_than( const basic_value< Traits >& lhs, empty_array_t ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - return p->type() < type::ARRAY; - } - else { - return type::NULL_ < type::ARRAY; - } + template< template< typename... > class Traits > + [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, empty_binary_t /*unused*/ ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::BINARY: + case type::BINARY_VIEW: + return false; + default: + return p.type() < type::BINARY; } + } - template< template< typename... > class Traits > - static bool greater_than( const basic_value< Traits >& lhs, empty_array_t ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - return ( p->type() > type::ARRAY ) || ( p->is_array() && !p->unsafe_get_array().empty() ); - } - else { - return type::NULL_ > type::ARRAY; - } + template< template< typename... > class Traits > + [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, empty_binary_t /*unused*/ ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::BINARY: + return !p.get_binary().empty(); + case type::BINARY_VIEW: + return !p.get_binary_view().empty(); + default: + return p.type() > type::BINARY; } - }; + } + }; - template<> - struct traits< empty_object_t > + template<> + struct traits< empty_array_t > + { + static constexpr bool enable_implicit_constructor = true; + + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, empty_array_t /*unused*/ ) noexcept { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, empty_object_t ) noexcept - { - v.unsafe_emplace_object(); - } + v.emplace_array(); + } - template< template< typename... > class Traits > - static bool equal( const basic_value< Traits >& lhs, empty_object_t ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - return p->is_object() && p->unsafe_get_object().empty(); - } - else { - return false; - } - } + template< template< typename... > class Traits > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, empty_array_t /*unused*/ ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + return p.is_array() && p.get_array().empty(); + } - template< template< typename... > class Traits > - static bool less_than( const basic_value< Traits >& lhs, empty_object_t ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - return p->type() < type::OBJECT; - } - else { - return type::NULL_ < type::OBJECT; - } - } + template< template< typename... > class Traits > + [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, empty_array_t /*unused*/ ) noexcept + { + return lhs.skip_value_ptr().type() < type::ARRAY; + } - template< template< typename... > class Traits > - static bool greater_than( const basic_value< Traits >& lhs, empty_object_t ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - return ( p->type() > type::OBJECT ) || ( p->is_object() && !p->unsafe_get_object().empty() ); - } - else { - return type::NULL_ > type::OBJECT; - } - } - }; + template< template< typename... > class Traits > + [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, empty_array_t /*unused*/ ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + return ( p.type() > type::ARRAY ) || ( p.is_array() && !p.get_array().empty() ); + } + }; + + template<> + struct traits< empty_object_t > + { + static constexpr bool enable_implicit_constructor = true; - template<> - struct traits< std::string > + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, empty_object_t /*unused*/ ) noexcept { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const std::string& s ) - { - v.unsafe_assign_string( s ); - } + v.emplace_object(); + } - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, std::string&& s ) noexcept - { - v.unsafe_assign_string( std::move( s ) ); - } + template< template< typename... > class Traits > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, empty_object_t /*unused*/ ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + return p.is_object() && p.get_object().empty(); + } - template< template< typename... > class Traits > - static void extract( const basic_value< Traits >& v, std::string& s ) - { - switch( v.type() ) { - case type::STRING: - s = v.unsafe_get_string(); - break; - case type::STRING_VIEW: { - const auto sv = v.unsafe_get_string_view(); - s.assign( sv.data(), sv.size() ); - break; - } - default: - TAOCPP_JSON_THROW_TYPE_ERROR( v.type() ); - } - } + template< template< typename... > class Traits > + [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, empty_object_t /*unused*/ ) noexcept + { + return lhs.skip_value_ptr().type() < type::OBJECT; + } - template< template< typename... > class Traits > - static bool equal( const basic_value< Traits >& lhs, const std::string& rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::STRING: - return p->unsafe_get_string() == rhs; - case type::STRING_VIEW: - return p->unsafe_get_string_view() == rhs; - default: - return false; - } - } - else { - return false; - } - } + template< template< typename... > class Traits > + [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, empty_object_t /*unused*/ ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + return ( p.type() > type::OBJECT ) || ( p.is_object() && !p.get_object().empty() ); + } + }; - template< template< typename... > class Traits > - static bool less_than( const basic_value< Traits >& lhs, const std::string& rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::STRING: - return p->unsafe_get_string() < rhs; - case type::STRING_VIEW: - return p->unsafe_get_string_view() < rhs; - default: - return p->type() < type::STRING; - } - } - else { - return type::NULL_ < type::STRING; - } + template<> + struct traits< std::string > + { + template< template< typename... > class Traits > + [[nodiscard]] static std::string as( const basic_value< Traits >& v ) + { + switch( v.type() ) { + case type::STRING: + return v.get_string(); + case type::STRING_VIEW: + return std::string( v.get_string_view() ); + default: + throw std::logic_error( internal::format( "invalid json type '", v.type(), "' for conversion to std::string", json::message_extension( v ) ) ); } + } - template< template< typename... > class Traits > - static bool greater_than( const basic_value< Traits >& lhs, const std::string& rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::STRING: - return p->unsafe_get_string() > rhs; - case type::STRING_VIEW: - return p->unsafe_get_string_view() > rhs; - default: - return p->type() > type::STRING; - } - } - else { - return type::NULL_ > type::STRING; - } - } - }; + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const std::string& s ) + { + v.set_string( s ); + } - template<> - struct traits< tao::string_view > + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, std::string&& s ) noexcept { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const tao::string_view sv ) - { - v.unsafe_emplace_string( sv.data(), sv.size() ); - } + v.set_string( std::move( s ) ); + } - template< template< typename... > class Traits > - static tao::string_view as( const basic_value< Traits >& v ) - { - switch( v.type() ) { - case type::STRING: - return v.unsafe_get_string(); - case type::STRING_VIEW: - return v.unsafe_get_string_view(); - default: - TAOCPP_JSON_THROW_TYPE_ERROR( v.type() ); - } - } + template< template< typename... > class, typename Producer > + [[nodiscard]] static std::string consume( Producer& parser ) + { + return parser.string(); + } - template< template< typename... > class Traits > - static bool equal( const basic_value< Traits >& lhs, const tao::string_view rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::STRING: - return p->unsafe_get_string() == rhs; - case type::STRING_VIEW: - return p->unsafe_get_string_view() == rhs; - default: - return false; - } - } - else { + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, const std::string& s ) + { + c.string( s ); + } + + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, std::string&& s ) + { + c.string( std::move( s ) ); + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const std::string& rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::STRING: + return p.get_string() == rhs; + case type::STRING_VIEW: + return p.get_string_view() == rhs; + default: return false; - } } + } - template< template< typename... > class Traits > - static bool less_than( const basic_value< Traits >& lhs, const tao::string_view rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::STRING: - return p->unsafe_get_string() < rhs; - case type::STRING_VIEW: - return p->unsafe_get_string_view() < rhs; - default: - return p->type() < type::STRING; - } - } - else { - return type::NULL_ < type::STRING; - } + template< template< typename... > class Traits > + [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const std::string& rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::STRING: + return p.get_string() < rhs; + case type::STRING_VIEW: + return p.get_string_view() < rhs; + default: + return p.type() < type::STRING; } + } - template< template< typename... > class Traits > - static bool greater_than( const basic_value< Traits >& lhs, const tao::string_view rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::STRING: - return p->unsafe_get_string() > rhs; - case type::STRING_VIEW: - return p->unsafe_get_string_view() > rhs; - default: - return p->type() > type::STRING; - } - } - else { - return type::NULL_ > type::STRING; - } + template< template< typename... > class Traits > + [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const std::string& rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::STRING: + return p.get_string() > rhs; + case type::STRING_VIEW: + return p.get_string_view() > rhs; + default: + return p.type() > type::STRING; } - }; + } + }; - template<> - struct traits< const char* > + template<> + struct traits< std::string_view > + { + template< template< typename... > class Traits > + [[nodiscard]] static std::string_view as( const basic_value< Traits >& v ) { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const char* s ) - { - v.unsafe_emplace_string( s ); + switch( v.type() ) { + case type::STRING: + return v.get_string(); + case type::STRING_VIEW: + return v.get_string_view(); + default: + throw std::logic_error( internal::format( "invalid json type '", v.type(), "' for conversion to std::string_view", json::message_extension( v ) ) ); } + } - template< template< typename... > class Traits > - static const char* as( const basic_value< Traits >& v ) - { - return v.get_string().c_str(); - } + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const std::string_view sv ) + { + v.emplace_string( sv ); + } - template< template< typename... > class Traits > - static bool equal( const basic_value< Traits >& lhs, const char* rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::STRING: - return p->unsafe_get_string() == rhs; - case type::STRING_VIEW: - return p->unsafe_get_string_view() == rhs; - default: - return false; - } - } - else { + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, const std::string_view sv ) + { + c.string( sv ); + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const std::string_view rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::STRING: + return p.get_string() == rhs; + case type::STRING_VIEW: + return p.get_string_view() == rhs; + default: return false; - } } + } - template< template< typename... > class Traits > - static bool less_than( const basic_value< Traits >& lhs, const char* rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::STRING: - return p->unsafe_get_string() < rhs; - case type::STRING_VIEW: - return p->unsafe_get_string_view() < rhs; - default: - return p->type() < type::STRING; - } - } - else { - return type::NULL_ < type::STRING; - } + template< template< typename... > class Traits > + [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const std::string_view rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::STRING: + return p.get_string() < rhs; + case type::STRING_VIEW: + return p.get_string_view() < rhs; + default: + return p.type() < type::STRING; } + } - template< template< typename... > class Traits > - static bool greater_than( const basic_value< Traits >& lhs, const char* rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::STRING: - return p->unsafe_get_string() > rhs; - case type::STRING_VIEW: - return p->unsafe_get_string_view() > rhs; - default: - return p->type() > type::STRING; - } - } - else { - return type::NULL_ > type::STRING; - } + template< template< typename... > class Traits > + [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const std::string_view rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::STRING: + return p.get_string() > rhs; + case type::STRING_VIEW: + return p.get_string_view() > rhs; + default: + return p.type() > type::STRING; } - }; + } + }; - template<> - struct traits< const std::string& > + template<> + struct traits< const char* > + { + template< template< typename... > class Traits > + [[nodiscard]] static const char* as( const basic_value< Traits >& v ) { - template< template< typename... > class Traits > - static const std::string& as( const basic_value< Traits >& v ) - { - return v.get_string(); - } - }; + return v.get_string().c_str(); // String views might not be '\0'-terminated. + } - template<> - struct traits< std::vector< tao::byte > > + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const char* s ) { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const std::vector< tao::byte >& x ) - { - v.unsafe_assign_binary( x ); - } + v.emplace_string( s ); + } - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, std::vector< tao::byte >&& x ) noexcept - { - v.unsafe_assign_binary( std::move( x ) ); + template< template< typename... > class Traits > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const char* rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::STRING: + return p.get_string() == rhs; + case type::STRING_VIEW: + return p.get_string_view() == rhs; + default: + return false; } + } - template< template< typename... > class Traits > - static void extract( const basic_value< Traits >& v, std::vector< tao::byte >& x ) - { - switch( v.type() ) { - case type::BINARY: - x = v.unsafe_get_binary(); - break; - case type::BINARY_VIEW: { - const auto xv = v.unsafe_get_binary_view(); - x.assign( xv.begin(), xv.end() ); - break; - } - default: - TAOCPP_JSON_THROW_TYPE_ERROR( v.type() ); - } + template< template< typename... > class Traits > + [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const char* rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::STRING: + return p.get_string() < rhs; + case type::STRING_VIEW: + return p.get_string_view() < rhs; + default: + return p.type() < type::STRING; } + } - template< template< typename... > class Traits > - static bool equal( const basic_value< Traits >& lhs, const std::vector< tao::byte >& rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::BINARY: - return p->unsafe_get_binary() == rhs; - case type::BINARY_VIEW: - return p->unsafe_get_binary_view() == rhs; - default: - return false; - } - } - else { - return false; - } + template< template< typename... > class Traits > + [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const char* rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::STRING: + return p.get_string() > rhs; + case type::STRING_VIEW: + return p.get_string_view() > rhs; + default: + return p.type() > type::STRING; } + } + }; - template< template< typename... > class Traits > - static bool less_than( const basic_value< Traits >& lhs, const std::vector< tao::byte >& rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::BINARY: - return p->unsafe_get_binary() < rhs; - case type::BINARY_VIEW: - return p->unsafe_get_binary_view() < rhs; - default: - return p->type() < type::BINARY; - } - } - else { - return type::NULL_ < type::BINARY; - } - } + template<> + struct traits< const std::string& > + { + template< template< typename... > class Traits > + [[nodiscard]] static const std::string& as( const basic_value< Traits >& v ) + { + return v.get_string(); + } + }; - template< template< typename... > class Traits > - static bool greater_than( const basic_value< Traits >& lhs, const std::vector< tao::byte >& rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::BINARY: - return p->unsafe_get_binary() > rhs; - case type::BINARY_VIEW: - return p->unsafe_get_binary_view() > rhs; - default: - return p->type() > type::BINARY; - } - } - else { - return type::NULL_ > type::BINARY; + template<> + struct traits< std::vector< std::byte > > + { + template< template< typename... > class Traits > + [[nodiscard]] static std::vector< std::byte > as( const basic_value< Traits >& v ) + { + switch( v.type() ) { + case type::BINARY: + return v.get_binary(); + case type::BINARY_VIEW: { + const auto xv = v.get_binary_view(); + return std::vector< std::byte >( xv.begin(), xv.end() ); } + default: + throw std::logic_error( internal::format( "invalid json type '", v.type(), "' for conversion to std::vector< std::byte >", json::message_extension( v ) ) ); } - }; + } + + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const std::vector< std::byte >& x ) + { + v.set_binary( x ); + } - template<> - struct traits< tao::byte_view > + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, std::vector< std::byte >&& x ) noexcept { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const tao::byte_view xv ) noexcept - { - v.unsafe_emplace_binary( xv.begin(), xv.end() ); - } + v.set_binary( std::move( x ) ); + } - template< template< typename... > class Traits > - static tao::byte_view as( const basic_value< Traits >& v ) - { - switch( v.type() ) { - case type::BINARY: - return v.unsafe_get_binary(); - case type::BINARY_VIEW: - return v.unsafe_get_binary_view(); - default: - TAOCPP_JSON_THROW_TYPE_ERROR( v.type() ); - } - } + template< template< typename... > class, typename Producer > + [[nodiscard]] static std::vector< std::byte > consume( Producer& parser ) + { + return parser.binary(); + } - template< template< typename... > class Traits > - static bool equal( const basic_value< Traits >& lhs, const tao::byte_view rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::BINARY: - return p->unsafe_get_binary() == rhs; - case type::BINARY_VIEW: - return p->unsafe_get_binary_view() == rhs; - default: - return false; - } - } - else { + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, const std::vector< std::byte >& x ) + { + c.binary( x ); + } + + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, std::vector< std::byte >&& x ) + { + c.binary( std::move( x ) ); + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const std::vector< std::byte >& rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::BINARY: + return p.get_binary() == rhs; + case type::BINARY_VIEW: + return tao::internal::binary_equal( p.get_binary_view(), rhs ); + default: return false; - } } + } - template< template< typename... > class Traits > - static bool less_than( const basic_value< Traits >& lhs, const tao::byte_view rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::BINARY: - return p->unsafe_get_binary() < rhs; - case type::BINARY_VIEW: - return p->unsafe_get_binary_view() < rhs; - default: - return p->type() < type::BINARY; - } - } - else { - return type::NULL_ < type::BINARY; - } + template< template< typename... > class Traits > + [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const std::vector< std::byte >& rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::BINARY: + return p.get_binary() < rhs; + case type::BINARY_VIEW: + return tao::internal::binary_less( p.get_binary_view(), rhs ); + default: + return p.type() < type::BINARY; } + } - template< template< typename... > class Traits > - static bool greater_than( const basic_value< Traits >& lhs, const tao::byte_view rhs ) noexcept - { - if( const auto* p = lhs.skip_raw_ptr() ) { - switch( p->type() ) { - case type::BINARY: - return p->unsafe_get_binary() > rhs; - case type::BINARY_VIEW: - return p->unsafe_get_binary_view() > rhs; - default: - return p->type() > type::BINARY; - } - } - else { - return type::NULL_ > type::BINARY; - } + template< template< typename... > class Traits > + [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const std::vector< std::byte >& rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::BINARY: + return p.get_binary() > rhs; + case type::BINARY_VIEW: + return tao::internal::binary_less( rhs, p.get_binary_view() ); + default: + return p.type() > type::BINARY; } - }; + } + }; - template<> - struct traits< const std::vector< tao::byte >& > + template<> + struct traits< tao::binary_view > + { + template< template< typename... > class Traits > + [[nodiscard]] static tao::binary_view as( const basic_value< Traits >& v ) { - template< template< typename... > class Traits > - static const std::vector< tao::byte >& as( const basic_value< Traits >& v ) - { - return v.get_binary(); + switch( v.type() ) { + case type::BINARY: + return v.get_binary(); + case type::BINARY_VIEW: + return v.get_binary_view(); + default: + throw std::logic_error( internal::format( "invalid json type '", v.type(), "' for conversion to tao::binary_view", json::message_extension( v ) ) ); } - }; + } template< template< typename... > class Traits > - struct traits< std::vector< basic_value< Traits > > > + static void assign( basic_value< Traits >& v, const tao::binary_view xv ) { - static void assign( basic_value< Traits >& v, const std::vector< basic_value< Traits > >& a ) - { - v.unsafe_assign_array( a ); - } + v.emplace_binary( xv.begin(), xv.end() ); + } - static void assign( basic_value< Traits >& v, std::vector< basic_value< Traits > >&& a ) noexcept - { - v.unsafe_assign_array( std::move( a ) ); + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, const tao::binary_view xv ) + { + c.binary( xv ); + } + + template< template< typename... > class Traits > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const tao::binary_view rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::BINARY: + return tao::internal::binary_equal( p.get_binary(), rhs ); + case type::BINARY_VIEW: + return tao::internal::binary_equal( p.get_binary_view(), rhs ); + default: + return false; } - }; + } template< template< typename... > class Traits > - struct traits< std::map< std::string, basic_value< Traits > > > + [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const tao::binary_view rhs ) noexcept { - static void assign( basic_value< Traits >& v, const std::map< std::string, basic_value< Traits > >& o ) - { - v.unsafe_assign_object( std::move( o ) ); + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::BINARY: + return tao::internal::binary_less( p.get_binary(), rhs ); + case type::BINARY_VIEW: + return tao::internal::binary_less( p.get_binary_view(), rhs ); + default: + return p.type() < type::BINARY; } + } - static void assign( basic_value< Traits >& v, std::map< std::string, basic_value< Traits > >&& o ) noexcept - { - v.unsafe_assign_object( std::move( o ) ); + template< template< typename... > class Traits > + [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const tao::binary_view rhs ) noexcept + { + const auto& p = lhs.skip_value_ptr(); + switch( p.type() ) { + case type::BINARY: + return tao::internal::binary_less( rhs, p.get_binary() ); + case type::BINARY_VIEW: + return tao::internal::binary_less( rhs, p.get_binary_view() ); + default: + return p.type() > type::BINARY; } - }; + } + }; + template<> + struct traits< const std::vector< std::byte >& > + { template< template< typename... > class Traits > - struct traits< const basic_value< Traits >* > + [[nodiscard]] static const std::vector< std::byte >& as( const basic_value< Traits >& v ) + { + return v.get_binary(); + } + }; + + template< template< typename... > class Traits > + struct traits< basic_value< Traits > > + { + template< template< typename... > class, typename Consumer > + static void produce( Consumer& c, const basic_value< Traits >& v ) { - static void assign( basic_value< Traits >& v, const basic_value< Traits >* p ) noexcept - { - v.unsafe_assign_raw_ptr( p ); + events::from_value( c, v ); + } + + template< template< typename... > class, typename Consumer > + static void produce( Consumer& c, basic_value< Traits >&& v ) + { + events::from_value( c, std::move( v ) ); + } + }; + + template< template< typename... > class Traits > + struct traits< std::vector< basic_value< Traits > > > + { + static void assign( basic_value< Traits >& v, const std::vector< basic_value< Traits > >& a ) + { + v.set_array( a ); + } + + static void assign( basic_value< Traits >& v, std::vector< basic_value< Traits > >&& a ) noexcept + { + v.set_array( std::move( a ) ); + } + + template< template< typename... > class, typename Consumer > + static void produce( Consumer& c, const std::vector< basic_value< Traits > >& a ) + { + c.begin_array( a.size() ); + for( const auto& i : a ) { + Traits< basic_value< Traits > >::produce( c, i ); + c.element(); } + c.end_array( a.size() ); + } - template< template< typename... > class TraitsL > - static bool equal( const basic_value< TraitsL >& lhs, const basic_value< Traits >* rhs ) noexcept - { - return rhs ? ( lhs == *rhs ) : ( lhs == null ); + template< template< typename... > class, typename Consumer > + static void produce( Consumer& c, std::vector< basic_value< Traits > >&& a ) + { + c.begin_array( a.size() ); + for( auto&& i : a ) { + Traits< basic_value< Traits > >::produce( c, std::move( i ) ); + c.element(); } + c.end_array( a.size() ); + } + }; + + template< template< typename... > class Traits > + struct traits< std::map< std::string, basic_value< Traits >, std::less<> > > + { + static void assign( basic_value< Traits >& v, const std::map< std::string, basic_value< Traits >, std::less<> >& o ) + { + v.set_object( std::move( o ) ); + } + + static void assign( basic_value< Traits >& v, std::map< std::string, basic_value< Traits >, std::less<> >&& o ) noexcept + { + v.set_object( std::move( o ) ); + } - template< template< typename... > class TraitsL > - static bool less_than( const basic_value< TraitsL >& lhs, const basic_value< Traits >* rhs ) noexcept - { - return rhs ? ( lhs < *rhs ) : ( lhs < null ); + template< template< typename... > class, typename Consumer > + static void produce( Consumer& c, const std::map< std::string, basic_value< Traits >, std::less<> >& o ) + { + c.begin_object( o.size() ); + for( const auto& i : o ) { + c.key( i.first ); + Traits< basic_value< Traits > >::produce( c, i.second ); + c.member(); } + c.end_object( o.size() ); + } - template< template< typename... > class TraitsL > - static bool greater_than( const basic_value< TraitsL >& lhs, const basic_value< Traits >* rhs ) noexcept - { - return rhs ? ( lhs > *rhs ) : ( lhs > null ); + template< template< typename... > class, typename Consumer > + static void produce( Consumer& c, std::map< std::string, basic_value< Traits >, std::less<> >&& o ) + { + c.begin_object( o.size() ); + for( auto&& i : o ) { + c.key( std::move( i.first ) ); + Traits< basic_value< Traits > >::produce( c, std::move( i.second ) ); + c.member(); } - }; + c.end_object( o.size() ); + } + }; + + template< template< typename... > class Traits > + struct traits< const basic_value< Traits >* > + { + static void assign( basic_value< Traits >& v, const basic_value< Traits >* p ) noexcept + { + v.set_value_ptr( p ); + } + + template< template< typename... > class TraitsLL > + [[nodiscard]] static bool equal( const basic_value< TraitsLL >& lhs, const basic_value< Traits >* rhs ) noexcept + { + assert( rhs ); + return lhs == *rhs; + } + + template< template< typename... > class TraitsLL > + [[nodiscard]] static bool less_than( const basic_value< TraitsLL >& lhs, const basic_value< Traits >* rhs ) noexcept + { + assert( rhs ); + return lhs < *rhs; + } + + template< template< typename... > class TraitsLL > + [[nodiscard]] static bool greater_than( const basic_value< TraitsLL >& lhs, const basic_value< Traits >* rhs ) noexcept + { + assert( rhs ); + return lhs > *rhs; + } + }; + + template< template< typename... > class Traits > + struct traits< basic_value< Traits >* > + : traits< const basic_value< Traits >* > + { + }; + + template< typename T > + struct traits< std::optional< T > > + { + template< template< typename... > class Traits > + using default_key = typename Traits< T >::template default_key< Traits >; template< template< typename... > class Traits > - struct traits< basic_value< Traits >* > - : traits< const basic_value< Traits >* > + [[nodiscard]] static bool is_nothing( const std::optional< T >& o ) { - }; + return ( !bool( o ) ) || internal::is_nothing< Traits >( *o ); // TODO: Only query o? + } - template<> - struct traits< std::nullptr_t > + template< template< typename... > class Traits > + [[nodiscard]] static std::optional< T > as( const basic_value< Traits >& v ) { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, std::nullptr_t ) noexcept - { - v.unsafe_assign_raw_ptr( nullptr ); + if( v == null ) { + return std::nullopt; } + return v.template as< T >(); + } - template< template< typename... > class Traits > - static bool equal( const basic_value< Traits >& lhs, std::nullptr_t ) noexcept - { - return lhs == null; + template< template< typename... > class Traits > + static void assign( basic_value< Traits >& v, const std::optional< T >& o ) + { + if( o ) { + v.assign( *o ); } - - template< template< typename... > class Traits > - static bool less_than( const basic_value< Traits >& lhs, std::nullptr_t ) noexcept - { - return lhs < null; + else { + v.set_null(); } + } - template< template< typename... > class Traits > - static bool greater_than( const basic_value< Traits >& lhs, std::nullptr_t ) noexcept - { - return lhs > null; + template< template< typename... > class Traits, typename Producer > + [[nodiscard]] static std::optional< T > consume( Producer& parser ) + { + if( parser.null() ) { + return std::nullopt; } - }; + return json::consume< T, Traits >( parser ); + } - template< typename T > - struct traits< tao::optional< T > > + template< template< typename... > class Traits, typename Consumer > + static void produce( Consumer& c, const std::optional< T >& o ) { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const tao::optional< T >& o ) - { - if( o ) { - v = *o; - } - else { - v.unsafe_assign_null(); - } + if( o ) { + json::events::produce< Traits >( c, *o ); } - - template< template< typename... > class Traits > - static void extract( const basic_value< Traits >& v, tao::optional< T >& o ) - { - if( v.is_null() ) { - o = tao::nullopt; - } - else { - o = v.template as< T >(); - } + else { + json::events::produce< Traits >( c, null ); } + } - template< template< typename... > class Traits > - static bool equal( const basic_value< Traits >& lhs, const tao::optional< T >& rhs ) noexcept - { - return rhs ? ( lhs == *rhs ) : ( lhs == null ); - } + template< template< typename... > class Traits > + [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const std::optional< T >& rhs ) noexcept + { + return rhs ? ( lhs == *rhs ) : ( lhs == null ); + } - template< template< typename... > class Traits > - static bool less_than( const basic_value< Traits >& lhs, const tao::optional< T >& rhs ) noexcept - { - return rhs ? ( lhs < *rhs ) : ( lhs < null ); - } + template< template< typename... > class Traits > + [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const std::optional< T >& rhs ) noexcept + { + return rhs ? ( lhs < *rhs ) : ( lhs < null ); + } - template< template< typename... > class Traits > - static bool greater_than( const basic_value< Traits >& lhs, const tao::optional< T >& rhs ) noexcept - { - return rhs ? ( lhs > *rhs ) : ( lhs > null ); - } - }; + template< template< typename... > class Traits > + [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const std::optional< T >& rhs ) noexcept + { + return rhs ? ( lhs > *rhs ) : ( lhs > null ); + } + }; - } // namespace json +} // namespace tao::json -} // namespace tao +#ifdef _MSC_VER +#pragma warning( pop ) +#endif #endif diff --git a/include/tao/json/type.hpp b/include/tao/json/type.hpp index 98998d14..bb25d29c 100644 --- a/include/tao/json/type.hpp +++ b/include/tao/json/type.hpp @@ -1,121 +1,112 @@ -// Copyright (c) 2015-2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_TYPE_HPP -#define TAOCPP_JSON_INCLUDE_TYPE_HPP +#ifndef TAO_JSON_TYPE_HPP +#define TAO_JSON_TYPE_HPP #include +#include +#include +#include -namespace tao +#include "binary_view.hpp" + +namespace tao::json { - namespace json + enum class type : std::size_t { - enum class type : std::uint8_t - { - UNINITIALIZED, - DISCARDED, - DESTROYED, - NULL_, - BOOLEAN, - SIGNED, - UNSIGNED, - DOUBLE, - STRING, - STRING_VIEW, - BINARY, - BINARY_VIEW, - ARRAY, - OBJECT, - RAW_PTR - }; - - inline bool needs_discard( const type t ) - { - switch( t ) { - case type::STRING: - case type::STRING_VIEW: - case type::BINARY: - case type::BINARY_VIEW: - case type::ARRAY: - case type::OBJECT: - return true; - default: - return false; - } - } + UNINITIALIZED = 0, + NULL_, + BOOLEAN, + SIGNED, + UNSIGNED, + DOUBLE, + STRING, + STRING_VIEW, + BINARY, + BINARY_VIEW, + ARRAY, + OBJECT, + VALUE_PTR, + OPAQUE_PTR, + + VALUELESS_BY_EXCEPTION = std::variant_npos + }; - inline const char* to_string( const type t ) - { - switch( t ) { - case type::UNINITIALIZED: - return "uninitialized"; - case type::DISCARDED: - return "discarded"; - case type::DESTROYED: - return "destroyed"; - case type::NULL_: - return "null"; - case type::BOOLEAN: - return "boolean"; - case type::SIGNED: - return "signed"; - case type::UNSIGNED: - return "unsigned"; - case type::DOUBLE: - return "double"; - case type::STRING: - return "string"; - case type::STRING_VIEW: - return "string_view"; - case type::BINARY: - return "binary"; - case type::BINARY_VIEW: - return "binary_view"; - case type::ARRAY: - return "array"; - case type::OBJECT: - return "object"; - case type::RAW_PTR: - return "raw_ptr"; - } - return "unknown"; + constexpr std::string_view to_string( const type t ) + { + switch( t ) { + case type::UNINITIALIZED: + return "uninitialized"; + case type::NULL_: + return "null"; + case type::BOOLEAN: + return "boolean"; + case type::SIGNED: + return "signed"; + case type::UNSIGNED: + return "unsigned"; + case type::DOUBLE: + return "double"; + case type::STRING: + return "string"; + case type::STRING_VIEW: + return "string_view"; + case type::BINARY: + return "binary"; + case type::BINARY_VIEW: + return "binary_view"; + case type::ARRAY: + return "array"; + case type::OBJECT: + return "object"; + case type::VALUE_PTR: + return "value_ptr"; + case type::OPAQUE_PTR: + return "opaque_ptr"; + case type::VALUELESS_BY_EXCEPTION: + return "valueless_by_exception"; } + return "unknown"; + } + + struct null_t + { + explicit constexpr null_t( int /*unused*/ ) {} + }; + + struct empty_string_t + { + explicit constexpr empty_string_t( int /*unused*/ ) {} + }; + + struct empty_binary_t + { + explicit constexpr empty_binary_t( int /*unused*/ ) {} + }; + + struct empty_array_t + { + explicit constexpr empty_array_t( int /*unused*/ ) {} + }; + + struct empty_object_t + { + constexpr explicit empty_object_t( int /*unused*/ ) {} + }; + + struct uninitialized_t + {}; + + constexpr null_t null{ 0 }; + + constexpr empty_string_t empty_string{ 0 }; + constexpr empty_binary_t empty_binary{ 0 }; + constexpr empty_array_t empty_array{ 0 }; + constexpr empty_object_t empty_object{ 0 }; + + constexpr uninitialized_t uninitialized; - struct null_t - { - constexpr explicit null_t( int ) - { - } - }; - - struct empty_binary_t - { - constexpr explicit empty_binary_t( int ) - { - } - }; - - struct empty_array_t - { - constexpr explicit empty_array_t( int ) - { - } - }; - - struct empty_object_t - { - constexpr explicit empty_object_t( int ) - { - } - }; - - constexpr null_t null{ 0 }; - constexpr empty_binary_t empty_binary{ 0 }; - constexpr empty_array_t empty_array{ 0 }; - constexpr empty_object_t empty_object{ 0 }; - - } // namespace json - -} // namespace tao +} // namespace tao::json #endif diff --git a/include/tao/json/ubjson.hpp b/include/tao/json/ubjson.hpp index 89df4793..bce51858 100644 --- a/include/tao/json/ubjson.hpp +++ b/include/tao/json/ubjson.hpp @@ -1,12 +1,17 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_UBJSON_HPP -#define TAOCPP_JSON_INCLUDE_UBJSON_HPP +#ifndef TAO_JSON_UBJSON_HPP +#define TAO_JSON_UBJSON_HPP #include "../json.hpp" +#include "ubjson/consume_file.hpp" +#include "ubjson/consume_string.hpp" +#include "ubjson/from_file.hpp" +#include "ubjson/from_input.hpp" #include "ubjson/from_string.hpp" +#include "ubjson/parts_parser.hpp" #include "ubjson/to_stream.hpp" #include "ubjson/to_string.hpp" diff --git a/include/tao/json/ubjson/consume_file.hpp b/include/tao/json/ubjson/consume_file.hpp new file mode 100644 index 00000000..1252222b --- /dev/null +++ b/include/tao/json/ubjson/consume_file.hpp @@ -0,0 +1,34 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_UBJSON_CONSUME_FILE_HPP +#define TAO_JSON_UBJSON_CONSUME_FILE_HPP + +#include + +#include "../external/pegtl/file_input.hpp" + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "parts_parser.hpp" + +namespace tao::json::ubjson +{ + template< typename T, template< typename... > class Traits = traits, typename F > + [[nodiscard]] T consume_file( F&& filename ) + { + ubjson::basic_parts_parser< 1 << 24, utf8_mode::check, pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); + return json::consume< T, Traits >( pp ); + } + + template< template< typename... > class Traits = traits, typename F, typename T > + void consume_file( F&& filename, T& t ) + { + ubjson::basic_parts_parser< 1 << 24, utf8_mode::check, pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); + json::consume< Traits >( pp, t ); + } + +} // namespace tao::json::ubjson + +#endif diff --git a/include/tao/json/ubjson/consume_string.hpp b/include/tao/json/ubjson/consume_string.hpp new file mode 100644 index 00000000..72d1ecdc --- /dev/null +++ b/include/tao/json/ubjson/consume_string.hpp @@ -0,0 +1,32 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_UBJSON_CONSUME_STRING_HPP +#define TAO_JSON_UBJSON_CONSUME_STRING_HPP + +#include "../external/pegtl/string_input.hpp" + +#include "../consume.hpp" +#include "../forward.hpp" + +#include "parts_parser.hpp" + +namespace tao::json::ubjson +{ + template< typename T, template< typename... > class Traits = traits, typename F > + [[nodiscard]] T consume_string( F&& string ) + { + ubjson::basic_parts_parser< 1 << 24, utf8_mode::check, pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); + return json::consume< T, Traits >( pp ); + } + + template< template< typename... > class Traits = traits, typename F, typename T > + void consume_string( F&& string, T& t ) + { + ubjson::basic_parts_parser< 1 << 24, utf8_mode::check, pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); + json::consume< Traits >( pp, t ); + } + +} // namespace tao::json::ubjson + +#endif diff --git a/include/tao/json/ubjson/events/from_file.hpp b/include/tao/json/ubjson/events/from_file.hpp new file mode 100644 index 00000000..580e4a63 --- /dev/null +++ b/include/tao/json/ubjson/events/from_file.hpp @@ -0,0 +1,27 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_UBJSON_EVENTS_FROM_FILE_HPP +#define TAO_JSON_UBJSON_EVENTS_FROM_FILE_HPP + +#include + +#include "../../external/pegtl/file_input.hpp" +#include "../../external/pegtl/parse.hpp" + +#include "../internal/grammar.hpp" + +namespace tao::json::ubjson::events +{ + // Events producer to parse a file containing a UBJSON string representation. + + template< typename T, typename Consumer > + void from_file( Consumer& consumer, T&& filename ) + { + pegtl::file_input< pegtl::tracking_mode::lazy > in( std::forward< T >( filename ) ); + pegtl::parse< internal::grammar >( in, consumer ); + } + +} // namespace tao::json::ubjson::events + +#endif diff --git a/include/tao/json/ubjson/events/from_input.hpp b/include/tao/json/ubjson/events/from_input.hpp new file mode 100644 index 00000000..3fa4ac3f --- /dev/null +++ b/include/tao/json/ubjson/events/from_input.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_UBJSON_EVENTS_FROM_INPUT_HPP +#define TAO_JSON_UBJSON_EVENTS_FROM_INPUT_HPP + +#include + +#include "../../external/pegtl/parse.hpp" + +#include "../internal/grammar.hpp" + +namespace tao::json::ubjson::events +{ + // Events producers that parse UBJSON from a PEGTL input (or something compatible). + + template< typename Consumer, typename Input > + void from_input( Consumer& consumer, Input&& in ) + { + pegtl::parse< ubjson::internal::grammar >( std::forward< Input >( in ), consumer ); + } + + template< typename Consumer, typename Input > + void from_input_embedded( Consumer& consumer, Input&& in ) + { + pegtl::parse< ubjson::internal::embedded >( std::forward< Input >( in ), consumer ); + } + + template< typename Consumer, typename Outer, typename Input > + void from_input_nested( Consumer& consumer, const Outer& oi, Input&& in ) + { + pegtl::parse_nested< ubjson::internal::grammar >( oi, std::forward< Input >( in ), consumer ); + } + + template< typename Consumer, typename Outer, typename Input > + void from_input_embedded_nested( Consumer& consumer, const Outer& oi, Input&& in ) + { + pegtl::parse_nested< ubjson::internal::embedded >( oi, std::forward< Input >( in ), consumer ); + } + +} // namespace tao::json::ubjson::events + +#endif diff --git a/include/tao/json/ubjson/events/from_string.hpp b/include/tao/json/ubjson/events/from_string.hpp new file mode 100644 index 00000000..de605b76 --- /dev/null +++ b/include/tao/json/ubjson/events/from_string.hpp @@ -0,0 +1,37 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_UBJSON_EVENTS_FROM_STRING_HPP +#define TAO_JSON_UBJSON_EVENTS_FROM_STRING_HPP + +#include +#include + +#include "../../external/pegtl/memory_input.hpp" + +#include "from_input.hpp" + +namespace tao::json::ubjson::events +{ + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t byte_in_line = 0 ) + { + pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::ubjson::from_string", byte, line, byte_in_line ); + ubjson::events::from_input( consumer, std::move( in ) ); + } + + template< typename Consumer > + void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) + { + ubjson::events::from_string( consumer, data, size, source.c_str(), byte, line, column ); + } + + template< typename Consumer, typename... Ts > + void from_string( Consumer& consumer, const std::string_view data, Ts&&... ts ) + { + ubjson::events::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); + } + +} // namespace tao::json::ubjson::events + +#endif diff --git a/include/tao/json/ubjson/events/to_stream.hpp b/include/tao/json/ubjson/events/to_stream.hpp new file mode 100644 index 00000000..4bc32c3c --- /dev/null +++ b/include/tao/json/ubjson/events/to_stream.hpp @@ -0,0 +1,174 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_UBJSON_EVENTS_TO_STREAM_HPP +#define TAO_JSON_UBJSON_EVENTS_TO_STREAM_HPP + +#include +#include +#include +#include +#include + +#include "../../binary_view.hpp" + +#include "../../internal/endian.hpp" + +namespace tao::json::ubjson::events +{ + class to_stream + { + private: + std::ostream& os; + + public: + explicit to_stream( std::ostream& in_os ) noexcept + : os( in_os ) + {} + + void null() + { + os.put( 'Z' ); + } + + void boolean( const bool v ) + { + os.put( v ? 'T' : 'F' ); + } + + void number( const std::int64_t v ) + { + if( ( v >= -128 ) && ( v <= 127 ) ) { + os.put( 'i' ); + const auto x = static_cast< std::int8_t >( v ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else if( ( v >= -32768 ) && ( v <= 32767 ) ) { + os.put( 'I' ); + const std::uint16_t x = json::internal::h_to_be( std::uint16_t( v ) ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else if( ( v >= -2147483648LL ) && ( v <= 2147483647LL ) ) { + os.put( 'l' ); + const std::uint32_t x = json::internal::h_to_be( std::uint32_t( v ) ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else { + os.put( 'L' ); + const std::uint64_t x = json::internal::h_to_be( std::uint64_t( v ) ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + } + + void number( const std::uint64_t v ) + { + if( v <= 255 ) { + os.put( 'U' ); + const auto x = static_cast< std::uint8_t >( v ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else if( v <= 32767 ) { + os.put( 'I' ); + const std::uint16_t x = json::internal::h_to_be( std::uint16_t( v ) ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else if( v <= 2147483647UL ) { + os.put( 'l' ); + const std::uint32_t x = json::internal::h_to_be( std::uint32_t( v ) ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else if( v <= 9223372036854775807ULL ) { + os.put( 'L' ); + const std::uint64_t x = json::internal::h_to_be( v ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + else { + os.put( 'H' ); + os.put( 'U' ); + os.put( char( 19 ) + char( v >= 10000000000000000000ULL ) ); + os << v; + } + } + + void number( const double v ) + { + os.put( 'D' ); + const double x = json::internal::h_to_be( v ); + os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); + } + + void string( const std::string_view v ) + { + if( ( v.size() == 1 ) && ( ( v[ 0 ] & 0x80 ) == 0 ) ) { + os.put( 'C' ); + os.put( v[ 0 ] ); + } + else { + os.put( 'S' ); + number( std::uint64_t( v.size() ) ); + os.write( v.data(), v.size() ); + } + } + + void binary( const tao::binary_view v ) + { + // NOTE: UBJSON encodes binary data as 'strongly typed array of uint8 values'. + os.write( "[$U#", 4 ); + number( std::uint64_t( v.size() ) ); + os.write( reinterpret_cast< const char* >( v.data() ), v.size() ); + } + + void begin_array() + { + os.put( '[' ); + } + + void begin_array( const std::size_t size ) + { + os.write( "[#", 2 ); + number( std::uint64_t( size ) ); + } + + void element() noexcept + {} + + void end_array() + { + os.put( ']' ); + } + + void end_array( const std::size_t /*unused*/ ) noexcept + {} + + void begin_object() + { + os.put( '{' ); + } + + void begin_object( const std::size_t size ) + { + os.write( "{#", 2 ); + number( std::uint64_t( size ) ); + } + + void key( const std::string_view v ) + { + number( std::uint64_t( v.size() ) ); + os.write( v.data(), v.size() ); + } + + void member() noexcept + {} + + void end_object() + { + os.put( '}' ); + } + + void end_object( const std::size_t /*unused*/ ) noexcept + {} + }; + +} // namespace tao::json::ubjson::events + +#endif diff --git a/include/tao/json/ubjson/events/to_string.hpp b/include/tao/json/ubjson/events/to_string.hpp new file mode 100644 index 00000000..fbd8bbd6 --- /dev/null +++ b/include/tao/json/ubjson/events/to_string.hpp @@ -0,0 +1,31 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_UBJSON_EVENTS_TO_STRING_HPP +#define TAO_JSON_UBJSON_EVENTS_TO_STRING_HPP + +#include +#include + +#include "to_stream.hpp" + +namespace tao::json::ubjson::events +{ + struct to_string + : to_stream + { + std::ostringstream oss; + + to_string() + : to_stream( oss ) + {} + + [[nodiscard]] std::string value() const + { + return oss.str(); + } + }; + +} // namespace tao::json::ubjson::events + +#endif diff --git a/include/tao/json/ubjson/from_file.hpp b/include/tao/json/ubjson/from_file.hpp new file mode 100644 index 00000000..2f26c939 --- /dev/null +++ b/include/tao/json/ubjson/from_file.hpp @@ -0,0 +1,33 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_UBJSON_FROM_FILE_HPP +#define TAO_JSON_UBJSON_FROM_FILE_HPP + +#include +#include + +#include "../events/to_value.hpp" +#include "../events/transformer.hpp" + +#include "events/from_file.hpp" + +namespace tao::json::ubjson +{ + template< template< typename... > class Traits, template< typename... > class... Transformers > + [[nodiscard]] basic_value< Traits > basic_from_file( const std::string& filename ) + { + json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; + events::from_file( consumer, filename ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers > + [[nodiscard]] value from_file( const std::string& filename ) + { + return basic_from_file< traits, Transformers... >( filename ); + } + +} // namespace tao::json::ubjson + +#endif diff --git a/include/tao/json/ubjson/from_input.hpp b/include/tao/json/ubjson/from_input.hpp new file mode 100644 index 00000000..9d798007 --- /dev/null +++ b/include/tao/json/ubjson/from_input.hpp @@ -0,0 +1,33 @@ +// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_UBJSON_FROM_INPUT_HPP +#define TAO_JSON_UBJSON_FROM_INPUT_HPP + +#include +#include + +#include "../events/to_value.hpp" +#include "../events/transformer.hpp" + +#include "events/from_input.hpp" + +namespace tao::json::ubjson +{ + template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] basic_value< Traits > basic_from_input( Ts&&... ts ) + { + json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; + ubjson::events::from_input( consumer, std::forward< Ts >( ts )... ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] value from_input( Ts&&... ts ) + { + return basic_from_input< traits, Transformers... >( std::forward< Ts >( ts )... ); + } + +} // namespace tao::json::ubjson + +#endif diff --git a/include/tao/json/ubjson/from_string.hpp b/include/tao/json/ubjson/from_string.hpp index 49287610..1c415680 100644 --- a/include/tao/json/ubjson/from_string.hpp +++ b/include/tao/json/ubjson/from_string.hpp @@ -1,40 +1,32 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_UBJSON_FROM_STRING_HPP -#define TAOCPP_JSON_INCLUDE_UBJSON_FROM_STRING_HPP +#ifndef TAO_JSON_UBJSON_FROM_STRING_HPP +#define TAO_JSON_UBJSON_FROM_STRING_HPP #include #include "../events/to_value.hpp" #include "../events/transformer.hpp" -#include "../events/ubjson/from_string.hpp" +#include "events/from_string.hpp" -namespace tao +namespace tao::json::ubjson { - namespace json + template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] basic_value< Traits > basic_from_string( Ts&&... ts ) { - namespace ubjson - { - template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > - basic_value< Traits > basic_from_string( Ts&&... ts ) - { - events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; - events::ubjson::from_string( consumer, std::forward< Ts >( ts )... ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers, typename... Ts > - value from_string( Ts&&... ts ) - { - return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); - } - - } // namespace ubjson - - } // namespace json - -} // namespace tao + json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; + events::from_string( consumer, std::forward< Ts >( ts )... ); + return std::move( consumer.value ); + } + + template< template< typename... > class... Transformers, typename... Ts > + [[nodiscard]] value from_string( Ts&&... ts ) + { + return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); + } + +} // namespace tao::json::ubjson #endif diff --git a/include/tao/json/ubjson/internal/grammar.hpp b/include/tao/json/ubjson/internal/grammar.hpp new file mode 100644 index 00000000..5f262fb5 --- /dev/null +++ b/include/tao/json/ubjson/internal/grammar.hpp @@ -0,0 +1,413 @@ +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_UBJSON_INTERNAL_GRAMMAR_HPP +#define TAO_JSON_UBJSON_INTERNAL_GRAMMAR_HPP + +#include +#include + +#include "../../binary_view.hpp" +#include "../../internal/action.hpp" +#include "../../internal/endian.hpp" +#include "../../internal/errors.hpp" +#include "../../internal/grammar.hpp" +#include "../../internal/parse_util.hpp" +#include "../../utf8.hpp" + +#include "marker.hpp" + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4702 ) +#endif + +namespace tao::json +{ + namespace ubjson::internal + { + struct number + { + using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; + + template< pegtl::apply_mode A, + pegtl::rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename Consumer > + [[nodiscard]] static bool match( Input& in, Consumer& consumer ) + { + if( in.size( 2 ) && match_unsafe< A, M, Action, Control >( in, consumer ) ) { + in.discard(); + return true; + } + return false; + } + + private: + template< pegtl::apply_mode A, + pegtl::rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename Consumer > + [[nodiscard]] static bool match_unsafe( Input& in, Consumer& consumer ) + { + if( in.peek_char() == '-' ) { + in.bump_in_this_line(); + if( in.empty() || !json::internal::rules::sor_value::match_number< true, A, pegtl::rewind_mode::dontcare, Action, Control >( in, consumer ) ) { + throw pegtl::parse_error( "incomplete ubjson high-precision number", in ); + } + return true; + } + return json::internal::rules::sor_value::match_number< false, A, M, Action, Control >( in, consumer ); + } + }; + + } // namespace ubjson::internal + + namespace internal + { + // clang-format off + template<> inline const std::string errors< ubjson::internal::number >::error_message = "invalid ubjson high-precision number"; + // clang-format on + + } // namespace internal + + namespace ubjson::internal + { + template< typename Input > + [[nodiscard]] marker peek_marker( Input& in ) + { + return marker( json::internal::peek_char( in ) ); + } + + template< typename Input > + [[nodiscard]] marker read_marker( Input& in ) + { + return marker( json::internal::read_char( in ) ); + } + + template< typename Input > + [[nodiscard]] marker read_marker_unsafe( Input& in ) + { + return marker( json::internal::read_char_unsafe( in ) ); + } + + template< typename Input > + [[nodiscard]] std::int64_t read_size_read( Input& in ) + { + switch( const auto c = read_marker( in ) ) { + case marker::INT8: + return json::internal::read_big_endian_number< std::int64_t, std::int8_t >( in ); + case marker::UINT8: + return json::internal::read_big_endian_number< std::int64_t, std::uint8_t >( in ); + case marker::INT16: + return json::internal::read_big_endian_number< std::int64_t, std::int16_t >( in ); + case marker::INT32: + return json::internal::read_big_endian_number< std::int64_t, std::int32_t >( in ); + case marker::INT64: + return json::internal::read_big_endian_number< std::int64_t >( in ); + default: + throw pegtl::parse_error( "unknown ubjson size type " + std::to_string( unsigned( c ) ), in ); + } + } + + template< std::size_t L, typename Input > + [[nodiscard]] std::size_t read_size( Input& in ) + { + const auto s = read_size_read( in ); + if( s < 0 ) { + throw pegtl::parse_error( "negative ubjson size " + std::to_string( s ), in ); + } + const auto t = static_cast< std::uint64_t >( s ); + if( t > static_cast< std::uint64_t >( L ) ) { + throw pegtl::parse_error( "ubjson size exceeds limit " + std::to_string( t ), in ); + } + return static_cast< std::size_t >( t ); + } + + template< typename Result, typename Input > + [[nodiscard]] Result read_char( Input& in ) + { + if( in.empty() || ( in.peek_uint8( 0 ) > 127 ) ) { + throw pegtl::parse_error( "missing or invalid ubjson char", in ); + } + Result result( in.current(), 1 ); + in.bump_in_this_line( 1 ); + return result; + } + + template< std::size_t L, utf8_mode U, typename Result, typename Input > + [[nodiscard]] Result read_string( Input& in ) + { + const auto size = read_size< L >( in ); + return json::internal::read_string< U, Result >( in, size ); + } + + template< std::size_t L, utf8_mode V > + struct data + { + using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; + + template< pegtl::apply_mode A, + pegtl::rewind_mode M, + template< typename... > + class Action, + template< typename... > + class Control, + typename Input, + typename Consumer > + [[nodiscard]] static bool match( Input& in, Consumer& consumer ) + { + if( !in.empty() ) { + parse_unsafe( in, consumer ); + return true; + } + return false; + } + + private: + template< typename Input, typename Consumer > + static void parse( Input& in, Consumer& consumer ) + { + parse( in, consumer, read_marker( in ) ); + } + + template< typename Input, typename Consumer > + static void parse_unsafe( Input& in, Consumer& consumer ) + { + parse( in, consumer, read_marker_unsafe( in ) ); + } + + template< typename Input, typename Consumer > + static void parse( Input& in, Consumer& consumer, const marker c ) + { + switch( c ) { + case marker::NULL_: + consumer.null(); + break; + case marker::TRUE_: + consumer.boolean( true ); + break; + case marker::FALSE_: + consumer.boolean( false ); + break; + case marker::INT8: + consumer.number( json::internal::read_big_endian_number< std::int64_t, std::int8_t >( in ) ); + break; + case marker::UINT8: + consumer.number( json::internal::read_big_endian_number< std::uint64_t, std::uint8_t >( in ) ); + break; + case marker::INT16: + consumer.number( json::internal::read_big_endian_number< std::int64_t, std::int16_t >( in ) ); + break; + case marker::INT32: + consumer.number( json::internal::read_big_endian_number< std::int64_t, std::int32_t >( in ) ); + break; + case marker::INT64: + consumer.number( json::internal::read_big_endian_number< std::int64_t >( in ) ); + break; + case marker::FLOAT32: + consumer.number( json::internal::read_big_endian_number< double, float >( in ) ); + break; + case marker::FLOAT64: + consumer.number( json::internal::read_big_endian_number< double >( in ) ); + break; + case marker::HIGH_PRECISION: + parse_high_precision( in, consumer ); + break; + case marker::CHAR: + consumer.string( read_char< std::string_view >( in ) ); + break; + case marker::STRING: + consumer.string( read_string< L, V, std::string_view >( in ) ); + break; + case marker::BEGIN_ARRAY: + parse_array( in, consumer ); + break; + case marker::BEGIN_OBJECT: + parse_object( in, consumer ); + break; + case marker::NO_OP: + throw pegtl::parse_error( "unsupported ubjson no-op", in ); + default: + throw pegtl::parse_error( "unknown ubjson type " + std::to_string( unsigned( c ) ), in ); + } + } + + template< typename Input, typename Consumer > + static void parse_high_precision( Input& in, Consumer& consumer ) + { + const auto size = read_size< L >( in ); + json::internal::throw_on_empty( in, size ); + pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > i2( in.current(), in.current() + size, "UBJSON" ); + pegtl::parse_nested< pegtl::must< number, pegtl::eof >, json::internal::action, json::internal::errors >( in, i2, consumer ); + in.bump_in_this_line( size ); + } + + template< typename Input, typename Consumer > + static void parse_array( Input& in, Consumer& consumer ) + { + switch( peek_marker( in ) ) { + case marker::CONTAINER_SIZE: + in.bump_in_this_line( 1 ); + parse_sized_array( in, consumer ); + break; + case marker::CONTAINER_TYPE: + in.bump_in_this_line( 1 ); + parse_typed_array( in, consumer ); + break; + default: + parse_basic_array( in, consumer ); + break; + } + } + + template< typename Input, typename Consumer > + static void parse_sized_array( Input& in, Consumer& consumer ) + { + const auto size = read_size< L >( in ); + consumer.begin_array( size ); + for( std::size_t i = 0; i < size; ++i ) { + parse( in, consumer ); + consumer.element(); + } + consumer.end_array( size ); + } + + template< typename Input, typename Consumer > + static void parse_typed_array( Input& in, Consumer& consumer ) + { + const auto c = read_marker( in ); + if( read_marker( in ) != marker::CONTAINER_SIZE ) { + throw pegtl::parse_error( "ubjson array type not followed by size", in ); + } + if( c == marker::UINT8 ) { + // NOTE: UBJSON encodes binary data as 'strongly typed array of uint8 values'. + consumer.binary( read_string< L, utf8_mode::trust, tao::binary_view >( in ) ); + return; + } + const auto size = read_size< L >( in ); + consumer.begin_array( size ); + for( std::size_t i = 0; i < size; ++i ) { + parse( in, consumer, c ); + consumer.element(); + } + consumer.end_array( size ); + } + + template< typename Input, typename Consumer > + static void parse_basic_array( Input& in, Consumer& consumer ) + { + consumer.begin_array(); + while( peek_marker( in ) != marker::END_ARRAY ) { + parse_unsafe( in, consumer ); + consumer.element(); + } + in.bump_in_this_line( 1 ); + consumer.end_array(); + } + + template< typename Input, typename Consumer > + static void parse_key( Input& in, Consumer& consumer ) + { + consumer.key( read_string< L, V, std::string_view >( in ) ); + } + + template< typename Input, typename Consumer > + static void parse_object( Input& in, Consumer& consumer ) + { + switch( peek_marker( in ) ) { + case marker::CONTAINER_SIZE: + in.bump_in_this_line( 1 ); + parse_sized_object( in, consumer ); + break; + case marker::CONTAINER_TYPE: + in.bump_in_this_line( 1 ); + parse_typed_object( in, consumer ); + break; + default: + parse_basic_object( in, consumer ); + break; + } + } + + template< typename Input, typename Consumer > + static void parse_sized_object( Input& in, Consumer& consumer ) + { + const auto size = read_size< L >( in ); + consumer.begin_object( size ); + for( std::size_t i = 0; i < size; ++i ) { + parse_key( in, consumer ); + parse( in, consumer ); + consumer.member(); + } + consumer.end_object( size ); + } + + template< typename Input, typename Consumer > + static void parse_typed_object( Input& in, Consumer& consumer ) + { + const auto c = read_marker( in ); + if( read_marker( in ) != marker::CONTAINER_SIZE ) { + throw pegtl::parse_error( "ubjson object type not followed by size", in ); + } + const auto size = read_size< L >( in ); + consumer.begin_object( size ); + for( std::size_t i = 0; i < size; ++i ) { + parse_key( in, consumer ); + parse( in, consumer, c ); + consumer.member(); + } + consumer.end_object( size ); + } + + template< typename Input, typename Consumer > + static void parse_basic_object( Input& in, Consumer& consumer ) + { + consumer.begin_object(); + while( peek_marker( in ) != marker::END_OBJECT ) { + parse_key( in, consumer ); + parse( in, consumer ); + consumer.member(); + } + in.bump_in_this_line( 1 ); + consumer.end_object(); + } + }; + + struct nops + : pegtl::star< pegtl::one< char( marker::NO_OP ) > > + { + }; + + template< std::size_t L, utf8_mode V > + struct basic_grammar + : pegtl::must< nops, data< L, V >, nops, pegtl::eof > + { + }; + + template< std::size_t L, utf8_mode V > + struct basic_embedded + : pegtl::must< data< L, V > > + { + }; + + using grammar = basic_grammar< 1 << 24, utf8_mode::check >; + using embedded = basic_embedded< 1 << 24, utf8_mode::check >; + + } // namespace ubjson::internal + +} // namespace tao::json + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + +#endif diff --git a/include/tao/json/ubjson/internal/marker.hpp b/include/tao/json/ubjson/internal/marker.hpp new file mode 100644 index 00000000..3b6d242b --- /dev/null +++ b/include/tao/json/ubjson/internal/marker.hpp @@ -0,0 +1,46 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_UBJSON_INTERNAL_MARKER_HPP +#define TAO_JSON_UBJSON_INTERNAL_MARKER_HPP + +#include + +namespace tao::json::ubjson::internal +{ + enum class marker : char + { + NULL_ = 'Z', + + NO_OP = 'N', + + TRUE_ = 'T', + FALSE_ = 'F', + + INT8 = 'i', + UINT8 = 'U', + INT16 = 'I', + INT32 = 'l', + INT64 = 'L', + + FLOAT32 = 'd', + FLOAT64 = 'D', + + HIGH_PRECISION = 'H', + + CHAR = 'C', + STRING = 'S', + + BEGIN_ARRAY = '[', + END_ARRAY = ']', + + BEGIN_OBJECT = '{', + END_OBJECT = '}', + + CONTAINER_SIZE = '#', + CONTAINER_TYPE = '$' + }; + +} // namespace tao::json::ubjson::internal + +#endif diff --git a/include/tao/json/ubjson/parts_parser.hpp b/include/tao/json/ubjson/parts_parser.hpp new file mode 100644 index 00000000..4f53ce08 --- /dev/null +++ b/include/tao/json/ubjson/parts_parser.hpp @@ -0,0 +1,393 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_UBJSON_PARTS_PARSER_HPP +#define TAO_JSON_UBJSON_PARTS_PARSER_HPP + +#include +#include + +#include "../events/discard.hpp" +#include "../external/pegtl/string_input.hpp" +#include "../utf8.hpp" + +#include "internal/grammar.hpp" + +namespace tao::json::ubjson +{ + namespace internal + { + template< typename Input > + [[nodiscard]] bool read_boolean( Input& in ) + { + const auto b = peek_marker( in ); + switch( b ) { + case marker::TRUE_: + in.bump_in_this_line( 1 ); + return true; + case marker::FALSE_: + in.bump_in_this_line( 1 ); + return false; + default: + throw pegtl::parse_error( "expected boolean", in ); + } + std::abort(); + } + + template< typename Input > + [[nodiscard]] std::int64_t read_signed( Input& in ) + { + const auto b = peek_marker( in ); + switch( format( b ) ) { + case marker::INT8: + return json::internal::read_big_endian_number< std::int64_t, std::int8_t >( in, 1 ); + case marker::UINT8: + return json::internal::read_big_endian_number< std::int64_t, std::uint8_t >( in, 1 ); + case marker::INT16: + return json::internal::read_big_endian_number< std::int64_t, std::int16_t >( in, 1 ); + case marker::INT32: + return json::internal::read_big_endian_number< std::int64_t, std::int32_t >( in, 1 ); + case marker::INT64: + return json::internal::read_big_endian_number< std::int64_t >( in, 1 ); + default: + throw pegtl::parse_error( "expected signed number", in ); + } + } + + [[nodiscard]] inline std::uint64_t test_unsigned( const std::int64_t i ) + { + if( i < 0 ) { + throw std::runtime_error( "negative number for unsigned" ); + } + return std::uint64_t( i ); + } + + template< typename Input > + [[nodiscard]] std::uint64_t read_unsigned( Input& in ) + { + const auto b = peek_marker( in ); + switch( b ) { + case marker::INT8: + return test_unsigned( json::internal::read_big_endian_number< std::int64_t, std::int8_t >( in, 1 ) ); + case marker::UINT8: + return json::internal::read_big_endian_number< std::uint64_t, std::uint8_t >( in, 1 ); + case marker::INT16: + return test_unsigned( json::internal::read_big_endian_number< std::int64_t, std::int16_t >( in, 1 ) ); + case marker::INT32: + return test_unsigned( json::internal::read_big_endian_number< std::int64_t, std::int32_t >( in, 1 ) ); + case marker::INT64: + return test_unsigned( json::internal::read_big_endian_number< std::int64_t >( in, 1 ) ); + default: + throw pegtl::parse_error( "expected positive number", in ); + } + } + + template< typename Input > + [[nodiscard]] double read_double( Input& in ) + { + switch( peek_marker( in ) ) { + case marker::FLOAT32: + return json::internal::read_big_endian_number< double, float >( in, 1 ); + case marker::FLOAT64: + return json::internal::read_big_endian_number< double >( in, 1 ); + default: + throw pegtl::parse_error( "expected floating point number", in ); + } + } + + template< utf8_mode V, typename Result, typename Input > + [[nodiscard]] Result read_string_or_char( Input& in ) + { + const auto b = read_marker( in ); + switch( b ) { + case marker::CHAR: + return internal::read_char< Result >( in ); + case marker::STRING: + return internal::read_string< V, Result >( in ); + default: + throw pegtl::parse_error( "expected string (or char)", in ); + } + } + + } // namespace internal + + template< std::size_t L, utf8_mode V = utf8_mode::check, typename Input = pegtl::string_input< pegtl::tracking_mode::lazy > > + class basic_parts_parser + { + public: + template< typename... Ts > + explicit basic_parts_parser( Ts&&... ts ) + : m_input( std::forward< Ts >( ts )... ) + {} + + [[nodiscard]] bool empty() + { + return m_input.empty(); + } + + [[nodiscard]] bool null() + { + if( internal::peek_marker( m_input ) == internal::marker::NULL_ ) { + m_input.bump_in_this_line( 1 ); + return true; + } + return false; + } + + [[nodiscard]] bool boolean() + { + return internal::read_boolean( m_input ); + } + + void check_marker( const internal::marker m, const char* e ) + { + const auto b = internal::peek_marker( m_input ); + if( b != m ) { + throw pegtl::parse_error( e, m_input ); + } + m_input.bump_in_this_line(); + } + + [[nodiscard]] std::string_view string() + { + return internal::read_string_or_char< V, std::string_view >( m_input ); + } + + [[nodiscard]] tao::binary_view binary() + { + check_marker( internal::marker::BEGIN_ARRAY, "expected array for binary" ); + check_marker( internal::marker::CONTAINER_TYPE, "expected typed array for binary" ); + check_marker( internal::marker::UINT8, "expected type uint8 for array for binary" ); + check_marker( internal::marker::CONTAINER_SIZE, "expected sized array for binary" ); + const auto size = internal::read_size< L >( m_input ); + return json::internal::read_string< utf8_mode::trust, tao::binary_view >( m_input, size ); + } + + [[nodiscard]] std::string_view key() + { + return string(); + } + + [[nodiscard]] std::int64_t number_signed() + { + return internal::read_signed( m_input ); + } + + [[nodiscard]] std::uint64_t number_unsigned() + { + return internal::read_unsigned( m_input ); + } + + [[nodiscard]] double number_double() + { + return internal::read_double( m_input ); + } + + struct state_t + { + state_t() = default; + + explicit state_t( const std::size_t in_size ) + : size( in_size ) + {} + + std::size_t i = 0; + std::optional< std::size_t > size; + }; + + template< internal::marker Begin, internal::marker End > + [[nodiscard]] state_t begin_container( const char* e ) + { + check_marker( Begin, e ); + const auto b = internal::peek_marker( m_input ); + switch( b ) { + case End: + return state_t( 0 ); + case internal::marker::CONTAINER_TYPE: + throw pegtl::parse_error( "typed ubjson containers not implemented", m_input ); + case internal::marker::CONTAINER_SIZE: + m_input.bump_in_this_line( 1 ); + return state_t( number_unsigned() ); + default: + return state_t(); + } + } + + [[nodiscard]] state_t begin_array() + { + return begin_container< internal::marker::BEGIN_ARRAY, internal::marker::END_ARRAY >( "expected array" ); + } + + [[nodiscard]] state_t begin_object() + { + return begin_container< internal::marker::BEGIN_OBJECT, internal::marker::END_OBJECT >( "expected object" ); + } + + void end_array_sized( const state_t& p ) + { + if( *p.size != p.i ) { + throw pegtl::parse_error( "array size mismatch", m_input ); + } + } + + void end_object_sized( const state_t& p ) + { + if( *p.size != p.i ) { + throw pegtl::parse_error( "object size mismatch", m_input ); + } + } + + void end_array_indefinite( const state_t& /*unused*/ ) + { + if( internal::peek_marker( m_input ) != internal::marker::END_ARRAY ) { + throw pegtl::parse_error( "array not at end", m_input ); + } + m_input.bump_in_this_line( 1 ); + } + + void end_object_indefinite( const state_t& /*unused*/ ) + { + if( internal::peek_marker( m_input ) != internal::marker::END_OBJECT ) { + throw pegtl::parse_error( "object not at end", m_input ); + } + m_input.bump_in_this_line( 1 ); + } + + void end_array( const state_t& p ) + { + if( p.size ) { + end_array_sized( p ); + } + else { + end_array_indefinite( p ); + } + } + + void end_object( const state_t& p ) + { + if( p.size ) { + end_object_sized( p ); + } + else { + end_object_indefinite( p ); + } + } + + void element_sized( state_t& p ) + { + if( p.i++ >= *p.size ) { + throw pegtl::parse_error( "unexpected array end", m_input ); + } + } + + void member_sized( state_t& p ) + { + if( p.i++ >= *p.size ) { + throw pegtl::parse_error( "unexpected object end", m_input ); + } + } + + void element_indefinite( state_t& /*unused*/ ) + { + if( internal::peek_marker( m_input ) == internal::marker::END_ARRAY ) { + throw pegtl::parse_error( "unexpected array end", m_input ); + } + } + + void member_indefinite( state_t& /*unused*/ ) + { + if( internal::peek_marker( m_input ) == internal::marker::END_OBJECT ) { + throw pegtl::parse_error( "unexpected object end", m_input ); + } + } + + void element( state_t& p ) + { + if( p.size ) { + element_sized( p ); + } + else { + element_indefinite( p ); + } + } + + void member( state_t& p ) + { + if( p.size ) { + member_sized( p ); + } + else { + member_indefinite( p ); + } + } + + [[nodiscard]] bool element_or_end_array_sized( state_t& p ) + { + return p.i++ < *p.size; + } + + [[nodiscard]] bool member_or_end_object_sized( state_t& p ) + { + return p.i++ < *p.size; + } + + [[nodiscard]] bool element_or_end_array_indefinite( const state_t& /*unused*/ ) + { + if( internal::peek_marker( m_input ) == internal::marker::END_ARRAY ) { + m_input.bump_in_this_line( 1 ); + return false; + } + return true; + } + + [[nodiscard]] bool member_or_end_object_indefinite( const state_t& /*unused*/ ) + { + if( internal::peek_marker( m_input ) == internal::marker::END_OBJECT ) { + m_input.bump_in_this_line( 1 ); + return false; + } + return true; + } + + [[nodiscard]] bool element_or_end_array( state_t& p ) + { + if( p.size ) { + return element_or_end_array_sized( p ); + } + return element_or_end_array_indefinite( p ); + } + + [[nodiscard]] bool member_or_end_object( state_t& p ) + { + if( p.size ) { + return member_or_end_object_sized( p ); + } + return member_or_end_object_indefinite( p ); + } + + void skip_value() + { + json::events::discard consumer; // TODO: Optimise to not generate events (which requires preparing their - discarded - arguments)? + pegtl::parse< pegtl::must< internal::data< L, V > > >( m_input, consumer ); + } + + [[nodiscard]] auto mark() + { + return m_input.template mark< pegtl::rewind_mode::required >(); + } + + template< typename T > + void throw_parse_error( T&& t ) const + { + throw pegtl::parse_error( std::forward< T >( t ), m_input ); + } + + protected: + Input m_input; + }; + + using parts_parser = basic_parts_parser< 1 << 24 >; + +} // namespace tao::json::ubjson + +#endif diff --git a/include/tao/json/ubjson/to_stream.hpp b/include/tao/json/ubjson/to_stream.hpp index 31c14317..d278f07f 100644 --- a/include/tao/json/ubjson/to_stream.hpp +++ b/include/tao/json/ubjson/to_stream.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_UBJSON_TO_STREAM_HPP -#define TAOCPP_JSON_INCLUDE_UBJSON_TO_STREAM_HPP +#ifndef TAO_JSON_UBJSON_TO_STREAM_HPP +#define TAO_JSON_UBJSON_TO_STREAM_HPP #include @@ -12,25 +12,17 @@ #include "../events/non_finite_to_null.hpp" #include "../events/transformer.hpp" -#include "../events/ubjson/to_stream.hpp" +#include "events/to_stream.hpp" -namespace tao +namespace tao::json::ubjson { - namespace json + template< template< typename... > class... Transformers, template< typename... > class Traits > + void to_stream( std::ostream& os, const basic_value< Traits >& v ) { - namespace ubjson - { - template< template< typename... > class... Transformers, template< typename... > class Traits > - void to_stream( std::ostream& os, const basic_value< Traits >& v ) - { - events::transformer< events::ubjson::to_stream, Transformers..., events::non_finite_to_null > consumer( os ); - events::from_value( consumer, v ); - } + json::events::transformer< events::to_stream, Transformers..., json::events::non_finite_to_null > consumer( os ); + json::events::from_value( consumer, v ); + } - } // namespace ubjson - - } // namespace json - -} // namespace tao +} // namespace tao::json::ubjson #endif diff --git a/include/tao/json/ubjson/to_string.hpp b/include/tao/json/ubjson/to_string.hpp index cd6680a0..7afe0cb8 100644 --- a/include/tao/json/ubjson/to_string.hpp +++ b/include/tao/json/ubjson/to_string.hpp @@ -1,8 +1,8 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_UBJSON_TO_STRING_HPP -#define TAOCPP_JSON_INCLUDE_UBJSON_TO_STRING_HPP +#ifndef TAO_JSON_UBJSON_TO_STRING_HPP +#define TAO_JSON_UBJSON_TO_STRING_HPP #include @@ -12,26 +12,18 @@ #include "../events/non_finite_to_null.hpp" #include "../events/transformer.hpp" -#include "../events/ubjson/to_string.hpp" +#include "events/to_string.hpp" -namespace tao +namespace tao::json::ubjson { - namespace json + template< template< typename... > class... Transformers, template< typename... > class Traits > + [[nodiscard]] std::string to_string( const basic_value< Traits >& v ) { - namespace ubjson - { - template< template< typename... > class... Transformers, template< typename... > class Traits > - std::string to_string( const basic_value< Traits >& v ) - { - events::transformer< events::ubjson::to_string, Transformers..., events::non_finite_to_null > consumer; - events::from_value( consumer, v ); - return consumer.value(); - } + json::events::transformer< events::to_string, Transformers..., json::events::non_finite_to_null > consumer; + json::events::from_value( consumer, v ); + return consumer.value(); + } - } // namespace ubjson - - } // namespace json - -} // namespace tao +} // namespace tao::json::ubjson #endif diff --git a/include/tao/json/utf8.hpp b/include/tao/json/utf8.hpp new file mode 100644 index 00000000..18f139fe --- /dev/null +++ b/include/tao/json/utf8.hpp @@ -0,0 +1,57 @@ +// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey +// Please see LICENSE for license or visit https://github.com/taocpp/json/ + +#ifndef TAO_JSON_UTF8_HPP +#define TAO_JSON_UTF8_HPP + +#include "external/pegtl/memory_input.hpp" +#include "external/pegtl/parse.hpp" +#include "external/pegtl/rules.hpp" +#include "external/pegtl/utf8.hpp" + +namespace tao::json +{ + enum class utf8_mode : bool + { + check, + trust + }; + + namespace internal + { + template< typename Input > + bool consume_utf8_impl( Input& in, const std::size_t todo ) + { + std::size_t i = 0; + while( i < todo ) { + const auto p = pegtl::internal::peek_utf8::peek( in, pegtl::internal::peek_utf8::max_input_size ).size; + if( ( p == 0 ) || ( ( i += p ) > todo ) ) { + return false; + } + in.bump_in_this_line( p ); + } + return true; + } + + template< utf8_mode M, typename Input > + void consume_utf8_throws( Input& in, const std::size_t todo ) + { + if constexpr( M == utf8_mode::trust ) { + in.bump_in_this_line( todo ); + } + else if( !consume_utf8_impl( in, todo ) ) { + throw pegtl::parse_error( "invalid utf8", in ); + } + } + + inline bool validate_utf8_nothrow( const std::string_view sv ) noexcept + { + pegtl::memory_input in( sv, "validate_utf8" ); + return consume_utf8_impl( in, sv.size() ); + } + + } // namespace internal + +} // namespace tao::json + +#endif diff --git a/include/tao/json/value.hpp b/include/tao/json/value.hpp index afb6bd3b..df8453ec 100644 --- a/include/tao/json/value.hpp +++ b/include/tao/json/value.hpp @@ -1,1905 +1,12 @@ -// Copyright (c) 2017 Dr. Colin Hirsch and Daniel Frey +// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ -#ifndef TAOCPP_JSON_INCLUDE_VALUE_HPP -#define TAOCPP_JSON_INCLUDE_VALUE_HPP +#ifndef TAO_JSON_VALUE_HPP +#define TAO_JSON_VALUE_HPP -#include -#include -#include -#include -#include -#include - -#include "external/byte.hpp" -#include "external/string_view.hpp" - -#include "internal/get_by_enum.hpp" -#include "internal/identity.hpp" -#include "internal/throw.hpp" -#include "internal/value_union.hpp" - -#include "byte_view.hpp" -#include "pair.hpp" -#include "pointer.hpp" -#include "single.hpp" +#include "basic_value.hpp" +#include "forward.hpp" +#include "operators.hpp" #include "traits.hpp" -#include "type.hpp" - -namespace tao -{ - namespace json - { - namespace internal - { - template< typename, typename, typename = void > - struct has_as : std::false_type - { - }; - - template< typename T, typename V > - struct has_as< T, V, decltype( T::as( std::declval< const V& >() ), void() ) > : std::true_type - { - }; - - // required work-around for GCC 6 - inline void rethrow() - { - throw; - } - - } // namespace internal - - template< template< typename... > class Traits > - class basic_value - { - public: - using binary_t = std::vector< tao::byte >; - using array_t = std::vector< basic_value >; - using object_t = std::map< std::string, basic_value >; - - basic_value() noexcept = default; - - basic_value( const basic_value& r ) - : m_type( r.m_type ) - { - try { - embed( r ); - } - catch( ... ) { - this->~basic_value(); - throw; - } - } - - basic_value( basic_value&& r ) noexcept - : m_type( r.m_type ) - { - seize( std::move( r ) ); - } - - basic_value( null_t ) noexcept - { - unsafe_assign_null(); - } - - basic_value( empty_binary_t ) noexcept - { - unsafe_emplace_binary(); - } - - basic_value( empty_array_t ) noexcept - { - unsafe_emplace_array(); - } - - basic_value( empty_object_t ) noexcept - { - unsafe_emplace_object(); - } - - template< typename T, typename = typename std::enable_if< !std::is_convertible< T&&, const basic_value& >::value >::type > - basic_value( T&& v ) noexcept( noexcept( Traits< typename std::decay< T >::type >::assign( std::declval< basic_value& >(), std::forward< T >( v ) ) ) ) - { - try { - using D = typename std::decay< T >::type; - Traits< D >::assign( *this, std::forward< T >( v ) ); - } - catch( ... ) { - this->~basic_value(); - internal::rethrow(); - } - } - - basic_value( std::initializer_list< pair< Traits > >&& l ) - { - try { - unsafe_assign( std::move( l ) ); - } - catch( ... ) { - this->~basic_value(); - throw; - } - } - - basic_value( const std::initializer_list< pair< Traits > >& l ) - { - try { - unsafe_assign( l ); - } - catch( ... ) { - this->~basic_value(); - throw; - } - } - - basic_value( std::initializer_list< pair< Traits > >& l ) - : basic_value( static_cast< const std::initializer_list< pair< Traits > >& >( l ) ) - { - } - - ~basic_value() noexcept - { - unsafe_discard(); - assert( ( const_cast< volatile json::type& >( m_type ) = json::type::DESTROYED, true ) ); - } - - static basic_value array( std::initializer_list< single< Traits > >&& l ) - { - basic_value v; - v.append( std::move( l ) ); - return v; - } - - static basic_value array( const std::initializer_list< single< Traits > >& l ) - { - basic_value v; - v.append( l ); - return v; - } - - basic_value& operator=( basic_value v ) noexcept - { - unsafe_discard(); - m_type = v.m_type; - seize( std::move( v ) ); - return *this; - } - - basic_value& operator=( null_t ) noexcept - { - unsafe_discard(); - unsafe_assign_null(); - return *this; - } - - basic_value& operator=( empty_binary_t ) noexcept - { - unsafe_discard(); - unsafe_emplace_binary(); - return *this; - } - - basic_value& operator=( empty_array_t ) noexcept - { - unsafe_discard(); - unsafe_emplace_array(); - return *this; - } - - basic_value& operator=( empty_object_t ) noexcept - { - unsafe_discard(); - unsafe_emplace_object(); - return *this; - } - - void swap( basic_value& r ) noexcept - { - basic_value t( std::move( r ) ); - r = std::move( *this ); - ( *this ) = ( std::move( t ) ); - } - - json::type type() const noexcept - { - return m_type; - } - - explicit operator bool() const noexcept - { - assert( m_type != json::type::DISCARDED ); - assert( m_type != json::type::DESTROYED ); - return m_type != json::type::UNINITIALIZED; - } - - bool is_null() const noexcept - { - return m_type == json::type::NULL_; - } - - bool is_boolean() const noexcept - { - return m_type == json::type::BOOLEAN; - } - - bool is_signed() const noexcept - { - return m_type == json::type::SIGNED; - } - - bool is_unsigned() const noexcept - { - return m_type == json::type::UNSIGNED; - } - - bool is_integer() const noexcept - { - return is_signed() || is_unsigned(); - } - - bool is_double() const noexcept - { - return m_type == json::type::DOUBLE; - } - - bool is_number() const noexcept - { - return is_integer() || is_double(); - } - - bool is_string() const noexcept - { - return m_type == json::type::STRING; - } - - bool is_string_view() const noexcept - { - return m_type == json::type::STRING_VIEW; - } - - bool is_string_type() const noexcept - { - return is_string() || is_string_view(); - } - - bool is_binary() const noexcept - { - return m_type == json::type::BINARY; - } - - bool is_binary_view() const noexcept - { - return m_type == json::type::BINARY_VIEW; - } - - bool is_binary_type() const noexcept - { - return is_binary() || is_binary_view(); - } - - bool is_array() const noexcept - { - return m_type == json::type::ARRAY; - } - - bool is_object() const noexcept - { - return m_type == json::type::OBJECT; - } - - bool is_raw_ptr() const noexcept - { - return m_type == json::type::RAW_PTR; - } - - // The unsafe_get_*() accessor functions MUST NOT be - // called when the type of the value is not the one - // corresponding to the type of the accessor! - - bool unsafe_get_boolean() const noexcept - { - return m_union.b; - } - - std::int64_t unsafe_get_signed() const noexcept - { - return m_union.i; - } - - std::uint64_t unsafe_get_unsigned() const noexcept - { - return m_union.u; - } - - double unsafe_get_double() const noexcept - { - return m_union.d; - } - - std::string& unsafe_get_string() noexcept - { - return m_union.s; - } - - const std::string& unsafe_get_string() const noexcept - { - return m_union.s; - } - - tao::string_view unsafe_get_string_view() const noexcept - { - return m_union.sv; - } - - binary_t& unsafe_get_binary() noexcept - { - return m_union.x; - } - - const binary_t& unsafe_get_binary() const noexcept - { - return m_union.x; - } - - tao::byte_view unsafe_get_binary_view() const noexcept - { - return m_union.xv; - } - - array_t& unsafe_get_array() noexcept - { - return m_union.a; - } - - const array_t& unsafe_get_array() const noexcept - { - return m_union.a; - } - - object_t& unsafe_get_object() noexcept - { - return m_union.o; - } - - const object_t& unsafe_get_object() const noexcept - { - return m_union.o; - } - - const basic_value* unsafe_get_raw_ptr() const noexcept - { - return m_union.p; - } - - template< json::type E > - decltype( internal::get_by_enum< E >::get( std::declval< internal::value_union< basic_value >& >() ) ) unsafe_get() noexcept - { - return internal::get_by_enum< E >::get( m_union ); - } - - template< json::type E > - decltype( internal::get_by_enum< E >::get( std::declval< const internal::value_union< basic_value >& >() ) ) unsafe_get() const noexcept - { - return internal::get_by_enum< E >::get( m_union ); - } - - bool get_boolean() const - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::BOOLEAN ); - return unsafe_get_boolean(); - } - - std::int64_t get_signed() const - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::SIGNED ); - return unsafe_get_signed(); - } - - std::uint64_t get_unsigned() const - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::UNSIGNED ); - return unsafe_get_unsigned(); - } - - double get_double() const - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::DOUBLE ); - return unsafe_get_double(); - } - - std::string& get_string() - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::STRING ); - return unsafe_get_string(); - } - - const std::string& get_string() const - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::STRING ); - return unsafe_get_string(); - } - - tao::string_view get_string_view() const - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::STRING_VIEW ); - return unsafe_get_string_view(); - } - - binary_t& get_binary() - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::BINARY ); - return unsafe_get_binary(); - } - - const binary_t& get_binary() const - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::BINARY ); - return unsafe_get_binary(); - } - - tao::byte_view get_binary_view() const - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::BINARY_VIEW ); - return unsafe_get_binary_view(); - } - - array_t& get_array() - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::ARRAY ); - return unsafe_get_array(); - } - - const array_t& get_array() const - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::ARRAY ); - return unsafe_get_array(); - } - - object_t& get_object() - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::OBJECT ); - return unsafe_get_object(); - } - - const object_t& get_object() const - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::OBJECT ); - return unsafe_get_object(); - } - - const basic_value* get_raw_ptr() const - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::RAW_PTR ); - return unsafe_get_raw_ptr(); - } - - template< json::type E > - decltype( internal::get_by_enum< E >::get( std::declval< internal::value_union< basic_value >& >() ) ) get() - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, E ); - return internal::get_by_enum< E >::get( m_union ); - } - - template< json::type E > - decltype( internal::get_by_enum< E >::get( std::declval< const internal::value_union< basic_value >& >() ) ) get() const - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, E ); - return internal::get_by_enum< E >::get( m_union ); - } - - void unsafe_assign_null() noexcept - { - m_type = json::type::NULL_; - } - - void unsafe_assign_bool( const bool b ) noexcept - { - m_union.b = b; - m_type = json::type::BOOLEAN; - } - - void unsafe_assign_signed( const std::int64_t i ) noexcept - { - m_union.i = i; - m_type = json::type::SIGNED; - } - - void unsafe_assign_unsigned( const std::uint64_t u ) noexcept - { - m_union.u = u; - m_type = json::type::UNSIGNED; - } - - void unsafe_assign_double( const double d ) noexcept - { - m_union.d = d; - m_type = json::type::DOUBLE; - } - - template< typename... Ts > - void unsafe_emplace_string( Ts&&... ts ) noexcept( noexcept( std::string( std::forward< Ts >( ts )... ) ) ) - { - new( &m_union.s ) std::string( std::forward< Ts >( ts )... ); - m_type = json::type::STRING; - } - - void unsafe_assign_string( const std::string& s ) - { - unsafe_emplace_string( s ); - } - - void unsafe_assign_string( std::string&& s ) noexcept - { - unsafe_emplace_string( std::move( s ) ); - } - - void unsafe_assign_string_view( const tao::string_view sv ) noexcept - { - m_union.sv = sv; - m_type = json::type::STRING_VIEW; - } - - template< typename... Ts > - void unsafe_emplace_binary( Ts&&... ts ) noexcept( noexcept( binary_t( std::forward< Ts >( ts )... ) ) ) - { - new( &m_union.x ) binary_t( std::forward< Ts >( ts )... ); - m_type = json::type::BINARY; - } - - void unsafe_assign_binary( const binary_t& x ) - { - unsafe_emplace_binary( x ); - } - - void unsafe_assign_binary( binary_t&& x ) noexcept - { - unsafe_emplace_binary( std::move( x ) ); - } - - void unsafe_assign_binary_view( const tao::byte_view xv ) noexcept - { - m_union.xv = xv; - m_type = json::type::BINARY_VIEW; - } - - template< typename... Ts > - void unsafe_emplace_array( Ts&&... ts ) noexcept( noexcept( array_t( std::forward< Ts >( ts )... ) ) ) - { - new( &m_union.a ) array_t( std::forward< Ts >( ts )... ); - m_type = json::type::ARRAY; - } - - void unsafe_assign_array( const array_t& a ) - { - unsafe_emplace_array( a ); - } - - void unsafe_assign_array( array_t&& a ) noexcept - { - unsafe_emplace_array( std::move( a ) ); - } - - void unsafe_push_back( const basic_value& v ) - { - m_union.a.push_back( v ); - } - - void unsafe_push_back( basic_value&& v ) - { - m_union.a.push_back( std::move( v ) ); - } - - template< typename... Args > - auto unsafe_emplace_back( Args&&... args ) -> decltype( std::declval< array_t >().emplace_back( std::forward< Args >( args )... ) ) - { - return m_union.a.emplace_back( std::forward< Args >( args )... ); - } - - template< typename... Ts > - void unsafe_emplace_object( Ts&&... ts ) noexcept( noexcept( object_t( std::forward< Ts >( ts )... ) ) ) - { - new( &m_union.o ) object_t( std::forward< Ts >( ts )... ); - m_type = json::type::OBJECT; - } - - void unsafe_assign_object( const object_t& o ) - { - unsafe_emplace_object( o ); - } - - void unsafe_assign_object( object_t&& o ) noexcept - { - unsafe_emplace_object( std::move( o ) ); - } - - template< typename... Args > - std::pair< typename object_t::iterator, bool > unsafe_emplace( Args&&... args ) - { - return m_union.o.emplace( std::forward< Args >( args )... ); - } - - void unsafe_assign_raw_ptr( const basic_value* p ) noexcept - { - m_union.p = p; - m_type = json::type::RAW_PTR; - } - - template< typename T > - void unsafe_assign( T&& v ) noexcept( noexcept( Traits< typename std::decay< T >::type >::assign( std::declval< basic_value& >(), std::forward< T >( v ) ) ) ) - { - using D = typename std::decay< T >::type; - Traits< D >::assign( *this, std::forward< T >( v ) ); - } - - void unsafe_assign( std::initializer_list< pair< Traits > >&& l ) - { - unsafe_emplace_object(); - for( auto& e : l ) { - const auto r = unsafe_emplace( std::move( e.key ), std::move( e.value ) ); - if( !r.second ) { - throw std::runtime_error( "duplicate JSON object key: " + r.first->first ); - } - } - } - - void unsafe_assign( const std::initializer_list< pair< Traits > >& l ) - { - unsafe_emplace_object(); - for( const auto& e : l ) { - const auto r = unsafe_emplace( e.key, e.value ); - if( !r.second ) { - throw std::runtime_error( "duplicate JSON object key: " + r.first->first ); - } - } - } - - void unsafe_assign( std::initializer_list< pair< Traits > >& l ) - { - unsafe_assign( static_cast< const std::initializer_list< pair< Traits > >& >( l ) ); - } - - void assign_null() noexcept - { - unsafe_discard(); - unsafe_assign_null(); - } - - void assign_bool( const bool b ) noexcept - { - unsafe_discard(); - unsafe_assign_bool( b ); - } - - void assign_signed( const std::int64_t i ) noexcept - { - unsafe_discard(); - unsafe_assign_signed( i ); - } - - void assign_unsigned( const std::uint64_t u ) noexcept - { - unsafe_discard(); - unsafe_assign_unsigned( u ); - } - - void assign_double( const double d ) noexcept - { - unsafe_discard(); - unsafe_assign_double( d ); - } - - template< typename... Ts > - void emplace_string( Ts&&... ts ) noexcept( noexcept( unsafe_emplace_string( std::forward< Ts >( ts )... ) ) ) - { - discard(); - unsafe_emplace_string( std::forward< Ts >( ts )... ); - } - - void assign_string( const std::string& s ) - { - discard(); - unsafe_assign_string( s ); - } - - void assign_string( std::string&& s ) noexcept - { - unsafe_discard(); - unsafe_assign_string( std::move( s ) ); - } - - void assign_string_view( const tao::string_view sv ) noexcept - { - unsafe_discard(); - unsafe_assign_string_view( sv ); - } - - template< typename... Ts > - void emplace_binary( Ts&&... ts ) noexcept( noexcept( unsafe_emplace_binary( std::forward< Ts >( ts )... ) ) ) - { - discard(); - unsafe_emplace_binary( std::forward< Ts >( ts )... ); - } - - void assign_binary( const binary_t& v ) - { - discard(); - unsafe_assign_binary( v ); - } - - void assign_binary( binary_t&& v ) noexcept - { - unsafe_discard(); - unsafe_assign_binary( std::move( v ) ); - } - - void assign_binary_view( const tao::byte_view xv ) noexcept - { - unsafe_discard(); - unsafe_assign_binary_view( xv ); - } - - template< typename... Ts > - void emplace_array( Ts&&... ts ) noexcept( noexcept( unsafe_emplace_array( std::forward< Ts >( ts )... ) ) ) - { - discard(); - unsafe_emplace_array( std::forward< Ts >( ts )... ); - } - - void assign_array( const array_t& v ) - { - discard(); - unsafe_assign_array( v ); - } - - void assign_array( array_t&& v ) noexcept - { - unsafe_discard(); - unsafe_assign_array( std::move( v ) ); - } - - void prepare_array() - { - switch( m_type ) { - case json::type::UNINITIALIZED: - case json::type::DISCARDED: - unsafe_emplace_array(); - case json::type::ARRAY: - break; - default: - TAOCPP_JSON_THROW_TYPE_ERROR( m_type ); - } - } - - void push_back( const basic_value& v ) - { - prepare_array(); - unsafe_push_back( v ); - } - - void push_back( basic_value&& v ) - { - prepare_array(); - unsafe_push_back( std::move( v ) ); - } - - template< typename... Args > - void emplace_back( Args&&... args ) - { - prepare_array(); - unsafe_emplace_back( std::forward< Args... >( args )... ); - } - - void append( std::initializer_list< single< Traits > >&& l ) - { - prepare_array(); - auto& v = unsafe_get_array(); - v.reserve( v.size() + l.size() ); - for( auto& e : l ) { - unsafe_push_back( std::move( e.value ) ); - } - } - - void append( const std::initializer_list< single< Traits > >& l ) - { - prepare_array(); - auto& v = unsafe_get_array(); - v.reserve( v.size() + l.size() ); - for( const auto& e : l ) { - unsafe_push_back( e.value ); - } - } - - template< typename... Ts > - void emplace_object( Ts&&... ts ) noexcept( noexcept( unsafe_emplace_object( std::forward< Ts >( ts )... ) ) ) - { - discard(); - unsafe_emplace_object( std::forward< Ts >( ts )... ); - } - - void assign_object( const object_t& o ) - { - discard(); - unsafe_assign_object( o ); - } - - void assign_object( object_t&& o ) noexcept - { - unsafe_discard(); - unsafe_assign_object( std::move( o ) ); - } - - void prepare_object() - { - switch( m_type ) { - case json::type::UNINITIALIZED: - case json::type::DISCARDED: - unsafe_emplace_object(); - case json::type::OBJECT: - break; - default: - TAOCPP_JSON_THROW_TYPE_ERROR( m_type ); - } - } - - template< typename... Args > - std::pair< typename object_t::iterator, bool > emplace( Args&&... args ) - { - prepare_object(); - return unsafe_emplace( std::forward< Args >( args )... ); - } - - void insert( std::initializer_list< pair< Traits > >&& l ) - { - prepare_object(); - for( auto& e : l ) { - const auto r = unsafe_emplace( std::move( e.key ), std::move( e.value ) ); - if( !r.second ) { - throw std::runtime_error( "duplicate JSON object key: " + r.first->first ); - } - } - } - - void insert( const std::initializer_list< pair< Traits > >& l ) - { - prepare_object(); - for( const auto& e : l ) { - const auto r = unsafe_emplace( e.key, e.value ); - if( !r.second ) { - throw std::runtime_error( "duplicate JSON object key: " + r.first->first ); - } - } - } - - void assign_raw_ptr( const basic_value* p ) noexcept - { - unsafe_discard(); - unsafe_assign_raw_ptr( p ); - } - - const basic_value* skip_raw_ptr() const noexcept - { - const basic_value* p = this; - while( p && p->is_raw_ptr() ) { - p = p->unsafe_get_raw_ptr(); - } - return p; - } - - basic_value* unsafe_find( const std::string& key ) noexcept - { - const auto it = m_union.o.find( key ); - return ( it != m_union.o.end() ) ? ( &it->second ) : nullptr; - } - - template< typename T > - basic_value* unsafe_find( const T& key ) noexcept - { - const auto it = m_union.o.find( key ); - return ( it != m_union.o.end() ) ? ( &it->second ) : nullptr; - } - - const basic_value* unsafe_find( const std::string& key ) const noexcept - { - const auto it = m_union.o.find( key ); - return ( it != m_union.o.end() ) ? ( &it->second ) : nullptr; - } - - template< typename T > - const basic_value* unsafe_find( const T& key ) const noexcept - { - const auto it = m_union.o.find( key ); - return ( it != m_union.o.end() ) ? ( &it->second ) : nullptr; - } - - basic_value* find( const std::string& key ) - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::OBJECT ); - return unsafe_find( key ); - } - - template< typename T > - basic_value* find( const T& key ) - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::OBJECT ); - return unsafe_find( key ); - } - - const basic_value* find( const std::string& key ) const - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::OBJECT ); - return unsafe_find( key ); - } - - template< typename T > - const basic_value* find( const T& key ) const - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::OBJECT ); - return unsafe_find( key ); - } - - basic_value& unsafe_at( const std::size_t index ) noexcept - { - return m_union.a[ index ]; - } - - const basic_value& unsafe_at( const std::size_t index ) const noexcept - { - return m_union.a[ index ]; - } - - basic_value& unsafe_at( const std::string& key ) noexcept - { - return m_union.o.find( key )->second; - } - - const basic_value& unsafe_at( const std::string& key ) const noexcept - { - return m_union.o.find( key )->second; - } - - basic_value& at( const std::size_t index ) - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::ARRAY ); - return m_union.a.at( index ); - } - - const basic_value& at( const std::size_t index ) const - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::ARRAY ); - return m_union.a.at( index ); - } - - basic_value& at( const std::string& key ) - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::OBJECT ); - return m_union.o.at( key ); - } - - const basic_value& at( const std::string& key ) const - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::OBJECT ); - return m_union.o.at( key ); - } - - basic_value& at( const pointer& k ) - { - return internal::pointer_at( this, k.begin(), k.end() ); - } - - const basic_value& at( const pointer& k ) const - { - return internal::pointer_at( this, k.begin(), k.end() ); - } - - basic_value& operator[]( const std::size_t index ) noexcept - { - assert( m_type == json::type::ARRAY ); - return m_union.a[ index ]; - } - - const basic_value& operator[]( const std::size_t index ) const noexcept - { - assert( m_type == json::type::ARRAY ); - return m_union.a[ index ]; - } - - basic_value& operator[]( const std::string& key ) - { - prepare_object(); - return m_union.o[ key ]; - } - - basic_value& operator[]( std::string&& key ) - { - prepare_object(); - return m_union.o[ std::move( key ) ]; - } - - basic_value& operator[]( const pointer& k ) - { - if( !k ) { - return *this; - } - const auto b = k.begin(); - const auto e = std::prev( k.end() ); - basic_value& v = internal::pointer_at( this, b, e ); - switch( v.m_type ) { - case json::type::ARRAY: { - if( e->key() == "-" ) { - basic_value d; - d.unsafe_assign_null(); - v.unsafe_emplace_back( std::move( d ) ); - return v.m_union.a.back(); - } - return v.at( e->index() ); - } break; - case json::type::OBJECT: { - const auto& key = e->key(); - const auto it = v.m_union.o.find( key ); - if( it == v.m_union.o.end() ) { - basic_value d; - d.unsafe_assign_null(); - const auto r = v.unsafe_emplace( key, std::move( d ) ); - assert( r.second ); - return r.first->second; - } - return it->second; - } break; - default: - throw internal::invalid_type( b, std::next( e ) ); - } - } - - template< typename T > - void extract( T& v ) const - { - Traits< typename std::decay< T >::type >::extract( *this, v ); - } - - template< typename T > - typename std::enable_if< internal::has_as< Traits< T >, basic_value >::value, T >::type as() const - { - return Traits< T >::as( *this ); - } - - template< typename T > - typename std::enable_if< !internal::has_as< Traits< T >, basic_value >::value, T >::type as() const - { - T nrv; - this->extract( nrv ); - return nrv; - } - - template< typename T > - tao::optional< T > optional() const - { - if( is_null() ) { - return tao::nullopt; - } - else { - return as< T >(); - } - } - - template< typename T, typename K > - tao::optional< T > optional( const K& key ) const - { - if( const auto* p = find( key ) ) { - return tao::nullopt; - } - else { - return p->template as< T >(); - } - } - - template< typename T > - tao::optional< T > optional( const std::string& key ) const - { - return optional< T, std::string >( key ); - } - - void erase( const std::size_t index ) - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::ARRAY ); - auto& a = m_union.a; - if( index >= a.size() ) { - throw std::out_of_range( "JSON array index out of bounds" ); - } - a.erase( a.begin() + index ); - } - - void erase( const std::string& key ) - { - TAOCPP_JSON_CHECK_TYPE_ERROR( m_type, json::type::OBJECT ); - if( m_union.o.erase( key ) == 0 ) { - throw std::out_of_range( "JSON object key not found: " + key ); - } - } - - void erase( const pointer& k ) - { - if( !k ) { - throw std::runtime_error( "invalid root JSON Pointer for erase" ); - } - const auto b = k.begin(); - const auto e = std::prev( k.end() ); - basic_value& v = internal::pointer_at( this, b, e ); - switch( v.m_type ) { - case json::type::ARRAY: - v.erase( e->index() ); - break; - case json::type::OBJECT: - v.erase( e->key() ); - break; - default: - throw internal::invalid_type( b, std::next( e ) ); - } - } - - basic_value& insert( const pointer& k, basic_value value ) - { - if( !k ) { - *this = std::move( value ); - return *this; - } - const auto b = k.begin(); - const auto e = std::prev( k.end() ); - basic_value& v = internal::pointer_at( this, b, e ); - switch( v.m_type ) { - case json::type::ARRAY: { - if( e->key() == "-" ) { - v.unsafe_emplace_back( std::move( value ) ); - return v.m_union.a.back(); - } - const auto i = e->index(); - if( i >= v.m_union.a.size() ) { - throw std::out_of_range( "invalid JSON Pointer '" + internal::tokens_to_string( b, std::next( e ) ) + "' -- array index out of bounds" ); - } - v.m_union.a.insert( v.m_union.a.begin() + i, std::move( value ) ); - return v.m_union.a.at( i ); - } break; - case json::type::OBJECT: { - const auto& key = e->key(); - const auto it = v.m_union.o.find( key ); - if( it == v.m_union.o.end() ) { - const auto r = v.unsafe_emplace( key, std::move( value ) ); - assert( r.second ); - return r.first->second; - } - it->second = std::move( value ); - return it->second; - } break; - default: - throw internal::invalid_type( b, std::next( e ) ); - } - } - - bool empty() const noexcept - { - switch( m_type ) { - case json::type::UNINITIALIZED: - return true; - - // LCOV_EXCL_START - case json::type::DISCARDED: - assert( m_type != json::type::DISCARDED ); - return true; - - case json::type::DESTROYED: - assert( m_type != json::type::DESTROYED ); - return true; - // LCOV_EXCL_STOP - - case json::type::NULL_: - case json::type::BOOLEAN: - case json::type::SIGNED: - case json::type::UNSIGNED: - case json::type::DOUBLE: - return false; - - case json::type::STRING: - return m_union.s.empty(); - - case json::type::STRING_VIEW: - return m_union.sv.empty(); - - case json::type::BINARY: - return m_union.x.empty(); - - case json::type::BINARY_VIEW: - return m_union.xv.empty(); - - case json::type::ARRAY: - return m_union.a.empty(); - - case json::type::OBJECT: - return m_union.o.empty(); - - case json::type::RAW_PTR: - return !m_union.p; - } - // LCOV_EXCL_START - assert( false ); - return false; - // LCOV_EXCL_STOP - } - - void unsafe_discard() noexcept - { - assert( m_type != json::type::DESTROYED ); - - switch( m_type ) { - case json::type::UNINITIALIZED: - case json::type::DISCARDED: - case json::type::DESTROYED: - case json::type::NULL_: - case json::type::BOOLEAN: - case json::type::SIGNED: - case json::type::UNSIGNED: - case json::type::DOUBLE: - case json::type::RAW_PTR: - return; - - case json::type::STRING: - m_union.s.~basic_string(); - return; - - case json::type::STRING_VIEW: - m_union.sv.~string_view(); - return; - - case json::type::BINARY: - m_union.x.~vector(); - return; - - case json::type::BINARY_VIEW: - m_union.xv.~byte_view(); - return; - - case json::type::ARRAY: - m_union.a.~vector(); - return; - - case json::type::OBJECT: - m_union.o.~map(); - return; - } - assert( false ); // LCOV_EXCL_LINE - } - - void discard() noexcept - { - unsafe_discard(); - m_type = json::type::DISCARDED; - } - - void reset() noexcept - { - unsafe_discard(); - m_type = json::type::UNINITIALIZED; - } - - private: - void seize( basic_value&& r ) noexcept - { - assert( m_type != json::type::DESTROYED ); - - switch( r.m_type ) { - case json::type::UNINITIALIZED: - assert( ( r.m_type = json::type::DISCARDED, true ) ); - return; - - // LCOV_EXCL_START - case json::type::DISCARDED: - assert( r.m_type != json::type::DISCARDED ); - return; - - case json::type::DESTROYED: - assert( r.m_type != json::type::DESTROYED ); - return; - // LCOV_EXCL_STOP - - case json::type::NULL_: - assert( ( r.m_type = json::type::DISCARDED, true ) ); - return; - - case json::type::BOOLEAN: - m_union.b = r.m_union.b; - assert( ( r.m_type = json::type::DISCARDED, true ) ); - return; - - case json::type::SIGNED: - m_union.i = r.m_union.i; - assert( ( r.m_type = json::type::DISCARDED, true ) ); - return; - - case json::type::UNSIGNED: - m_union.u = r.m_union.u; - assert( ( r.m_type = json::type::DISCARDED, true ) ); - return; - - case json::type::DOUBLE: - m_union.d = r.m_union.d; - assert( ( r.m_type = json::type::DISCARDED, true ) ); - return; - - case json::type::STRING: - new( &m_union.s ) std::string( std::move( r.m_union.s ) ); - assert( ( r.discard(), true ) ); - return; - - case json::type::STRING_VIEW: - new( &m_union.sv ) tao::string_view( r.m_union.sv ); - assert( ( r.m_type = json::type::DISCARDED, true ) ); - return; - - case json::type::BINARY: - new( &m_union.x ) binary_t( std::move( r.m_union.x ) ); - assert( ( r.discard(), true ) ); - return; - - case json::type::BINARY_VIEW: - new( &m_union.xv ) tao::byte_view( r.m_union.xv ); - assert( ( r.m_type = json::type::DISCARDED, true ) ); - return; - - case json::type::ARRAY: - new( &m_union.a ) array_t( std::move( r.m_union.a ) ); - assert( ( r.discard(), true ) ); - return; - - case json::type::OBJECT: - new( &m_union.o ) object_t( std::move( r.m_union.o ) ); - assert( ( r.discard(), true ) ); - return; - - case json::type::RAW_PTR: - m_union.p = r.m_union.p; - assert( ( r.m_type = json::type::DISCARDED, true ) ); - return; - } - assert( false ); // LCOV_EXCL_LINE - } - - void embed( const basic_value& r ) - { - assert( m_type != json::type::DESTROYED ); - - switch( r.m_type ) { - case json::type::UNINITIALIZED: - return; - - case json::type::DISCARDED: - throw std::logic_error( "attempt to use a discarded value" ); - - case json::type::DESTROYED: - throw std::logic_error( "attempt to use a destroyed value" ); - - case json::type::NULL_: - return; - - case json::type::BOOLEAN: - m_union.b = r.m_union.b; - return; - - case json::type::SIGNED: - m_union.i = r.m_union.i; - return; - - case json::type::UNSIGNED: - m_union.u = r.m_union.u; - return; - - case json::type::DOUBLE: - m_union.d = r.m_union.d; - return; - - case json::type::STRING: - new( &m_union.s ) std::string( r.m_union.s ); - return; - - case json::type::STRING_VIEW: - new( &m_union.sv ) tao::string_view( r.m_union.sv ); - return; - - case json::type::BINARY: - new( &m_union.x ) binary_t( r.m_union.x ); - return; - - case json::type::BINARY_VIEW: - new( &m_union.xv ) tao::byte_view( r.m_union.xv ); - return; - - case json::type::ARRAY: - new( &m_union.a ) array_t( r.m_union.a ); - return; - - case json::type::OBJECT: - new( &m_union.o ) object_t( r.m_union.o ); - return; - - case json::type::RAW_PTR: - m_union.p = r.m_union.p; - return; - } - assert( false ); // LCOV_EXCL_LINE - } - - protected: - json::type m_type = json::type::UNINITIALIZED; - internal::value_union< basic_value > m_union; - }; - - template< template< typename... > class TraitsL, template< typename... > class TraitsR > - bool operator==( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept - { - if( rhs.is_raw_ptr() ) { - if( const auto* p = rhs.skip_raw_ptr() ) { - return lhs == *p; - } - else { - if( const auto* q = lhs.skip_raw_ptr() ) { - return q->is_null(); - } - else { - return true; - } - } - } - - if( lhs.type() != rhs.type() ) { - switch( lhs.type() ) { - case type::RAW_PTR: - if( const auto* p = lhs.skip_raw_ptr() ) { - return *p == rhs; - } - return rhs.is_null(); - - case type::SIGNED: - if( rhs.type() == type::UNSIGNED ) { - const auto v = lhs.unsafe_get_signed(); - return ( v >= 0 ) && ( static_cast< std::uint64_t >( v ) == rhs.unsafe_get_unsigned() ); - } - if( rhs.type() == type::DOUBLE ) { - return lhs.unsafe_get_signed() == rhs.unsafe_get_double(); - } - break; - - case type::UNSIGNED: - if( rhs.type() == type::SIGNED ) { - const auto v = rhs.unsafe_get_signed(); - return ( v >= 0 ) && ( lhs.unsafe_get_unsigned() == static_cast< std::uint64_t >( v ) ); - } - if( rhs.type() == type::DOUBLE ) { - return lhs.unsafe_get_unsigned() == rhs.unsafe_get_double(); - } - break; - - case type::DOUBLE: - if( rhs.type() == type::SIGNED ) { - return lhs.unsafe_get_double() == rhs.unsafe_get_signed(); - } - if( rhs.type() == type::UNSIGNED ) { - return lhs.unsafe_get_double() == rhs.unsafe_get_unsigned(); - } - break; - - case type::STRING: - if( rhs.type() == type::STRING_VIEW ) { - return lhs.unsafe_get_string() == rhs.unsafe_get_string_view(); - } - break; - - case type::STRING_VIEW: - if( rhs.type() == type::STRING ) { - return lhs.unsafe_get_string_view() == rhs.unsafe_get_string(); - } - break; - - case type::BINARY: - if( rhs.type() == type::BINARY_VIEW ) { - return lhs.unsafe_get_binary() == rhs.unsafe_get_binary_view(); - } - break; - - case type::BINARY_VIEW: - if( rhs.type() == type::BINARY ) { - return lhs.unsafe_get_binary_view() == rhs.unsafe_get_binary(); - } - break; - - case type::DISCARDED: - case type::DESTROYED: - assert( false ); - break; - - default: - break; - } - assert( rhs.type() != type::DISCARDED ); - assert( rhs.type() != type::DESTROYED ); - return false; - } - - switch( lhs.type() ) { - case type::UNINITIALIZED: - return true; - - // LCOV_EXCL_START - case type::DISCARDED: - assert( lhs.type() != type::DISCARDED ); - break; - - case type::DESTROYED: - assert( lhs.type() != type::DESTROYED ); - break; - // LCOV_EXCL_STOP - - case type::NULL_: - return true; - - case type::BOOLEAN: - return lhs.unsafe_get_boolean() == rhs.unsafe_get_boolean(); - - case type::SIGNED: - return lhs.unsafe_get_signed() == rhs.unsafe_get_signed(); - - case type::UNSIGNED: - return lhs.unsafe_get_unsigned() == rhs.unsafe_get_unsigned(); - - case type::DOUBLE: - return lhs.unsafe_get_double() == rhs.unsafe_get_double(); - - case type::STRING: - return lhs.unsafe_get_string() == rhs.unsafe_get_string(); - - case type::STRING_VIEW: - return lhs.unsafe_get_string_view() == rhs.unsafe_get_string_view(); - - case type::BINARY: - return lhs.unsafe_get_binary() == rhs.unsafe_get_binary(); - - case type::BINARY_VIEW: - return lhs.unsafe_get_binary_view() == rhs.unsafe_get_binary_view(); - - case type::ARRAY: - return lhs.unsafe_get_array() == rhs.unsafe_get_array(); - - case type::OBJECT: - return lhs.unsafe_get_object() == rhs.unsafe_get_object(); - - case type::RAW_PTR: - assert( false ); - break; // LCOV_EXCL_LINE - } - // LCOV_EXCL_START - assert( false ); - return false; - // LCOV_EXCL_STOP - } - - template< template< typename... > class Traits > - bool operator==( const basic_value< Traits >& lhs, tao::internal::identity< basic_value< Traits > > rhs ) noexcept - { - return lhs == rhs; - } - - template< template< typename... > class Traits > - bool operator==( tao::internal::identity< basic_value< Traits > > lhs, const basic_value< Traits >& rhs ) noexcept - { - return lhs == rhs; - } - - template< template< typename... > class Traits, typename T, typename = decltype( Traits< typename std::decay< T >::type >::equal( std::declval< const basic_value< Traits >& >(), std::declval< const T& >() ) ) > - bool operator==( const basic_value< Traits >& lhs, const T& rhs ) noexcept - { - using D = typename std::decay< T >::type; - static_assert( noexcept( Traits< D >::equal( lhs, rhs ) ), "equal must be noexcept" ); - return Traits< D >::equal( lhs, rhs ); - } - - template< typename T, template< typename... > class Traits, typename = decltype( Traits< typename std::decay< T >::type >::equal( std::declval< const basic_value< Traits >& >(), std::declval< const T& >() ) ) > - bool operator==( const T& lhs, const basic_value< Traits >& rhs ) noexcept - { - using D = typename std::decay< T >::type; - static_assert( noexcept( Traits< D >::equal( rhs, lhs ) ), "equal must be noexcept" ); - return Traits< D >::equal( rhs, lhs ); - } - - template< template< typename... > class TraitsL, template< typename... > class TraitsR > - bool operator!=( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept - { - return !( lhs == rhs ); - } - - template< template< typename... > class Traits, typename T > - bool operator!=( const basic_value< Traits >& lhs, const T& rhs ) noexcept - { - return !( lhs == rhs ); - } - - template< typename T, template< typename... > class Traits > - bool operator!=( const T& lhs, const basic_value< Traits >& rhs ) noexcept - { - return !( lhs == rhs ); - } - - template< template< typename... > class TraitsL, template< typename... > class TraitsR > - bool operator<( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept - { - if( rhs.is_raw_ptr() ) { - if( const auto* p = rhs.skip_raw_ptr() ) { - return lhs < *p; - } - else { - if( const auto* q = lhs.skip_raw_ptr() ) { - return q->type() < type::NULL_; - } - else { - return false; - } - } - } - - if( lhs.type() != rhs.type() ) { - switch( lhs.type() ) { - case type::RAW_PTR: - if( const auto* p = lhs.skip_raw_ptr() ) { - return *p < rhs; - } - return type::NULL_ < rhs.type(); - - case type::SIGNED: - if( rhs.type() == type::UNSIGNED ) { - const auto v = lhs.unsafe_get_signed(); - return ( v < 0 ) || ( static_cast< std::uint64_t >( v ) < rhs.unsafe_get_unsigned() ); - } - if( rhs.type() == type::DOUBLE ) { - return lhs.unsafe_get_signed() < rhs.unsafe_get_double(); - } - break; - - case type::UNSIGNED: - if( rhs.type() == type::SIGNED ) { - const auto v = rhs.unsafe_get_signed(); - return ( v >= 0 ) && ( lhs.unsafe_get_unsigned() < static_cast< std::uint64_t >( v ) ); - } - if( rhs.type() == type::DOUBLE ) { - return lhs.unsafe_get_unsigned() < rhs.unsafe_get_double(); - } - break; - - case type::DOUBLE: - if( rhs.type() == type::SIGNED ) { - return lhs.unsafe_get_double() < rhs.unsafe_get_signed(); - } - if( rhs.type() == type::UNSIGNED ) { - return lhs.unsafe_get_double() < rhs.unsafe_get_unsigned(); - } - break; - - case type::STRING: - if( rhs.type() == type::STRING_VIEW ) { - return lhs.unsafe_get_string() < rhs.unsafe_get_string_view(); - } - break; - - case type::STRING_VIEW: - if( rhs.type() == type::STRING ) { - return lhs.unsafe_get_string_view() < rhs.unsafe_get_string(); - } - break; - - case type::BINARY: - if( rhs.type() == type::BINARY_VIEW ) { - return lhs.unsafe_get_binary() < rhs.unsafe_get_binary_view(); - } - break; - - case type::BINARY_VIEW: - if( rhs.type() == type::BINARY ) { - return lhs.unsafe_get_binary_view() < rhs.unsafe_get_binary(); - } - break; - - case type::DISCARDED: - case type::DESTROYED: - assert( false ); - break; - - default: - break; - } - assert( rhs.type() != type::DISCARDED ); - assert( rhs.type() != type::DESTROYED ); - return lhs.type() < rhs.type(); - } - - switch( lhs.type() ) { - case type::UNINITIALIZED: - return false; - - // LCOV_EXCL_START - case type::DISCARDED: - assert( lhs.type() != type::DISCARDED ); - break; - - case type::DESTROYED: - assert( lhs.type() != type::DESTROYED ); - break; - // LCOV_EXCL_STOP - - case type::NULL_: - return false; - - case type::BOOLEAN: - return lhs.unsafe_get_boolean() < rhs.unsafe_get_boolean(); - - case type::SIGNED: - return lhs.unsafe_get_signed() < rhs.unsafe_get_signed(); - - case type::UNSIGNED: - return lhs.unsafe_get_unsigned() < rhs.unsafe_get_unsigned(); - - case type::DOUBLE: - return lhs.unsafe_get_double() < rhs.unsafe_get_double(); - - case type::STRING: - return lhs.unsafe_get_string() < rhs.unsafe_get_string(); - - case type::STRING_VIEW: - return lhs.unsafe_get_string_view() < rhs.unsafe_get_string_view(); - - case type::BINARY: - return lhs.unsafe_get_binary() < rhs.unsafe_get_binary(); - - case type::BINARY_VIEW: - return lhs.unsafe_get_binary_view() < rhs.unsafe_get_binary_view(); - - case type::ARRAY: - return lhs.unsafe_get_array() < rhs.unsafe_get_array(); - - case type::OBJECT: - return lhs.unsafe_get_object() < rhs.unsafe_get_object(); - - case type::RAW_PTR: - break; // LCOV_EXCL_LINE - } - // LCOV_EXCL_START - assert( false ); - return false; - // LCOV_EXCL_STOP - } - - template< template< typename... > class Traits > - bool operator<( const basic_value< Traits >& lhs, tao::internal::identity< basic_value< Traits > > rhs ) noexcept - { - return lhs < rhs; - } - - template< template< typename... > class Traits > - bool operator<( const tao::internal::identity< basic_value< Traits > > lhs, const basic_value< Traits >& rhs ) noexcept - { - return lhs < rhs; - } - - template< template< typename... > class Traits, typename T, typename = decltype( Traits< typename std::decay< T >::type >::less_than( std::declval< const basic_value< Traits >& >(), std::declval< const T& >() ) ) > - bool operator<( const basic_value< Traits >& lhs, const T& rhs ) noexcept - { - using D = typename std::decay< T >::type; - static_assert( noexcept( Traits< D >::less_than( lhs, rhs ) ), "less_than must be noexcept" ); - return Traits< D >::less_than( lhs, rhs ); - } - - template< typename T, template< typename... > class Traits, typename = decltype( Traits< typename std::decay< T >::type >::greater_than( std::declval< const basic_value< Traits >& >(), std::declval< const T& >() ) ) > - bool operator<( const T& lhs, const basic_value< Traits >& rhs ) noexcept - { - using D = typename std::decay< T >::type; - static_assert( noexcept( Traits< D >::greater_than( rhs, lhs ) ), "less_than must be noexcept" ); - return Traits< D >::greater_than( rhs, lhs ); - } - - template< template< typename... > class TraitsL, template< typename... > class TraitsR > - bool operator>( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept - { - return rhs < lhs; - } - - template< template< typename... > class Traits > - bool operator>( const basic_value< Traits >& lhs, tao::internal::identity< basic_value< Traits > > rhs ) noexcept - { - return rhs < lhs; - } - - template< template< typename... > class Traits > - bool operator>( tao::internal::identity< basic_value< Traits > > lhs, const basic_value< Traits >& rhs ) noexcept - { - return rhs < lhs; - } - - template< template< typename... > class Traits, typename T, typename = decltype( Traits< typename std::decay< T >::type >::greater_than( std::declval< const basic_value< Traits >& >(), std::declval< const T& >() ) ) > - bool operator>( const basic_value< Traits >& lhs, const T& rhs ) noexcept - { - using D = typename std::decay< T >::type; - static_assert( noexcept( Traits< D >::greater_than( lhs, rhs ) ), "less_than must be noexcept" ); - return Traits< D >::greater_than( lhs, rhs ); - } - - template< typename T, template< typename... > class Traits, typename = decltype( Traits< typename std::decay< T >::type >::less_than( std::declval< const basic_value< Traits >& >(), std::declval< const T& >() ) ) > - bool operator>( const T& lhs, const basic_value< Traits >& rhs ) noexcept - { - using D = typename std::decay< T >::type; - static_assert( noexcept( Traits< D >::less_than( rhs, lhs ) ), "less_than must be noexcept" ); - return Traits< D >::less_than( rhs, lhs ); - } - - template< template< typename... > class TraitsL, template< typename... > class TraitsR > - bool operator<=( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept - { - return !( lhs > rhs ); - } - - template< template< typename... > class Traits, typename T > - bool operator<=( const basic_value< Traits >& lhs, const T& rhs ) noexcept - { - return !( lhs > rhs ); - } - - template< typename T, template< typename... > class Traits > - bool operator<=( const T& lhs, const basic_value< Traits >& rhs ) noexcept - { - return !( lhs > rhs ); - } - - template< template< typename... > class TraitsL, template< typename... > class TraitsR > - bool operator>=( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept - { - return !( lhs < rhs ); - } - - template< template< typename... > class Traits, typename T > - bool operator>=( const basic_value< Traits >& lhs, const T& rhs ) noexcept - { - return !( lhs < rhs ); - } - - template< typename T, template< typename... > class Traits > - bool operator>=( const T& lhs, const basic_value< Traits >& rhs ) noexcept - { - return !( lhs < rhs ); - } - - template< template< typename... > class Traits > - basic_value< Traits >& operator+=( basic_value< Traits >& v, std::initializer_list< pair< Traits > >&& l ) - { - v.insert( std::move( l ) ); - return v; - } - - template< template< typename... > class Traits > - basic_value< Traits >& operator+=( basic_value< Traits >& v, const std::initializer_list< pair< Traits > >& l ) - { - v.insert( l ); - return v; - } - - template< template< typename... > class Traits > - basic_value< Traits >& operator-=( basic_value< Traits >& v, std::initializer_list< std::string > l ) - { - auto& o = v.get_object(); - for( const auto& k : l ) { - if( o.erase( k ) == 0 ) { - throw std::runtime_error( "JSON object key not found: " + k ); - } - } - return v; - } - - using value = basic_value< traits >; - - } // namespace json - -} // namespace tao #endif From 28ee035d9ff646d2a32248b0e4eb09dcb54bdc27 Mon Sep 17 00:00:00 2001 From: Jan Christoph Uhde Date: Fri, 14 Feb 2020 13:03:16 +0100 Subject: [PATCH 5/7] Update bindings. (Needs review) --- include/velocypack/Json.h | 12 +++++++----- src/TaoParser.cpp | 8 +++++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/include/velocypack/Json.h b/include/velocypack/Json.h index 0811a586..e03619b8 100644 --- a/include/velocypack/Json.h +++ b/include/velocypack/Json.h @@ -94,12 +94,12 @@ namespace arangodb add( Value( v ) ); } - void string( const tao::string_view v ) + void string( const std::string_view v ) { add( ValuePair( reinterpret_cast< const uint8_t* >( v.data() ), v.size(), ValueType::String ) ); } - void binary( const tao::byte_view v ) + void binary( const tao::binary_view v ) { add( ValuePair( reinterpret_cast< const uint8_t* >( v.data() ), v.size(), ValueType::Binary ) ); } @@ -177,7 +177,7 @@ namespace arangodb for ( const auto& s : ObjectIterator( slice ) ) { ValueLength size; const char * data = s.key.getString( size ); - consumer.key( tao::string_view( data, size ) ); + consumer.key( std::string_view( data, size ) ); sliceToEvents( consumer, s.value ); consumer.member(); } @@ -208,18 +208,20 @@ namespace arangodb case ValueType::String: { ValueLength size; const char * data = slice.getString( size ); - consumer.string( tao::string_view( data, size ) ); + consumer.string( std::string_view( data, size ) ); } break; case ValueType::Binary: { ValueLength size; const auto * data = slice.getBinary( size ); - consumer.binary( tao::byte_view( reinterpret_cast< const tao::byte* >( data ), size ) ); + consumer.binary( tao::binary_view( reinterpret_cast< const std::byte* >( data ), size ) ); } break; case ValueType::BCD: // TODO: Convert to other number format or string? break; case ValueType::Custom: // TODO: What? + case ValueType::Tagged: + // TODO: What? break; } } diff --git a/src/TaoParser.cpp b/src/TaoParser.cpp index 947f68f0..cfd44747 100644 --- a/src/TaoParser.cpp +++ b/src/TaoParser.cpp @@ -26,6 +26,8 @@ #include "velocypack/velocypack-common.h" #include "velocypack/TaoParser.h" +#include "tao/json/external/pegtl/memory_input.hpp" + #include namespace arangodb @@ -36,18 +38,18 @@ namespace arangodb if (options->clearBuilderBeforeParse) { _e.builder->clear(); } - tao::json_pegtl::memory_input< tao::json_pegtl::tracking_mode::LAZY, tao::json_pegtl::eol::lf_crlf, const char* > in( reinterpret_cast< const char * >( json ), size, __PRETTY_FUNCTION__ ); + tao::json::pegtl::memory_input< tao::json::pegtl::tracking_mode::lazy, tao::json::pegtl::eol::lf_crlf, const char* > in( reinterpret_cast< const char * >( json ), size, __PRETTY_FUNCTION__ ); if ( multi ) { ValueLength nr = 0; do { const auto * const t = in.current(); - tao::json_pegtl::parse< tao::json_pegtl::must< tao::json::internal::rules::text >, tao::json::internal::action, tao::json::internal::control >( in, _e ); + tao::json::pegtl::parse< tao::json::pegtl::must< tao::json::internal::rules::text >, tao::json::internal::action>( in, _e ); nr += in.current() - t; } while ( !in.empty() ); return nr; } const auto * const t = in.current(); - tao::json_pegtl::parse< tao::json::internal::grammar, tao::json::internal::action, tao::json::internal::control >( in, _e ); + tao::json::pegtl::parse< tao::json::internal::grammar, tao::json::internal::action>( in, _e ); return in.current() - t; } From 6d2989058f6b96382e1e48e932379b4814d90ec0 Mon Sep 17 00:00:00 2001 From: Jan Christoph Uhde Date: Mon, 17 Feb 2020 20:27:46 +0100 Subject: [PATCH 6/7] remove taolib --- include/tao/json.hpp | 45 - include/tao/json/basic_value.hpp | 941 --------- include/tao/json/binary.hpp | 103 - include/tao/json/binary_view.hpp | 31 - include/tao/json/binding.hpp | 71 - include/tao/json/binding/constant.hpp | 232 --- include/tao/json/binding/element.hpp | 182 -- include/tao/json/binding/factory.hpp | 250 --- .../tao/json/binding/for_nothing_value.hpp | 17 - include/tao/json/binding/for_unknown_key.hpp | 17 - include/tao/json/binding/inherit.hpp | 14 - include/tao/json/binding/internal/array.hpp | 103 - include/tao/json/binding/internal/inherit.hpp | 45 - include/tao/json/binding/internal/object.hpp | 267 --- .../tao/json/binding/internal/type_key.hpp | 54 - include/tao/json/binding/member.hpp | 32 - include/tao/json/binding/member_kind.hpp | 17 - include/tao/json/binding/versions.hpp | 127 -- include/tao/json/cbor.hpp | 18 - include/tao/json/cbor/consume_file.hpp | 34 - include/tao/json/cbor/consume_string.hpp | 32 - include/tao/json/cbor/events/from_file.hpp | 27 - include/tao/json/cbor/events/from_input.hpp | 43 - include/tao/json/cbor/events/from_string.hpp | 37 - include/tao/json/cbor/events/to_stream.hpp | 161 -- include/tao/json/cbor/events/to_string.hpp | 31 - include/tao/json/cbor/from_file.hpp | 33 - include/tao/json/cbor/from_input.hpp | 33 - include/tao/json/cbor/from_string.hpp | 32 - include/tao/json/cbor/internal/grammar.hpp | 417 ---- include/tao/json/cbor/internal/major.hpp | 28 - include/tao/json/cbor/parts_parser.hpp | 392 ---- include/tao/json/cbor/to_stream.hpp | 27 - include/tao/json/cbor/to_string.hpp | 28 - include/tao/json/consume.hpp | 43 - include/tao/json/consume_file.hpp | 33 - include/tao/json/consume_string.hpp | 31 - include/tao/json/contrib/array_traits.hpp | 43 - include/tao/json/contrib/deque_traits.hpp | 41 - include/tao/json/contrib/diff.hpp | 106 - include/tao/json/contrib/get.hpp | 152 -- .../json/contrib/internal/array_traits.hpp | 92 - .../json/contrib/internal/indirect_traits.hpp | 69 - .../json/contrib/internal/object_traits.hpp | 105 - .../tao/json/contrib/internal/type_traits.hpp | 36 - include/tao/json/contrib/list_traits.hpp | 41 - include/tao/json/contrib/map_traits.hpp | 43 - include/tao/json/contrib/multimap_traits.hpp | 43 - include/tao/json/contrib/multiset_traits.hpp | 41 - include/tao/json/contrib/pair_traits.hpp | 21 - include/tao/json/contrib/patch.hpp | 105 - include/tao/json/contrib/pointer_traits.hpp | 59 - include/tao/json/contrib/position.hpp | 166 -- include/tao/json/contrib/reference.hpp | 115 - include/tao/json/contrib/schema.hpp | 1851 ----------------- include/tao/json/contrib/set_traits.hpp | 41 - .../tao/json/contrib/shared_ptr_traits.hpp | 90 - include/tao/json/contrib/traits.hpp | 121 -- include/tao/json/contrib/tuple_traits.hpp | 51 - .../tao/json/contrib/unique_ptr_traits.hpp | 89 - .../tao/json/contrib/unordered_map_traits.hpp | 43 - .../tao/json/contrib/unordered_set_traits.hpp | 41 - .../tao/json/contrib/vector_bool_traits.hpp | 45 - include/tao/json/contrib/vector_traits.hpp | 51 - include/tao/json/events.hpp | 47 - include/tao/json/events/apply.hpp | 20 - include/tao/json/events/binary_to_base64.hpp | 26 - .../tao/json/events/binary_to_base64url.hpp | 28 - .../tao/json/events/binary_to_exception.hpp | 27 - include/tao/json/events/binary_to_hex.hpp | 26 - include/tao/json/events/compare.hpp | 265 --- include/tao/json/events/debug.hpp | 145 -- include/tao/json/events/discard.hpp | 43 - include/tao/json/events/from_file.hpp | 28 - include/tao/json/events/from_input.hpp | 45 - include/tao/json/events/from_stream.hpp | 33 - include/tao/json/events/from_string.hpp | 38 - include/tao/json/events/from_value.hpp | 202 -- include/tao/json/events/hash.hpp | 174 -- .../json/events/invalid_string_to_binary.hpp | 50 - .../events/invalid_string_to_exception.hpp | 49 - .../tao/json/events/invalid_string_to_hex.hpp | 48 - .../events/key_camel_case_to_snake_case.hpp | 62 - .../events/key_snake_case_to_camel_case.hpp | 57 - .../tao/json/events/limit_nesting_depth.hpp | 82 - include/tao/json/events/limit_value_count.hpp | 46 - .../json/events/non_finite_to_exception.hpp | 31 - .../tao/json/events/non_finite_to_null.hpp | 32 - .../tao/json/events/non_finite_to_string.hpp | 40 - include/tao/json/events/prefer_signed.hpp | 32 - include/tao/json/events/prefer_unsigned.hpp | 32 - include/tao/json/events/produce.hpp | 22 - include/tao/json/events/ref.hpp | 111 - include/tao/json/events/statistics.hpp | 112 - include/tao/json/events/tee.hpp | 386 ---- include/tao/json/events/to_pretty_stream.hpp | 172 -- include/tao/json/events/to_stream.hpp | 142 -- include/tao/json/events/to_string.hpp | 33 - include/tao/json/events/to_value.hpp | 137 -- include/tao/json/events/transformer.hpp | 70 - .../tao/json/events/validate_event_order.hpp | 411 ---- include/tao/json/events/validate_keys.hpp | 51 - include/tao/json/events/virtual_base.hpp | 192 -- include/tao/json/events/virtual_ref.hpp | 170 -- include/tao/json/external/double.hpp | 1313 ------------ include/tao/json/external/itoa.hpp | 149 -- include/tao/json/external/pegtl.hpp | 53 - .../pegtl/analysis/analyze_cycles.hpp | 127 -- .../json/external/pegtl/analysis/counted.hpp | 23 - .../json/external/pegtl/analysis/generic.hpp | 31 - .../external/pegtl/analysis/grammar_info.hpp | 32 - .../external/pegtl/analysis/insert_guard.hpp | 51 - .../external/pegtl/analysis/insert_rules.hpp | 25 - .../external/pegtl/analysis/rule_info.hpp | 29 - .../external/pegtl/analysis/rule_type.hpp | 21 - include/tao/json/external/pegtl/analyze.hpp | 21 - .../tao/json/external/pegtl/apply_mode.hpp | 19 - .../tao/json/external/pegtl/argv_input.hpp | 51 - include/tao/json/external/pegtl/ascii.hpp | 67 - .../tao/json/external/pegtl/buffer_input.hpp | 212 -- .../tao/json/external/pegtl/change_action.hpp | 38 - .../pegtl/change_action_and_state.hpp | 53 - .../pegtl/change_action_and_states.hpp | 62 - .../json/external/pegtl/change_control.hpp | 36 - .../tao/json/external/pegtl/change_state.hpp | 50 - .../tao/json/external/pegtl/change_states.hpp | 61 - include/tao/json/external/pegtl/config.hpp | 11 - .../tao/json/external/pegtl/contrib/abnf.hpp | 35 - .../json/external/pegtl/contrib/alphabet.hpp | 67 - .../json/external/pegtl/contrib/counter.hpp | 54 - .../tao/json/external/pegtl/contrib/http.hpp | 253 --- .../external/pegtl/contrib/icu/internal.hpp | 68 - .../json/external/pegtl/contrib/icu/utf16.hpp | 200 -- .../json/external/pegtl/contrib/icu/utf32.hpp | 200 -- .../json/external/pegtl/contrib/icu/utf8.hpp | 105 - .../json/external/pegtl/contrib/if_then.hpp | 55 - .../json/external/pegtl/contrib/integer.hpp | 446 ---- .../tao/json/external/pegtl/contrib/json.hpp | 88 - .../external/pegtl/contrib/json_pointer.hpp | 33 - .../external/pegtl/contrib/parse_tree.hpp | 561 ----- .../pegtl/contrib/parse_tree_to_dot.hpp | 104 - .../external/pegtl/contrib/raw_string.hpp | 225 -- .../pegtl/contrib/remove_first_state.hpp | 86 - .../pegtl/contrib/rep_one_min_max.hpp | 62 - .../external/pegtl/contrib/rep_string.hpp | 44 - .../json/external/pegtl/contrib/to_string.hpp | 38 - .../json/external/pegtl/contrib/tracer.hpp | 158 -- .../json/external/pegtl/contrib/unescape.hpp | 199 -- .../tao/json/external/pegtl/contrib/uri.hpp | 106 - .../tao/json/external/pegtl/cstream_input.hpp | 33 - .../json/external/pegtl/disable_action.hpp | 35 - .../tao/json/external/pegtl/discard_input.hpp | 37 - .../pegtl/discard_input_on_failure.hpp | 39 - .../pegtl/discard_input_on_success.hpp | 39 - .../tao/json/external/pegtl/enable_action.hpp | 35 - include/tao/json/external/pegtl/eol.hpp | 37 - include/tao/json/external/pegtl/eol_pair.hpp | 18 - .../tao/json/external/pegtl/file_input.hpp | 44 - .../json/external/pegtl/internal/action.hpp | 44 - .../external/pegtl/internal/action_input.hpp | 107 - .../json/external/pegtl/internal/alnum.hpp | 18 - .../json/external/pegtl/internal/alpha.hpp | 18 - .../external/pegtl/internal/always_false.hpp | 21 - .../tao/json/external/pegtl/internal/any.hpp | 58 - .../json/external/pegtl/internal/apply.hpp | 53 - .../json/external/pegtl/internal/apply0.hpp | 50 - .../external/pegtl/internal/apply0_single.hpp | 34 - .../external/pegtl/internal/apply_single.hpp | 34 - .../tao/json/external/pegtl/internal/at.hpp | 53 - .../tao/json/external/pegtl/internal/bof.hpp | 31 - .../tao/json/external/pegtl/internal/bol.hpp | 31 - .../tao/json/external/pegtl/internal/bump.hpp | 45 - .../external/pegtl/internal/bump_help.hpp | 29 - .../json/external/pegtl/internal/bytes.hpp | 36 - .../json/external/pegtl/internal/control.hpp | 44 - .../external/pegtl/internal/cr_crlf_eol.hpp | 32 - .../json/external/pegtl/internal/cr_eol.hpp | 32 - .../json/external/pegtl/internal/crlf_eol.hpp | 32 - .../pegtl/internal/cstream_reader.hpp | 49 - .../pegtl/internal/cstring_reader.hpp | 40 - .../json/external/pegtl/internal/demangle.hpp | 140 -- .../json/external/pegtl/internal/disable.hpp | 44 - .../json/external/pegtl/internal/discard.hpp | 33 - .../external/pegtl/internal/dusel_mode.hpp | 23 - .../external/pegtl/internal/duseltronik.hpp | 187 -- .../json/external/pegtl/internal/enable.hpp | 44 - .../json/external/pegtl/internal/endian.hpp | 62 - .../external/pegtl/internal/endian_gcc.hpp | 206 -- .../external/pegtl/internal/endian_win.hpp | 106 - .../tao/json/external/pegtl/internal/eof.hpp | 31 - .../tao/json/external/pegtl/internal/eol.hpp | 31 - .../tao/json/external/pegtl/internal/eolf.hpp | 32 - .../pegtl/internal/file_mapper_posix.hpp | 83 - .../pegtl/internal/file_mapper_win32.hpp | 219 -- .../external/pegtl/internal/file_opener.hpp | 72 - .../external/pegtl/internal/file_reader.hpp | 114 - .../external/pegtl/internal/has_apply.hpp | 25 - .../external/pegtl/internal/has_apply0.hpp | 25 - .../external/pegtl/internal/has_match.hpp | 56 - .../external/pegtl/internal/identifier.hpp | 22 - .../json/external/pegtl/internal/if_apply.hpp | 53 - .../json/external/pegtl/internal/if_must.hpp | 48 - .../external/pegtl/internal/if_must_else.hpp | 19 - .../external/pegtl/internal/if_then_else.hpp | 51 - .../external/pegtl/internal/input_pair.hpp | 29 - .../pegtl/internal/istream_reader.hpp | 40 - .../json/external/pegtl/internal/istring.hpp | 72 - .../json/external/pegtl/internal/iterator.hpp | 52 - .../external/pegtl/internal/lf_crlf_eol.hpp | 37 - .../json/external/pegtl/internal/lf_eol.hpp | 32 - .../tao/json/external/pegtl/internal/list.hpp | 19 - .../external/pegtl/internal/list_must.hpp | 20 - .../external/pegtl/internal/list_tail.hpp | 20 - .../external/pegtl/internal/list_tail_pad.hpp | 22 - .../json/external/pegtl/internal/marker.hpp | 82 - .../external/pegtl/internal/missing_apply.hpp | 25 - .../pegtl/internal/missing_apply0.hpp | 23 - .../tao/json/external/pegtl/internal/must.hpp | 72 - .../json/external/pegtl/internal/not_at.hpp | 53 - .../tao/json/external/pegtl/internal/one.hpp | 44 - .../tao/json/external/pegtl/internal/opt.hpp | 57 - .../tao/json/external/pegtl/internal/pad.hpp | 19 - .../json/external/pegtl/internal/pad_opt.hpp | 20 - .../external/pegtl/internal/peek_char.hpp | 32 - .../pegtl/internal/peek_mask_uint.hpp | 54 - .../pegtl/internal/peek_mask_uint8.hpp | 34 - .../external/pegtl/internal/peek_uint.hpp | 45 - .../external/pegtl/internal/peek_uint8.hpp | 33 - .../external/pegtl/internal/peek_utf16.hpp | 54 - .../external/pegtl/internal/peek_utf32.hpp | 43 - .../external/pegtl/internal/peek_utf8.hpp | 90 - .../external/pegtl/internal/pegtl_string.hpp | 90 - .../tao/json/external/pegtl/internal/plus.hpp | 53 - .../json/external/pegtl/internal/raise.hpp | 53 - .../json/external/pegtl/internal/range.hpp | 51 - .../json/external/pegtl/internal/ranges.hpp | 93 - .../external/pegtl/internal/read_uint.hpp | 77 - .../json/external/pegtl/internal/rematch.hpp | 69 - .../tao/json/external/pegtl/internal/rep.hpp | 66 - .../json/external/pegtl/internal/rep_min.hpp | 20 - .../external/pegtl/internal/rep_min_max.hpp | 79 - .../json/external/pegtl/internal/rep_opt.hpp | 46 - .../json/external/pegtl/internal/require.hpp | 42 - .../pegtl/internal/result_on_found.hpp | 19 - .../json/external/pegtl/internal/rules.hpp | 61 - .../tao/json/external/pegtl/internal/seq.hpp | 73 - .../external/pegtl/internal/skip_control.hpp | 25 - .../tao/json/external/pegtl/internal/sor.hpp | 60 - .../tao/json/external/pegtl/internal/star.hpp | 47 - .../external/pegtl/internal/star_must.hpp | 19 - .../json/external/pegtl/internal/state.hpp | 49 - .../json/external/pegtl/internal/string.hpp | 58 - .../json/external/pegtl/internal/trivial.hpp | 32 - .../pegtl/internal/try_catch_type.hpp | 64 - .../json/external/pegtl/internal/until.hpp | 84 - .../tao/json/external/pegtl/istream_input.hpp | 33 - include/tao/json/external/pegtl/match.hpp | 73 - .../tao/json/external/pegtl/memory_input.hpp | 381 ---- .../tao/json/external/pegtl/mmap_input.hpp | 79 - include/tao/json/external/pegtl/normal.hpp | 87 - include/tao/json/external/pegtl/nothing.hpp | 20 - include/tao/json/external/pegtl/parse.hpp | 53 - .../tao/json/external/pegtl/parse_error.hpp | 69 - include/tao/json/external/pegtl/position.hpp | 75 - .../tao/json/external/pegtl/read_input.hpp | 74 - .../tao/json/external/pegtl/require_apply.hpp | 16 - .../json/external/pegtl/require_apply0.hpp | 16 - .../tao/json/external/pegtl/rewind_mode.hpp | 20 - include/tao/json/external/pegtl/rules.hpp | 67 - .../tao/json/external/pegtl/string_input.hpp | 66 - .../tao/json/external/pegtl/tracking_mode.hpp | 19 - include/tao/json/external/pegtl/uint16.hpp | 62 - include/tao/json/external/pegtl/uint32.hpp | 62 - include/tao/json/external/pegtl/uint64.hpp | 63 - include/tao/json/external/pegtl/uint8.hpp | 36 - include/tao/json/external/pegtl/utf16.hpp | 49 - include/tao/json/external/pegtl/utf32.hpp | 49 - include/tao/json/external/pegtl/utf8.hpp | 28 - include/tao/json/external/pegtl/version.hpp | 13 - include/tao/json/external/ryu.hpp | 1216 ----------- include/tao/json/forward.hpp | 44 - include/tao/json/from_file.hpp | 32 - include/tao/json/from_input.hpp | 32 - include/tao/json/from_stream.hpp | 45 - include/tao/json/from_string.hpp | 41 - include/tao/json/internal/action.hpp | 268 --- include/tao/json/internal/base64.hpp | 55 - include/tao/json/internal/base64url.hpp | 53 - include/tao/json/internal/endian.hpp | 60 - include/tao/json/internal/endian_gcc.hpp | 198 -- include/tao/json/internal/endian_win.hpp | 103 - include/tao/json/internal/errors.hpp | 85 - include/tao/json/internal/escape.hpp | 77 - include/tao/json/internal/format.hpp | 59 - include/tao/json/internal/grammar.hpp | 229 -- include/tao/json/internal/hexdump.hpp | 31 - include/tao/json/internal/identity.hpp | 22 - include/tao/json/internal/number_state.hpp | 80 - include/tao/json/internal/number_traits.hpp | 267 --- include/tao/json/internal/pair.hpp | 42 - include/tao/json/internal/parse_util.hpp | 112 - include/tao/json/internal/sha256.hpp | 218 -- include/tao/json/internal/single.hpp | 40 - include/tao/json/internal/string_t.hpp | 35 - include/tao/json/internal/type_traits.hpp | 113 - include/tao/json/internal/unescape_action.hpp | 24 - include/tao/json/internal/uri_fragment.hpp | 182 -- include/tao/json/jaxn.hpp | 19 - include/tao/json/jaxn/consume_file.hpp | 34 - include/tao/json/jaxn/consume_string.hpp | 32 - include/tao/json/jaxn/events/from_file.hpp | 28 - include/tao/json/jaxn/events/from_input.hpp | 45 - include/tao/json/jaxn/events/from_stream.hpp | 33 - include/tao/json/jaxn/events/from_string.hpp | 39 - .../tao/json/jaxn/events/to_pretty_stream.hpp | 69 - include/tao/json/jaxn/events/to_stream.hpp | 67 - include/tao/json/jaxn/events/to_string.hpp | 33 - include/tao/json/jaxn/from_file.hpp | 33 - include/tao/json/jaxn/from_input.hpp | 33 - include/tao/json/jaxn/from_stream.hpp | 48 - include/tao/json/jaxn/from_string.hpp | 42 - include/tao/json/jaxn/internal/action.hpp | 355 ---- .../json/jaxn/internal/bunescape_action.hpp | 114 - include/tao/json/jaxn/internal/errors.hpp | 108 - include/tao/json/jaxn/internal/grammar.hpp | 375 ---- include/tao/json/jaxn/internal/integer.hpp | 256 --- .../json/jaxn/internal/unescape_action.hpp | 28 - include/tao/json/jaxn/is_identifier.hpp | 27 - include/tao/json/jaxn/parts_parser.hpp | 263 --- include/tao/json/jaxn/to_stream.hpp | 36 - include/tao/json/jaxn/to_string.hpp | 33 - include/tao/json/message_extension.hpp | 49 - include/tao/json/msgpack.hpp | 18 - include/tao/json/msgpack/consume_file.hpp | 34 - include/tao/json/msgpack/consume_string.hpp | 32 - include/tao/json/msgpack/events/from_file.hpp | 27 - .../tao/json/msgpack/events/from_input.hpp | 43 - .../tao/json/msgpack/events/from_string.hpp | 37 - include/tao/json/msgpack/events/to_stream.hpp | 214 -- include/tao/json/msgpack/events/to_string.hpp | 31 - include/tao/json/msgpack/from_file.hpp | 33 - include/tao/json/msgpack/from_input.hpp | 33 - include/tao/json/msgpack/from_string.hpp | 32 - include/tao/json/msgpack/internal/format.hpp | 57 - include/tao/json/msgpack/internal/grammar.hpp | 249 --- include/tao/json/msgpack/parts_parser.hpp | 311 --- include/tao/json/msgpack/to_stream.hpp | 27 - include/tao/json/msgpack/to_string.hpp | 28 - include/tao/json/operators.hpp | 494 ----- include/tao/json/parts_parser.hpp | 306 --- include/tao/json/pointer.hpp | 432 ---- include/tao/json/produce.hpp | 61 - include/tao/json/self_contained.hpp | 143 -- include/tao/json/span.hpp | 568 ----- include/tao/json/stream.hpp | 38 - include/tao/json/to_stream.hpp | 42 - include/tao/json/to_string.hpp | 23 - include/tao/json/traits.hpp | 971 --------- include/tao/json/type.hpp | 112 - include/tao/json/ubjson.hpp | 18 - include/tao/json/ubjson/consume_file.hpp | 34 - include/tao/json/ubjson/consume_string.hpp | 32 - include/tao/json/ubjson/events/from_file.hpp | 27 - include/tao/json/ubjson/events/from_input.hpp | 43 - .../tao/json/ubjson/events/from_string.hpp | 37 - include/tao/json/ubjson/events/to_stream.hpp | 174 -- include/tao/json/ubjson/events/to_string.hpp | 31 - include/tao/json/ubjson/from_file.hpp | 33 - include/tao/json/ubjson/from_input.hpp | 33 - include/tao/json/ubjson/from_string.hpp | 32 - include/tao/json/ubjson/internal/grammar.hpp | 413 ---- include/tao/json/ubjson/internal/marker.hpp | 46 - include/tao/json/ubjson/parts_parser.hpp | 393 ---- include/tao/json/ubjson/to_stream.hpp | 28 - include/tao/json/ubjson/to_string.hpp | 29 - include/tao/json/utf8.hpp | 57 - include/tao/json/value.hpp | 12 - 377 files changed, 35895 deletions(-) delete mode 100644 include/tao/json.hpp delete mode 100644 include/tao/json/basic_value.hpp delete mode 100644 include/tao/json/binary.hpp delete mode 100644 include/tao/json/binary_view.hpp delete mode 100644 include/tao/json/binding.hpp delete mode 100644 include/tao/json/binding/constant.hpp delete mode 100644 include/tao/json/binding/element.hpp delete mode 100644 include/tao/json/binding/factory.hpp delete mode 100644 include/tao/json/binding/for_nothing_value.hpp delete mode 100644 include/tao/json/binding/for_unknown_key.hpp delete mode 100644 include/tao/json/binding/inherit.hpp delete mode 100644 include/tao/json/binding/internal/array.hpp delete mode 100644 include/tao/json/binding/internal/inherit.hpp delete mode 100644 include/tao/json/binding/internal/object.hpp delete mode 100644 include/tao/json/binding/internal/type_key.hpp delete mode 100644 include/tao/json/binding/member.hpp delete mode 100644 include/tao/json/binding/member_kind.hpp delete mode 100644 include/tao/json/binding/versions.hpp delete mode 100644 include/tao/json/cbor.hpp delete mode 100644 include/tao/json/cbor/consume_file.hpp delete mode 100644 include/tao/json/cbor/consume_string.hpp delete mode 100644 include/tao/json/cbor/events/from_file.hpp delete mode 100644 include/tao/json/cbor/events/from_input.hpp delete mode 100644 include/tao/json/cbor/events/from_string.hpp delete mode 100644 include/tao/json/cbor/events/to_stream.hpp delete mode 100644 include/tao/json/cbor/events/to_string.hpp delete mode 100644 include/tao/json/cbor/from_file.hpp delete mode 100644 include/tao/json/cbor/from_input.hpp delete mode 100644 include/tao/json/cbor/from_string.hpp delete mode 100644 include/tao/json/cbor/internal/grammar.hpp delete mode 100644 include/tao/json/cbor/internal/major.hpp delete mode 100644 include/tao/json/cbor/parts_parser.hpp delete mode 100644 include/tao/json/cbor/to_stream.hpp delete mode 100644 include/tao/json/cbor/to_string.hpp delete mode 100644 include/tao/json/consume.hpp delete mode 100644 include/tao/json/consume_file.hpp delete mode 100644 include/tao/json/consume_string.hpp delete mode 100644 include/tao/json/contrib/array_traits.hpp delete mode 100644 include/tao/json/contrib/deque_traits.hpp delete mode 100644 include/tao/json/contrib/diff.hpp delete mode 100644 include/tao/json/contrib/get.hpp delete mode 100644 include/tao/json/contrib/internal/array_traits.hpp delete mode 100644 include/tao/json/contrib/internal/indirect_traits.hpp delete mode 100644 include/tao/json/contrib/internal/object_traits.hpp delete mode 100644 include/tao/json/contrib/internal/type_traits.hpp delete mode 100644 include/tao/json/contrib/list_traits.hpp delete mode 100644 include/tao/json/contrib/map_traits.hpp delete mode 100644 include/tao/json/contrib/multimap_traits.hpp delete mode 100644 include/tao/json/contrib/multiset_traits.hpp delete mode 100644 include/tao/json/contrib/pair_traits.hpp delete mode 100644 include/tao/json/contrib/patch.hpp delete mode 100644 include/tao/json/contrib/pointer_traits.hpp delete mode 100644 include/tao/json/contrib/position.hpp delete mode 100644 include/tao/json/contrib/reference.hpp delete mode 100644 include/tao/json/contrib/schema.hpp delete mode 100644 include/tao/json/contrib/set_traits.hpp delete mode 100644 include/tao/json/contrib/shared_ptr_traits.hpp delete mode 100644 include/tao/json/contrib/traits.hpp delete mode 100644 include/tao/json/contrib/tuple_traits.hpp delete mode 100644 include/tao/json/contrib/unique_ptr_traits.hpp delete mode 100644 include/tao/json/contrib/unordered_map_traits.hpp delete mode 100644 include/tao/json/contrib/unordered_set_traits.hpp delete mode 100644 include/tao/json/contrib/vector_bool_traits.hpp delete mode 100644 include/tao/json/contrib/vector_traits.hpp delete mode 100644 include/tao/json/events.hpp delete mode 100644 include/tao/json/events/apply.hpp delete mode 100644 include/tao/json/events/binary_to_base64.hpp delete mode 100644 include/tao/json/events/binary_to_base64url.hpp delete mode 100644 include/tao/json/events/binary_to_exception.hpp delete mode 100644 include/tao/json/events/binary_to_hex.hpp delete mode 100644 include/tao/json/events/compare.hpp delete mode 100644 include/tao/json/events/debug.hpp delete mode 100644 include/tao/json/events/discard.hpp delete mode 100644 include/tao/json/events/from_file.hpp delete mode 100644 include/tao/json/events/from_input.hpp delete mode 100644 include/tao/json/events/from_stream.hpp delete mode 100644 include/tao/json/events/from_string.hpp delete mode 100644 include/tao/json/events/from_value.hpp delete mode 100644 include/tao/json/events/hash.hpp delete mode 100644 include/tao/json/events/invalid_string_to_binary.hpp delete mode 100644 include/tao/json/events/invalid_string_to_exception.hpp delete mode 100644 include/tao/json/events/invalid_string_to_hex.hpp delete mode 100644 include/tao/json/events/key_camel_case_to_snake_case.hpp delete mode 100644 include/tao/json/events/key_snake_case_to_camel_case.hpp delete mode 100644 include/tao/json/events/limit_nesting_depth.hpp delete mode 100644 include/tao/json/events/limit_value_count.hpp delete mode 100644 include/tao/json/events/non_finite_to_exception.hpp delete mode 100644 include/tao/json/events/non_finite_to_null.hpp delete mode 100644 include/tao/json/events/non_finite_to_string.hpp delete mode 100644 include/tao/json/events/prefer_signed.hpp delete mode 100644 include/tao/json/events/prefer_unsigned.hpp delete mode 100644 include/tao/json/events/produce.hpp delete mode 100644 include/tao/json/events/ref.hpp delete mode 100644 include/tao/json/events/statistics.hpp delete mode 100644 include/tao/json/events/tee.hpp delete mode 100644 include/tao/json/events/to_pretty_stream.hpp delete mode 100644 include/tao/json/events/to_stream.hpp delete mode 100644 include/tao/json/events/to_string.hpp delete mode 100644 include/tao/json/events/to_value.hpp delete mode 100644 include/tao/json/events/transformer.hpp delete mode 100644 include/tao/json/events/validate_event_order.hpp delete mode 100644 include/tao/json/events/validate_keys.hpp delete mode 100644 include/tao/json/events/virtual_base.hpp delete mode 100644 include/tao/json/events/virtual_ref.hpp delete mode 100644 include/tao/json/external/double.hpp delete mode 100644 include/tao/json/external/itoa.hpp delete mode 100644 include/tao/json/external/pegtl.hpp delete mode 100644 include/tao/json/external/pegtl/analysis/analyze_cycles.hpp delete mode 100644 include/tao/json/external/pegtl/analysis/counted.hpp delete mode 100644 include/tao/json/external/pegtl/analysis/generic.hpp delete mode 100644 include/tao/json/external/pegtl/analysis/grammar_info.hpp delete mode 100644 include/tao/json/external/pegtl/analysis/insert_guard.hpp delete mode 100644 include/tao/json/external/pegtl/analysis/insert_rules.hpp delete mode 100644 include/tao/json/external/pegtl/analysis/rule_info.hpp delete mode 100644 include/tao/json/external/pegtl/analysis/rule_type.hpp delete mode 100644 include/tao/json/external/pegtl/analyze.hpp delete mode 100644 include/tao/json/external/pegtl/apply_mode.hpp delete mode 100644 include/tao/json/external/pegtl/argv_input.hpp delete mode 100644 include/tao/json/external/pegtl/ascii.hpp delete mode 100644 include/tao/json/external/pegtl/buffer_input.hpp delete mode 100644 include/tao/json/external/pegtl/change_action.hpp delete mode 100644 include/tao/json/external/pegtl/change_action_and_state.hpp delete mode 100644 include/tao/json/external/pegtl/change_action_and_states.hpp delete mode 100644 include/tao/json/external/pegtl/change_control.hpp delete mode 100644 include/tao/json/external/pegtl/change_state.hpp delete mode 100644 include/tao/json/external/pegtl/change_states.hpp delete mode 100644 include/tao/json/external/pegtl/config.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/abnf.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/alphabet.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/counter.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/http.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/icu/internal.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/icu/utf16.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/icu/utf32.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/icu/utf8.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/if_then.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/integer.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/json.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/json_pointer.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/parse_tree.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/parse_tree_to_dot.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/raw_string.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/remove_first_state.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/rep_one_min_max.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/rep_string.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/to_string.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/tracer.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/unescape.hpp delete mode 100644 include/tao/json/external/pegtl/contrib/uri.hpp delete mode 100644 include/tao/json/external/pegtl/cstream_input.hpp delete mode 100644 include/tao/json/external/pegtl/disable_action.hpp delete mode 100644 include/tao/json/external/pegtl/discard_input.hpp delete mode 100644 include/tao/json/external/pegtl/discard_input_on_failure.hpp delete mode 100644 include/tao/json/external/pegtl/discard_input_on_success.hpp delete mode 100644 include/tao/json/external/pegtl/enable_action.hpp delete mode 100644 include/tao/json/external/pegtl/eol.hpp delete mode 100644 include/tao/json/external/pegtl/eol_pair.hpp delete mode 100644 include/tao/json/external/pegtl/file_input.hpp delete mode 100644 include/tao/json/external/pegtl/internal/action.hpp delete mode 100644 include/tao/json/external/pegtl/internal/action_input.hpp delete mode 100644 include/tao/json/external/pegtl/internal/alnum.hpp delete mode 100644 include/tao/json/external/pegtl/internal/alpha.hpp delete mode 100644 include/tao/json/external/pegtl/internal/always_false.hpp delete mode 100644 include/tao/json/external/pegtl/internal/any.hpp delete mode 100644 include/tao/json/external/pegtl/internal/apply.hpp delete mode 100644 include/tao/json/external/pegtl/internal/apply0.hpp delete mode 100644 include/tao/json/external/pegtl/internal/apply0_single.hpp delete mode 100644 include/tao/json/external/pegtl/internal/apply_single.hpp delete mode 100644 include/tao/json/external/pegtl/internal/at.hpp delete mode 100644 include/tao/json/external/pegtl/internal/bof.hpp delete mode 100644 include/tao/json/external/pegtl/internal/bol.hpp delete mode 100644 include/tao/json/external/pegtl/internal/bump.hpp delete mode 100644 include/tao/json/external/pegtl/internal/bump_help.hpp delete mode 100644 include/tao/json/external/pegtl/internal/bytes.hpp delete mode 100644 include/tao/json/external/pegtl/internal/control.hpp delete mode 100644 include/tao/json/external/pegtl/internal/cr_crlf_eol.hpp delete mode 100644 include/tao/json/external/pegtl/internal/cr_eol.hpp delete mode 100644 include/tao/json/external/pegtl/internal/crlf_eol.hpp delete mode 100644 include/tao/json/external/pegtl/internal/cstream_reader.hpp delete mode 100644 include/tao/json/external/pegtl/internal/cstring_reader.hpp delete mode 100644 include/tao/json/external/pegtl/internal/demangle.hpp delete mode 100644 include/tao/json/external/pegtl/internal/disable.hpp delete mode 100644 include/tao/json/external/pegtl/internal/discard.hpp delete mode 100644 include/tao/json/external/pegtl/internal/dusel_mode.hpp delete mode 100644 include/tao/json/external/pegtl/internal/duseltronik.hpp delete mode 100644 include/tao/json/external/pegtl/internal/enable.hpp delete mode 100644 include/tao/json/external/pegtl/internal/endian.hpp delete mode 100644 include/tao/json/external/pegtl/internal/endian_gcc.hpp delete mode 100644 include/tao/json/external/pegtl/internal/endian_win.hpp delete mode 100644 include/tao/json/external/pegtl/internal/eof.hpp delete mode 100644 include/tao/json/external/pegtl/internal/eol.hpp delete mode 100644 include/tao/json/external/pegtl/internal/eolf.hpp delete mode 100644 include/tao/json/external/pegtl/internal/file_mapper_posix.hpp delete mode 100644 include/tao/json/external/pegtl/internal/file_mapper_win32.hpp delete mode 100644 include/tao/json/external/pegtl/internal/file_opener.hpp delete mode 100644 include/tao/json/external/pegtl/internal/file_reader.hpp delete mode 100644 include/tao/json/external/pegtl/internal/has_apply.hpp delete mode 100644 include/tao/json/external/pegtl/internal/has_apply0.hpp delete mode 100644 include/tao/json/external/pegtl/internal/has_match.hpp delete mode 100644 include/tao/json/external/pegtl/internal/identifier.hpp delete mode 100644 include/tao/json/external/pegtl/internal/if_apply.hpp delete mode 100644 include/tao/json/external/pegtl/internal/if_must.hpp delete mode 100644 include/tao/json/external/pegtl/internal/if_must_else.hpp delete mode 100644 include/tao/json/external/pegtl/internal/if_then_else.hpp delete mode 100644 include/tao/json/external/pegtl/internal/input_pair.hpp delete mode 100644 include/tao/json/external/pegtl/internal/istream_reader.hpp delete mode 100644 include/tao/json/external/pegtl/internal/istring.hpp delete mode 100644 include/tao/json/external/pegtl/internal/iterator.hpp delete mode 100644 include/tao/json/external/pegtl/internal/lf_crlf_eol.hpp delete mode 100644 include/tao/json/external/pegtl/internal/lf_eol.hpp delete mode 100644 include/tao/json/external/pegtl/internal/list.hpp delete mode 100644 include/tao/json/external/pegtl/internal/list_must.hpp delete mode 100644 include/tao/json/external/pegtl/internal/list_tail.hpp delete mode 100644 include/tao/json/external/pegtl/internal/list_tail_pad.hpp delete mode 100644 include/tao/json/external/pegtl/internal/marker.hpp delete mode 100644 include/tao/json/external/pegtl/internal/missing_apply.hpp delete mode 100644 include/tao/json/external/pegtl/internal/missing_apply0.hpp delete mode 100644 include/tao/json/external/pegtl/internal/must.hpp delete mode 100644 include/tao/json/external/pegtl/internal/not_at.hpp delete mode 100644 include/tao/json/external/pegtl/internal/one.hpp delete mode 100644 include/tao/json/external/pegtl/internal/opt.hpp delete mode 100644 include/tao/json/external/pegtl/internal/pad.hpp delete mode 100644 include/tao/json/external/pegtl/internal/pad_opt.hpp delete mode 100644 include/tao/json/external/pegtl/internal/peek_char.hpp delete mode 100644 include/tao/json/external/pegtl/internal/peek_mask_uint.hpp delete mode 100644 include/tao/json/external/pegtl/internal/peek_mask_uint8.hpp delete mode 100644 include/tao/json/external/pegtl/internal/peek_uint.hpp delete mode 100644 include/tao/json/external/pegtl/internal/peek_uint8.hpp delete mode 100644 include/tao/json/external/pegtl/internal/peek_utf16.hpp delete mode 100644 include/tao/json/external/pegtl/internal/peek_utf32.hpp delete mode 100644 include/tao/json/external/pegtl/internal/peek_utf8.hpp delete mode 100644 include/tao/json/external/pegtl/internal/pegtl_string.hpp delete mode 100644 include/tao/json/external/pegtl/internal/plus.hpp delete mode 100644 include/tao/json/external/pegtl/internal/raise.hpp delete mode 100644 include/tao/json/external/pegtl/internal/range.hpp delete mode 100644 include/tao/json/external/pegtl/internal/ranges.hpp delete mode 100644 include/tao/json/external/pegtl/internal/read_uint.hpp delete mode 100644 include/tao/json/external/pegtl/internal/rematch.hpp delete mode 100644 include/tao/json/external/pegtl/internal/rep.hpp delete mode 100644 include/tao/json/external/pegtl/internal/rep_min.hpp delete mode 100644 include/tao/json/external/pegtl/internal/rep_min_max.hpp delete mode 100644 include/tao/json/external/pegtl/internal/rep_opt.hpp delete mode 100644 include/tao/json/external/pegtl/internal/require.hpp delete mode 100644 include/tao/json/external/pegtl/internal/result_on_found.hpp delete mode 100644 include/tao/json/external/pegtl/internal/rules.hpp delete mode 100644 include/tao/json/external/pegtl/internal/seq.hpp delete mode 100644 include/tao/json/external/pegtl/internal/skip_control.hpp delete mode 100644 include/tao/json/external/pegtl/internal/sor.hpp delete mode 100644 include/tao/json/external/pegtl/internal/star.hpp delete mode 100644 include/tao/json/external/pegtl/internal/star_must.hpp delete mode 100644 include/tao/json/external/pegtl/internal/state.hpp delete mode 100644 include/tao/json/external/pegtl/internal/string.hpp delete mode 100644 include/tao/json/external/pegtl/internal/trivial.hpp delete mode 100644 include/tao/json/external/pegtl/internal/try_catch_type.hpp delete mode 100644 include/tao/json/external/pegtl/internal/until.hpp delete mode 100644 include/tao/json/external/pegtl/istream_input.hpp delete mode 100644 include/tao/json/external/pegtl/match.hpp delete mode 100644 include/tao/json/external/pegtl/memory_input.hpp delete mode 100644 include/tao/json/external/pegtl/mmap_input.hpp delete mode 100644 include/tao/json/external/pegtl/normal.hpp delete mode 100644 include/tao/json/external/pegtl/nothing.hpp delete mode 100644 include/tao/json/external/pegtl/parse.hpp delete mode 100644 include/tao/json/external/pegtl/parse_error.hpp delete mode 100644 include/tao/json/external/pegtl/position.hpp delete mode 100644 include/tao/json/external/pegtl/read_input.hpp delete mode 100644 include/tao/json/external/pegtl/require_apply.hpp delete mode 100644 include/tao/json/external/pegtl/require_apply0.hpp delete mode 100644 include/tao/json/external/pegtl/rewind_mode.hpp delete mode 100644 include/tao/json/external/pegtl/rules.hpp delete mode 100644 include/tao/json/external/pegtl/string_input.hpp delete mode 100644 include/tao/json/external/pegtl/tracking_mode.hpp delete mode 100644 include/tao/json/external/pegtl/uint16.hpp delete mode 100644 include/tao/json/external/pegtl/uint32.hpp delete mode 100644 include/tao/json/external/pegtl/uint64.hpp delete mode 100644 include/tao/json/external/pegtl/uint8.hpp delete mode 100644 include/tao/json/external/pegtl/utf16.hpp delete mode 100644 include/tao/json/external/pegtl/utf32.hpp delete mode 100644 include/tao/json/external/pegtl/utf8.hpp delete mode 100644 include/tao/json/external/pegtl/version.hpp delete mode 100644 include/tao/json/external/ryu.hpp delete mode 100644 include/tao/json/forward.hpp delete mode 100644 include/tao/json/from_file.hpp delete mode 100644 include/tao/json/from_input.hpp delete mode 100644 include/tao/json/from_stream.hpp delete mode 100644 include/tao/json/from_string.hpp delete mode 100644 include/tao/json/internal/action.hpp delete mode 100644 include/tao/json/internal/base64.hpp delete mode 100644 include/tao/json/internal/base64url.hpp delete mode 100644 include/tao/json/internal/endian.hpp delete mode 100644 include/tao/json/internal/endian_gcc.hpp delete mode 100644 include/tao/json/internal/endian_win.hpp delete mode 100644 include/tao/json/internal/errors.hpp delete mode 100644 include/tao/json/internal/escape.hpp delete mode 100644 include/tao/json/internal/format.hpp delete mode 100644 include/tao/json/internal/grammar.hpp delete mode 100644 include/tao/json/internal/hexdump.hpp delete mode 100644 include/tao/json/internal/identity.hpp delete mode 100644 include/tao/json/internal/number_state.hpp delete mode 100644 include/tao/json/internal/number_traits.hpp delete mode 100644 include/tao/json/internal/pair.hpp delete mode 100644 include/tao/json/internal/parse_util.hpp delete mode 100644 include/tao/json/internal/sha256.hpp delete mode 100644 include/tao/json/internal/single.hpp delete mode 100644 include/tao/json/internal/string_t.hpp delete mode 100644 include/tao/json/internal/type_traits.hpp delete mode 100644 include/tao/json/internal/unescape_action.hpp delete mode 100644 include/tao/json/internal/uri_fragment.hpp delete mode 100644 include/tao/json/jaxn.hpp delete mode 100644 include/tao/json/jaxn/consume_file.hpp delete mode 100644 include/tao/json/jaxn/consume_string.hpp delete mode 100644 include/tao/json/jaxn/events/from_file.hpp delete mode 100644 include/tao/json/jaxn/events/from_input.hpp delete mode 100644 include/tao/json/jaxn/events/from_stream.hpp delete mode 100644 include/tao/json/jaxn/events/from_string.hpp delete mode 100644 include/tao/json/jaxn/events/to_pretty_stream.hpp delete mode 100644 include/tao/json/jaxn/events/to_stream.hpp delete mode 100644 include/tao/json/jaxn/events/to_string.hpp delete mode 100644 include/tao/json/jaxn/from_file.hpp delete mode 100644 include/tao/json/jaxn/from_input.hpp delete mode 100644 include/tao/json/jaxn/from_stream.hpp delete mode 100644 include/tao/json/jaxn/from_string.hpp delete mode 100644 include/tao/json/jaxn/internal/action.hpp delete mode 100644 include/tao/json/jaxn/internal/bunescape_action.hpp delete mode 100644 include/tao/json/jaxn/internal/errors.hpp delete mode 100644 include/tao/json/jaxn/internal/grammar.hpp delete mode 100644 include/tao/json/jaxn/internal/integer.hpp delete mode 100644 include/tao/json/jaxn/internal/unescape_action.hpp delete mode 100644 include/tao/json/jaxn/is_identifier.hpp delete mode 100644 include/tao/json/jaxn/parts_parser.hpp delete mode 100644 include/tao/json/jaxn/to_stream.hpp delete mode 100644 include/tao/json/jaxn/to_string.hpp delete mode 100644 include/tao/json/message_extension.hpp delete mode 100644 include/tao/json/msgpack.hpp delete mode 100644 include/tao/json/msgpack/consume_file.hpp delete mode 100644 include/tao/json/msgpack/consume_string.hpp delete mode 100644 include/tao/json/msgpack/events/from_file.hpp delete mode 100644 include/tao/json/msgpack/events/from_input.hpp delete mode 100644 include/tao/json/msgpack/events/from_string.hpp delete mode 100644 include/tao/json/msgpack/events/to_stream.hpp delete mode 100644 include/tao/json/msgpack/events/to_string.hpp delete mode 100644 include/tao/json/msgpack/from_file.hpp delete mode 100644 include/tao/json/msgpack/from_input.hpp delete mode 100644 include/tao/json/msgpack/from_string.hpp delete mode 100644 include/tao/json/msgpack/internal/format.hpp delete mode 100644 include/tao/json/msgpack/internal/grammar.hpp delete mode 100644 include/tao/json/msgpack/parts_parser.hpp delete mode 100644 include/tao/json/msgpack/to_stream.hpp delete mode 100644 include/tao/json/msgpack/to_string.hpp delete mode 100644 include/tao/json/operators.hpp delete mode 100644 include/tao/json/parts_parser.hpp delete mode 100644 include/tao/json/pointer.hpp delete mode 100644 include/tao/json/produce.hpp delete mode 100644 include/tao/json/self_contained.hpp delete mode 100644 include/tao/json/span.hpp delete mode 100644 include/tao/json/stream.hpp delete mode 100644 include/tao/json/to_stream.hpp delete mode 100644 include/tao/json/to_string.hpp delete mode 100644 include/tao/json/traits.hpp delete mode 100644 include/tao/json/type.hpp delete mode 100644 include/tao/json/ubjson.hpp delete mode 100644 include/tao/json/ubjson/consume_file.hpp delete mode 100644 include/tao/json/ubjson/consume_string.hpp delete mode 100644 include/tao/json/ubjson/events/from_file.hpp delete mode 100644 include/tao/json/ubjson/events/from_input.hpp delete mode 100644 include/tao/json/ubjson/events/from_string.hpp delete mode 100644 include/tao/json/ubjson/events/to_stream.hpp delete mode 100644 include/tao/json/ubjson/events/to_string.hpp delete mode 100644 include/tao/json/ubjson/from_file.hpp delete mode 100644 include/tao/json/ubjson/from_input.hpp delete mode 100644 include/tao/json/ubjson/from_string.hpp delete mode 100644 include/tao/json/ubjson/internal/grammar.hpp delete mode 100644 include/tao/json/ubjson/internal/marker.hpp delete mode 100644 include/tao/json/ubjson/parts_parser.hpp delete mode 100644 include/tao/json/ubjson/to_stream.hpp delete mode 100644 include/tao/json/ubjson/to_string.hpp delete mode 100644 include/tao/json/utf8.hpp delete mode 100644 include/tao/json/value.hpp diff --git a/include/tao/json.hpp b/include/tao/json.hpp deleted file mode 100644 index 716c976e..00000000 --- a/include/tao/json.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_HPP -#define TAO_JSON_HPP - -// Value Class -#include "json/value.hpp" - -// Value Reading -#include "json/from_file.hpp" -#include "json/from_input.hpp" -#include "json/from_stream.hpp" -#include "json/from_string.hpp" -#include "json/parts_parser.hpp" - -// Value Writing -#include "json/stream.hpp" // operator<< -#include "json/to_stream.hpp" -#include "json/to_string.hpp" - -// Value Support -#include "json/operators.hpp" -#include "json/self_contained.hpp" - -// Custom Types -#include "json/binding.hpp" -#include "json/consume.hpp" -#include "json/consume_file.hpp" -#include "json/consume_string.hpp" -#include "json/produce.hpp" - -// Binary Literals -#include "json/binary.hpp" - -// Other Formats -#include "json/cbor.hpp" -#include "json/jaxn.hpp" -#include "json/msgpack.hpp" -#include "json/ubjson.hpp" - -// Events Implementations -#include "json/events.hpp" - -#endif diff --git a/include/tao/json/basic_value.hpp b/include/tao/json/basic_value.hpp deleted file mode 100644 index 612bc903..00000000 --- a/include/tao/json/basic_value.hpp +++ /dev/null @@ -1,941 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_BASIC_VALUE_HPP -#define TAO_JSON_BASIC_VALUE_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "events/virtual_base.hpp" - -#include "internal/escape.hpp" -#include "internal/format.hpp" -#include "internal/identity.hpp" -#include "internal/pair.hpp" -#include "internal/single.hpp" -#include "internal/type_traits.hpp" - -#include "binary.hpp" -#include "binary_view.hpp" -#include "forward.hpp" -#include "message_extension.hpp" -#include "pointer.hpp" -#include "type.hpp" - -namespace tao::json -{ - template< template< typename... > class Traits > - class basic_value - : public Traits< void >::template public_base< basic_value< Traits > > - { - public: - using public_base_t = typename Traits< void >::template public_base< basic_value< Traits > >; - - static_assert( std::is_nothrow_destructible_v< public_base_t > ); - - using array_t = std::vector< basic_value >; - using object_t = std::map< std::string, basic_value, std::less<> >; - - private: - using variant_t = std::variant< uninitialized_t, - null_t, - bool, - std::int64_t, - std::uint64_t, - double, - std::string, - std::string_view, - tao::binary, - tao::binary_view, - array_t, - object_t, - const basic_value*, - internal::opaque_ptr_t >; - - static_assert( std::is_nothrow_destructible_v< variant_t > ); - - variant_t m_variant; - - public: - basic_value() = default; - - basic_value( const basic_value& r ) = default; - basic_value( basic_value&& r ) = default; - -#if( __cplusplus > 201703L ) - - template< typename T, - typename D = std::decay_t< T >, - typename = decltype( Traits< D >::assign( std::declval< basic_value& >(), std::declval< T&& >() ) ) > - explicit( !internal::enable_implicit_constructor< Traits, D > ) basic_value( T&& v, public_base_t b = public_base_t() ) noexcept( noexcept( Traits< D >::assign( std::declval< basic_value& >(), std::forward< T >( v ) ) ) && std::is_nothrow_move_assignable_v< public_base_t > ) - : public_base_t( std::move( b ) ) - { - Traits< D >::assign( *this, std::forward< T >( v ) ); - } - -#else - - template< typename T, - typename D = std::decay_t< T >, - typename = std::enable_if_t< internal::enable_implicit_constructor< Traits, D > >, - typename = decltype( Traits< D >::assign( std::declval< basic_value& >(), std::declval< T&& >() ) ) > - basic_value( T&& v, public_base_t b = public_base_t() ) noexcept( noexcept( Traits< D >::assign( std::declval< basic_value& >(), std::forward< T >( v ) ) ) && std::is_nothrow_move_assignable_v< public_base_t > ) - : public_base_t( std::move( b ) ) - { - Traits< D >::assign( *this, std::forward< T >( v ) ); - } - - template< typename T, - typename D = std::decay_t< T >, - typename = std::enable_if_t< !internal::enable_implicit_constructor< Traits, D > >, - typename = decltype( Traits< D >::assign( std::declval< basic_value& >(), std::declval< T&& >() ) ), - int = 0 > - explicit basic_value( T&& v, public_base_t b = public_base_t() ) noexcept( noexcept( Traits< D >::assign( std::declval< basic_value& >(), std::forward< T >( v ) ) ) && std::is_nothrow_move_assignable_v< public_base_t > ) - : public_base_t( std::move( b ) ) - { - Traits< D >::assign( *this, std::forward< T >( v ) ); - } - -#endif - - basic_value( std::initializer_list< internal::pair< Traits > >&& l, public_base_t b = public_base_t() ) - : public_base_t( std::move( b ) ) - { - assign( std::move( l ) ); - } - - basic_value( const std::initializer_list< internal::pair< Traits > >& l, public_base_t b = public_base_t() ) - : public_base_t( std::move( b ) ) - { - assign( l ); - } - - basic_value( std::initializer_list< internal::pair< Traits > >& l, public_base_t b = public_base_t() ) - : basic_value( static_cast< const std::initializer_list< internal::pair< Traits > >& >( l ), std::move( b ) ) - {} - - ~basic_value() = default; - - [[nodiscard]] static basic_value array( std::initializer_list< internal::single< Traits > >&& l, public_base_t b = public_base_t() ) - { - basic_value v( uninitialized, std::move( b ) ); - v.append( std::move( l ) ); - return v; - } - - [[nodiscard]] static basic_value array( const std::initializer_list< internal::single< Traits > >& l, public_base_t b = public_base_t() ) - { - basic_value v( uninitialized, std::move( b ) ); - v.append( l ); - return v; - } - - [[nodiscard]] static basic_value object( std::initializer_list< internal::pair< Traits > >&& l, public_base_t b = public_base_t() ) - { - basic_value v( uninitialized, std::move( b ) ); - v.insert( std::move( l ) ); - return v; - } - - [[nodiscard]] static basic_value object( const std::initializer_list< internal::pair< Traits > >& l, public_base_t b = public_base_t() ) - { - basic_value v( uninitialized, std::move( b ) ); - v.insert( l ); - return v; - } - - basic_value& operator=( basic_value v ) noexcept( std::is_nothrow_move_assignable_v< variant_t >&& std::is_nothrow_move_assignable_v< public_base_t > ) - { - m_variant = std::move( v.m_variant ); - public_base_t::operator=( static_cast< public_base_t&& >( v ) ); - return *this; - } - - [[nodiscard]] public_base_t& public_base() noexcept - { - return static_cast< public_base_t& >( *this ); - } - - [[nodiscard]] const public_base_t& public_base() const noexcept - { - return static_cast< const public_base_t& >( *this ); - } - - [[nodiscard]] json::type type() const noexcept - { - return static_cast< json::type >( m_variant.index() ); - } - - [[nodiscard]] explicit operator bool() const noexcept - { - return !is_uninitialized(); - } - - [[nodiscard]] bool is_uninitialized() const noexcept - { - return std::holds_alternative< uninitialized_t >( m_variant ); - } - - [[nodiscard]] bool is_null() const noexcept - { - return std::holds_alternative< null_t >( m_variant ); - } - - [[nodiscard]] bool is_boolean() const noexcept - { - return std::holds_alternative< bool >( m_variant ); - } - - [[nodiscard]] bool is_signed() const noexcept - { - return std::holds_alternative< std::int64_t >( m_variant ); - } - - [[nodiscard]] bool is_unsigned() const noexcept - { - return std::holds_alternative< std::uint64_t >( m_variant ); - } - - [[nodiscard]] bool is_integer() const noexcept - { - return is_signed() || is_unsigned(); - } - - [[nodiscard]] bool is_double() const noexcept - { - return std::holds_alternative< double >( m_variant ); - } - - [[nodiscard]] bool is_number() const noexcept - { - return is_integer() || is_double(); - } - - [[nodiscard]] bool is_string() const noexcept - { - return std::holds_alternative< std::string >( m_variant ); - } - - [[nodiscard]] bool is_string_view() const noexcept - { - return std::holds_alternative< std::string_view >( m_variant ); - } - - [[nodiscard]] bool is_string_type() const noexcept - { - return is_string() || is_string_view(); - } - - [[nodiscard]] bool is_binary() const noexcept - { - return std::holds_alternative< binary >( m_variant ); - } - - [[nodiscard]] bool is_binary_view() const noexcept - { - return std::holds_alternative< tao::binary_view >( m_variant ); - } - - [[nodiscard]] bool is_binary_type() const noexcept - { - return is_binary() || is_binary_view(); - } - - [[nodiscard]] bool is_array() const noexcept - { - return std::holds_alternative< array_t >( m_variant ); - } - - [[nodiscard]] bool is_object() const noexcept - { - return std::holds_alternative< object_t >( m_variant ); - } - - [[nodiscard]] bool is_value_ptr() const noexcept - { - return std::holds_alternative< const basic_value* >( m_variant ); - } - - [[nodiscard]] bool is_opaque_ptr() const noexcept - { - return std::holds_alternative< internal::opaque_ptr_t >( m_variant ); - } - - [[nodiscard]] bool get_boolean() const - { - return std::get< bool >( m_variant ); - } - - [[nodiscard]] std::int64_t get_signed() const - { - return std::get< std::int64_t >( m_variant ); - } - - [[nodiscard]] std::uint64_t get_unsigned() const - { - return std::get< std::uint64_t >( m_variant ); - } - - [[nodiscard]] double get_double() const - { - return std::get< double >( m_variant ); - } - - [[nodiscard]] std::string& get_string() - { - return std::get< std::string >( m_variant ); - } - - [[nodiscard]] const std::string& get_string() const - { - return std::get< std::string >( m_variant ); - } - - [[nodiscard]] std::string_view get_string_view() const - { - return std::get< std::string_view >( m_variant ); - } - - [[nodiscard]] std::string_view get_string_type() const - { - return is_string() ? get_string() : get_string_view(); - } - - [[nodiscard]] binary& get_binary() - { - return std::get< binary >( m_variant ); - } - - [[nodiscard]] const binary& get_binary() const - { - return std::get< binary >( m_variant ); - } - - [[nodiscard]] tao::binary_view get_binary_view() const - { - return std::get< tao::binary_view >( m_variant ); - } - - [[nodiscard]] tao::binary_view get_binary_type() const - { - return is_binary() ? get_binary() : get_binary_view(); - } - - [[nodiscard]] array_t& get_array() - { - return std::get< array_t >( m_variant ); - } - - [[nodiscard]] const array_t& get_array() const - { - return std::get< array_t >( m_variant ); - } - - [[nodiscard]] object_t& get_object() - { - return std::get< object_t >( m_variant ); - } - - [[nodiscard]] const object_t& get_object() const - { - return std::get< object_t >( m_variant ); - } - - [[nodiscard]] const basic_value* get_value_ptr() const - { - return std::get< const basic_value* >( m_variant ); - } - - [[nodiscard]] internal::opaque_ptr_t get_opaque_ptr() const - { - return std::get< internal::opaque_ptr_t >( m_variant ); - } - - private: - void throw_duplicate_key_exception( const std::string_view k ) const - { - throw std::runtime_error( internal::format( "duplicate JSON object key \"", internal::escape( k ), '"', json::message_extension( *this ) ) ); - } - - void throw_index_out_of_bound_exception( const std::size_t i ) const - { - throw std::out_of_range( internal::format( "JSON array index '", i, "' out of bound '", get_array().size(), '\'', json::message_extension( *this ) ) ); - } - - void throw_key_not_found_exception( const std::string_view k ) const - { - throw std::out_of_range( internal::format( "JSON object key \"", internal::escape( k ), "\" not found", json::message_extension( *this ) ) ); - } - - public: - void set_uninitialized() noexcept - { - m_variant = uninitialized; - } - - void set_null() noexcept - { - m_variant = null; - } - - void set_boolean( const bool b ) noexcept - { - m_variant = b; - } - - void set_signed( const std::int64_t i ) noexcept - { - m_variant = i; - } - - void set_unsigned( const std::uint64_t u ) noexcept - { - m_variant = u; - } - - void set_double( const double d ) noexcept - { - m_variant = d; - } - - template< typename... Ts > - std::string& emplace_string( Ts&&... ts ) noexcept( noexcept( std::string( std::forward< Ts >( ts )... ) ) ) - { - return m_variant.template emplace< std::string >( std::forward< Ts >( ts )... ); - } - - void set_string( const std::string& s ) - { - m_variant = s; - } - - void set_string( std::string&& s ) noexcept - { - m_variant = std::move( s ); - } - - void set_string_view( const std::string_view sv ) noexcept - { - m_variant = sv; - } - - template< typename... Ts > - binary& emplace_binary( Ts&&... ts ) noexcept( noexcept( binary( std::forward< Ts >( ts )... ) ) ) - { - return m_variant.template emplace< binary >( std::forward< Ts >( ts )... ); - } - - void set_binary( const binary& x ) - { - m_variant = x; - } - - void set_binary( binary&& x ) noexcept - { - m_variant = std::move( x ); - } - - void set_binary_view( const tao::binary_view xv ) noexcept - { - m_variant = xv; - } - - template< typename... Ts > - array_t& emplace_array( Ts&&... ts ) noexcept( noexcept( array_t( std::forward< Ts >( ts )... ) ) ) - { - return m_variant.template emplace< array_t >( std::forward< Ts >( ts )... ); - } - - void set_array( const array_t& a ) - { - m_variant = a; - } - - void set_array( array_t&& a ) noexcept( std::is_nothrow_move_assignable_v< array_t > ) - { - m_variant = std::move( a ); - } - - array_t& prepare_array() - { - return is_uninitialized() ? emplace_array() : get_array(); - } - - void push_back( const basic_value& v ) - { - prepare_array().push_back( v ); - } - - void push_back( basic_value&& v ) - { - prepare_array().push_back( std::move( v ) ); - } - - template< typename... Ts > - basic_value& emplace_back( Ts&&... ts ) - { - return prepare_array().emplace_back( std::forward< Ts >( ts )... ); - } - - template< typename... Ts > - object_t& emplace_object( Ts&&... ts ) noexcept( noexcept( object_t( std::forward< Ts >( ts )... ) ) ) - { - return m_variant.template emplace< object_t >( std::forward< Ts >( ts )... ); - } - - void set_object( const object_t& o ) - { - m_variant = o; - } - - void set_object( object_t&& o ) noexcept( std::is_nothrow_move_assignable_v< object_t > ) - { - m_variant = std::move( o ); - } - - object_t& prepare_object() - { - return is_uninitialized() ? emplace_object() : get_object(); - } - - template< typename... Ts > - auto try_emplace( Ts&&... ts ) - { - auto r = prepare_object().try_emplace( std::forward< Ts >( ts )... ); - if( !r.second ) { - throw_duplicate_key_exception( r.first->first ); - } - return r; - } - - auto insert( typename object_t::value_type&& t ) - { - return prepare_object().emplace( std::move( t ) ); - } - - auto insert( const typename object_t::value_type& t ) - { - return prepare_object().emplace( t ); - } - - void set_value_ptr( const basic_value* p ) noexcept - { - assert( p ); - m_variant = p; - } - - template< typename T > - void set_opaque_ptr( const T* data, const producer_t producer ) noexcept - { - assert( data ); - assert( producer ); - m_variant = internal::opaque_ptr_t{ data, producer }; - } - - template< typename T > - void set_opaque_ptr( const T* data ) noexcept - { - set_opaque_ptr( data, &basic_value::produce_from_opaque_ptr< T > ); - } - - template< typename T > - void assign( T&& v ) noexcept( noexcept( Traits< std::decay_t< T > >::assign( std::declval< basic_value& >(), std::forward< T >( v ) ) ) ) - { - Traits< std::decay_t< T > >::assign( *this, std::forward< T >( v ) ); - } - - template< typename T > - void assign( T&& v, public_base_t b ) noexcept( noexcept( Traits< std::decay_t< T > >::assign( std::declval< basic_value& >(), std::forward< T >( v ) ) ) && std::is_nothrow_move_assignable_v< public_base_t > ) - { - Traits< std::decay_t< T > >::assign( *this, std::forward< T >( v ) ); - public_base() = std::move( b ); - } - - void assign( std::initializer_list< internal::pair< Traits > >&& l ) - { - emplace_object(); - for( auto& e : l ) { - try_emplace( std::move( e.key ), std::move( e.value ) ); - } - } - - void assign( const std::initializer_list< internal::pair< Traits > >& l ) - { - emplace_object(); - for( const auto& e : l ) { - try_emplace( e.key, e.value ); - } - } - - void assign( std::initializer_list< internal::pair< Traits > >& l ) - { - assign( static_cast< const std::initializer_list< internal::pair< Traits > >& >( l ) ); - } - - void append( std::initializer_list< internal::single< Traits > >&& l ) - { - auto& v = prepare_array(); - v.reserve( v.size() + l.size() ); - for( auto& e : l ) { - v.push_back( std::move( e.value ) ); - } - } - - void append( const std::initializer_list< internal::single< Traits > >& l ) - { - auto& v = prepare_array(); - v.reserve( v.size() + l.size() ); - for( const auto& e : l ) { - v.push_back( e.value ); - } - } - - void insert( std::initializer_list< internal::pair< Traits > >&& l ) - { - prepare_object(); - for( auto& e : l ) { - try_emplace( std::move( e.key ), std::move( e.value ) ); - } - } - - void insert( const std::initializer_list< internal::pair< Traits > >& l ) - { - prepare_object(); - for( const auto& e : l ) { - try_emplace( e.key, e.value ); - } - } - - [[nodiscard]] const basic_value& skip_value_ptr() const noexcept - { - const basic_value* p = this; - while( p->is_value_ptr() ) { - p = p->get_value_ptr(); - assert( p ); - } - return *p; - } - - [[nodiscard]] basic_value* find( const std::size_t index ) - { - auto& a = get_array(); - return ( index < a.size() ) ? ( a.data() + index ) : nullptr; - } - - [[nodiscard]] const basic_value* find( const std::size_t index ) const - { - const auto& a = get_array(); - return ( index < a.size() ) ? ( a.data() + index ) : nullptr; - } - - template< typename Key > - [[nodiscard]] std::enable_if_t< !std::is_convertible_v< Key, std::size_t > && !std::is_convertible_v< Key, pointer >, basic_value* > find( Key&& key ) - { - auto& o = get_object(); - const auto it = o.find( std::forward< Key >( key ) ); - return ( it != o.end() ) ? ( &it->second ) : nullptr; - } - - template< typename Key > - [[nodiscard]] std::enable_if_t< !std::is_convertible_v< Key, std::size_t > && !std::is_convertible_v< Key, pointer >, const basic_value* > find( Key&& key ) const - { - const auto& o = get_object(); - const auto it = o.find( std::forward< Key >( key ) ); - return ( it != o.end() ) ? ( &it->second ) : nullptr; - } - - [[nodiscard]] basic_value* find( const pointer& k ) - { - return internal::pointer_find( this, k.begin(), k.end() ); - } - - [[nodiscard]] const basic_value* find( const pointer& k ) const - { - return internal::pointer_find( this, k.begin(), k.end() ); - } - - [[nodiscard]] basic_value& at( const std::size_t index ) - { - auto& a = get_array(); - if( index >= a.size() ) { - throw_index_out_of_bound_exception( index ); - } - return a[ index ]; - } - - [[nodiscard]] const basic_value& at( const std::size_t index ) const - { - const auto& a = get_array(); - if( index >= a.size() ) { - throw_index_out_of_bound_exception( index ); - } - return a[ index ]; - } - - template< typename Key > - [[nodiscard]] std::enable_if_t< !std::is_convertible_v< Key, std::size_t > && !std::is_convertible_v< Key, pointer >, basic_value& > at( const Key& key ) - { - auto& o = get_object(); - const auto it = o.find( key ); - if( it == o.end() ) { - throw_key_not_found_exception( key ); - } - return it->second; - } - - template< typename Key > - [[nodiscard]] std::enable_if_t< !std::is_convertible_v< Key, std::size_t > && !std::is_convertible_v< Key, pointer >, const basic_value& > at( const Key& key ) const - { - const auto& o = get_object(); - const auto it = o.find( key ); - if( it == o.end() ) { - throw_key_not_found_exception( key ); - } - return it->second; - } - - [[nodiscard]] basic_value& at( const pointer& k ) - { - return internal::pointer_at( this, k.begin(), k.end() ); - } - - [[nodiscard]] const basic_value& at( const pointer& k ) const - { - return internal::pointer_at( this, k.begin(), k.end() ); - } - - [[nodiscard]] basic_value& operator[]( const std::size_t index ) - { - return get_array()[ index ]; - } - - [[nodiscard]] const basic_value& operator[]( const std::size_t index ) const - { - return get_array()[ index ]; - } - - template< typename Key > - [[nodiscard]] std::enable_if_t< !std::is_convertible_v< Key, std::size_t > && !std::is_convertible_v< Key, pointer >, basic_value& > operator[]( Key&& key ) - { - return prepare_object()[ std::forward< Key >( key ) ]; - } - - [[nodiscard]] basic_value& operator[]( const pointer& k ) - { - if( k.empty() ) { - return *this; - } - const auto b = k.begin(); - const auto e = std::prev( k.end() ); - basic_value& v = internal::pointer_at( this, b, e ); - if( v.is_object() ) { - return v.get_object()[ e->key() ]; - } - if( v.is_array() ) { - if( e->key() == "-" ) { - v.emplace_back( null ); - return v.get_array().back(); - } - return v.at( e->index() ); - } - throw internal::invalid_type( b, std::next( e ) ); - } - - template< typename T > - [[nodiscard]] std::enable_if_t< internal::has_as< Traits< T >, basic_value >, T > as() const - { - return Traits< T >::as( *this ); - } - - template< typename T > - [[nodiscard]] std::enable_if_t< !internal::has_as< Traits< T >, basic_value > && internal::has_as_type< Traits, T, basic_value >, T > as() const - { - return Traits< T >::template as_type< Traits, T >( *this ); - } - - template< typename T > - [[nodiscard]] std::enable_if_t< !internal::has_as< Traits< T >, basic_value > && !internal::has_as_type< Traits, T, basic_value > && internal::has_to< Traits< T >, basic_value, T >, T > as() const - { - T v; // TODO: Should is_default_constructible< T > be part of the enable_if, static_assert()ed here, or this line allowed to error? - Traits< T >::to( *this, v ); - return v; - } - - template< typename T > - std::enable_if_t< !internal::has_as< Traits< T >, basic_value > && !internal::has_as_type< Traits, T, basic_value > && !internal::has_to< Traits< T >, basic_value, T > > as() const = delete; - - template< typename T, typename K > - [[nodiscard]] T as( const K& key ) const - { - return this->at( key ).template as< T >(); - } - - // TODO: Incorporate has_as_type in the following functions (and throughout the library) (if we decide keep it)! - - template< typename T, typename... With > - [[nodiscard]] std::enable_if_t< internal::has_as< Traits< T >, basic_value, With... >, T > as_with( With&&... with ) const - { - return Traits< T >::as( *this, with... ); - } - - template< typename T, typename... With > - [[nodiscard]] std::enable_if_t< !internal::has_as< Traits< T >, basic_value, With... > && internal::has_to< Traits< T >, basic_value, T, With... >, T > as_with( With&&... with ) const - { - T v; // TODO: Should is_default_constructible< T > be part of the enable_if, static_assert()ed here, or this line allowed to error? - Traits< T >::to( *this, v, with... ); - return v; - } - - template< typename T, typename... With > - std::enable_if_t< !internal::has_as< Traits< T >, basic_value, With... > && !internal::has_to< Traits< T >, basic_value, T, With... >, T > as_with( With&&... with ) const = delete; - - template< typename T > - std::enable_if_t< internal::has_to< Traits< T >, basic_value, T > > to( T& v ) const - { - Traits< std::decay_t< T > >::to( *this, v ); - } - - template< typename T > - std::enable_if_t< !internal::has_to< Traits< T >, basic_value, T > && internal::has_as< Traits< T >, basic_value > > to( T& v ) const - { - v = Traits< std::decay_t< T > >::as( *this ); - } - - template< typename T > - std::enable_if_t< !internal::has_to< Traits< T >, basic_value, T > && !internal::has_as< Traits< T >, basic_value > > to( T& v ) const = delete; - - template< typename T, typename K > - void to( T& v, const K& key ) - { - this->at( key ).to( v ); - } - - template< typename T, typename... With > - std::enable_if_t< internal::has_to< Traits< T >, basic_value, T, With... > > to_with( T& v, With&&... with ) const - { - Traits< std::decay_t< T > >::to( *this, v, with... ); - } - - template< typename T, typename... With > - std::enable_if_t< !internal::has_to< Traits< T >, basic_value, T, With... > && internal::has_as< Traits< T >, basic_value, With... > > to_with( T& v, With&&... with ) const - { - v = Traits< std::decay_t< T > >::as( *this, with... ); - } - - template< typename T, typename... With > - std::enable_if_t< !internal::has_to< Traits< T >, basic_value, T, With... > && !internal::has_as< Traits< T >, basic_value, With... > > to_with( T& v, With&&... with ) const = delete; - - template< typename T > - [[nodiscard]] std::optional< T > optional() const - { - if( is_null() ) { - return std::nullopt; - } - return as< T >(); - } - - template< typename T, typename K > - [[nodiscard]] std::optional< T > optional( const K& key ) const - { - if( const auto* p = find( key ) ) { - return p->template as< T >(); - } - return std::nullopt; - } - - void erase( const std::size_t index ) - { - auto& a = get_array(); - if( index >= a.size() ) { - throw_index_out_of_bound_exception( index ); - } - a.erase( a.begin() + index ); - } - - template< typename Key > - std::enable_if_t< !std::is_convertible_v< Key, std::size_t > && !std::is_convertible_v< Key, pointer > > erase( const Key& key ) - { - if( get_object().erase( key ) == 0 ) { - throw_key_not_found_exception( key ); - } - } - - void erase( const pointer& k ) - { - if( !k ) { - throw std::runtime_error( internal::format( "invalid root JSON Pointer for erase", json::message_extension( *this ) ) ); - } - const auto b = k.begin(); - const auto e = std::prev( k.end() ); - basic_value& v = internal::pointer_at( this, b, e ); - if( v.is_object() ) { - v.erase( e->key() ); - } - else if( v.is_array() ) { - v.erase( e->index() ); - } - else { - throw internal::invalid_type( b, std::next( e ) ); - } - } - - basic_value& insert( const pointer& k, basic_value in ) - { - if( !k ) { - *this = std::move( in ); - return *this; - } - const auto b = k.begin(); - const auto e = std::prev( k.end() ); - basic_value& v = internal::pointer_at( this, b, e ); - if( v.is_object() ) { - return v.get_object().insert_or_assign( e->key(), std::move( in ) ).first->second; - } - if( v.is_array() ) { - auto& a = v.get_array(); - if( e->key() == "-" ) { - v.emplace_back( std::move( in ) ); - return a.back(); - } - const auto i = e->index(); - if( i >= a.size() ) { - throw std::out_of_range( internal::format( "invalid JSON Pointer \"", internal::tokens_to_string( b, std::next( e ) ), "\", array index '", i, "' out of bound '", a.size(), '\'', json::message_extension( *this ) ) ); - } - a.insert( a.begin() + i, std::move( in ) ); - return a.at( i ); - } - throw internal::invalid_type( b, std::next( e ) ); - } - - variant_t& variant() noexcept - { - return m_variant; - } - - const variant_t& variant() const noexcept - { - return m_variant; - } - - private: - template< typename T > - static void produce_from_opaque_ptr( events::virtual_base& consumer, const void* raw ) - { - Traits< T >::template produce< Traits >( consumer, *static_cast< const T* >( raw ) ); - } - }; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/binary.hpp b/include/tao/json/binary.hpp deleted file mode 100644 index c762fdf7..00000000 --- a/include/tao/json/binary.hpp +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_BINARY_HPP -#define TAO_JSON_BINARY_HPP - -#include -#include - -#include "external/pegtl/internal/always_false.hpp" - -namespace tao -{ - using binary = std::vector< std::byte >; - -} // namespace tao - -namespace tao::json -{ - namespace internal - { - [[nodiscard]] constexpr char unhex_char( const char c ) noexcept - { - return static_cast< char >( ( c < 'A' ) ? ( c - '0' ) : ( ( c < 'a' ) ? ( c - 'A' + 10 ) : ( c - 'a' + 10 ) ) ); - } - - template< typename V, V... > - struct vlist; - - template< typename T, typename L, char... Cs > - struct unhex_helper; - - template< typename T, typename V, V... Vs > - struct unhex_helper< T, vlist< V, Vs... > > - { - [[nodiscard]] static constexpr T unhex() - { - return T{ Vs... }; - } - }; - - template< typename T, typename V, V... Vs, char C > - struct unhex_helper< T, vlist< V, Vs... >, C > - : unhex_helper< T, vlist< V > > - { - static_assert( pegtl::internal::always_false< T >::value, "digits must occur in pairs" ); - }; - - template< typename T, typename V, V... Vs, char C1, char... Cs > - struct unhex_helper< T, vlist< V, Vs... >, '\'', C1, Cs... > - : unhex_helper< T, vlist< V, Vs... >, C1, Cs... > - { - }; - - template< typename T, typename V, V... Vs, char C0, char... Cs > - struct unhex_helper< T, vlist< V, Vs... >, C0, '\'', Cs... > - : unhex_helper< T, vlist< V > > - { - static_assert( pegtl::internal::always_false< T >::value, "digit separator only allowed between pairs of digits" ); - }; - - template< typename T, typename V, V... Vs, char C0, char C1, char... Cs > - struct unhex_helper< T, vlist< V, Vs... >, C0, C1, Cs... > - : unhex_helper< T, vlist< V, Vs..., V( ( unhex_char( C0 ) << 4 ) + unhex_char( C1 ) ) >, Cs... > - { - }; - - template< typename T, typename V, char C > - [[nodiscard]] constexpr T unhex() - { - static_assert( pegtl::internal::always_false< T >::value, "not a hex literal" ); - return T{}; - } - - template< typename T, typename V, char C0, char C1, char... Cs > - [[nodiscard]] constexpr T unhex() - { - static_assert( C0 == '0', "not a hex literal" ); - static_assert( C1 == 'x' || C1 == 'X', "not a hex literal" ); - return unhex_helper< T, vlist< V >, Cs... >::unhex(); - } - - template< typename T, char... Cs > - [[nodiscard]] constexpr T unhex() - { - return unhex< T, typename T::value_type, Cs... >(); - } - - } // namespace internal - - inline namespace literals - { - template< char... Cs > - [[nodiscard]] std::vector< std::byte > operator"" _binary() - { - return internal::unhex< std::vector< std::byte >, Cs... >(); - } - - } // namespace literals - -} // namespace tao::json - -#endif diff --git a/include/tao/json/binary_view.hpp b/include/tao/json/binary_view.hpp deleted file mode 100644 index 9014b2e2..00000000 --- a/include/tao/json/binary_view.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_BINARY_VIEW_HPP -#define TAO_JSON_BINARY_VIEW_HPP - -#include "span.hpp" - -#include - -namespace tao -{ - using binary_view = span< const std::byte >; - - namespace internal - { - [[nodiscard]] inline bool binary_equal( const binary_view lhs, const binary_view rhs ) noexcept - { - return std::equal( lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend() ); - } - - [[nodiscard]] inline bool binary_less( const binary_view lhs, const binary_view rhs ) noexcept - { - return std::lexicographical_compare( lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend() ); - } - - } // namespace internal - -} // namespace tao - -#endif diff --git a/include/tao/json/binding.hpp b/include/tao/json/binding.hpp deleted file mode 100644 index 7c0f861b..00000000 --- a/include/tao/json/binding.hpp +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_BINDING_HPP -#define TAO_JSON_BINDING_HPP - -#include "binding/constant.hpp" -#include "binding/element.hpp" -#include "binding/factory.hpp" -#include "binding/for_nothing_value.hpp" -#include "binding/for_unknown_key.hpp" -#include "binding/inherit.hpp" -#include "binding/member.hpp" -#include "binding/versions.hpp" - -#include "binding/internal/array.hpp" -#include "binding/internal/inherit.hpp" -#include "binding/internal/object.hpp" - -namespace tao::json::binding -{ - namespace internal - { - template< typename... As > - struct make_array - { - using list = json::internal::merge_type_lists< internal::inherit_elements< As >... >; - using type = internal::array< list >; - }; - - } // namespace internal - - template< typename... As > - using array = typename internal::make_array< As... >::type; - - template< for_unknown_key E, for_nothing_value N, typename... As > - using basic_object = internal::basic_object< E, N, json::internal::merge_type_lists< internal::inherit_members< As >... > >; - - template< typename... As > - using object = basic_object< for_unknown_key::fail, for_nothing_value::encode, As... >; - -} // namespace tao::json::binding - -#define TAO_JSON_BIND_ELEMENT( ... ) tao::json::binding::element< __VA_ARGS__ > - -#define TAO_JSON_BIND_ELEMENT_BOOL( VaLue ) tao::json::binding::element_b< VaLue > -#define TAO_JSON_BIND_ELEMENT_SIGNED( VaLue ) tao::json::binding::element_i< VaLue > -#define TAO_JSON_BIND_ELEMENT_UNSIGNED( VaLue ) tao::json::binding::element_u< VaLue > -#define TAO_JSON_BIND_ELEMENT_STRING( VaLue ) tao::json::binding::element_s< TAO_JSON_STRING_T( VaLue ) > - -#define TAO_JSON_BIND_REQUIRED( KeY, ... ) tao::json::binding::member< tao::json::binding::member_kind::required, TAO_JSON_STRING_T( KeY ), __VA_ARGS__ > -#define TAO_JSON_BIND_OPTIONAL( KeY, ... ) tao::json::binding::member< tao::json::binding::member_kind::optional, TAO_JSON_STRING_T( KeY ), __VA_ARGS__ > - -#define TAO_JSON_BIND_REQUIRED_BOOL( KeY, VaLue ) tao::json::binding::member_b< tao::json::binding::member_kind::required, TAO_JSON_STRING_T( KeY ), VaLue > -#define TAO_JSON_BIND_REQUIRED_SIGNED( KeY, VaLue ) tao::json::binding::member_i< tao::json::binding::member_kind::required, TAO_JSON_STRING_T( KeY ), VaLue > -#define TAO_JSON_BIND_REQUIRED_UNSIGNED( KeY, VaLue ) tao::json::binding::member_u< tao::json::binding::member_kind::required, TAO_JSON_STRING_T( KeY ), VaLue > -#define TAO_JSON_BIND_REQUIRED_STRING( KeY, VaLue ) tao::json::binding::member_s< tao::json::binding::member_kind::required, TAO_JSON_STRING_T( KeY ), TAO_JSON_STRING_T( VaLue ) > - -#define TAO_JSON_BIND_OPTIONAL_BOOL( KeY, VaLue ) tao::json::binding::member_b< tao::json::binding::member_kind::optional, TAO_JSON_STRING_T( KeY ), VaLue > -#define TAO_JSON_BIND_OPTIONAL_SIGNED( KeY, VaLue ) tao::json::binding::member_i< tao::json::binding::member_kind::optional, TAO_JSON_STRING_T( KeY ), VaLue > -#define TAO_JSON_BIND_OPTIONAL_UNSIGNED( KeY, VaLue ) tao::json::binding::member_u< tao::json::binding::member_kind::optional, TAO_JSON_STRING_T( KeY ), VaLue > -#define TAO_JSON_BIND_OPTIONAL_STRING( KeY, VaLue ) tao::json::binding::member_s< tao::json::binding::member_kind::optional, TAO_JSON_STRING_T( KeY ), TAO_JSON_STRING_T( VaLue ) > - -#define TAO_JSON_BIND_REQUIRED1( ... ) tao::json::binding::member< tao::json::binding::member_kind::required, tao::json::binding::internal::use_default_key, __VA_ARGS__ > -#define TAO_JSON_BIND_OPTIONAL1( ... ) tao::json::binding::member< tao::json::binding::member_kind::optional, tao::json::binding::internal::use_default_key, __VA_ARGS__ > - -#define TAO_JSON_FACTORY_BIND( KeY, ... ) tao::json::binding::internal::factory_temp< TAO_JSON_STRING_T( KeY ), __VA_ARGS__ > - -#define TAO_JSON_FACTORY_BIND1( ... ) tao::json::binding::internal::factory_temp< tao::json::binding::internal::use_default_key, __VA_ARGS__ > - -#endif diff --git a/include/tao/json/binding/constant.hpp b/include/tao/json/binding/constant.hpp deleted file mode 100644 index 193de3f0..00000000 --- a/include/tao/json/binding/constant.hpp +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_BINDING_CONSTANT_HPP -#define TAO_JSON_BINDING_CONSTANT_HPP - -#include -#include - -#include "../external/pegtl/internal/pegtl_string.hpp" -#include "../internal/escape.hpp" -#include "../internal/format.hpp" -#include "../internal/string_t.hpp" -#include "../message_extension.hpp" - -#include "element.hpp" -#include "member_kind.hpp" - -#include "internal/type_key.hpp" - -namespace tao::json::binding -{ - template< bool V > - struct element_b - { - using value_t = bool; - - template< typename C > - [[nodiscard]] static bool read( const C& /*unused*/ ) - { - return V; - } - - template< template< typename... > class Traits, typename C > - static void to( const basic_value< Traits >& v, C& /*unused*/ ) - { - const auto t = v.template as< bool >(); - if( t != V ) { - throw std::runtime_error( json::internal::format( "boolean mismatch, expected '", V, "' parsed '", t, '\'', json::message_extension( v ) ) ); - } - } - - template< template< typename... > class Traits = traits, typename Consumer, typename C > - static void produce( Consumer& consumer, const C& /*unused*/ ) - { - consumer.boolean( V ); - } - - template< template< typename... > class Traits = traits, typename Producer, typename C > - static void consume( Producer& parser, C& /*unused*/ ) - { - const auto t = parser.boolean(); - if( t != V ) { - parser.throw_parse_error( json::internal::format( "boolean mismatch, expected '", V, "' parsed '", t, '\'' ) ); - } - } - }; - - template< std::int64_t V > - struct element_i - { - using value_t = std::int64_t; - - template< typename C > - [[nodiscard]] static std::int64_t read( const C& /*unused*/ ) - { - return V; - } - - template< template< typename... > class Traits, typename C > - static void to( const basic_value< Traits >& v, C& /*unused*/ ) - { - const auto t = v.template as< std::int64_t >(); - if( t != V ) { - throw std::runtime_error( json::internal::format( "signed integer mismatch, expected '", V, "' parsed '", t, '\'', json::message_extension( v ) ) ); - } - } - - template< template< typename... > class Traits = traits, typename Consumer, typename C > - static void produce( Consumer& consumer, const C& /*unused*/ ) - { - consumer.number( V ); - } - - template< template< typename... > class Traits = traits, typename Producer, typename C > - static void consume( Producer& parser, C& /*unused*/ ) - { - const auto t = parser.number_signed(); - if( t != V ) { - parser.throw_parse_error( json::internal::format( "signed integer mismatch, expected '", V, "' parsed '", t, '\'' ) ); - } - } - }; - - template< std::uint64_t V > - struct element_u - { - using value_t = std::uint64_t; - - template< typename C > - [[nodiscard]] static std::uint64_t read( const C& /*unused*/ ) - { - return V; - } - - template< template< typename... > class Traits, typename C > - static void to( const basic_value< Traits >& v, C& /*unused*/ ) - { - const auto t = v.template as< std::uint64_t >(); - if( t != V ) { - throw std::runtime_error( json::internal::format( "unsigned integer mismatch, expected '", V, "' parsed '", t, '\'', json::message_extension( v ) ) ); - } - } - - template< template< typename... > class Traits = traits, typename Consumer, typename C > - static void produce( Consumer& consumer, const C& /*unused*/ ) - { - consumer.number( V ); - } - - template< template< typename... > class Traits = traits, typename Producer, typename C > - static void consume( Producer& parser, C& /*unused*/ ) - { - const auto t = parser.number_unsigned(); - if( t != V ) { - parser.throw_parse_error( json::internal::format( "unsigned integer mismatch, expected '", V, "' parsed '", t, '\'' ) ); - } - } - }; - - template< typename S > - struct element_s; - - template< char... Cs > - struct element_s< json::internal::string_t< Cs... > > - { - using value_t = std::string; // TODO: Or std::string_view? Something else? Nothing? - - using string = json::internal::string_t< Cs... >; - - template< typename C > - [[nodiscard]] static std::string_view read( const C& /*unused*/ ) - { - return string::as_string_view(); - } - - template< template< typename... > class Traits, typename C > - static void to( const basic_value< Traits >& v, C& /*unused*/ ) - { - const auto sc = string::as_string_view(); - const auto sv = v.template as< std::string_view >(); - if( sv != sc ) { - throw std::runtime_error( json::internal::format( "string mismatch, expected \"", json::internal::escape( sc ), "\" parsed \"", json::internal::escape( sv ), '"', json::message_extension( v ) ) ); - } - } - - template< template< typename... > class Traits = traits, typename Consumer, typename T > - static void produce( Consumer& consumer, const T& /*unused*/ ) - { - consumer.string( string::as_string_view() ); - } - - template< template< typename... > class Traits = traits, typename Producer, typename T > - static void consume( Producer& parser, T& /*unused*/ ) - { - const auto sc = string::as_string_view(); - const auto ss = parser.string(); - if( ss != sc ) { - parser.throw_parse_error( json::internal::format( "string mismatch, expected \"", json::internal::escape( sc ), "\" parsed \"", json::internal::escape( ss ), '"' ) ); - } - } - }; - - template< member_kind R, typename K, bool B > - struct member_b - : element_b< B >, - internal::type_key< K, void > - { - static constexpr member_kind kind = R; - - template< template< typename... > class Traits, typename T > - [[nodiscard]] static bool is_nothing( const T& /*unused*/ ) - { - return false; - } - }; - - template< member_kind R, typename K, std::int64_t V > - struct member_i - : element_i< V >, - internal::type_key< K, void > - { - static constexpr member_kind kind = R; - - template< template< typename... > class Traits, typename T > - [[nodiscard]] static bool is_nothing( const T& /*unused*/ ) - { - return false; - } - }; - - template< member_kind R, typename K, std::uint64_t V > - struct member_u - : element_u< V >, - internal::type_key< K, void > - { - static constexpr member_kind kind = R; - - template< template< typename... > class Traits, typename T > - [[nodiscard]] static bool is_nothing( const T& /*unused*/ ) - { - return false; - } - }; - - template< member_kind R, typename K, typename S > - struct member_s - : element_s< S >, - internal::type_key< K, void > - { - static constexpr member_kind kind = R; - - template< template< typename... > class Traits, typename T > - [[nodiscard]] static bool is_nothing( const T& /*unused*/ ) - { - return false; - } - }; - -} // namespace tao::json::binding - -#endif diff --git a/include/tao/json/binding/element.hpp b/include/tao/json/binding/element.hpp deleted file mode 100644 index 7fc0b5cf..00000000 --- a/include/tao/json/binding/element.hpp +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_BINDING_ELEMENT_HPP -#define TAO_JSON_BINDING_ELEMENT_HPP - -#include - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "../events/produce.hpp" - -namespace tao::json::binding -{ - namespace internal - { - template< typename T, T, typename = void > - struct element; - - template< typename C, typename T, T C::*P > - struct element< T C::*, P, std::enable_if_t< std::is_member_object_pointer_v< T C::* > > > - { - using class_t = C; - using value_t = T; - - using internal_t = std::decay_t< decltype( std::declval< C >().*P ) >; - - [[nodiscard]] static const auto& read( const C& v ) - { - return v.*P; - } - - template< typename W > - static void write( C& v, W&& w ) - { - v.*P = std::forward< W >( w ); - } - - template< template< typename... > class Traits > - static void to( const basic_value< Traits >& v, C& x ) - { - v.to( x.*P ); - } - - template< template< typename... > class Traits = traits, typename Producer > - static void consume( Producer& parser, C& v ) - { - json::consume< Traits >( parser, v.*P ); - } - - template< template< typename... > class Traits = traits, typename Consumer > - static void produce( Consumer& consumer, const C& v ) - { - events::produce< Traits >( consumer, v.*P ); - } - }; - - template< typename C, typename T, T C::*P > - struct element< T C::*, P, std::enable_if_t< std::is_member_function_pointer_v< T C::* > > > - { - using class_t = C; - using value_t = T; - - using internal_t = std::decay_t< decltype( ( std::declval< const C >().*P )() ) >; - - [[nodiscard]] static decltype( auto ) read( const C& v ) - { - return ( v.*P )(); - } - - template< template< typename... > class Traits = traits, typename Consumer > - static void produce( Consumer& consumer, const C& v ) - { - events::produce< Traits >( consumer, ( v.*P )() ); - } - }; - - template< typename C, typename T, T ( *P )( const C& ) > - struct element< T ( * )( const C& ), P > - { - using class_t = C; - using value_t = T; - - [[nodiscard]] static decltype( auto ) read( const C& v ) - { - return P( v ); - } - - template< template< typename... > class Traits = traits, typename Consumer > - static void produce( Consumer& consumer, const C& v ) - { - events::produce< Traits >( consumer, P( v ) ); - } - }; - - template< typename CT, CT CP, typename T, T P > - struct element2; - - template< typename A, typename CR, CR ( *CP )( const A& ) noexcept, typename R, R ( *P )( A& ) noexcept > - struct element2< CR ( * )( const A& ) noexcept, CP, R ( * )( A& ) noexcept, P > - { - using class_t = A; - using value_t = std::decay_t< R >; - - [[nodiscard]] static decltype( auto ) read( const A& v ) noexcept - { - return CP( v ); - } - - template< typename W > - static void write( A& v, W&& w ) - { - P( v ) = std::forward< W >( w ); - } - - template< template< typename... > class Traits > - static void to( const basic_value< Traits >& v, A& x ) - { - v.to( P( x ) ); - } - - template< template< typename... > class Traits = traits, typename Producer > - static void consume( Producer& parser, A& v ) - { - json::consume< Traits >( parser, P( v ) ); - } - - template< template< typename... > class Traits = traits, typename Consumer > - static void produce( Consumer& consumer, const A& v ) - { - events::produce< Traits >( consumer, CP( v ) ); - } - }; - - template< typename A, typename CR, CR ( *CP )( const A& ) noexcept, typename R, void ( *P )( A&, R&& ) noexcept > - struct element2< CR ( * )( const A& ) noexcept, CP, void ( * )( A&, R&& ) noexcept, P > - { - using class_t = A; - using value_t = std::decay_t< R >; - - [[nodiscard]] static decltype( auto ) read( const A& v ) noexcept - { - return CP( v ); - } - - template< typename W > - static void write( A& v, W&& w ) - { - P( v, std::forward< W >( w ) ); - } - - template< template< typename... > class Traits > - static void to( const basic_value< Traits >& v, A& x ) - { - P( x, v.template as< std::decay_t< R > >() ); - } - - template< template< typename... > class Traits = traits, typename Producer > - static void consume( Producer& parser, A& v ) - { - P( v, json::consume< Traits >( parser ) ); - } - - template< template< typename... > class Traits = traits, typename Consumer > - static void produce( Consumer& consumer, const A& v ) - { - events::produce< Traits >( consumer, CP( v ) ); - } - }; - - } // namespace internal - - template< auto P > - using element = internal::element< decltype( P ), P >; - - template< auto CP, auto P > - using element2 = internal::element2< decltype( CP ), CP, decltype( P ), P >; - -} // namespace tao::json::binding - -#endif diff --git a/include/tao/json/binding/factory.hpp b/include/tao/json/binding/factory.hpp deleted file mode 100644 index 28362f18..00000000 --- a/include/tao/json/binding/factory.hpp +++ /dev/null @@ -1,250 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_BINDING_FACTORY_HPP -#define TAO_JSON_BINDING_FACTORY_HPP - -#include -#include -#include -#include -#include - -#include "../forward.hpp" - -#include "../basic_value.hpp" -#include "../external/pegtl/internal/pegtl_string.hpp" -#include "../internal/escape.hpp" -#include "../internal/format.hpp" -#include "../internal/string_t.hpp" - -#include "internal/type_key.hpp" - -namespace tao::json::binding -{ - namespace internal - { - template< typename... Ts > - void list_all_types( std::ostream& oss, const std::map< std::string, Ts... >& m ) - { - for( const auto& i : m ) { - json::internal::format_to( oss, " \"", i.first, '\"' ); - } - } - - template< typename... Ts > - void list_all_types( std::ostream& oss, const std::map< const std::type_info*, Ts... >& m ) - { - for( const auto& i : m ) { - json::internal::format_to( oss, ' ', i.first->name() ); - } - } - - template< typename K, typename T, typename Base, template< typename... > class Pointer > - struct factory_type - : type_key< K, T > - { - [[nodiscard]] static const std::type_info* type() - { - return &typeid( T ); - } - - template< template< typename... > class Traits, typename... With > - [[nodiscard]] static Pointer< Base > as( const basic_value< Traits >& v, With&... with ) - { - using R = typename Traits< Pointer< T > >::template with_base< Base >; - return R::as( v, with... ); - } - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const Pointer< Base >& p ) - { - using R = typename Traits< Pointer< T > >::template with_base< Base >; - R::assign( v, p ); - } - - template< template< typename... > class Traits, typename Producer > - [[nodiscard]] static Pointer< Base > consume( Producer& parser ) - { - using R = typename Traits< Pointer< T > >::template with_base< Base >; - return R::template consume< Traits >( parser ); - } - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, const Pointer< Base >& p ) - { - using R = typename Traits< Pointer< T > >::template with_base< Base >; - R::template produce< Traits >( c, p ); - } - }; - - template< typename K, typename T > - struct factory_temp - { - template< typename Base, template< typename... > class Pointer > - using bind = factory_type< K, T, Base, Pointer >; - }; - - template< template< typename... > class Traits, template< typename... > class Pointer, typename Base, typename... With > - using as_func_t = Pointer< Base > ( * )( const basic_value< Traits >&, With&... ); - - } // namespace internal - - template< typename... Ts > - struct factory - { - template< typename F > - struct entry1 - { - explicit entry1( F c ) - : function( c ) - {} - - F function; - }; - - template< typename F > - struct entry2 - { - entry2( F c, std::string&& n ) - : function( c ), - name( std::move( n ) ) - {} - - F function; - std::string name; - }; - - template< typename V, template< typename... > class Traits, template< typename... > class Pointer, typename Base, typename... With > - static void emplace_as( std::map< std::string, entry1< internal::as_func_t< Traits, Pointer, Base, With... > >, std::less<> >& m ) - { - using W = typename V::template bind< Base, Pointer >; - m.try_emplace( W::template key< Traits >(), entry1< internal::as_func_t< Traits, Pointer, Base, With... > >( &W::template as< Traits, With... > ) ); - } - - template< template< typename... > class Traits, template< typename... > class Pointer, typename Base, typename... With > - static void to( const basic_value< Traits >& v, Pointer< Base >& r, With&... with ) - { - static const std::map< std::string, entry1< internal::as_func_t< Traits, Pointer, Base, With... > >, std::less<> > m = []() { - std::map< std::string, entry1< internal::as_func_t< Traits, Pointer, Base, With... > >, std::less<> > t; - ( emplace_as< Ts >( t ), ... ); - assert( t.size() == sizeof...( Ts ) ); - return t; - }(); - - const auto& a = v.get_object(); - if( a.size() != 1 ) { - throw std::runtime_error( json::internal::format( "polymorphic factory requires object of size one for base class ", pegtl::internal::demangle< Base >(), json::message_extension( v ) ) ); - } - const auto b = a.begin(); - const auto i = m.find( b->first ); - if( i == m.end() ) { - std::ostringstream oss; - json::internal::format_to( oss, "unknown factory type \"", json::internal::escape( b->first ), "\" -- known are" ); - internal::list_all_types( oss, m ); - json::internal::format_to( oss, " for base class ", pegtl::internal::demangle< Base >(), json::message_extension( v ) ); - throw std::runtime_error( oss.str() ); - } - r = i->second.function( b->second, with... ); - } - - template< typename V, template< typename... > class Traits, template< typename... > class Pointer, typename Base, typename F > - static void emplace_assign( std::map< const std::type_info*, entry2< F >, json::internal::type_info_less >& m ) - { - using W = typename V::template bind< Base, Pointer >; - m.try_emplace( W::type(), entry2< F >( &W::template assign< Traits >, W::template key< Traits >() ) ); - } - - template< template< typename... > class Traits, template< typename... > class Pointer, typename Base > - static void assign( basic_value< Traits >& v, const Pointer< Base >& p ) - { - using F = void ( * )( basic_value< Traits >&, const Pointer< Base >& ); - static const std::map< const std::type_info*, entry2< F >, json::internal::type_info_less > m = []() { - std::map< const std::type_info*, entry2< F >, json::internal::type_info_less > t; - ( emplace_assign< Ts, Traits, Pointer, Base >( t ), ... ); - assert( t.size() == sizeof...( Ts ) ); - return t; - }(); - - const auto i = m.find( &typeid( *p ) ); - if( i == m.end() ) { - std::ostringstream oss; - json::internal::format_to( oss, "unknown factory type ", pegtl::internal::demangle< decltype( *p ) >(), " -- known are" ); - internal::list_all_types( oss, m ); - json::internal::format_to( oss, " for base class ", pegtl::internal::demangle< Base >() ); - throw std::runtime_error( oss.str() ); - } - i->second.function( v, p ); - v = { - { i->second.name, std::move( v ) } - }; - } - - template< typename V, template< typename... > class Traits, template< typename... > class Pointer, typename Base, typename Producer, typename F > - static void emplace_consume( std::map< std::string, entry1< F >, std::less<> >& m ) - { - using W = typename V::template bind< Base, Pointer >; - m.try_emplace( W::template key< Traits >(), entry1< F >( &W::template consume< Traits, Producer > ) ); - } - - template< template< typename... > class Traits, template< typename... > class Pointer, typename Base, typename Producer > - static void consume( Producer& parser, Pointer< Base >& r ) - { - using F = Pointer< Base > ( * )( Producer& ); - static const std::map< std::string, entry1< F >, std::less<> > m = []() { - std::map< std::string, entry1< F >, std::less<> > t; - ( emplace_consume< Ts, Traits, Pointer, Base, Producer >( t ), ... ); - return t; - }(); - - auto s = parser.begin_object(); - const auto k = parser.key(); - const auto i = m.find( k ); - if( i == m.end() ) { - std::ostringstream oss; - json::internal::format_to( oss, "unknown factory type \"", json::internal::escape( k ), "\" -- known are" ); - internal::list_all_types( oss, m ); - json::internal::format_to( oss, " for base class ", pegtl::internal::demangle< Base >() ); - throw std::runtime_error( oss.str() ); - } - r = i->second.function( parser ); - parser.end_object( s ); - } - - template< typename V, template< typename... > class Traits, template< typename... > class Pointer, typename Base, typename Consumer, typename F > - static void emplace_produce( std::map< const std::type_info*, entry2< F >, json::internal::type_info_less >& m ) - { - using W = typename V::template bind< Base, Pointer >; - m.try_emplace( W::type(), entry2< F >( &W::template produce< Traits, Consumer >, W::template key< Traits >() ) ); - } - - template< template< typename... > class Traits, template< typename... > class Pointer, typename Base, typename Consumer > - static void produce( Consumer& consumer, const Pointer< Base >& p ) - { - using F = void ( * )( Consumer&, const Pointer< Base >& ); - static const std::map< const std::type_info*, entry2< F >, json::internal::type_info_less > m = []() { - std::map< const std::type_info*, entry2< F >, json::internal::type_info_less > t; - ( emplace_produce< Ts, Traits, Pointer, Base, Consumer >( t ), ... ); - assert( t.size() == sizeof...( Ts ) ); - return t; - }(); - - const auto i = m.find( &typeid( *p ) ); - if( i == m.end() ) { - std::ostringstream oss; - json::internal::format_to( oss, "unknown factory type ", pegtl::internal::demangle< decltype( *p ) >(), " -- known are" ); - internal::list_all_types( oss, m ); - json::internal::format_to( oss, " for base class ", pegtl::internal::demangle< Base >() ); - throw std::runtime_error( oss.str() ); - } - consumer.begin_object( 1 ); - consumer.key( i->second.name ); - i->second.function( consumer, p ); - consumer.member(); - consumer.end_object( 1 ); - } - }; - -} // namespace tao::json::binding - -#endif diff --git a/include/tao/json/binding/for_nothing_value.hpp b/include/tao/json/binding/for_nothing_value.hpp deleted file mode 100644 index 6fbae902..00000000 --- a/include/tao/json/binding/for_nothing_value.hpp +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_BINDING_FOR_NOTHING_VALUE_HPP -#define TAO_JSON_BINDING_FOR_NOTHING_VALUE_HPP - -namespace tao::json::binding -{ - enum class for_nothing_value : bool - { - encode, - suppress - }; - -} // namespace tao::json::binding - -#endif diff --git a/include/tao/json/binding/for_unknown_key.hpp b/include/tao/json/binding/for_unknown_key.hpp deleted file mode 100644 index 07e1e2ed..00000000 --- a/include/tao/json/binding/for_unknown_key.hpp +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_BINDING_FOR_UNKNOWN_KEY_HPP -#define TAO_JSON_BINDING_FOR_UNKNOWN_KEY_HPP - -namespace tao::json::binding -{ - enum class for_unknown_key : bool - { - fail, - skip - }; - -} // namespace tao::json::binding - -#endif diff --git a/include/tao/json/binding/inherit.hpp b/include/tao/json/binding/inherit.hpp deleted file mode 100644 index ea6ddcdd..00000000 --- a/include/tao/json/binding/inherit.hpp +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_BINDING_INHERIT_HPP -#define TAO_JSON_BINDING_INHERIT_HPP - -namespace tao::json::binding -{ - template< typename T > - struct inherit; - -} // namespace tao::json::binding - -#endif diff --git a/include/tao/json/binding/internal/array.hpp b/include/tao/json/binding/internal/array.hpp deleted file mode 100644 index 72896dcb..00000000 --- a/include/tao/json/binding/internal/array.hpp +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_BINDING_INTERNAL_ARRAY_HPP -#define TAO_JSON_BINDING_INTERNAL_ARRAY_HPP - -#include -#include - -#include "../../basic_value.hpp" -#include "../../forward.hpp" - -#include "../../internal/format.hpp" -#include "../../internal/type_traits.hpp" - -namespace tao::json::binding::internal -{ - template< typename T, typename L = std::make_index_sequence< T::size > > - struct array; - - template< typename... As, std::size_t... Is > - struct array< json::internal::type_list< As... >, std::index_sequence< Is... > > - { - using elements = json::internal::type_list< As... >; - - template< template< typename... > class Traits, typename C > - static const std::vector< basic_value< Traits > >& get_array_impl( const basic_value< Traits >& v ) - { - const auto& a = v.get_array(); - if( a.size() != sizeof...( As ) ) { - throw std::runtime_error( json::internal::format( "array size mismatch for type ", pegtl::internal::demangle< C >(), " -- expected ", sizeof...( As ), " received ", a.size(), json::message_extension( v ) ) ); - } - return a; - } - - template< template< typename... > class Traits, typename C > - static std::enable_if_t< std::is_constructible_v< C, typename As::value_t... >, C > as_type( const basic_value< Traits >& v ) - { - const auto& a = get_array_impl< Traits, C >( v ); - return C( a[ Is ].template as< typename As::value_t >()... ); - } - - template< template< typename... > class Traits, typename C > - static void to( const basic_value< Traits >& v, C& x ) // TODO: std::enable_if_t< WHAT?, void > - { - const auto& a = get_array_impl< Traits, C >( v ); - ( As::to( a[ Is ], x ), ... ); - } - - template< template< typename... > class Traits, typename C > - static void assign( basic_value< Traits >& v, const C& x ) - { - v.emplace_array(); - ( v.emplace_back( As::read( x ) ), ... ); - } - - template< typename A, template< typename... > class Traits = traits, typename Producer, typename C, typename State > - static void consume_element( Producer& parser, C& x, State& s ) - { - parser.element( s ); - A::template consume< Traits >( parser, x ); - } - - template< template< typename... > class Traits = traits, typename Producer, typename C > - static void consume( Producer& parser, C& x ) - { - auto s = parser.begin_array(); - ( consume_element< As, Traits >( parser, x, s ), ... ); - parser.end_array( s ); - } - - template< typename A, template< typename... > class Traits, typename Consumer, typename C > - static void produce_element( Consumer& consumer, const C& x ) - { - A::template produce< Traits >( consumer, x ); - consumer.element(); - } - - template< template< typename... > class Traits = traits, typename Consumer, typename C > - static void produce( Consumer& consumer, const C& x ) - { - consumer.begin_array( sizeof...( As ) ); - ( produce_element< As, Traits >( consumer, x ), ... ); - consumer.end_array( sizeof...( As ) ); - } - - template< template< typename... > class Traits, typename C > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const C& rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - if( p.is_array() ) { - const auto& a = p.get_array(); - if( a.size() == sizeof...( As ) ) { - return ( ( a[ Is ] == As::read( rhs ) ) && ... ); - } - } - return false; - } - }; - -} // namespace tao::json::binding::internal - -#endif diff --git a/include/tao/json/binding/internal/inherit.hpp b/include/tao/json/binding/internal/inherit.hpp deleted file mode 100644 index 09bfc0a8..00000000 --- a/include/tao/json/binding/internal/inherit.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_BINDING_INTERNAL_INHERIT_HPP -#define TAO_JSON_BINDING_INTERNAL_INHERIT_HPP - -#include "../../internal/type_traits.hpp" - -#include "../inherit.hpp" - -namespace tao::json::binding::internal -{ - template< typename T > - struct inherit_elements_t - { - using list = json::internal::type_list< T >; - }; - - template< typename T > - struct inherit_elements_t< inherit< T > > - { - using list = typename T::elements; - }; - - template< typename T > - using inherit_elements = typename inherit_elements_t< T >::list; - - template< typename T > - struct inherit_members_t - { - using list = json::internal::type_list< T >; - }; - - template< typename T > - struct inherit_members_t< inherit< T > > - { - using list = typename T::members; - }; - - template< typename T > - using inherit_members = typename inherit_members_t< T >::list; - -} // namespace tao::json::binding::internal - -#endif diff --git a/include/tao/json/binding/internal/object.hpp b/include/tao/json/binding/internal/object.hpp deleted file mode 100644 index 733784bb..00000000 --- a/include/tao/json/binding/internal/object.hpp +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_BINDING_INTERNAL_OBJECT_HPP -#define TAO_JSON_BINDING_INTERNAL_OBJECT_HPP - -#include -#include -#include -#include -#include -#include - -#include "../for_nothing_value.hpp" -#include "../for_unknown_key.hpp" -#include "../member_kind.hpp" - -#include "../../forward.hpp" - -#include "../../basic_value.hpp" -#include "../../internal/escape.hpp" -#include "../../internal/format.hpp" -#include "../../internal/type_traits.hpp" - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4702 ) -#endif - -namespace tao::json::binding::internal -{ - template< typename... Ts > - void list_all_keys( std::ostream& oss, const std::map< std::string, Ts... >& m ) - { - for( const auto& p : m ) { - json::internal::format_to( oss, ' ', p.first ); - } - } - - template< std::size_t N, typename... Ts > - void list_missing_keys( std::ostream& oss, const std::bitset< N >& t, const std::map< std::string, Ts... >& m ) - { - for( const auto& p : m ) { - if( !t.test( p.second.index ) ) { - json::internal::format_to( oss, ' ', p.first ); - } - } - } - - template< typename... As, std::size_t... Is > - auto make_bitset( std::index_sequence< Is... > /*unused*/ ) noexcept - { - std::bitset< sizeof...( As ) > r; - ( r.set( Is, As::kind == member_kind::optional ), ... ); - return r; - } - - template< typename F > - struct wrap - { - F function; - std::size_t index; - }; - - template< typename A, typename C, template< typename... > class Traits > - void wrap_to( const basic_value< Traits >& v, C& x ) - { - A::template to< Traits >( v, x ); - } - - template< template< typename... > class Traits, typename C, typename... As, std::size_t... Is > - auto make_map_to( std::index_sequence< Is... > /*unused*/ ) - { - using F = void ( * )( const basic_value< Traits >&, C& ); - return std::map< std::string, wrap< F > >{ - { As::template key< Traits >(), { &wrap_to< As, C, Traits >, Is } }... - }; - } - - template< typename A, typename C, template< typename... > class Traits, typename Producer > - void wrap_consume( Producer& p, C& x ) - { - A::template consume< Traits, Producer >( p, x ); - } - - template< typename C, template< typename... > class Traits, typename Producer, typename... As, std::size_t... Is > - auto make_map_consume( std::index_sequence< Is... > /*unused*/ ) - { - using F = void ( * )( Producer&, C& ); - return std::map< std::string, wrap< F > >{ - { As::template key< Traits >(), { &wrap_consume< As, C, Traits, Producer >, Is } }... - }; - } - - template< for_unknown_key E, for_nothing_value N, typename T > - struct basic_object; - - template< for_unknown_key E, for_nothing_value N, typename... As > - struct basic_object< E, N, json::internal::type_list< As... > > - { - using members = json::internal::type_list< As... >; - - template< template< typename... > class Traits, typename C > - static void to( const basic_value< Traits >& v, C& x ) - { - static const auto m = make_map_to< Traits, C, As... >( std::index_sequence_for< As... >() ); - static const auto o = make_bitset< As... >( std::index_sequence_for< As... >() ); - - const auto& a = v.get_object(); - std::bitset< sizeof...( As ) > b; - for( const auto& p : a ) { - const auto& k = p.first; - const auto i = m.find( k ); - if( i == m.end() ) { - if constexpr( E == for_unknown_key::skip ) { - continue; - } - std::ostringstream oss; - json::internal::format_to( oss, "unknown object key \"", json::internal::escape( k ), "\" -- known are" ); - list_all_keys( oss, m ); - json::internal::format_to( oss, " for type ", pegtl::internal::demangle< C >(), json::message_extension( v ) ); - throw std::runtime_error( oss.str() ); - } - i->second.function( p.second, x ); - b.set( i->second.index ); - } - b |= o; - if( !b.all() ) { - std::ostringstream oss; - json::internal::format_to( oss, "missing required key(s)" ); - list_missing_keys( oss, b, m ); - json::internal::format_to( oss, " for type ", pegtl::internal::demangle< C >(), json::message_extension( v ) ); - throw std::runtime_error( oss.str() ); - } - } - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4127 ) -#endif - template< typename A, template< typename... > class Traits, typename C > - static void assign_member( basic_value< Traits >& v, const C& x ) - { - if( ( N == for_nothing_value::encode ) || ( !A::template is_nothing< Traits >( x ) ) ) { - v.try_emplace( A::template key< Traits >(), A::read( x ) ); - } - } -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - - template< template< typename... > class Traits, typename C > - static void assign( basic_value< Traits >& v, const C& x ) - { - v.emplace_object(); - ( assign_member< As >( v, x ), ... ); - } - - template< template< typename... > class Traits = traits, typename Producer, typename C > - static void consume( Producer& parser, C& x ) - { - static const auto m = make_map_consume< C, Traits, Producer, As... >( std::index_sequence_for< As... >() ); - static const auto o = make_bitset< As... >( std::index_sequence_for< As... >() ); - - auto s = parser.begin_object(); - std::bitset< sizeof...( As ) > b; - while( parser.member_or_end_object( s ) ) { - const auto k = parser.key(); - const auto i = m.find( k ); - if( i == m.end() ) { - if constexpr( E == for_unknown_key::skip ) { - parser.skip_value(); - continue; - } - std::ostringstream oss; - json::internal::format_to( oss, "unknown object key \"", json::internal::escape( k ), "\" -- known are" ); - list_all_keys( oss, m ); - json::internal::format_to( oss, " for type ", pegtl::internal::demangle< C >() ); - parser.throw_parse_error( oss.str() ); - } - if( b.test( i->second.index ) ) { - parser.throw_parse_error( json::internal::format( "duplicate object key \"", json::internal::escape( k ), "\" for type ", pegtl::internal::demangle< C >() ) ); - } - i->second.function( parser, x ); - b.set( i->second.index ); - } - b |= o; - if( !b.all() ) { - std::ostringstream oss; - json::internal::format_to( oss, "missing required key(s)" ); - list_missing_keys( oss, b, m ); - json::internal::format_to( oss, " for type ", pegtl::internal::demangle< C >() ); - parser.throw_parse_error( oss.str() ); - } - } - - template< template< typename... > class Traits, typename C > - [[nodiscard]] static std::size_t produce_size( const C& x ) - { - if constexpr( N == for_nothing_value::encode ) { - return sizeof...( As ); - } - return ( std::size_t( !As::template is_nothing< Traits >( x ) ) + ... ); - } - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4127 ) -#endif - - template< typename A, template< typename... > class Traits, typename Consumer, typename C > - static void produce_member( Consumer& consumer, const C& x ) - { - if( ( N == for_nothing_value::encode ) || ( !A::template is_nothing< Traits >( x ) ) ) { - A::template produce_key< Traits >( consumer ); - A::template produce< Traits >( consumer, x ); - consumer.member(); - } - } - -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - - template< template< typename... > class Traits = traits, typename Consumer, typename C > - static void produce( Consumer& consumer, const C& x ) - { - const auto size = produce_size< Traits >( x ); - consumer.begin_object( size ); - ( produce_member< As, Traits >( consumer, x ), ... ); - consumer.end_object( size ); - } - - template< typename A, template< typename... > class Traits, typename C > - [[nodiscard]] static bool equal_member( const std::map< std::string, basic_value< Traits >, std::less<> >& a, C& x ) - { - if( !A::template is_nothing< Traits >( x ) ) { - return a.at( A::template key< Traits >() ) == A::read( x ); - } - if constexpr( N == for_nothing_value::encode ) { - return a.at( A::template key< Traits >() ).is_null(); - } - const auto i = a.find( A::template key< Traits >() ); - return ( i == a.end() ) || i->second.is_null(); - } - - template< template< typename... > class Traits, typename C > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const C& rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - if( p.is_object() ) { - const auto& a = p.get_object(); - if( p.get_object().size() == sizeof...( As ) ) { - return ( equal_member< As >( a, rhs ) && ... ); - } - } - return false; - } - }; - -} // namespace tao::json::binding::internal - -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - -#endif diff --git a/include/tao/json/binding/internal/type_key.hpp b/include/tao/json/binding/internal/type_key.hpp deleted file mode 100644 index fd42a51e..00000000 --- a/include/tao/json/binding/internal/type_key.hpp +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_BINDING_INTERNAL_TYPE_KEY_HPP -#define TAO_JSON_BINDING_INTERNAL_TYPE_KEY_HPP - -#include - -#include "../../internal/string_t.hpp" -#include "../../internal/type_traits.hpp" - -namespace tao::json::binding::internal -{ - struct use_default_key - {}; - - template< typename K, typename V > - struct type_key; - - template< char... Cs, typename V > - struct type_key< json::internal::string_t< Cs... >, V > - { - template< template< typename... > class Traits > - [[nodiscard]] static std::string key() - { - return json::internal::string_t< Cs... >::as_string(); - } - - template< template< typename... > class Traits = traits, typename Consumer > - static void produce_key( Consumer& consumer ) - { - consumer.key( json::internal::string_t< Cs... >::as_string_view() ); - } - }; - - template< typename V > - struct type_key< use_default_key, V > - { - template< template< typename... > class Traits > - [[nodiscard]] static std::string key() - { - return Traits< V >::template default_key< Traits >::as_string(); - } - - template< template< typename... > class Traits = traits, typename Consumer > - static void produce_key( Consumer& consumer ) - { - consumer.key( Traits< V >::template default_key< Traits >::as_string_view() ); - } - }; - -} // namespace tao::json::binding::internal - -#endif diff --git a/include/tao/json/binding/member.hpp b/include/tao/json/binding/member.hpp deleted file mode 100644 index eb785a34..00000000 --- a/include/tao/json/binding/member.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_BINDING_MEMBER_HPP -#define TAO_JSON_BINDING_MEMBER_HPP - -#include - -#include "element.hpp" -#include "member_kind.hpp" - -#include "internal/type_key.hpp" - -namespace tao::json::binding -{ - template< member_kind R, typename K, auto P > - struct member - : element< P >, - internal::type_key< K, typename binding::element< P >::internal_t > - { - static constexpr member_kind kind = R; - - template< template< typename... > class Traits, typename C > - [[nodiscard]] static bool is_nothing( const C& x ) - { - return json::internal::is_nothing< Traits >( binding::element< P >::read( x ) ); - } - }; - -} // namespace tao::json::binding - -#endif diff --git a/include/tao/json/binding/member_kind.hpp b/include/tao/json/binding/member_kind.hpp deleted file mode 100644 index 019dad08..00000000 --- a/include/tao/json/binding/member_kind.hpp +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_BINDING_MEMBER_KIND_HPP -#define TAO_JSON_BINDING_MEMBER_KIND_HPP - -namespace tao::json::binding -{ - enum class member_kind : bool - { - optional, - required - }; - -} // namespace tao::json::binding - -#endif diff --git a/include/tao/json/binding/versions.hpp b/include/tao/json/binding/versions.hpp deleted file mode 100644 index 5759c5e9..00000000 --- a/include/tao/json/binding/versions.hpp +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_BINDING_VERSIONS_HPP -#define TAO_JSON_BINDING_VERSIONS_HPP - -#include -#include - -#include "../forward.hpp" -#include "../internal/format.hpp" -#include "../internal/type_traits.hpp" - -namespace tao::json::binding -{ - template< typename... Vs > - struct versions; - - template< typename V > - struct versions< V > - : V - {}; - - template< typename V, typename... Vs > - struct versions< V, Vs... > - : V - { - template< typename C > - static void throw_on_error( const bool ok, const std::exception_ptr& e ) - { - if( !ok ) { - try { - std::rethrow_exception( e ); // TODO: Did I miss a way to avoid the throw? - } - catch( ... ) { - std::throw_with_nested( std::runtime_error( json::internal::format( "all versions failed for type ", pegtl::internal::demangle< C >(), " -- see nested for first error" ) ) ); - } - } - } - - template< template< typename... > class Traits, typename C > - [[nodiscard]] static std::exception_ptr first_to( const basic_value< Traits >& v, C& x ) noexcept - { - try { - if constexpr( json::internal::has_to< V, basic_value< Traits >, C > ) { - V::to( v, x ); - } - else if constexpr( json::internal::has_as< V, basic_value< Traits > > ) { - x = V::as( v ); - } - else { - static_assert( std::is_void_v< V >, "neither V::to() nor V::as() found" ); - } - return std::exception_ptr(); - } - catch( ... ) { - return std::current_exception(); - } - } - - template< typename A, template< typename... > class Traits, typename C > - [[nodiscard]] static bool later_to( const basic_value< Traits >& v, C& x ) noexcept - { - try { - if constexpr( json::internal::has_to< A, basic_value< Traits >, C > ) { - A::to( v, x ); - } - else if constexpr( json::internal::has_as< A, basic_value< Traits > > ) { - x = A::as( v ); - } - else { - static_assert( std::is_void_v< A >, "neither A::to() nor A::as() found" ); - } - return true; - } - catch( ... ) { - return false; - } - } - - template< template< typename... > class Traits, typename C > - static void to( const basic_value< Traits >& v, C& x ) - { - const std::exception_ptr e = first_to( v, x ); - const bool ok = ( ( e == std::exception_ptr() ) || ... || later_to< Vs >( v, x ) ); - throw_on_error< C >( ok, e ); - } - - template< template< typename... > class Traits, typename Producer, typename C > - [[nodiscard]] static std::exception_ptr first_consume( Producer& parser, C& x ) - { - try { - auto m = parser.mark(); - V::template consume< Traits >( parser, x ); - (void)m( true ); - return std::exception_ptr(); - } - catch( ... ) { - return std::current_exception(); - } - } - - template< typename A, template< typename... > class Traits, typename Producer, typename C > - [[nodiscard]] static bool later_consume( Producer& parser, C& x ) - { - try { - auto m = parser.mark(); - A::template consume< Traits >( parser, x ); - return m( true ); - } - catch( ... ) { - return false; - } - } - - template< template< typename... > class Traits, typename Producer, typename C > - static void consume( Producer& parser, C& x ) - { - const std::exception_ptr e = first_consume< Traits >( parser, x ); - const bool ok = ( ( e == std::exception_ptr() ) || ... || later_consume< Vs, Traits >( parser, x ) ); - throw_on_error< C >( ok, e ); - } - }; - -} // namespace tao::json::binding - -#endif diff --git a/include/tao/json/cbor.hpp b/include/tao/json/cbor.hpp deleted file mode 100644 index ccd77f60..00000000 --- a/include/tao/json/cbor.hpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CBOR_HPP -#define TAO_JSON_CBOR_HPP - -#include "../json.hpp" - -#include "cbor/consume_file.hpp" -#include "cbor/consume_string.hpp" -#include "cbor/from_file.hpp" -#include "cbor/from_input.hpp" -#include "cbor/from_string.hpp" -#include "cbor/parts_parser.hpp" -#include "cbor/to_stream.hpp" -#include "cbor/to_string.hpp" - -#endif diff --git a/include/tao/json/cbor/consume_file.hpp b/include/tao/json/cbor/consume_file.hpp deleted file mode 100644 index b09adf70..00000000 --- a/include/tao/json/cbor/consume_file.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CBOR_CONSUME_FILE_HPP -#define TAO_JSON_CBOR_CONSUME_FILE_HPP - -#include - -#include "../external/pegtl/file_input.hpp" - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "parts_parser.hpp" - -namespace tao::json::cbor -{ - template< typename T, template< typename... > class Traits = traits, typename F > - [[nodiscard]] T consume_file( F&& filename ) - { - cbor::basic_parts_parser< utf8_mode::check, pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); - return json::consume< T, Traits >( pp ); - } - - template< template< typename... > class Traits = traits, typename F, typename T > - void consume_file( F&& filename, T& t ) - { - cbor::basic_parts_parser< utf8_mode::check, pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); - json::consume< Traits >( pp, t ); - } - -} // namespace tao::json::cbor - -#endif diff --git a/include/tao/json/cbor/consume_string.hpp b/include/tao/json/cbor/consume_string.hpp deleted file mode 100644 index a6d54dd5..00000000 --- a/include/tao/json/cbor/consume_string.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CBOR_CONSUME_STRING_HPP -#define TAO_JSON_CBOR_CONSUME_STRING_HPP - -#include "../external/pegtl/string_input.hpp" - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "parts_parser.hpp" - -namespace tao::json::cbor -{ - template< typename T, template< typename... > class Traits = traits, typename F > - [[nodiscard]] T consume_string( F&& string ) - { - cbor::basic_parts_parser< utf8_mode::check, pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); - return json::consume< T, Traits >( pp ); - } - - template< template< typename... > class Traits = traits, typename F, typename T > - void consume_string( F&& string, T& t ) - { - cbor::basic_parts_parser< utf8_mode::check, pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); - json::consume< Traits >( pp, t ); - } - -} // namespace tao::json::cbor - -#endif diff --git a/include/tao/json/cbor/events/from_file.hpp b/include/tao/json/cbor/events/from_file.hpp deleted file mode 100644 index ea94b7b3..00000000 --- a/include/tao/json/cbor/events/from_file.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CBOR_EVENTS_FROM_FILE_HPP -#define TAO_JSON_CBOR_EVENTS_FROM_FILE_HPP - -#include - -#include "../../external/pegtl/file_input.hpp" -#include "../../external/pegtl/parse.hpp" - -#include "../internal/grammar.hpp" - -namespace tao::json::cbor::events -{ - // Events producer to parse a file containing a CBOR string representation. - - template< typename T, typename Consumer > - void from_file( Consumer& consumer, T&& filename ) - { - pegtl::file_input< pegtl::tracking_mode::lazy > in( std::forward< T >( filename ) ); - pegtl::parse< internal::grammar >( in, consumer ); - } - -} // namespace tao::json::cbor::events - -#endif diff --git a/include/tao/json/cbor/events/from_input.hpp b/include/tao/json/cbor/events/from_input.hpp deleted file mode 100644 index 22a46383..00000000 --- a/include/tao/json/cbor/events/from_input.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CBOR_EVENTS_FROM_INPUT_HPP -#define TAO_JSON_CBOR_EVENTS_FROM_INPUT_HPP - -#include - -#include "../../external/pegtl/parse.hpp" - -#include "../internal/grammar.hpp" - -namespace tao::json::cbor::events -{ - // Events producers that parse CBOR from a PEGTL input (or something compatible). - - template< typename Consumer, typename Input > - void from_input( Consumer& consumer, Input&& in ) - { - pegtl::parse< cbor::internal::grammar >( std::forward< Input >( in ), consumer ); - } - - template< typename Consumer, typename Input > - void from_input_embedded( Consumer& consumer, Input&& in ) - { - pegtl::parse< cbor::internal::embedded >( std::forward< Input >( in ), consumer ); - } - - template< typename Consumer, typename Outer, typename Input > - void from_input_nested( Consumer& consumer, const Outer& oi, Input&& in ) - { - pegtl::parse_nested< cbor::internal::grammar >( oi, std::forward< Input >( in ), consumer ); - } - - template< typename Consumer, typename Outer, typename Input > - void from_input_embedded_nested( Consumer& consumer, const Outer& oi, Input&& in ) - { - pegtl::parse_nested< cbor::internal::embedded >( oi, std::forward< Input >( in ), consumer ); - } - -} // namespace tao::json::cbor::events - -#endif diff --git a/include/tao/json/cbor/events/from_string.hpp b/include/tao/json/cbor/events/from_string.hpp deleted file mode 100644 index 3659ae50..00000000 --- a/include/tao/json/cbor/events/from_string.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CBOR_EVENTS_FROM_STRING_HPP -#define TAO_JSON_CBOR_EVENTS_FROM_STRING_HPP - -#include -#include - -#include "../../external/pegtl/memory_input.hpp" - -#include "from_input.hpp" - -namespace tao::json::cbor::events -{ - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t byte_in_line = 0 ) - { - pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::cbor::events::from_string", byte, line, byte_in_line ); - cbor::events::from_input( consumer, std::move( in ) ); - } - - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) - { - cbor::events::from_string( consumer, data, size, source.c_str(), byte, line, column ); - } - - template< typename Consumer, typename... Ts > - void from_string( Consumer& consumer, const std::string_view data, Ts&&... ts ) - { - cbor::events::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); - } - -} // namespace tao::json::cbor::events - -#endif diff --git a/include/tao/json/cbor/events/to_stream.hpp b/include/tao/json/cbor/events/to_stream.hpp deleted file mode 100644 index db66da17..00000000 --- a/include/tao/json/cbor/events/to_stream.hpp +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CBOR_EVENTS_TO_STREAM_HPP -#define TAO_JSON_CBOR_EVENTS_TO_STREAM_HPP - -#include -#include -#include -#include - -#include "../internal/major.hpp" - -#include "../../binary_view.hpp" - -#include "../../internal/endian.hpp" - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4310 ) -#endif - -namespace tao::json::cbor::events -{ - class to_stream - { - private: - std::ostream& os; - - public: - explicit to_stream( std::ostream& in_os ) noexcept - : os( in_os ) - {} - - void null() - { - os.put( char( std::uint8_t( internal::major::OTHER ) + 22 ) ); - } - - void boolean( const bool v ) - { - os.put( char( std::uint8_t( internal::major::OTHER ) + 20 + std::uint8_t( v ) ) ); - } - - void number( const internal::major m, const std::uint64_t v ) - { - if( v < 24 ) { - os.put( char( std::uint8_t( m ) + v ) ); - } - else if( v < 256 ) { - os.put( char( std::uint8_t( m ) + 24 ) ); - os.put( char( v ) ); - } - else if( v < 65536 ) { - os.put( char( std::uint8_t( m ) + 25 ) ); - const std::uint16_t x = json::internal::h_to_be( std::uint16_t( v ) ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else if( v < 4294967296ULL ) { - os.put( char( std::uint8_t( m ) + 26 ) ); - const std::uint32_t x = json::internal::h_to_be( std::uint32_t( v ) ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else { - os.put( char( std::uint8_t( m ) + 27 ) ); - const std::uint64_t x = json::internal::h_to_be( v ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - } - - void number( const std::int64_t v ) - { - if( v >= 0 ) { - number( internal::major::UNSIGNED, v ); - } - else { - number( internal::major::NEGATIVE, -( v + 1 ) ); - } - } - - void number( const std::uint64_t v ) - { - number( internal::major::UNSIGNED, v ); - } - - void number( const double v ) - { - std::uint64_t n; - std::memcpy( &n, &v, sizeof( n ) ); - n = json::internal::h_to_be( n ); - os.put( char( std::uint8_t( internal::major::OTHER ) + 27 ) ); - os.write( reinterpret_cast< const char* >( &n ), sizeof( n ) ); - } - - void string( const std::string_view v ) - { - number( internal::major::STRING, v.size() ); - os.write( v.data(), v.size() ); - } - - void binary( const tao::binary_view v ) - { - number( internal::major::BINARY, v.size() ); - os.write( reinterpret_cast< const char* >( v.data() ), v.size() ); - } - - void begin_array() - { - os.put( char( std::uint8_t( internal::major::ARRAY ) + internal::minor_mask ) ); - } - - void begin_array( const std::size_t size ) - { - number( internal::major::ARRAY, size ); - } - - void element() noexcept - {} - - void end_array() - { - os.put( char( 0xff ) ); - } - - void end_array( const std::size_t /*unused*/ ) noexcept - {} - - void begin_object() - { - os.put( char( std::uint8_t( internal::major::OBJECT ) + internal::minor_mask ) ); - } - - void begin_object( const std::size_t size ) - { - number( internal::major::OBJECT, size ); - } - - void key( const std::string_view v ) - { - string( v ); - } - - void member() noexcept - {} - - void end_object() - { - os.put( char( 0xff ) ); - } - - void end_object( const std::size_t /*unused*/ ) noexcept - {} - }; - -} // namespace tao::json::cbor::events - -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - -#endif diff --git a/include/tao/json/cbor/events/to_string.hpp b/include/tao/json/cbor/events/to_string.hpp deleted file mode 100644 index f323e3c7..00000000 --- a/include/tao/json/cbor/events/to_string.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CBOR_EVENTS_TO_STRING_HPP -#define TAO_JSON_CBOR_EVENTS_TO_STRING_HPP - -#include - -#include "to_stream.hpp" - -namespace tao::json::cbor::events -{ - struct to_string - : to_stream - { - std::ostringstream oss; - - to_string() - : to_stream( oss ) - { - } - - [[nodiscard]] std::string value() const - { - return oss.str(); - } - }; - -} // namespace tao::json::cbor::events - -#endif diff --git a/include/tao/json/cbor/from_file.hpp b/include/tao/json/cbor/from_file.hpp deleted file mode 100644 index 89f18ff1..00000000 --- a/include/tao/json/cbor/from_file.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CBOR_FROM_FILE_HPP -#define TAO_JSON_CBOR_FROM_FILE_HPP - -#include -#include - -#include "../events/to_value.hpp" -#include "../events/transformer.hpp" - -#include "events/from_file.hpp" - -namespace tao::json::cbor -{ - template< template< typename... > class Traits, template< typename... > class... Transformers > - [[nodiscard]] basic_value< Traits > basic_from_file( const std::string& filename ) - { - json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; - events::from_file( consumer, filename ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers > - [[nodiscard]] value from_file( const std::string& filename ) - { - return basic_from_file< traits, Transformers... >( filename ); - } - -} // namespace tao::json::cbor - -#endif diff --git a/include/tao/json/cbor/from_input.hpp b/include/tao/json/cbor/from_input.hpp deleted file mode 100644 index c5df41f9..00000000 --- a/include/tao/json/cbor/from_input.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CBOR_FROM_INPUT_HPP -#define TAO_JSON_CBOR_FROM_INPUT_HPP - -#include -#include - -#include "../events/to_value.hpp" -#include "../events/transformer.hpp" - -#include "events/from_input.hpp" - -namespace tao::json::cbor -{ - template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] basic_value< Traits > basic_from_input( Ts&&... ts ) - { - json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; - cbor::events::from_input( consumer, std::forward< Ts >( ts )... ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] value from_input( Ts&&... ts ) - { - return basic_from_input< traits, Transformers... >( std::forward< Ts >( ts )... ); - } - -} // namespace tao::json::cbor - -#endif diff --git a/include/tao/json/cbor/from_string.hpp b/include/tao/json/cbor/from_string.hpp deleted file mode 100644 index d3c29112..00000000 --- a/include/tao/json/cbor/from_string.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CBOR_FROM_STRING_HPP -#define TAO_JSON_CBOR_FROM_STRING_HPP - -#include - -#include "../events/to_value.hpp" -#include "../events/transformer.hpp" - -#include "events/from_string.hpp" - -namespace tao::json::cbor -{ - template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] basic_value< Traits > basic_from_string( Ts&&... ts ) - { - json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; - events::from_string( consumer, std::forward< Ts >( ts )... ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] value from_string( Ts&&... ts ) - { - return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); - } - -} // namespace tao::json::cbor - -#endif diff --git a/include/tao/json/cbor/internal/grammar.hpp b/include/tao/json/cbor/internal/grammar.hpp deleted file mode 100644 index 12449e92..00000000 --- a/include/tao/json/cbor/internal/grammar.hpp +++ /dev/null @@ -1,417 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CBOR_INTERNAL_GRAMMAR_HPP -#define TAO_JSON_CBOR_INTERNAL_GRAMMAR_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "major.hpp" - -#include "../../binary_view.hpp" -#include "../../external/pegtl.hpp" -#include "../../forward.hpp" -#include "../../internal/endian.hpp" -#include "../../internal/format.hpp" -#include "../../internal/parse_util.hpp" -#include "../../utf8.hpp" - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4702 ) -#endif - -namespace tao::json::cbor::internal -{ - template< typename Input > - void consume_or_throw( Input& in, const std::size_t size = 1 ) - { - json::internal::throw_on_empty( in, size ); - in.bump_in_this_line( size ); - } - - template< typename Input > - [[nodiscard]] major peek_major_unsafe( Input& in ) - { - return static_cast< major >( in.peek_uint8() & major_mask ); - } - - template< typename Input > - [[nodiscard]] std::uint8_t peek_minor_unsafe( Input& in ) - { - return in.peek_uint8() & minor_mask; - } - - template< typename Input > - [[nodiscard]] major peek_major( Input& in ) - { - return static_cast< major >( json::internal::peek_uint8( in ) & major_mask ); - } - - // Assume in.size( 1 ) >= 1 and in.peek_uint8() is the byte with major/minor. - - template< typename Input > - [[nodiscard]] double read_fp16( Input& in ) - { - json::internal::throw_on_empty( in, 3 ); - - const int half = ( in.peek_uint8( 1 ) << 8 ) + in.peek_uint8( 2 ); - const int exp = ( half >> 10 ) & 0x1f; - const int mant = half & 0x3ff; - - double val; - if( exp == 0 ) { - val = std::ldexp( mant, -24 ); - } - else if( exp != 31 ) { - val = std::ldexp( mant + 1024, exp - 25 ); - } - else { - val = ( mant == 0 ) ? INFINITY : NAN; - } - in.bump_in_this_line( 3 ); - return half & 0x8000 ? -val : val; - } - - template< typename Input > - [[nodiscard]] std::uint64_t read_embedded_unsafe( Input& in ) - { - const auto result = peek_minor_unsafe( in ) & minor_mask; - in.bump_in_this_line(); - return result; - } - - template< typename Input > - [[nodiscard]] std::uint64_t read_unsigned_unsafe( Input& in ) - { - switch( const auto m = peek_minor_unsafe( in ) ) { - default: - return read_embedded_unsafe( in ); - case 24: - return json::internal::read_big_endian_number< std::uint64_t, std::uint8_t >( in, 1 ); - case 25: - return json::internal::read_big_endian_number< std::uint64_t, std::uint16_t >( in, 1 ); - case 26: - return json::internal::read_big_endian_number< std::uint64_t, std::uint32_t >( in, 1 ); - case 27: - return json::internal::read_big_endian_number< std::uint64_t >( in, 1 ); - case 28: - case 29: - case 30: - case 31: - throw pegtl::parse_error( json::internal::format( "unexpected minor ", m, " for number or length" ), in ); - } - } - - template< typename Input > - [[nodiscard]] std::int64_t read_negative_unsafe( Input& in ) - { - const auto u = read_unsigned_unsafe( in ); - if( u > 9223372036854775808ULL ) { - throw pegtl::parse_error( "negative integer overflow", in ); - } - return std::int64_t( ~u ); - } - - template< typename Input > - [[nodiscard]] std::size_t read_size_unsafe( Input& in ) - { - const auto s = read_unsigned_unsafe( in ); - if( s > static_cast< std::uint64_t >( ( std::numeric_limits< std::size_t >::max )() ) ) { - throw pegtl::parse_error( "cbor size exceeds size_t " + std::to_string( s ), in ); - } - return static_cast< std::size_t >( s ); - } - - template< utf8_mode U, typename Result, typename Input > - [[nodiscard]] Result read_string_1( Input& in ) - { - const auto size = read_size_unsafe( in ); - json::internal::throw_on_empty( in, size ); - using value_t = typename Result::value_type; - const auto* pointer = reinterpret_cast< const value_t* >( in.current() ); - Result result( pointer, size ); - json::internal::consume_utf8_throws< U >( in, size ); - return result; - } - - template< utf8_mode U, typename Result, typename Input > - [[nodiscard]] Result read_string_n( Input& in, const major m ) - { - Result result; - in.bump_in_this_line(); - while( json::internal::peek_uint8( in ) != 0xff ) { - if( peek_major_unsafe( in ) != m ) { - throw pegtl::parse_error( "non-matching fragment in indefinite length string", in ); - } - const auto size = read_size_unsafe( in ); - json::internal::throw_on_empty( in, size ); - using value_t = typename Result::value_type; - const auto* pointer = static_cast< const value_t* >( static_cast< const void* >( in.current() ) ); - result.insert( result.end(), pointer, pointer + size ); - json::internal::consume_utf8_throws< U >( in, size ); - } - in.bump_in_this_line(); - return result; - } - - template< utf8_mode V > - struct data - { - using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; - - template< pegtl::apply_mode A, - pegtl::rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename Consumer > - [[nodiscard]] static bool match( Input& in, Consumer& consumer ) - { - if( !in.empty() ) { - parse_unsafe( in, consumer ); - return true; - } - return false; - } - - private: - template< typename Input, typename Consumer > - static void parse_unsafe( Input& in, Consumer& consumer ) - { - switch( peek_major_unsafe( in ) ) { - case major::UNSIGNED: - consumer.number( read_unsigned_unsafe( in ) ); - return; - case major::NEGATIVE: - consumer.number( read_negative_unsafe( in ) ); - return; - case major::BINARY: - parse_binary_unsafe( in, consumer ); - return; - case major::STRING: - parse_string_unsafe( in, consumer ); - return; - case major::ARRAY: - parse_array_unsafe( in, consumer ); - return; - case major::OBJECT: - parse_object_unsafe( in, consumer ); - return; - case major::TAG: - parse_tag_unsafe( in, consumer ); - return; - case major::OTHER: - parse_other_unsafe( in, consumer ); - return; - } - // LCOV_EXCL_START - assert( false ); - // LCOV_EXCL_STOP - } - - template< typename Input, typename Consumer > - static void parse_string_unsafe( Input& in, Consumer& consumer ) - { - if( peek_minor_unsafe( in ) != minor_mask ) { - consumer.string( read_string_1< V, std::string_view >( in ) ); - } - else { - consumer.string( read_string_n< V, std::string >( in, major::STRING ) ); - } - } - - template< typename Input, typename Consumer > - static void parse_binary_unsafe( Input& in, Consumer& consumer ) - { - if( peek_minor_unsafe( in ) != minor_mask ) { - consumer.binary( read_string_1< utf8_mode::trust, tao::binary_view >( in ) ); - } - else { - consumer.binary( read_string_n< utf8_mode::trust, std::vector< std::byte > >( in, major::BINARY ) ); - } - } - - template< typename Input, typename Consumer > - static void parse_key_unsafe( Input& in, Consumer& consumer ) - { - if( peek_minor_unsafe( in ) != minor_mask ) { - consumer.key( read_string_1< V, std::string_view >( in ) ); - } - else { - consumer.key( read_string_n< V, std::string >( in, major::STRING ) ); - } - } - - template< typename Input, typename Consumer > - static void parse_array_1( Input& in, Consumer& consumer ) - { - const auto size = read_size_unsafe( in ); - consumer.begin_array( size ); - for( std::size_t i = 0; i < size; ++i ) { - json::internal::throw_on_empty( in ); - parse_unsafe( in, consumer ); - consumer.element(); - } - consumer.end_array( size ); - } - - template< typename Input, typename Consumer > - static void parse_array_n( Input& in, Consumer& consumer ) - { - in.bump_in_this_line(); - consumer.begin_array(); - while( json::internal::peek_uint8( in ) != 0xff ) { - parse_unsafe( in, consumer ); - consumer.element(); - } - in.bump_in_this_line(); - consumer.end_array(); - } - - template< typename Input, typename Consumer > - static void parse_array_unsafe( Input& in, Consumer& consumer ) - { - if( peek_minor_unsafe( in ) != minor_mask ) { - parse_array_1( in, consumer ); - } - else { - parse_array_n( in, consumer ); - } - } - - template< typename Input, typename Consumer > - static void parse_object_1( Input& in, Consumer& consumer ) - { - const auto size = read_size_unsafe( in ); - consumer.begin_object( size ); - for( std::size_t i = 0; i < size; ++i ) { - if( peek_major( in ) != major::STRING ) { - throw pegtl::parse_error( "non-string object key", in ); - } - parse_key_unsafe( in, consumer ); - json::internal::throw_on_empty( in ); - parse_unsafe( in, consumer ); - consumer.member(); - } - consumer.end_object( size ); - } - - template< typename Input, typename Consumer > - static void parse_object_n( Input& in, Consumer& consumer ) - { - in.bump_in_this_line(); - consumer.begin_object(); - while( json::internal::peek_uint8( in ) != 0xff ) { - if( peek_major_unsafe( in ) != major::STRING ) { - throw pegtl::parse_error( "non-string object key", in ); - } - parse_key_unsafe( in, consumer ); - json::internal::throw_on_empty( in ); - parse_unsafe( in, consumer ); - consumer.member(); - } - in.bump_in_this_line(); - consumer.end_object(); - } - - template< typename Input, typename Consumer > - static void parse_object_unsafe( Input& in, Consumer& consumer ) - { - if( peek_minor_unsafe( in ) != minor_mask ) { - parse_object_1( in, consumer ); - } - else { - parse_object_n( in, consumer ); - } - } - - template< typename Input, typename Consumer > - static void parse_tag_unsafe( Input& in, Consumer& /*unused*/ ) - { - switch( const auto m = peek_minor_unsafe( in ) ) { - default: - in.bump_in_this_line(); - return; - case 24: - consume_or_throw( in, 2 ); - return; - case 25: - consume_or_throw( in, 3 ); - return; - case 26: - consume_or_throw( in, 5 ); - return; - case 27: - consume_or_throw( in, 9 ); - return; - case 28: - case 29: - case 30: - case 31: - throw pegtl::parse_error( json::internal::format( "unexpected minor ", m, " for tag" ), in ); - } - } - - template< typename Input, typename Consumer > - static void parse_other_unsafe( Input& in, Consumer& consumer ) - { - switch( const auto m = peek_minor_unsafe( in ) ) { - case 20: - consumer.boolean( false ); - in.bump_in_this_line(); - return; - case 21: - consumer.boolean( true ); - in.bump_in_this_line(); - return; - case 22: - consumer.null(); - in.bump_in_this_line(); - return; - case 25: - consumer.number( read_fp16( in ) ); - return; - case 26: - consumer.number( json::internal::read_big_endian_number< float >( in, 1 ) ); - return; - case 27: - consumer.number( json::internal::read_big_endian_number< double >( in, 1 ) ); - return; - default: - throw pegtl::parse_error( json::internal::format( "unsupported minor ", m, " for major 7" ), in ); - } - } - }; - - template< utf8_mode V > - struct basic_grammar - : pegtl::must< data< V >, pegtl::eof > - { - }; - - template< utf8_mode V > - struct basic_embedded - : pegtl::must< data< V > > - { - }; - - using grammar = basic_grammar< utf8_mode::check >; - using embedded = basic_embedded< utf8_mode::check >; - -} // namespace tao::json::cbor::internal - -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - -#endif diff --git a/include/tao/json/cbor/internal/major.hpp b/include/tao/json/cbor/internal/major.hpp deleted file mode 100644 index e0a9ebb7..00000000 --- a/include/tao/json/cbor/internal/major.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CBOR_INTERNAL_MAJOR_HPP -#define TAO_JSON_CBOR_INTERNAL_MAJOR_HPP - -#include - -namespace tao::json::cbor::internal -{ - enum class major : std::uint8_t - { - UNSIGNED = 0, - NEGATIVE = 0x20, - BINARY = 0x40, - STRING = 0x60, - ARRAY = 0x80, - OBJECT = 0xa0, - TAG = 0xc0, - OTHER = 0xe0 - }; - - static constexpr std::uint8_t major_mask = 0xe0; - static constexpr std::uint8_t minor_mask = 0x1f; - -} // namespace tao::json::cbor::internal - -#endif diff --git a/include/tao/json/cbor/parts_parser.hpp b/include/tao/json/cbor/parts_parser.hpp deleted file mode 100644 index 81bcfad5..00000000 --- a/include/tao/json/cbor/parts_parser.hpp +++ /dev/null @@ -1,392 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CBOR_PARTS_PARSER_HPP -#define TAO_JSON_CBOR_PARTS_PARSER_HPP - -#include -#include - -#include "../events/discard.hpp" -#include "../external/pegtl/string_input.hpp" -#include "../utf8.hpp" - -#include "internal/grammar.hpp" - -namespace tao::json::cbor -{ - namespace internal - { - template< typename Input > - [[nodiscard]] major peek_first_major( Input& in ) - { - const auto m = peek_major( in ); - if( m != major::TAG ) { - return m; - } - switch( auto n = peek_minor_unsafe( in ) ) { - default: - in.bump_in_this_line(); - break; - case 24: - consume_or_throw( in, 2 ); - break; - case 25: - consume_or_throw( in, 3 ); - break; - case 26: - consume_or_throw( in, 5 ); - break; - case 27: - consume_or_throw( in, 9 ); - break; - case 28: - case 29: - case 30: - case 31: - throw pegtl::parse_error( json::internal::format( "unexpected minor ", n, " for tag" ), in ); - } - return peek_major( in ); - } - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4702 ) -#endif - template< typename Input > - [[nodiscard]] bool read_boolean( Input& in ) - { - const auto b = json::internal::peek_uint8( in ); - switch( b ) { - case std::uint8_t( major::OTHER ) + 20: - case std::uint8_t( major::OTHER ) + 21: - in.bump_in_this_line( 1 ); - return bool( b - std::uint8_t( major::OTHER ) - 20 ); - default: - throw pegtl::parse_error( "expected boolean", in ); - } - std::abort(); - } -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - - } // namespace internal - - template< utf8_mode V = utf8_mode::check, typename Input = pegtl::string_input< pegtl::tracking_mode::lazy > > - class basic_parts_parser - { - public: - template< typename... Ts > - explicit basic_parts_parser( Ts&&... ts ) - : m_input( std::forward< Ts >( ts )... ) - { - } - - [[nodiscard]] bool empty() - { - return m_input.empty(); - } - - [[nodiscard]] bool null() - { - if( json::internal::peek_uint8( m_input ) == std::uint8_t( internal::major::OTHER ) + 22 ) { - m_input.bump_in_this_line( 1 ); - return true; - } - return false; - } - - [[nodiscard]] bool boolean() - { - return internal::read_boolean( m_input ); - } - - private: - void check_major( const internal::major m, const char* e ) - { - const auto b = internal::peek_first_major( m_input ); - if( b != m ) { - throw pegtl::parse_error( e, m_input ); - } - } - - template< utf8_mode U, typename T > - [[nodiscard]] T string_impl( const internal::major m, const char* e ) - { - check_major( m, e ); - if( internal::peek_minor_unsafe( m_input ) != internal::minor_mask ) { - return internal::read_string_1< U, T >( m_input ); - } - return internal::read_string_n< U, T >( m_input, m ); - } - - public: - [[nodiscard]] std::string string() - { - return string_impl< V, std::string >( internal::major::STRING, "expected string" ); - } - - [[nodiscard]] std::string binary() - { - return string_impl< utf8_mode::trust, std::vector< std::byte > >( internal::major::BINARY, "expected binary" ); - } - - [[nodiscard]] std::string key() - { - return string(); - } - - [[nodiscard]] std::string_view string_view() - { - const auto b = json::internal::peek_uint8( m_input ); - if( b != std::uint8_t( internal::major::STRING ) + internal::minor_mask ) { - throw pegtl::parse_error( "expected definitive string", m_input ); - } - return internal::read_string_1< V, std::string_view >( m_input ); - } - - [[nodiscard]] tao::binary_view binary_view() - { - const auto b = json::internal::peek_uint8( m_input ); - if( b != std::uint8_t( internal::major::BINARY ) + internal::minor_mask ) { - throw pegtl::parse_error( "expected definitive binary", m_input ); - } - return internal::read_string_1< utf8_mode::trust, tao::binary_view >( m_input ); - } - - [[nodiscard]] std::string_view key_view() - { - return string_view(); - } - - private: - [[nodiscard]] std::int64_t number_signed_unsigned() - { - const auto u = internal::read_unsigned_unsafe( m_input ); - if( u > 9223372036854775807ULL ) { - throw pegtl::parse_error( "positive integer overflow", m_input ); - } - return std::int64_t( u ); - } - - [[nodiscard]] std::int64_t number_signed_negative() - { - const auto u = internal::read_unsigned_unsafe( m_input ); - if( u > 9223372036854775808ULL ) { - throw pegtl::parse_error( "negative integer overflow", m_input ); - } - return std::int64_t( ~u ); - } - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4702 ) -#endif - public: - [[nodiscard]] std::int64_t number_signed() - { - const auto b = internal::peek_first_major( m_input ); - switch( b ) { - case internal::major::UNSIGNED: - return number_signed_unsigned(); - case internal::major::NEGATIVE: - return number_signed_negative(); - default: - throw pegtl::parse_error( "expected integer", m_input ); - } - std::abort(); - } -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - - [[nodiscard]] std::uint64_t number_unsigned() - { - check_major( internal::major::UNSIGNED, "expected unsigned" ); - return internal::read_unsigned_unsafe( m_input ); - } - - [[nodiscard]] double number_double() - { - const auto b = json::internal::peek_uint8( m_input ); - switch( b ) { - case std::uint8_t( internal::major::OTHER ) + 25: - return internal::read_fp16( m_input ); - case std::uint8_t( internal::major::OTHER ) + 26: - return json::internal::read_big_endian_number< float >( m_input + 1 ); - case std::uint8_t( internal::major::OTHER ) + 27: - return json::internal::read_big_endian_number< double >( m_input + 1 ); - default: - throw pegtl::parse_error( "expected floating point number", m_input ); - } - } - - private: - struct state_t - { - state_t() = default; - - explicit state_t( const std::size_t in_size ) - : size( in_size ) - {} - - std::size_t i = 0; - std::optional< std::size_t > size; - }; - - [[nodiscard]] state_t begin_container() - { - if( internal::peek_minor_unsafe( m_input ) == 31 ) { - m_input.bump_in_this_line( 1 ); - return state_t(); - } - return state_t( internal::read_size_unsafe( m_input ) ); - } - - public: - [[nodiscard]] state_t begin_array() - { - check_major( internal::major::ARRAY, "expected array" ); - return begin_container(); - } - - [[nodiscard]] state_t begin_object() - { - check_major( internal::major::OBJECT, "expected object" ); - return begin_container(); - } - - private: - void end_container_sized( const state_t& p ) - { - if( *p.size != p.i ) { - throw pegtl::parse_error( "container size mismatch", m_input ); - } - } - - void end_container_indefinite() - { - if( json::internal::peek_uint8( m_input ) != 0xff ) { - throw pegtl::parse_error( "container not at end", m_input ); - } - m_input.bump_in_this_line( 1 ); - } - - void end_container( const state_t& p ) - { - if( p.size ) { - end_container_sized( p ); - } - else { - end_container_indefinite(); - } - } - - public: - void end_array( const state_t& p ) - { - end_container( p ); - } - - void end_object( const state_t& p ) - { - end_container( p ); - } - - private: - void next_in_container_sized( state_t& p ) - { - if( p.i++ >= *p.size ) { - throw pegtl::parse_error( "unexpected end of sized container", m_input ); - } - } - - void next_in_container_indefinite() - { - if( json::internal::peek_uint8( m_input ) == 0xff ) { - throw pegtl::parse_error( "unexpected end of indefinite container", m_input ); - } - } - - void next_in_container( state_t& p ) - { - if( p.size ) { - next_in_container_sized( p ); - } - else { - next_in_container_indefinite(); - } - } - - public: - void element( state_t& p ) - { - next_in_container( p ); - } - - void member( state_t& p ) - { - next_in_container( p ); - } - - private: - [[nodiscard]] bool next_or_end_container_sized( state_t& p ) - { - return p.i++ < *p.size; - } - - [[nodiscard]] bool next_or_end_container_indefinite() - { - if( json::internal::peek_uint8( m_input ) == 0xff ) { - m_input.bump_in_this_line( 1 ); - return false; - } - return true; - } - - [[nodiscard]] bool next_or_end_container( state_t& p ) - { - if( p.size ) { - return next_or_end_container_sized( p ); - } - return next_or_end_container_indefinite(); - } - - public: - [[nodiscard]] bool element_or_end_array( state_t& p ) - { - return next_or_end_container( p ); - } - - [[nodiscard]] bool member_or_end_object( state_t& p ) - { - return next_or_end_container( p ); - } - - void skip_value() - { - json::events::discard consumer; // TODO: Optimise to not generate events (which requires preparing their - discarded - arguments)? - pegtl::parse< pegtl::must< internal::data< V > > >( m_input, consumer ); - } - - [[nodiscard]] auto mark() - { - return m_input.template mark< pegtl::rewind_mode::required >(); - } - - template< typename T > - void throw_parse_error( T&& t ) const - { - throw pegtl::parse_error( std::forward< T >( t ), m_input ); - } - - protected: - Input m_input; - }; - - using parts_parser = basic_parts_parser<>; - -} // namespace tao::json::cbor - -#endif diff --git a/include/tao/json/cbor/to_stream.hpp b/include/tao/json/cbor/to_stream.hpp deleted file mode 100644 index 520552b2..00000000 --- a/include/tao/json/cbor/to_stream.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CBOR_TO_STREAM_HPP -#define TAO_JSON_CBOR_TO_STREAM_HPP - -#include - -#include "../value.hpp" - -#include "../events/from_value.hpp" -#include "../events/transformer.hpp" - -#include "events/to_stream.hpp" - -namespace tao::json::cbor -{ - template< template< typename... > class... Transformers, template< typename... > class Traits > - void to_stream( std::ostream& os, const basic_value< Traits >& v ) - { - json::events::transformer< events::to_stream, Transformers... > consumer( os ); - json::events::from_value( consumer, v ); - } - -} // namespace tao::json::cbor - -#endif diff --git a/include/tao/json/cbor/to_string.hpp b/include/tao/json/cbor/to_string.hpp deleted file mode 100644 index 2f711689..00000000 --- a/include/tao/json/cbor/to_string.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CBOR_TO_STRING_HPP -#define TAO_JSON_CBOR_TO_STRING_HPP - -#include - -#include "../value.hpp" - -#include "../events/from_value.hpp" -#include "../events/transformer.hpp" - -#include "events/to_string.hpp" - -namespace tao::json::cbor -{ - template< template< typename... > class... Transformers, template< typename... > class Traits > - [[nodiscard]] std::string to_string( const basic_value< Traits >& v ) - { - json::events::transformer< events::to_string, Transformers... > consumer; - json::events::from_value( consumer, v ); - return consumer.value(); - } - -} // namespace tao::json::cbor - -#endif diff --git a/include/tao/json/consume.hpp b/include/tao/json/consume.hpp deleted file mode 100644 index 7ec5ebae..00000000 --- a/include/tao/json/consume.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONSUME_HPP -#define TAO_JSON_CONSUME_HPP - -#include - -#include "forward.hpp" - -#include "internal/type_traits.hpp" - -namespace tao::json -{ - template< typename T, template< typename... > class Traits = traits, typename Producer > - [[nodiscard]] std::enable_if_t< internal::has_consume_one< Traits, Producer, T >, T > consume( Producer& parser ) - { - return Traits< T >::template consume< Traits >( parser ); - } - - template< typename T, template< typename... > class Traits = traits, typename Producer > - [[nodiscard]] std::enable_if_t< !internal::has_consume_one< Traits, Producer, T >, T > consume( Producer& parser ) - { - T t; - Traits< T >::template consume< Traits >( parser, t ); - return t; - } - - template< template< typename... > class Traits = traits, typename Producer, typename T > - std::enable_if_t< internal::has_consume_two< Traits, Producer, T >, void > consume( Producer& parser, T& t ) - { - Traits< T >::template consume< Traits >( parser, t ); - } - - template< template< typename... > class Traits = traits, typename Producer, typename T > - std::enable_if_t< !internal::has_consume_two< Traits, Producer, T >, void > consume( Producer& parser, T& t ) - { - t = Traits< T >::template consume< Traits >( parser ); - } - -} // namespace tao::json - -#endif diff --git a/include/tao/json/consume_file.hpp b/include/tao/json/consume_file.hpp deleted file mode 100644 index 1ed6c5b2..00000000 --- a/include/tao/json/consume_file.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONSUME_FILE_HPP -#define TAO_JSON_CONSUME_FILE_HPP - -#include - -#include "external/pegtl/file_input.hpp" - -#include "consume.hpp" -#include "forward.hpp" -#include "parts_parser.hpp" - -namespace tao::json -{ - template< typename T, template< typename... > class Traits = traits, typename F > - [[nodiscard]] T consume_file( F&& filename ) - { - basic_parts_parser< pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); - return consume< T, Traits >( pp ); - } - - template< template< typename... > class Traits = traits, typename F, typename T > - void consume_file( F&& filename, T& t ) - { - basic_parts_parser< pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); - consume< Traits >( pp, t ); - } - -} // namespace tao::json - -#endif diff --git a/include/tao/json/consume_string.hpp b/include/tao/json/consume_string.hpp deleted file mode 100644 index 5c1573d8..00000000 --- a/include/tao/json/consume_string.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONSUME_STRING_HPP -#define TAO_JSON_CONSUME_STRING_HPP - -#include "external/pegtl/string_input.hpp" - -#include "consume.hpp" -#include "forward.hpp" -#include "parts_parser.hpp" - -namespace tao::json -{ - template< typename T, template< typename... > class Traits = traits, typename F > - [[nodiscard]] T consume_string( F&& string ) - { - basic_parts_parser< pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); - return consume< T, Traits >( pp ); - } - - template< template< typename... > class Traits = traits, typename F, typename T > - void consume_string( F&& string, T& t ) - { - basic_parts_parser< pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); - consume< Traits >( pp, t ); - } - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/array_traits.hpp b/include/tao/json/contrib/array_traits.hpp deleted file mode 100644 index e05bef5e..00000000 --- a/include/tao/json/contrib/array_traits.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_ARRAY_TRAITS_HPP -#define TAO_JSON_CONTRIB_ARRAY_TRAITS_HPP - -#include - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "internal/array_traits.hpp" - -namespace tao::json -{ - template< typename T, std::size_t N > - struct array_traits - : internal::array_traits< std::array< T, N > > - { - template< template< typename... > class Traits, typename... With > - static void to( const basic_value< Traits >& v, std::array< T, N >& r, With&... with ) - { - const auto& a = v.get_array(); - for( std::size_t i = 0; i < N; ++i ) { - v.to_with( r[ i ], with... ); - } - } - - template< template< typename... > class Traits, typename Producer > - static void consume( Producer& parser, std::array< T, N >& r ) - { - auto s = parser.begin_array(); - for( std::size_t i = 0; i < N; ++i ) { - parser.element( s ); - json::consume< Traits >( parser, r[ i ] ); - } - parser.end_array( s ); - } - }; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/deque_traits.hpp b/include/tao/json/contrib/deque_traits.hpp deleted file mode 100644 index 7ffbbd94..00000000 --- a/include/tao/json/contrib/deque_traits.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_DEQUE_TRAITS_HPP -#define TAO_JSON_CONTRIB_DEQUE_TRAITS_HPP - -#include - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "internal/array_traits.hpp" - -namespace tao::json -{ - template< typename T, typename... Ts > - struct deque_traits - : internal::array_traits< std::deque< T, Ts... > > - { - template< template< typename... > class Traits, typename... With > - static void to( const basic_value< Traits >& v, std::deque< T, Ts... >& r, With&... with ) - { - const auto& a = v.get_array(); - for( const auto& i : a ) { - r.emplace_back( i.template as_with< T >( with... ) ); - } - } - - template< template< typename... > class Traits, typename Producer > - static void consume( Producer& parser, std::vector< T, Ts... >& v ) - { - auto s = parser.begin_array(); - while( parser.element_or_end_array( s ) ) { - v.emplace_back( json::consume< T, Traits >( parser ) ); - } - } - }; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/diff.hpp b/include/tao/json/contrib/diff.hpp deleted file mode 100644 index 579f3d9c..00000000 --- a/include/tao/json/contrib/diff.hpp +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_DIFF_HPP -#define TAO_JSON_CONTRIB_DIFF_HPP - -#include -#include -#include -#include - -#include "../pointer.hpp" -#include "../value.hpp" - -namespace tao::json -{ - namespace internal - { - template< typename... Ts > - void move_append( std::vector< Ts... >& lhs, std::vector< Ts... >& rhs ) - { - if( lhs.empty() ) { - lhs = std::move( rhs ); - } - else if( !rhs.empty() ) { - lhs.reserve( lhs.size() + rhs.size() ); - std::move( std::begin( rhs ), std::end( rhs ), std::back_inserter( lhs ) ); - } - } - - } // namespace internal - - template< template< typename... > class Traits > - [[nodiscard]] basic_value< Traits > diff( const basic_value< Traits >& source, const basic_value< Traits >& destination, const pointer& path = pointer() ) - { - basic_value< Traits > result = empty_array; - if( source == destination ) { - return result; - } - if( source.type() != destination.type() ) { - result.push_back( { { "op", "replace" }, - { "path", to_string( path ) }, - { "value", destination } } ); - } - else { - auto& a = result.get_array(); - switch( source.type() ) { - case type::ARRAY: { - const auto ss = source.get_array().size(); - const auto ds = destination.get_array().size(); - std::size_t i = 0; - while( ( i < ss ) && ( i < ds ) ) { - internal::move_append( a, diff( source.at( i ), destination.at( i ), path + i ).get_array() ); - ++i; - } - const auto s = ss + i - 1; - while( i < ss ) { - result.push_back( { { "op", "remove" }, - { "path", to_string( path + ( s - i ) ) } } ); - ++i; - } - while( i < ds ) { - result.push_back( { { "op", "add" }, - { "path", to_string( path + i ) }, - { "value", destination.at( i ) } } ); - ++i; - } - } break; - - case type::OBJECT: { - const auto& sm = source.get_object(); - const auto& dm = destination.get_object(); - auto sit = sm.begin(); - auto dit = dm.begin(); - while( ( sit != sm.end() ) || ( dit != dm.end() ) ) { - if( ( sit == sm.end() ) || ( ( dit != dm.end() ) && ( sit->first > dit->first ) ) ) { - result.push_back( { { "op", "add" }, - { "path", to_string( path + dit->first ) }, - { "value", dit->second } } ); - ++dit; - } - else if( ( dit == dm.end() ) || ( ( sit != sm.end() ) && ( sit->first < dit->first ) ) ) { - result.push_back( { { "op", "remove" }, - { "path", to_string( path + sit->first ) } } ); - ++sit; - } - else { - internal::move_append( a, diff( sit->second, dit->second, path + sit->first ).get_array() ); - ++sit; - ++dit; - } - } - } break; - - default: - result.push_back( { { "op", "replace" }, - { "path", to_string( path ) }, - { "value", destination } } ); - } - } - return result; - } - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/get.hpp b/include/tao/json/contrib/get.hpp deleted file mode 100644 index e83dda13..00000000 --- a/include/tao/json/contrib/get.hpp +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_GET_HPP -#define TAO_JSON_CONTRIB_GET_HPP - -#include "../basic_value.hpp" - -namespace tao::json::get -{ - namespace internal - { - template< template< typename... > class Traits > - [[nodiscard]] const basic_value< Traits >* find( const basic_value< Traits >& v, const std::string& key ) - { - return v.find( key ); - } - - template< template< typename... > class Traits > - [[nodiscard]] const basic_value< Traits >* find( const basic_value< Traits >& v, const std::size_t index ) - { - const auto& a = v.get_array(); - return ( index < a.size() ) ? ( a.data() + index ) : nullptr; - } - - } // namespace internal - - template< template< typename... > class Traits, typename K > - [[nodiscard]] basic_value< Traits > value( const basic_value< Traits >& v, const K& key ) - { - if( const auto& w = v.skip_value_ptr() ) { - if( const auto* p = internal::find( w, key ) ) { - return basic_value< Traits >( &p->skip_value_ptr() ); // Returns a Value with tao::json::type::VALUE_PTR that is invalidated when v is destroyed! - } - } - return basic_value< Traits >(); - } - - template< template< typename... > class Traits, typename K, typename... Ks > - [[nodiscard]] basic_value< Traits > value( const basic_value< Traits >& v, const K& key, const Ks&... ks ) - { - if( const auto& w = v.skip_value_ptr() ) { - if( const auto* p = internal::find( w, key ) ) { - return get::value( *p, ks... ); - } - } - return basic_value< Traits >(); - } - - template< typename T, typename U, template< typename... > class Traits > - [[nodiscard]] T as( const basic_value< Traits >& v ) - { - return v.skip_value_ptr().template as< U >(); - } - - template< typename T, template< typename... > class Traits > - [[nodiscard]] auto as( const basic_value< Traits >& v ) - { - return as< T, T >( v ); - } - - template< typename T, typename U, template< typename... > class Traits, typename K, typename... Ks > - [[nodiscard]] T as( const basic_value< Traits >& v, const K& key, Ks&&... ks ) - { - return get::as< T, U >( v.skip_value_ptr().at( key ), ks... ); - } - - template< typename T, template< typename... > class Traits, typename K, typename... Ks > - [[nodiscard]] auto as( const basic_value< Traits >& v, const K& key, Ks&&... ks ) - { - return as< T, T >( v, key, ks... ); - } - - template< typename T, template< typename... > class Traits > - void to( const basic_value< Traits >& v, T& t ) - { - v.skip_value_ptr().to( t ); - } - - template< typename T, template< typename... > class Traits, typename K, typename... Ks > - void to( const basic_value< Traits >& v, T& t, const K& key, Ks&&... ks ) - { - get::to( v.skip_value_ptr().at( key ), t, ks... ); - } - - template< typename T, typename U, template< typename... > class Traits > - [[nodiscard]] std::optional< T > optional( const basic_value< Traits >& v ) - { - if( const auto& w = v.skip_value_ptr() ) { - return std::optional< T >( std::in_place, get::as< U >( w ) ); - } - return std::nullopt; - } - - template< typename T, template< typename... > class Traits > - [[nodiscard]] auto optional( const basic_value< Traits >& v ) - { - return optional< T, T >( v ); - } - - template< typename T, typename U, template< typename... > class Traits, typename K, typename... Ks > - [[nodiscard]] std::optional< T > optional( const basic_value< Traits >& v, const K& key, const Ks&... ks ) - { - if( const auto& w = v.skip_value_ptr() ) { - if( const auto* p = internal::find( w, key ) ) { - return get::optional< T, U >( *p, ks... ); - } - } - return std::nullopt; - } - - template< typename T, template< typename... > class Traits, typename K, typename... Ks > - [[nodiscard]] auto optional( const basic_value< Traits >& v, const K& key, const Ks&... ks ) - { - return optional< T, T >( v, key, ks... ); - } - - template< typename T, typename U, template< typename... > class Traits > - [[nodiscard]] T defaulted( const T& t, const basic_value< Traits >& v ) - { - if( const auto& w = v.skip_value_ptr() ) { - return get::as< T, U >( w ); - } - return t; - } - - template< typename T, template< typename... > class Traits > - [[nodiscard]] auto defaulted( const T& t, const basic_value< Traits >& v ) - { - return defaulted< T, T >( t, v ); - } - - template< typename T, typename U, template< typename... > class Traits, typename K, typename... Ks > - [[nodiscard]] T defaulted( const T& t, const basic_value< Traits >& v, const K& key, const Ks&... ks ) - { - if( const auto& w = v.skip_value_ptr() ) { - if( const auto* p = internal::find( w, key ) ) { - return get::defaulted< T, U >( t, *p, ks... ); - } - } - return t; - } - - template< typename T, template< typename... > class Traits, typename K, typename... Ks > - [[nodiscard]] auto defaulted( const T& t, const basic_value< Traits >& v, const K& key, const Ks&... ks ) - { - return defaulted< T, T >( t, v, key, ks... ); - } - -} // namespace tao::json::get - -#endif diff --git a/include/tao/json/contrib/internal/array_traits.hpp b/include/tao/json/contrib/internal/array_traits.hpp deleted file mode 100644 index 6d59cf7b..00000000 --- a/include/tao/json/contrib/internal/array_traits.hpp +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_INTERNAL_ARRAY_TRAITS_HPP -#define TAO_JSON_CONTRIB_INTERNAL_ARRAY_TRAITS_HPP - -#include - -#include "../../forward.hpp" -#include "../../type.hpp" - -#include "../../events/produce.hpp" - -namespace tao::json::internal -{ - template< typename T > - struct array_multi_traits - { - template< template< typename... > class Traits > - [[nodiscard]] static bool is_nothing( const T& o ) - { - return o.empty(); - } - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const T& o ) = delete; - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, const T& o ) - { - c.begin_array( o.size() ); - for( const auto& i : o ) { - json::events::produce< Traits >( c, i ); - c.element(); - } - c.end_array( o.size() ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const T& rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - if( !p.is_array() ) { - return false; - } - const auto& a = p.get_array(); - return ( a.size() == rhs.size() ) && std::equal( rhs.begin(), rhs.end(), a.begin() ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const T& rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - const auto t = p.type(); - if( t != type::ARRAY ) { - return t < type::ARRAY; - } - const auto& a = p.get_array(); - return std::lexicographical_compare( a.begin(), a.end(), rhs.begin(), rhs.end() ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const T& rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - const auto t = p.type(); - if( t != type::ARRAY ) { - return t > type::ARRAY; - } - const auto& a = p.get_array(); - return std::lexicographical_compare( rhs.begin(), rhs.end(), a.begin(), a.end() ); - } - }; - - template< typename T > - struct array_traits - : array_multi_traits< T > - { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const T& o ) - { - v.emplace_array(); - v.get_array().reserve( o.size() ); - for( const auto& e : o ) { - v.emplace_back( e ); - } - } - }; - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/contrib/internal/indirect_traits.hpp b/include/tao/json/contrib/internal/indirect_traits.hpp deleted file mode 100644 index 7022b325..00000000 --- a/include/tao/json/contrib/internal/indirect_traits.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_INTERNAL_INDIRECT_TRAITS_HPP -#define TAO_JSON_CONTRIB_INTERNAL_INDIRECT_TRAITS_HPP - -#include - -#include "../../forward.hpp" -#include "../../type.hpp" - -#include "../../events/produce.hpp" - -#include "../../internal/type_traits.hpp" - -namespace tao::json::internal -{ - template< typename T > - struct indirect_traits - { - template< typename U > - [[nodiscard]] static const U& add_const( const U& u ) - { - return u; - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool is_nothing( const T& o ) - { - assert( o ); - return internal::is_nothing< Traits >( add_const( *o ) ); - } - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const T& o ) - { - assert( o ); - v = add_const( *o ); - } - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, const T& o ) - { - assert( o ); - json::events::produce< Traits >( c, add_const( *o ) ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const T& rhs ) noexcept - { - return rhs ? ( lhs == *rhs ) : ( lhs == null ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const T& rhs ) noexcept - { - return rhs ? ( lhs < *rhs ) : ( lhs < null ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const T& rhs ) noexcept - { - return rhs ? ( lhs > *rhs ) : ( lhs > null ); - } - }; - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/contrib/internal/object_traits.hpp b/include/tao/json/contrib/internal/object_traits.hpp deleted file mode 100644 index 7f531de6..00000000 --- a/include/tao/json/contrib/internal/object_traits.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_INTERNAL_OBJECT_TRAITS_HPP -#define TAO_JSON_CONTRIB_INTERNAL_OBJECT_TRAITS_HPP - -#include -#include - -#include "../../forward.hpp" -#include "../../type.hpp" - -#include "../../events/produce.hpp" - -namespace tao::json::internal -{ - template< typename T > - struct object_multi_traits - { - template< template< typename... > class Traits > - [[nodiscard]] static bool is_nothing( const T& o ) - { - return o.empty(); - } - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const T& o ) = delete; - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, const T& o ) - { - c.begin_object( o.size() ); - for( const auto& i : o ) { - c.key( i.first ); - json::events::produce< Traits >( c, i.second ); - c.member(); - } - c.end_object( o.size() ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const T& rhs ) noexcept - { - static const auto eq = []( const typename T::value_type& r, const std::pair< const std::string, basic_value< Traits > >& l ) { - return ( l.first == r.first ) && ( l.second == r.second ); - }; - const auto& p = lhs.skip_value_ptr(); - if( !p.is_object() ) { - return false; - } - const auto& o = p.get_object(); - return ( o.size() == rhs.size() ) && std::equal( rhs.begin(), rhs.end(), o.begin(), eq ); - } - - struct pair_less - { - template< typename L, typename R > - [[nodiscard]] bool operator()( const L& l, const R& r ) const noexcept - { - return ( l.first < r.first ) || ( ( l.first == r.first ) && ( l.second < r.second ) ); - } - }; - - template< template< typename... > class Traits > - [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const T& rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - const auto t = p.type(); - if( t != type::OBJECT ) { - return t < type::OBJECT; - } - const auto& o = p.get_object(); - return std::lexicographical_compare( o.begin(), o.end(), rhs.begin(), rhs.end(), pair_less() ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const T& rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - const auto t = p.type(); - if( t != type::OBJECT ) { - return t > type::OBJECT; - } - const auto& o = p.get_object(); - return std::lexicographical_compare( rhs.begin(), rhs.end(), o.begin(), o.end(), pair_less() ); - } - }; - - template< typename T > - struct object_traits - : object_multi_traits< T > - { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const T& o ) - { - v.prepare_object(); - for( const auto& i : o ) { - v.try_emplace( i.first, i.second ); - } - } - }; - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/contrib/internal/type_traits.hpp b/include/tao/json/contrib/internal/type_traits.hpp deleted file mode 100644 index 4cdf44b0..00000000 --- a/include/tao/json/contrib/internal/type_traits.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_INTERNAL_TYPE_TRAITS_HPP -#define TAO_JSON_CONTRIB_INTERNAL_TYPE_TRAITS_HPP - -#include "../../forward.hpp" - -#include "../../internal/type_traits.hpp" - -namespace tao::json::internal -{ - template< typename T, template< typename... > class Traits, typename... With > - inline constexpr bool use_first_ptr_as = std::is_constructible_v< T, const basic_value< Traits >&, With&... >; - - template< typename T, template< typename... > class Traits, typename... With > - inline constexpr bool use_second_ptr_as = !use_first_ptr_as< T, Traits, With... > && std::is_move_constructible_v< T > && has_as< Traits< T >, basic_value< Traits >, With... >; - - template< typename T, template< typename... > class Traits, typename... With > - inline constexpr bool use_third_ptr_as = !use_first_ptr_as< T, Traits, With... > && !use_second_ptr_as< T, Traits, With... > && std::is_default_constructible_v< T > && has_to< Traits< T >, basic_value< Traits >, T, With... >; - - template< typename T, template< typename... > class Traits, typename... With > - inline constexpr bool use_fourth_ptr_as = !use_first_ptr_as< T, Traits, With... > && !use_third_ptr_as< T, Traits, With... > && std::is_copy_constructible_v< T > && has_as< Traits< T >, basic_value< Traits >, With... >; - - template< typename T, template< typename... > class Traits, class Producer > - inline constexpr bool use_first_ptr_consume = std::is_move_constructible_v< T >&& has_consume_one< Traits, Producer, T >; - - template< typename T, template< typename... > class Traits, class Producer > - inline constexpr bool use_second_ptr_consume = !use_first_ptr_consume< T, Traits, Producer > && std::is_default_constructible_v< T > && has_consume_two< Traits, Producer, T >; - - template< typename T, template< typename... > class Traits, class Producer > - inline constexpr bool use_third_ptr_consume = !use_second_ptr_consume< T, Traits, Producer > && std::is_copy_constructible_v< T > && has_consume_one< Traits, Producer, T >; - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/contrib/list_traits.hpp b/include/tao/json/contrib/list_traits.hpp deleted file mode 100644 index 5416cd0e..00000000 --- a/include/tao/json/contrib/list_traits.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_LIST_TRAITS_HPP -#define TAO_JSON_CONTRIB_LIST_TRAITS_HPP - -#include - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "internal/array_traits.hpp" - -namespace tao::json -{ - template< typename T, typename... Ts > - struct list_traits - : internal::array_traits< std::list< T, Ts... > > - { - template< template< typename... > class Traits, typename... With > - static void to( const basic_value< Traits >& v, std::list< T, Ts... >& r, With&... with ) - { - const auto& a = v.get_array(); - for( const auto& i : a ) { - r.emplace_back( i.template as_with< T >( with... ) ); - } - } - - template< template< typename... > class Traits, typename Producer > - static void consume( Producer& parser, std::list< T, Ts... >& r ) - { - auto s = parser.begin_array(); - while( parser.element_or_end_array( s ) ) { - r.emplace_back( json::consume< T, Traits >( parser ) ); - } - } - }; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/map_traits.hpp b/include/tao/json/contrib/map_traits.hpp deleted file mode 100644 index c0c9e3e2..00000000 --- a/include/tao/json/contrib/map_traits.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_MAP_TRAITS_HPP -#define TAO_JSON_CONTRIB_MAP_TRAITS_HPP - -#include -#include - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "internal/object_traits.hpp" - -namespace tao::json -{ - template< typename T, typename... Ts > - struct map_traits - : internal::object_traits< std::map< std::string, T, Ts... > > - { - template< template< typename... > class Traits, typename... With > - static void to( const basic_value< Traits >& v, std::map< std::string, T, Ts... >& r, With&... with ) - { - const auto& o = v.get_object(); - for( const auto& i : o ) { - r.try_emplace( i.first, i.second.template as_with< T >( with... ) ); - } - } - - template< template< typename... > class Traits, typename Producer > - static void consume( Producer& parser, std::map< std::string, T, Ts... >& v ) - { - auto s = parser.begin_object(); - while( parser.member_or_end_object( s ) ) { - auto k = parser.key(); - v.try_emplace( std::move( k ), json::consume< T, Traits >( parser ) ); - } - } - }; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/multimap_traits.hpp b/include/tao/json/contrib/multimap_traits.hpp deleted file mode 100644 index ee480395..00000000 --- a/include/tao/json/contrib/multimap_traits.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_MULTIMAP_TRAITS_HPP -#define TAO_JSON_CONTRIB_MULTIMAP_TRAITS_HPP - -#include -#include - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "internal/object_traits.hpp" - -namespace tao::json -{ - template< typename T, typename... Ts > - struct multimap_traits - : internal::object_multi_traits< std::multimap< std::string, T, Ts... > > - { - template< template< typename... > class Traits, typename... With > - static void to( const basic_value< Traits >& v, std::multimap< std::string, T, Ts... >& r, With&... with ) - { - const auto& o = v.get_object(); - for( const auto& i : o ) { - r.try_emplace( i.first, i.second.template as_with< T >( with... ) ); - } - } - - template< template< typename... > class Traits, typename Producer > - static void consume( Producer& parser, std::multimap< std::string, T, Ts... >& v ) - { - auto s = parser.begin_object(); - while( parser.member_or_end_object( s ) ) { - auto k = parser.key(); - v.try_emplace( std::move( k ), json::consume< T, Traits >( parser ) ); - } - } - }; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/multiset_traits.hpp b/include/tao/json/contrib/multiset_traits.hpp deleted file mode 100644 index 2ace4adf..00000000 --- a/include/tao/json/contrib/multiset_traits.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_MULTISET_TRAITS_HPP -#define TAO_JSON_CONTRIB_MULTISET_TRAITS_HPP - -#include - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "internal/array_traits.hpp" - -namespace tao::json -{ - template< typename T, typename... Ts > - struct multiset_traits - : internal::array_traits< std::multiset< T, Ts... > > - { - template< template< typename... > class Traits, typename... With > - static void to( const basic_value< Traits >& v, std::multiset< T, Ts... >& r, With&... with ) - { - const auto& a = v.get_array(); - for( const auto& i : a ) { - r.emplace( i.template as_with< T >( with... ) ); - } - } - - template< template< typename... > class Traits, typename Producer > - static void consume( Producer& parser, std::multiset< T, Ts... >& r ) - { - auto s = parser.begin_array(); - while( parser.element_or_end_array( s ) ) { - r.emplace( json::consume< T, Traits >( parser ) ); - } - } - }; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/pair_traits.hpp b/include/tao/json/contrib/pair_traits.hpp deleted file mode 100644 index f6413cde..00000000 --- a/include/tao/json/contrib/pair_traits.hpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_PAIR_TRAITS_HPP -#define TAO_JSON_CONTRIB_PAIR_TRAITS_HPP - -#include - -#include "../binding.hpp" - -namespace tao::json -{ - template< typename U, typename V > - struct pair_traits - : binding::array< TAO_JSON_BIND_ELEMENT( &std::pair< U, V >::first ), - TAO_JSON_BIND_ELEMENT( &std::pair< U, V >::second ) > - {}; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/patch.hpp b/include/tao/json/contrib/patch.hpp deleted file mode 100644 index 1c2ee384..00000000 --- a/include/tao/json/contrib/patch.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_PATCH_HPP -#define TAO_JSON_CONTRIB_PATCH_HPP - -#include -#include - -#include "../pointer.hpp" -#include "../value.hpp" - -namespace tao::json -{ - template< template< typename... > class Traits > - void patch_inplace( basic_value< Traits >& v, const basic_value< Traits >& patch ) - { - for( const auto& entry : patch.get_array() ) { - const auto& op = entry.at( "op" ).get_string(); - const auto& path = entry.at( "path" ).get_string(); - const pointer path_pointer( path ); - if( op == "test" ) { - if( v.at( path_pointer ) != entry.at( "value" ) ) { - throw std::runtime_error( internal::format( "json patch 'test' failed for '", path, '\'', json::message_extension( v ) ) ); - } - } - else if( op == "remove" ) { - v.erase( path_pointer ); - } - else if( op == "add" ) { - v.insert( path_pointer, entry.at( "value" ) ); - } - else if( op == "replace" ) { - v.at( path_pointer ) = entry.at( "value" ); - } - else if( op == "move" ) { - const pointer from( entry.at( "from" ).get_string() ); - auto t = std::move( v.at( from ) ); - v.erase( from ); - v.insert( path_pointer, std::move( t ) ); - } - else if( op == "copy" ) { - const pointer from( entry.at( "from" ).get_string() ); - v.insert( path_pointer, v.at( from ) ); - } - else { - throw std::runtime_error( internal::format( "unknown json patch operation '", op, '\'' ) ); - } - } - } - - template< template< typename... > class Traits > - void patch_inplace( basic_value< Traits >& v, basic_value< Traits >&& patch ) - { - for( const auto& entry : patch.get_array() ) { - const auto& op = entry.at( "op" ).get_string(); - const auto& path = entry.at( "path" ).get_string(); - const pointer path_pointer( path ); - if( op == "test" ) { - if( v.at( path_pointer ) != entry.at( "value" ) ) { - throw std::runtime_error( internal::format( "json patch 'test' failed for '", path, '\'', json::message_extension( v ) ) ); - } - } - else if( op == "remove" ) { - v.erase( path_pointer ); - } - else if( op == "add" ) { - v.insert( path_pointer, std::move( entry.at( "value" ) ) ); - } - else if( op == "replace" ) { - v.at( path_pointer ) = std::move( entry.at( "value" ) ); - } - else if( op == "move" ) { - const pointer from( entry.at( "from" ).get_string() ); - auto t = std::move( v.at( from ) ); - v.erase( from ); - v.insert( path_pointer, std::move( t ) ); - } - else if( op == "copy" ) { - const pointer from( entry.at( "from" ).get_string() ); - v.insert( path_pointer, v.at( from ) ); - } - else { - throw std::runtime_error( internal::format( "unknown json patch operation '", op, '\'' ) ); - } - } - } - - template< template< typename... > class Traits > - [[nodiscard]] basic_value< Traits > patch( basic_value< Traits > v, const basic_value< Traits >& patch ) - { - patch_inplace( v, patch ); - return v; - } - - template< template< typename... > class Traits > - [[nodiscard]] basic_value< Traits > patch( basic_value< Traits > v, basic_value< Traits >&& patch ) - { - patch_inplace( v, std::move( patch ) ); - return v; - } - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/pointer_traits.hpp b/include/tao/json/contrib/pointer_traits.hpp deleted file mode 100644 index c079f468..00000000 --- a/include/tao/json/contrib/pointer_traits.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef TAO_JSON_CONTRIB_POINTER_TRAITS_HPP -#define TAO_JSON_CONTRIB_POINTER_TRAITS_HPP - -#include "../pointer.hpp" -#include "../traits.hpp" - -namespace tao::json -{ - struct token_traits - { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const token& t ) - { - if( t.has_index() ) { - v = t.index(); - } - else { - v = t.key(); - } - } - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, const token& t ) - { - if( t.has_index() ) { - json::events::produce< Traits >( c, t.index() ); - } - else { - json::events::produce< Traits >( c, t.key() ); - } - } - }; - - struct pointer_traits - { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const pointer& p ) - { - v.prepare_array().reserve( p.size() ); - for( const auto& i : p ) { - v.emplace_back( i ); - } - } - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, const pointer& p ) - { - c.begin_array( p.size() ); - for( const auto& i : p ) { - json::events::produce< Traits >( c, i ); - c.element(); - } - c.end_array( p.size() ); - } - }; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/position.hpp b/include/tao/json/contrib/position.hpp deleted file mode 100644 index fd80f13e..00000000 --- a/include/tao/json/contrib/position.hpp +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_POSITION_HPP -#define TAO_JSON_CONTRIB_POSITION_HPP - -#include -#include -#include -#include - -#include "../events/to_value.hpp" -#include "../events/transformer.hpp" -#include "../from_file.hpp" -#include "../message_extension.hpp" -#include "../value.hpp" - -namespace tao::json -{ - struct position - { - private: - std::size_t m_line = 0; - std::size_t m_byte_in_line = 0; - std::string m_source; - - public: - position() noexcept - {} - - position( std::string in_source, const std::size_t in_line, const std::size_t in_byte_in_line ) - : m_line( in_line ), - m_byte_in_line( in_byte_in_line ), - m_source( std::move( in_source ) ) - {} - - position( const position& ) = default; - - position( position&& p ) noexcept - { - m_line = p.m_line; - m_byte_in_line = p.m_byte_in_line; - m_source = std::move( p.m_source ); - } - - ~position() = default; - - position& operator=( const position& ) = default; - - position& operator=( position&& p ) noexcept - { - m_line = p.m_line; - m_byte_in_line = p.m_byte_in_line; - m_source = std::move( p.m_source ); - return *this; - } - - [[nodiscard]] const std::string& source() const noexcept - { - return m_source; - } - - [[nodiscard]] std::size_t line() const noexcept - { - return m_line; - } - - [[nodiscard]] std::size_t byte_in_line() const noexcept - { - return m_byte_in_line; - } - - void set_source( const std::string& s ) - { - m_source = s; - } - - template< typename T > - void set_position( const T& p ) - { - m_line = p.line; - m_byte_in_line = p.byte_in_line; - m_source = p.source; - } - - void append_message_extension( std::ostream& os ) const - { - os << '[' << m_source << ':' << m_line << ':' << m_byte_in_line << ']'; - } - }; - - namespace internal - { - template< typename Rule > - struct position_action - : action< Rule > - { - }; - - template<> - struct position_action< rules::object::begin > - { - template< typename Input, typename Consumer > - static void apply( const Input& in, Consumer& consumer ) - { - action< rules::object::begin >::apply0( consumer ); - consumer.stack_.back().set_position( in.position() ); - } - }; - - template<> - struct position_action< rules::array::begin > - { - template< typename Input, typename Consumer > - static void apply( const Input& in, Consumer& consumer ) - { - action< rules::array::begin >::apply0( consumer ); - consumer.stack_.back().set_position( in.position() ); - } - }; - - template<> - struct position_action< rules::sor_value > - { - template< typename Input, typename Consumer > - static void apply( const Input& in, Consumer& consumer ) - { - consumer.value.set_position( in.position() ); - } - }; - - template< template< typename... > class Traits > - struct position_traits - : Traits< void > - { - template< typename > - using public_base = position; - }; - - } // namespace internal - - template< template< typename... > class Traits > - struct make_position_traits - { - template< typename T > - using type = std::conditional_t< std::is_same_v< T, void >, internal::position_traits< Traits >, Traits< T > >; - }; - - template< template< typename... > class Traits, template< typename... > class... Transformers > - [[nodiscard]] auto basic_from_file_with_position( const std::string& filename ) - { - events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; - pegtl::file_input< pegtl::tracking_mode::eager > in( filename ); - pegtl::parse< internal::grammar, internal::position_action, internal::errors >( in, consumer ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers > - [[nodiscard]] auto from_file_with_position( const std::string& filename ) - { - return basic_from_file_with_position< make_position_traits< traits >::template type, Transformers... >( filename ); - } - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/reference.hpp b/include/tao/json/contrib/reference.hpp deleted file mode 100644 index 422efd7c..00000000 --- a/include/tao/json/contrib/reference.hpp +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_REFERENCE_HPP -#define TAO_JSON_CONTRIB_REFERENCE_HPP - -#include "../internal/uri_fragment.hpp" -#include "../pointer.hpp" -#include "../value.hpp" - -namespace tao::json -{ - namespace internal - { - // JSON Reference, see draft ("work in progress") RFC at - // https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03 - - // NOTE: Currently, only URI fragments are supported. - // Remote references are ignored, i.e., left untouched. - - // JSON References are replaced with a VALUE_PTR, - // which might lead to infinite loops if you try - // to traverse the value. Make sure you understand - // the consequences and handle the resulting value - // accordingly! - - // Self-references will throw an exception, as well as - // references into JSON Reference additional members - // (which shall be ignored as per the specification). - - template< template< typename... > class Traits > - void resolve_references( basic_value< Traits >& r, basic_value< Traits >& v ) - { - switch( v.type() ) { - case type::UNINITIALIZED: - return; - case type::NULL_: - case type::BOOLEAN: - case type::SIGNED: - case type::UNSIGNED: - case type::DOUBLE: - case type::STRING: - case type::STRING_VIEW: - case type::BINARY: - case type::BINARY_VIEW: - return; - case type::ARRAY: - for( auto& e : v.get_array() ) { - resolve_references( r, e ); - } - return; - case type::OBJECT: - for( auto& e : v.get_object() ) { - resolve_references( r, e.second ); - } - if( const auto* ref = v.find( "$ref" ) ) { - ref = &ref->skip_value_ptr(); - if( ref->is_string_type() ) { - const std::string_view s = ref->get_string_type(); - if( !s.empty() && s[ 0 ] == '#' ) { - const pointer ptr = internal::uri_fragment_to_pointer( s ); - const auto* p = &r; - auto it = ptr.begin(); - while( it != ptr.end() ) { - switch( p->type() ) { - case type::ARRAY: - p = &p->at( it->index() ).skip_value_ptr(); - break; - case type::OBJECT: - if( const auto* t = p->find( "$ref" ) ) { - if( t->is_string_type() ) { - throw std::runtime_error( "invalid JSON Reference: referencing additional data members is invalid" ); - } - } - p = &p->at( it->key() ).skip_value_ptr(); - break; - default: - throw invalid_type( ptr.begin(), std::next( it ) ); - } - ++it; - } - if( p == &v ) { - throw std::runtime_error( "JSON Reference: invalid self reference" ); - } - v.set_value_ptr( p ); - resolve_references( r, v ); - } - else { - // Ignore remote references for now... - // throw std::runtime_error( "JSON Reference: unsupported or invalid URI: " + s ); // NOLINT - } - } - } - return; - case type::VALUE_PTR: - return; - case type::OPAQUE_PTR: - return; - case type::VALUELESS_BY_EXCEPTION: - return; - } - throw std::logic_error( "invalid value for tao::json::type" ); // LCOV_EXCL_LINE - } - - } // namespace internal - - template< template< typename... > class Traits > - void resolve_references( basic_value< Traits >& r ) - { - internal::resolve_references( r, r ); - } - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/schema.hpp b/include/tao/json/contrib/schema.hpp deleted file mode 100644 index 4f74dd01..00000000 --- a/include/tao/json/contrib/schema.hpp +++ /dev/null @@ -1,1851 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_SCHEMA_HPP -#define TAO_JSON_CONTRIB_SCHEMA_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "reference.hpp" - -#include "../events/compare.hpp" -#include "../events/from_value.hpp" -#include "../events/hash.hpp" -#include "../pointer.hpp" -#include "../value.hpp" - -#include "../external/pegtl/contrib/uri.hpp" -#include "../external/pegtl/parse.hpp" - -namespace tao::json -{ - namespace internal - { - // TODO: Check if these grammars are correct. - struct local_part_label - : pegtl::plus< pegtl::sor< pegtl::alnum, pegtl::one< '!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', '=', '?', '^', '_', '`', '{', '|', '}', '~' > > > - {}; - - struct local_part - : pegtl::list_must< local_part_label, pegtl::one< '.' > > - {}; - - struct hostname_label - : pegtl::seq< pegtl::alnum, pegtl::rep_max< 62, pegtl::ranges< 'a', 'z', 'A', 'Z', '0', '9', '-' > > > - {}; - - struct hostname - : pegtl::list_must< hostname_label, pegtl::one< '.' > > - {}; - - struct email - : pegtl::seq< local_part, pegtl::one< '@' >, hostname > - {}; - - template< typename Rule > - [[nodiscard]] bool parse( const std::string_view v ) - { - pegtl::memory_input in( v.data(), v.size(), "" ); - return pegtl::parse< pegtl::seq< Rule, pegtl::eof > >( in ); - } - - [[nodiscard]] inline bool parse_date_time( const std::string_view v ) - { - static std::regex re( "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:[0-5]\\d:[0-5]\\d(\\.\\d+)?(Z|[+-]\\d{2}:[0-5]\\d)$" ); - if( !std::regex_search( v.begin(), v.end(), re ) ) { - return false; - } - - const unsigned year = ( v[ 0 ] - '0' ) * 1000 + ( v[ 1 ] - '0' ) * 100 + ( v[ 2 ] - '0' ) * 10 + ( v[ 3 ] - '0' ); - const unsigned month = ( v[ 5 ] - '0' ) * 10 + ( v[ 6 ] - '0' ); - const unsigned day = ( v[ 8 ] - '0' ) * 10 + ( v[ 9 ] - '0' ); - - if( month == 0 || month > 12 ) { - return false; - } - if( day == 0 || day > 31 ) { - return false; - } - if( month == 2 ) { - const bool is_leap_year = ( year % 4 == 0 ) && ( year % 100 != 0 || year % 400 == 0 ); - if( day > ( is_leap_year ? 29U : 28U ) ) { - return false; - } - } - else if( day == 31 ) { - switch( month ) { - case 4: - case 6: - case 9: - case 11: - return false; - default:; - } - } - - const unsigned hour = ( v[ 11 ] - '0' ) * 10 + ( v[ 12 ] - '0' ); - if( hour >= 24 ) { - return false; - } - - if( *v.rbegin() != 'Z' ) { - const auto s = v.size(); - const unsigned tz_hour = ( v[ s - 5 ] - '0' ) * 10 + ( v[ s - 4 ] - '0' ); - if( tz_hour >= 24 ) { - return false; - } - } - - return true; - } - - enum schema_flags - { - NONE = 0, - - HAS_TYPE = 1 << 0, - NULL_ = 1 << 1, - BOOLEAN = 1 << 2, - INTEGER = 1 << 3, - NUMBER = 1 << 4, - STRING = 1 << 5, - ARRAY = 1 << 6, - OBJECT = 1 << 7, - - HAS_ENUM = 1 << 8, - - HAS_MULTIPLE_OF_UNSIGNED = 1 << 9, - HAS_MULTIPLE_OF_DOUBLE = 1 << 10, - HAS_MULTIPLE_OF = 3 << 9, - - HAS_MAXIMUM_SIGNED = 1 << 11, - HAS_MAXIMUM_UNSIGNED = 1 << 12, - HAS_MAXIMUM_DOUBLE = 3 << 11, - HAS_MAXIMUM = 3 << 11, - EXCLUSIVE_MAXIMUM = 1 << 13, - - HAS_MINIMUM_SIGNED = 1 << 14, - HAS_MINIMUM_UNSIGNED = 1 << 15, - HAS_MINIMUM_DOUBLE = 3 << 14, - HAS_MINIMUM = 3 << 14, - EXCLUSIVE_MINIMUM = 1 << 16, - - HAS_MAX_LENGTH = 1 << 17, - HAS_MIN_LENGTH = 1 << 18, - - HAS_MAX_ITEMS = 1 << 19, - HAS_MIN_ITEMS = 1 << 20, - HAS_UNIQUE_ITEMS = 1 << 21, - - HAS_MAX_PROPERTIES = 1 << 22, - HAS_MIN_PROPERTIES = 1 << 23, - NO_ADDITIONAL_PROPERTIES = 1 << 24, - HAS_DEPENDENCIES = 1 << 25 - }; - - enum class schema_format - { - none, - date_time, - email, - hostname, - ipv4, - ipv6, - uri - }; - - [[nodiscard]] inline constexpr schema_flags operator|( const schema_flags lhs, const schema_flags rhs ) noexcept - { - return static_cast< schema_flags >( static_cast< std::underlying_type< schema_flags >::type >( lhs ) | static_cast< std::underlying_type< schema_flags >::type >( rhs ) ); - } - - union schema_limit - { - std::int64_t i; - std::uint64_t u; - double d; - }; - - template< template< typename... > class Traits > - class schema_container; - - template< template< typename... > class Traits > - struct schema_node - { - const schema_container< Traits >* m_container; - const basic_value< Traits >* m_value; - const basic_value< Traits >* m_all_of = nullptr; - const basic_value< Traits >* m_any_of = nullptr; - const basic_value< Traits >* m_one_of = nullptr; - const basic_value< Traits >* m_not = nullptr; - const basic_value< Traits >* m_items = nullptr; - const basic_value< Traits >* m_additional_items = nullptr; - const basic_value< Traits >* m_properties = nullptr; - const basic_value< Traits >* m_additional_properties = nullptr; - - std::map< std::string, std::set< std::string > > m_property_dependencies; - std::map< std::string, const basic_value< Traits >* > m_schema_dependencies; - - std::vector< std::pair< std::regex, const basic_value< Traits >* > > m_pattern_properties; - - std::set< const basic_value< Traits >* > m_referenced_pointers; - - // number - schema_limit m_multiple_of; - schema_limit m_maximum; - schema_limit m_minimum; - - // string - std::uint64_t m_max_length; - std::uint64_t m_min_length; - std::unique_ptr< std::regex > m_pattern; - - // array - std::uint64_t m_max_items; - std::uint64_t m_min_items; - - // object - std::uint64_t m_max_properties; - std::uint64_t m_min_properties; - std::set< std::string > m_required; - - schema_flags m_flags = NONE; - schema_format m_format = schema_format::none; - - void add_type( const schema_flags v ) - { - if( ( m_flags & v ) != 0 ) { - throw std::runtime_error( "invalid JSON Schema: duplicate primitive type" ); - } - m_flags = m_flags | v; - } - - void add_type( const std::string& v ) - { - if( !v.empty() ) { - switch( v[ 0 ] ) { - case 'n': - if( v == "number" ) { - return add_type( NUMBER ); - } - else if( v == "null" ) { - return add_type( NULL_ ); - } - break; - case 'b': - if( v == "boolean" ) { - return add_type( BOOLEAN ); - } - break; - case 'i': - if( v == "integer" ) { - return add_type( INTEGER ); - } - break; - case 's': - if( v == "string" ) { - return add_type( STRING ); - } - break; - case 'a': - if( v == "array" ) { - return add_type( ARRAY ); - } - break; - case 'o': - if( v == "object" ) { - return add_type( OBJECT ); - } - break; - } - } - throw std::runtime_error( "invalid JSON Schema: invalid primitive type '" + v + '\'' ); - } - - [[nodiscard]] const basic_value< Traits >* find( const char* s ) const - { - const auto* p = m_value->find( s ); - if( p != nullptr ) { - p = &p->skip_value_ptr(); - } - return p; - } - - schema_node( const schema_container< Traits >* c, const basic_value< Traits >& v ) - : m_container( c ), - m_value( &v ) - { - // general - if( !m_value->is_object() ) { - throw std::runtime_error( "invalid JSON Schema: a schema must be of type 'object'" ); - } - - // title - if( const auto* p = find( "title" ) ) { - if( !p->is_string() ) { - throw std::runtime_error( "invalid JSON Schema: \"title\" must be of type 'string'" ); - } - } - - // description - if( const auto* p = find( "description" ) ) { - if( !p->is_string() ) { - throw std::runtime_error( "invalid JSON Schema: \"description\" must be of type 'string'" ); - } - } - - // type - if( const auto* p = find( "type" ) ) { - switch( p->type() ) { - case type::STRING: - add_type( p->get_string() ); - break; - case type::ARRAY: - for( const auto& e : p->get_array() ) { - if( !e.is_string() ) { - throw std::runtime_error( "invalid JSON Schema: elements in array \"type\" must be of type 'string'" ); - } - add_type( e.get_string() ); - } - break; - default: - throw std::runtime_error( "invalid JSON Schema: \"type\" must be of type 'string' or 'array'" ); - } - m_flags = m_flags | HAS_TYPE; - } - - // enum - if( const auto* p = find( "enum" ) ) { - if( !p->is_array() ) { - throw std::runtime_error( "invalid JSON Schema: \"enum\" must be of type 'array'" ); - } - m_flags = m_flags | HAS_ENUM; - } - - // allOf - if( const auto* p = find( "allOf" ) ) { - if( !p->is_array() ) { - throw std::runtime_error( "invalid JSON Schema: \"allOf\" must be of type 'array'" ); - } - if( p->get_array().empty() ) { - throw std::runtime_error( "invalid JSON Schema: \"allOf\" must have at least one element" ); - } - for( const auto& e : p->get_array() ) { - m_referenced_pointers.insert( &e.skip_value_ptr() ); - } - m_all_of = p; - } - - // anyOf - if( const auto* p = find( "anyOf" ) ) { - if( !p->is_array() ) { - throw std::runtime_error( "invalid JSON Schema: \"anyOf\" must be of type 'array'" ); - } - if( p->get_array().empty() ) { - throw std::runtime_error( "invalid JSON Schema: \"anyOf\" must have at least one element" ); - } - for( const auto& e : p->get_array() ) { - m_referenced_pointers.insert( &e.skip_value_ptr() ); - } - m_any_of = p; - } - - // oneOf - if( const auto* p = find( "oneOf" ) ) { - if( !p->is_array() ) { - throw std::runtime_error( "invalid JSON Schema: \"oneOf\" must be of type 'array'" ); - } - if( p->get_array().empty() ) { - throw std::runtime_error( "invalid JSON Schema: \"oneOf\" must have at least one element" ); - } - for( const auto& e : p->get_array() ) { - m_referenced_pointers.insert( &e.skip_value_ptr() ); - } - m_one_of = p; - } - - // not - if( const auto* p = find( "not" ) ) { - m_referenced_pointers.insert( p ); - m_not = p; - } - - // definitions - if( const auto* p = find( "definitions" ) ) { - if( !p->is_object() ) { - throw std::runtime_error( "invalid JSON Schema: \"definitions\" must be of type 'object'" ); - } - for( const auto& e : p->get_object() ) { - m_referenced_pointers.insert( &e.second.skip_value_ptr() ); - } - } - - // multipleOf - if( const auto* p = find( "multipleOf" ) ) { - switch( p->type() ) { - case type::SIGNED: { - const auto i = p->get_signed(); - if( i <= 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"multipleOf\" must be strictly greater than zero" ); - } - m_multiple_of.u = i; - m_flags = m_flags | HAS_MULTIPLE_OF_UNSIGNED; - } break; - case type::UNSIGNED: { - const auto u = p->get_unsigned(); - if( u == 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"multipleOf\" must be strictly greater than zero" ); - } - m_multiple_of.u = u; - m_flags = m_flags | HAS_MULTIPLE_OF_UNSIGNED; - } break; - case type::DOUBLE: { - const auto d = p->get_double(); - if( d <= 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"multipleOf\" must be strictly greater than zero" ); - } - m_multiple_of.d = d; - m_flags = m_flags | HAS_MULTIPLE_OF_DOUBLE; - } break; - default: - throw std::runtime_error( "invalid JSON Schema: \"multipleOf\" must be of type 'number'" ); - } - } - - // maximum - if( const auto* p = find( "maximum" ) ) { - switch( p->type() ) { - case type::SIGNED: - m_maximum.i = p->get_signed(); - m_flags = m_flags | HAS_MAXIMUM_SIGNED; - break; - case type::UNSIGNED: - m_maximum.u = p->get_unsigned(); - m_flags = m_flags | HAS_MAXIMUM_UNSIGNED; - break; - case type::DOUBLE: - m_maximum.d = p->get_double(); - m_flags = m_flags | HAS_MAXIMUM_DOUBLE; - break; - default: - throw std::runtime_error( "invalid JSON Schema: \"maximum\" must be of type 'number'" ); - } - } - - // exclusiveMaximum - if( const auto* p = find( "exclusiveMaximum" ) ) { - if( !p->is_boolean() ) { - throw std::runtime_error( "invalid JSON Schema: \"exclusiveMaximum\" must be of type 'boolean'" ); - } - if( ( m_flags & HAS_MAXIMUM ) == 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"exclusiveMaximum\" requires presence of \"maximum\"" ); - } - if( p->get_boolean() ) { - m_flags = m_flags | EXCLUSIVE_MAXIMUM; - } - } - - // minimum - if( const auto* p = find( "minimum" ) ) { - switch( p->type() ) { - case type::SIGNED: - m_minimum.i = p->get_signed(); - m_flags = m_flags | HAS_MINIMUM_SIGNED; - break; - case type::UNSIGNED: - m_minimum.u = p->get_unsigned(); - m_flags = m_flags | HAS_MINIMUM_UNSIGNED; - break; - case type::DOUBLE: - m_minimum.d = p->get_double(); - m_flags = m_flags | HAS_MINIMUM_DOUBLE; - break; - default: - throw std::runtime_error( "invalid JSON Schema: \"minimum\" must be of type 'number'" ); - } - } - - // exclusiveMinimum - if( const auto* p = find( "exclusiveMinimum" ) ) { - if( !p->is_boolean() ) { - throw std::runtime_error( "invalid JSON Schema: \"exclusiveMinimum\" must be of type 'boolean'" ); - } - if( ( m_flags & HAS_MINIMUM ) == 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"exclusiveMinimum\" requires presence of \"minimum\"" ); - } - if( p->get_boolean() ) { - m_flags = m_flags | EXCLUSIVE_MINIMUM; - } - } - - // maxLength - if( const auto* p = find( "maxLength" ) ) { - switch( p->type() ) { - case type::SIGNED: { - const auto i = p->get_signed(); - if( i < 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"maxLength\" must be greater than or equal to zero" ); - } - m_max_length = i; - m_flags = m_flags | HAS_MAX_LENGTH; - } break; - case type::UNSIGNED: - m_max_length = p->get_unsigned(); - m_flags = m_flags | HAS_MAX_LENGTH; - break; - default: - throw std::runtime_error( "invalid JSON Schema: \"maxLength\" must be of type 'integer'" ); - } - } - - // minLength - if( const auto* p = find( "minLength" ) ) { - switch( p->type() ) { - case type::SIGNED: { - const auto i = p->get_signed(); - if( i < 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"minLength\" must be greater than or equal to zero" ); - } - if( i > 0 ) { - m_min_length = i; - m_flags = m_flags | HAS_MIN_LENGTH; - } - } break; - case type::UNSIGNED: { - const auto u = p->get_unsigned(); - if( u > 0 ) { - m_min_length = u; - m_flags = m_flags | HAS_MIN_LENGTH; - } - } break; - default: - throw std::runtime_error( "invalid JSON Schema: \"minLength\" must be of type 'integer'" ); - } - } - - // pattern - if( const auto* p = find( "pattern" ) ) { - if( !p->is_string() ) { - throw std::runtime_error( "invalid JSON Schema: \"pattern\" must be of type 'string'" ); - } - try { - m_pattern = std::make_unique< std::regex >( p->get_string() ); - } - catch( const std::regex_error& e ) { - throw std::runtime_error( "invalid JSON Schema: \"pattern\" must be a regular expression: " + std::string( e.what() ) ); - } - } - - // format - // TODO: offer an option to disable "format" support? - if( const auto* p = find( "format" ) ) { - if( !p->is_string() ) { - throw std::runtime_error( "invalid JSON Schema: \"format\" must be of type 'string'" ); - } - const auto& s = p->get_string(); - if( s == "date-time" ) { - m_format = schema_format::date_time; - } - else if( s == "email" ) { - m_format = schema_format::email; - } - else if( s == "hostname" ) { - m_format = schema_format::hostname; - } - else if( s == "ipv4" ) { - m_format = schema_format::ipv4; - } - else if( s == "ipv6" ) { - m_format = schema_format::ipv6; - } - else if( s == "uri" ) { - m_format = schema_format::uri; - } - // unknown "format" values are ignored - } - - // items - if( const auto* p = find( "items" ) ) { - if( p->is_array() ) { - for( const auto& e : p->get_array() ) { - m_referenced_pointers.insert( &e.skip_value_ptr() ); - } - } - else if( p->is_object() ) { - m_referenced_pointers.insert( p ); - } - else { - throw std::runtime_error( "invalid JSON Schema: \"items\" must be of type 'object' or 'array'" ); - } - m_items = p; - } - - // additionalItems - if( const auto* p = find( "additionalItems" ) ) { - if( p->is_object() ) { - m_referenced_pointers.insert( p ); - } - else if( !p->is_boolean() ) { - throw std::runtime_error( "invalid JSON Schema: \"additionalItems\" must be of type 'boolean' or 'object'" ); - } - m_additional_items = p; - } - - // maxItems - if( const auto* p = find( "maxItems" ) ) { - switch( p->type() ) { - case type::SIGNED: { - const auto i = p->get_signed(); - if( i < 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"maxItems\" must be greater than or equal to zero" ); - } - m_max_items = i; - m_flags = m_flags | HAS_MAX_ITEMS; - } break; - case type::UNSIGNED: - m_max_items = p->get_unsigned(); - m_flags = m_flags | HAS_MAX_ITEMS; - break; - default: - throw std::runtime_error( "invalid JSON Schema: \"maxItems\" must be of type 'integer'" ); - } - } - - // minItems - if( const auto* p = find( "minItems" ) ) { - switch( p->type() ) { - case type::SIGNED: { - const auto i = p->get_signed(); - if( i < 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"minItems\" must be greater than or equal to zero" ); - } - m_min_items = i; - m_flags = m_flags | HAS_MIN_ITEMS; - } break; - case type::UNSIGNED: - m_min_items = p->get_unsigned(); - m_flags = m_flags | HAS_MIN_ITEMS; - break; - default: - throw std::runtime_error( "invalid JSON Schema: \"minItems\" must be of type 'integer'" ); - } - } - - // uniqueItems - if( const auto* p = find( "uniqueItems" ) ) { - if( p->get_boolean() ) { - m_flags = m_flags | HAS_UNIQUE_ITEMS; - } - } - - // maxProperties - if( const auto* p = find( "maxProperties" ) ) { - switch( p->type() ) { - case type::SIGNED: { - const auto i = p->get_signed(); - if( i < 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"maxProperties\" must be greater than or equal to zero" ); - } - m_max_properties = i; - m_flags = m_flags | HAS_MAX_PROPERTIES; - } break; - case type::UNSIGNED: - m_max_properties = p->get_unsigned(); - m_flags = m_flags | HAS_MAX_PROPERTIES; - break; - default: - throw std::runtime_error( "invalid JSON Schema: \"maxProperties\" must be of type 'integer'" ); - } - } - - // minProperties - if( const auto* p = find( "minProperties" ) ) { - switch( p->type() ) { - case type::SIGNED: { - const auto i = p->get_signed(); - if( i < 0 ) { - throw std::runtime_error( "invalid JSON Schema: \"minProperties\" must be greater than or equal to zero" ); - } - m_min_properties = i; - m_flags = m_flags | HAS_MIN_PROPERTIES; - } break; - case type::UNSIGNED: - m_min_properties = p->get_unsigned(); - m_flags = m_flags | HAS_MIN_PROPERTIES; - break; - default: - throw std::runtime_error( "invalid JSON Schema: \"minProperties\" must be of type 'integer'" ); - } - } - - // required - if( const auto* p = find( "required" ) ) { - if( !p->is_array() ) { - throw std::runtime_error( "invalid JSON Schema: \"required\" must be of type 'array'" ); - } - if( p->get_array().empty() ) { - throw std::runtime_error( "invalid JSON Schema: \"required\" must have at least one element" ); - } - for( const auto& e : p->get_array() ) { - if( !m_required.insert( e.get_string() ).second ) { - throw std::runtime_error( "invalid JSON Schema: duplicate required key" ); - } - } - } - - // properties - if( const auto* p = find( "properties" ) ) { - if( !p->is_object() ) { - throw std::runtime_error( "invalid JSON Schema: \"properties\" must be of type 'object'" ); - } - for( const auto& e : p->get_object() ) { - m_referenced_pointers.insert( &e.second.skip_value_ptr() ); - } - m_properties = p; - } - - // patternProperties - if( const auto* p = find( "patternProperties" ) ) { - if( !p->is_object() ) { - throw std::runtime_error( "invalid JSON Schema: \"patternProperties\" must be of type 'object'" ); - } - for( const auto& e : p->get_object() ) { - try { - m_pattern_properties.emplace_back( std::regex( e.first ), &e.second.skip_value_ptr() ); - } - catch( const std::regex_error& ex ) { - throw std::runtime_error( "invalid JSON Schema: keys in object \"patternProperties\" must be regular expressions: " + std::string( ex.what() ) ); - } - m_referenced_pointers.insert( &e.second.skip_value_ptr() ); - } - } - - // additionalProperties - if( const auto* p = find( "additionalProperties" ) ) { - const type t = p->type(); - if( t == type::OBJECT ) { - m_referenced_pointers.insert( p ); - } - else if( t != type::BOOLEAN ) { - throw std::runtime_error( "invalid JSON Schema: \"additionalProperties\" must be of type 'boolean' or 'object'" ); - } - m_additional_properties = p; - } - - // dependencies - if( const auto* p = find( "dependencies" ) ) { - if( !p->is_object() ) { - throw std::runtime_error( "invalid JSON Schema: \"dependencies\" must be of type 'object'" ); - } - for( const auto& e : p->get_object() ) { - const auto* p2 = &e.second.skip_value_ptr(); - if( p2->is_object() ) { - m_schema_dependencies.emplace( e.first, p2 ); - m_referenced_pointers.insert( p2 ); - } - else if( p2->is_array() ) { - if( p2->get_array().empty() ) { - throw std::runtime_error( "invalid JSON Schema: values in object \"dependencies\" of type 'array' must have at least one element" ); - } - std::set< std::string > s; - for( const auto& r : p2->get_array() ) { - if( !r.is_string() ) { - throw std::runtime_error( "invalid JSON Schema: values in object \"dependencies\" of type 'array' must contain elements of type 'string'" ); - } - if( !s.emplace( r.get_string() ).second ) { - throw std::runtime_error( "invalid JSON Schema: values in object \"dependencies\" of type 'array' must contain unique elements of type 'string'" ); - } - } - m_property_dependencies.emplace( e.first, std::move( s ) ); - } - else { - throw std::runtime_error( "invalid JSON Schema: values in object \"dependencies\" must be of type 'object' or 'array'" ); - } - } - if( !p->get_object().empty() ) { - m_flags = m_flags | HAS_DEPENDENCIES; - } - } - - // default - if( const auto* p = find( "default" ) ) { - // TODO: the value should validate against the JSON Schema itself - } - } - - schema_node( const schema_node& ) = delete; - schema_node( schema_node&& ) = delete; - - ~schema_node() = default; - - void operator=( const schema_node& ) = delete; - void operator=( schema_node&& ) = delete; - - [[nodiscard]] const std::set< const basic_value< Traits >* >& referenced_pointers() const noexcept - { - return m_referenced_pointers; - } - }; - - template< template< typename... > class Traits > - class schema_consumer - { - private: - const std::shared_ptr< const schema_container< Traits > > m_container; - const schema_node< Traits >* const m_node; - - std::vector< std::unique_ptr< events_compare< Traits > > > m_enum; - std::unique_ptr< events::hash > m_hash; - std::set< std::string > m_unique; - std::set< std::string > m_keys; - std::vector< std::size_t > m_count; - std::vector< std::unique_ptr< schema_consumer > > m_properties; - std::vector< std::unique_ptr< schema_consumer > > m_all_of; - std::vector< std::unique_ptr< schema_consumer > > m_any_of; - std::vector< std::unique_ptr< schema_consumer > > m_one_of; - std::map< std::string, std::unique_ptr< schema_consumer > > m_schema_dependencies; - std::unique_ptr< schema_consumer > m_not; - std::unique_ptr< schema_consumer > m_item; - bool m_match = true; - - void validate_type( const schema_flags t ) - { - if( !m_count.empty() ) { - return; - } - if( ( m_node->m_flags & HAS_TYPE ) == 0 ) { - return; - } - if( ( m_node->m_flags & t ) == 0 ) { - m_match = false; - } - } - - // note: lambda returns true if validation failure detected - template< typename F > - void validate_enum( F&& f ) - { - assert( m_match ); - if( m_node->m_flags & HAS_ENUM ) { - m_enum.erase( std::remove_if( m_enum.begin(), m_enum.end(), [&]( const std::unique_ptr< events_compare< Traits > >& p ) { return f( *p ); } ), m_enum.end() ); - if( m_enum.empty() ) { - m_match = false; - } - } - } - - template< typename F > - void validate_item( F&& f ) - { - if( m_item ) { - if( f( m_item ) ) { - m_match = false; - } - } - } - - template< typename F > - void validate_properties( F&& f ) - { - for( auto& p : m_properties ) { - if( f( p ) ) { - m_match = false; - break; - } - } - } - - template< typename F > - void validate_schema_dependencies( F&& f ) - { - auto it = m_schema_dependencies.begin(); - while( it != m_schema_dependencies.end() ) { - if( f( it->second ) ) { - it = m_schema_dependencies.erase( it ); - } - else { - ++it; - } - } - } - - template< typename F > - void validate_all_of( F&& f ) - { - for( auto& p : m_all_of ) { - if( f( p ) ) { - m_match = false; - break; - } - } - } - - template< typename F > - void validate_any_of( F&& f ) - { - if( !m_any_of.empty() ) { - m_any_of.erase( std::remove_if( m_any_of.begin(), m_any_of.end(), f ), m_any_of.end() ); - if( m_any_of.empty() ) { - m_match = false; - } - } - } - - template< typename F > - void validate_one_of( F&& f ) - { - if( !m_one_of.empty() ) { - m_one_of.erase( std::remove_if( m_one_of.begin(), m_one_of.end(), f ), m_one_of.end() ); - if( m_one_of.empty() ) { - m_match = false; - } - } - } - - template< typename F > - void validate_not( F&& f ) - { - if( m_not ) { - if( f( m_not ) ) { - m_not.reset(); - } - } - } - - // note: lambda returns true if validation failure detected - template< typename F > - void validate_collections( F&& f ) - { - assert( m_match ); - const auto f2 = [&]( const std::unique_ptr< schema_consumer >& p ) { return f( *p ); }; - if( m_match ) { - validate_item( f2 ); - } - if( m_match ) { - validate_properties( f2 ); - } - if( m_match ) { - validate_all_of( f2 ); - } - if( m_match ) { - validate_any_of( f2 ); - } - if( m_match ) { - validate_one_of( f2 ); - } - if( m_match ) { - validate_not( f2 ); - } - if( m_match ) { - validate_schema_dependencies( f2 ); - } - } - - [[nodiscard]] static bool is_multiple_of( const double v, const double d ) - { - const auto r = std::fmod( v, d ); - if( std::fabs( r ) < std::numeric_limits< double >::epsilon() ) { - return true; - } - if( std::fabs( r - d ) < std::numeric_limits< double >::epsilon() ) { - return true; - } - return false; - } - - void validate_multiple_of( const std::int64_t v ) - { - switch( m_node->m_flags & HAS_MULTIPLE_OF ) { - case HAS_MULTIPLE_OF_UNSIGNED: - if( v < 0 ) { - if( ( -v % m_node->m_multiple_of.u ) != 0 ) { - m_match = false; - } - } - else { - if( ( v % m_node->m_multiple_of.u ) != 0 ) { - m_match = false; - } - } - break; - case HAS_MULTIPLE_OF_DOUBLE: - if( !is_multiple_of( double( v ), m_node->m_multiple_of.d ) ) { - m_match = false; - } - break; - } - } - - void validate_multiple_of( const std::uint64_t v ) - { - switch( m_node->m_flags & HAS_MULTIPLE_OF ) { - case HAS_MULTIPLE_OF_UNSIGNED: - if( ( v % m_node->m_multiple_of.u ) != 0 ) { - m_match = false; - } - break; - case HAS_MULTIPLE_OF_DOUBLE: - if( !is_multiple_of( double( v ), m_node->m_multiple_of.d ) ) { - m_match = false; - } - break; - } - } - - void validate_multiple_of( const double v ) - { - switch( m_node->m_flags & HAS_MULTIPLE_OF ) { - case HAS_MULTIPLE_OF_UNSIGNED: - if( !is_multiple_of( v, double( m_node->m_multiple_of.u ) ) ) { - m_match = false; - } - break; - case HAS_MULTIPLE_OF_DOUBLE: - if( !is_multiple_of( v, m_node->m_multiple_of.d ) ) { - m_match = false; - } - break; - } - } - - void validate_number( const std::int64_t v ) - { - validate_multiple_of( v ); - switch( m_node->m_flags & ( HAS_MAXIMUM | EXCLUSIVE_MAXIMUM ) ) { - case HAS_MAXIMUM_SIGNED: - if( v > m_node->m_maximum.i ) { - m_match = false; - } - break; - case HAS_MAXIMUM_SIGNED | EXCLUSIVE_MAXIMUM: - if( v >= m_node->m_maximum.i ) { - m_match = false; - } - break; - case HAS_MAXIMUM_UNSIGNED: - if( v >= 0 && static_cast< std::uint64_t >( v ) > m_node->m_maximum.u ) { - m_match = false; - } - break; - case HAS_MAXIMUM_UNSIGNED | EXCLUSIVE_MAXIMUM: - if( v >= 0 && static_cast< std::uint64_t >( v ) >= m_node->m_maximum.u ) { - m_match = false; - } - break; - case HAS_MAXIMUM_DOUBLE: - if( v > m_node->m_maximum.d ) { - m_match = false; - } - break; - case HAS_MAXIMUM_DOUBLE | EXCLUSIVE_MAXIMUM: - if( v >= m_node->m_maximum.d ) { - m_match = false; - } - break; - } - switch( m_node->m_flags & ( HAS_MINIMUM | EXCLUSIVE_MINIMUM ) ) { - case HAS_MINIMUM_SIGNED: - if( v < m_node->m_minimum.i ) { - m_match = false; - } - break; - case HAS_MINIMUM_SIGNED | EXCLUSIVE_MINIMUM: - if( v <= m_node->m_minimum.i ) { - m_match = false; - } - break; - case HAS_MINIMUM_UNSIGNED: - if( v < 0 || static_cast< std::uint64_t >( v ) < m_node->m_minimum.u ) { - m_match = false; - } - break; - case HAS_MINIMUM_UNSIGNED | EXCLUSIVE_MINIMUM: - if( v < 0 || static_cast< std::uint64_t >( v ) <= m_node->m_minimum.u ) { - m_match = false; - } - break; - case HAS_MINIMUM_DOUBLE: - if( v < m_node->m_minimum.d ) { - m_match = false; - } - break; - case HAS_MINIMUM_DOUBLE | EXCLUSIVE_MINIMUM: - if( v <= m_node->m_minimum.d ) { - m_match = false; - } - break; - } - } - - void validate_number( const std::uint64_t v ) - { - validate_multiple_of( v ); - switch( m_node->m_flags & ( HAS_MAXIMUM | EXCLUSIVE_MAXIMUM ) ) { - case HAS_MAXIMUM_SIGNED: - if( m_node->m_maximum.i < 0 || v > static_cast< std::uint64_t >( m_node->m_maximum.i ) ) { - m_match = false; - } - break; - case HAS_MAXIMUM_SIGNED | EXCLUSIVE_MAXIMUM: - if( m_node->m_maximum.i < 0 || v >= static_cast< std::uint64_t >( m_node->m_maximum.i ) ) { - m_match = false; - } - break; - case HAS_MAXIMUM_UNSIGNED: - if( v > m_node->m_maximum.u ) { - m_match = false; - } - break; - case HAS_MAXIMUM_UNSIGNED | EXCLUSIVE_MAXIMUM: - if( v >= m_node->m_maximum.u ) { - m_match = false; - } - break; - case HAS_MAXIMUM_DOUBLE: - if( v > m_node->m_maximum.d ) { - m_match = false; - } - break; - case HAS_MAXIMUM_DOUBLE | EXCLUSIVE_MAXIMUM: - if( v >= m_node->m_maximum.d ) { - m_match = false; - } - break; - } - switch( m_node->m_flags & ( HAS_MINIMUM | EXCLUSIVE_MINIMUM ) ) { - case HAS_MINIMUM_SIGNED: - if( m_node->m_minimum.i >= 0 && v < static_cast< std::uint64_t >( m_node->m_minimum.i ) ) { - m_match = false; - } - break; - case HAS_MINIMUM_SIGNED | EXCLUSIVE_MINIMUM: - if( m_node->m_minimum.i >= 0 && v <= static_cast< std::uint64_t >( m_node->m_minimum.i ) ) { - m_match = false; - } - break; - case HAS_MINIMUM_UNSIGNED: - if( v < m_node->m_minimum.u ) { - m_match = false; - } - break; - case HAS_MINIMUM_UNSIGNED | EXCLUSIVE_MINIMUM: - if( v <= m_node->m_minimum.u ) { - m_match = false; - } - break; - case HAS_MINIMUM_DOUBLE: - if( v < m_node->m_minimum.d ) { - m_match = false; - } - break; - case HAS_MINIMUM_DOUBLE | EXCLUSIVE_MINIMUM: - if( v <= m_node->m_minimum.d ) { - m_match = false; - } - break; - } - } - - void validate_number( const double v ) - { - validate_multiple_of( v ); - switch( m_node->m_flags & ( HAS_MAXIMUM | EXCLUSIVE_MAXIMUM ) ) { - case HAS_MAXIMUM_SIGNED: - if( v > m_node->m_maximum.i ) { - m_match = false; - } - break; - case HAS_MAXIMUM_SIGNED | EXCLUSIVE_MAXIMUM: - if( v >= m_node->m_maximum.i ) { - m_match = false; - } - break; - case HAS_MAXIMUM_UNSIGNED: - if( v > m_node->m_maximum.u ) { - m_match = false; - } - break; - case HAS_MAXIMUM_UNSIGNED | EXCLUSIVE_MAXIMUM: - if( v >= m_node->m_maximum.u ) { - m_match = false; - } - break; - case HAS_MAXIMUM_DOUBLE: - if( v > m_node->m_maximum.d ) { - m_match = false; - } - break; - case HAS_MAXIMUM_DOUBLE | EXCLUSIVE_MAXIMUM: - if( v >= m_node->m_maximum.d ) { - m_match = false; - } - break; - } - switch( m_node->m_flags & ( HAS_MINIMUM | EXCLUSIVE_MINIMUM ) ) { - case HAS_MINIMUM_SIGNED: - if( v < m_node->m_minimum.i ) { - m_match = false; - } - break; - case HAS_MINIMUM_SIGNED | EXCLUSIVE_MINIMUM: - if( v <= m_node->m_minimum.i ) { - m_match = false; - } - break; - case HAS_MINIMUM_UNSIGNED: - if( v < m_node->m_minimum.u ) { - m_match = false; - } - break; - case HAS_MINIMUM_UNSIGNED | EXCLUSIVE_MINIMUM: - if( v <= m_node->m_minimum.u ) { - m_match = false; - } - break; - case HAS_MINIMUM_DOUBLE: - if( v < m_node->m_minimum.d ) { - m_match = false; - } - break; - case HAS_MINIMUM_DOUBLE | EXCLUSIVE_MINIMUM: - if( v <= m_node->m_minimum.d ) { - m_match = false; - } - break; - } - } - - void validate_string( const std::string_view v ) - { - if( m_node->m_flags & HAS_MAX_LENGTH && v.size() > m_node->m_max_length ) { - m_match = false; - } - if( m_node->m_flags & HAS_MIN_LENGTH && v.size() < m_node->m_min_length ) { - m_match = false; - } - if( m_match && m_node->m_pattern ) { - if( !std::regex_search( v.begin(), v.end(), *m_node->m_pattern ) ) { - m_match = false; - } - } - if( m_match && m_node->m_format != schema_format::none ) { - switch( m_node->m_format ) { - case schema_format::date_time: - if( !internal::parse_date_time( v ) ) { - m_match = false; - } - break; - case schema_format::email: - if( ( v.size() > 255 ) || !internal::parse< internal::email >( v ) ) { - m_match = false; - } - break; - case schema_format::hostname: - if( ( v.size() > 255 ) || !internal::parse< internal::hostname >( v ) ) { - m_match = false; - } - break; - case schema_format::ipv4: - if( !internal::parse< pegtl::uri::IPv4address >( v ) ) { - m_match = false; - } - break; - case schema_format::ipv6: - if( !internal::parse< pegtl::uri::IPv6address >( v ) ) { - m_match = false; - } - break; - case schema_format::uri: - // TODO: What rule exactly should we apply here?? JSON Schema is not exactly the best spec I've ever read... - if( !internal::parse< pegtl::uri::URI >( v ) ) { - m_match = false; - } - break; - case schema_format::none:; - } - } - } - - void validate_elements( const std::size_t v ) - { - if( m_node->m_flags & HAS_MAX_ITEMS && v > m_node->m_max_items ) { - m_match = false; - } - if( m_node->m_flags & HAS_MIN_ITEMS && v < m_node->m_min_items ) { - m_match = false; - } - } - - void validate_members( const std::size_t v ) - { - if( m_node->m_flags & HAS_MAX_PROPERTIES && v > m_node->m_max_properties ) { - m_match = false; - } - if( m_node->m_flags & HAS_MIN_PROPERTIES && v < m_node->m_min_properties ) { - m_match = false; - } - } - - public: - schema_consumer( const std::shared_ptr< const schema_container< Traits > >& c, const schema_node< Traits >& n ) - : m_container( c ), - m_node( &n ) - { - if( m_node->m_flags & HAS_ENUM ) { - const auto& a = m_node->m_value->at( "enum" ).get_array(); - m_enum.reserve( a.size() ); - for( const auto& e : a ) { - m_enum.emplace_back( std::make_unique< events_compare< Traits > >() ); - m_enum.back()->push( &e ); - } - } - if( const auto* p = m_node->m_all_of ) { - for( const auto& e : p->get_array() ) { - m_all_of.push_back( m_container->consumer( &e.skip_value_ptr() ) ); - } - } - if( const auto* p = m_node->m_any_of ) { - for( const auto& e : p->get_array() ) { - m_any_of.push_back( m_container->consumer( &e.skip_value_ptr() ) ); - } - } - if( const auto* p = m_node->m_one_of ) { - for( const auto& e : p->get_array() ) { - m_one_of.push_back( m_container->consumer( &e.skip_value_ptr() ) ); - } - } - if( const auto* p = m_node->m_not ) { - m_not = m_container->consumer( p ); - } - for( const auto& e : m_node->m_schema_dependencies ) { - m_schema_dependencies.emplace( e.first, m_container->consumer( e.second ) ); - } - } - - schema_consumer( const schema_consumer& ) = delete; - schema_consumer( schema_consumer&& ) = delete; - - ~schema_consumer() = default; - - void operator=( const schema_consumer& ) = delete; - void operator=( schema_consumer&& ) = delete; - - [[nodiscard]] bool finalize() - { - if( m_match && !m_all_of.empty() ) { - for( auto& e : m_all_of ) { - if( !e->finalize() ) { - m_match = false; - break; - } - } - } - if( m_match && !m_any_of.empty() ) { - m_any_of.erase( std::remove_if( m_any_of.begin(), m_any_of.end(), []( const std::unique_ptr< schema_consumer >& c ) { return !c->finalize(); } ), m_any_of.end() ); - if( m_any_of.empty() ) { - m_match = false; - } - } - if( m_match && !m_one_of.empty() ) { - m_one_of.erase( std::remove_if( m_one_of.begin(), m_one_of.end(), []( const std::unique_ptr< schema_consumer >& c ) { return !c->finalize(); } ), m_one_of.end() ); - if( m_one_of.size() != 1 ) { - m_match = false; - } - } - if( m_match && m_not && m_not->finalize() ) { - m_match = false; - } - if( m_match && m_node->m_flags & HAS_DEPENDENCIES ) { - for( const auto& e : m_node->m_schema_dependencies ) { - if( m_keys.count( e.first ) != 0 ) { - const auto it = m_schema_dependencies.find( e.first ); - if( it == m_schema_dependencies.end() ) { - m_match = false; - break; - } - if( !it->second->finalize() ) { - m_match = false; - break; - } - } - } - } - return m_match; - } - - [[nodiscard]] bool match() const noexcept - { - return m_match; - } - - void null() - { - if( m_match ) { - validate_type( NULL_ ); - } - if( m_match ) { - validate_enum( []( events_compare< Traits >& c ) { c.null(); return ! c.match(); } ); - } - if( m_match ) { - validate_collections( []( schema_consumer& c ) { c.null(); return ! c.match(); } ); - } - if( m_match && m_hash ) { - m_hash->null(); - } - } - - void boolean( const bool v ) - { - if( m_match ) { - validate_type( BOOLEAN ); - } - if( m_match ) { - validate_enum( [=]( events_compare< Traits >& c ) { c.boolean( v ); return ! c.match(); } ); - } - if( m_match ) { - validate_collections( [=]( schema_consumer& c ) { c.boolean( v ); return ! c.match(); } ); - } - if( m_match && m_hash ) { - m_hash->boolean( v ); - } - } - - void number( const std::int64_t v ) - { - if( m_match ) { - validate_type( INTEGER | NUMBER ); - } - if( m_match ) { - validate_enum( [=]( events_compare< Traits >& c ) { c.number( v ); return ! c.match(); } ); - } - if( m_match ) { - validate_collections( [=]( schema_consumer& c ) { c.number( v ); return ! c.match(); } ); - } - if( m_match && m_count.empty() ) { - validate_number( v ); - } - if( m_match && m_hash ) { - m_hash->number( v ); - } - } - - void number( const std::uint64_t v ) - { - if( m_match ) { - validate_type( INTEGER | NUMBER ); - } - if( m_match ) { - validate_enum( [=]( events_compare< Traits >& c ) { c.number( v ); return ! c.match(); } ); - } - if( m_match ) { - validate_collections( [=]( schema_consumer& c ) { c.number( v ); return ! c.match(); } ); - } - if( m_match && m_count.empty() ) { - validate_number( v ); - } - if( m_match && m_hash ) { - m_hash->number( v ); - } - } - - void number( const double v ) - { - if( m_match ) { - validate_type( NUMBER ); - } - if( m_match ) { - validate_enum( [=]( events_compare< Traits >& c ) { c.number( v ); return ! c.match(); } ); - } - if( m_match ) { - validate_collections( [=]( schema_consumer& c ) { c.number( v ); return ! c.match(); } ); - } - if( m_match && m_count.empty() ) { - validate_number( v ); - } - if( m_match && m_hash ) { - m_hash->number( v ); - } - } - - void string( const std::string_view v ) - { - if( m_match ) { - validate_type( STRING ); - } - if( m_match ) { - validate_enum( [&]( events_compare< Traits >& c ) { c.string( v ); return ! c.match(); } ); - } - if( m_match ) { - validate_collections( [&]( schema_consumer& c ) { c.string( v ); return ! c.match(); } ); - } - if( m_match && m_count.empty() ) { - validate_string( v ); - } - if( m_match && m_hash ) { - m_hash->string( v ); - } - } - - void binary( const tao::binary_view /*unused*/ ) - { - // TODO: What? - } - - void begin_array( const std::size_t /*unused*/ = 0 ) - { - if( m_match ) { - validate_type( ARRAY ); - } - if( m_match ) { - validate_enum( []( events_compare< Traits >& c ) { c.begin_array(); return ! c.match(); } ); - } - if( m_match ) { - validate_collections( []( schema_consumer& c ) { c.begin_array(); return ! c.match(); } ); - } - if( m_match ) { - if( m_hash ) { - m_hash->begin_array(); - } - else if( m_count.empty() && ( ( m_node->m_flags & HAS_UNIQUE_ITEMS ) != 0 ) ) { - m_hash = std::make_unique< events::hash >(); - } - } - if( m_match && m_count.empty() ) { - if( const auto* p = m_node->m_items ) { - if( p->is_object() ) { - m_item = m_container->consumer( p ); - } - else { - const auto& a = p->get_array(); - if( !a.empty() ) { - m_item = m_container->consumer( &a[ 0 ].skip_value_ptr() ); - } - } - } - if( !m_item ) { - if( const auto* p = m_node->m_additional_items ) { - if( p->is_object() ) { - m_item = m_container->consumer( p ); - } - } - } - } - m_count.push_back( 0 ); - } - - void element() - { - if( m_match ) { - validate_enum( []( events_compare< Traits >& c ) { c.element(); return ! c.match(); } ); - } - if( m_match && m_item ) { - if( m_count.size() == 1 ) { - if( !m_item->finalize() ) { - m_match = false; - } - m_item.reset(); - } - } - if( m_match ) { - validate_collections( []( schema_consumer& c ) { c.element(); return ! c.match(); } ); - } - if( m_match && m_hash ) { - if( m_count.size() == 1 ) { - if( !m_unique.emplace( m_hash->value() ).second ) { - m_match = false; - } - m_hash->reset(); - } - else { - m_hash->element(); - } - } - const auto next = ++m_count.back(); - if( m_match && ( m_count.size() == 1 ) ) { - if( const auto* p = m_node->m_items ) { - if( p->is_object() ) { - m_item = m_container->consumer( p ); - } - else { - const auto& a = p->get_array(); - if( next < a.size() ) { - m_item = m_container->consumer( &a[ next ].skip_value_ptr() ); - } - } - } - if( !m_item ) { - if( const auto* p = m_node->m_additional_items ) { - if( p->is_object() ) { - m_item = m_container->consumer( p ); - } - } - } - } - } - - void end_array( const std::size_t /*unused*/ = 0 ) - { - if( m_match ) { - validate_enum( []( events_compare< Traits >& c ) { c.end_array(); return ! c.match(); } ); - } - if( m_match && m_item && ( m_count.size() == 1 ) ) { - if( !m_item->finalize() ) { - m_match = false; - } - m_item.reset(); - } - if( m_match && ( m_count.size() == 1 ) ) { - if( m_node->m_items && m_node->m_items->is_array() ) { - if( m_node->m_additional_items && m_node->m_additional_items->is_boolean() ) { - if( !m_node->m_additional_items->get_boolean() ) { - if( m_count.back() > m_node->m_items->get_array().size() ) { - m_match = false; - } - } - } - } - } - if( m_match ) { - validate_collections( []( schema_consumer& c ) { c.end_array(); return ! c.match(); } ); - } - if( m_match && m_hash ) { - m_hash->end_array(); - } - if( m_match && ( m_count.size() == 1 ) ) { - validate_elements( m_count.back() ); - } - m_count.pop_back(); - } - - void begin_object( const std::size_t /*unused*/ = 0 ) - { - if( m_match ) { - validate_type( OBJECT ); - } - if( m_match ) { - validate_enum( []( events_compare< Traits >& c ) { c.begin_object(); return ! c.match(); } ); - } - if( m_match ) { - validate_collections( []( schema_consumer& c ) { c.begin_object(); return ! c.match(); } ); - } - if( m_match && m_hash ) { - m_hash->begin_object(); - } - m_count.push_back( 0 ); - } - - void key( const std::string& v ) - { - if( m_match ) { - validate_enum( [&]( events_compare< Traits >& c ) { c.key( v ); return ! c.match(); } ); - } - if( m_match ) { - validate_collections( [&]( schema_consumer& c ) { c.key( v ); return ! c.match(); } ); - } - if( m_match && m_hash ) { - m_hash->key( v ); - } - if( m_match && ( m_count.size() == 1 ) && ( m_node->m_flags & HAS_DEPENDENCIES || !m_node->m_required.empty() ) ) { - if( !m_keys.insert( v ).second ) { - // duplicate keys immediately invalidate! - // TODO: throw? - m_match = false; - } - } - if( m_match && m_properties.empty() && ( m_count.size() == 1 ) ) { - if( const auto* p = m_node->m_properties ) { - const auto& o = p->get_object(); - const auto it = o.find( v ); - if( it != o.end() ) { - m_properties.push_back( m_container->consumer( &it->second.skip_value_ptr() ) ); - } - } - for( const auto& e : m_node->m_pattern_properties ) { - if( std::regex_search( v, e.first ) ) { - m_properties.push_back( m_container->consumer( e.second ) ); - } - } - if( m_properties.empty() ) { - if( const auto* p = m_node->m_additional_properties ) { - if( p->is_boolean() ) { - if( !p->get_boolean() ) { - m_match = false; - } - } - else { - m_properties.push_back( m_container->consumer( p ) ); - } - } - } - } - } - - void key( const std::string_view sv ) - { - key( std::string( sv ) ); - } - - void key( const char* v ) - { - key( std::string( v ) ); - } - - void member() - { - if( m_match ) { - validate_enum( []( events_compare< Traits >& c ) { c.member(); return ! c.match(); } ); - } - if( m_match && !m_properties.empty() && ( m_count.size() == 1 ) ) { - for( auto& e : m_properties ) { - if( !e->finalize() ) { - m_match = false; - break; - } - } - m_properties.clear(); - } - if( m_match ) { - validate_collections( []( schema_consumer& c ) { c.member(); return ! c.match(); } ); - } - if( m_match && m_hash ) { - m_hash->member(); - } - ++m_count.back(); - } - - void end_object( const std::size_t /*unused*/ = 0 ) - { - if( m_match ) { - validate_enum( []( events_compare< Traits >& c ) { c.end_object(); return ! c.match(); } ); - } - if( m_match ) { - validate_collections( []( schema_consumer& c ) { c.end_object(); return ! c.match(); } ); - } - if( m_match && m_hash ) { - m_hash->end_object(); - } - if( m_match && ( m_count.size() == 1 ) ) { - validate_members( m_count.back() ); - } - if( m_match && ( m_count.size() == 1 ) && !m_node->m_required.empty() ) { - if( !std::includes( m_keys.begin(), m_keys.end(), m_node->m_required.begin(), m_node->m_required.end() ) ) { - m_match = false; - } - } - if( m_match && ( m_count.size() == 1 ) && m_node->m_flags & HAS_DEPENDENCIES ) { - for( const auto& e : m_node->m_property_dependencies ) { - if( m_keys.count( e.first ) != 0 ) { - if( !std::includes( m_keys.begin(), m_keys.end(), e.second.begin(), e.second.end() ) ) { - m_match = false; - break; - } - } - } - } - m_count.pop_back(); - } - }; - - template< template< typename... > class Traits > - class schema_container - : public std::enable_shared_from_this< schema_container< Traits > > - { - private: - basic_value< Traits > m_value; - - using nodes_t = std::map< const basic_value< Traits >*, std::unique_ptr< schema_node< Traits > > >; - nodes_t m_nodes; - - void make_node( const basic_value< Traits >* p ) - { - m_nodes.emplace( p, std::make_unique< schema_node< Traits > >( this, *p ) ); - } - - public: - explicit schema_container( const basic_value< Traits >& v ) - : m_value( v.skip_value_ptr() ) - { - resolve_references( m_value ); - make_node( &m_value ); - while( true ) { - std::set< const basic_value< Traits >* > required; - for( const auto& e : m_nodes ) { - auto s = e.second->referenced_pointers(); - required.insert( s.begin(), s.end() ); - } - for( const auto& e : m_nodes ) { - required.erase( e.first ); - } - if( required.empty() ) { - break; - } - for( const auto& e : required ) { - make_node( e ); - } - } - } - - [[nodiscard]] std::unique_ptr< schema_consumer< Traits > > consumer( const basic_value< Traits >* p ) const - { - const auto it = m_nodes.find( p ); - if( it == m_nodes.end() ) { - throw std::logic_error( "invalid node ptr, no schema registered" ); - } - return std::make_unique< schema_consumer< Traits > >( this->shared_from_this(), *it->second ); - } - - [[nodiscard]] std::unique_ptr< schema_consumer< Traits > > consumer() const - { - return consumer( &m_value ); - } - }; - - } // namespace internal - - template< template< typename... > class Traits > - class basic_schema - { - private: - const std::shared_ptr< const internal::schema_container< Traits > > m_container; - - public: - explicit basic_schema( const basic_value< Traits >& v ) - : m_container( std::make_shared< internal::schema_container< Traits > >( v ) ) - { - } - - [[nodiscard]] std::unique_ptr< internal::schema_consumer< Traits > > consumer() const - { - return m_container->consumer(); - } - - [[nodiscard]] bool validate( const basic_value< Traits >& v ) const - { - // TODO: Value validation should be implemented independently, - // as it could be more efficient than Events validation! - const auto c = consumer(); - events::from_value( *c, v ); - return c->finalize(); - } - }; - - using schema = basic_schema< traits >; - - template< template< typename... > class Traits > - [[nodiscard]] basic_schema< Traits > make_schema( const basic_value< Traits >& v ) - { - return basic_schema< Traits >( v ); - } - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/set_traits.hpp b/include/tao/json/contrib/set_traits.hpp deleted file mode 100644 index 0b4b5fd4..00000000 --- a/include/tao/json/contrib/set_traits.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_SET_TRAITS_HPP -#define TAO_JSON_CONTRIB_SET_TRAITS_HPP - -#include - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "internal/array_traits.hpp" - -namespace tao::json -{ - template< typename T, typename... Ts > - struct set_traits - : internal::array_traits< std::set< T, Ts... > > - { - template< template< typename... > class Traits, typename... With > - static void to( const basic_value< Traits >& v, std::set< T, Ts... >& r, With&... with ) - { - const auto& a = v.get_array(); - for( const auto& i : a ) { - r.emplace( i.template as_with< T >( with... ) ); - } - } - - template< template< typename... > class Traits, typename Producer > - static void consume( Producer& parser, std::set< T, Ts... >& r ) - { - auto s = parser.begin_array(); - while( parser.element_or_end_array( s ) ) { - r.emplace( json::consume< T, Traits >( parser ) ); - } - } - }; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/shared_ptr_traits.hpp b/include/tao/json/contrib/shared_ptr_traits.hpp deleted file mode 100644 index a6c45713..00000000 --- a/include/tao/json/contrib/shared_ptr_traits.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_SHARED_PTR_TRAITS_HPP -#define TAO_JSON_CONTRIB_SHARED_PTR_TRAITS_HPP - -#include -#include -#include - -#include "../forward.hpp" - -#include "internal/indirect_traits.hpp" -#include "internal/type_traits.hpp" - -namespace tao::json -{ - namespace internal - { - template< typename T, typename U > - struct shared_ptr_traits - { - template< template< typename... > class Traits, typename... With > - [[nodiscard]] static auto as( const basic_value< Traits >& v, With&... with ) -> std::enable_if_t< use_first_ptr_as< T, Traits, With... >, std::shared_ptr< U > > - { - return std::make_shared< T >( v, with... ); - } - - template< template< typename... > class Traits, typename... With > - [[nodiscard]] static auto as( const basic_value< Traits >& v, With&... with ) -> std::enable_if_t< use_second_ptr_as< T, Traits, With... > || use_fourth_ptr_as< T, Traits, With... >, std::shared_ptr< U > > - { - return std::make_shared< T >( Traits< T >::as( v, with... ) ); - } - - template< template< typename... > class Traits, typename... With > - [[nodiscard]] static auto as( const basic_value< Traits >& v, With&... with ) -> std::enable_if_t< use_third_ptr_as< T, Traits, With... >, std::shared_ptr< U > > - { - auto t = std::make_shared< T >(); - Traits< T >::to( v, *t, with... ); - return t; - } - - template< template< typename... > class Traits, typename Producer > - [[nodiscard]] static auto consume( Producer& parser ) -> std::enable_if_t< use_first_ptr_consume< T, Traits, Producer > || use_third_ptr_consume< T, Traits, Producer >, std::shared_ptr< U > > - { - return Traits< T >::template consume< Traits >( parser ); - } - - template< template< typename... > class Traits, typename Producer > - [[nodiscard]] static auto consume( Producer& parser ) -> std::enable_if_t< use_second_ptr_consume< T, Traits, Producer >, std::shared_ptr< U > > - { - auto t = std::make_shared< T >(); - Traits< T >::template consume< Traits >( parser, *t ); - return t; - } - }; - - } // namespace internal - - template< typename T, typename U = T > - struct shared_ptr_traits - : internal::shared_ptr_traits< T, U > - { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const std::shared_ptr< U >& o ) - { - assert( o ); - v = static_cast< const T& >( *o ); - } - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, const std::shared_ptr< U >& o ) - { - assert( o ); - json::events::produce< Traits >( c, static_cast< const T& >( *o ) ); - } - }; - - template< typename T > - struct shared_ptr_traits< T, T > - : internal::shared_ptr_traits< T, T >, - internal::indirect_traits< std::shared_ptr< T > > - { - template< typename V > - using with_base = shared_ptr_traits< T, V >; - }; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/traits.hpp b/include/tao/json/contrib/traits.hpp deleted file mode 100644 index 16504d76..00000000 --- a/include/tao/json/contrib/traits.hpp +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_TRAITS_HPP -#define TAO_JSON_CONTRIB_TRAITS_HPP - -#include "../traits.hpp" - -#include "pair_traits.hpp" -#include "tuple_traits.hpp" - -#include "pointer_traits.hpp" - -#include "array_traits.hpp" -#include "deque_traits.hpp" -#include "list_traits.hpp" -#include "set_traits.hpp" -#include "unordered_set_traits.hpp" -#include "vector_traits.hpp" - -#include "vector_bool_traits.hpp" - -#include "map_traits.hpp" -#include "unordered_map_traits.hpp" - -#include "multimap_traits.hpp" -#include "multiset_traits.hpp" - -#include "shared_ptr_traits.hpp" -#include "unique_ptr_traits.hpp" - -namespace tao::json -{ - template< typename U, typename V > - struct traits< std::pair< U, V > > - : pair_traits< U, V > - {}; - - template< typename... Ts > - struct traits< std::tuple< Ts... > > - : tuple_traits< Ts... > - {}; - - template<> - struct traits< token > - : token_traits - {}; - - template<> - struct traits< pointer > - : pointer_traits - {}; - - template< typename T, std::size_t N > - struct traits< std::array< T, N > > - : array_traits< T, N > - {}; - - template< typename T, typename... Ts > - struct traits< std::deque< T, Ts... > > - : deque_traits< T, Ts... > - {}; - - template< typename T, typename... Ts > - struct traits< std::list< T, Ts... > > - : list_traits< T, Ts... > - {}; - - template< typename T, typename... Ts > - struct traits< std::set< T, Ts... > > - : set_traits< T, Ts... > - {}; - - template< typename T, typename... Ts > - struct traits< std::unordered_set< T, Ts... > > - : unordered_set_traits< T, Ts... > - {}; - - template< typename T, typename... Ts > - struct traits< std::vector< T, Ts... > > - : vector_traits< T, Ts... > - {}; - - template<> - struct traits< std::vector< bool > > - : vector_bool_traits - {}; - - template< typename T, typename... Ts > - struct traits< std::map< std::string, T, Ts... > > - : map_traits< T, Ts... > - {}; - - template< typename T, typename... Ts > - struct traits< std::unordered_map< std::string, T, Ts... > > - : unordered_map_traits< T, Ts... > - {}; - - template< typename T, typename... Ts > - struct traits< std::multiset< T, Ts... > > - : multiset_traits< T, Ts... > - {}; - - template< typename T, typename... Ts > - struct traits< std::multimap< std::string, T, Ts... > > - : multimap_traits< T, Ts... > - {}; - - template< typename T > - struct traits< std::shared_ptr< T > > - : shared_ptr_traits< T > - {}; - - template< typename T > - struct traits< std::unique_ptr< T > > - : unique_ptr_traits< T > - {}; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/tuple_traits.hpp b/include/tao/json/contrib/tuple_traits.hpp deleted file mode 100644 index 3061cfa2..00000000 --- a/include/tao/json/contrib/tuple_traits.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_TUPLE_TRAITS_HPP -#define TAO_JSON_CONTRIB_TUPLE_TRAITS_HPP - -#include -#include - -#include "../binding.hpp" - -namespace tao::json -{ - namespace internal - { - template< std::size_t I, typename... Ts > - struct getter - { - [[nodiscard]] static decltype( auto ) get( std::tuple< Ts... >& t ) noexcept - { - return std::get< I >( t ); - } - - [[nodiscard]] static decltype( auto ) cget( const std::tuple< Ts... >& t ) noexcept - { - return std::get< I >( t ); - } - }; - - template< typename Indices, typename... Ts > - struct tuple_traits; - - template< std::size_t... Is, typename... Ts > - struct tuple_traits< std::index_sequence< Is... >, Ts... > - { - template< std::size_t I > - using helper_t = binding::element2< &getter< I, Ts... >::cget, &getter< I, Ts... >::get >; - - using type = binding::array< helper_t< Is >... >; - }; - - } // namespace internal - - template< typename... Ts > - struct tuple_traits - : internal::tuple_traits< std::index_sequence_for< Ts... >, Ts... >::type - {}; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/unique_ptr_traits.hpp b/include/tao/json/contrib/unique_ptr_traits.hpp deleted file mode 100644 index 58f87483..00000000 --- a/include/tao/json/contrib/unique_ptr_traits.hpp +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_UNIQUE_PTR_TRAITS_HPP -#define TAO_JSON_CONTRIB_UNIQUE_PTR_TRAITS_HPP - -#include -#include - -#include "../forward.hpp" - -#include "internal/indirect_traits.hpp" -#include "internal/type_traits.hpp" - -namespace tao::json -{ - namespace internal - { - template< typename T, typename U > - struct unique_ptr_traits - { - template< template< typename... > class Traits, typename... With > - [[nodiscard]] static auto as( const basic_value< Traits >& v, With&... with ) -> std::enable_if_t< use_first_ptr_as< T, Traits, With... >, std::unique_ptr< U > > - { - return std::unique_ptr< U >( new T( v, with... ) ); - } - - template< template< typename... > class Traits, typename... With > - [[nodiscard]] static auto as( const basic_value< Traits >& v, With&... with ) -> std::enable_if_t< use_second_ptr_as< T, Traits, With... > || use_fourth_ptr_as< T, Traits, With... >, std::unique_ptr< U > > - { - return std::unique_ptr< U >( new T( Traits< T >::as( v, with... ) ) ); - } - - template< template< typename... > class Traits, typename... With > - [[nodiscard]] static auto as( const basic_value< Traits >& v, With&... with ) -> std::enable_if_t< use_third_ptr_as< T, Traits, With... >, std::unique_ptr< U > > - { - std::unique_ptr< U > t( new T() ); - Traits< T >::to( v, static_cast< T& >( *t ), with... ); - return t; - } - - template< template< typename... > class Traits, typename Producer > - [[nodiscard]] static auto consume( Producer& parser ) -> std::enable_if_t< use_first_ptr_consume< T, Traits, Producer > || use_third_ptr_consume< T, Traits, Producer >, std::unique_ptr< U > > - { - return Traits< T >::template consume< Traits >( parser ); - } - - template< template< typename... > class Traits, typename Producer > - [[nodiscard]] static auto consume( Producer& parser ) -> std::enable_if_t< use_second_ptr_consume< T, Traits, Producer >, std::unique_ptr< U > > - { - std::unique_ptr< U > t( new T() ); - Traits< T >::template consume< Traits >( parser, static_cast< T& >( *t ) ); - return t; - } - }; - - } // namespace internal - - template< typename T, typename U = T > - struct unique_ptr_traits - : internal::unique_ptr_traits< T, U > - { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const std::unique_ptr< U >& o ) - { - assert( o ); - v = static_cast< const T& >( *o ); - } - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, const std::unique_ptr< U >& o ) - { - assert( o ); - json::events::produce< Traits >( c, static_cast< const T& >( *o ) ); - } - }; - - template< typename T > - struct unique_ptr_traits< T, T > - : internal::unique_ptr_traits< T, T >, - internal::indirect_traits< std::unique_ptr< T > > - { - template< typename V > - using with_base = unique_ptr_traits< T, V >; - }; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/unordered_map_traits.hpp b/include/tao/json/contrib/unordered_map_traits.hpp deleted file mode 100644 index b591981a..00000000 --- a/include/tao/json/contrib/unordered_map_traits.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_UNORDERED_MAP_TRAITS_HPP -#define TAO_JSON_CONTRIB_UNORDERED_MAP_TRAITS_HPP - -#include -#include - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "internal/object_traits.hpp" - -namespace tao::json -{ - template< typename T, typename... Ts > - struct unordered_map_traits - : internal::object_traits< std::unordered_map< std::string, T, Ts... > > - { - template< template< typename... > class Traits, typename... With > - static void to( const basic_value< Traits >& v, std::unordered_map< std::string, T, Ts... >& r, With&... with ) - { - const auto& o = v.get_object(); - for( const auto& i : o ) { - r.try_emplace( i.first, Traits< T >::as( i.second, with... ) ); - } - } - - template< template< typename... > class Traits, typename Producer > - static void consume( Producer& parser, std::unordered_map< std::string, T, Ts... >& v ) - { - auto s = parser.begin_object(); - while( parser.member_or_end_object( s ) ) { - auto k = parser.key(); - v.try_emplace( std::move( k ), json::consume< T, Traits >( parser ) ); - } - } - }; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/unordered_set_traits.hpp b/include/tao/json/contrib/unordered_set_traits.hpp deleted file mode 100644 index 45b5de01..00000000 --- a/include/tao/json/contrib/unordered_set_traits.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_UNORDERED_SET_TRAITS_HPP -#define TAO_JSON_CONTRIB_UNORDERED_SET_TRAITS_HPP - -#include - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "internal/array_traits.hpp" - -namespace tao::json -{ - template< typename T, typename... Ts > - struct unordered_set_traits - : internal::array_traits< std::unordered_set< T, Ts... > > - { - template< template< typename... > class Traits, typename... With > - static void to( const basic_value< Traits >& v, std::unordered_set< T, Ts... >& r, With&... with ) - { - const auto& a = v.get_array(); - for( const auto& i : a ) { - r.try_emplace( Traits< T >::as( i, with... ) ); - } - } - - template< template< typename... > class Traits, typename Producer > - static void consume( Producer& parser, std::unordered_set< T, Ts... >& r ) - { - auto s = parser.begin_array(); - while( parser.element_or_end_array( s ) ) { - r.try_emplace( json::consume< T, Traits >( parser ) ); - } - } - }; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/vector_bool_traits.hpp b/include/tao/json/contrib/vector_bool_traits.hpp deleted file mode 100644 index 3b1d8db6..00000000 --- a/include/tao/json/contrib/vector_bool_traits.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_VECTOR_BOOL_TRAITS_HPP -#define TAO_JSON_CONTRIB_VECTOR_BOOL_TRAITS_HPP - -#include - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "vector_traits.hpp" - -namespace tao::json -{ - struct vector_bool_traits - : vector_traits< bool > - { - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const std::vector< bool >& o ) - { - v.emplace_array(); - v.get_array().reserve( o.size() ); - for( const auto& e : o ) { - v.emplace_back( bool( e ) ); - } - } - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, const std::vector< bool >& o ) - { - c.begin_array( o.size() ); - for( const auto& i : o ) { - json::events::produce< Traits >( c, bool( i ) ); - c.element(); - } - c.end_array( o.size() ); - } - - // TODO: Check whether anything else needs "special-casing". - }; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/contrib/vector_traits.hpp b/include/tao/json/contrib/vector_traits.hpp deleted file mode 100644 index 32c3734f..00000000 --- a/include/tao/json/contrib/vector_traits.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_CONTRIB_VECTOR_TRAITS_HPP -#define TAO_JSON_CONTRIB_VECTOR_TRAITS_HPP - -#include - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "internal/array_traits.hpp" - -namespace tao::json -{ - template< typename T, typename... Ts > - struct vector_traits - : internal::array_traits< std::vector< T, Ts... > > - { - template< template< typename... > class Traits, typename... With > - static void to( const basic_value< Traits >& v, std::vector< T, Ts... >& r, With&... with ) - { - const auto& a = v.get_array(); - for( const auto& i : a ) { - r.emplace_back( i.template as_with< T >( with... ) ); - } - } - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4127 ) -#endif - template< template< typename... > class Traits, typename Producer > - static void consume( Producer& parser, std::vector< T, Ts... >& v ) - { - auto s = parser.begin_array(); - if( s.size ) { - v.reserve( *s.size ); - } - while( parser.element_or_end_array( s ) ) { - v.emplace_back( json::consume< T, Traits >( parser ) ); - } - } -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - }; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/events.hpp b/include/tao/json/events.hpp deleted file mode 100644 index 8063909c..00000000 --- a/include/tao/json/events.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_HPP -#define TAO_JSON_EVENTS_HPP - -// Events producers -#include "events/from_file.hpp" -#include "events/from_input.hpp" -#include "events/from_stream.hpp" -#include "events/from_string.hpp" -#include "events/from_value.hpp" -#include "events/produce.hpp" - -// Events consumers -#include "events/to_pretty_stream.hpp" -#include "events/to_stream.hpp" -#include "events/to_string.hpp" -#include "events/to_value.hpp" - -// Events transformers -#include "events/binary_to_base64.hpp" -#include "events/binary_to_base64url.hpp" -#include "events/binary_to_exception.hpp" -#include "events/binary_to_hex.hpp" -#include "events/invalid_string_to_binary.hpp" -#include "events/invalid_string_to_exception.hpp" -#include "events/invalid_string_to_hex.hpp" -#include "events/key_camel_case_to_snake_case.hpp" -#include "events/key_snake_case_to_camel_case.hpp" -#include "events/limit_nesting_depth.hpp" -#include "events/limit_value_count.hpp" -#include "events/non_finite_to_exception.hpp" -#include "events/non_finite_to_null.hpp" -#include "events/non_finite_to_string.hpp" -#include "events/prefer_signed.hpp" -#include "events/prefer_unsigned.hpp" - -// Events other -#include "events/debug.hpp" -#include "events/discard.hpp" -#include "events/hash.hpp" -#include "events/tee.hpp" -#include "events/validate_event_order.hpp" -#include "events/validate_keys.hpp" - -#endif diff --git a/include/tao/json/events/apply.hpp b/include/tao/json/events/apply.hpp deleted file mode 100644 index 78a1ba90..00000000 --- a/include/tao/json/events/apply.hpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_APPLY_HPP -#define TAO_JSON_EVENTS_APPLY_HPP - -#include "ref.hpp" -#include "transformer.hpp" - -namespace tao::json::events -{ - template< template< typename... > class... Transformer, typename Consumer > - [[nodiscard]] transformer< ref< Consumer >, Transformer... > apply( Consumer& c ) noexcept( noexcept( transformer< ref< Consumer >, Transformer... >( c ) ) ) - { - return transformer< ref< Consumer >, Transformer... >( c ); - } - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/binary_to_base64.hpp b/include/tao/json/events/binary_to_base64.hpp deleted file mode 100644 index dcf930d2..00000000 --- a/include/tao/json/events/binary_to_base64.hpp +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_BINARY_TO_BASE64_HPP -#define TAO_JSON_EVENTS_BINARY_TO_BASE64_HPP - -#include "../binary_view.hpp" -#include "../internal/base64.hpp" - -namespace tao::json::events -{ - template< typename Consumer > - struct binary_to_base64 - : Consumer - { - using Consumer::Consumer; - - void binary( const tao::binary_view v ) - { - Consumer::string( internal::base64( v ) ); - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/binary_to_base64url.hpp b/include/tao/json/events/binary_to_base64url.hpp deleted file mode 100644 index e46bd6cc..00000000 --- a/include/tao/json/events/binary_to_base64url.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_BINARY_TO_BASE64URL_HPP -#define TAO_JSON_EVENTS_BINARY_TO_BASE64URL_HPP - -#include - -#include "../binary_view.hpp" -#include "../internal/base64url.hpp" - -namespace tao::json::events -{ - template< typename Consumer > - struct binary_to_base64url - : Consumer - { - using Consumer::Consumer; - - void binary( const tao::binary_view v ) - { - Consumer::string( internal::base64url( v ) ); - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/binary_to_exception.hpp b/include/tao/json/events/binary_to_exception.hpp deleted file mode 100644 index c14b34a5..00000000 --- a/include/tao/json/events/binary_to_exception.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_BINARY_TO_EXCEPTION_HPP -#define TAO_JSON_EVENTS_BINARY_TO_EXCEPTION_HPP - -#include - -#include "../binary_view.hpp" - -namespace tao::json::events -{ - template< typename Consumer > - struct binary_to_exception - : Consumer - { - using Consumer::Consumer; - - void binary( const tao::binary_view /*unused*/ ) - { - throw std::runtime_error( "invalid binary data" ); - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/binary_to_hex.hpp b/include/tao/json/events/binary_to_hex.hpp deleted file mode 100644 index 87cb21e3..00000000 --- a/include/tao/json/events/binary_to_hex.hpp +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_BINARY_TO_HEX_HPP -#define TAO_JSON_EVENTS_BINARY_TO_HEX_HPP - -#include "../binary_view.hpp" -#include "../internal/hexdump.hpp" - -namespace tao::json::events -{ - template< typename Consumer > - struct binary_to_hex - : Consumer - { - using Consumer::Consumer; - - void binary( const tao::binary_view v ) - { - Consumer::string( internal::hexdump( v ) ); - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/compare.hpp b/include/tao/json/events/compare.hpp deleted file mode 100644 index 80c907d3..00000000 --- a/include/tao/json/events/compare.hpp +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_COMPARE_HPP -#define TAO_JSON_EVENTS_COMPARE_HPP - -#include -#include -#include -#include -#include - -#include "../value.hpp" - -namespace tao::json -{ - namespace internal - { - template< template< typename... > class Traits > - class events_compare - { - protected: - std::vector< const basic_value< Traits >* > m_current; - std::vector< std::size_t > m_array_index; - // TODO: use std::unordered_set? or even std::vector!? - std::vector< std::set< const basic_value< Traits >* > > m_object_keys; - bool m_match = true; - - public: - events_compare() = default; - - events_compare( const events_compare& ) = delete; - events_compare( events_compare&& ) = delete; - - ~events_compare() = default; - - void operator=( const events_compare& ) = delete; - void operator=( events_compare&& ) = delete; - - void reset() noexcept - { - m_current.clear(); - m_array_index.clear(); - m_object_keys.clear(); - m_match = true; - } - - [[nodiscard]] static const basic_value< Traits >* skip_pointer( const basic_value< Traits >* p ) noexcept - { - while( p && p->is_value_ptr() ) { - p = p->get_value_ptr(); - } - return p; - } - - void push( const basic_value< Traits >* p ) - { - m_current.push_back( skip_pointer( p ) ); - } - - [[nodiscard]] bool match() const noexcept - { - return m_match; - } - - [[nodiscard]] const basic_value< Traits >& current() const noexcept - { - return *m_current.back(); - } - - void null() noexcept - { - m_match = m_match && ( m_current.back() != nullptr ) && ( current().is_null() ); - } - - void boolean( const bool v ) noexcept - { - m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); - } - - void number( const std::int64_t v ) noexcept - { - m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); - } - - void number( const std::uint64_t v ) noexcept - { - m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); - } - - void number( const double v ) noexcept - { - m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); - } - - void string( const std::string_view v ) noexcept - { - m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); - } - - void binary( const tao::binary_view v ) noexcept - { - m_match = m_match && ( m_current.back() != nullptr ) && ( current() == v ); - } - - void begin_array( const std::size_t /*unused*/ = 0 ) - { - if( m_current.back() == nullptr ) { - m_match = false; - m_current.push_back( nullptr ); - } - else { - const auto& a = current(); - if( !a.is_array() ) { - m_match = false; - m_current.push_back( nullptr ); - } - else { - const auto& v = a.get_array(); - if( !v.empty() ) { - push( &v.front() ); - } - else { - m_current.push_back( nullptr ); - } - } - } - m_array_index.push_back( 0 ); - } - - void element() noexcept - { - const auto i = ++m_array_index.back(); - if( m_match ) { - if( m_current.back() != nullptr ) { - const auto& a = ( *( m_current.end() - 2 ) )->get_array(); - if( i < a.size() ) { - m_current.back() = skip_pointer( &a[ i ] ); - } - else { - m_current.back() = nullptr; - } - } - } - } - - void end_array( const std::size_t /*unused*/ = 0 ) noexcept - { - m_current.pop_back(); - if( m_match ) { - if( m_array_index.back() != current().get_array().size() ) { - m_match = false; - } - } - m_array_index.pop_back(); - } - - void begin_object( const std::size_t /*unused*/ = 0 ) - { - if( m_current.back() == nullptr ) { - m_match = false; - } - else { - const auto& o = current(); - if( !o.is_object() ) { - m_match = false; - } - } - m_object_keys.emplace_back(); - } - - void key( const std::string& v ) - { - if( !m_match ) { - m_current.push_back( nullptr ); - } - else if( const auto* p = current().find( v ) ) { - if( !m_object_keys.back().insert( p ).second ) { - m_match = false; // duplicate key found! -> fail - m_current.push_back( nullptr ); - } - else { - push( p ); - } - } - else { - m_match = false; - m_current.push_back( nullptr ); - } - } - - void key( const std::string_view v ) - { - key( std::string( v ) ); - } - - void key( const char* v ) - { - key( std::string( v ) ); - } - - void member() noexcept - { - m_current.pop_back(); - } - - void end_object( const std::size_t /*unused*/ = 0 ) noexcept - { - if( m_match ) { - if( m_object_keys.back().size() != current().get_object().size() ) { - m_match = false; - } - } - m_object_keys.pop_back(); - } - }; - - } // namespace internal - - namespace events - { - // Events consumer that compares against a JSON Value. - - template< template< typename... > class Traits > - class basic_compare - : public internal::events_compare< Traits > - { - private: - const basic_value< Traits > m_value; - - public: - explicit basic_compare( const basic_value< Traits >& v ) - : m_value( v ) - { - reset(); - } - - explicit basic_compare( basic_value< Traits >&& v ) - : m_value( std::move( v ) ) - { - reset(); - } - - basic_compare( const basic_compare& ) = delete; - basic_compare( basic_compare&& ) = delete; - - ~basic_compare() = default; - - void operator=( const basic_compare& ) = delete; - void operator=( basic_compare&& ) = delete; - - void reset() - { - internal::events_compare< Traits >::reset(); - internal::events_compare< Traits >::push( &m_value ); - } - }; - - using compare = basic_compare< traits >; - - } // namespace events - -} // namespace tao::json - -#endif diff --git a/include/tao/json/events/debug.hpp b/include/tao/json/events/debug.hpp deleted file mode 100644 index 44eead54..00000000 --- a/include/tao/json/events/debug.hpp +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_DEBUG_HPP -#define TAO_JSON_EVENTS_DEBUG_HPP - -#include -#include -#include -#include -#include - -#include "../binary_view.hpp" - -#include "../external/ryu.hpp" - -#include "../internal/escape.hpp" -#include "../internal/hexdump.hpp" - -namespace tao::json::events -{ - // Events consumer that writes the events to a stream for debug purposes. - - class debug - { - private: - std::ostream& os; - - public: - explicit debug( std::ostream& in_os ) noexcept - : os( in_os ) - {} - - void null() - { - os << "null\n"; - } - - void boolean( const bool v ) - { - if( v ) { - os << "boolean: true\n"; - } - else { - os << "boolean: false\n"; - } - } - - void number( const std::int64_t v ) - { - os << "std::int64_t: " << v << '\n'; - } - - void number( const std::uint64_t v ) - { - os << "std::uint64_t: " << v << '\n'; - } - - void number( const double v ) - { - os << "double: "; - if( !std::isfinite( v ) ) { - os << v; - } - else { - ryu::d2s_stream( os, v ); - } - os << '\n'; - } - - void string( const std::string_view v ) - { - os << "string: \""; - internal::escape( os, v ); - os << "\"\n"; - } - - void binary( const tao::binary_view v ) - { - os << "binary: "; - internal::hexdump( os, v ); - os << '\n'; - } - - void begin_array() - { - os << "begin array\n"; - } - - void begin_array( const std::size_t size ) - { - os << "begin array " << size << '\n'; - } - - void element() - { - os << "element\n"; - } - - void end_array() - { - os << "end array\n"; - } - - void end_array( const std::size_t size ) - { - os << "end array " << size << '\n'; - } - - void begin_object() - { - os << "begin object\n"; - } - - void begin_object( const std::size_t size ) - { - os << "begin object " << size << '\n'; - } - - void key( const std::string_view v ) - { - os << "key: \""; - internal::escape( os, v ); - os << "\"\n"; - } - - void member() - { - os << "member\n"; - } - - void end_object() - { - os << "end object\n"; - } - - void end_object( const std::size_t size ) - { - os << "end object " << size << '\n'; - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/discard.hpp b/include/tao/json/events/discard.hpp deleted file mode 100644 index ffe6a39b..00000000 --- a/include/tao/json/events/discard.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_DISCARD_HPP -#define TAO_JSON_EVENTS_DISCARD_HPP - -#include -#include -#include - -#include "../binary_view.hpp" - -namespace tao::json::events -{ - // Events consumer that discards events. - - struct discard - { - void null() noexcept {} - - void boolean( const bool /*unused*/ ) noexcept {} - - void number( const std::int64_t /*unused*/ ) noexcept {} - void number( const std::uint64_t /*unused*/ ) noexcept {} - void number( const double /*unused*/ ) noexcept {} - - void string( const std::string_view /*unused*/ ) noexcept {} - - void binary( const tao::binary_view /*unused*/ ) noexcept {} - - void begin_array( const std::size_t /*unused*/ = 0 ) noexcept {} - void element() noexcept {} - void end_array( const std::size_t /*unused*/ = 0 ) noexcept {} - - void begin_object( const std::size_t /*unused*/ = 0 ) noexcept {} - void key( const std::string_view /*unused*/ ) noexcept {} - void member() noexcept {} - void end_object( const std::size_t /*unused*/ = 0 ) noexcept {} - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/from_file.hpp b/include/tao/json/events/from_file.hpp deleted file mode 100644 index c94024fd..00000000 --- a/include/tao/json/events/from_file.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_FROM_FILE_HPP -#define TAO_JSON_EVENTS_FROM_FILE_HPP - -#include - -#include "../internal/action.hpp" -#include "../internal/errors.hpp" -#include "../internal/grammar.hpp" - -#include "../external/pegtl/file_input.hpp" - -namespace tao::json::events -{ - // Events producer to parse a file containing a JSON string representation. - - template< typename T, typename Consumer > - void from_file( Consumer& consumer, T&& filename ) - { - pegtl::file_input< pegtl::tracking_mode::lazy > in( std::forward< T >( filename ) ); - pegtl::parse< internal::grammar, internal::action, internal::errors >( in, consumer ); - } - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/from_input.hpp b/include/tao/json/events/from_input.hpp deleted file mode 100644 index 0845db92..00000000 --- a/include/tao/json/events/from_input.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_FROM_INPUT_HPP -#define TAO_JSON_EVENTS_FROM_INPUT_HPP - -#include - -#include "../external/pegtl/parse.hpp" - -#include "../internal/action.hpp" -#include "../internal/errors.hpp" -#include "../internal/grammar.hpp" - -namespace tao::json::events -{ - // Events producers that parse a JSON string representation from a PEGTL input (or something compatible). - - template< typename Consumer, typename Input > - void from_input( Consumer& consumer, Input&& in ) - { - pegtl::parse< internal::grammar, internal::action, internal::errors >( std::forward< Input >( in ), consumer ); - } - - template< typename Consumer, typename Input > - void from_input_embedded( Consumer& consumer, Input&& in ) - { - pegtl::parse< internal::embedded, internal::action, internal::errors >( std::forward< Input >( in ), consumer ); - } - - template< typename Consumer, typename Outer, typename Input > - void from_input_nested( Consumer& consumer, const Outer& oi, Input&& in ) - { - pegtl::parse_nested< internal::grammar, internal::action, internal::errors >( oi, std::forward< Input >( in ), consumer ); - } - - template< typename Consumer, typename Outer, typename Input > - void from_input_embedded_nested( Consumer& consumer, const Outer& oi, Input&& in ) - { - pegtl::parse_nested< internal::embedded, internal::action, internal::errors >( oi, std::forward< Input >( in ), consumer ); - } - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/from_stream.hpp b/include/tao/json/events/from_stream.hpp deleted file mode 100644 index 5c6a03ef..00000000 --- a/include/tao/json/events/from_stream.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_FROM_STREAM_HPP -#define TAO_JSON_EVENTS_FROM_STREAM_HPP - -#include - -#include "../external/pegtl/internal/istream_reader.hpp" -#include "../external/pegtl/parse.hpp" - -#include "../internal/action.hpp" -#include "../internal/errors.hpp" -#include "../internal/grammar.hpp" - -namespace tao::json::events -{ - template< typename Consumer > - void from_stream( Consumer& consumer, std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) - { - pegtl::istream_input in( stream, maximum_buffer_size, source ? source : "tao::json::events::from_stream" ); - pegtl::parse< internal::grammar, internal::action, internal::errors >( in, consumer ); - } - - template< typename Consumer > - void from_stream( Consumer& consumer, std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) - { - events::from_stream( consumer, stream, source.c_str(), maximum_buffer_size ); - } - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/from_string.hpp b/include/tao/json/events/from_string.hpp deleted file mode 100644 index 5710d795..00000000 --- a/include/tao/json/events/from_string.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_FROM_STRING_HPP -#define TAO_JSON_EVENTS_FROM_STRING_HPP - -#include - -#include "../external/pegtl/memory_input.hpp" - -#include "from_input.hpp" - -namespace tao::json::events -{ - // Events producer to parse a JSON string representation. - - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) - { - pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::events::from_string", byte, line, column ); - json::events::from_input( consumer, std::move( in ) ); - } - - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) - { - events::from_string( consumer, data, size, source.c_str(), byte, line, column ); - } - - template< typename Consumer, typename... Ts > - void from_string( Consumer& consumer, const std::string_view data, Ts&&... ts ) - { - events::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); - } - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/from_value.hpp b/include/tao/json/events/from_value.hpp deleted file mode 100644 index aa4124f9..00000000 --- a/include/tao/json/events/from_value.hpp +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_FROM_VALUE_HPP -#define TAO_JSON_EVENTS_FROM_VALUE_HPP - -#include - -#include "../basic_value.hpp" -#include "../internal/format.hpp" - -#include "virtual_ref.hpp" - -namespace tao::json::events -{ - // Events producer to generate events from a JSON Value. - - template< auto Recurse, typename Consumer, template< typename... > class Traits > - void from_value( Consumer& consumer, const basic_value< Traits >& v ) - { - switch( v.type() ) { - case type::UNINITIALIZED: - throw std::logic_error( "unable to produce events from uninitialized values" ); - - case type::NULL_: - consumer.null(); - return; - - case type::BOOLEAN: - consumer.boolean( v.get_boolean() ); - return; - - case type::SIGNED: - consumer.number( v.get_signed() ); - return; - - case type::UNSIGNED: - consumer.number( v.get_unsigned() ); - return; - - case type::DOUBLE: - consumer.number( v.get_double() ); - return; - - case type::STRING: - consumer.string( v.get_string() ); - return; - - case type::STRING_VIEW: - consumer.string( v.get_string_view() ); - return; - - case type::BINARY: - consumer.binary( v.get_binary() ); - return; - - case type::BINARY_VIEW: - consumer.binary( v.get_binary_view() ); - return; - - case type::ARRAY: { - const auto& a = v.get_array(); - const auto s = a.size(); - consumer.begin_array( s ); - for( const auto& e : a ) { - Recurse( consumer, e ); - consumer.element(); - } - consumer.end_array( s ); - return; - } - - case type::OBJECT: { - const auto& o = v.get_object(); - const auto s = o.size(); - consumer.begin_object( s ); - for( const auto& e : o ) { - consumer.key( e.first ); - Recurse( consumer, e.second ); - consumer.member(); - } - consumer.end_object( s ); - return; - } - - case type::VALUE_PTR: - Recurse( consumer, *v.get_value_ptr() ); - return; - - case type::OPAQUE_PTR: { - const auto& q = v.get_opaque_ptr(); - virtual_ref< Consumer > ref( consumer ); - q.producer( ref, q.data ); - return; - } - - case type::VALUELESS_BY_EXCEPTION: - throw std::logic_error( "unable to produce events from valueless-by-exception value" ); - } - throw std::logic_error( internal::format( "invalid value '", static_cast< std::uint8_t >( v.type() ), "' for tao::json::type" ) ); // LCOV_EXCL_LINE - } - - template< typename Consumer, template< typename... > class Traits > - void from_value( Consumer& consumer, const basic_value< Traits >& v ) - { - from_value< static_cast< void ( * )( Consumer&, const basic_value< Traits >& ) >( &from_value< Consumer, Traits > ), Consumer, Traits >( consumer, v ); - } - - // Events producer to generate events from an rvalue JSON value. - // Note: Strings from the source might be moved to the consumer. - - template< auto Recurse, typename Consumer, template< typename... > class Traits > - void from_value( Consumer& consumer, basic_value< Traits >&& v ) - { - switch( v.type() ) { - case type::UNINITIALIZED: - throw std::logic_error( "unable to produce events from uninitialized values" ); - - case type::NULL_: - consumer.null(); - return; - - case type::BOOLEAN: - consumer.boolean( v.get_boolean() ); - return; - - case type::SIGNED: - consumer.number( v.get_signed() ); - return; - - case type::UNSIGNED: - consumer.number( v.get_unsigned() ); - return; - - case type::DOUBLE: - consumer.number( v.get_double() ); - return; - - case type::STRING: - consumer.string( std::move( v.get_string() ) ); - return; - - case type::STRING_VIEW: - consumer.string( v.get_string_view() ); - return; - - case type::BINARY: - consumer.binary( std::move( v.get_binary() ) ); - return; - - case type::BINARY_VIEW: - consumer.binary( v.get_binary_view() ); - return; - - case type::ARRAY: { - const auto& a = v.get_array(); - const auto s = a.size(); - consumer.begin_array( s ); - for( auto&& e : a ) { - Recurse( consumer, std::move( e ) ); - consumer.element(); - } - consumer.end_array( s ); - return; - } - - case type::OBJECT: { - const auto& o = v.get_object(); - const auto s = o.size(); - consumer.begin_object( s ); - for( auto&& e : o ) { - consumer.key( e.first ); - Recurse( consumer, std::move( e.second ) ); - consumer.member(); - } - consumer.end_object( s ); - return; - } - - case type::VALUE_PTR: - Recurse( consumer, *v.get_value_ptr() ); - return; - - case type::OPAQUE_PTR: { - const auto& q = v.get_opaque_ptr(); - virtual_ref< Consumer > ref( consumer ); - q.producer( ref, q.data ); - return; - } - } - throw std::logic_error( internal::format( "invalid value '", static_cast< std::uint8_t >( v.type() ), "' for tao::json::type" ) ); // LCOV_EXCL_LINE - } - - template< typename Consumer, template< typename... > class Traits > - void from_value( Consumer& consumer, basic_value< Traits >&& v ) - { - from_value< static_cast< void ( * )( Consumer&, basic_value< Traits > && ) >( &from_value< Consumer, Traits > ), Consumer, Traits >( consumer, std::move( v ) ); - } - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/hash.hpp b/include/tao/json/events/hash.hpp deleted file mode 100644 index e0d2e7ea..00000000 --- a/include/tao/json/events/hash.hpp +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_HASH_HPP -#define TAO_JSON_EVENTS_HASH_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../binary_view.hpp" - -#include "../internal/sha256.hpp" - -namespace tao::json::events -{ - // Events consumer that calculates an SHA-256 hash. - - class hash - { - private: - std::vector< std::unique_ptr< internal::sha256 > > m_digests; - std::vector< std::string > m_keys; - std::vector< std::map< std::string, std::string > > m_properties; - - void push() - { - m_digests.push_back( std::make_unique< internal::sha256 >() ); - } - - public: - hash() - { - push(); - } - - hash( const hash& ) = delete; - hash( hash&& ) = delete; - - ~hash() = default; - - void operator=( const hash& ) = delete; - void operator=( hash&& ) = delete; - - [[nodiscard]] std::string value() const - { - return m_digests.back()->get(); - } - - void reset() - { - m_digests.back()->reset(); - } - - void null() - { - m_digests.back()->feed( 'n' ); - } - - void boolean( const bool v ) - { - m_digests.back()->feed( v ? 't' : 'f' ); - } - - void number( const std::int64_t v ) - { - if( v >= 0 ) { - number( static_cast< std::uint64_t >( v ) ); - } - else { - m_digests.back()->feed( 'i' ); - m_digests.back()->feed( &v, sizeof( v ) ); - } - } - - void number( const std::uint64_t v ) - { - m_digests.back()->feed( 'u' ); - m_digests.back()->feed( &v, sizeof( v ) ); - } - - void number( const double v ) - { - if( v >= 0 ) { - const auto u = static_cast< std::uint64_t >( v ); - if( u == v ) { - number( u ); - return; - } - } - else { - const auto i = static_cast< std::int64_t >( v ); - if( i == v ) { - number( i ); - return; - } - } - m_digests.back()->feed( 'd' ); - m_digests.back()->feed( &v, sizeof( v ) ); - } - - void string( const std::string_view v ) - { - m_digests.back()->feed( 's' ); - const auto s = v.size(); - m_digests.back()->feed( &s, sizeof( s ) ); - m_digests.back()->feed( v ); - } - - void binary( const tao::binary_view v ) - { - m_digests.back()->feed( 'x' ); - const auto s = v.size(); - m_digests.back()->feed( &s, sizeof( s ) ); - m_digests.back()->feed( v.data(), v.size() ); - } - - void begin_array( const std::size_t /*unused*/ = 0 ) - { - m_digests.back()->feed( '[' ); - } - - void element() - {} - - void end_array( const std::size_t /*unused*/ = 0 ) - { - m_digests.back()->feed( ']' ); - } - - void begin_object( const std::size_t /*unused*/ = 0 ) - { - m_digests.back()->feed( '{' ); - m_properties.emplace_back(); - push(); - } - - void key( const std::string_view v ) - { - m_digests.back()->feed( v ); - m_keys.emplace_back( m_digests.back()->get() ); - if( m_properties.back().count( m_keys.back() ) != 0 ) { - throw std::runtime_error( "duplicate JSON object key: " + std::string( v ) ); - } - m_digests.back()->reset(); - } - - void member() - { - m_properties.back().emplace( std::move( m_keys.back() ), m_digests.back()->get() ); - m_keys.pop_back(); - m_digests.back()->reset(); - } - - void end_object( const std::size_t /*unused*/ = 0 ) - { - m_digests.pop_back(); - for( const auto& e : m_properties.back() ) { - m_digests.back()->feed( e.first ); - m_digests.back()->feed( e.second ); - } - m_properties.pop_back(); - m_digests.back()->feed( '}' ); - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/invalid_string_to_binary.hpp b/include/tao/json/events/invalid_string_to_binary.hpp deleted file mode 100644 index a0636bc0..00000000 --- a/include/tao/json/events/invalid_string_to_binary.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_INVALID_STRING_TO_BINARY_HPP -#define TAO_JSON_EVENTS_INVALID_STRING_TO_BINARY_HPP - -#include -#include - -#include "../binary_view.hpp" -#include "../utf8.hpp" - -namespace tao::json::events -{ - template< typename Consumer > - struct invalid_string_to_binary - : Consumer - { - using Consumer::Consumer; - - void string( const char* v ) - { - string( std::string_view( v ) ); - } - - void string( std::string&& v ) - { - if( internal::validate_utf8_nothrow( v ) ) { - Consumer::string( std::move( v ) ); - } - else { - const std::byte* data = reinterpret_cast< const std::byte* >( v.data() ); - Consumer::binary( std::vector< std::byte >( data, data + v.size() ) ); - } - } - - void string( const std::string_view v ) - { - if( internal::validate_utf8_nothrow( v ) ) { - Consumer::string( v ); - } - else { - Consumer::binary( tao::binary_view( reinterpret_cast< const std::byte* >( v.data() ), v.size() ) ); - } - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/invalid_string_to_exception.hpp b/include/tao/json/events/invalid_string_to_exception.hpp deleted file mode 100644 index aeb2ed18..00000000 --- a/include/tao/json/events/invalid_string_to_exception.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_INVALID_STRING_TO_EXCEPTION_HPP -#define TAO_JSON_EVENTS_INVALID_STRING_TO_EXCEPTION_HPP - -#include -#include - -#include "../internal/hexdump.hpp" -#include "../utf8.hpp" - -namespace tao::json::events -{ - template< typename Consumer > - struct invalid_string_to_exception - : Consumer - { - using Consumer::Consumer; - - void string( const char* v ) - { - string( std::string_view( v ) ); - } - - void string( std::string&& v ) - { - if( internal::validate_utf8_nothrow( v ) ) { - Consumer::string( std::move( v ) ); - } - else { - throw std::runtime_error( "invalid UTF8 string: $" + internal::hexdump( v ) ); - } - } - - void string( const std::string_view v ) - { - if( internal::validate_utf8_nothrow( v ) ) { - Consumer::string( v ); - } - else { - throw std::runtime_error( "invalid UTF8 string: $" + internal::hexdump( v ) ); - } - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/invalid_string_to_hex.hpp b/include/tao/json/events/invalid_string_to_hex.hpp deleted file mode 100644 index 6950e422..00000000 --- a/include/tao/json/events/invalid_string_to_hex.hpp +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_INVALID_STRING_TO_HEX_HPP -#define TAO_JSON_EVENTS_INVALID_STRING_TO_HEX_HPP - -#include - -#include "../internal/hexdump.hpp" -#include "../utf8.hpp" - -namespace tao::json::events -{ - template< typename Consumer > - struct invalid_string_to_hex - : Consumer - { - using Consumer::Consumer; - - void string( const char* v ) - { - string( std::string_view( v ) ); - } - - void string( std::string&& v ) - { - if( internal::validate_utf8_nothrow( v ) ) { - Consumer::string( std::move( v ) ); - } - else { - Consumer::string( internal::hexdump( v ) ); - } - } - - void string( const std::string_view v ) - { - if( internal::validate_utf8_nothrow( v ) ) { - Consumer::string( v ); - } - else { - Consumer::string( internal::hexdump( v ) ); - } - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/key_camel_case_to_snake_case.hpp b/include/tao/json/events/key_camel_case_to_snake_case.hpp deleted file mode 100644 index b7e78d4c..00000000 --- a/include/tao/json/events/key_camel_case_to_snake_case.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_KEY_CAMEL_CASE_TO_SNAKE_CASE_HPP -#define TAO_JSON_EVENTS_KEY_CAMEL_CASE_TO_SNAKE_CASE_HPP - -#include -#include -#include - -namespace tao::json::events -{ - template< typename Consumer > - struct key_camel_case_to_snake_case - : Consumer - { - using Consumer::Consumer; - - void key( const std::string_view v ) - { - std::string t; - bool last_upper = false; - for( const auto c : v ) { - if( std::isupper( c ) ) { - last_upper = true; - t += c; - } - else { - if( last_upper ) { - const char o = t.back(); - t.pop_back(); - if( !t.empty() && t.back() != '_' ) { - t += '_'; - } - t += o; - } - last_upper = false; - t += c; - } - } - std::string r; - bool last_lower = false; - for( const auto c : t ) { - if( std::isupper( c ) ) { - if( last_lower ) { - r += '_'; - } - last_lower = false; - r += static_cast< char >( std::tolower( c ) ); - } - else { - last_lower = static_cast< bool >( std::islower( c ) ); - r += c; - } - } - Consumer::key( std::move( r ) ); - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/key_snake_case_to_camel_case.hpp b/include/tao/json/events/key_snake_case_to_camel_case.hpp deleted file mode 100644 index 4889fbf8..00000000 --- a/include/tao/json/events/key_snake_case_to_camel_case.hpp +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_KEY_SNAKE_CASE_TO_CAMEL_CASE_HPP -#define TAO_JSON_EVENTS_KEY_SNAKE_CASE_TO_CAMEL_CASE_HPP - -#include -#include -#include - -namespace tao::json::events -{ - template< typename Consumer > - struct key_snake_case_to_camel_case - : Consumer - { - using Consumer::Consumer; - - void key( const std::string_view v ) - { - std::string r; - r.reserve( v.size() ); - bool active = false; - for( const auto c : v ) { - if( active ) { - if( c == '_' ) { - r += c; - } - else if( std::isupper( c ) ) { - r += '_'; - r += c; - active = false; - } - else { - r += static_cast< char >( std::toupper( c ) ); - active = false; - } - } - else { - if( c == '_' ) { - active = true; - } - else { - r += c; - } - } - } - if( active ) { - r += '_'; - } - Consumer::key( std::move( r ) ); - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/limit_nesting_depth.hpp b/include/tao/json/events/limit_nesting_depth.hpp deleted file mode 100644 index d3e9c428..00000000 --- a/include/tao/json/events/limit_nesting_depth.hpp +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_LIMIT_NESTING_DEPTH_HPP -#define TAO_JSON_EVENTS_LIMIT_NESTING_DEPTH_HPP - -#include -#include - -#include - -namespace tao::json::events -{ - template< typename Consumer, std::size_t Limit > - class limit_nesting_depth - : public Consumer - { - private: - std::size_t m_depth = 0; - - void count_and_limit() - { - if( ++m_depth > Limit ) { - throw std::runtime_error( "nesting depth limit exceeded" ); - } - } - - public: - using Consumer::Consumer; - - void begin_array() - { - count_and_limit(); - Consumer::begin_array(); - } - - void begin_array( const std::size_t size ) - { - count_and_limit(); - Consumer::begin_array( size ); - } - - void end_array() - { - Consumer::end_array(); - --m_depth; - } - - void end_array( const std::size_t size ) - { - Consumer::end_array( size ); - --m_depth; - } - - void begin_object() - { - count_and_limit(); - Consumer::begin_object(); - } - - void begin_object( const std::size_t size ) - { - count_and_limit(); - Consumer::begin_object( size ); - } - - void end_object() - { - Consumer::end_object(); - --m_depth; - } - - void end_object( const std::size_t size ) - { - Consumer::end_object( size ); - --m_depth; - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/limit_value_count.hpp b/include/tao/json/events/limit_value_count.hpp deleted file mode 100644 index 6c70aaaf..00000000 --- a/include/tao/json/events/limit_value_count.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_LIMIT_VALUE_COUNT_HPP -#define TAO_JSON_EVENTS_LIMIT_VALUE_COUNT_HPP - -#include -#include - -#include - -namespace tao::json::events -{ - template< typename Consumer, std::size_t Limit > - class limit_value_count - : public Consumer - { - private: - std::size_t m_count = 1; // Top-level value is implied. - - void count_and_limit() - { - if( ++m_count > Limit ) { - throw std::runtime_error( "value count limit exceeded" ); - } - } - - public: - using Consumer::Consumer; - - void element() - { - count_and_limit(); - Consumer::element(); - } - - void member() - { - count_and_limit(); - Consumer::member(); - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/non_finite_to_exception.hpp b/include/tao/json/events/non_finite_to_exception.hpp deleted file mode 100644 index a4f48049..00000000 --- a/include/tao/json/events/non_finite_to_exception.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_NON_FINITE_TO_EXCEPTION_HPP -#define TAO_JSON_EVENTS_NON_FINITE_TO_EXCEPTION_HPP - -#include -#include - -namespace tao::json::events -{ - template< typename Consumer > - struct non_finite_to_exception - : Consumer - { - using Consumer::Consumer; - - using Consumer::number; - - void number( const double v ) - { - if( !std::isfinite( v ) ) { - throw std::runtime_error( "invalid non-finite double value" ); - } - Consumer::number( v ); - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/non_finite_to_null.hpp b/include/tao/json/events/non_finite_to_null.hpp deleted file mode 100644 index 1556d1fa..00000000 --- a/include/tao/json/events/non_finite_to_null.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_NON_FINITE_TO_NULL_HPP -#define TAO_JSON_EVENTS_NON_FINITE_TO_NULL_HPP - -#include - -namespace tao::json::events -{ - template< typename Consumer > - struct non_finite_to_null - : Consumer - { - using Consumer::Consumer; - - using Consumer::number; - - void number( const double v ) - { - if( !std::isfinite( v ) ) { - Consumer::null(); - } - else { - Consumer::number( v ); - } - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/non_finite_to_string.hpp b/include/tao/json/events/non_finite_to_string.hpp deleted file mode 100644 index a61855cf..00000000 --- a/include/tao/json/events/non_finite_to_string.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_NON_FINITE_TO_STRING_HPP -#define TAO_JSON_EVENTS_NON_FINITE_TO_STRING_HPP - -#include - -namespace tao::json::events -{ - template< typename Consumer > - struct non_finite_to_string - : Consumer - { - using Consumer::Consumer; - - using Consumer::number; - - void number( const double v ) - { - if( !std::isfinite( v ) ) { - if( std::isnan( v ) ) { - Consumer::string( "NaN" ); - } - else if( v > 0 ) { - Consumer::string( "Infinity" ); - } - else { - Consumer::string( "-Infinity" ); - } - } - else { - Consumer::number( v ); - } - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/prefer_signed.hpp b/include/tao/json/events/prefer_signed.hpp deleted file mode 100644 index 3df0e979..00000000 --- a/include/tao/json/events/prefer_signed.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_PREFER_SIGNED_HPP -#define TAO_JSON_EVENTS_PREFER_SIGNED_HPP - -#include - -namespace tao::json::events -{ - template< typename Consumer > - struct prefer_signed - : Consumer - { - using Consumer::Consumer; - - using Consumer::number; - - void number( const std::uint64_t v ) - { - if( v <= 9223372036854775807ULL ) { - Consumer::number( std::int64_t( v ) ); - } - else { - Consumer::number( v ); - } - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/prefer_unsigned.hpp b/include/tao/json/events/prefer_unsigned.hpp deleted file mode 100644 index 1e082a83..00000000 --- a/include/tao/json/events/prefer_unsigned.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_PREFER_UNSIGNED_HPP -#define TAO_JSON_EVENTS_PREFER_UNSIGNED_HPP - -#include - -namespace tao::json::events -{ - template< typename Consumer > - struct prefer_unsigned - : Consumer - { - using Consumer::Consumer; - - using Consumer::number; - - void number( const std::int64_t v ) - { - if( v >= 0 ) { - Consumer::number( std::uint64_t( v ) ); - } - else { - Consumer::number( v ); - } - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/produce.hpp b/include/tao/json/events/produce.hpp deleted file mode 100644 index 14d0ecf1..00000000 --- a/include/tao/json/events/produce.hpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_PRODUCE_HPP -#define TAO_JSON_EVENTS_PRODUCE_HPP - -#include -#include - -#include "../forward.hpp" - -namespace tao::json::events -{ - template< template< typename... > class Traits = traits, typename Consumer, typename T > - void produce( Consumer& c, T&& t ) - { - Traits< std::decay_t< T > >::template produce< Traits >( c, std::forward< T >( t ) ); - } - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/ref.hpp b/include/tao/json/events/ref.hpp deleted file mode 100644 index 0c4b78d3..00000000 --- a/include/tao/json/events/ref.hpp +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_REF_HPP -#define TAO_JSON_EVENTS_REF_HPP - -#include -#include - -namespace tao::json::events -{ - template< typename Consumer > - class ref - { - private: - Consumer& r_; - - public: - explicit ref( Consumer& r ) noexcept - : r_( r ) - {} - - void null() noexcept( noexcept( r_.null() ) ) - { - r_.null(); - } - - template< typename T > - void boolean( T&& v ) noexcept( noexcept( r_.boolean( std::forward< T >( v ) ) ) ) - { - r_.boolean( std::forward< T >( v ) ); - } - - template< typename T > - void number( T&& v ) noexcept( noexcept( r_.number( std::forward< T >( v ) ) ) ) - { - r_.number( std::forward< T >( v ) ); - } - - template< typename T > - void string( T&& v ) noexcept( noexcept( r_.string( std::forward< T >( v ) ) ) ) - { - r_.string( std::forward< T >( v ) ); - } - - template< typename T > - void binary( T&& v ) noexcept( noexcept( r_.binary( std::forward< T >( v ) ) ) ) - { - r_.binary( std::forward< T >( v ) ); - } - - void begin_array() noexcept( noexcept( r_.begin_array() ) ) - { - r_.begin_array(); - } - - void begin_array( const std::size_t size ) noexcept( noexcept( r_.begin_array( size ) ) ) - { - r_.begin_array( size ); - } - - void element() noexcept( noexcept( r_.element() ) ) - { - r_.element(); - } - - void end_array() noexcept( noexcept( r_.end_array() ) ) - { - r_.end_array(); - } - - void end_array( const std::size_t size ) noexcept( noexcept( r_.end_array( size ) ) ) - { - r_.end_array( size ); - } - - void begin_object() noexcept( noexcept( r_.begin_object() ) ) - { - r_.begin_object(); - } - - void begin_object( const std::size_t size ) noexcept( noexcept( r_.begin_object( size ) ) ) - { - r_.begin_object( size ); - } - - template< typename T > - void key( T&& v ) noexcept( noexcept( r_.key( std::forward< T >( v ) ) ) ) - { - r_.key( std::forward< T >( v ) ); - } - - void member() noexcept( noexcept( r_.member() ) ) - { - r_.member(); - } - - void end_object() noexcept( noexcept( r_.end_object() ) ) - { - r_.end_object(); - } - - void end_object( const std::size_t size ) noexcept( noexcept( r_.end_object( size ) ) ) - { - r_.end_object( size ); - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/statistics.hpp b/include/tao/json/events/statistics.hpp deleted file mode 100644 index 895b2ce6..00000000 --- a/include/tao/json/events/statistics.hpp +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_STATISTICS_HPP -#define TAO_JSON_EVENTS_STATISTICS_HPP - -#include -#include -#include -#include -#include -#include - -#include "../binary_view.hpp" - -namespace tao::json::events -{ - struct statistics - { - std::size_t null_count = 0; - std::size_t true_count = 0; - std::size_t false_count = 0; - - std::size_t signed_count = 0; - std::size_t unsigned_count = 0; - std::size_t double_count = 0; - - std::size_t string_count = 0; - std::size_t string_lengths = 0; - std::size_t key_count = 0; - std::size_t key_lengths = 0; - std::size_t binary_count = 0; - std::size_t binary_lengths = 0; - - std::size_t array_count = 0; - std::size_t array_elements = 0; - std::size_t object_count = 0; - std::size_t object_members = 0; - - void null() noexcept - { - ++null_count; - } - - void boolean( const bool v ) noexcept - { - ++( v ? true_count : false_count ); - } - - void number( const std::int64_t /*unused*/ ) noexcept - { - ++signed_count; - } - - void number( const std::uint64_t /*unused*/ ) noexcept - { - ++unsigned_count; - } - - void number( const double /*unused*/ ) noexcept - { - ++double_count; - } - - void string( const std::string_view v ) noexcept - { - ++string_count; - string_lengths += v.size(); - } - - void binary( const tao::binary_view v ) noexcept - { - ++binary_count; - binary_lengths += v.size(); - } - - void begin_array( const std::size_t /*unused*/ = 0 ) noexcept - { - ++array_count; - } - - void element() noexcept - { - ++array_elements; - } - - void end_array( const std::size_t /*unused*/ = 0 ) noexcept - {} - - void begin_object( const std::size_t /*unused*/ = 0 ) noexcept - { - ++object_count; - } - - void key( const std::string_view v ) noexcept - { - ++key_count; - key_lengths += v.size(); - } - - void member() noexcept - { - ++object_members; - } - - void end_object( const std::size_t /*unused*/ = 0 ) noexcept - {} - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/tee.hpp b/include/tao/json/events/tee.hpp deleted file mode 100644 index b1cd1f93..00000000 --- a/include/tao/json/events/tee.hpp +++ /dev/null @@ -1,386 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_TEE_HPP -#define TAO_JSON_EVENTS_TEE_HPP - -#include -#include -#include -#include -#include -#include - -#include "discard.hpp" - -namespace tao::json -{ - namespace internal - { - template< typename T > - struct strip_reference_wrapper - { - using type = T; - }; - - template< typename T > - struct strip_reference_wrapper< std::reference_wrapper< T > > - { - using type = T&; - }; - - template< typename T > - using decay_and_strip_t = typename strip_reference_wrapper< std::decay_t< T > >::type; - - template< typename > - struct events_apply; - - template<> - struct events_apply< std::index_sequence<> > - { - template< typename... Ts > - static void null( std::tuple< Ts... >& /*unused*/ ) - {} - - template< typename... Ts > - static void boolean( std::tuple< Ts... >& /*unused*/, const bool /*unused*/ ) - {} - - template< typename... Ts > - static void number( std::tuple< Ts... >& /*unused*/, const std::int64_t /*unused*/ ) - {} - - template< typename... Ts > - static void number( std::tuple< Ts... >& /*unused*/, const std::uint64_t /*unused*/ ) - {} - - template< typename... Ts > - static void number( std::tuple< Ts... >& /*unused*/, const double /*unused*/ ) - {} - - template< typename... Ts > - static void string( std::tuple< Ts... >& /*unused*/, const std::string_view /*unused*/ ) - {} - - template< typename... Ts > - static void binary( std::tuple< Ts... >& /*unused*/, const tao::binary_view /*unused*/ ) - {} - - template< typename... Ts > - static void begin_array( std::tuple< Ts... >& /*unused*/ ) - {} - - template< typename... Ts > - static void begin_array( std::tuple< Ts... >& /*unused*/, const std::size_t /*unused*/ ) - {} - - template< typename... Ts > - static void element( std::tuple< Ts... >& /*unused*/ ) - {} - - template< typename... Ts > - static void end_array( std::tuple< Ts... >& /*unused*/ ) - {} - - template< typename... Ts > - static void end_array( std::tuple< Ts... >& /*unused*/, const std::size_t /*unused*/ ) - {} - - template< typename... Ts > - static void begin_object( std::tuple< Ts... >& /*unused*/ ) - {} - - template< typename... Ts > - static void begin_object( std::tuple< Ts... >& /*unused*/, const std::size_t /*unused*/ ) - {} - - template< typename... Ts > - static void key( std::tuple< Ts... >& /*unused*/, const std::string_view /*unused*/ ) - {} - - template< typename... Ts > - static void member( std::tuple< Ts... >& /*unused*/ ) - {} - - template< typename... Ts > - static void end_object( std::tuple< Ts... >& /*unused*/ ) - {} - - template< typename... Ts > - static void end_object( std::tuple< Ts... >& /*unused*/, const std::size_t /*unused*/ ) - {} - }; - - template< std::size_t... Is > - struct events_apply< std::index_sequence< Is... > > - { - template< typename... Ts > - static void null( std::tuple< Ts... >& t ) - { - ( std::get< Is >( t ).null(), ... ); - } - - template< typename... Ts > - static void boolean( std::tuple< Ts... >& t, const bool v ) - { - ( std::get< Is >( t ).boolean( v ), ... ); - } - - template< typename... Ts > - static void number( std::tuple< Ts... >& t, const std::int64_t v ) - { - ( std::get< Is >( t ).number( v ), ... ); - } - - template< typename... Ts > - static void number( std::tuple< Ts... >& t, const std::uint64_t v ) - { - ( std::get< Is >( t ).number( v ), ... ); - } - - template< typename... Ts > - static void number( std::tuple< Ts... >& t, const double v ) - { - ( std::get< Is >( t ).number( v ), ... ); - } - - template< typename... Ts > - static void string( std::tuple< Ts... >& t, const std::string_view v ) - { - ( std::get< Is >( t ).string( v ), ... ); - } - - template< typename... Ts > - static void binary( std::tuple< Ts... >& t, const tao::binary_view v ) - { - ( std::get< Is >( t ).binary( v ), ... ); - } - - template< typename... Ts > - static void begin_array( std::tuple< Ts... >& t ) - { - ( std::get< Is >( t ).begin_array(), ... ); - } - - template< typename... Ts > - static void begin_array( std::tuple< Ts... >& t, const std::size_t size ) - { - ( std::get< Is >( t ).begin_array( size ), ... ); - } - - template< typename... Ts > - static void element( std::tuple< Ts... >& t ) - { - ( std::get< Is >( t ).element(), ... ); - } - - template< typename... Ts > - static void end_array( std::tuple< Ts... >& t ) - { - ( std::get< Is >( t ).end_array(), ... ); - } - - template< typename... Ts > - static void end_array( std::tuple< Ts... >& t, const std::size_t size ) - { - ( std::get< Is >( t ).end_array( size ), ... ); - } - - template< typename... Ts > - static void begin_object( std::tuple< Ts... >& t ) - { - ( std::get< Is >( t ).begin_object(), ... ); - } - - template< typename... Ts > - static void begin_object( std::tuple< Ts... >& t, const std::size_t size ) - { - ( std::get< Is >( t ).begin_object( size ), ... ); - } - - template< typename... Ts > - static void key( std::tuple< Ts... >& t, const std::string_view v ) - { - ( std::get< Is >( t ).key( v ), ... ); - } - - template< typename... Ts > - static void member( std::tuple< Ts... >& t ) - { - ( std::get< Is >( t ).member(), ... ); - } - - template< typename... Ts > - static void end_object( std::tuple< Ts... >& t ) - { - ( std::get< Is >( t ).end_object(), ... ); - } - - template< typename... Ts > - static void end_object( std::tuple< Ts... >& t, const std::size_t size ) - { - ( std::get< Is >( t ).end_object( size ), ... ); - } - }; - - } // namespace internal - - namespace events - { - // Events consumer that forwards to multiple nested consumers. - - template< typename... Ts > - class tee - { - private: - static constexpr std::size_t S = sizeof...( Ts ); - - using I = std::make_index_sequence< S >; - using H = std::make_index_sequence< S - 1 >; - - std::tuple< Ts... > ts; - - public: - template< typename... Us > - explicit tee( Us&&... us ) - : ts( std::forward< Us >( us )... ) - {} - - void null() - { - internal::events_apply< I >::null( ts ); - } - - void boolean( const bool v ) - { - internal::events_apply< I >::boolean( ts, v ); - } - - void number( const std::int64_t v ) - { - internal::events_apply< I >::number( ts, v ); - } - - void number( const std::uint64_t v ) - { - internal::events_apply< I >::number( ts, v ); - } - - void number( const double v ) - { - internal::events_apply< I >::number( ts, v ); - } - - void string( const std::string_view v ) - { - internal::events_apply< I >::string( ts, v ); - } - - void string( const char* v ) - { - internal::events_apply< I >::string( ts, v ); - } - - void string( std::string&& v ) - { - internal::events_apply< H >::string( ts, v ); - std::get< S - 1 >( ts ).string( std::move( v ) ); - } - - void binary( const tao::binary_view v ) - { - internal::events_apply< I >::binary( ts, v ); - } - - void binary( std::vector< std::byte >&& v ) - { - internal::events_apply< H >::binary( ts, v ); - std::get< S - 1 >( ts ).binary( std::move( v ) ); - } - - void begin_array() - { - internal::events_apply< I >::begin_array( ts ); - } - - void begin_array( const std::size_t size ) - { - internal::events_apply< I >::begin_array( ts, size ); - } - - void element() - { - internal::events_apply< I >::element( ts ); - } - - void end_array() - { - internal::events_apply< I >::end_array( ts ); - } - - void end_array( const std::size_t size ) - { - internal::events_apply< I >::end_array( ts, size ); - } - - void begin_object() - { - internal::events_apply< I >::begin_object( ts ); - } - - void begin_object( const std::size_t size ) - { - internal::events_apply< I >::begin_object( ts, size ); - } - - void key( const std::string_view v ) - { - internal::events_apply< I >::key( ts, v ); - } - - void key( const char* v ) - { - internal::events_apply< I >::key( ts, v ); - } - - void key( std::string&& v ) - { - internal::events_apply< H >::key( ts, v ); - std::get< S - 1 >( ts ).key( std::move( v ) ); - } - - void member() - { - internal::events_apply< I >::member( ts ); - } - - void end_object() - { - internal::events_apply< I >::end_object( ts ); - } - - void end_object( const std::size_t size ) - { - internal::events_apply< I >::end_object( ts, size ); - } - }; - - template<> - class tee<> - : public discard - {}; - - template< typename... Ts > - tee( Ts&&... )->tee< internal::decay_and_strip_t< Ts >... >; - - template< typename... T > - [[nodiscard]] tee< T&... > tie( T&... t ) - { - return tee< T&... >( t... ); - } - - } // namespace events - -} // namespace tao::json - -#endif diff --git a/include/tao/json/events/to_pretty_stream.hpp b/include/tao/json/events/to_pretty_stream.hpp deleted file mode 100644 index 9e7b5698..00000000 --- a/include/tao/json/events/to_pretty_stream.hpp +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_TO_PRETTY_STREAM_HPP -#define TAO_JSON_EVENTS_TO_PRETTY_STREAM_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../binary_view.hpp" - -#include "../external/itoa.hpp" -#include "../external/ryu.hpp" - -#include "../internal/escape.hpp" - -namespace tao::json::events -{ - // Events consumer to build a JSON pretty string representation. - - class to_pretty_stream - { - protected: - std::ostream& os; - const std::size_t indent; - std::string eol; - - bool first = true; - bool after_key = true; - - void next() - { - if( !first ) { - os.put( ',' ); - } - if( after_key ) { - after_key = false; - } - else { - os << eol; - } - } - - public: - template< typename S > - to_pretty_stream( std::ostream& in_os, const std::size_t in_indent, S&& in_eol ) - : os( in_os ), - indent( in_indent ), - eol( std::forward< S >( in_eol ) ) - {} - - to_pretty_stream( std::ostream& in_os, const std::size_t in_indent ) - : to_pretty_stream( in_os, in_indent, "\n" ) - {} - - void null() - { - next(); - os.write( "null", 4 ); - } - - void boolean( const bool v ) - { - next(); - if( v ) { - os.write( "true", 4 ); - } - else { - os.write( "false", 5 ); - } - } - - void number( const std::int64_t v ) - { - next(); - itoa::i64tos( os, v ); - } - - void number( const std::uint64_t v ) - { - next(); - itoa::u64tos( os, v ); - } - - void number( const double v ) - { - next(); - if( !std::isfinite( v ) ) { - // if this throws, consider using non_finite_to_* transformers - throw std::runtime_error( "non-finite double value invalid for JSON string representation" ); - } - ryu::d2s_stream( os, v ); - } - - void string( const std::string_view v ) - { - next(); - os.put( '"' ); - internal::escape( os, v ); - os.put( '"' ); - } - - void binary( const tao::binary_view /*unused*/ ) - { - // if this throws, consider using binary_to_* transformers - throw std::runtime_error( "binary data invalid for JSON string representation" ); - } - - void begin_array( const std::size_t /*unused*/ = 0 ) - { - next(); - os.put( '[' ); - eol.resize( eol.size() + indent, os.fill() ); - first = true; - } - - void element() noexcept - { - first = false; - } - - void end_array( const std::size_t /*unused*/ = 0 ) - { - eol.resize( eol.size() - indent ); - if( !first ) { - os << eol; - } - os.put( ']' ); - } - - void begin_object( const std::size_t /*unused*/ = 0 ) - { - next(); - os.put( '{' ); - eol.resize( eol.size() + indent, os.fill() ); - first = true; - } - - void key( const std::string_view v ) - { - string( v ); - os.write( ": ", 2 ); - first = true; - after_key = true; - } - - void member() noexcept - { - first = false; - } - - void end_object( const std::size_t /*unused*/ = 0 ) - { - eol.resize( eol.size() - indent ); - if( !first ) { - os << eol; - } - os.put( '}' ); - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/to_stream.hpp b/include/tao/json/events/to_stream.hpp deleted file mode 100644 index a144622e..00000000 --- a/include/tao/json/events/to_stream.hpp +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_TO_STREAM_HPP -#define TAO_JSON_EVENTS_TO_STREAM_HPP - -#include -#include -#include -#include -#include -#include -#include - -#include "../binary_view.hpp" - -#include "../external/itoa.hpp" -#include "../external/ryu.hpp" - -#include "../internal/escape.hpp" - -namespace tao::json::events -{ - // Events consumer to build a JSON string representation. - - class to_stream - { - protected: - std::ostream& os; - bool first; - - void next() - { - if( !first ) { - os.put( ',' ); - } - } - - public: - explicit to_stream( std::ostream& in_os ) noexcept - : os( in_os ), - first( true ) - {} - - void null() - { - next(); - os.write( "null", 4 ); - } - - void boolean( const bool v ) - { - next(); - if( v ) { - os.write( "true", 4 ); - } - else { - os.write( "false", 5 ); - } - } - - void number( const std::int64_t v ) - { - next(); - itoa::i64tos( os, v ); - } - - void number( const std::uint64_t v ) - { - next(); - itoa::u64tos( os, v ); - } - - void number( const double v ) - { - next(); - if( !std::isfinite( v ) ) { - // if this throws, consider using non_finite_to_* transformers - throw std::runtime_error( "non-finite double value invalid for JSON string representation" ); - } - ryu::d2s_stream( os, v ); - } - - void string( const std::string_view v ) - { - next(); - os.put( '"' ); - internal::escape( os, v ); - os.put( '"' ); - } - - void binary( const tao::binary_view /*unused*/ ) - { - // if this throws, consider using binary_to_* transformers - throw std::runtime_error( "binary data invalid for JSON string representation" ); - } - - void begin_array( const std::size_t /*unused*/ = 0 ) - { - next(); - os.put( '[' ); - first = true; - } - - void element() noexcept - { - first = false; - } - - void end_array( const std::size_t /*unused*/ = 0 ) - { - os.put( ']' ); - } - - void begin_object( const std::size_t /*unused*/ = 0 ) - { - next(); - os.put( '{' ); - first = true; - } - - void key( const std::string_view v ) - { - string( v ); - os.put( ':' ); - first = true; - } - - void member() noexcept - { - first = false; - } - - void end_object( const std::size_t /*unused*/ = 0 ) - { - os.put( '}' ); - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/to_string.hpp b/include/tao/json/events/to_string.hpp deleted file mode 100644 index 972f09f3..00000000 --- a/include/tao/json/events/to_string.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_TO_STRING_HPP -#define TAO_JSON_EVENTS_TO_STRING_HPP - -#include -#include - -#include "to_stream.hpp" - -namespace tao::json::events -{ - // Events consumer to build a JSON string representation. - - struct to_string - : to_stream - { - std::ostringstream oss; - - to_string() - : to_stream( oss ) - {} - - [[nodiscard]] std::string value() const - { - return oss.str(); - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/to_value.hpp b/include/tao/json/events/to_value.hpp deleted file mode 100644 index 4d47d555..00000000 --- a/include/tao/json/events/to_value.hpp +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_TO_VALUE_HPP -#define TAO_JSON_EVENTS_TO_VALUE_HPP - -#include -#include -#include -#include -#include -#include - -#include "../binary_view.hpp" -#include "../value.hpp" - -namespace tao::json::events -{ - // Events consumer to build a JSON Value. - - template< template< typename... > class Traits > - struct to_basic_value - { - std::vector< basic_value< Traits > > stack_; - std::vector< std::string > keys_; - basic_value< Traits > value; - - void null() - { - value.set_null(); - } - - void boolean( const bool v ) - { - value.set_boolean( v ); - } - - void number( const std::int64_t v ) - { - value.set_signed( v ); - } - - void number( const std::uint64_t v ) - { - value.set_unsigned( v ); - } - - void number( const double v ) - { - value.set_double( v ); - } - - void string( const std::string_view v ) - { - value.emplace_string( v ); - } - - void string( const char* v ) - { - value.emplace_string( v ); - } - - void string( std::string&& v ) - { - value.emplace_string( std::move( v ) ); - } - - void binary( const tao::binary_view v ) - { - value.emplace_binary( v.begin(), v.end() ); - } - - void binary( std::vector< std::byte >&& v ) - { - value.emplace_binary( std::move( v ) ); - } - - void begin_array() - { - stack_.emplace_back( empty_array ); - } - - void begin_array( const std::size_t size ) - { - begin_array(); - stack_.back().get_array().reserve( size ); - } - - void element() - { - stack_.back().emplace_back( std::move( value ) ); - } - - void end_array( const std::size_t /*unused*/ = 0 ) - { - value = std::move( stack_.back() ); - stack_.pop_back(); - } - - void begin_object( const std::size_t /*unused*/ = 0 ) - { - stack_.emplace_back( empty_object ); - } - - void key( const std::string_view v ) - { - keys_.emplace_back( v ); - } - - void key( const char* v ) - { - keys_.emplace_back( v ); - } - - void key( std::string&& v ) - { - keys_.emplace_back( std::move( v ) ); - } - - void member() - { - stack_.back().try_emplace( std::move( keys_.back() ), std::move( value ) ); - keys_.pop_back(); - } - - void end_object( const std::size_t /*unused*/ = 0 ) - { - value = std::move( stack_.back() ); - stack_.pop_back(); - } - }; - - using to_value = to_basic_value< traits >; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/transformer.hpp b/include/tao/json/events/transformer.hpp deleted file mode 100644 index 564a3896..00000000 --- a/include/tao/json/events/transformer.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_TRANSFORMER_HPP -#define TAO_JSON_EVENTS_TRANSFORMER_HPP - -#include - -#include "../external/pegtl/internal/always_false.hpp" - -namespace tao::json -{ - namespace internal - { - template< template< typename... > class T > - struct invalid_transformer - { - // if this static assert is triggered there is a high chance that 'T' is - // a traits class template and you intended to call a method starting with "basic_*", - // e.g. basic_from_file< my_traits >( ... ) instead of from_file< my_traits >( ... ). - static_assert( pegtl::internal::always_false< invalid_transformer< T > >::value, "T is not a valid transformer" ); - }; - - template< typename B, template< typename... > class T, typename = void > - struct check_transformer - : invalid_transformer< T > - { - using type = B; - }; - - template< typename B, template< typename... > class T > - struct check_transformer< B, - T, - decltype( std::declval< T< B > >().null(), - std::declval< T< B > >().boolean( true ), - std::declval< T< B > >().number( double( 0.0 ) ), - std::declval< T< B > >().string( "" ), - std::declval< T< B > >().element(), - std::declval< T< B > >().member(), - void() ) > - { - using type = T< B >; - }; - - template< typename Consumer, template< typename... > class... Transformer > - struct transformer; - - template< typename Consumer > - struct transformer< Consumer > - { - using type = Consumer; - }; - - template< typename Consumer, template< typename... > class Head, template< typename... > class... Tail > - struct transformer< Consumer, Head, Tail... > - : check_transformer< typename transformer< Consumer, Tail... >::type, Head > - {}; - - } // namespace internal - - namespace events - { - template< typename Consumer, template< typename... > class... Transformer > - using transformer = typename internal::transformer< Consumer, Transformer... >::type; - - } // namespace events - -} // namespace tao::json - -#endif diff --git a/include/tao/json/events/validate_event_order.hpp b/include/tao/json/events/validate_event_order.hpp deleted file mode 100644 index f4106e13..00000000 --- a/include/tao/json/events/validate_event_order.hpp +++ /dev/null @@ -1,411 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_VALIDATE_EVENT_ORDER_HPP -#define TAO_JSON_EVENTS_VALIDATE_EVENT_ORDER_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../binary_view.hpp" - -namespace tao::json::events -{ - // Events consumer that validates the order of events. - - class validate_event_order - { - private: - enum state_t - { - EXPECT_TOP_LEVEL_VALUE, - EXPECT_ARRAY_VALUE_OR_END, - EXPECT_ARRAY_ELEMENT, - EXPECT_SIZED_ARRAY_VALUE_OR_END, - EXPECT_SIZED_ARRAY_ELEMENT, - EXPECT_OBJECT_KEY_OR_END, - EXPECT_OBJECT_VALUE, - EXPECT_OBJECT_MEMBER, - EXPECT_SIZED_OBJECT_KEY_OR_END, - EXPECT_SIZED_OBJECT_VALUE, - EXPECT_SIZED_OBJECT_MEMBER, - EXPECT_NOTHING - }; - - struct sizes_t - { - explicit sizes_t( const std::size_t in_expected ) - : expected( in_expected ) - {} - - void check( const std::size_t in_expected ) - { - if( expected != in_expected ) { - throw std::logic_error( "inconsistent size" ); - } - if( expected != counted ) { - throw std::logic_error( "wrong size" ); - } - } - - std::size_t expected; - std::size_t counted = 0; - }; - - state_t state = EXPECT_TOP_LEVEL_VALUE; - std::vector< state_t > stack; - std::vector< sizes_t > sizes; - - void atom( const std::string& function ) - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - state = EXPECT_NOTHING; - return; - case EXPECT_ARRAY_VALUE_OR_END: - state = EXPECT_ARRAY_ELEMENT; - return; - case EXPECT_SIZED_ARRAY_VALUE_OR_END: - state = EXPECT_SIZED_ARRAY_ELEMENT; - return; - case EXPECT_ARRAY_ELEMENT: - case EXPECT_SIZED_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but " + function + " was called" ); - case EXPECT_OBJECT_KEY_OR_END: - case EXPECT_SIZED_OBJECT_KEY_OR_END: - throw std::logic_error( "expected key() or end_object(...), but " + function + " was called" ); - case EXPECT_OBJECT_VALUE: - state = EXPECT_OBJECT_MEMBER; - return; - case EXPECT_SIZED_OBJECT_VALUE: - state = EXPECT_SIZED_OBJECT_MEMBER; - return; - case EXPECT_OBJECT_MEMBER: - case EXPECT_SIZED_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but " + function + " was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but " + function + " was called" ); - } - throw std::logic_error( "invalid state" ); - } - - public: - [[nodiscard]] bool is_complete() const noexcept - { - return state == EXPECT_NOTHING; - } - - void null() - { - atom( "null()" ); - } - - void boolean( const bool /*unused*/ ) - { - atom( "boolen()" ); - } - - void number( const std::int64_t /*unused*/ ) - { - atom( "number(std::int64_t)" ); - } - - void number( const std::uint64_t /*unused*/ ) - { - atom( "number(std::uint64_t)" ); - } - - void number( const double /*unused*/ ) - { - atom( "number(double)" ); - } - - void string( const std::string_view /*unused*/ ) - { - atom( "string(...)" ); - } - - void binary( const tao::binary_view /*unused*/ ) - { - atom( "binary(...)" ); - } - - void begin_array() - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - stack.push_back( EXPECT_NOTHING ); - state = EXPECT_ARRAY_VALUE_OR_END; - return; - case EXPECT_ARRAY_VALUE_OR_END: - stack.push_back( EXPECT_ARRAY_ELEMENT ); - return; - case EXPECT_SIZED_ARRAY_VALUE_OR_END: - stack.push_back( EXPECT_SIZED_ARRAY_ELEMENT ); - return; - case EXPECT_ARRAY_ELEMENT: - case EXPECT_SIZED_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but begin_array(...) was called" ); - case EXPECT_OBJECT_KEY_OR_END: - case EXPECT_SIZED_OBJECT_KEY_OR_END: - throw std::logic_error( "expected key() or end_object(...), but begin_array(...) was called" ); - case EXPECT_OBJECT_VALUE: - stack.push_back( EXPECT_OBJECT_MEMBER ); - state = EXPECT_ARRAY_VALUE_OR_END; - return; - case EXPECT_SIZED_OBJECT_VALUE: - stack.push_back( EXPECT_SIZED_OBJECT_MEMBER ); - state = EXPECT_ARRAY_VALUE_OR_END; - return; - case EXPECT_OBJECT_MEMBER: - case EXPECT_SIZED_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but begin_array(...) was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but begin_array(...) was called" ); - } - throw std::logic_error( "invalid state" ); - } - - void begin_array( const std::size_t expected ) - { - begin_array(); - sizes.emplace_back( expected ); - state = EXPECT_SIZED_ARRAY_VALUE_OR_END; - } - - void element() - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - throw std::logic_error( "expected any value, but element() was called" ); - case EXPECT_ARRAY_VALUE_OR_END: - case EXPECT_SIZED_ARRAY_VALUE_OR_END: - throw std::logic_error( "expected any value or end_array(...), but element() was called" ); - case EXPECT_ARRAY_ELEMENT: - state = EXPECT_ARRAY_VALUE_OR_END; - return; - case EXPECT_SIZED_ARRAY_ELEMENT: - state = EXPECT_SIZED_ARRAY_VALUE_OR_END; - ++sizes.back().counted; - return; - case EXPECT_OBJECT_KEY_OR_END: - case EXPECT_SIZED_OBJECT_KEY_OR_END: - throw std::logic_error( "expected key() or end_object(...), but element() was called" ); - case EXPECT_OBJECT_VALUE: - case EXPECT_SIZED_OBJECT_VALUE: - throw std::logic_error( "expected any value, but element() was called" ); - case EXPECT_OBJECT_MEMBER: - case EXPECT_SIZED_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but element() was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but element() was called" ); - } - throw std::logic_error( "invalid state" ); - } - - void end_array() - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - throw std::logic_error( "expected any value, but end_array(....) was called" ); - case EXPECT_ARRAY_VALUE_OR_END: - state = stack.back(); - stack.pop_back(); - return; - case EXPECT_SIZED_ARRAY_VALUE_OR_END: - throw std::logic_error( "expected end_array(std::size_t), but end_array() was called" ); - case EXPECT_ARRAY_ELEMENT: - case EXPECT_SIZED_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but end_array(...) was called" ); - case EXPECT_OBJECT_KEY_OR_END: - case EXPECT_SIZED_OBJECT_KEY_OR_END: - throw std::logic_error( "expected key() or end_object(...), but end_array(...) was called" ); - case EXPECT_OBJECT_VALUE: - case EXPECT_SIZED_OBJECT_VALUE: - throw std::logic_error( "expected any value, but end_array(...) was called" ); - case EXPECT_OBJECT_MEMBER: - case EXPECT_SIZED_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but end_array(...) was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but end_array(...) was called" ); - } - throw std::logic_error( "invalid state" ); - } - - void end_array( const std::size_t expected ) - { - switch( state ) { - case EXPECT_SIZED_ARRAY_VALUE_OR_END: - state = EXPECT_ARRAY_VALUE_OR_END; - break; - case EXPECT_ARRAY_VALUE_OR_END: - throw std::logic_error( "expected any value or end_array(), but end_array(std::size_t) was called" ); - default: - break; - } - assert( sizes.size() ); - sizes.back().check( expected ); - sizes.pop_back(); - end_array(); - } - - void begin_object() - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - stack.push_back( EXPECT_NOTHING ); - state = EXPECT_OBJECT_KEY_OR_END; - return; - case EXPECT_ARRAY_VALUE_OR_END: - stack.push_back( EXPECT_ARRAY_ELEMENT ); - state = EXPECT_OBJECT_KEY_OR_END; - return; - case EXPECT_SIZED_ARRAY_VALUE_OR_END: - stack.push_back( EXPECT_SIZED_ARRAY_ELEMENT ); - state = EXPECT_OBJECT_KEY_OR_END; - return; - case EXPECT_ARRAY_ELEMENT: - case EXPECT_SIZED_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but begin_object(...) was called" ); - case EXPECT_OBJECT_KEY_OR_END: - case EXPECT_SIZED_OBJECT_KEY_OR_END: - throw std::logic_error( "expected key() or end_object(...), but begin_object(...) was called" ); - case EXPECT_OBJECT_VALUE: - stack.push_back( EXPECT_OBJECT_MEMBER ); - state = EXPECT_OBJECT_KEY_OR_END; - return; - case EXPECT_SIZED_OBJECT_VALUE: - stack.push_back( EXPECT_SIZED_OBJECT_MEMBER ); - state = EXPECT_OBJECT_KEY_OR_END; - return; - case EXPECT_OBJECT_MEMBER: - case EXPECT_SIZED_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but begin_object(...) was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but begin_object(...) was called" ); - } - throw std::logic_error( "invalid state" ); - } - - void begin_object( const std::size_t expected ) - { - begin_object(); - sizes.emplace_back( expected ); - state = EXPECT_SIZED_OBJECT_KEY_OR_END; - } - - void key( const std::string_view /*unused*/ ) - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - throw std::logic_error( "expected any value, but key() was called" ); - case EXPECT_ARRAY_VALUE_OR_END: - case EXPECT_SIZED_ARRAY_VALUE_OR_END: - throw std::logic_error( "expected any value or end_array(...), but key() was called" ); - case EXPECT_ARRAY_ELEMENT: - case EXPECT_SIZED_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but key() was called" ); - case EXPECT_OBJECT_KEY_OR_END: - state = EXPECT_OBJECT_VALUE; - return; - case EXPECT_SIZED_OBJECT_KEY_OR_END: - state = EXPECT_SIZED_OBJECT_VALUE; - return; - case EXPECT_OBJECT_VALUE: - case EXPECT_SIZED_OBJECT_VALUE: - throw std::logic_error( "expected any value, but key() was called" ); - case EXPECT_OBJECT_MEMBER: - case EXPECT_SIZED_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but key() was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but key() was called" ); - } - throw std::logic_error( "invalid state" ); - } - - void member() - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - throw std::logic_error( "expected any value, but member() was called" ); - case EXPECT_ARRAY_VALUE_OR_END: - case EXPECT_SIZED_ARRAY_VALUE_OR_END: - throw std::logic_error( "expected any value or end_array(...), but member() was called" ); - case EXPECT_ARRAY_ELEMENT: - case EXPECT_SIZED_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but member() was called" ); - case EXPECT_OBJECT_KEY_OR_END: - case EXPECT_SIZED_OBJECT_KEY_OR_END: - throw std::logic_error( "expected key() or end_object(...), but member() was called" ); - case EXPECT_OBJECT_VALUE: - case EXPECT_SIZED_OBJECT_VALUE: - throw std::logic_error( "expected any value, but member() was called" ); - case EXPECT_OBJECT_MEMBER: - state = EXPECT_OBJECT_KEY_OR_END; - return; - case EXPECT_SIZED_OBJECT_MEMBER: - state = EXPECT_SIZED_OBJECT_KEY_OR_END; - ++sizes.back().counted; - return; - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but member() was called" ); - } - throw std::logic_error( "invalid state" ); - } - - void end_object() - { - switch( state ) { - case EXPECT_TOP_LEVEL_VALUE: - throw std::logic_error( "expected any value, but end_object(...) was called" ); - case EXPECT_ARRAY_VALUE_OR_END: - case EXPECT_SIZED_ARRAY_VALUE_OR_END: - throw std::logic_error( "expected any value or end_array(...), but end_object(...) was called" ); - case EXPECT_ARRAY_ELEMENT: - case EXPECT_SIZED_ARRAY_ELEMENT: - throw std::logic_error( "expected element(), but end_object(...) was called" ); - case EXPECT_OBJECT_KEY_OR_END: - state = stack.back(); - stack.pop_back(); - return; - case EXPECT_SIZED_OBJECT_KEY_OR_END: - throw std::logic_error( "expected any value or end_object(std::size_t), but end_object() was called" ); - case EXPECT_OBJECT_VALUE: - case EXPECT_SIZED_OBJECT_VALUE: - throw std::logic_error( "expected any value, but end_object(...) was called" ); - case EXPECT_OBJECT_MEMBER: - case EXPECT_SIZED_OBJECT_MEMBER: - throw std::logic_error( "expected member(), but end_object(...) was called" ); - case EXPECT_NOTHING: - throw std::logic_error( "expected nothing, but end_object(...) was called" ); - } - throw std::logic_error( "invalid state" ); - } - - void end_object( const std::size_t expected ) - { - switch( state ) { - case EXPECT_SIZED_OBJECT_KEY_OR_END: - state = EXPECT_OBJECT_KEY_OR_END; - break; - case EXPECT_OBJECT_KEY_OR_END: - throw std::logic_error( "expected any value or end_object(), but end_object(std::size_t) was called" ); - default: - break; - } - assert( sizes.size() ); - sizes.back().check( expected ); - sizes.pop_back(); - end_object(); - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/validate_keys.hpp b/include/tao/json/events/validate_keys.hpp deleted file mode 100644 index c03d123d..00000000 --- a/include/tao/json/events/validate_keys.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_VALIDATE_KEYS_HPP -#define TAO_JSON_EVENTS_VALIDATE_KEYS_HPP - -#include -#include -#include -#include - -#include "../external/pegtl.hpp" - -namespace tao::json::events -{ - template< typename Consumer, typename Rule > - struct validate_keys - : Consumer - { - using Consumer::Consumer; - - void validate_key( const std::string_view v ) - { - pegtl::memory_input< pegtl::tracking_mode::lazy > in( v.data(), v.size(), "validate_key" ); - if( !pegtl::parse< Rule >( in ) ) { - throw std::runtime_error( "invalid key: " + std::string( v ) ); - } - } - - void key( const std::string_view v ) - { - validate_key( v ); - Consumer::key( v ); - } - - void key( const char* v ) - { - validate_key( v ); - Consumer::key( v ); - } - - void key( std::string&& v ) - { - validate_key( v ); - Consumer::key( std::move( v ) ); - } - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/virtual_base.hpp b/include/tao/json/events/virtual_base.hpp deleted file mode 100644 index 553f2443..00000000 --- a/include/tao/json/events/virtual_base.hpp +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_VIRTUAL_BASE_HPP -#define TAO_JSON_EVENTS_VIRTUAL_BASE_HPP - -#include -#include -#include -#include -#include - -#include "../binary_view.hpp" - -namespace tao::json::events -{ - // Events consumer interface with virtual functions. - - class virtual_base - { - public: - void null() - { - v_null(); - } - - void boolean( const bool v ) - { - v_boolean( v ); - } - - void number( const std::int64_t v ) - { - v_number( v ); - } - - void number( const std::uint64_t v ) - { - v_number( v ); - } - - void number( const double v ) - { - v_number( v ); - } - - void string( const char* v ) - { - v_string( v ); - } - - void string( std::string&& v ) - { - v_string( std::move( v ) ); - } - - void string( const std::string& v ) - { - v_string( v ); - } - - void string( const std::string_view v ) - { - v_string( v ); - } - - void binary( std::vector< std::byte >&& v ) - { - v_binary( std::move( v ) ); - } - - void binary( const std::vector< std::byte >& v ) - { - v_binary( v ); - } - - void binary( const tao::binary_view v ) - { - v_binary( v ); - } - - void begin_array() - { - v_begin_array(); - } - - void begin_array( const std::size_t v ) - { - v_begin_array( v ); - } - - void element() - { - v_element(); - } - - void end_array() - { - v_end_array(); - } - - void end_array( const std::size_t v ) - { - v_end_array( v ); - } - - void begin_object() - { - v_begin_object(); - } - - void begin_object( const std::size_t v ) - { - v_begin_object( v ); - } - - void key( const char* v ) - { - v_key( v ); - } - - void key( std::string&& v ) - { - v_key( std::move( v ) ); - } - - void key( const std::string& v ) - { - v_key( v ); - } - - void key( const std::string_view v ) - { - v_key( v ); - } - - void member() - { - v_member(); - } - - void end_object() - { - v_end_object(); - } - - void end_object( const std::size_t v ) - { - v_end_object( v ); - } - - virtual_base( virtual_base&& ) = delete; - virtual_base( const virtual_base& ) = delete; - - void operator=( virtual_base&& ) = delete; - void operator=( const virtual_base& ) = delete; - - protected: - virtual_base() = default; - ~virtual_base() = default; - - virtual void v_null() = 0; - virtual void v_boolean( bool ) = 0; - virtual void v_number( std::int64_t ) = 0; - virtual void v_number( std::uint64_t ) = 0; - virtual void v_number( double ) = 0; - virtual void v_string( const char* ) = 0; - virtual void v_string( std::string&& ) = 0; - virtual void v_string( const std::string& ) = 0; - virtual void v_string( std::string_view ) = 0; - virtual void v_binary( std::vector< std::byte >&& ) = 0; - virtual void v_binary( const std::vector< std::byte >& ) = 0; - virtual void v_binary( tao::binary_view ) = 0; - virtual void v_begin_array() = 0; - virtual void v_begin_array( std::size_t ) = 0; - virtual void v_element() = 0; - virtual void v_end_array() = 0; - virtual void v_end_array( std::size_t ) = 0; - virtual void v_begin_object() = 0; - virtual void v_begin_object( std::size_t ) = 0; - virtual void v_key( const char* ) = 0; - virtual void v_key( std::string&& ) = 0; - virtual void v_key( const std::string& ) = 0; - virtual void v_key( std::string_view ) = 0; - virtual void v_member() = 0; - virtual void v_end_object() = 0; - virtual void v_end_object( std::size_t ) = 0; - }; - -} // namespace tao::json::events - -#endif diff --git a/include/tao/json/events/virtual_ref.hpp b/include/tao/json/events/virtual_ref.hpp deleted file mode 100644 index f5d40e96..00000000 --- a/include/tao/json/events/virtual_ref.hpp +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_EVENTS_VIRTUAL_REF_HPP -#define TAO_JSON_EVENTS_VIRTUAL_REF_HPP - -#include -#include - -#include "virtual_base.hpp" - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4373 ) -#endif - -namespace tao::json::events -{ - template< typename Consumer > - class virtual_ref - : public virtual_base - { - public: - explicit virtual_ref( Consumer& r ) noexcept - : m_r( r ) - {} - - virtual ~virtual_ref() = default; - - private: - Consumer& m_r; - - void v_null() override - { - m_r.null(); - } - - void v_boolean( const bool v ) override - { - m_r.boolean( v ); - } - - void v_number( const std::int64_t v ) override - { - m_r.number( v ); - } - - void v_number( const std::uint64_t v ) override - { - m_r.number( v ); - } - - void v_number( const double v ) override - { - m_r.number( v ); - } - - void v_string( const char* v ) override - { - m_r.string( v ); - } - - void v_string( std::string&& v ) override - { - m_r.string( std::move( v ) ); - } - - void v_string( const std::string& v ) override - { - m_r.string( v ); - } - - void v_string( const std::string_view v ) override - { - m_r.string( v ); - } - - void v_binary( std::vector< std::byte >&& v ) override - { - m_r.binary( std::move( v ) ); - } - - void v_binary( const std::vector< std::byte >& v ) override - { - m_r.binary( v ); - } - - void v_binary( const tao::binary_view v ) override - { - m_r.binary( v ); - } - - void v_begin_array() override - { - m_r.begin_array(); - } - - void v_begin_array( const std::size_t v ) override - { - m_r.begin_array( v ); - } - - void v_element() override - { - m_r.element(); - } - - void v_end_array() override - { - m_r.end_array(); - } - - void v_end_array( const std::size_t v ) override - { - m_r.end_array( v ); - } - - void v_begin_object() override - { - m_r.begin_object(); - } - - void v_begin_object( const std::size_t v ) override - { - m_r.begin_object( v ); - } - - void v_key( const char* v ) override - { - m_r.key( v ); - } - - void v_key( std::string&& v ) override - { - m_r.key( std::move( v ) ); - } - - void v_key( const std::string& v ) override - { - m_r.key( v ); - } - - void v_key( const std::string_view v ) override - { - m_r.key( v ); - } - - void v_member() override - { - m_r.member(); - } - - void v_end_object() override - { - m_r.end_object(); - } - - void v_end_object( const std::size_t v ) override - { - m_r.end_object( v ); - } - }; - -} // namespace tao::json::events - -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - -#endif diff --git a/include/tao/json/external/double.hpp b/include/tao/json/external/double.hpp deleted file mode 100644 index 9087c4e8..00000000 --- a/include/tao/json/external/double.hpp +++ /dev/null @@ -1,1313 +0,0 @@ -// This header include/tao/json/external/double.hpp contains -// modified portions of the double-conversion library from -// https://www.github.com/google/double-conversion -// which is licensed as follows: - -// Copyright 2006-2011 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef TAO_JSON_EXTERNAL_DOUBLE_HPP -#define TAO_JSON_EXTERNAL_DOUBLE_HPP - -// clang-format off - -#include - -#include -#include -#include -#include -#include - -// Double operations detection based on target architecture. -// Linux uses a 80bit wide floating point stack on x86. This induces double -// rounding, which in turn leads to wrong results. -// An easy way to test if the floating-point operations are correct is to -// evaluate: 89255.0/1e22. If the floating-point stack is 64 bits wide then -// the result is equal to 89255e-22. -// The best way to test this, is to create a division-function and to compare -// the output of the division with the expected result. (Inlining must be -// disabled.) -// On Linux,x86 89255e-22 != Div_double(89255.0/1e22) -#if defined(_M_X64) || defined(__x86_64__) || \ - defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || defined(_M_ARM64) || \ - defined(__hppa__) || defined(__ia64__) || \ - defined(__mips__) || \ - defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \ - defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \ - defined(__sparc__) || defined(__sparc) || defined(__s390__) || \ - defined(__SH4__) || defined(__alpha__) || \ - defined(_MIPS_ARCH_MIPS32R2) || \ - defined(__AARCH64EL__) || defined(__aarch64__) -#define TAO_JSON_DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 -#elif defined(__mc68000__) -#undef TAO_JSON_DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS -#elif defined(_M_IX86) || defined(__i386__) || defined(__i386) -#if defined(_WIN32) -// Windows uses a 64bit wide floating point stack. -#define TAO_JSON_DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 -#else -#undef TAO_JSON_DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS -#endif // _WIN32 -#else -#error Target architecture was not detected as supported by Double-Conversion. -#endif - -#if defined(__GNUC__) -#define TAO_JSON_DOUBLE_CONVERSION_UNUSED __attribute__((unused)) -#else -#define TAO_JSON_DOUBLE_CONVERSION_UNUSED -#endif - -#if defined(_WIN32) && !defined(__MINGW32__) - -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef short int16_t; -typedef unsigned short uint16_t; -typedef int int32_t; -typedef unsigned int uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; - -// intptr_t and friends are defined in crtdefs.h through stdio.h. - -#else - -#include - -#endif - -typedef uint16_t uc16; - -#define TAO_JSON_UINT64_2PART_C(a, b) (((static_cast(a) << 32) + 0x##b##u)) - -#ifndef TAO_JSON_GDCV8_ARRAY_SIZE -#define TAO_JSON_GDCV8_ARRAY_SIZE(a) \ - ((sizeof(a) / sizeof(*(a))) / \ - static_cast(!(sizeof(a) % sizeof(*(a))))) -#endif - -namespace tao::json::double_conversion -{ - static const int kCharSize = sizeof( char ); - - template - class Vector { - public: - Vector() : start_(nullptr), length_(0) {} - Vector(T* data, int len) : start_(data), length_(len) { - assert(len == 0 || (len > 0 && data != nullptr)); - } - - int length() const { return length_; } - - T& operator[](int index) const { - assert(0 <= index && index < length_); - return start_[index]; - } - - private: - T* start_; - int length_; - }; - - template - inline Dest BitCast(const Source& source) { - TAO_JSON_DOUBLE_CONVERSION_UNUSED - typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1]; - - Dest dest; - std::memmove(&dest, &source, sizeof(dest)); - return dest; - } - - template - inline Dest BitCast(Source* source) { - return BitCast(reinterpret_cast(source)); - } - - class Bignum - { - public: - static const int kMaxSignificantBits = 3584; - - Bignum(); - - void AssignUInt16(uint16_t value); - void AssignUInt64(uint64_t value); - - void AssignDecimalString(Vector value); - - void AssignPowerUInt16(uint16_t base, int exponent); - - void AddUInt64(uint64_t operand); - void AddBignum(const Bignum& other); - void SubtractBignum(const Bignum& other); - - void Square(); - void ShiftLeft(int shift_amount); - void MultiplyByUInt32(uint32_t factor); - void MultiplyByUInt64(uint64_t factor); - void MultiplyByPowerOfTen(int exponent); - - static int Compare(const Bignum& a, const Bignum& b); - static bool LessEqual(const Bignum& a, const Bignum& b) { - return Compare(a, b) <= 0; - } - - private: - typedef uint32_t Chunk; - typedef uint64_t DoubleChunk; - - static const int kChunkSize = sizeof(Chunk) * 8; - static const int kDoubleChunkSize = sizeof(DoubleChunk) * 8; - static const int kBigitSize = 28; - static const Chunk kBigitMask = (1 << kBigitSize) - 1; - static const int kBigitCapacity = kMaxSignificantBits / kBigitSize; - - void EnsureCapacity(int size) { - assert(size <= kBigitCapacity); - (void)size; - } - void Align(const Bignum& other); - void Clamp(); - bool IsClamped() const; - void Zero(); - - void BigitsShiftLeft(int shift_amount); - int BigitLength() const { return used_digits_ + exponent_; } - Chunk BigitAt(int index) const; - void SubtractTimes(const Bignum& other, int factor); - - Chunk bigits_buffer_[kBigitCapacity]; - Vector bigits_; - int used_digits_; - int exponent_; - - Bignum( const Bignum & ) = delete; - void operator= ( const Bignum & ) = delete; - }; - - inline Bignum::Bignum() - : bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) { - for (int i = 0; i < kBigitCapacity; ++i) { - bigits_[i] = 0; - } - } - - template - inline int BitSize(S value) { - (void) value; // Mark variable as used. - return 8 * sizeof(value); - } - - inline void Bignum::AssignUInt16(uint16_t value) { - assert(kBigitSize >= BitSize(value)); - Zero(); - if (value == 0) return; - - EnsureCapacity(1); - bigits_[0] = value; - used_digits_ = 1; - } - - inline void Bignum::AssignUInt64(uint64_t value) { - const int kUInt64Size = 64; - - Zero(); - if (value == 0) return; - - int needed_bigits = kUInt64Size / kBigitSize + 1; - EnsureCapacity(needed_bigits); - for (int i = 0; i < needed_bigits; ++i) { - bigits_[i] = value & kBigitMask; - value = value >> kBigitSize; - } - used_digits_ = needed_bigits; - Clamp(); - } - - inline uint64_t ReadUInt64(Vector buffer, - int from, - int digits_to_read) { - uint64_t result = 0; - for (int i = from; i < from + digits_to_read; ++i) { - int digit = buffer[i] - '0'; - assert(0 <= digit && digit <= 9); - result = result * 10 + digit; - } - return result; - } - - inline void Bignum::AssignDecimalString(Vector value) { - const int kMaxUint64DecimalDigits = 19; - Zero(); - int length = value.length(); - unsigned int pos = 0; - while (length >= kMaxUint64DecimalDigits) { - uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits); - pos += kMaxUint64DecimalDigits; - length -= kMaxUint64DecimalDigits; - MultiplyByPowerOfTen(kMaxUint64DecimalDigits); - AddUInt64(digits); - } - uint64_t digits = ReadUInt64(value, pos, length); - MultiplyByPowerOfTen(length); - AddUInt64(digits); - Clamp(); - } - - inline void Bignum::AddUInt64(uint64_t operand) { - if (operand == 0) return; - Bignum other; - other.AssignUInt64(operand); - AddBignum(other); - } - - inline void Bignum::AddBignum(const Bignum& other) { - assert(IsClamped()); - assert(other.IsClamped()); - Align(other); - EnsureCapacity(1 + (std::max)(BigitLength(), other.BigitLength()) - exponent_); - Chunk carry = 0; - int bigit_pos = other.exponent_ - exponent_; - assert(bigit_pos >= 0); - for (int i = 0; i < other.used_digits_; ++i) { - Chunk sum = bigits_[bigit_pos] + other.bigits_[i] + carry; - bigits_[bigit_pos] = sum & kBigitMask; - carry = sum >> kBigitSize; - bigit_pos++; - } - while (carry != 0) { - Chunk sum = bigits_[bigit_pos] + carry; - bigits_[bigit_pos] = sum & kBigitMask; - carry = sum >> kBigitSize; - bigit_pos++; - } - used_digits_ = (std::max)(bigit_pos, used_digits_); - assert(IsClamped()); - } - - inline void Bignum::SubtractBignum(const Bignum& other) { - assert(IsClamped()); - assert(other.IsClamped()); - assert(LessEqual(other, *this)); - Align(other); - - int offset = other.exponent_ - exponent_; - Chunk borrow = 0; - int i; - for (i = 0; i < other.used_digits_; ++i) { - assert((borrow == 0) || (borrow == 1)); - Chunk difference = bigits_[i + offset] - other.bigits_[i] - borrow; - bigits_[i + offset] = difference & kBigitMask; - borrow = difference >> (kChunkSize - 1); - } - while (borrow != 0) { - Chunk difference = bigits_[i + offset] - borrow; - bigits_[i + offset] = difference & kBigitMask; - borrow = difference >> (kChunkSize - 1); - ++i; - } - Clamp(); - } - - inline void Bignum::ShiftLeft(int shift_amount) { - if (used_digits_ == 0) return; - exponent_ += shift_amount / kBigitSize; - int local_shift = shift_amount % kBigitSize; - EnsureCapacity(used_digits_ + 1); - BigitsShiftLeft(local_shift); - } - - inline void Bignum::MultiplyByUInt32(uint32_t factor) { - if (factor == 1) return; - if (factor == 0) { - Zero(); - return; - } - if (used_digits_ == 0) return; - assert(kDoubleChunkSize >= kBigitSize + 32 + 1); - DoubleChunk carry = 0; - for (int i = 0; i < used_digits_; ++i) { - DoubleChunk product = static_cast(factor) * bigits_[i] + carry; - bigits_[i] = static_cast(product & kBigitMask); - carry = (product >> kBigitSize); - } - while (carry != 0) { - EnsureCapacity(used_digits_ + 1); - bigits_[used_digits_] = carry & kBigitMask; - used_digits_++; - carry >>= kBigitSize; - } - } - - inline void Bignum::MultiplyByUInt64(uint64_t factor) { - if (factor == 1) return; - if (factor == 0) { - Zero(); - return; - } - assert(kBigitSize < 32); - uint64_t carry = 0; - uint64_t low = factor & 0xFFFFFFFF; - uint64_t high = factor >> 32; - for (int i = 0; i < used_digits_; ++i) { - uint64_t product_low = low * bigits_[i]; - uint64_t product_high = high * bigits_[i]; - uint64_t tmp = (carry & kBigitMask) + product_low; - bigits_[i] = tmp & kBigitMask; - carry = (carry >> kBigitSize) + (tmp >> kBigitSize) + - (product_high << (32 - kBigitSize)); - } - while (carry != 0) { - EnsureCapacity(used_digits_ + 1); - bigits_[used_digits_] = carry & kBigitMask; - used_digits_++; - carry >>= kBigitSize; - } - } - - inline void Bignum::MultiplyByPowerOfTen(int exponent) { - const uint64_t kFive27 = TAO_JSON_UINT64_2PART_C(0x6765c793, fa10079d); - const uint16_t kFive1 = 5; - const uint16_t kFive2 = kFive1 * 5; - const uint16_t kFive3 = kFive2 * 5; - const uint16_t kFive4 = kFive3 * 5; - const uint16_t kFive5 = kFive4 * 5; - const uint16_t kFive6 = kFive5 * 5; - const uint32_t kFive7 = kFive6 * 5; - const uint32_t kFive8 = kFive7 * 5; - const uint32_t kFive9 = kFive8 * 5; - const uint32_t kFive10 = kFive9 * 5; - const uint32_t kFive11 = kFive10 * 5; - const uint32_t kFive12 = kFive11 * 5; - const uint32_t kFive13 = kFive12 * 5; - const uint32_t kFive1_to_12[] = - { kFive1, kFive2, kFive3, kFive4, kFive5, kFive6, - kFive7, kFive8, kFive9, kFive10, kFive11, kFive12 }; - - assert(exponent >= 0); - if (exponent == 0) return; - if (used_digits_ == 0) return; - int remaining_exponent = exponent; - while (remaining_exponent >= 27) { - MultiplyByUInt64(kFive27); - remaining_exponent -= 27; - } - while (remaining_exponent >= 13) { - MultiplyByUInt32(kFive13); - remaining_exponent -= 13; - } - if (remaining_exponent > 0) { - MultiplyByUInt32(kFive1_to_12[remaining_exponent - 1]); - } - ShiftLeft(exponent); - } - - inline void Bignum::Square() { - assert(IsClamped()); - int product_length = 2 * used_digits_; - EnsureCapacity(product_length); - - if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_digits_) { - std::abort(); // Unimplemented. - } - DoubleChunk accumulator = 0; - int copy_offset = used_digits_; - for (int i = 0; i < used_digits_; ++i) { - bigits_[copy_offset + i] = bigits_[i]; - } - for (int i = 0; i < used_digits_; ++i) { - int bigit_index1 = i; - int bigit_index2 = 0; - while (bigit_index1 >= 0) { - Chunk chunk1 = bigits_[copy_offset + bigit_index1]; - Chunk chunk2 = bigits_[copy_offset + bigit_index2]; - accumulator += static_cast(chunk1) * chunk2; - bigit_index1--; - bigit_index2++; - } - bigits_[i] = static_cast(accumulator) & kBigitMask; - accumulator >>= kBigitSize; - } - for (int i = used_digits_; i < product_length; ++i) { - int bigit_index1 = used_digits_ - 1; - int bigit_index2 = i - bigit_index1; - while (bigit_index2 < used_digits_) { - Chunk chunk1 = bigits_[copy_offset + bigit_index1]; - Chunk chunk2 = bigits_[copy_offset + bigit_index2]; - accumulator += static_cast(chunk1) * chunk2; - bigit_index1--; - bigit_index2++; - } - bigits_[i] = static_cast(accumulator) & kBigitMask; - accumulator >>= kBigitSize; - } - assert(accumulator == 0); - used_digits_ = product_length; - exponent_ *= 2; - Clamp(); - } - - inline void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) { - assert(base != 0); - assert(power_exponent >= 0); - if (power_exponent == 0) { - AssignUInt16(1); - return; - } - Zero(); - int shifts = 0; - while ((base & 1) == 0) { - base >>= 1; - shifts++; - } - int bit_size = 0; - int tmp_base = base; - while (tmp_base != 0) { - tmp_base >>= 1; - bit_size++; - } - int final_size = bit_size * power_exponent; - EnsureCapacity(final_size / kBigitSize + 2); - int mask = 1; - while (power_exponent >= mask) mask <<= 1; - mask >>= 2; - uint64_t this_value = base; - bool delayed_multipliciation = false; - const uint64_t max_32bits = 0xFFFFFFFF; - while (mask != 0 && this_value <= max_32bits) { - this_value = this_value * this_value; - if ((power_exponent & mask) != 0) { - uint64_t base_bits_mask = - ~((static_cast(1) << (64 - bit_size)) - 1); - bool high_bits_zero = (this_value & base_bits_mask) == 0; - if (high_bits_zero) { - this_value *= base; - } else { - delayed_multipliciation = true; - } - } - mask >>= 1; - } - AssignUInt64(this_value); - if (delayed_multipliciation) { - MultiplyByUInt32(base); - } - while (mask != 0) { - Square(); - if ((power_exponent & mask) != 0) { - MultiplyByUInt32(base); - } - mask >>= 1; - } - ShiftLeft(shifts * power_exponent); - } - - inline Bignum::Chunk Bignum::BigitAt(int index) const { - if (index >= BigitLength()) return 0; - if (index < exponent_) return 0; - return bigits_[index - exponent_]; - } - - inline int Bignum::Compare(const Bignum& a, const Bignum& b) { - assert(a.IsClamped()); - assert(b.IsClamped()); - int bigit_length_a = a.BigitLength(); - int bigit_length_b = b.BigitLength(); - if (bigit_length_a < bigit_length_b) return -1; - if (bigit_length_a > bigit_length_b) return +1; - for (int i = bigit_length_a - 1; i >= (std::min)(a.exponent_, b.exponent_); --i) { - const Chunk bigit_a = a.BigitAt(i); - const Chunk bigit_b = b.BigitAt(i); - if (bigit_a < bigit_b) return -1; - if (bigit_a > bigit_b) return +1; - } - return 0; - } - - inline void Bignum::Clamp() { - while (used_digits_ > 0 && bigits_[used_digits_ - 1] == 0) { - used_digits_--; - } - if (used_digits_ == 0) { - exponent_ = 0; - } - } - - inline bool Bignum::IsClamped() const { - return used_digits_ == 0 || bigits_[used_digits_ - 1] != 0; - } - - inline void Bignum::Zero() { - for (int i = 0; i < used_digits_; ++i) { - bigits_[i] = 0; - } - used_digits_ = 0; - exponent_ = 0; - } - - inline void Bignum::Align(const Bignum& other) { - if (exponent_ > other.exponent_) { - int zero_digits = exponent_ - other.exponent_; - EnsureCapacity(used_digits_ + zero_digits); - for (int i = used_digits_ - 1; i >= 0; --i) { - bigits_[i + zero_digits] = bigits_[i]; - } - for (int i = 0; i < zero_digits; ++i) { - bigits_[i] = 0; - } - used_digits_ += zero_digits; - exponent_ -= zero_digits; - assert(used_digits_ >= 0); - assert(exponent_ >= 0); - } - } - - inline void Bignum::BigitsShiftLeft(int shift_amount) { - assert(shift_amount < kBigitSize); - assert(shift_amount >= 0); - Chunk carry = 0; - for (int i = 0; i < used_digits_; ++i) { - Chunk new_carry = bigits_[i] >> (kBigitSize - shift_amount); - bigits_[i] = ((bigits_[i] << shift_amount) + carry) & kBigitMask; - carry = new_carry; - } - if (carry != 0) { - bigits_[used_digits_] = carry; - used_digits_++; - } - } - - inline void Bignum::SubtractTimes(const Bignum& other, int factor) { - assert(exponent_ <= other.exponent_); - if (factor < 3) { - for (int i = 0; i < factor; ++i) { - SubtractBignum(other); - } - return; - } - Chunk borrow = 0; - int exponent_diff = other.exponent_ - exponent_; - for (int i = 0; i < other.used_digits_; ++i) { - DoubleChunk product = static_cast(factor) * other.bigits_[i]; - DoubleChunk remove = borrow + product; - Chunk difference = bigits_[i + exponent_diff] - (remove & kBigitMask); - bigits_[i + exponent_diff] = difference & kBigitMask; - borrow = static_cast((difference >> (kChunkSize - 1)) + - (remove >> kBigitSize)); - } - for (int i = other.used_digits_ + exponent_diff; i < used_digits_; ++i) { - if (borrow == 0) return; - Chunk difference = bigits_[i] - borrow; - bigits_[i] = difference & kBigitMask; - borrow = difference >> (kChunkSize - 1); - } - Clamp(); - } - - class DiyFp - { - public: - static const int kSignificandSize = 64; - - DiyFp() : f_(0), e_(0) {} - DiyFp(uint64_t significand, int exponent) : f_(significand), e_(exponent) {} - - void Subtract(const DiyFp& other) { - assert(e_ == other.e_); - assert(f_ >= other.f_); - f_ -= other.f_; - } - - static DiyFp Minus(const DiyFp& a, const DiyFp& b) { - DiyFp result = a; - result.Subtract(b); - return result; - } - - void Multiply(const DiyFp& other) - { - const uint64_t kM32 = 0xFFFFFFFFU; - uint64_t a = f_ >> 32; - uint64_t b = f_ & kM32; - uint64_t c = other.f_ >> 32; - uint64_t d = other.f_ & kM32; - uint64_t ac = a * c; - uint64_t bc = b * c; - uint64_t ad = a * d; - uint64_t bd = b * d; - uint64_t tmp = (bd >> 32) + (ad & kM32) + (bc & kM32); - tmp += 1U << 31; - uint64_t result_f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32); - e_ += other.e_ + 64; - f_ = result_f; - } - - static DiyFp Times(const DiyFp& a, const DiyFp& b) - { - DiyFp result = a; - result.Multiply(b); - return result; - } - - void Normalize() { - assert(f_ != 0); - uint64_t significand = f_; - int exponent = e_; - - const uint64_t k10MSBits = TAO_JSON_UINT64_2PART_C(0xFFC00000, 00000000); - while ((significand & k10MSBits) == 0) { - significand <<= 10; - exponent -= 10; - } - while ((significand & kUint64MSB) == 0) { - significand <<= 1; - exponent--; - } - f_ = significand; - e_ = exponent; - } - - static DiyFp Normalize(const DiyFp& a) { - DiyFp result = a; - result.Normalize(); - return result; - } - - uint64_t f() const { return f_; } - int e() const { return e_; } - - void set_f(uint64_t new_value) { f_ = new_value; } - void set_e(int new_value) { e_ = new_value; } - - private: - static const uint64_t kUint64MSB = TAO_JSON_UINT64_2PART_C(0x80000000, 00000000); - - uint64_t f_; - int e_; - }; - - static uint64_t double_to_uint64(double d) { return BitCast(d); } - static double uint64_to_double(uint64_t d64) { return BitCast(d64); } - - class Double { - public: - static const uint64_t kSignMask = TAO_JSON_UINT64_2PART_C(0x80000000, 00000000); - static const uint64_t kExponentMask = TAO_JSON_UINT64_2PART_C(0x7FF00000, 00000000); - static const uint64_t kSignificandMask = TAO_JSON_UINT64_2PART_C(0x000FFFFF, FFFFFFFF); - static const uint64_t kHiddenBit = TAO_JSON_UINT64_2PART_C(0x00100000, 00000000); - static const int kPhysicalSignificandSize = 52; - static const int kSignificandSize = 53; - - Double() : d64_(0) {} - explicit Double(double d) : d64_(double_to_uint64(d)) {} - explicit Double(uint64_t d64) : d64_(d64) {} - explicit Double(DiyFp diy_fp) - : d64_(DiyFpToUint64(diy_fp)) {} - - DiyFp AsDiyFp() const { - assert(Sign() > 0); - assert(!IsSpecial()); - return DiyFp(Significand(), Exponent()); - } - - DiyFp AsNormalizedDiyFp() const { - assert(value() > 0.0); - uint64_t f = Significand(); - int e = Exponent(); - - while ((f & kHiddenBit) == 0) { - f <<= 1; - e--; - } - f <<= DiyFp::kSignificandSize - kSignificandSize; - e -= DiyFp::kSignificandSize - kSignificandSize; - return DiyFp(f, e); - } - - uint64_t AsUint64() const { - return d64_; - } - - double NextDouble() const { - if (d64_ == kInfinity) return Double(kInfinity).value(); - if (Sign() < 0 && Significand() == 0) { - return 0.0; - } - if (Sign() < 0) { - return Double(d64_ - 1).value(); - } else { - return Double(d64_ + 1).value(); - } - } - - double PreviousDouble() const { - if (d64_ == (kInfinity | kSignMask)) return -Double::Infinity(); - if (Sign() < 0) { - return Double(d64_ + 1).value(); - } else { - if (Significand() == 0) return -0.0; - return Double(d64_ - 1).value(); - } - } - - int Exponent() const { - if (IsDenormal()) return kDenormalExponent; - - uint64_t d64 = AsUint64(); - int biased_e = - static_cast((d64 & kExponentMask) >> kPhysicalSignificandSize); - return biased_e - kExponentBias; - } - - uint64_t Significand() const { - uint64_t d64 = AsUint64(); - uint64_t significand = d64 & kSignificandMask; - if (!IsDenormal()) { - return significand + kHiddenBit; - } else { - return significand; - } - } - - bool IsDenormal() const { - uint64_t d64 = AsUint64(); - return (d64 & kExponentMask) == 0; - } - - bool IsSpecial() const { - uint64_t d64 = AsUint64(); - return (d64 & kExponentMask) == kExponentMask; - } - - bool IsNan() const { - uint64_t d64 = AsUint64(); - return ((d64 & kExponentMask) == kExponentMask) && - ((d64 & kSignificandMask) != 0); - } - - bool IsInfinite() const { - uint64_t d64 = AsUint64(); - return ((d64 & kExponentMask) == kExponentMask) && - ((d64 & kSignificandMask) == 0); - } - - int Sign() const { - uint64_t d64 = AsUint64(); - return (d64 & kSignMask) == 0? 1: -1; - } - - DiyFp UpperBoundary() const { - assert(Sign() > 0); - return DiyFp(Significand() * 2 + 1, Exponent() - 1); - } - - void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const { - assert(value() > 0.0); - DiyFp v = this->AsDiyFp(); - DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1)); - DiyFp m_minus; - if (LowerBoundaryIsCloser()) { - m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2); - } else { - m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1); - } - m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e())); - m_minus.set_e(m_plus.e()); - *out_m_plus = m_plus; - *out_m_minus = m_minus; - } - - bool LowerBoundaryIsCloser() const { - bool physical_significand_is_zero = ((AsUint64() & kSignificandMask) == 0); - return physical_significand_is_zero && (Exponent() != kDenormalExponent); - } - - double value() const { return uint64_to_double(d64_); } - - static int SignificandSizeForOrderOfMagnitude(int order) { - if (order >= (kDenormalExponent + kSignificandSize)) { - return kSignificandSize; - } - if (order <= kDenormalExponent) return 0; - return order - kDenormalExponent; - } - - static double Infinity() { - return Double(kInfinity).value(); - } - - static double NaN() { - return Double(kNaN).value(); - } - - private: - static const int kExponentBias = 0x3FF + kPhysicalSignificandSize; - static const int kDenormalExponent = -kExponentBias + 1; - static const int kMaxExponent = 0x7FF - kExponentBias; - static const uint64_t kInfinity = TAO_JSON_UINT64_2PART_C(0x7FF00000, 00000000); - static const uint64_t kNaN = TAO_JSON_UINT64_2PART_C(0x7FF80000, 00000000); - - const uint64_t d64_; - - static uint64_t DiyFpToUint64(DiyFp diy_fp) { - uint64_t significand = diy_fp.f(); - int exponent = diy_fp.e(); - while (significand > kHiddenBit + kSignificandMask) { - significand >>= 1; - exponent++; - } - if (exponent >= kMaxExponent) { - return kInfinity; - } - if (exponent < kDenormalExponent) { - return 0; - } - while (exponent > kDenormalExponent && (significand & kHiddenBit) == 0) { - significand <<= 1; - exponent--; - } - uint64_t biased_exponent; - if (exponent == kDenormalExponent && (significand & kHiddenBit) == 0) { - biased_exponent = 0; - } else { - biased_exponent = static_cast(exponent + kExponentBias); - } - return (significand & kSignificandMask) | - (biased_exponent << kPhysicalSignificandSize); - } - - Double( const Double& ) = delete; - void operator=( const Double& ) = delete; - }; - - struct PowersOfTenCache - { - static const int kDecimalExponentDistance = 8; - - static const int kMinDecimalExponent = -348; - static const int kMaxDecimalExponent = 340; - - static void GetCachedPowerForDecimalExponent(int requested_exponent, - DiyFp* power, - int* found_exponent); - }; - - struct CachedPower { - uint64_t significand; - int16_t binary_exponent; - int16_t decimal_exponent; - }; - - static const CachedPower kCachedPowers[] = { - {TAO_JSON_UINT64_2PART_C(0xfa8fd5a0, 081c0288), -1220, -348}, - {TAO_JSON_UINT64_2PART_C(0xbaaee17f, a23ebf76), -1193, -340}, - {TAO_JSON_UINT64_2PART_C(0x8b16fb20, 3055ac76), -1166, -332}, - {TAO_JSON_UINT64_2PART_C(0xcf42894a, 5dce35ea), -1140, -324}, - {TAO_JSON_UINT64_2PART_C(0x9a6bb0aa, 55653b2d), -1113, -316}, - {TAO_JSON_UINT64_2PART_C(0xe61acf03, 3d1a45df), -1087, -308}, - {TAO_JSON_UINT64_2PART_C(0xab70fe17, c79ac6ca), -1060, -300}, - {TAO_JSON_UINT64_2PART_C(0xff77b1fc, bebcdc4f), -1034, -292}, - {TAO_JSON_UINT64_2PART_C(0xbe5691ef, 416bd60c), -1007, -284}, - {TAO_JSON_UINT64_2PART_C(0x8dd01fad, 907ffc3c), -980, -276}, - {TAO_JSON_UINT64_2PART_C(0xd3515c28, 31559a83), -954, -268}, - {TAO_JSON_UINT64_2PART_C(0x9d71ac8f, ada6c9b5), -927, -260}, - {TAO_JSON_UINT64_2PART_C(0xea9c2277, 23ee8bcb), -901, -252}, - {TAO_JSON_UINT64_2PART_C(0xaecc4991, 4078536d), -874, -244}, - {TAO_JSON_UINT64_2PART_C(0x823c1279, 5db6ce57), -847, -236}, - {TAO_JSON_UINT64_2PART_C(0xc2109436, 4dfb5637), -821, -228}, - {TAO_JSON_UINT64_2PART_C(0x9096ea6f, 3848984f), -794, -220}, - {TAO_JSON_UINT64_2PART_C(0xd77485cb, 25823ac7), -768, -212}, - {TAO_JSON_UINT64_2PART_C(0xa086cfcd, 97bf97f4), -741, -204}, - {TAO_JSON_UINT64_2PART_C(0xef340a98, 172aace5), -715, -196}, - {TAO_JSON_UINT64_2PART_C(0xb23867fb, 2a35b28e), -688, -188}, - {TAO_JSON_UINT64_2PART_C(0x84c8d4df, d2c63f3b), -661, -180}, - {TAO_JSON_UINT64_2PART_C(0xc5dd4427, 1ad3cdba), -635, -172}, - {TAO_JSON_UINT64_2PART_C(0x936b9fce, bb25c996), -608, -164}, - {TAO_JSON_UINT64_2PART_C(0xdbac6c24, 7d62a584), -582, -156}, - {TAO_JSON_UINT64_2PART_C(0xa3ab6658, 0d5fdaf6), -555, -148}, - {TAO_JSON_UINT64_2PART_C(0xf3e2f893, dec3f126), -529, -140}, - {TAO_JSON_UINT64_2PART_C(0xb5b5ada8, aaff80b8), -502, -132}, - {TAO_JSON_UINT64_2PART_C(0x87625f05, 6c7c4a8b), -475, -124}, - {TAO_JSON_UINT64_2PART_C(0xc9bcff60, 34c13053), -449, -116}, - {TAO_JSON_UINT64_2PART_C(0x964e858c, 91ba2655), -422, -108}, - {TAO_JSON_UINT64_2PART_C(0xdff97724, 70297ebd), -396, -100}, - {TAO_JSON_UINT64_2PART_C(0xa6dfbd9f, b8e5b88f), -369, -92}, - {TAO_JSON_UINT64_2PART_C(0xf8a95fcf, 88747d94), -343, -84}, - {TAO_JSON_UINT64_2PART_C(0xb9447093, 8fa89bcf), -316, -76}, - {TAO_JSON_UINT64_2PART_C(0x8a08f0f8, bf0f156b), -289, -68}, - {TAO_JSON_UINT64_2PART_C(0xcdb02555, 653131b6), -263, -60}, - {TAO_JSON_UINT64_2PART_C(0x993fe2c6, d07b7fac), -236, -52}, - {TAO_JSON_UINT64_2PART_C(0xe45c10c4, 2a2b3b06), -210, -44}, - {TAO_JSON_UINT64_2PART_C(0xaa242499, 697392d3), -183, -36}, - {TAO_JSON_UINT64_2PART_C(0xfd87b5f2, 8300ca0e), -157, -28}, - {TAO_JSON_UINT64_2PART_C(0xbce50864, 92111aeb), -130, -20}, - {TAO_JSON_UINT64_2PART_C(0x8cbccc09, 6f5088cc), -103, -12}, - {TAO_JSON_UINT64_2PART_C(0xd1b71758, e219652c), -77, -4}, - {TAO_JSON_UINT64_2PART_C(0x9c400000, 00000000), -50, 4}, - {TAO_JSON_UINT64_2PART_C(0xe8d4a510, 00000000), -24, 12}, - {TAO_JSON_UINT64_2PART_C(0xad78ebc5, ac620000), 3, 20}, - {TAO_JSON_UINT64_2PART_C(0x813f3978, f8940984), 30, 28}, - {TAO_JSON_UINT64_2PART_C(0xc097ce7b, c90715b3), 56, 36}, - {TAO_JSON_UINT64_2PART_C(0x8f7e32ce, 7bea5c70), 83, 44}, - {TAO_JSON_UINT64_2PART_C(0xd5d238a4, abe98068), 109, 52}, - {TAO_JSON_UINT64_2PART_C(0x9f4f2726, 179a2245), 136, 60}, - {TAO_JSON_UINT64_2PART_C(0xed63a231, d4c4fb27), 162, 68}, - {TAO_JSON_UINT64_2PART_C(0xb0de6538, 8cc8ada8), 189, 76}, - {TAO_JSON_UINT64_2PART_C(0x83c7088e, 1aab65db), 216, 84}, - {TAO_JSON_UINT64_2PART_C(0xc45d1df9, 42711d9a), 242, 92}, - {TAO_JSON_UINT64_2PART_C(0x924d692c, a61be758), 269, 100}, - {TAO_JSON_UINT64_2PART_C(0xda01ee64, 1a708dea), 295, 108}, - {TAO_JSON_UINT64_2PART_C(0xa26da399, 9aef774a), 322, 116}, - {TAO_JSON_UINT64_2PART_C(0xf209787b, b47d6b85), 348, 124}, - {TAO_JSON_UINT64_2PART_C(0xb454e4a1, 79dd1877), 375, 132}, - {TAO_JSON_UINT64_2PART_C(0x865b8692, 5b9bc5c2), 402, 140}, - {TAO_JSON_UINT64_2PART_C(0xc83553c5, c8965d3d), 428, 148}, - {TAO_JSON_UINT64_2PART_C(0x952ab45c, fa97a0b3), 455, 156}, - {TAO_JSON_UINT64_2PART_C(0xde469fbd, 99a05fe3), 481, 164}, - {TAO_JSON_UINT64_2PART_C(0xa59bc234, db398c25), 508, 172}, - {TAO_JSON_UINT64_2PART_C(0xf6c69a72, a3989f5c), 534, 180}, - {TAO_JSON_UINT64_2PART_C(0xb7dcbf53, 54e9bece), 561, 188}, - {TAO_JSON_UINT64_2PART_C(0x88fcf317, f22241e2), 588, 196}, - {TAO_JSON_UINT64_2PART_C(0xcc20ce9b, d35c78a5), 614, 204}, - {TAO_JSON_UINT64_2PART_C(0x98165af3, 7b2153df), 641, 212}, - {TAO_JSON_UINT64_2PART_C(0xe2a0b5dc, 971f303a), 667, 220}, - {TAO_JSON_UINT64_2PART_C(0xa8d9d153, 5ce3b396), 694, 228}, - {TAO_JSON_UINT64_2PART_C(0xfb9b7cd9, a4a7443c), 720, 236}, - {TAO_JSON_UINT64_2PART_C(0xbb764c4c, a7a44410), 747, 244}, - {TAO_JSON_UINT64_2PART_C(0x8bab8eef, b6409c1a), 774, 252}, - {TAO_JSON_UINT64_2PART_C(0xd01fef10, a657842c), 800, 260}, - {TAO_JSON_UINT64_2PART_C(0x9b10a4e5, e9913129), 827, 268}, - {TAO_JSON_UINT64_2PART_C(0xe7109bfb, a19c0c9d), 853, 276}, - {TAO_JSON_UINT64_2PART_C(0xac2820d9, 623bf429), 880, 284}, - {TAO_JSON_UINT64_2PART_C(0x80444b5e, 7aa7cf85), 907, 292}, - {TAO_JSON_UINT64_2PART_C(0xbf21e440, 03acdd2d), 933, 300}, - {TAO_JSON_UINT64_2PART_C(0x8e679c2f, 5e44ff8f), 960, 308}, - {TAO_JSON_UINT64_2PART_C(0xd433179d, 9c8cb841), 986, 316}, - {TAO_JSON_UINT64_2PART_C(0x9e19db92, b4e31ba9), 1013, 324}, - {TAO_JSON_UINT64_2PART_C(0xeb96bf6e, badf77d9), 1039, 332}, - {TAO_JSON_UINT64_2PART_C(0xaf87023b, 9bf0ee6b), 1066, 340}, - }; - - static const int kCachedPowersLength = TAO_JSON_GDCV8_ARRAY_SIZE(kCachedPowers); - static const int kCachedPowersOffset = 348; - static const double kD_1_LOG2_10 = 0.30102999566398114; - - inline void PowersOfTenCache::GetCachedPowerForDecimalExponent(int requested_exponent, - DiyFp* power, - int* found_exponent) { - assert(kMinDecimalExponent <= requested_exponent); - assert(requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance); - int index = - (requested_exponent + kCachedPowersOffset) / kDecimalExponentDistance; - CachedPower cached_power = kCachedPowers[index]; - *power = DiyFp(cached_power.significand, cached_power.binary_exponent); - *found_exponent = cached_power.decimal_exponent; - assert(*found_exponent <= requested_exponent); - assert(requested_exponent < *found_exponent + kDecimalExponentDistance); - } - - static const int kMaxExactDoubleIntegerDecimalDigits = 15; - static const int kMaxUint64DecimalDigits = 19; - - static const int kMaxDecimalPower = 309; - static const int kMinDecimalPower = -324; - - static const uint64_t kMaxUint64 = TAO_JSON_UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF); - - static const double exact_powers_of_ten[] = { - 1.0, // 10^0 - 10.0, - 100.0, - 1000.0, - 10000.0, - 100000.0, - 1000000.0, - 10000000.0, - 100000000.0, - 1000000000.0, - 10000000000.0, // 10^10 - 100000000000.0, - 1000000000000.0, - 10000000000000.0, - 100000000000000.0, - 1000000000000000.0, - 10000000000000000.0, - 100000000000000000.0, - 1000000000000000000.0, - 10000000000000000000.0, - 100000000000000000000.0, // 10^20 - 1000000000000000000000.0, - 10000000000000000000000.0 - }; - - static const int kExactPowersOfTenSize = TAO_JSON_GDCV8_ARRAY_SIZE(exact_powers_of_ten); - static const int kMaxSignificantDecimalDigits = 780; - - inline uint64_t ReadUint64(Vector buffer, - int* number_of_read_digits) { - uint64_t result = 0; - int i = 0; - while (i < buffer.length() && result <= (kMaxUint64 / 10 - 1)) { - int digit = buffer[i++] - '0'; - assert(0 <= digit && digit <= 9); - result = 10 * result + digit; - } - *number_of_read_digits = i; - return result; - } - - inline void ReadDiyFp(Vector buffer, - DiyFp* result, - int* remaining_decimals) { - int read_digits; - uint64_t significand = ReadUint64(buffer, &read_digits); - if (buffer.length() == read_digits) { - *result = DiyFp(significand, 0); - *remaining_decimals = 0; - } else { - if (buffer[read_digits] >= '5') { - significand++; - } - int exponent = 0; - *result = DiyFp(significand, exponent); - *remaining_decimals = buffer.length() - read_digits; - } - } - - inline bool DoubleStrtod(Vector trimmed, - int exponent, - double* result) { -#if !defined(TAO_JSON_DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS) - // On x86 the floating-point stack can be 64 or 80 bits wide. If it is - // 80 bits wide (as is the case on Linux) then double-rounding occurs and the - // result is not accurate. - // We know that Windows32 uses 64 bits and is therefore accurate. - // Note that the ARM simulator is compiled for 32bits. It therefore exhibits - // the same problem. - return false; -#endif - if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) { - int read_digits; - if (exponent < 0 && -exponent < kExactPowersOfTenSize) { - *result = static_cast(ReadUint64(trimmed, &read_digits)); - assert(read_digits == trimmed.length()); - *result /= exact_powers_of_ten[-exponent]; - return true; - } - if (0 <= exponent && exponent < kExactPowersOfTenSize) { - *result = static_cast(ReadUint64(trimmed, &read_digits)); - assert(read_digits == trimmed.length()); - *result *= exact_powers_of_ten[exponent]; - return true; - } - int remaining_digits = - kMaxExactDoubleIntegerDecimalDigits - trimmed.length(); - if ((0 <= exponent) && - (exponent - remaining_digits < kExactPowersOfTenSize)) { - *result = static_cast(ReadUint64(trimmed, &read_digits)); - assert(read_digits == trimmed.length()); - *result *= exact_powers_of_ten[remaining_digits]; - *result *= exact_powers_of_ten[exponent - remaining_digits]; - return true; - } - } - return false; - } - - inline DiyFp AdjustmentPowerOfTen(int exponent) { - assert(0 < exponent); - assert(exponent < PowersOfTenCache::kDecimalExponentDistance); - assert(PowersOfTenCache::kDecimalExponentDistance == 8); - switch (exponent) { - case 1: return DiyFp(TAO_JSON_UINT64_2PART_C(0xa0000000, 00000000), -60); - case 2: return DiyFp(TAO_JSON_UINT64_2PART_C(0xc8000000, 00000000), -57); - case 3: return DiyFp(TAO_JSON_UINT64_2PART_C(0xfa000000, 00000000), -54); - case 4: return DiyFp(TAO_JSON_UINT64_2PART_C(0x9c400000, 00000000), -50); - case 5: return DiyFp(TAO_JSON_UINT64_2PART_C(0xc3500000, 00000000), -47); - case 6: return DiyFp(TAO_JSON_UINT64_2PART_C(0xf4240000, 00000000), -44); - case 7: return DiyFp(TAO_JSON_UINT64_2PART_C(0x98968000, 00000000), -40); - default: - std::abort(); - } - } - - inline bool DiyFpStrtod(Vector buffer, - int exponent, - double* result) { - DiyFp input; - int remaining_decimals; - ReadDiyFp(buffer, &input, &remaining_decimals); - const int kDenominatorLog = 3; - const int kDenominator = 1 << kDenominatorLog; - exponent += remaining_decimals; - uint64_t error = (remaining_decimals == 0 ? 0 : kDenominator / 2); - - int old_e = input.e(); - input.Normalize(); - error <<= old_e - input.e(); - - assert(exponent <= PowersOfTenCache::kMaxDecimalExponent); - if (exponent < PowersOfTenCache::kMinDecimalExponent) { - *result = 0.0; - return true; - } - DiyFp cached_power; - int cached_decimal_exponent; - PowersOfTenCache::GetCachedPowerForDecimalExponent(exponent, - &cached_power, - &cached_decimal_exponent); - - if (cached_decimal_exponent != exponent) { - int adjustment_exponent = exponent - cached_decimal_exponent; - DiyFp adjustment_power = AdjustmentPowerOfTen(adjustment_exponent); - input.Multiply(adjustment_power); - if (kMaxUint64DecimalDigits - buffer.length() >= adjustment_exponent) { - assert(DiyFp::kSignificandSize == 64); - } else { - error += kDenominator / 2; - } - } - - input.Multiply(cached_power); - int error_b = kDenominator / 2; - int error_ab = (error == 0 ? 0 : 1); - int fixed_error = kDenominator / 2; - error += error_b + error_ab + fixed_error; - - old_e = input.e(); - input.Normalize(); - error <<= old_e - input.e(); - - int order_of_magnitude = DiyFp::kSignificandSize + input.e(); - int effective_significand_size = - Double::SignificandSizeForOrderOfMagnitude(order_of_magnitude); - int precision_digits_count = - DiyFp::kSignificandSize - effective_significand_size; - if (precision_digits_count + kDenominatorLog >= DiyFp::kSignificandSize) { - int shift_amount = (precision_digits_count + kDenominatorLog) - - DiyFp::kSignificandSize + 1; - input.set_f(input.f() >> shift_amount); - input.set_e(input.e() + shift_amount); - error = (error >> shift_amount) + 1 + kDenominator; - precision_digits_count -= shift_amount; - } - assert(DiyFp::kSignificandSize == 64); - assert(precision_digits_count < 64); - uint64_t one64 = 1; - uint64_t precision_bits_mask = (one64 << precision_digits_count) - 1; - uint64_t precision_bits = input.f() & precision_bits_mask; - uint64_t half_way = one64 << (precision_digits_count - 1); - precision_bits *= kDenominator; - half_way *= kDenominator; - DiyFp rounded_input(input.f() >> precision_digits_count, - input.e() + precision_digits_count); - if (precision_bits >= half_way + error) { - rounded_input.set_f(rounded_input.f() + 1); - } - *result = Double(rounded_input).value(); - if (half_way - error < precision_bits && precision_bits < half_way + error) { - return false; - } else { - return true; - } - } - - inline int CompareBufferWithDiyFp(Vector buffer, - int exponent, - DiyFp diy_fp) { - assert(buffer.length() + exponent <= kMaxDecimalPower + 1); - assert(buffer.length() + exponent > kMinDecimalPower); - assert(buffer.length() <= kMaxSignificantDecimalDigits); - assert(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits); - Bignum buffer_bignum; - Bignum diy_fp_bignum; - buffer_bignum.AssignDecimalString(buffer); - diy_fp_bignum.AssignUInt64(diy_fp.f()); - if (exponent >= 0) { - buffer_bignum.MultiplyByPowerOfTen(exponent); - } else { - diy_fp_bignum.MultiplyByPowerOfTen(-exponent); - } - if (diy_fp.e() > 0) { - diy_fp_bignum.ShiftLeft(diy_fp.e()); - } else { - buffer_bignum.ShiftLeft(-diy_fp.e()); - } - return Bignum::Compare(buffer_bignum, diy_fp_bignum); - } - - inline bool ComputeGuess(Vector trimmed, int exponent, - double* guess) { - if (trimmed.length() == 0) { - *guess = 0.0; - return true; - } - if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) { - *guess = Double::Infinity(); - return true; - } - if (exponent + trimmed.length() <= kMinDecimalPower) { - *guess = 0.0; - return true; - } - - if (DoubleStrtod(trimmed, exponent, guess) || - DiyFpStrtod(trimmed, exponent, guess)) { - return true; - } - if (*guess == Double::Infinity()) { - return true; - } - return false; - } - - inline double Strtod( Vector< const char > buffer, int exponent ) - { - double guess; - if (ComputeGuess(buffer, exponent, &guess)) { - return guess; - } - DiyFp upper_boundary = Double(guess).UpperBoundary(); - int comparison = CompareBufferWithDiyFp(buffer, exponent, upper_boundary); - if (comparison < 0) { - return guess; - } else if (comparison > 0) { - return Double(guess).NextDouble(); - } else if ((Double(guess).Significand() & 1) == 0) { - return guess; - } else { - return Double(guess).NextDouble(); - } - } - -} // namespace tao::json::double_conversion - -#endif diff --git a/include/tao/json/external/itoa.hpp b/include/tao/json/external/itoa.hpp deleted file mode 100644 index 5e3afde9..00000000 --- a/include/tao/json/external/itoa.hpp +++ /dev/null @@ -1,149 +0,0 @@ -// This header include/tao/json/external/jeaiii.hpp contains -// modified portions of the jeaiii/itoa library from -// https://github.com/jeaiii/itoa -// which is licensed as follows: - -// Copyright (c) 2017 James Edward Anhalt III - https://github.com/jeaiii/itoa -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef TAO_JSON_EXTERNAL_ITOA_HPP -#define TAO_JSON_EXTERNAL_ITOA_HPP - -#include -#include - -// form a 4.32 fixed point number: t = u * 2^32 / 10^log10(u) -// use as much precision as possible when needed (log10(u) >= 5) -// so shift up then down afterwards by log10(u) * log2(10) ~= 53/16 -// need to round up before and or after in some cases -// once we have the fixed point number we can read off the digit in the upper 32 bits -// and multiply the lower 32 bits by 10 to get the next digit and so on -// we can do 2 digits at a time by multiplying by 100 each time - -// MISSING: -// - x64 optimized version (no need to line up on 32bit boundary, so can multiply by 5 instead of 10 using lea instruction) -// - full 64 bit LG() -// - try splitting the number into chucks that can be processed independently -// - try odd digit first -// - try writing 4 chars at a time - -namespace tao::json::itoa -{ - struct pair - { - char t; - char o; - }; - - // clang-format off -#define TAO_JSON_ITOA_P( T ) { T, '0' }, { T, '1' }, { T, '2' }, { T, '3' }, { T, '4' }, { T, '5' }, { T, '6' }, { T, '7' }, { T, '8' }, { T, '9' } - // clang-format on - - static const pair s_pairs[] = { TAO_JSON_ITOA_P( '0' ), - TAO_JSON_ITOA_P( '1' ), - TAO_JSON_ITOA_P( '2' ), - TAO_JSON_ITOA_P( '3' ), - TAO_JSON_ITOA_P( '4' ), - TAO_JSON_ITOA_P( '5' ), - TAO_JSON_ITOA_P( '6' ), - TAO_JSON_ITOA_P( '7' ), - TAO_JSON_ITOA_P( '8' ), - TAO_JSON_ITOA_P( '9' ) }; - -#define TAO_JSON_ITOA_W( N, I ) *(pair*)&b[ N ] = s_pairs[ I ] -#define TAO_JSON_ITOA_A( N ) t = ( std::uint64_t( 1 ) << ( 32 + N / 5 * N * 53 / 16 ) ) / std::uint32_t( 1e##N ) + 1 + N / 6 - N / 8, t *= u, t >>= N / 5 * N * 53 / 16, t += N / 6 * 4, TAO_JSON_ITOA_W( 0, t >> 32 ) -#define TAO_JSON_ITOA_S( N ) b[ N ] = char( std::uint64_t( 10 ) * std::uint32_t( t ) >> 32 ) + '0' -#define TAO_JSON_ITOA_D( N ) t = std::uint64_t( 100 ) * std::uint32_t( t ), TAO_JSON_ITOA_W( N, t >> 32 ) - -#define TAO_JSON_ITOA_L0 b[ 0 ] = char( u ) + '0' -#define TAO_JSON_ITOA_L1 TAO_JSON_ITOA_W( 0, u ) -#define TAO_JSON_ITOA_L2 TAO_JSON_ITOA_A( 1 ), TAO_JSON_ITOA_S( 2 ) -#define TAO_JSON_ITOA_L3 TAO_JSON_ITOA_A( 2 ), TAO_JSON_ITOA_D( 2 ) -#define TAO_JSON_ITOA_L4 TAO_JSON_ITOA_A( 3 ), TAO_JSON_ITOA_D( 2 ), TAO_JSON_ITOA_S( 4 ) -#define TAO_JSON_ITOA_L5 TAO_JSON_ITOA_A( 4 ), TAO_JSON_ITOA_D( 2 ), TAO_JSON_ITOA_D( 4 ) -#define TAO_JSON_ITOA_L6 TAO_JSON_ITOA_A( 5 ), TAO_JSON_ITOA_D( 2 ), TAO_JSON_ITOA_D( 4 ), TAO_JSON_ITOA_S( 6 ) -#define TAO_JSON_ITOA_L7 TAO_JSON_ITOA_A( 6 ), TAO_JSON_ITOA_D( 2 ), TAO_JSON_ITOA_D( 4 ), TAO_JSON_ITOA_D( 6 ) -#define TAO_JSON_ITOA_L8 TAO_JSON_ITOA_A( 7 ), TAO_JSON_ITOA_D( 2 ), TAO_JSON_ITOA_D( 4 ), TAO_JSON_ITOA_D( 6 ), TAO_JSON_ITOA_S( 8 ) -#define TAO_JSON_ITOA_L9 TAO_JSON_ITOA_A( 8 ), TAO_JSON_ITOA_D( 2 ), TAO_JSON_ITOA_D( 4 ), TAO_JSON_ITOA_D( 6 ), TAO_JSON_ITOA_D( 8 ) - -#define TAO_JSON_ITOA_LN( N ) ( TAO_JSON_ITOA_L##N, b += N + 1 ) - -#define TAO_JSON_ITOA_LG( F ) ( u < 100 ? u < 10 ? F( 0 ) : F( 1 ) : u < 1000000 ? u < 10000 ? u < 1000 ? F( 2 ) : F( 3 ) : u < 100000 ? F( 4 ) : F( 5 ) : u < 100000000 ? u < 10000000 ? F( 6 ) : F( 7 ) : u < 1000000000 ? F( 8 ) : F( 9 ) ) - - inline char* u32toa( const std::uint32_t u, char* b ) - { - std::uint64_t t; - return TAO_JSON_ITOA_LG( TAO_JSON_ITOA_LN ); - } - - inline char* i32toa( const std::int32_t i, char* b ) - { - const std::uint32_t u = i < 0 ? ( *b++ = '-', 0 - std::uint32_t( i ) ) : i; - std::uint64_t t; - return TAO_JSON_ITOA_LG( TAO_JSON_ITOA_LN ); - } - - inline char* u64toa( const std::uint64_t n, char* b ) - { - std::uint32_t u; - std::uint64_t t; - - if( std::uint32_t( n >> 32 ) == 0 ) { - return u = std::uint32_t( n ), TAO_JSON_ITOA_LG( TAO_JSON_ITOA_LN ); - } - std::uint64_t a = n / 100000000; - - if( std::uint32_t( a >> 32 ) == 0 ) { - u = std::uint32_t( a ); - TAO_JSON_ITOA_LG( TAO_JSON_ITOA_LN ); - } - else { - u = std::uint32_t( a / 100000000 ); - TAO_JSON_ITOA_LG( TAO_JSON_ITOA_LN ); - u = a % 100000000; - TAO_JSON_ITOA_LN( 7 ); - } - u = n % 100000000; - return TAO_JSON_ITOA_LN( 7 ); - } - - inline char* i64toa( const std::int64_t i, char* b ) - { - const std::uint64_t n = i < 0 ? ( *b++ = '-', 0 - std::uint64_t( i ) ) : i; - return u64toa( n, b ); - } - - inline void i64tos( std::ostream& o, const std::int64_t i ) - { - char b[ 24 ]; - const auto* s = i64toa( i, b ); - o.write( b, s - b ); - } - - inline void u64tos( std::ostream& o, const std::uint64_t i ) - { - char b[ 24 ]; - const auto* s = u64toa( i, b ); - o.write( b, s - b ); - } - -} // namespace tao::json::itoa - -#endif diff --git a/include/tao/json/external/pegtl.hpp b/include/tao/json/external/pegtl.hpp deleted file mode 100644 index 414dd7fa..00000000 --- a/include/tao/json/external/pegtl.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_HPP -#define TAO_JSON_PEGTL_HPP - -#include "pegtl/config.hpp" -#include "pegtl/version.hpp" - -#include "pegtl/parse.hpp" - -#include "pegtl/ascii.hpp" -#include "pegtl/rules.hpp" -#include "pegtl/uint16.hpp" -#include "pegtl/uint32.hpp" -#include "pegtl/uint64.hpp" -#include "pegtl/uint8.hpp" -#include "pegtl/utf16.hpp" -#include "pegtl/utf32.hpp" -#include "pegtl/utf8.hpp" - -#include "pegtl/argv_input.hpp" -#include "pegtl/buffer_input.hpp" -#include "pegtl/cstream_input.hpp" -#include "pegtl/istream_input.hpp" -#include "pegtl/memory_input.hpp" -#include "pegtl/read_input.hpp" -#include "pegtl/string_input.hpp" - -// this has to be included *after* the above inputs, -// otherwise the amalgamated header will not work! -#include "pegtl/file_input.hpp" - -#include "pegtl/change_action.hpp" -#include "pegtl/change_action_and_state.hpp" -#include "pegtl/change_action_and_states.hpp" -#include "pegtl/change_control.hpp" -#include "pegtl/change_state.hpp" -#include "pegtl/change_states.hpp" - -#include "pegtl/disable_action.hpp" -#include "pegtl/enable_action.hpp" - -#include "pegtl/discard_input.hpp" -#include "pegtl/discard_input_on_failure.hpp" -#include "pegtl/discard_input_on_success.hpp" - -// The following are not included by -// default because they include . - -// #include "pegtl/analyze.hpp" - -#endif diff --git a/include/tao/json/external/pegtl/analysis/analyze_cycles.hpp b/include/tao/json/external/pegtl/analysis/analyze_cycles.hpp deleted file mode 100644 index 4586d5d0..00000000 --- a/include/tao/json/external/pegtl/analysis/analyze_cycles.hpp +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_ANALYSIS_ANALYZE_CYCLES_HPP -#define TAO_JSON_PEGTL_ANALYSIS_ANALYZE_CYCLES_HPP - -#include - -#include -#include -#include -#include - -#include -#include - -#include "../config.hpp" - -#include "grammar_info.hpp" -#include "insert_guard.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::analysis -{ - struct analyze_cycles_impl - { - protected: - explicit analyze_cycles_impl( const bool verbose ) noexcept - : m_verbose( verbose ), - m_problems( 0 ) - { - } - - const bool m_verbose; - unsigned m_problems; - grammar_info m_info; - std::set< std::string_view > m_stack; - std::map< std::string_view, bool > m_cache; - std::map< std::string_view, bool > m_results; - - [[nodiscard]] std::map< std::string_view, rule_info >::const_iterator find( const std::string_view name ) const noexcept - { - const auto iter = m_info.map.find( name ); - assert( iter != m_info.map.end() ); - return iter; - } - - [[nodiscard]] bool work( const std::map< std::string_view, rule_info >::const_iterator& start, const bool accum ) - { - const auto j = m_cache.find( start->first ); - - if( j != m_cache.end() ) { - return j->second; - } - if( const auto g = insert_guard( m_stack, start->first ) ) { - switch( start->second.type ) { - case rule_type::any: { - bool a = false; - for( const auto& r : start->second.rules ) { - a = a || work( find( r ), accum || a ); - } - return m_cache[ start->first ] = true; - } - case rule_type::opt: { - bool a = false; - for( const auto& r : start->second.rules ) { - a = a || work( find( r ), accum || a ); - } - return m_cache[ start->first ] = false; - } - case rule_type::seq: { - bool a = false; - for( const auto& r : start->second.rules ) { - a = a || work( find( r ), accum || a ); - } - return m_cache[ start->first ] = a; - } - case rule_type::sor: { - bool a = true; - for( const auto& r : start->second.rules ) { - a = a && work( find( r ), accum ); - } - return m_cache[ start->first ] = a; - } - } - throw std::logic_error( "code should be unreachable: invalid rule_type value" ); // LCOV_EXCL_LINE - } - if( !accum ) { - ++m_problems; - if( m_verbose ) { - std::cout << "problem: cycle without progress detected at rule class " << start->first << std::endl; // LCOV_EXCL_LINE - } - } - return m_cache[ start->first ] = accum; - } - }; - - template< typename Grammar > - struct analyze_cycles - : private analyze_cycles_impl - { - explicit analyze_cycles( const bool verbose ) - : analyze_cycles_impl( verbose ) - { - Grammar::analyze_t::template insert< Grammar >( m_info ); - } - - [[nodiscard]] std::size_t problems() - { - for( auto i = m_info.map.begin(); i != m_info.map.end(); ++i ) { - m_results[ i->first ] = work( i, false ); - m_cache.clear(); - } - return m_problems; - } - - template< typename Rule > - [[nodiscard]] bool consumes() const noexcept - { - const auto i = m_results.find( internal::demangle< Rule >() ); - assert( i != m_results.end() ); - return i->second; - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::analysis - -#endif diff --git a/include/tao/json/external/pegtl/analysis/counted.hpp b/include/tao/json/external/pegtl/analysis/counted.hpp deleted file mode 100644 index 5e34638b..00000000 --- a/include/tao/json/external/pegtl/analysis/counted.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_ANALYSIS_COUNTED_HPP -#define TAO_JSON_PEGTL_ANALYSIS_COUNTED_HPP - -#include "../config.hpp" - -#include - -#include "generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::analysis -{ - template< rule_type Type, std::size_t Count, typename... Rules > - struct counted - : generic< ( Count != 0 ) ? Type : rule_type::opt, Rules... > - { - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::analysis - -#endif diff --git a/include/tao/json/external/pegtl/analysis/generic.hpp b/include/tao/json/external/pegtl/analysis/generic.hpp deleted file mode 100644 index 01cd0142..00000000 --- a/include/tao/json/external/pegtl/analysis/generic.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_ANALYSIS_GENERIC_HPP -#define TAO_JSON_PEGTL_ANALYSIS_GENERIC_HPP - -#include "../config.hpp" - -#include "grammar_info.hpp" -#include "insert_rules.hpp" -#include "rule_type.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::analysis -{ - template< rule_type Type, typename... Rules > - struct generic - { - template< typename Name > - static std::string_view insert( grammar_info& g ) - { - const auto [ it, success ] = g.insert< Name >( Type ); - if( success ) { - insert_rules< Rules... >::insert( g, it->second ); - } - return it->first; - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::analysis - -#endif diff --git a/include/tao/json/external/pegtl/analysis/grammar_info.hpp b/include/tao/json/external/pegtl/analysis/grammar_info.hpp deleted file mode 100644 index f1ade3a6..00000000 --- a/include/tao/json/external/pegtl/analysis/grammar_info.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_ANALYSIS_GRAMMAR_INFO_HPP -#define TAO_JSON_PEGTL_ANALYSIS_GRAMMAR_INFO_HPP - -#include -#include -#include - -#include "../config.hpp" -#include "../internal/demangle.hpp" - -#include "rule_info.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::analysis -{ - struct grammar_info - { - using map_t = std::map< std::string_view, rule_info >; - map_t map; - - template< typename Name > - auto insert( const rule_type type ) - { - return map.try_emplace( internal::demangle< Name >(), rule_info( type ) ); - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::analysis - -#endif diff --git a/include/tao/json/external/pegtl/analysis/insert_guard.hpp b/include/tao/json/external/pegtl/analysis/insert_guard.hpp deleted file mode 100644 index 597d4b8c..00000000 --- a/include/tao/json/external/pegtl/analysis/insert_guard.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_ANALYSIS_INSERT_GUARD_HPP -#define TAO_JSON_PEGTL_ANALYSIS_INSERT_GUARD_HPP - -#include - -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::analysis -{ - template< typename C > - class insert_guard - { - public: - insert_guard( C& container, const typename C::value_type& value ) - : m_i( container.insert( value ) ), - m_c( container ) - { - } - - insert_guard( const insert_guard& ) = delete; - insert_guard( insert_guard&& ) = delete; - - ~insert_guard() - { - if( m_i.second ) { - m_c.erase( m_i.first ); - } - } - - void operator=( const insert_guard& ) = delete; - void operator=( insert_guard&& ) = delete; - - explicit operator bool() const noexcept - { - return m_i.second; - } - - private: - const std::pair< typename C::iterator, bool > m_i; - C& m_c; - }; - - template< typename C > - insert_guard( C&, const typename C::value_type& )->insert_guard< C >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::analysis - -#endif diff --git a/include/tao/json/external/pegtl/analysis/insert_rules.hpp b/include/tao/json/external/pegtl/analysis/insert_rules.hpp deleted file mode 100644 index 9cfb51f0..00000000 --- a/include/tao/json/external/pegtl/analysis/insert_rules.hpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_ANALYSIS_INSERT_RULES_HPP -#define TAO_JSON_PEGTL_ANALYSIS_INSERT_RULES_HPP - -#include "../config.hpp" - -#include "grammar_info.hpp" -#include "rule_info.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::analysis -{ - template< typename... Rules > - struct insert_rules - { - static void insert( grammar_info& g, rule_info& r ) - { - ( r.rules.emplace_back( Rules::analyze_t::template insert< Rules >( g ) ), ... ); - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::analysis - -#endif diff --git a/include/tao/json/external/pegtl/analysis/rule_info.hpp b/include/tao/json/external/pegtl/analysis/rule_info.hpp deleted file mode 100644 index 25efeccb..00000000 --- a/include/tao/json/external/pegtl/analysis/rule_info.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_ANALYSIS_RULE_INFO_HPP -#define TAO_JSON_PEGTL_ANALYSIS_RULE_INFO_HPP - -#include -#include - -#include "../config.hpp" - -#include "rule_type.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::analysis -{ - struct rule_info - { - explicit rule_info( const rule_type in_type ) noexcept - : type( in_type ) - { - } - - rule_type type; - std::vector< std::string > rules; - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::analysis - -#endif diff --git a/include/tao/json/external/pegtl/analysis/rule_type.hpp b/include/tao/json/external/pegtl/analysis/rule_type.hpp deleted file mode 100644 index f82f2299..00000000 --- a/include/tao/json/external/pegtl/analysis/rule_type.hpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_ANALYSIS_RULE_TYPE_HPP -#define TAO_JSON_PEGTL_ANALYSIS_RULE_TYPE_HPP - -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::analysis -{ - enum class rule_type : char - { - any, // Consumption-on-success is always true; assumes bounded repetition of conjunction of sub-rules. - opt, // Consumption-on-success not necessarily true; assumes bounded repetition of conjunction of sub-rules. - seq, // Consumption-on-success depends on consumption of (non-zero bounded repetition of) conjunction of sub-rules. - sor // Consumption-on-success depends on consumption of (non-zero bounded repetition of) disjunction of sub-rules. - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::analysis - -#endif diff --git a/include/tao/json/external/pegtl/analyze.hpp b/include/tao/json/external/pegtl/analyze.hpp deleted file mode 100644 index 4b0ff629..00000000 --- a/include/tao/json/external/pegtl/analyze.hpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_ANALYZE_HPP -#define TAO_JSON_PEGTL_ANALYZE_HPP - -#include "config.hpp" - -#include "analysis/analyze_cycles.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - template< typename Rule > - [[nodiscard]] std::size_t analyze( const bool verbose = true ) - { - return analysis::analyze_cycles< Rule >( verbose ).problems(); - } - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/apply_mode.hpp b/include/tao/json/external/pegtl/apply_mode.hpp deleted file mode 100644 index b06b029c..00000000 --- a/include/tao/json/external/pegtl/apply_mode.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_APPLY_MODE_HPP -#define TAO_JSON_PEGTL_APPLY_MODE_HPP - -#include "config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - enum class apply_mode : bool - { - action = true, - nothing = false - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/argv_input.hpp b/include/tao/json/external/pegtl/argv_input.hpp deleted file mode 100644 index bbb6d008..00000000 --- a/include/tao/json/external/pegtl/argv_input.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_ARGV_INPUT_HPP -#define TAO_JSON_PEGTL_ARGV_INPUT_HPP - -#include -#include -#include -#include - -#include "config.hpp" -#include "eol.hpp" -#include "memory_input.hpp" -#include "tracking_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - namespace internal - { - [[nodiscard]] inline std::string make_argv_source( const std::size_t argn ) - { - std::ostringstream os; - os << "argv[" << argn << ']'; - return os.str(); - } - - } // namespace internal - - template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf > - struct argv_input - : memory_input< P, Eol > - { - template< typename T > - argv_input( char** argv, const std::size_t argn, T&& in_source ) - : memory_input< P, Eol >( static_cast< const char* >( argv[ argn ] ), std::forward< T >( in_source ) ) - { - } - - argv_input( char** argv, const std::size_t argn ) - : argv_input( argv, argn, internal::make_argv_source( argn ) ) - { - } - }; - - template< typename... Ts > - argv_input( Ts&&... )->argv_input<>; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/ascii.hpp b/include/tao/json/external/pegtl/ascii.hpp deleted file mode 100644 index 066c2ad5..00000000 --- a/include/tao/json/external/pegtl/ascii.hpp +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_ASCII_HPP -#define TAO_JSON_PEGTL_ASCII_HPP - -#include "config.hpp" -#include "eol.hpp" - -#include "internal/always_false.hpp" -#include "internal/result_on_found.hpp" -#include "internal/rules.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - inline namespace ascii - { - // clang-format off - struct alnum : internal::alnum {}; - struct alpha : internal::alpha {}; - struct any : internal::any< internal::peek_char > {}; - struct blank : internal::one< internal::result_on_found::success, internal::peek_char, ' ', '\t' > {}; - struct digit : internal::range< internal::result_on_found::success, internal::peek_char, '0', '9' > {}; - struct ellipsis : internal::string< '.', '.', '.' > {}; - struct eolf : internal::eolf {}; - template< char... Cs > struct forty_two : internal::rep< 42, internal::one< internal::result_on_found::success, internal::peek_char, Cs... > > {}; - struct identifier_first : internal::identifier_first {}; - struct identifier_other : internal::identifier_other {}; - struct identifier : internal::identifier {}; - template< char... Cs > struct istring : internal::istring< Cs... > {}; - template< char... Cs > struct keyword : internal::seq< internal::string< Cs... >, internal::not_at< internal::identifier_other > > {}; - struct lower : internal::range< internal::result_on_found::success, internal::peek_char, 'a', 'z' > {}; - template< char... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_char, Cs... > {}; - template< char Lo, char Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_char, Lo, Hi > {}; - struct nul : internal::one< internal::result_on_found::success, internal::peek_char, char( 0 ) > {}; - template< char... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_char, Cs... > {}; - struct print : internal::range< internal::result_on_found::success, internal::peek_char, char( 32 ), char( 126 ) > {}; - template< char Lo, char Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_char, Lo, Hi > {}; - template< char... Cs > struct ranges : internal::ranges< internal::peek_char, Cs... > {}; - struct seven : internal::range< internal::result_on_found::success, internal::peek_char, char( 0 ), char( 127 ) > {}; - struct shebang : internal::if_must< false, internal::string< '#', '!' >, internal::until< internal::eolf > > {}; - struct space : internal::one< internal::result_on_found::success, internal::peek_char, ' ', '\n', '\r', '\t', '\v', '\f' > {}; - template< char... Cs > struct string : internal::string< Cs... > {}; - template< char C > struct three : internal::string< C, C, C > {}; - template< char C > struct two : internal::string< C, C > {}; - struct upper : internal::range< internal::result_on_found::success, internal::peek_char, 'A', 'Z' > {}; - struct xdigit : internal::ranges< internal::peek_char, '0', '9', 'a', 'f', 'A', 'F' > {}; - // clang-format on - - template<> - struct keyword<> - { - template< typename Input > - [[nodiscard]] static bool match( Input& /*unused*/ ) noexcept - { - static_assert( internal::always_false< Input >::value, "empty keywords not allowed" ); - return false; - } - }; - - } // namespace ascii - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#include "internal/pegtl_string.hpp" - -#endif diff --git a/include/tao/json/external/pegtl/buffer_input.hpp b/include/tao/json/external/pegtl/buffer_input.hpp deleted file mode 100644 index 2f6ef8c7..00000000 --- a/include/tao/json/external/pegtl/buffer_input.hpp +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_BUFFER_INPUT_HPP -#define TAO_JSON_PEGTL_BUFFER_INPUT_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config.hpp" -#include "eol.hpp" -#include "memory_input.hpp" -#include "position.hpp" -#include "tracking_mode.hpp" - -#include "internal/action_input.hpp" -#include "internal/bump.hpp" -#include "internal/iterator.hpp" -#include "internal/marker.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - template< typename Reader, typename Eol = eol::lf_crlf, typename Source = std::string, std::size_t Chunk = 64 > - class buffer_input - { - public: - using reader_t = Reader; - - using eol_t = Eol; - using source_t = Source; - - using iterator_t = internal::iterator; - - using action_t = internal::action_input< buffer_input >; - - static constexpr std::size_t chunk_size = Chunk; - static constexpr tracking_mode tracking_mode_v = tracking_mode::eager; - - template< typename T, typename... As > - buffer_input( T&& in_source, const std::size_t maximum, As&&... as ) - : m_reader( std::forward< As >( as )... ), - m_maximum( maximum + Chunk ), - m_buffer( new char[ maximum + Chunk ] ), - m_current( m_buffer.get() ), - m_end( m_buffer.get() ), - m_source( std::forward< T >( in_source ) ) - { - static_assert( Chunk, "zero chunk size not implemented" ); - assert( m_maximum > maximum ); // Catches overflow; change to >= when zero chunk size is implemented. - } - - buffer_input( const buffer_input& ) = delete; - buffer_input( buffer_input&& ) = delete; - - ~buffer_input() = default; - - void operator=( const buffer_input& ) = delete; - void operator=( buffer_input&& ) = delete; - - [[nodiscard]] bool empty() - { - require( 1 ); - return m_current.data == m_end; - } - - [[nodiscard]] std::size_t size( const std::size_t amount ) - { - require( amount ); - return buffer_occupied(); - } - - [[nodiscard]] const char* current() const noexcept - { - return m_current.data; - } - - [[nodiscard]] const char* end( const std::size_t amount ) - { - require( amount ); - return m_end; - } - - [[nodiscard]] std::size_t byte() const noexcept - { - return m_current.byte; - } - - [[nodiscard]] std::size_t line() const noexcept - { - return m_current.line; - } - - [[nodiscard]] std::size_t byte_in_line() const noexcept - { - return m_current.byte_in_line; - } - - [[nodiscard]] const Source& source() const noexcept - { - return m_source; - } - - [[nodiscard]] char peek_char( const std::size_t offset = 0 ) const noexcept - { - return m_current.data[ offset ]; - } - - [[nodiscard]] std::uint8_t peek_uint8( const std::size_t offset = 0 ) const noexcept - { - return static_cast< std::uint8_t >( peek_char( offset ) ); - } - - void bump( const std::size_t in_count = 1 ) noexcept - { - internal::bump( m_current, in_count, Eol::ch ); - } - - void bump_in_this_line( const std::size_t in_count = 1 ) noexcept - { - internal::bump_in_this_line( m_current, in_count ); - } - - void bump_to_next_line( const std::size_t in_count = 1 ) noexcept - { - internal::bump_to_next_line( m_current, in_count ); - } - - void discard() noexcept - { - if( m_current.data > m_buffer.get() + Chunk ) { - const auto s = m_end - m_current.data; - std::memmove( m_buffer.get(), m_current.data, s ); - m_current.data = m_buffer.get(); - m_end = m_buffer.get() + s; - } - } - - void require( const std::size_t amount ) - { - if( m_current.data + amount <= m_end ) { - return; - } - if( m_current.data + amount > m_buffer.get() + m_maximum ) { - throw std::overflow_error( "require beyond end of buffer" ); - } - if( const auto r = m_reader( m_end, ( std::min )( buffer_free_after_end(), ( std::max )( amount, Chunk ) ) ) ) { - m_end += r; - } - } - - template< rewind_mode M > - [[nodiscard]] internal::marker< iterator_t, M > mark() noexcept - { - return internal::marker< iterator_t, M >( m_current ); - } - - [[nodiscard]] TAO_JSON_PEGTL_NAMESPACE::position position( const iterator_t& it ) const - { - return TAO_JSON_PEGTL_NAMESPACE::position( it, m_source ); - } - - [[nodiscard]] TAO_JSON_PEGTL_NAMESPACE::position position() const - { - return position( m_current ); - } - - [[nodiscard]] const iterator_t& iterator() const noexcept - { - return m_current; - } - - [[nodiscard]] std::size_t buffer_capacity() const noexcept - { - return m_maximum; - } - - [[nodiscard]] std::size_t buffer_occupied() const noexcept - { - assert( m_end >= m_current.data ); - return std::size_t( m_end - m_current.data ); - } - - [[nodiscard]] std::size_t buffer_free_before_current() const noexcept - { - assert( m_current.data >= m_buffer.get() ); - return std::size_t( m_current.data - m_buffer.get() ); - } - - [[nodiscard]] std::size_t buffer_free_after_end() const noexcept - { - assert( m_buffer.get() + m_maximum >= m_end ); - return std::size_t( m_buffer.get() + m_maximum - m_end ); - } - - private: - Reader m_reader; - std::size_t m_maximum; - std::unique_ptr< char[] > m_buffer; - iterator_t m_current; - char* m_end; - const Source m_source; - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/change_action.hpp b/include/tao/json/external/pegtl/change_action.hpp deleted file mode 100644 index 0738c4b4..00000000 --- a/include/tao/json/external/pegtl/change_action.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CHANGE_ACTION_HPP -#define TAO_JSON_PEGTL_CHANGE_ACTION_HPP - -#include - -#include "apply_mode.hpp" -#include "config.hpp" -#include "nothing.hpp" -#include "rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - template< template< typename... > class NewAction > - struct change_action - : maybe_nothing - { - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - static_assert( !std::is_same_v< Action< void >, NewAction< void > >, "old and new action class templates are identical" ); - return Control< Rule >::template match< A, M, NewAction, Control >( in, st... ); - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/change_action_and_state.hpp b/include/tao/json/external/pegtl/change_action_and_state.hpp deleted file mode 100644 index edcd03a3..00000000 --- a/include/tao/json/external/pegtl/change_action_and_state.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CHANGE_ACTION_AND_STATE_HPP -#define TAO_JSON_PEGTL_CHANGE_ACTION_AND_STATE_HPP - -#include - -#include "apply_mode.hpp" -#include "config.hpp" -#include "match.hpp" -#include "nothing.hpp" -#include "rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - template< template< typename... > class NewAction, typename NewState > - struct change_action_and_state - : maybe_nothing - { - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - static_assert( !std::is_same_v< Action< void >, NewAction< void > >, "old and new action class templates are identical" ); - NewState s( static_cast< const Input& >( in ), st... ); - if( Control< Rule >::template match< A, M, NewAction, Control >( in, s ) ) { - if constexpr( A == apply_mode::action ) { - Action< Rule >::success( static_cast< const Input& >( in ), s, st... ); - } - return true; - } - return false; - } - - template< typename Input, - typename... States > - static void success( const Input& in, NewState& s, States&&... st ) noexcept( noexcept( s.success( in, st... ) ) ) - { - s.success( in, st... ); - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/change_action_and_states.hpp b/include/tao/json/external/pegtl/change_action_and_states.hpp deleted file mode 100644 index e7d5bee2..00000000 --- a/include/tao/json/external/pegtl/change_action_and_states.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CHANGE_ACTION_AND_STATES_HPP -#define TAO_JSON_PEGTL_CHANGE_ACTION_AND_STATES_HPP - -#include -#include - -#include "apply_mode.hpp" -#include "config.hpp" -#include "match.hpp" -#include "nothing.hpp" -#include "rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - template< template< typename... > class NewAction, typename... NewStates > - struct change_action_and_states - : maybe_nothing - { - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - std::size_t... Ns, - typename Input, - typename... States > - [[nodiscard]] static bool match( std::index_sequence< Ns... > /*unused*/, Input& in, States&&... st ) - { - auto t = std::tie( st... ); - if( Control< Rule >::template match< A, M, NewAction, Control >( in, std::get< Ns >( t )... ) ) { - if constexpr( A == apply_mode::action ) { - Action< Rule >::success( static_cast< const Input& >( in ), st... ); - } - return true; - } - return false; - } - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - static_assert( !std::is_same_v< Action< void >, NewAction< void > >, "old and new action class templates are identical" ); - return match< Rule, A, M, Action, Control >( std::index_sequence_for< NewStates... >(), in, NewStates()..., st... ); - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/change_control.hpp b/include/tao/json/external/pegtl/change_control.hpp deleted file mode 100644 index eee03415..00000000 --- a/include/tao/json/external/pegtl/change_control.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CHANGE_CONTROL_HPP -#define TAO_JSON_PEGTL_CHANGE_CONTROL_HPP - -#include "apply_mode.hpp" -#include "config.hpp" -#include "match.hpp" -#include "nothing.hpp" -#include "rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - template< template< typename... > class NewControl > - struct change_control - : maybe_nothing - { - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - return TAO_JSON_PEGTL_NAMESPACE::match< Rule, A, M, Action, NewControl >( in, st... ); - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/change_state.hpp b/include/tao/json/external/pegtl/change_state.hpp deleted file mode 100644 index 9f3f9e52..00000000 --- a/include/tao/json/external/pegtl/change_state.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CHANGE_STATE_HPP -#define TAO_JSON_PEGTL_CHANGE_STATE_HPP - -#include "apply_mode.hpp" -#include "config.hpp" -#include "match.hpp" -#include "nothing.hpp" -#include "rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - template< typename NewState > - struct change_state - : maybe_nothing - { - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - NewState s( static_cast< const Input& >( in ), st... ); - if( TAO_JSON_PEGTL_NAMESPACE::match< Rule, A, M, Action, Control >( in, s ) ) { - if constexpr( A == apply_mode::action ) { - Action< Rule >::success( static_cast< const Input& >( in ), s, st... ); - } - return true; - } - return false; - } - - template< typename Input, - typename... States > - static void success( const Input& in, NewState& s, States&&... st ) noexcept( noexcept( s.success( in, st... ) ) ) - { - s.success( in, st... ); - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/change_states.hpp b/include/tao/json/external/pegtl/change_states.hpp deleted file mode 100644 index ce246977..00000000 --- a/include/tao/json/external/pegtl/change_states.hpp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CHANGE_STATES_HPP -#define TAO_JSON_PEGTL_CHANGE_STATES_HPP - -#include -#include - -#include "apply_mode.hpp" -#include "config.hpp" -#include "match.hpp" -#include "nothing.hpp" -#include "rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - template< typename... NewStates > - struct change_states - : maybe_nothing - { - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - std::size_t... Ns, - typename Input, - typename... States > - [[nodiscard]] static bool match( std::index_sequence< Ns... > /*unused*/, Input& in, States&&... st ) - { - auto t = std::tie( st... ); - if( TAO_JSON_PEGTL_NAMESPACE::match< Rule, A, M, Action, Control >( in, std::get< Ns >( t )... ) ) { - if constexpr( A == apply_mode::action ) { - Action< Rule >::success( static_cast< const Input& >( in ), st... ); - } - return true; - } - return false; - } - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - return match< Rule, A, M, Action, Control >( std::index_sequence_for< NewStates... >(), in, NewStates()..., st... ); - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/config.hpp b/include/tao/json/external/pegtl/config.hpp deleted file mode 100644 index 91cd8e10..00000000 --- a/include/tao/json/external/pegtl/config.hpp +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONFIG_HPP -#define TAO_JSON_PEGTL_CONFIG_HPP - -#if !defined( TAO_JSON_PEGTL_NAMESPACE ) -#define TAO_JSON_PEGTL_NAMESPACE tao::json::pegtl -#endif - -#endif diff --git a/include/tao/json/external/pegtl/contrib/abnf.hpp b/include/tao/json/external/pegtl/contrib/abnf.hpp deleted file mode 100644 index 67e7bbe9..00000000 --- a/include/tao/json/external/pegtl/contrib/abnf.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_ABNF_HPP -#define TAO_JSON_PEGTL_CONTRIB_ABNF_HPP - -#include "../config.hpp" -#include "../internal/rules.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::abnf -{ - // Core ABNF rules according to RFC 5234, Appendix B - - // clang-format off - struct ALPHA : internal::ranges< internal::peek_char, 'a', 'z', 'A', 'Z' > {}; - struct BIT : internal::one< internal::result_on_found::success, internal::peek_char, '0', '1' > {}; - struct CHAR : internal::range< internal::result_on_found::success, internal::peek_char, char( 1 ), char( 127 ) > {}; - struct CR : internal::one< internal::result_on_found::success, internal::peek_char, '\r' > {}; - struct CRLF : internal::string< '\r', '\n' > {}; - struct CTL : internal::ranges< internal::peek_char, char( 0 ), char( 31 ), char( 127 ) > {}; - struct DIGIT : internal::range< internal::result_on_found::success, internal::peek_char, '0', '9' > {}; - struct DQUOTE : internal::one< internal::result_on_found::success, internal::peek_char, '"' > {}; - struct HEXDIG : internal::ranges< internal::peek_char, '0', '9', 'a', 'f', 'A', 'F' > {}; - struct HTAB : internal::one< internal::result_on_found::success, internal::peek_char, '\t' > {}; - struct LF : internal::one< internal::result_on_found::success, internal::peek_char, '\n' > {}; - struct LWSP : internal::star< internal::sor< internal::string< '\r', '\n' >, internal::one< internal::result_on_found::success, internal::peek_char, ' ', '\t' > >, internal::one< internal::result_on_found::success, internal::peek_char, ' ', '\t' > > {}; - struct OCTET : internal::any< internal::peek_char > {}; - struct SP : internal::one< internal::result_on_found::success, internal::peek_char, ' ' > {}; - struct VCHAR : internal::range< internal::result_on_found::success, internal::peek_char, char( 33 ), char( 126 ) > {}; - struct WSP : internal::one< internal::result_on_found::success, internal::peek_char, ' ', '\t' > {}; - // clang-format on - -} // namespace TAO_JSON_PEGTL_NAMESPACE::abnf - -#endif diff --git a/include/tao/json/external/pegtl/contrib/alphabet.hpp b/include/tao/json/external/pegtl/contrib/alphabet.hpp deleted file mode 100644 index 8a10eed0..00000000 --- a/include/tao/json/external/pegtl/contrib/alphabet.hpp +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_ALPHABET_HPP -#define TAO_JSON_PEGTL_CONTRIB_ALPHABET_HPP - -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::alphabet -{ - static const int a = 'a'; - static const int b = 'b'; - static const int c = 'c'; - static const int d = 'd'; - static const int e = 'e'; - static const int f = 'f'; - static const int g = 'g'; - static const int h = 'h'; - static const int i = 'i'; - static const int j = 'j'; - static const int k = 'k'; - static const int l = 'l'; - static const int m = 'm'; - static const int n = 'n'; - static const int o = 'o'; - static const int p = 'p'; - static const int q = 'q'; - static const int r = 'r'; - static const int s = 's'; - static const int t = 't'; - static const int u = 'u'; - static const int v = 'v'; - static const int w = 'w'; - static const int x = 'x'; - static const int y = 'y'; - static const int z = 'z'; - - static const int A = 'A'; // NOLINT(readability-identifier-naming) - static const int B = 'B'; // NOLINT(readability-identifier-naming) - static const int C = 'C'; // NOLINT(readability-identifier-naming) - static const int D = 'D'; // NOLINT(readability-identifier-naming) - static const int E = 'E'; // NOLINT(readability-identifier-naming) - static const int F = 'F'; // NOLINT(readability-identifier-naming) - static const int G = 'G'; // NOLINT(readability-identifier-naming) - static const int H = 'H'; // NOLINT(readability-identifier-naming) - static const int I = 'I'; // NOLINT(readability-identifier-naming) - static const int J = 'J'; // NOLINT(readability-identifier-naming) - static const int K = 'K'; // NOLINT(readability-identifier-naming) - static const int L = 'L'; // NOLINT(readability-identifier-naming) - static const int M = 'M'; // NOLINT(readability-identifier-naming) - static const int N = 'N'; // NOLINT(readability-identifier-naming) - static const int O = 'O'; // NOLINT(readability-identifier-naming) - static const int P = 'P'; // NOLINT(readability-identifier-naming) - static const int Q = 'Q'; // NOLINT(readability-identifier-naming) - static const int R = 'R'; // NOLINT(readability-identifier-naming) - static const int S = 'S'; // NOLINT(readability-identifier-naming) - static const int T = 'T'; // NOLINT(readability-identifier-naming) - static const int U = 'U'; // NOLINT(readability-identifier-naming) - static const int V = 'V'; // NOLINT(readability-identifier-naming) - static const int W = 'W'; // NOLINT(readability-identifier-naming) - static const int X = 'X'; // NOLINT(readability-identifier-naming) - static const int Y = 'Y'; // NOLINT(readability-identifier-naming) - static const int Z = 'Z'; // NOLINT(readability-identifier-naming) - -} // namespace TAO_JSON_PEGTL_NAMESPACE::alphabet - -#endif diff --git a/include/tao/json/external/pegtl/contrib/counter.hpp b/include/tao/json/external/pegtl/contrib/counter.hpp deleted file mode 100644 index 98b80656..00000000 --- a/include/tao/json/external/pegtl/contrib/counter.hpp +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_COUNTER_HPP -#define TAO_JSON_PEGTL_CONTRIB_COUNTER_HPP - -#include -#include - -#include "../config.hpp" -#include "../normal.hpp" - -#include "../internal/demangle.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - struct counter_data - { - unsigned start = 0; - unsigned success = 0; - unsigned failure = 0; - }; - - struct counter_state - { - std::map< std::string_view, counter_data > counts; - }; - - template< typename Rule > - struct counter - : normal< Rule > - { - template< typename Input > - static void start( const Input& /*unused*/, counter_state& ts ) - { - ++ts.counts[ internal::demangle< Rule >() ].start; - } - - template< typename Input > - static void success( const Input& /*unused*/, counter_state& ts ) - { - ++ts.counts[ internal::demangle< Rule >() ].success; - } - - template< typename Input > - static void failure( const Input& /*unused*/, counter_state& ts ) - { - ++ts.counts[ internal::demangle< Rule >() ].failure; - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/contrib/http.hpp b/include/tao/json/external/pegtl/contrib/http.hpp deleted file mode 100644 index f9a24e9f..00000000 --- a/include/tao/json/external/pegtl/contrib/http.hpp +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_HTTP_HPP -#define TAO_JSON_PEGTL_CONTRIB_HTTP_HPP - -#include "../ascii.hpp" -#include "../config.hpp" -#include "../nothing.hpp" -#include "../rules.hpp" -#include "../utf8.hpp" - -#include "abnf.hpp" -#include "remove_first_state.hpp" -#include "uri.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::http -{ - // HTTP 1.1 grammar according to RFC 7230. - - // This grammar is a direct PEG translation of the original HTTP grammar. - // It should be considered experimental -- in case of any issues, in particular - // missing rules for attached actions, please contact the developers. - - using OWS = star< abnf::WSP >; // optional whitespace - using RWS = plus< abnf::WSP >; // required whitespace - using BWS = OWS; // "bad" whitespace - - using obs_text = not_range< 0x00, 0x7F >; - using obs_fold = seq< abnf::CRLF, plus< abnf::WSP > >; - - // clang-format off - struct tchar : sor< abnf::ALPHA, abnf::DIGIT, one< '!', '#', '$', '%', '&', '\'', '*', '+', '-', '.', '^', '_', '`', '|', '~' > > {}; - struct token : plus< tchar > {}; - - struct field_name : token {}; - - struct field_vchar : sor< abnf::VCHAR, obs_text > {}; - struct field_content : list< field_vchar, plus< abnf::WSP > > {}; - struct field_value : star< sor< field_content, obs_fold > > {}; - - struct header_field : seq< field_name, one< ':' >, OWS, field_value, OWS > {}; - - struct method : token {}; - - struct absolute_path : plus< one< '/' >, uri::segment > {}; - - struct origin_form : seq< absolute_path, uri::opt_query > {}; - struct absolute_form : uri::absolute_URI {}; - struct authority_form : uri::authority {}; - struct asterisk_form : one< '*' > {}; - - struct request_target : sor< origin_form, absolute_form, authority_form, asterisk_form > {}; - - struct status_code : rep< 3, abnf::DIGIT > {}; - struct reason_phrase : star< sor< abnf::VCHAR, obs_text, abnf::WSP > > {}; - - struct HTTP_version : if_must< string< 'H', 'T', 'T', 'P', '/' >, abnf::DIGIT, one< '.' >, abnf::DIGIT > {}; - - struct request_line : if_must< method, abnf::SP, request_target, abnf::SP, HTTP_version, abnf::CRLF > {}; - struct status_line : if_must< HTTP_version, abnf::SP, status_code, abnf::SP, reason_phrase, abnf::CRLF > {}; - struct start_line : sor< status_line, request_line > {}; - - struct message_body : star< abnf::OCTET > {}; - struct HTTP_message : seq< start_line, star< header_field, abnf::CRLF >, abnf::CRLF, opt< message_body > > {}; - - struct Content_Length : plus< abnf::DIGIT > {}; - - struct uri_host : uri::host {}; - struct port : uri::port {}; - - struct Host : seq< uri_host, opt< one< ':' >, port > > {}; - - // PEG are different from CFGs! (this replaces ctext and qdtext) - using text = sor< abnf::HTAB, range< 0x20, 0x7E >, obs_text >; - - struct quoted_pair : if_must< one< '\\' >, sor< abnf::VCHAR, obs_text, abnf::WSP > > {}; - struct quoted_string : if_must< abnf::DQUOTE, until< abnf::DQUOTE, sor< quoted_pair, text > > > {}; - - struct transfer_parameter : seq< token, BWS, one< '=' >, BWS, sor< token, quoted_string > > {}; - struct transfer_extension : seq< token, star< OWS, one< ';' >, OWS, transfer_parameter > > {}; - struct transfer_coding : sor< istring< 'c', 'h', 'u', 'n', 'k', 'e', 'd' >, - istring< 'c', 'o', 'm', 'p', 'r', 'e', 's', 's' >, - istring< 'd', 'e', 'f', 'l', 'a', 't', 'e' >, - istring< 'g', 'z', 'i', 'p' >, - transfer_extension > {}; - - struct rank : sor< seq< one< '0' >, opt< one< '.' >, rep_opt< 3, abnf::DIGIT > > >, - seq< one< '1' >, opt< one< '.' >, rep_opt< 3, one< '0' > > > > > {}; - - struct t_ranking : seq< OWS, one< ';' >, OWS, one< 'q', 'Q' >, one< '=' >, rank > {}; - struct t_codings : sor< istring< 't', 'r', 'a', 'i', 'l', 'e', 'r', 's' >, seq< transfer_coding, opt< t_ranking > > > {}; - - struct TE : opt< sor< one< ',' >, t_codings >, star< OWS, one< ',' >, opt< OWS, t_codings > > > {}; - - template< typename T > - using make_comma_list = seq< star< one< ',' >, OWS >, T, star< OWS, one< ',' >, opt< OWS, T > > >; - - struct connection_option : token {}; - struct Connection : make_comma_list< connection_option > {}; - - struct Trailer : make_comma_list< field_name > {}; - - struct Transfer_Encoding : make_comma_list< transfer_coding > {}; - - struct protocol_name : token {}; - struct protocol_version : token {}; - struct protocol : seq< protocol_name, opt< one< '/' >, protocol_version > > {}; - struct Upgrade : make_comma_list< protocol > {}; - - struct pseudonym : token {}; - - struct received_protocol : seq< opt< protocol_name, one< '/' > >, protocol_version > {}; - struct received_by : sor< seq< uri_host, opt< one< ':' >, port > >, pseudonym > {}; - - struct comment : if_must< one< '(' >, until< one< ')' >, sor< comment, quoted_pair, text > > > {}; - - struct Via : make_comma_list< seq< received_protocol, RWS, received_by, opt< RWS, comment > > > {}; - - struct http_URI : if_must< istring< 'h', 't', 't', 'p', ':', '/', '/' >, uri::authority, uri::path_abempty, uri::opt_query, uri::opt_fragment > {}; - struct https_URI : if_must< istring< 'h', 't', 't', 'p', 's', ':', '/', '/' >, uri::authority, uri::path_abempty, uri::opt_query, uri::opt_fragment > {}; - - struct partial_URI : seq< uri::relative_part, uri::opt_query > {}; - - // clang-format on - struct chunk_size - { - using analyze_t = plus< abnf::HEXDIG >::analyze_t; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, std::size_t& size, States&&... /*unused*/ ) - { - size = 0; - std::size_t i = 0; - while( in.size( i + 1 ) >= i + 1 ) { - const auto c = in.peek_char( i ); - if( ( '0' <= c ) && ( c <= '9' ) ) { - size <<= 4; - size |= std::size_t( c - '0' ); - ++i; - continue; - } - if( ( 'a' <= c ) && ( c <= 'f' ) ) { - size <<= 4; - size |= std::size_t( c - 'a' + 10 ); - ++i; - continue; - } - if( ( 'A' <= c ) && ( c <= 'F' ) ) { - size <<= 4; - size |= std::size_t( c - 'A' + 10 ); - ++i; - continue; - } - break; - } - in.bump_in_this_line( i ); - return i > 0; - } - }; - // clang-format off - - struct chunk_ext_name : token {}; - struct chunk_ext_val : sor< quoted_string, token > {}; - struct chunk_ext : star_must< one< ';' >, chunk_ext_name, if_must< one< '=' >, chunk_ext_val > > {}; - - // clang-format on - struct chunk_data - { - using analyze_t = star< abnf::OCTET >::analyze_t; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, const std::size_t size, States&&... /*unused*/ ) - { - if( in.size( size ) >= size ) { - in.bump( size ); - return true; - } - return false; - } - }; - - namespace internal::chunk_helper - { - template< typename Rule, template< typename... > class Control > - struct control - : remove_self_and_first_state< Rule, Control > - {}; - - template< template< typename... > class Control > - struct control< chunk_size, Control > - : remove_first_state_after_match< chunk_size, Control > - {}; - - template< template< typename... > class Control > - struct control< chunk_data, Control > - : remove_first_state_after_match< chunk_data, Control > - {}; - - template< template< typename... > class Control > - struct bind - { - template< typename Rule > - using type = control< Rule, Control >; - }; - - } // namespace internal::chunk_helper - - struct chunk - { - using impl = seq< chunk_size, chunk_ext, abnf::CRLF, chunk_data, abnf::CRLF >; - using analyze_t = impl::analyze_t; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - std::size_t size{}; - return impl::template match< A, M, Action, internal::chunk_helper::bind< Control >::template type >( in, size, st... ); - } - }; - - // clang-format off - struct last_chunk : seq< plus< one< '0' > >, not_at< digit >, chunk_ext, abnf::CRLF > {}; - - struct trailer_part : star< header_field, abnf::CRLF > {}; - - struct chunked_body : seq< until< last_chunk, chunk >, trailer_part, abnf::CRLF > {}; - // clang-format on - -} // namespace TAO_JSON_PEGTL_NAMESPACE::http - -#endif diff --git a/include/tao/json/external/pegtl/contrib/icu/internal.hpp b/include/tao/json/external/pegtl/contrib/icu/internal.hpp deleted file mode 100644 index 726b0de6..00000000 --- a/include/tao/json/external/pegtl/contrib/icu/internal.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_ICU_INTERNAL_HPP -#define TAO_JSON_PEGTL_CONTRIB_ICU_INTERNAL_HPP - -#include - -#include "../../config.hpp" - -#include "../../analysis/generic.hpp" -#include "../../internal/skip_control.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - namespace icu - { - template< typename Peek, UProperty P, bool V = true > - struct binary_property - { - using analyze_t = analysis::generic< analysis::rule_type::any >; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( Peek::max_input_size ) ) ) - { - if( const std::size_t s = in.size( Peek::max_input_size ); s >= Peek::min_input_size ) { - if( const auto r = Peek::peek( in, s ) ) { - if( u_hasBinaryProperty( r.data, P ) == V ) { - in.bump( r.size ); - return true; - } - } - } - return false; - } - }; - - template< typename Peek, UProperty P, int V > - struct property_value - { - using analyze_t = analysis::generic< analysis::rule_type::any >; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( Peek::max_input_size ) ) ) - { - if( const std::size_t s = in.size( Peek::max_input_size ); s >= Peek::min_input_size ) { - if( const auto r = Peek::peek( in, s ) ) { - if( u_getIntPropertyValue( r.data, P ) == V ) { - in.bump( r.size ); - return true; - } - } - } - return false; - } - }; - - } // namespace icu - - template< typename Peek, UProperty P, bool V > - inline constexpr bool skip_control< icu::binary_property< Peek, P, V > > = true; - - template< typename Peek, UProperty P, int V > - inline constexpr bool skip_control< icu::property_value< Peek, P, V > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/contrib/icu/utf16.hpp b/include/tao/json/external/pegtl/contrib/icu/utf16.hpp deleted file mode 100644 index 04af052e..00000000 --- a/include/tao/json/external/pegtl/contrib/icu/utf16.hpp +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_ICU_UTF16_HPP -#define TAO_JSON_PEGTL_CONTRIB_ICU_UTF16_HPP - -#include "internal.hpp" - -#include "../../config.hpp" -#include "../../utf16.hpp" - -#include "../../internal/peek_utf16.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - namespace utf16_be::icu - { - template< UProperty P, bool V = true > - struct binary_property - : internal::icu::binary_property< internal::peek_utf16_be, P, V > - { - }; - - template< UProperty P, int V > - struct property_value - : internal::icu::property_value< internal::peek_utf16_be, P, V > - { - }; - - // clang-format off - struct alphabetic : binary_property< UCHAR_ALPHABETIC > {}; - struct ascii_hex_digit : binary_property< UCHAR_ASCII_HEX_DIGIT > {}; - struct bidi_control : binary_property< UCHAR_BIDI_CONTROL > {}; - struct bidi_mirrored : binary_property< UCHAR_BIDI_MIRRORED > {}; - struct case_sensitive : binary_property< UCHAR_CASE_SENSITIVE > {}; - struct dash : binary_property< UCHAR_DASH > {}; - struct default_ignorable_code_point : binary_property< UCHAR_DEFAULT_IGNORABLE_CODE_POINT > {}; - struct deprecated : binary_property< UCHAR_DEPRECATED > {}; - struct diacritic : binary_property< UCHAR_DIACRITIC > {}; - struct extender : binary_property< UCHAR_EXTENDER > {}; - struct full_composition_exclusion : binary_property< UCHAR_FULL_COMPOSITION_EXCLUSION > {}; - struct grapheme_base : binary_property< UCHAR_GRAPHEME_BASE > {}; - struct grapheme_extend : binary_property< UCHAR_GRAPHEME_EXTEND > {}; - struct grapheme_link : binary_property< UCHAR_GRAPHEME_LINK > {}; - struct hex_digit : binary_property< UCHAR_HEX_DIGIT > {}; - struct hyphen : binary_property< UCHAR_HYPHEN > {}; - struct id_continue : binary_property< UCHAR_ID_CONTINUE > {}; - struct id_start : binary_property< UCHAR_ID_START > {}; - struct ideographic : binary_property< UCHAR_IDEOGRAPHIC > {}; - struct ids_binary_operator : binary_property< UCHAR_IDS_BINARY_OPERATOR > {}; - struct ids_trinary_operator : binary_property< UCHAR_IDS_TRINARY_OPERATOR > {}; - struct join_control : binary_property< UCHAR_JOIN_CONTROL > {}; - struct logical_order_exception : binary_property< UCHAR_LOGICAL_ORDER_EXCEPTION > {}; - struct lowercase : binary_property< UCHAR_LOWERCASE > {}; - struct math : binary_property< UCHAR_MATH > {}; - struct nfc_inert : binary_property< UCHAR_NFC_INERT > {}; - struct nfd_inert : binary_property< UCHAR_NFD_INERT > {}; - struct nfkc_inert : binary_property< UCHAR_NFKC_INERT > {}; - struct nfkd_inert : binary_property< UCHAR_NFKD_INERT > {}; - struct noncharacter_code_point : binary_property< UCHAR_NONCHARACTER_CODE_POINT > {}; - struct pattern_syntax : binary_property< UCHAR_PATTERN_SYNTAX > {}; - struct pattern_white_space : binary_property< UCHAR_PATTERN_WHITE_SPACE > {}; - struct posix_alnum : binary_property< UCHAR_POSIX_ALNUM > {}; - struct posix_blank : binary_property< UCHAR_POSIX_BLANK > {}; - struct posix_graph : binary_property< UCHAR_POSIX_GRAPH > {}; - struct posix_print : binary_property< UCHAR_POSIX_PRINT > {}; - struct posix_xdigit : binary_property< UCHAR_POSIX_XDIGIT > {}; - struct quotation_mark : binary_property< UCHAR_QUOTATION_MARK > {}; - struct radical : binary_property< UCHAR_RADICAL > {}; - struct s_term : binary_property< UCHAR_S_TERM > {}; - struct segment_starter : binary_property< UCHAR_SEGMENT_STARTER > {}; - struct soft_dotted : binary_property< UCHAR_SOFT_DOTTED > {}; - struct terminal_punctuation : binary_property< UCHAR_TERMINAL_PUNCTUATION > {}; - struct unified_ideograph : binary_property< UCHAR_UNIFIED_IDEOGRAPH > {}; - struct uppercase : binary_property< UCHAR_UPPERCASE > {}; - struct variation_selector : binary_property< UCHAR_VARIATION_SELECTOR > {}; - struct white_space : binary_property< UCHAR_WHITE_SPACE > {}; - struct xid_continue : binary_property< UCHAR_XID_CONTINUE > {}; - struct xid_start : binary_property< UCHAR_XID_START > {}; - - template< UCharDirection V > struct bidi_class : property_value< UCHAR_BIDI_CLASS, V > {}; - template< UBlockCode V > struct block : property_value< UCHAR_BLOCK, V > {}; - template< UDecompositionType V > struct decomposition_type : property_value< UCHAR_DECOMPOSITION_TYPE, V > {}; - template< UEastAsianWidth V > struct east_asian_width : property_value< UCHAR_EAST_ASIAN_WIDTH, V > {}; - template< UCharCategory V > struct general_category : property_value< UCHAR_GENERAL_CATEGORY, V > {}; - template< UGraphemeClusterBreak V > struct grapheme_cluster_break : property_value< UCHAR_GRAPHEME_CLUSTER_BREAK, V > {}; - template< UHangulSyllableType V > struct hangul_syllable_type : property_value< UCHAR_HANGUL_SYLLABLE_TYPE, V > {}; - template< UJoiningGroup V > struct joining_group : property_value< UCHAR_JOINING_GROUP, V > {}; - template< UJoiningType V > struct joining_type : property_value< UCHAR_JOINING_TYPE, V > {}; - template< ULineBreak V > struct line_break : property_value< UCHAR_LINE_BREAK, V > {}; - // UNormalizationCheckResult requires an additional header : - // template< UNormalizationCheckResult V > struct nfc_quick_check : property_value< UCHAR_NFC_QUICK_CHECK, V > {}; - // template< UNormalizationCheckResult V > struct nfd_quick_check : property_value< UCHAR_NFD_QUICK_CHECK, V > {}; - // template< UNormalizationCheckResult V > struct nfkc_quick_check : property_value< UCHAR_NFKC_QUICK_CHECK, V > {}; - // template< UNormalizationCheckResult V > struct nfkd_quick_check : property_value< UCHAR_NFKD_QUICK_CHECK, V > {}; - template< UNumericType V > struct numeric_type : property_value< UCHAR_NUMERIC_TYPE, V > {}; - template< USentenceBreak V > struct sentence_break : property_value< UCHAR_SENTENCE_BREAK, V > {}; - template< UWordBreakValues V > struct word_break : property_value< UCHAR_WORD_BREAK, V > {}; - - template< std::uint8_t V > struct canonical_combining_class : property_value< UCHAR_CANONICAL_COMBINING_CLASS, V > {}; - template< std::uint8_t V > struct lead_canonical_combining_class : property_value< UCHAR_LEAD_CANONICAL_COMBINING_CLASS, V > {}; - template< std::uint8_t V > struct trail_canonical_combining_class : property_value< UCHAR_TRAIL_CANONICAL_COMBINING_CLASS, V > {}; - // clang-format on - - } // namespace utf16_be::icu - - namespace utf16_le::icu - { - template< UProperty P, bool V = true > - struct binary_property - : internal::icu::binary_property< internal::peek_utf16_le, P, V > - { - }; - - template< UProperty P, int V > - struct property_value - : internal::icu::property_value< internal::peek_utf16_le, P, V > - { - }; - - // clang-format off - struct alphabetic : binary_property< UCHAR_ALPHABETIC > {}; - struct ascii_hex_digit : binary_property< UCHAR_ASCII_HEX_DIGIT > {}; - struct bidi_control : binary_property< UCHAR_BIDI_CONTROL > {}; - struct bidi_mirrored : binary_property< UCHAR_BIDI_MIRRORED > {}; - struct case_sensitive : binary_property< UCHAR_CASE_SENSITIVE > {}; - struct dash : binary_property< UCHAR_DASH > {}; - struct default_ignorable_code_point : binary_property< UCHAR_DEFAULT_IGNORABLE_CODE_POINT > {}; - struct deprecated : binary_property< UCHAR_DEPRECATED > {}; - struct diacritic : binary_property< UCHAR_DIACRITIC > {}; - struct extender : binary_property< UCHAR_EXTENDER > {}; - struct full_composition_exclusion : binary_property< UCHAR_FULL_COMPOSITION_EXCLUSION > {}; - struct grapheme_base : binary_property< UCHAR_GRAPHEME_BASE > {}; - struct grapheme_extend : binary_property< UCHAR_GRAPHEME_EXTEND > {}; - struct grapheme_link : binary_property< UCHAR_GRAPHEME_LINK > {}; - struct hex_digit : binary_property< UCHAR_HEX_DIGIT > {}; - struct hyphen : binary_property< UCHAR_HYPHEN > {}; - struct id_continue : binary_property< UCHAR_ID_CONTINUE > {}; - struct id_start : binary_property< UCHAR_ID_START > {}; - struct ideographic : binary_property< UCHAR_IDEOGRAPHIC > {}; - struct ids_binary_operator : binary_property< UCHAR_IDS_BINARY_OPERATOR > {}; - struct ids_trinary_operator : binary_property< UCHAR_IDS_TRINARY_OPERATOR > {}; - struct join_control : binary_property< UCHAR_JOIN_CONTROL > {}; - struct logical_order_exception : binary_property< UCHAR_LOGICAL_ORDER_EXCEPTION > {}; - struct lowercase : binary_property< UCHAR_LOWERCASE > {}; - struct math : binary_property< UCHAR_MATH > {}; - struct nfc_inert : binary_property< UCHAR_NFC_INERT > {}; - struct nfd_inert : binary_property< UCHAR_NFD_INERT > {}; - struct nfkc_inert : binary_property< UCHAR_NFKC_INERT > {}; - struct nfkd_inert : binary_property< UCHAR_NFKD_INERT > {}; - struct noncharacter_code_point : binary_property< UCHAR_NONCHARACTER_CODE_POINT > {}; - struct pattern_syntax : binary_property< UCHAR_PATTERN_SYNTAX > {}; - struct pattern_white_space : binary_property< UCHAR_PATTERN_WHITE_SPACE > {}; - struct posix_alnum : binary_property< UCHAR_POSIX_ALNUM > {}; - struct posix_blank : binary_property< UCHAR_POSIX_BLANK > {}; - struct posix_graph : binary_property< UCHAR_POSIX_GRAPH > {}; - struct posix_print : binary_property< UCHAR_POSIX_PRINT > {}; - struct posix_xdigit : binary_property< UCHAR_POSIX_XDIGIT > {}; - struct quotation_mark : binary_property< UCHAR_QUOTATION_MARK > {}; - struct radical : binary_property< UCHAR_RADICAL > {}; - struct s_term : binary_property< UCHAR_S_TERM > {}; - struct segment_starter : binary_property< UCHAR_SEGMENT_STARTER > {}; - struct soft_dotted : binary_property< UCHAR_SOFT_DOTTED > {}; - struct terminal_punctuation : binary_property< UCHAR_TERMINAL_PUNCTUATION > {}; - struct unified_ideograph : binary_property< UCHAR_UNIFIED_IDEOGRAPH > {}; - struct uppercase : binary_property< UCHAR_UPPERCASE > {}; - struct variation_selector : binary_property< UCHAR_VARIATION_SELECTOR > {}; - struct white_space : binary_property< UCHAR_WHITE_SPACE > {}; - struct xid_continue : binary_property< UCHAR_XID_CONTINUE > {}; - struct xid_start : binary_property< UCHAR_XID_START > {}; - - template< UCharDirection V > struct bidi_class : property_value< UCHAR_BIDI_CLASS, V > {}; - template< UBlockCode V > struct block : property_value< UCHAR_BLOCK, V > {}; - template< UDecompositionType V > struct decomposition_type : property_value< UCHAR_DECOMPOSITION_TYPE, V > {}; - template< UEastAsianWidth V > struct east_asian_width : property_value< UCHAR_EAST_ASIAN_WIDTH, V > {}; - template< UCharCategory V > struct general_category : property_value< UCHAR_GENERAL_CATEGORY, V > {}; - template< UGraphemeClusterBreak V > struct grapheme_cluster_break : property_value< UCHAR_GRAPHEME_CLUSTER_BREAK, V > {}; - template< UHangulSyllableType V > struct hangul_syllable_type : property_value< UCHAR_HANGUL_SYLLABLE_TYPE, V > {}; - template< UJoiningGroup V > struct joining_group : property_value< UCHAR_JOINING_GROUP, V > {}; - template< UJoiningType V > struct joining_type : property_value< UCHAR_JOINING_TYPE, V > {}; - template< ULineBreak V > struct line_break : property_value< UCHAR_LINE_BREAK, V > {}; - // UNormalizationCheckResult requires an additional header : - // template< UNormalizationCheckResult V > struct nfc_quick_check : property_value< UCHAR_NFC_QUICK_CHECK, V > {}; - // template< UNormalizationCheckResult V > struct nfd_quick_check : property_value< UCHAR_NFD_QUICK_CHECK, V > {}; - // template< UNormalizationCheckResult V > struct nfkc_quick_check : property_value< UCHAR_NFKC_QUICK_CHECK, V > {}; - // template< UNormalizationCheckResult V > struct nfkd_quick_check : property_value< UCHAR_NFKD_QUICK_CHECK, V > {}; - template< UNumericType V > struct numeric_type : property_value< UCHAR_NUMERIC_TYPE, V > {}; - template< USentenceBreak V > struct sentence_break : property_value< UCHAR_SENTENCE_BREAK, V > {}; - template< UWordBreakValues V > struct word_break : property_value< UCHAR_WORD_BREAK, V > {}; - - template< std::uint8_t V > struct canonical_combining_class : property_value< UCHAR_CANONICAL_COMBINING_CLASS, V > {}; - template< std::uint8_t V > struct lead_canonical_combining_class : property_value< UCHAR_LEAD_CANONICAL_COMBINING_CLASS, V > {}; - template< std::uint8_t V > struct trail_canonical_combining_class : property_value< UCHAR_TRAIL_CANONICAL_COMBINING_CLASS, V > {}; - // clang-format on - - } // namespace utf16_le::icu - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/contrib/icu/utf32.hpp b/include/tao/json/external/pegtl/contrib/icu/utf32.hpp deleted file mode 100644 index eebcd130..00000000 --- a/include/tao/json/external/pegtl/contrib/icu/utf32.hpp +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_ICU_UTF32_HPP -#define TAO_JSON_PEGTL_CONTRIB_ICU_UTF32_HPP - -#include "internal.hpp" - -#include "../../config.hpp" -#include "../../utf32.hpp" - -#include "../../internal/peek_utf32.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - namespace utf32_be::icu - { - template< UProperty P, bool V = true > - struct binary_property - : internal::icu::binary_property< internal::peek_utf32_be, P, V > - { - }; - - template< UProperty P, int V > - struct property_value - : internal::icu::property_value< internal::peek_utf32_be, P, V > - { - }; - - // clang-format off - struct alphabetic : binary_property< UCHAR_ALPHABETIC > {}; - struct ascii_hex_digit : binary_property< UCHAR_ASCII_HEX_DIGIT > {}; - struct bidi_control : binary_property< UCHAR_BIDI_CONTROL > {}; - struct bidi_mirrored : binary_property< UCHAR_BIDI_MIRRORED > {}; - struct case_sensitive : binary_property< UCHAR_CASE_SENSITIVE > {}; - struct dash : binary_property< UCHAR_DASH > {}; - struct default_ignorable_code_point : binary_property< UCHAR_DEFAULT_IGNORABLE_CODE_POINT > {}; - struct deprecated : binary_property< UCHAR_DEPRECATED > {}; - struct diacritic : binary_property< UCHAR_DIACRITIC > {}; - struct extender : binary_property< UCHAR_EXTENDER > {}; - struct full_composition_exclusion : binary_property< UCHAR_FULL_COMPOSITION_EXCLUSION > {}; - struct grapheme_base : binary_property< UCHAR_GRAPHEME_BASE > {}; - struct grapheme_extend : binary_property< UCHAR_GRAPHEME_EXTEND > {}; - struct grapheme_link : binary_property< UCHAR_GRAPHEME_LINK > {}; - struct hex_digit : binary_property< UCHAR_HEX_DIGIT > {}; - struct hyphen : binary_property< UCHAR_HYPHEN > {}; - struct id_continue : binary_property< UCHAR_ID_CONTINUE > {}; - struct id_start : binary_property< UCHAR_ID_START > {}; - struct ideographic : binary_property< UCHAR_IDEOGRAPHIC > {}; - struct ids_binary_operator : binary_property< UCHAR_IDS_BINARY_OPERATOR > {}; - struct ids_trinary_operator : binary_property< UCHAR_IDS_TRINARY_OPERATOR > {}; - struct join_control : binary_property< UCHAR_JOIN_CONTROL > {}; - struct logical_order_exception : binary_property< UCHAR_LOGICAL_ORDER_EXCEPTION > {}; - struct lowercase : binary_property< UCHAR_LOWERCASE > {}; - struct math : binary_property< UCHAR_MATH > {}; - struct nfc_inert : binary_property< UCHAR_NFC_INERT > {}; - struct nfd_inert : binary_property< UCHAR_NFD_INERT > {}; - struct nfkc_inert : binary_property< UCHAR_NFKC_INERT > {}; - struct nfkd_inert : binary_property< UCHAR_NFKD_INERT > {}; - struct noncharacter_code_point : binary_property< UCHAR_NONCHARACTER_CODE_POINT > {}; - struct pattern_syntax : binary_property< UCHAR_PATTERN_SYNTAX > {}; - struct pattern_white_space : binary_property< UCHAR_PATTERN_WHITE_SPACE > {}; - struct posix_alnum : binary_property< UCHAR_POSIX_ALNUM > {}; - struct posix_blank : binary_property< UCHAR_POSIX_BLANK > {}; - struct posix_graph : binary_property< UCHAR_POSIX_GRAPH > {}; - struct posix_print : binary_property< UCHAR_POSIX_PRINT > {}; - struct posix_xdigit : binary_property< UCHAR_POSIX_XDIGIT > {}; - struct quotation_mark : binary_property< UCHAR_QUOTATION_MARK > {}; - struct radical : binary_property< UCHAR_RADICAL > {}; - struct s_term : binary_property< UCHAR_S_TERM > {}; - struct segment_starter : binary_property< UCHAR_SEGMENT_STARTER > {}; - struct soft_dotted : binary_property< UCHAR_SOFT_DOTTED > {}; - struct terminal_punctuation : binary_property< UCHAR_TERMINAL_PUNCTUATION > {}; - struct unified_ideograph : binary_property< UCHAR_UNIFIED_IDEOGRAPH > {}; - struct uppercase : binary_property< UCHAR_UPPERCASE > {}; - struct variation_selector : binary_property< UCHAR_VARIATION_SELECTOR > {}; - struct white_space : binary_property< UCHAR_WHITE_SPACE > {}; - struct xid_continue : binary_property< UCHAR_XID_CONTINUE > {}; - struct xid_start : binary_property< UCHAR_XID_START > {}; - - template< UCharDirection V > struct bidi_class : property_value< UCHAR_BIDI_CLASS, V > {}; - template< UBlockCode V > struct block : property_value< UCHAR_BLOCK, V > {}; - template< UDecompositionType V > struct decomposition_type : property_value< UCHAR_DECOMPOSITION_TYPE, V > {}; - template< UEastAsianWidth V > struct east_asian_width : property_value< UCHAR_EAST_ASIAN_WIDTH, V > {}; - template< UCharCategory V > struct general_category : property_value< UCHAR_GENERAL_CATEGORY, V > {}; - template< UGraphemeClusterBreak V > struct grapheme_cluster_break : property_value< UCHAR_GRAPHEME_CLUSTER_BREAK, V > {}; - template< UHangulSyllableType V > struct hangul_syllable_type : property_value< UCHAR_HANGUL_SYLLABLE_TYPE, V > {}; - template< UJoiningGroup V > struct joining_group : property_value< UCHAR_JOINING_GROUP, V > {}; - template< UJoiningType V > struct joining_type : property_value< UCHAR_JOINING_TYPE, V > {}; - template< ULineBreak V > struct line_break : property_value< UCHAR_LINE_BREAK, V > {}; - // UNormalizationCheckResult requires an additional header : - // template< UNormalizationCheckResult V > struct nfc_quick_check : property_value< UCHAR_NFC_QUICK_CHECK, V > {}; - // template< UNormalizationCheckResult V > struct nfd_quick_check : property_value< UCHAR_NFD_QUICK_CHECK, V > {}; - // template< UNormalizationCheckResult V > struct nfkc_quick_check : property_value< UCHAR_NFKC_QUICK_CHECK, V > {}; - // template< UNormalizationCheckResult V > struct nfkd_quick_check : property_value< UCHAR_NFKD_QUICK_CHECK, V > {}; - template< UNumericType V > struct numeric_type : property_value< UCHAR_NUMERIC_TYPE, V > {}; - template< USentenceBreak V > struct sentence_break : property_value< UCHAR_SENTENCE_BREAK, V > {}; - template< UWordBreakValues V > struct word_break : property_value< UCHAR_WORD_BREAK, V > {}; - - template< std::uint8_t V > struct canonical_combining_class : property_value< UCHAR_CANONICAL_COMBINING_CLASS, V > {}; - template< std::uint8_t V > struct lead_canonical_combining_class : property_value< UCHAR_LEAD_CANONICAL_COMBINING_CLASS, V > {}; - template< std::uint8_t V > struct trail_canonical_combining_class : property_value< UCHAR_TRAIL_CANONICAL_COMBINING_CLASS, V > {}; - // clang-format on - - } // namespace utf32_be::icu - - namespace utf32_le::icu - { - template< UProperty P, bool V = true > - struct binary_property - : internal::icu::binary_property< internal::peek_utf32_le, P, V > - { - }; - - template< UProperty P, int V > - struct property_value - : internal::icu::property_value< internal::peek_utf32_le, P, V > - { - }; - - // clang-format off - struct alphabetic : binary_property< UCHAR_ALPHABETIC > {}; - struct ascii_hex_digit : binary_property< UCHAR_ASCII_HEX_DIGIT > {}; - struct bidi_control : binary_property< UCHAR_BIDI_CONTROL > {}; - struct bidi_mirrored : binary_property< UCHAR_BIDI_MIRRORED > {}; - struct case_sensitive : binary_property< UCHAR_CASE_SENSITIVE > {}; - struct dash : binary_property< UCHAR_DASH > {}; - struct default_ignorable_code_point : binary_property< UCHAR_DEFAULT_IGNORABLE_CODE_POINT > {}; - struct deprecated : binary_property< UCHAR_DEPRECATED > {}; - struct diacritic : binary_property< UCHAR_DIACRITIC > {}; - struct extender : binary_property< UCHAR_EXTENDER > {}; - struct full_composition_exclusion : binary_property< UCHAR_FULL_COMPOSITION_EXCLUSION > {}; - struct grapheme_base : binary_property< UCHAR_GRAPHEME_BASE > {}; - struct grapheme_extend : binary_property< UCHAR_GRAPHEME_EXTEND > {}; - struct grapheme_link : binary_property< UCHAR_GRAPHEME_LINK > {}; - struct hex_digit : binary_property< UCHAR_HEX_DIGIT > {}; - struct hyphen : binary_property< UCHAR_HYPHEN > {}; - struct id_continue : binary_property< UCHAR_ID_CONTINUE > {}; - struct id_start : binary_property< UCHAR_ID_START > {}; - struct ideographic : binary_property< UCHAR_IDEOGRAPHIC > {}; - struct ids_binary_operator : binary_property< UCHAR_IDS_BINARY_OPERATOR > {}; - struct ids_trinary_operator : binary_property< UCHAR_IDS_TRINARY_OPERATOR > {}; - struct join_control : binary_property< UCHAR_JOIN_CONTROL > {}; - struct logical_order_exception : binary_property< UCHAR_LOGICAL_ORDER_EXCEPTION > {}; - struct lowercase : binary_property< UCHAR_LOWERCASE > {}; - struct math : binary_property< UCHAR_MATH > {}; - struct nfc_inert : binary_property< UCHAR_NFC_INERT > {}; - struct nfd_inert : binary_property< UCHAR_NFD_INERT > {}; - struct nfkc_inert : binary_property< UCHAR_NFKC_INERT > {}; - struct nfkd_inert : binary_property< UCHAR_NFKD_INERT > {}; - struct noncharacter_code_point : binary_property< UCHAR_NONCHARACTER_CODE_POINT > {}; - struct pattern_syntax : binary_property< UCHAR_PATTERN_SYNTAX > {}; - struct pattern_white_space : binary_property< UCHAR_PATTERN_WHITE_SPACE > {}; - struct posix_alnum : binary_property< UCHAR_POSIX_ALNUM > {}; - struct posix_blank : binary_property< UCHAR_POSIX_BLANK > {}; - struct posix_graph : binary_property< UCHAR_POSIX_GRAPH > {}; - struct posix_print : binary_property< UCHAR_POSIX_PRINT > {}; - struct posix_xdigit : binary_property< UCHAR_POSIX_XDIGIT > {}; - struct quotation_mark : binary_property< UCHAR_QUOTATION_MARK > {}; - struct radical : binary_property< UCHAR_RADICAL > {}; - struct s_term : binary_property< UCHAR_S_TERM > {}; - struct segment_starter : binary_property< UCHAR_SEGMENT_STARTER > {}; - struct soft_dotted : binary_property< UCHAR_SOFT_DOTTED > {}; - struct terminal_punctuation : binary_property< UCHAR_TERMINAL_PUNCTUATION > {}; - struct unified_ideograph : binary_property< UCHAR_UNIFIED_IDEOGRAPH > {}; - struct uppercase : binary_property< UCHAR_UPPERCASE > {}; - struct variation_selector : binary_property< UCHAR_VARIATION_SELECTOR > {}; - struct white_space : binary_property< UCHAR_WHITE_SPACE > {}; - struct xid_continue : binary_property< UCHAR_XID_CONTINUE > {}; - struct xid_start : binary_property< UCHAR_XID_START > {}; - - template< UCharDirection V > struct bidi_class : property_value< UCHAR_BIDI_CLASS, V > {}; - template< UBlockCode V > struct block : property_value< UCHAR_BLOCK, V > {}; - template< UDecompositionType V > struct decomposition_type : property_value< UCHAR_DECOMPOSITION_TYPE, V > {}; - template< UEastAsianWidth V > struct east_asian_width : property_value< UCHAR_EAST_ASIAN_WIDTH, V > {}; - template< UCharCategory V > struct general_category : property_value< UCHAR_GENERAL_CATEGORY, V > {}; - template< UGraphemeClusterBreak V > struct grapheme_cluster_break : property_value< UCHAR_GRAPHEME_CLUSTER_BREAK, V > {}; - template< UHangulSyllableType V > struct hangul_syllable_type : property_value< UCHAR_HANGUL_SYLLABLE_TYPE, V > {}; - template< UJoiningGroup V > struct joining_group : property_value< UCHAR_JOINING_GROUP, V > {}; - template< UJoiningType V > struct joining_type : property_value< UCHAR_JOINING_TYPE, V > {}; - template< ULineBreak V > struct line_break : property_value< UCHAR_LINE_BREAK, V > {}; - // UNormalizationCheckResult requires an additional header : - // template< UNormalizationCheckResult V > struct nfc_quick_check : property_value< UCHAR_NFC_QUICK_CHECK, V > {}; - // template< UNormalizationCheckResult V > struct nfd_quick_check : property_value< UCHAR_NFD_QUICK_CHECK, V > {}; - // template< UNormalizationCheckResult V > struct nfkc_quick_check : property_value< UCHAR_NFKC_QUICK_CHECK, V > {}; - // template< UNormalizationCheckResult V > struct nfkd_quick_check : property_value< UCHAR_NFKD_QUICK_CHECK, V > {}; - template< UNumericType V > struct numeric_type : property_value< UCHAR_NUMERIC_TYPE, V > {}; - template< USentenceBreak V > struct sentence_break : property_value< UCHAR_SENTENCE_BREAK, V > {}; - template< UWordBreakValues V > struct word_break : property_value< UCHAR_WORD_BREAK, V > {}; - - template< std::uint8_t V > struct canonical_combining_class : property_value< UCHAR_CANONICAL_COMBINING_CLASS, V > {}; - template< std::uint8_t V > struct lead_canonical_combining_class : property_value< UCHAR_LEAD_CANONICAL_COMBINING_CLASS, V > {}; - template< std::uint8_t V > struct trail_canonical_combining_class : property_value< UCHAR_TRAIL_CANONICAL_COMBINING_CLASS, V > {}; - // clang-format on - - } // namespace utf32_le::icu - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/contrib/icu/utf8.hpp b/include/tao/json/external/pegtl/contrib/icu/utf8.hpp deleted file mode 100644 index a47a2d2a..00000000 --- a/include/tao/json/external/pegtl/contrib/icu/utf8.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_ICU_UTF8_HPP -#define TAO_JSON_PEGTL_CONTRIB_ICU_UTF8_HPP - -#include "internal.hpp" - -#include "../../config.hpp" -#include "../../utf8.hpp" - -#include "../../internal/peek_utf8.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::utf8::icu -{ - template< UProperty P, bool V = true > - struct binary_property - : internal::icu::binary_property< internal::peek_utf8, P, V > - { - }; - - template< UProperty P, int V > - struct property_value - : internal::icu::property_value< internal::peek_utf8, P, V > - { - }; - - // clang-format off - struct alphabetic : binary_property< UCHAR_ALPHABETIC > {}; - struct ascii_hex_digit : binary_property< UCHAR_ASCII_HEX_DIGIT > {}; - struct bidi_control : binary_property< UCHAR_BIDI_CONTROL > {}; - struct bidi_mirrored : binary_property< UCHAR_BIDI_MIRRORED > {}; - struct case_sensitive : binary_property< UCHAR_CASE_SENSITIVE > {}; - struct dash : binary_property< UCHAR_DASH > {}; - struct default_ignorable_code_point : binary_property< UCHAR_DEFAULT_IGNORABLE_CODE_POINT > {}; - struct deprecated : binary_property< UCHAR_DEPRECATED > {}; - struct diacritic : binary_property< UCHAR_DIACRITIC > {}; - struct extender : binary_property< UCHAR_EXTENDER > {}; - struct full_composition_exclusion : binary_property< UCHAR_FULL_COMPOSITION_EXCLUSION > {}; - struct grapheme_base : binary_property< UCHAR_GRAPHEME_BASE > {}; - struct grapheme_extend : binary_property< UCHAR_GRAPHEME_EXTEND > {}; - struct grapheme_link : binary_property< UCHAR_GRAPHEME_LINK > {}; - struct hex_digit : binary_property< UCHAR_HEX_DIGIT > {}; - struct hyphen : binary_property< UCHAR_HYPHEN > {}; - struct id_continue : binary_property< UCHAR_ID_CONTINUE > {}; - struct id_start : binary_property< UCHAR_ID_START > {}; - struct ideographic : binary_property< UCHAR_IDEOGRAPHIC > {}; - struct ids_binary_operator : binary_property< UCHAR_IDS_BINARY_OPERATOR > {}; - struct ids_trinary_operator : binary_property< UCHAR_IDS_TRINARY_OPERATOR > {}; - struct join_control : binary_property< UCHAR_JOIN_CONTROL > {}; - struct logical_order_exception : binary_property< UCHAR_LOGICAL_ORDER_EXCEPTION > {}; - struct lowercase : binary_property< UCHAR_LOWERCASE > {}; - struct math : binary_property< UCHAR_MATH > {}; - struct nfc_inert : binary_property< UCHAR_NFC_INERT > {}; - struct nfd_inert : binary_property< UCHAR_NFD_INERT > {}; - struct nfkc_inert : binary_property< UCHAR_NFKC_INERT > {}; - struct nfkd_inert : binary_property< UCHAR_NFKD_INERT > {}; - struct noncharacter_code_point : binary_property< UCHAR_NONCHARACTER_CODE_POINT > {}; - struct pattern_syntax : binary_property< UCHAR_PATTERN_SYNTAX > {}; - struct pattern_white_space : binary_property< UCHAR_PATTERN_WHITE_SPACE > {}; - struct posix_alnum : binary_property< UCHAR_POSIX_ALNUM > {}; - struct posix_blank : binary_property< UCHAR_POSIX_BLANK > {}; - struct posix_graph : binary_property< UCHAR_POSIX_GRAPH > {}; - struct posix_print : binary_property< UCHAR_POSIX_PRINT > {}; - struct posix_xdigit : binary_property< UCHAR_POSIX_XDIGIT > {}; - struct quotation_mark : binary_property< UCHAR_QUOTATION_MARK > {}; - struct radical : binary_property< UCHAR_RADICAL > {}; - struct s_term : binary_property< UCHAR_S_TERM > {}; - struct segment_starter : binary_property< UCHAR_SEGMENT_STARTER > {}; - struct soft_dotted : binary_property< UCHAR_SOFT_DOTTED > {}; - struct terminal_punctuation : binary_property< UCHAR_TERMINAL_PUNCTUATION > {}; - struct unified_ideograph : binary_property< UCHAR_UNIFIED_IDEOGRAPH > {}; - struct uppercase : binary_property< UCHAR_UPPERCASE > {}; - struct variation_selector : binary_property< UCHAR_VARIATION_SELECTOR > {}; - struct white_space : binary_property< UCHAR_WHITE_SPACE > {}; - struct xid_continue : binary_property< UCHAR_XID_CONTINUE > {}; - struct xid_start : binary_property< UCHAR_XID_START > {}; - - template< UCharDirection V > struct bidi_class : property_value< UCHAR_BIDI_CLASS, V > {}; - template< UBlockCode V > struct block : property_value< UCHAR_BLOCK, V > {}; - template< UDecompositionType V > struct decomposition_type : property_value< UCHAR_DECOMPOSITION_TYPE, V > {}; - template< UEastAsianWidth V > struct east_asian_width : property_value< UCHAR_EAST_ASIAN_WIDTH, V > {}; - template< UCharCategory V > struct general_category : property_value< UCHAR_GENERAL_CATEGORY, V > {}; - template< UGraphemeClusterBreak V > struct grapheme_cluster_break : property_value< UCHAR_GRAPHEME_CLUSTER_BREAK, V > {}; - template< UHangulSyllableType V > struct hangul_syllable_type : property_value< UCHAR_HANGUL_SYLLABLE_TYPE, V > {}; - template< UJoiningGroup V > struct joining_group : property_value< UCHAR_JOINING_GROUP, V > {}; - template< UJoiningType V > struct joining_type : property_value< UCHAR_JOINING_TYPE, V > {}; - template< ULineBreak V > struct line_break : property_value< UCHAR_LINE_BREAK, V > {}; - // UNormalizationCheckResult requires an additional header : - // template< UNormalizationCheckResult V > struct nfc_quick_check : property_value< UCHAR_NFC_QUICK_CHECK, V > {}; - // template< UNormalizationCheckResult V > struct nfd_quick_check : property_value< UCHAR_NFD_QUICK_CHECK, V > {}; - // template< UNormalizationCheckResult V > struct nfkc_quick_check : property_value< UCHAR_NFKC_QUICK_CHECK, V > {}; - // template< UNormalizationCheckResult V > struct nfkd_quick_check : property_value< UCHAR_NFKD_QUICK_CHECK, V > {}; - template< UNumericType V > struct numeric_type : property_value< UCHAR_NUMERIC_TYPE, V > {}; - template< USentenceBreak V > struct sentence_break : property_value< UCHAR_SENTENCE_BREAK, V > {}; - template< UWordBreakValues V > struct word_break : property_value< UCHAR_WORD_BREAK, V > {}; - - template< std::uint8_t V > struct canonical_combining_class : property_value< UCHAR_CANONICAL_COMBINING_CLASS, V > {}; - template< std::uint8_t V > struct lead_canonical_combining_class : property_value< UCHAR_LEAD_CANONICAL_COMBINING_CLASS, V > {}; - template< std::uint8_t V > struct trail_canonical_combining_class : property_value< UCHAR_TRAIL_CANONICAL_COMBINING_CLASS, V > {}; - // clang-format on - -} // namespace TAO_JSON_PEGTL_NAMESPACE::utf8::icu - -#endif diff --git a/include/tao/json/external/pegtl/contrib/if_then.hpp b/include/tao/json/external/pegtl/contrib/if_then.hpp deleted file mode 100644 index 85079031..00000000 --- a/include/tao/json/external/pegtl/contrib/if_then.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_IF_THEN_HPP -#define TAO_JSON_PEGTL_CONTRIB_IF_THEN_HPP - -#include - -#include "../config.hpp" - -#include "../internal/if_then_else.hpp" -#include "../internal/seq.hpp" -#include "../internal/skip_control.hpp" -#include "../internal/trivial.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - namespace internal - { - template< typename Cond, typename Then > - struct if_pair - { - }; - - template< typename... Pairs > - struct if_then; - - template< typename Cond, typename Then, typename... Pairs > - struct if_then< if_pair< Cond, Then >, Pairs... > - : if_then_else< Cond, Then, if_then< Pairs... > > - { - template< typename ElseCond, typename... Thens > - using else_if_then = if_then< if_pair< Cond, Then >, Pairs..., if_pair< ElseCond, seq< Thens... > > >; - - template< typename... Thens > - using else_then = if_then_else< Cond, Then, if_then< Pairs..., if_pair< trivial< true >, seq< Thens... > > > >; - }; - - template<> - struct if_then<> - : trivial< false > - { - }; - - template< typename... Pairs > - inline constexpr bool skip_control< if_then< Pairs... > > = true; - - } // namespace internal - - template< typename Cond, typename... Thens > - using if_then = internal::if_then< internal::if_pair< Cond, internal::seq< Thens... > > >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/contrib/integer.hpp b/include/tao/json/external/pegtl/contrib/integer.hpp deleted file mode 100644 index 332168a2..00000000 --- a/include/tao/json/external/pegtl/contrib/integer.hpp +++ /dev/null @@ -1,446 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_INTEGER_HPP -#define TAO_JSON_PEGTL_CONTRIB_INTEGER_HPP - -#include -#include - -#include - -#include "../ascii.hpp" -#include "../parse.hpp" -#include "../parse_error.hpp" -#include "../rules.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::integer -{ - namespace internal - { - struct unsigned_rule_old - : plus< digit > - { - // Pre-3.0 version of this rule. - }; - - struct unsigned_rule_new - : if_then_else< one< '0' >, not_at< digit >, plus< digit > > - { - // New version that does not allow leading zeros. - }; - - struct signed_rule_old - : seq< opt< one< '-', '+' > >, plus< digit > > - { - // Pre-3.0 version of this rule. - }; - - struct signed_rule_new - : seq< opt< one< '-', '+' > >, if_then_else< one< '0' >, not_at< digit >, plus< digit > > > - { - // New version that does not allow leading zeros. - }; - - struct signed_rule_bis - : seq< opt< one< '-' > >, if_then_else< one< '0' >, not_at< digit >, plus< digit > > > - { - }; - - struct signed_rule_ter - : seq< one< '-', '+' >, if_then_else< one< '0' >, not_at< digit >, plus< digit > > > - { - }; - - [[nodiscard]] constexpr bool is_digit( const char c ) noexcept - { - // We don't use std::isdigit() because it might - // return true for other values on MS platforms. - - return ( '0' <= c ) && ( c <= '9' ); - } - - template< typename Integer, Integer Maximum = ( std::numeric_limits< Integer >::max )() > - [[nodiscard]] constexpr bool accumulate_digit( Integer& result, const char digit ) noexcept - { - // Assumes that digit is a digit as per is_digit(); returns false on overflow. - - static_assert( std::is_integral_v< Integer > ); - - constexpr Integer cutoff = Maximum / 10; - constexpr Integer cutlim = Maximum % 10; - - const Integer c = digit - '0'; - - if( ( result > cutoff ) || ( ( result == cutoff ) && ( c > cutlim ) ) ) { - return false; - } - result *= 10; - result += c; - return true; - } - - template< typename Integer, Integer Maximum = ( std::numeric_limits< Integer >::max )() > - [[nodiscard]] constexpr bool accumulate_digits( Integer& result, const std::string_view input ) noexcept - { - // Assumes input is a non-empty sequence of digits; returns false on overflow. - - for( char c : input ) { - if( !accumulate_digit< Integer, Maximum >( result, c ) ) { - return false; - } - } - return true; - } - - template< typename Integer, Integer Maximum = ( std::numeric_limits< Integer >::max )() > - [[nodiscard]] constexpr bool convert_positive( Integer& result, const std::string_view input ) noexcept - { - // Assumes result == 0 and that input is a non-empty sequence of digits; returns false on overflow. - - static_assert( std::is_integral_v< Integer > ); - return accumulate_digits< Integer, Maximum >( result, input ); - } - - template< typename Signed > - [[nodiscard]] constexpr bool convert_negative( Signed& result, const std::string_view input ) noexcept - { - // Assumes result == 0 and that input is a non-empty sequence of digits; returns false on overflow. - - static_assert( std::is_signed_v< Signed > ); - using Unsigned = std::make_unsigned_t< Signed >; - constexpr Unsigned maximum = static_cast< Unsigned >( ( std::numeric_limits< Signed >::max )() ) + 1; - Unsigned temporary = 0; - if( accumulate_digits< Unsigned, maximum >( temporary, input ) ) { - result = static_cast< Signed >( ~temporary ) + 1; - return true; - } - return false; - } - - template< typename Unsigned, Unsigned Maximum = ( std::numeric_limits< Unsigned >::max )() > - [[nodiscard]] constexpr bool convert_unsigned( Unsigned& result, const std::string_view input ) noexcept - { - // Assumes result == 0 and that input is a non-empty sequence of digits; returns false on overflow. - - static_assert( std::is_unsigned_v< Unsigned > ); - return accumulate_digits< Unsigned, Maximum >( result, input ); - } - - template< typename Signed > - [[nodiscard]] constexpr bool convert_signed( Signed& result, const std::string_view input ) noexcept - { - // Assumes result == 0 and that input is an optional sign followed by a non-empty sequence of digits; returns false on overflow. - - static_assert( std::is_signed_v< Signed > ); - if( input[ 0 ] == '-' ) { - return convert_negative< Signed >( result, std::string_view( input.data() + 1, input.size() - 1 ) ); - } - const auto offset = unsigned( input[ 0 ] == '+' ); - return convert_positive< Signed >( result, std::string_view( input.data() + offset, input.size() - offset ) ); - } - - template< typename Input > - [[nodiscard]] bool match_unsigned( Input& in ) noexcept( noexcept( in.empty() ) ) - { - if( !in.empty() ) { - const char c = in.peek_char(); - if( is_digit( c ) ) { - in.bump_in_this_line(); - if( c == '0' ) { - return in.empty() || ( !is_digit( in.peek_char() ) ); // TODO: Throw exception on digit? - } - while( ( !in.empty() ) && is_digit( in.peek_char() ) ) { - in.bump_in_this_line(); - } - return true; - } - } - return false; - } - - template< typename Input, - typename Unsigned, - Unsigned Maximum = ( std::numeric_limits< Unsigned >::max )() > - [[nodiscard]] bool match_and_convert_unsigned_with_maximum( Input& in, Unsigned& st ) - { - // Assumes st == 0. - - if( !in.empty() ) { - char c = in.peek_char(); - if( is_digit( c ) ) { - if( c == '0' ) { - in.bump_in_this_line(); - return in.empty() || ( !is_digit( in.peek_char() ) ); // TODO: Throw exception on digit? - } - do { - if( !accumulate_digit< Unsigned, Maximum >( st, c ) ) { - throw parse_error( "integer overflow", in ); // Consistent with "as if" an action was doing the conversion. - } - in.bump_in_this_line(); - } while( ( !in.empty() ) && is_digit( c = in.peek_char() ) ); - return true; - } - } - return false; - } - - } // namespace internal - - struct unsigned_action - { - // Assumes that 'in' contains a non-empty sequence of ASCII digits. - - template< typename Input, typename Unsigned > - static auto apply( const Input& in, Unsigned& st ) -> std::enable_if_t< std::is_unsigned_v< Unsigned >, void > - { - // This function "only" offers basic exception safety. - st = 0; - if( !internal::convert_unsigned( st, in.string_view() ) ) { - throw parse_error( "unsigned integer overflow", in ); - } - } - - template< typename Input, typename State > - static auto apply( const Input& in, State& st ) -> std::enable_if_t< std::is_class_v< State >, void > - { - apply( in, st.converted ); // Compatibility for pre-3.0 behaviour. - } - - template< typename Input, typename Unsigned, typename... Ts > - static auto apply( const Input& in, std::vector< Unsigned, Ts... >& st ) -> std::enable_if_t< std::is_unsigned_v< Unsigned >, void > - { - Unsigned u = 0; - apply( in, u ); - st.emplace_back( u ); - } - }; - - struct unsigned_rule - { - using analyze_t = internal::unsigned_rule_new::analyze_t; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.empty() ) ) - { - return internal::match_unsigned( in ); // Does not check for any overflow. - } - }; - - struct unsigned_rule_with_action - { - using analyze_t = internal::unsigned_rule_new::analyze_t; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static auto match( Input& in, States&&... /*unused*/ ) noexcept( noexcept( in.empty() ) ) -> std::enable_if_t< A == apply_mode::nothing, bool > - { - return internal::match_unsigned( in ); // Does not check for any overflow. - } - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename Unsigned > - [[nodiscard]] static auto match( Input& in, Unsigned& st ) -> std::enable_if_t< ( A == apply_mode::action ) && std::is_unsigned_v< Unsigned >, bool > - { - // This function "only" offers basic exception safety. - st = 0; - return internal::match_and_convert_unsigned_with_maximum( in, st ); // Throws on overflow. - } - - // TODO: Overload for st.converted? - // TODO: Overload for std::vector< Unsigned >? - }; - - template< typename Unsigned, Unsigned Maximum > - struct maximum_action - { - // Assumes that 'in' contains a non-empty sequence of ASCII digits. - - static_assert( std::is_unsigned_v< Unsigned > ); - - template< typename Input, typename Unsigned2 > - static auto apply( const Input& in, Unsigned2& st ) -> std::enable_if_t< std::is_same_v< Unsigned, Unsigned2 >, void > - { - // This function "only" offers basic exception safety. - st = 0; - if( !internal::convert_unsigned< Unsigned, Maximum >( st, in.string_view() ) ) { - throw parse_error( "unsigned integer overflow", in ); - } - } - - template< typename Input, typename State > - static auto apply( const Input& in, State& st ) -> std::enable_if_t< std::is_class_v< State >, void > - { - apply( in, st.converted ); // Compatibility for pre-3.0 behaviour. - } - - template< typename Input, typename Unsigned2, typename... Ts > - static auto apply( const Input& in, std::vector< Unsigned2, Ts... >& st ) -> std::enable_if_t< std::is_same_v< Unsigned, Unsigned2 >, void > - { - Unsigned u = 0; - apply( in, u ); - st.emplace_back( u ); - } - }; - - template< typename Unsigned, Unsigned Maximum = ( std::numeric_limits< Unsigned >::max )() > - struct maximum_rule - { - static_assert( std::is_unsigned_v< Unsigned > ); - - using analyze_t = internal::unsigned_rule_new::analyze_t; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) - { - Unsigned st = 0; - return internal::match_and_convert_unsigned_with_maximum< Input, Unsigned, Maximum >( in, st ); // Throws on overflow. - } - }; - - template< typename Unsigned, Unsigned Maximum = ( std::numeric_limits< Unsigned >::max )() > - struct maximum_rule_with_action - { - static_assert( std::is_unsigned_v< Unsigned > ); - - using analyze_t = internal::unsigned_rule_new::analyze_t; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static auto match( Input& in, States&&... /*unused*/ ) -> std::enable_if_t< A == apply_mode::nothing, bool > - { - Unsigned st = 0; - return internal::match_and_convert_unsigned_with_maximum< Input, Unsigned, Maximum >( in, st ); // Throws on overflow. - } - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename Unsigned2 > - [[nodiscard]] static auto match( Input& in, Unsigned2& st ) -> std::enable_if_t< ( A == apply_mode::action ) && std::is_same_v< Unsigned, Unsigned2 >, bool > - { - // This function "only" offers basic exception safety. - st = 0; - return internal::match_and_convert_unsigned_with_maximum< Input, Unsigned, Maximum >( in, st ); // Throws on overflow. - } - - // TODO: Overload for st.converted? - // TODO: Overload for std::vector< Unsigned >? - }; - - struct signed_action - { - // Assumes that 'in' contains a non-empty sequence of ASCII digits, - // with optional leading sign; with sign, in.size() must be >= 2. - - template< typename Input, typename Signed > - static auto apply( const Input& in, Signed& st ) -> std::enable_if_t< std::is_signed_v< Signed >, void > - { - // This function "only" offers basic exception safety. - st = 0; - if( !internal::convert_signed( st, in.string_view() ) ) { - throw parse_error( "signed integer overflow", in ); - } - } - - template< typename Input, typename State > - static auto apply( const Input& in, State& st ) -> std::enable_if_t< std::is_class_v< State >, void > - { - apply( in, st.converted ); // Compatibility for pre-3.0 behaviour. - } - - template< typename Input, typename Signed, typename... Ts > - static auto apply( const Input& in, std::vector< Signed, Ts... >& st ) -> std::enable_if_t< std::is_signed_v< Signed >, void > - { - Signed s = 0; - apply( in, s ); - st.emplace_back( s ); - } - }; - - struct signed_rule - { - using analyze_t = internal::signed_rule_new::analyze_t; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.empty() ) ) - { - return TAO_JSON_PEGTL_NAMESPACE::parse< internal::signed_rule_new >( in ); // Does not check for any overflow. - } - }; - - namespace internal - { - template< typename Rule > - struct signed_action_action - : nothing< Rule > - { - }; - - template<> - struct signed_action_action< signed_rule_new > - : signed_action - { - }; - - } // namespace internal - - struct signed_rule_with_action - { - using analyze_t = internal::signed_rule_new::analyze_t; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static auto match( Input& in, States&&... /*unused*/ ) noexcept( noexcept( in.empty() ) ) -> std::enable_if_t< A == apply_mode::nothing, bool > - { - return TAO_JSON_PEGTL_NAMESPACE::parse< internal::signed_rule_new >( in ); // Does not check for any overflow. - } - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename Signed > - [[nodiscard]] static auto match( Input& in, Signed& st ) -> std::enable_if_t< ( A == apply_mode::action ) && std::is_signed_v< Signed >, bool > - { - return TAO_JSON_PEGTL_NAMESPACE::parse< internal::signed_rule_new, internal::signed_action_action >( in, st ); // Throws on overflow. - } - - // TODO: Overload for st.converted? - // TODO: Overload for std::vector< Signed >? - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::integer - -#endif diff --git a/include/tao/json/external/pegtl/contrib/json.hpp b/include/tao/json/external/pegtl/contrib/json.hpp deleted file mode 100644 index ccdf5ea9..00000000 --- a/include/tao/json/external/pegtl/contrib/json.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_JSON_HPP -#define TAO_JSON_PEGTL_CONTRIB_JSON_HPP - -#include "../ascii.hpp" -#include "../config.hpp" -#include "../rules.hpp" -#include "../utf8.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::json -{ - // JSON grammar according to RFC 8259 - - // clang-format off - struct ws : one< ' ', '\t', '\n', '\r' > {}; - - template< typename R, typename P = ws > - struct padr : internal::seq< R, internal::star< P > > {}; - - struct begin_array : padr< one< '[' > > {}; - struct begin_object : padr< one< '{' > > {}; - struct end_array : one< ']' > {}; - struct end_object : one< '}' > {}; - struct name_separator : pad< one< ':' >, ws > {}; - struct value_separator : padr< one< ',' > > {}; - - struct false_ : string< 'f', 'a', 'l', 's', 'e' > {}; // NOLINT(readability-identifier-naming) - struct null : string< 'n', 'u', 'l', 'l' > {}; - struct true_ : string< 't', 'r', 'u', 'e' > {}; // NOLINT(readability-identifier-naming) - - struct digits : plus< digit > {}; - struct exp : seq< one< 'e', 'E' >, opt< one< '-', '+'> >, must< digits > > {}; - struct frac : if_must< one< '.' >, digits > {}; - struct int_ : sor< one< '0' >, digits > {}; // NOLINT(readability-identifier-naming) - struct number : seq< opt< one< '-' > >, int_, opt< frac >, opt< exp > > {}; - - struct xdigit : pegtl::xdigit {}; - struct unicode : list< seq< one< 'u' >, rep< 4, must< xdigit > > >, one< '\\' > > {}; - struct escaped_char : one< '"', '\\', '/', 'b', 'f', 'n', 'r', 't' > {}; - struct escaped : sor< escaped_char, unicode > {}; - struct unescaped : utf8::range< 0x20, 0x10FFFF > {}; - struct char_ : if_then_else< one< '\\' >, must< escaped >, unescaped > {}; // NOLINT(readability-identifier-naming) - - struct string_content : until< at< one< '"' > >, must< char_ > > {}; - struct string : seq< one< '"' >, must< string_content >, any > - { - using content = string_content; - }; - - struct key_content : until< at< one< '"' > >, must< char_ > > {}; - struct key : seq< one< '"' >, must< key_content >, any > - { - using content = key_content; - }; - - struct value; - - struct array_element; - struct array_content : opt< list_must< array_element, value_separator > > {}; - struct array : seq< begin_array, array_content, must< end_array > > - { - using begin = begin_array; - using end = end_array; - using element = array_element; - using content = array_content; - }; - - struct member : if_must< key, name_separator, value > {}; - struct object_content : opt< list_must< member, value_separator > > {}; - struct object : seq< begin_object, object_content, must< end_object > > - { - using begin = begin_object; - using end = end_object; - using element = member; - using content = object_content; - }; - - struct value : padr< sor< string, number, object, array, false_, true_, null > > {}; - struct array_element : seq< value > {}; - - struct text : seq< star< ws >, value > {}; - // clang-format on - -} // namespace TAO_JSON_PEGTL_NAMESPACE::json - -#endif diff --git a/include/tao/json/external/pegtl/contrib/json_pointer.hpp b/include/tao/json/external/pegtl/contrib/json_pointer.hpp deleted file mode 100644 index 153766fe..00000000 --- a/include/tao/json/external/pegtl/contrib/json_pointer.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_JSON_POINTER_HPP -#define TAO_JSON_PEGTL_CONTRIB_JSON_POINTER_HPP - -#include "../ascii.hpp" -#include "../config.hpp" -#include "../rules.hpp" -#include "../utf8.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::json_pointer -{ - // JSON pointer grammar according to RFC 6901 - - // clang-format off - struct unescaped : utf8::ranges< 0x0, 0x2E, 0x30, 0x7D, 0x7F, 0x10FFFF > {}; - struct escaped : seq< one< '~' >, one< '0', '1' > > {}; - - struct reference_token : star< sor< unescaped, escaped > > {}; - struct json_pointer : star< one< '/' >, reference_token > {}; - // clang-format on - - // relative JSON pointer, see ... - - // clang-format off - struct non_negative_integer : sor< one< '0' >, plus< digit > > {}; - struct relative_json_pointer : seq< non_negative_integer, sor< one< '#' >, json_pointer > > {}; - // clang-format on - -} // namespace TAO_JSON_PEGTL_NAMESPACE::json_pointer - -#endif diff --git a/include/tao/json/external/pegtl/contrib/parse_tree.hpp b/include/tao/json/external/pegtl/contrib/parse_tree.hpp deleted file mode 100644 index 43f9f9ce..00000000 --- a/include/tao/json/external/pegtl/contrib/parse_tree.hpp +++ /dev/null @@ -1,561 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_PARSE_TREE_HPP -#define TAO_JSON_PEGTL_CONTRIB_PARSE_TREE_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../config.hpp" -#include "../memory_input.hpp" -#include "../normal.hpp" -#include "../nothing.hpp" -#include "../parse.hpp" - -#include "../analysis/counted.hpp" -#include "../analysis/generic.hpp" -#include "../internal/demangle.hpp" -#include "../internal/iterator.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::parse_tree -{ - template< typename T > - struct basic_node - { - using node_t = T; - using children_t = std::vector< std::unique_ptr< node_t > >; - children_t children; - - std::string_view type; - std::string source; - - TAO_JSON_PEGTL_NAMESPACE::internal::iterator m_begin; - TAO_JSON_PEGTL_NAMESPACE::internal::iterator m_end; - - // each node will be default constructed - basic_node() = default; - - // no copy/move is necessary - // (nodes are always owned/handled by a std::unique_ptr) - basic_node( const basic_node& ) = delete; - basic_node( basic_node&& ) = delete; - - ~basic_node() = default; - - // no assignment either - basic_node& operator=( const basic_node& ) = delete; - basic_node& operator=( basic_node&& ) = delete; - - [[nodiscard]] bool is_root() const noexcept - { - return type.empty(); - } - - template< typename U > - [[nodiscard]] bool is_type() const noexcept - { - return type == TAO_JSON_PEGTL_NAMESPACE::internal::demangle< U >(); - } - - template< typename U > - void set_type() noexcept - { - type = TAO_JSON_PEGTL_NAMESPACE::internal::demangle< U >(); - } - - [[nodiscard]] position begin() const - { - return position( m_begin, source ); - } - - [[nodiscard]] position end() const - { - return position( m_end, source ); - } - - [[nodiscard]] bool has_content() const noexcept - { - return m_end.data != nullptr; - } - - [[nodiscard]] std::string_view string_view() const noexcept - { - assert( has_content() ); - return std::string_view( m_begin.data, m_end.data - m_begin.data ); - } - - [[nodiscard]] std::string string() const - { - assert( has_content() ); - return std::string( m_begin.data, m_end.data ); - } - - template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf > - [[nodiscard]] memory_input< P, Eol > as_memory_input() const - { - assert( has_content() ); - return { m_begin.data, m_end.data, source, m_begin.byte, m_begin.line, m_begin.byte_in_line }; - } - - template< typename... States > - void remove_content( States&&... /*unused*/ ) noexcept - { - m_end.reset(); - } - - // all non-root nodes are initialized by calling this method - template< typename Rule, typename Input, typename... States > - void start( const Input& in, States&&... /*unused*/ ) - { - set_type< Rule >(); - source = in.source(); - m_begin = TAO_JSON_PEGTL_NAMESPACE::internal::iterator( in.iterator() ); - } - - // if parsing of the rule succeeded, this method is called - template< typename Rule, typename Input, typename... States > - void success( const Input& in, States&&... /*unused*/ ) noexcept - { - m_end = TAO_JSON_PEGTL_NAMESPACE::internal::iterator( in.iterator() ); - } - - // if parsing of the rule failed, this method is called - template< typename Rule, typename Input, typename... States > - void failure( const Input& /*unused*/, States&&... /*unused*/ ) noexcept - { - } - - // if parsing succeeded and the (optional) transform call - // did not discard the node, it is appended to its parent. - // note that "child" is the node whose Rule just succeeded - // and "*this" is the parent where the node should be appended. - template< typename... States > - void emplace_back( std::unique_ptr< node_t >&& child, States&&... /*unused*/ ) - { - assert( child ); - children.emplace_back( std::move( child ) ); - } - }; - - struct node - : basic_node< node > - { - }; - - namespace internal - { - template< typename Node > - struct state - { - std::vector< std::unique_ptr< Node > > stack; - - state() - { - emplace_back(); - } - - void emplace_back() - { - stack.emplace_back( std::make_unique< Node >() ); - } - - [[nodiscard]] std::unique_ptr< Node >& back() noexcept - { - assert( !stack.empty() ); - return stack.back(); - } - - void pop_back() noexcept - { - assert( !stack.empty() ); - return stack.pop_back(); - } - }; - - template< typename Selector, typename... Parameters > - void transform( Parameters&&... /*unused*/ ) noexcept - { - } - - template< typename Selector, typename Input, typename Node, typename... States > - auto transform( const Input& in, std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( Selector::transform( in, n, st... ) ) ) - -> decltype( Selector::transform( in, n, st... ), void() ) - { - Selector::transform( in, n, st... ); - } - - template< typename Selector, typename Input, typename Node, typename... States > - auto transform( const Input& /*unused*/, std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( Selector::transform( n, st... ) ) ) - -> decltype( Selector::transform( n, st... ), void() ) - { - Selector::transform( n, st... ); - } - - template< unsigned Level, typename Analyse, template< typename... > class Selector > - struct is_leaf - : std::false_type - { - }; - - template< analysis::rule_type Type, template< typename... > class Selector > - struct is_leaf< 0, analysis::generic< Type >, Selector > - : std::true_type - { - }; - - template< analysis::rule_type Type, std::size_t Count, template< typename... > class Selector > - struct is_leaf< 0, analysis::counted< Type, Count >, Selector > - : std::true_type - { - }; - - template< analysis::rule_type Type, typename... Rules, template< typename... > class Selector > - struct is_leaf< 0, analysis::generic< Type, Rules... >, Selector > - : std::false_type - { - }; - - template< analysis::rule_type Type, std::size_t Count, typename... Rules, template< typename... > class Selector > - struct is_leaf< 0, analysis::counted< Type, Count, Rules... >, Selector > - : std::false_type - { - }; - - template< unsigned Level, typename Rule, template< typename... > class Selector > - inline constexpr bool is_unselected_leaf = !Selector< Rule >::value && is_leaf< Level, typename Rule::analyze_t, Selector >::value; - - template< unsigned Level, analysis::rule_type Type, typename... Rules, template< typename... > class Selector > - struct is_leaf< Level, analysis::generic< Type, Rules... >, Selector > - : std::bool_constant< ( is_unselected_leaf< Level - 1, Rules, Selector > && ... ) > - { - }; - - template< unsigned Level, analysis::rule_type Type, std::size_t Count, typename... Rules, template< typename... > class Selector > - struct is_leaf< Level, analysis::counted< Type, Count, Rules... >, Selector > - : std::bool_constant< ( is_unselected_leaf< Level - 1, Rules, Selector > && ... ) > - { - }; - - template< typename T > - struct control - { - template< typename Input, typename Tuple, std::size_t... Is > - static void start_impl( const Input& in, const Tuple& t, std::index_sequence< Is... > /*unused*/ ) noexcept( noexcept( T::start( in, std::get< sizeof...( Is ) >( t ), std::get< Is >( t )... ) ) ) - { - T::start( in, std::get< sizeof...( Is ) >( t ), std::get< Is >( t )... ); - } - - template< typename Input, typename... States > - static void start( const Input& in, States&&... st ) noexcept( noexcept( start_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ) ) ) - { - start_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ); - } - - template< typename Input, typename Tuple, std::size_t... Is > - static void success_impl( const Input& in, const Tuple& t, std::index_sequence< Is... > /*unused*/ ) noexcept( noexcept( T::success( in, std::get< sizeof...( Is ) >( t ), std::get< Is >( t )... ) ) ) - { - T::success( in, std::get< sizeof...( Is ) >( t ), std::get< Is >( t )... ); - } - - template< typename Input, typename... States > - static void success( const Input& in, States&&... st ) noexcept( noexcept( success_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ) ) ) - { - success_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ); - } - - template< typename Input, typename Tuple, std::size_t... Is > - static void failure_impl( const Input& in, const Tuple& t, std::index_sequence< Is... > /*unused*/ ) noexcept( noexcept( T::failure( in, std::get< sizeof...( Is ) >( t ), std::get< Is >( t )... ) ) ) - { - T::failure( in, std::get< sizeof...( Is ) >( t ), std::get< Is >( t )... ); - } - - template< typename Input, typename... States > - static void failure( const Input& in, States&&... st ) noexcept( noexcept( failure_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ) ) ) - { - failure_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ); - } - - template< typename Input, typename Tuple, std::size_t... Is > - static void raise_impl( const Input& in, const Tuple& t, std::index_sequence< Is... > /*unused*/ ) noexcept( noexcept( T::raise( in, std::get< Is >( t )... ) ) ) - { - T::raise( in, std::get< Is >( t )... ); - } - - template< typename Input, typename... States > - static void raise( const Input& in, States&&... st ) noexcept( noexcept( raise_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ) ) ) - { - raise_impl( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ); - } - - template< template< typename... > class Action, typename Iterator, typename Input, typename Tuple, std::size_t... Is > - static auto apply_impl( const Iterator& begin, const Input& in, const Tuple& t, std::index_sequence< Is... > /*unused*/ ) noexcept( noexcept( T::template apply< Action >( begin, in, std::get< Is >( t )... ) ) ) - -> decltype( T::template apply< Action >( begin, in, std::get< Is >( t )... ) ) - { - return T::template apply< Action >( begin, in, std::get< Is >( t )... ); - } - - template< template< typename... > class Action, typename Iterator, typename Input, typename... States > - static auto apply( const Iterator& begin, const Input& in, States&&... st ) noexcept( noexcept( apply_impl< Action >( begin, in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ) ) ) - -> decltype( apply_impl< Action >( begin, in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ) ) - { - return apply_impl< Action >( begin, in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ); - } - - template< template< typename... > class Action, typename Input, typename Tuple, std::size_t... Is > - static auto apply0_impl( const Input& in, const Tuple& t, std::index_sequence< Is... > /*unused*/ ) noexcept( noexcept( T::template apply0< Action >( in, std::get< Is >( t )... ) ) ) - -> decltype( T::template apply0< Action >( in, std::get< Is >( t )... ) ) - { - return T::template apply0< Action >( in, std::get< Is >( t )... ); - } - - template< template< typename... > class Action, typename Input, typename... States > - static auto apply0( const Input& in, States&&... st ) noexcept( noexcept( apply0_impl< Action >( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ) ) ) - -> decltype( apply0_impl< Action >( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ) ) - { - return apply0_impl< Action >( in, std::tie( st... ), std::make_index_sequence< sizeof...( st ) - 1 >() ); - } - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - return T::template match< A, M, Action, Control >( in, st... ); - } - }; - - template< typename Node, template< typename... > class Selector, template< typename... > class Control > - struct make_control - { - template< typename Rule, bool, bool > - struct state_handler; - - template< typename Rule > - using type = control< state_handler< Rule, Selector< Rule >::value, is_leaf< 8, typename Rule::analyze_t, Selector >::value > >; - }; - - template< typename Node, template< typename... > class Selector, template< typename... > class Control > - template< typename Rule > - struct make_control< Node, Selector, Control >::state_handler< Rule, false, true > - : Control< Rule > - { - template< typename Input, typename... States > - static void start( const Input& in, state< Node >& /*unused*/, States&&... st ) noexcept( noexcept( Control< Rule >::start( in, st... ) ) ) - { - Control< Rule >::start( in, st... ); - } - - template< typename Input, typename... States > - static void success( const Input& in, state< Node >& /*unused*/, States&&... st ) noexcept( noexcept( Control< Rule >::success( in, st... ) ) ) - { - Control< Rule >::success( in, st... ); - } - - template< typename Input, typename... States > - static void failure( const Input& in, state< Node >& /*unused*/, States&&... st ) noexcept( noexcept( Control< Rule >::failure( in, st... ) ) ) - { - Control< Rule >::failure( in, st... ); - } - }; - - template< typename Node, template< typename... > class Selector, template< typename... > class Control > - template< typename Rule > - struct make_control< Node, Selector, Control >::state_handler< Rule, false, false > - : Control< Rule > - { - template< typename Input, typename... States > - static void start( const Input& in, state< Node >& state, States&&... st ) - { - Control< Rule >::start( in, st... ); - state.emplace_back(); - } - - template< typename Input, typename... States > - static void success( const Input& in, state< Node >& state, States&&... st ) - { - Control< Rule >::success( in, st... ); - auto n = std::move( state.back() ); - state.pop_back(); - for( auto& c : n->children ) { - state.back()->children.emplace_back( std::move( c ) ); - } - } - - template< typename Input, typename... States > - static void failure( const Input& in, state< Node >& state, States&&... st ) noexcept( noexcept( Control< Rule >::failure( in, st... ) ) ) - { - Control< Rule >::failure( in, st... ); - state.pop_back(); - } - }; - - template< typename Node, template< typename... > class Selector, template< typename... > class Control > - template< typename Rule, bool B > - struct make_control< Node, Selector, Control >::state_handler< Rule, true, B > - : Control< Rule > - { - template< typename Input, typename... States > - static void start( const Input& in, state< Node >& state, States&&... st ) - { - Control< Rule >::start( in, st... ); - state.emplace_back(); - state.back()->template start< Rule >( in, st... ); - } - - template< typename Input, typename... States > - static void success( const Input& in, state< Node >& state, States&&... st ) - { - Control< Rule >::success( in, st... ); - auto n = std::move( state.back() ); - state.pop_back(); - n->template success< Rule >( in, st... ); - transform< Selector< Rule > >( in, n, st... ); - if( n ) { - state.back()->emplace_back( std::move( n ), st... ); - } - } - - template< typename Input, typename... States > - static void failure( const Input& in, state< Node >& state, States&&... st ) noexcept( noexcept( Control< Rule >::failure( in, st... ) ) && noexcept( std::declval< Node& >().template failure< Rule >( in, st... ) ) ) - { - Control< Rule >::failure( in, st... ); - state.back()->template failure< Rule >( in, st... ); - state.pop_back(); - } - }; - - template< typename > - using store_all = std::true_type; - - template< typename > - struct selector; - - template< typename T > - struct selector< std::tuple< T > > - { - using type = typename T::type; - }; - - template< typename... Ts > - struct selector< std::tuple< Ts... > > - { - static_assert( sizeof...( Ts ) == 0, "multiple matches found" ); - using type = std::false_type; - }; - - template< typename T > - using selector_t = typename selector< T >::type; - - template< typename Rule, typename Collection > - using select_tuple = std::conditional_t< Collection::template contains< Rule >, std::tuple< Collection >, std::tuple<> >; - - } // namespace internal - - template< typename Rule, typename... Collections > - using selector = internal::selector_t< decltype( std::tuple_cat( std::declval< internal::select_tuple< Rule, Collections > >()... ) ) >; - - template< typename Base > - struct apply - : std::true_type - { - template< typename... Rules > - struct on - { - using type = Base; - - template< typename Rule > - static constexpr bool contains = ( std::is_same_v< Rule, Rules > || ... ); - }; - }; - - struct store_content - : apply< store_content > - {}; - - // some nodes don't need to store their content - struct remove_content - : apply< remove_content > - { - template< typename Node, typename... States > - static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->Node::remove_content( st... ) ) ) - { - n->remove_content( st... ); - } - }; - - // if a node has only one child, replace the node with its child, otherwise remove content - struct fold_one - : apply< fold_one > - { - template< typename Node, typename... States > - static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->children.size(), n->Node::remove_content( st... ) ) ) - { - if( n->children.size() == 1 ) { - n = std::move( n->children.front() ); - } - else { - n->remove_content( st... ); - } - } - }; - - // if a node has no children, discard the node, otherwise remove content - struct discard_empty - : apply< discard_empty > - { - template< typename Node, typename... States > - static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->children.empty(), n->Node::remove_content( st... ) ) ) - { - if( n->children.empty() ) { - n.reset(); - } - else { - n->remove_content( st... ); - } - } - }; - - template< typename Rule, - typename Node, - template< typename... > class Selector = internal::store_all, - template< typename... > class Action = nothing, - template< typename... > class Control = normal, - typename Input, - typename... States > - [[nodiscard]] std::unique_ptr< Node > parse( Input&& in, States&&... st ) - { - internal::state< Node > state; - if( !TAO_JSON_PEGTL_NAMESPACE::parse< Rule, Action, internal::make_control< Node, Selector, Control >::template type >( in, st..., state ) ) { - return nullptr; - } - assert( state.stack.size() == 1 ); - return std::move( state.back() ); - } - - template< typename Rule, - template< typename... > class Selector = internal::store_all, - template< typename... > class Action = nothing, - template< typename... > class Control = normal, - typename Input, - typename... States > - [[nodiscard]] std::unique_ptr< node > parse( Input&& in, States&&... st ) - { - return parse< Rule, node, Selector, Action, Control >( in, st... ); - } - -} // namespace TAO_JSON_PEGTL_NAMESPACE::parse_tree - -#endif diff --git a/include/tao/json/external/pegtl/contrib/parse_tree_to_dot.hpp b/include/tao/json/external/pegtl/contrib/parse_tree_to_dot.hpp deleted file mode 100644 index c4f0eee6..00000000 --- a/include/tao/json/external/pegtl/contrib/parse_tree_to_dot.hpp +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_PARSE_TREE_TO_DOT_HPP -#define TAO_JSON_PEGTL_CONTRIB_PARSE_TREE_TO_DOT_HPP - -#include -#include -#include - -#include "parse_tree.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::parse_tree -{ - namespace internal - { - inline void escape( std::ostream& os, const std::string_view s ) - { - static const char* h = "0123456789abcdef"; - - const char* p = s.data(); - const char* l = p; - const char* const e = s.data() + s.size(); - while( p != e ) { - const unsigned char c = *p; - if( c == '\\' ) { - os.write( l, p - l ); - l = ++p; - os << "\\\\"; - } - else if( c == '"' ) { - os.write( l, p - l ); - l = ++p; - os << "\\\""; - } - else if( c < 32 ) { - os.write( l, p - l ); - l = ++p; - switch( c ) { - case '\b': - os << "\\b"; - break; - case '\f': - os << "\\f"; - break; - case '\n': - os << "\\n"; - break; - case '\r': - os << "\\r"; - break; - case '\t': - os << "\\t"; - break; - default: - os << "\\u00" << h[ ( c & 0xf0 ) >> 4 ] << h[ c & 0x0f ]; - } - } - else if( c == 127 ) { - os.write( l, p - l ); - l = ++p; - os << "\\u007f"; - } - else { - ++p; - } - } - os.write( l, p - l ); - } - - template< typename Node > - void print_dot_node( std::ostream& os, const Node& n, const std::string_view s ) - { - os << " x" << &n << " [ label=\""; - escape( os, s ); - if( n.has_content() ) { - os << "\\n"; - escape( os, n.string_view() ); - } - os << "\" ]\n"; - if( !n.children.empty() ) { - os << " x" << &n << " -> { "; - for( auto& up : n.children ) { - os << "x" << up.get() << ( ( up == n.children.back() ) ? " }\n" : ", " ); - } - for( auto& up : n.children ) { - print_dot_node( os, *up, up->type ); - } - } - } - - } // namespace internal - - template< typename Node > - void print_dot( std::ostream& os, const Node& n ) - { - os << "digraph parse_tree\n{\n"; - internal::print_dot_node( os, n, n.is_root() ? "ROOT" : n.type ); - os << "}\n"; - } - -} // namespace TAO_JSON_PEGTL_NAMESPACE::parse_tree - -#endif diff --git a/include/tao/json/external/pegtl/contrib/raw_string.hpp b/include/tao/json/external/pegtl/contrib/raw_string.hpp deleted file mode 100644 index 1c141531..00000000 --- a/include/tao/json/external/pegtl/contrib/raw_string.hpp +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_RAW_STRING_HPP -#define TAO_JSON_PEGTL_CONTRIB_RAW_STRING_HPP - -#include -#include - -#include "../apply_mode.hpp" -#include "../config.hpp" -#include "../rewind_mode.hpp" - -#include "../internal/bytes.hpp" -#include "../internal/eof.hpp" -#include "../internal/eol.hpp" -#include "../internal/must.hpp" -#include "../internal/not_at.hpp" -#include "../internal/seq.hpp" -#include "../internal/skip_control.hpp" -#include "../internal/star.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - namespace internal - { - template< char Open, char Marker > - struct raw_string_open - { - using analyze_t = analysis::generic< analysis::rule_type::any >; - - template< apply_mode A, - rewind_mode, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, std::size_t& marker_size, States&&... /*unused*/ ) noexcept( noexcept( in.size( 0 ) ) ) - { - if( in.empty() || ( in.peek_char( 0 ) != Open ) ) { - return false; - } - for( std::size_t i = 1; i < in.size( i + 1 ); ++i ) { - switch( const auto c = in.peek_char( i ) ) { - case Open: - marker_size = i + 1; - in.bump_in_this_line( marker_size ); - (void)eol::match( in ); - return true; - case Marker: - break; - default: - return false; - } - } - return false; - } - }; - - template< char Open, char Marker > - inline constexpr bool skip_control< raw_string_open< Open, Marker > > = true; - - template< char Marker, char Close > - struct at_raw_string_close - { - using analyze_t = analysis::generic< analysis::rule_type::opt >; - - template< apply_mode A, - rewind_mode, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, const std::size_t& marker_size, States&&... /*unused*/ ) noexcept( noexcept( in.size( 0 ) ) ) - { - if( in.size( marker_size ) < marker_size ) { - return false; - } - if( in.peek_char( 0 ) != Close ) { - return false; - } - if( in.peek_char( marker_size - 1 ) != Close ) { - return false; - } - for( std::size_t i = 0; i < ( marker_size - 2 ); ++i ) { - if( in.peek_char( i + 1 ) != Marker ) { - return false; - } - } - return true; - } - }; - - template< char Marker, char Close > - inline constexpr bool skip_control< at_raw_string_close< Marker, Close > > = true; - - template< typename Cond, typename... Rules > - struct raw_string_until; - - template< typename Cond > - struct raw_string_until< Cond > - { - using analyze_t = analysis::generic< analysis::rule_type::seq, star< not_at< Cond >, not_at< eof >, bytes< 1 > >, Cond >; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, const std::size_t& marker_size, States&&... st ) - { - auto m = in.template mark< M >(); - - while( !Control< Cond >::template match< A, rewind_mode::required, Action, Control >( in, marker_size, st... ) ) { - if( in.empty() ) { - return false; - } - in.bump(); - } - return m( true ); - } - }; - - template< typename Cond, typename... Rules > - struct raw_string_until - { - using analyze_t = analysis::generic< analysis::rule_type::seq, star< not_at< Cond >, not_at< eof >, Rules... >, Cond >; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, const std::size_t& marker_size, States&&... st ) - { - auto m = in.template mark< M >(); - using m_t = decltype( m ); - - while( !Control< Cond >::template match< A, rewind_mode::required, Action, Control >( in, marker_size, st... ) ) { - if( in.empty() || !( Control< Rules >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) && ... ) ) { - return false; - } - } - return m( true ); - } - }; - - template< typename Cond, typename... Rules > - inline constexpr bool skip_control< raw_string_until< Cond, Rules... > > = true; - - } // namespace internal - - // raw_string matches Lua-style long literals. - // - // The following description was taken from the Lua documentation - // (see http://www.lua.org/docs.html): - // - // - An "opening long bracket of level n" is defined as an opening square - // bracket followed by n equal signs followed by another opening square - // bracket. So, an opening long bracket of level 0 is written as `[[`, - // an opening long bracket of level 1 is written as `[=[`, and so on. - // - A "closing long bracket" is defined similarly; for instance, a closing - // long bracket of level 4 is written as `]====]`. - // - A "long literal" starts with an opening long bracket of any level and - // ends at the first closing long bracket of the same level. It can - // contain any text except a closing bracket of the same level. - // - Literals in this bracketed form can run for several lines, do not - // interpret any escape sequences, and ignore long brackets of any other - // level. - // - For convenience, when the opening long bracket is eagerly followed - // by a newline, the newline is not included in the string. - // - // Note that unlike Lua's long literal, a raw_string is customizable to use - // other characters than `[`, `=` and `]` for matching. Also note that Lua - // introduced newline-specific replacements in Lua 5.2, which we do not - // support on the grammar level. - - template< char Open, char Marker, char Close, typename... Contents > - struct raw_string - { - // This is used for binding the apply()-method and for error-reporting - // when a raw string is not closed properly or has invalid content. - struct content - : internal::raw_string_until< internal::at_raw_string_close< Marker, Close >, Contents... > - { - }; - - using analyze_t = typename internal::seq< internal::bytes< 1 >, content, internal::bytes< 1 > >::analyze_t; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - std::size_t marker_size; - if( internal::raw_string_open< Open, Marker >::template match< A, M, Action, Control >( in, marker_size, st... ) ) { - // TODO: Do not rely on must<> - (void)internal::must< content >::template match< A, M, Action, Control >( in, marker_size, st... ); - in.bump_in_this_line( marker_size ); - return true; - } - return false; - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/contrib/remove_first_state.hpp b/include/tao/json/external/pegtl/contrib/remove_first_state.hpp deleted file mode 100644 index fd47d6f5..00000000 --- a/include/tao/json/external/pegtl/contrib/remove_first_state.hpp +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_REMOVE_FIRST_STATE_HPP -#define TAO_JSON_PEGTL_CONTRIB_REMOVE_FIRST_STATE_HPP - -#include "../apply_mode.hpp" -#include "../config.hpp" -#include "../rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - // NOTE: The naming of the following classes might still change. - - template< typename Rule, template< typename... > class Control > - struct remove_first_state_after_match - : Control< Rule > - { - template< typename Input, typename State, typename... States > - static void start( const Input& in, State&& /*unused*/, States&&... st ) noexcept( noexcept( Control< Rule >::start( in, st... ) ) ) - { - Control< Rule >::start( in, st... ); - } - - template< typename Input, typename State, typename... States > - static void success( const Input& in, State&& /*unused*/, States&&... st ) noexcept( noexcept( Control< Rule >::success( in, st... ) ) ) - { - Control< Rule >::success( in, st... ); - } - - template< typename Input, typename State, typename... States > - static void failure( const Input& in, State&& /*unused*/, States&&... st ) noexcept( noexcept( Control< Rule >::failure( in, st... ) ) ) - { - Control< Rule >::failure( in, st... ); - } - - template< typename Input, typename State, typename... States > - static void raise( const Input& in, State&& /*unused*/, States&&... st ) - { - Control< Rule >::raise( in, st... ); - } - - template< template< typename... > class Action, - typename Iterator, - typename Input, - typename State, - typename... States > - static auto apply( const Iterator& begin, const Input& in, State&& /*unused*/, States&&... st ) noexcept( noexcept( Control< Rule >::template apply< Action >( begin, in, st... ) ) ) - -> decltype( Control< Rule >::template apply< Action >( begin, in, st... ) ) - { - return Control< Rule >::template apply< Action >( begin, in, st... ); - } - - template< template< typename... > class Action, - typename Input, - typename State, - typename... States > - static auto apply0( const Input& in, State&& /*unused*/, States&&... st ) noexcept( noexcept( Control< Rule >::template apply0< Action >( in, st... ) ) ) - -> decltype( Control< Rule >::template apply0< Action >( in, st... ) ) - { - return Control< Rule >::template apply0< Action >( in, st... ); - } - }; - - template< typename Rule, template< typename... > class Control > - struct remove_self_and_first_state - : Control< Rule > - { - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class, - typename Input, - typename State, - typename... States > - [[nodiscard]] static bool match( Input& in, State&& /*unused*/, States&&... st ) - { - return Control< Rule >::template match< A, M, Action, Control >( in, st... ); - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/contrib/rep_one_min_max.hpp b/include/tao/json/external/pegtl/contrib/rep_one_min_max.hpp deleted file mode 100644 index 8d7e6b4e..00000000 --- a/include/tao/json/external/pegtl/contrib/rep_one_min_max.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_REP_ONE_MIN_MAX_HPP -#define TAO_JSON_PEGTL_CONTRIB_REP_ONE_MIN_MAX_HPP - -#include - -#include "../config.hpp" - -#include "../analysis/counted.hpp" - -#include "../internal/bump_help.hpp" -#include "../internal/skip_control.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - namespace internal - { - template< unsigned Min, unsigned Max, char C > - struct rep_one_min_max - { - using analyze_t = analysis::counted< analysis::rule_type::any, Min >; - - static_assert( Min <= Max ); - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) - { - const auto size = in.size( Max + 1 ); - if( size < Min ) { - return false; - } - std::size_t i = 0; - while( ( i < size ) && ( in.peek_char( i ) == C ) ) { - ++i; - } - if( ( Min <= i ) && ( i <= Max ) ) { - bump_help< result_on_found::success, Input, char, C >( in, i ); - return true; - } - return false; - } - }; - - template< unsigned Min, unsigned Max, char C > - inline constexpr bool skip_control< rep_one_min_max< Min, Max, C > > = true; - - } // namespace internal - - inline namespace ascii - { - template< unsigned Min, unsigned Max, char C > - struct rep_one_min_max : internal::rep_one_min_max< Min, Max, C > - { - }; - - } // namespace ascii - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/contrib/rep_string.hpp b/include/tao/json/external/pegtl/contrib/rep_string.hpp deleted file mode 100644 index 74525ca5..00000000 --- a/include/tao/json/external/pegtl/contrib/rep_string.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_REP_STRING_HPP -#define TAO_JSON_PEGTL_CONTRIB_REP_STRING_HPP - -#include - -#include "../config.hpp" -#include "../internal/string.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - namespace internal - { - template< std::size_t, typename, char... > - struct make_rep_string; - - template< char... Ss, char... Cs > - struct make_rep_string< 0, string< Ss... >, Cs... > - { - using type = string< Ss... >; - }; - - template< std::size_t N, char... Ss, char... Cs > - struct make_rep_string< N, string< Ss... >, Cs... > - : make_rep_string< N - 1, string< Ss..., Cs... >, Cs... > - { - }; - - } // namespace internal - - inline namespace ascii - { - template< std::size_t N, char... Cs > - struct rep_string - : internal::make_rep_string< N, internal::string<>, Cs... >::type - {}; - - } // namespace ascii - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/contrib/to_string.hpp b/include/tao/json/external/pegtl/contrib/to_string.hpp deleted file mode 100644 index 3835d4e1..00000000 --- a/include/tao/json/external/pegtl/contrib/to_string.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_TO_STRING_HPP -#define TAO_JSON_PEGTL_CONTRIB_TO_STRING_HPP - -#include - -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - namespace internal - { - template< typename > - struct to_string; - - template< template< char... > class X, char... Cs > - struct to_string< X< Cs... > > - { - [[nodiscard]] static std::string get() - { - const char s[] = { Cs..., 0 }; - return std::string( s, sizeof...( Cs ) ); - } - }; - - } // namespace internal - - template< typename T > - [[nodiscard]] std::string to_string() - { - return internal::to_string< T >::get(); - } - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/contrib/tracer.hpp b/include/tao/json/external/pegtl/contrib/tracer.hpp deleted file mode 100644 index 56faeba9..00000000 --- a/include/tao/json/external/pegtl/contrib/tracer.hpp +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_TRACER_HPP -#define TAO_JSON_PEGTL_CONTRIB_TRACER_HPP - -#include -#include -#include -#include -#include - -#include "../config.hpp" -#include "../normal.hpp" - -#include "../internal/demangle.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - namespace internal - { - template< typename Input > - void print_current( const Input& in ) - { - if( in.empty() ) { - std::cerr << ""; - } - else { - const auto c = in.peek_uint8(); - switch( c ) { - case 0: - std::cerr << " = "; - break; - case 9: - std::cerr << " = "; - break; - case 10: - std::cerr << " = "; - break; - case 13: - std::cerr << " = "; - break; - default: - if( isprint( c ) ) { - std::cerr << '\'' << c << "' = "; - } - } - std::cerr << "(char)" << unsigned( c ); - } - } - - } // namespace internal - - struct trace_state - { - unsigned rule = 0; - unsigned line = 0; - std::vector< unsigned > stack; - }; - - template< template< typename... > class Base > - struct trace - { - template< typename Rule > - struct control - : Base< Rule > - { - template< typename Input, typename... States > - static void start( const Input& in, States&&... st ) - { - std::cerr << in.position() << " start " << internal::demangle< Rule >() << "; current "; - print_current( in ); - std::cerr << std::endl; - Base< Rule >::start( in, st... ); - } - - template< typename Input, typename... States > - static void start( const Input& in, trace_state& ts, States&&... st ) - { - std::cerr << std::setw( 6 ) << ++ts.line << " " << std::setw( 6 ) << ++ts.rule << " "; - start( in, st... ); - ts.stack.push_back( ts.rule ); - } - - template< typename Input, typename... States > - static void success( const Input& in, States&&... st ) - { - std::cerr << in.position() << " success " << internal::demangle< Rule >() << "; next "; - print_current( in ); - std::cerr << std::endl; - Base< Rule >::success( in, st... ); - } - - template< typename Input, typename... States > - static void success( const Input& in, trace_state& ts, States&&... st ) - { - assert( !ts.stack.empty() ); - std::cerr << std::setw( 6 ) << ++ts.line << " " << std::setw( 6 ) << ts.stack.back() << " "; - success( in, st... ); - ts.stack.pop_back(); - } - - template< typename Input, typename... States > - static void failure( const Input& in, States&&... st ) - { - std::cerr << in.position() << " failure " << internal::demangle< Rule >() << std::endl; - Base< Rule >::failure( in, st... ); - } - - template< typename Input, typename... States > - static void failure( const Input& in, trace_state& ts, States&&... st ) - { - assert( !ts.stack.empty() ); - std::cerr << std::setw( 6 ) << ++ts.line << " " << std::setw( 6 ) << ts.stack.back() << " "; - failure( in, st... ); - ts.stack.pop_back(); - } - - template< template< typename... > class Action, typename Iterator, typename Input, typename... States > - static auto apply( const Iterator& begin, const Input& in, States&&... st ) - -> decltype( Base< Rule >::template apply< Action >( begin, in, st... ) ) - { - std::cerr << in.position() << " apply " << internal::demangle< Rule >() << std::endl; - return Base< Rule >::template apply< Action >( begin, in, st... ); - } - - template< template< typename... > class Action, typename Iterator, typename Input, typename... States > - static auto apply( const Iterator& begin, const Input& in, trace_state& ts, States&&... st ) - -> decltype( apply< Action >( begin, in, st... ) ) - { - std::cerr << std::setw( 6 ) << ++ts.line << " "; - return apply< Action >( begin, in, st... ); - } - - template< template< typename... > class Action, typename Input, typename... States > - static auto apply0( const Input& in, States&&... st ) - -> decltype( Base< Rule >::template apply0< Action >( in, st... ) ) - { - std::cerr << in.position() << " apply0 " << internal::demangle< Rule >() << std::endl; - return Base< Rule >::template apply0< Action >( in, st... ); - } - - template< template< typename... > class Action, typename Input, typename... States > - static auto apply0( const Input& in, trace_state& ts, States&&... st ) - -> decltype( apply0< Action >( in, st... ) ) - { - std::cerr << std::setw( 6 ) << ++ts.line << " "; - return apply0< Action >( in, st... ); - } - }; - }; - - template< typename Rule > - using tracer = trace< normal >::control< Rule >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/contrib/unescape.hpp b/include/tao/json/external/pegtl/contrib/unescape.hpp deleted file mode 100644 index 76abe5e7..00000000 --- a/include/tao/json/external/pegtl/contrib/unescape.hpp +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_UNESCAPE_HPP -#define TAO_JSON_PEGTL_CONTRIB_UNESCAPE_HPP - -#include -#include - -#include "../ascii.hpp" -#include "../config.hpp" -#include "../parse_error.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::unescape -{ - // Utility functions for the unescape actions. - - [[nodiscard]] inline bool utf8_append_utf32( std::string& string, const unsigned utf32 ) - { - if( utf32 <= 0x7f ) { - string += char( utf32 & 0xff ); - return true; - } - if( utf32 <= 0x7ff ) { - char tmp[] = { char( ( ( utf32 & 0x7c0 ) >> 6 ) | 0xc0 ), - char( ( ( utf32 & 0x03f ) ) | 0x80 ) }; - string.append( tmp, sizeof( tmp ) ); - return true; - } - if( utf32 <= 0xffff ) { - if( utf32 >= 0xd800 && utf32 <= 0xdfff ) { - // nope, this is a UTF-16 surrogate - return false; - } - char tmp[] = { char( ( ( utf32 & 0xf000 ) >> 12 ) | 0xe0 ), - char( ( ( utf32 & 0x0fc0 ) >> 6 ) | 0x80 ), - char( ( ( utf32 & 0x003f ) ) | 0x80 ) }; - string.append( tmp, sizeof( tmp ) ); - return true; - } - if( utf32 <= 0x10ffff ) { - char tmp[] = { char( ( ( utf32 & 0x1c0000 ) >> 18 ) | 0xf0 ), - char( ( ( utf32 & 0x03f000 ) >> 12 ) | 0x80 ), - char( ( ( utf32 & 0x000fc0 ) >> 6 ) | 0x80 ), - char( ( ( utf32 & 0x00003f ) ) | 0x80 ) }; - string.append( tmp, sizeof( tmp ) ); - return true; - } - return false; - } - - // This function MUST only be called for characters matching TAO_JSON_PEGTL_NAMESPACE::ascii::xdigit! - template< typename I > - [[nodiscard]] I unhex_char( const char c ) - { - switch( c ) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return I( c - '0' ); - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - return I( c - 'a' + 10 ); - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - return I( c - 'A' + 10 ); - default: // LCOV_EXCL_LINE - throw std::runtime_error( "invalid character in unhex" ); // LCOV_EXCL_LINE - } - } - - template< typename I > - [[nodiscard]] I unhex_string( const char* begin, const char* end ) - { - I r = 0; - while( begin != end ) { - r <<= 4; - r += unhex_char< I >( *begin++ ); - } - return r; - } - - // Actions for common unescape situations. - - struct append_all - { - template< typename Input > - static void apply( const Input& in, std::string& s ) - { - s.append( in.begin(), in.size() ); - } - }; - - // This action MUST be called for a character matching T which MUST be TAO_JSON_PEGTL_NAMESPACE::one< ... >. - template< typename T, char... Rs > - struct unescape_c - { - template< typename Input > - static void apply( const Input& in, std::string& s ) - { - assert( in.size() == 1 ); - s += apply_one( in, static_cast< const T* >( nullptr ) ); - } - - template< typename Input, char... Qs > - [[nodiscard]] static char apply_one( const Input& in, const one< Qs... >* /*unused*/ ) - { - static_assert( sizeof...( Qs ) == sizeof...( Rs ), "size mismatch between escaped characters and their mappings" ); - return apply_two( in, { Qs... }, { Rs... } ); - } - - template< typename Input > - [[nodiscard]] static char apply_two( const Input& in, const std::initializer_list< char >& q, const std::initializer_list< char >& r ) - { - const char c = *in.begin(); - for( std::size_t i = 0; i < q.size(); ++i ) { - if( *( q.begin() + i ) == c ) { - return *( r.begin() + i ); - } - } - throw parse_error( "invalid character in unescape", in ); // LCOV_EXCL_LINE - } - }; - - // See src/example/pegtl/unescape.cpp for why the following two actions - // skip the first input character. They also MUST be called - // with non-empty matched inputs! - - struct unescape_u - { - template< typename Input > - static void apply( const Input& in, std::string& s ) - { - assert( !in.empty() ); // First character MUST be present, usually 'u' or 'U'. - if( !utf8_append_utf32( s, unhex_string< unsigned >( in.begin() + 1, in.end() ) ) ) { - throw parse_error( "invalid escaped unicode code point", in ); - } - } - }; - - struct unescape_x - { - template< typename Input > - static void apply( const Input& in, std::string& s ) - { - assert( !in.empty() ); // First character MUST be present, usually 'x'. - s += unhex_string< char >( in.begin() + 1, in.end() ); - } - }; - - // The unescape_j action is similar to unescape_u, however unlike - // unescape_u it - // (a) assumes exactly 4 hexdigits per escape sequence, - // (b) accepts multiple consecutive escaped 16-bit values. - // When applied to more than one escape sequence, unescape_j - // translates UTF-16 surrogate pairs in the input into a single - // UTF-8 sequence in s, as required for JSON by RFC 8259. - - struct unescape_j - { - template< typename Input > - static void apply( const Input& in, std::string& s ) - { - assert( ( ( in.size() + 1 ) % 6 ) == 0 ); // Expects multiple "\\u1234", starting with the first "u". - for( const char* b = in.begin() + 1; b < in.end(); b += 6 ) { - const auto c = unhex_string< unsigned >( b, b + 4 ); - if( ( 0xd800 <= c ) && ( c <= 0xdbff ) && ( b + 6 < in.end() ) ) { - const auto d = unhex_string< unsigned >( b + 6, b + 10 ); - if( ( 0xdc00 <= d ) && ( d <= 0xdfff ) ) { - b += 6; - (void)utf8_append_utf32( s, ( ( ( c & 0x03ff ) << 10 ) | ( d & 0x03ff ) ) + 0x10000 ); - continue; - } - } - if( !utf8_append_utf32( s, c ) ) { - throw parse_error( "invalid escaped unicode code point", in ); - } - } - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::unescape - -#endif diff --git a/include/tao/json/external/pegtl/contrib/uri.hpp b/include/tao/json/external/pegtl/contrib/uri.hpp deleted file mode 100644 index 4a0700b6..00000000 --- a/include/tao/json/external/pegtl/contrib/uri.hpp +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CONTRIB_URI_HPP -#define TAO_JSON_PEGTL_CONTRIB_URI_HPP - -#include - -#include "../ascii.hpp" -#include "../config.hpp" -#include "../rules.hpp" -#include "../utf8.hpp" - -#include "abnf.hpp" -#include "integer.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::uri -{ - // URI grammar according to RFC 3986. - - // This grammar is a direct PEG translation of the original URI grammar. - // It should be considered experimental -- in case of any issues, in particular - // missing rules for attached actions, please contact the developers. - - // Note that this grammar has multiple top-level rules. - - using dot = one< '.' >; - using colon = one< ':' >; - - // clang-format off - struct dec_octet : integer::maximum_rule< std::uint8_t > {}; - - struct IPv4address : seq< dec_octet, dot, dec_octet, dot, dec_octet, dot, dec_octet > {}; - - struct h16 : rep_min_max< 1, 4, abnf::HEXDIG > {}; - struct ls32 : sor< seq< h16, colon, h16 >, IPv4address > {}; - - struct dcolon : two< ':' > {}; - - struct IPv6address : sor< seq< rep< 6, h16, colon >, ls32 >, - seq< dcolon, rep< 5, h16, colon >, ls32 >, - seq< opt< h16 >, dcolon, rep< 4, h16, colon >, ls32 >, - seq< opt< h16, opt< colon, h16 > >, dcolon, rep< 3, h16, colon >, ls32 >, - seq< opt< h16, rep_opt< 2, colon, h16 > >, dcolon, rep< 2, h16, colon >, ls32 >, - seq< opt< h16, rep_opt< 3, colon, h16 > >, dcolon, h16, colon, ls32 >, - seq< opt< h16, rep_opt< 4, colon, h16 > >, dcolon, ls32 >, - seq< opt< h16, rep_opt< 5, colon, h16 > >, dcolon, h16 >, - seq< opt< h16, rep_opt< 6, colon, h16 > >, dcolon > > {}; - - struct gen_delims : one< ':', '/', '?', '#', '[', ']', '@' > {}; - struct sub_delims : one< '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=' > {}; - - struct unreserved : sor< abnf::ALPHA, abnf::DIGIT, one< '-', '.', '_', '~' > > {}; - struct reserved : sor< gen_delims, sub_delims > {}; - - struct IPvFuture : if_must< one< 'v', 'V' >, plus< abnf::HEXDIG >, dot, plus< sor< unreserved, sub_delims, colon > > > {}; - - struct IP_literal : if_must< one< '[' >, sor< IPvFuture, IPv6address >, one< ']' > > {}; - - struct pct_encoded : if_must< one< '%' >, abnf::HEXDIG, abnf::HEXDIG > {}; - struct pchar : sor< unreserved, pct_encoded, sub_delims, one< ':', '@' > > {}; - - struct query : star< sor< pchar, one< '/', '?' > > > {}; - struct fragment : star< sor< pchar, one< '/', '?' > > > {}; - - struct segment : star< pchar > {}; - struct segment_nz : plus< pchar > {}; - struct segment_nz_nc : plus< sor< unreserved, pct_encoded, sub_delims, one< '@' > > > {}; // non-zero-length segment without any colon ":" - - struct path_abempty : star< one< '/' >, segment > {}; - struct path_absolute : seq< one< '/' >, opt< segment_nz, star< one< '/' >, segment > > > {}; - struct path_noscheme : seq< segment_nz_nc, star< one< '/' >, segment > > {}; - struct path_rootless : seq< segment_nz, star< one< '/' >, segment > > {}; - struct path_empty : success {}; - - struct path : sor< path_noscheme, // begins with a non-colon segment - path_rootless, // begins with a segment - path_absolute, // begins with "/" but not "//" - path_abempty > {}; // begins with "/" or is empty - - struct reg_name : star< sor< unreserved, pct_encoded, sub_delims > > {}; - - struct port : star< abnf::DIGIT > {}; - struct host : sor< IP_literal, IPv4address, reg_name > {}; - struct userinfo : star< sor< unreserved, pct_encoded, sub_delims, colon > > {}; - struct opt_userinfo : opt< userinfo, one< '@' > > {}; - struct authority : seq< opt_userinfo, host, opt< colon, port > > {}; - - struct scheme : seq< abnf::ALPHA, star< sor< abnf::ALPHA, abnf::DIGIT, one< '+', '-', '.' > > > > {}; - - using dslash = two< '/' >; - using opt_query = opt_must< one< '?' >, query >; - using opt_fragment = opt_must< one< '#' >, fragment >; - - struct hier_part : sor< if_must< dslash, authority, path_abempty >, path_rootless, path_absolute, path_empty > {}; - struct relative_part : sor< if_must< dslash, authority, path_abempty >, path_noscheme, path_absolute, path_empty > {}; - struct relative_ref : seq< relative_part, opt_query, opt_fragment > {}; - - struct URI : seq< scheme, one< ':' >, hier_part, opt_query, opt_fragment > {}; - struct URI_reference : sor< URI, relative_ref > {}; - struct absolute_URI : seq< scheme, one< ':' >, hier_part, opt_query > {}; - // clang-format on - -} // namespace TAO_JSON_PEGTL_NAMESPACE::uri - -#endif diff --git a/include/tao/json/external/pegtl/cstream_input.hpp b/include/tao/json/external/pegtl/cstream_input.hpp deleted file mode 100644 index f330f08e..00000000 --- a/include/tao/json/external/pegtl/cstream_input.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_CSTREAM_INPUT_HPP -#define TAO_JSON_PEGTL_CSTREAM_INPUT_HPP - -#include - -#include "buffer_input.hpp" -#include "config.hpp" -#include "eol.hpp" - -#include "internal/cstream_reader.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - template< typename Eol = eol::lf_crlf, std::size_t Chunk = 64 > - struct cstream_input - : buffer_input< internal::cstream_reader, Eol, std::string, Chunk > - { - template< typename T > - cstream_input( std::FILE* in_stream, const std::size_t in_maximum, T&& in_source ) - : buffer_input< internal::cstream_reader, Eol, std::string, Chunk >( std::forward< T >( in_source ), in_maximum, in_stream ) - { - } - }; - - template< typename... Ts > - cstream_input( Ts&&... )->cstream_input<>; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/disable_action.hpp b/include/tao/json/external/pegtl/disable_action.hpp deleted file mode 100644 index c7dad5bb..00000000 --- a/include/tao/json/external/pegtl/disable_action.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_DISABLE_ACTION_HPP -#define TAO_JSON_PEGTL_DISABLE_ACTION_HPP - -#include "apply_mode.hpp" -#include "config.hpp" -#include "match.hpp" -#include "nothing.hpp" -#include "rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - struct disable_action - : maybe_nothing - { - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - return TAO_JSON_PEGTL_NAMESPACE::match< Rule, apply_mode::nothing, M, Action, Control >( in, st... ); - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/discard_input.hpp b/include/tao/json/external/pegtl/discard_input.hpp deleted file mode 100644 index ccb205c0..00000000 --- a/include/tao/json/external/pegtl/discard_input.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_DISCARD_INPUT_HPP -#define TAO_JSON_PEGTL_DISCARD_INPUT_HPP - -#include "apply_mode.hpp" -#include "config.hpp" -#include "match.hpp" -#include "nothing.hpp" -#include "rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - struct discard_input - : maybe_nothing - { - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - const bool result = TAO_JSON_PEGTL_NAMESPACE::match< Rule, A, M, Action, Control >( in, st... ); - in.discard(); - return result; - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/discard_input_on_failure.hpp b/include/tao/json/external/pegtl/discard_input_on_failure.hpp deleted file mode 100644 index 11c5f9c9..00000000 --- a/include/tao/json/external/pegtl/discard_input_on_failure.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_DISCARD_INPUT_ON_FAILURE_HPP -#define TAO_JSON_PEGTL_DISCARD_INPUT_ON_FAILURE_HPP - -#include "apply_mode.hpp" -#include "config.hpp" -#include "match.hpp" -#include "nothing.hpp" -#include "rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - struct discard_input_on_failure - : maybe_nothing - { - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - const bool result = TAO_JSON_PEGTL_NAMESPACE::match< Rule, A, M, Action, Control >( in, st... ); - if( !result ) { - in.discard(); - } - return result; - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/discard_input_on_success.hpp b/include/tao/json/external/pegtl/discard_input_on_success.hpp deleted file mode 100644 index cb00f5d9..00000000 --- a/include/tao/json/external/pegtl/discard_input_on_success.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_DISCARD_INPUT_ON_SUCCESS_HPP -#define TAO_JSON_PEGTL_DISCARD_INPUT_ON_SUCCESS_HPP - -#include "apply_mode.hpp" -#include "config.hpp" -#include "match.hpp" -#include "nothing.hpp" -#include "rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - struct discard_input_on_success - : maybe_nothing - { - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - const bool result = TAO_JSON_PEGTL_NAMESPACE::match< Rule, A, M, Action, Control >( in, st... ); - if( result ) { - in.discard(); - } - return result; - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/enable_action.hpp b/include/tao/json/external/pegtl/enable_action.hpp deleted file mode 100644 index 75134981..00000000 --- a/include/tao/json/external/pegtl/enable_action.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_ENABLE_ACTION_HPP -#define TAO_JSON_PEGTL_ENABLE_ACTION_HPP - -#include "apply_mode.hpp" -#include "config.hpp" -#include "match.hpp" -#include "nothing.hpp" -#include "rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - struct enable_action - : maybe_nothing - { - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - return TAO_JSON_PEGTL_NAMESPACE::match< Rule, apply_mode::action, M, Action, Control >( in, st... ); - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/eol.hpp b/include/tao/json/external/pegtl/eol.hpp deleted file mode 100644 index c69ded1b..00000000 --- a/include/tao/json/external/pegtl/eol.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_EOL_HPP -#define TAO_JSON_PEGTL_EOL_HPP - -#include "config.hpp" - -#include "internal/eol.hpp" - -#include "internal/cr_crlf_eol.hpp" -#include "internal/cr_eol.hpp" -#include "internal/crlf_eol.hpp" -#include "internal/lf_crlf_eol.hpp" -#include "internal/lf_eol.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - inline namespace ascii - { - // this is both a rule and a pseudo-namespace for eol::cr, ... - struct eol : internal::eol - { - // clang-format off - struct cr : internal::cr_eol {}; - struct cr_crlf : internal::cr_crlf_eol {}; - struct crlf : internal::crlf_eol {}; - struct lf : internal::lf_eol {}; - struct lf_crlf : internal::lf_crlf_eol {}; - // clang-format on - }; - - } // namespace ascii - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/eol_pair.hpp b/include/tao/json/external/pegtl/eol_pair.hpp deleted file mode 100644 index 97e3f904..00000000 --- a/include/tao/json/external/pegtl/eol_pair.hpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_EOL_PAIR_HPP -#define TAO_JSON_PEGTL_EOL_PAIR_HPP - -#include -#include - -#include "config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - using eol_pair = std::pair< bool, std::size_t >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/file_input.hpp b/include/tao/json/external/pegtl/file_input.hpp deleted file mode 100644 index 2543e412..00000000 --- a/include/tao/json/external/pegtl/file_input.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_FILE_INPUT_HPP -#define TAO_JSON_PEGTL_FILE_INPUT_HPP - -#include "config.hpp" -#include "eol.hpp" -#include "tracking_mode.hpp" - -#if defined( __unix__ ) || ( defined( __APPLE__ ) && defined( __MACH__ ) ) -#include // Required for _POSIX_MAPPED_FILES -#endif - -#if defined( _POSIX_MAPPED_FILES ) || defined( _WIN32 ) -#include "mmap_input.hpp" -#else -#include "read_input.hpp" -#endif - -namespace TAO_JSON_PEGTL_NAMESPACE -{ -#if defined( _POSIX_MAPPED_FILES ) || defined( _WIN32 ) - template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf > - struct file_input - : mmap_input< P, Eol > - { - using mmap_input< P, Eol >::mmap_input; - }; -#else - template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf > - struct file_input - : read_input< P, Eol > - { - using read_input< P, Eol >::read_input; - }; -#endif - - template< typename... Ts > - explicit file_input( Ts&&... )->file_input<>; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/internal/action.hpp b/include/tao/json/external/pegtl/internal/action.hpp deleted file mode 100644 index 6f3a6c94..00000000 --- a/include/tao/json/external/pegtl/internal/action.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_ACTION_HPP -#define TAO_JSON_PEGTL_INTERNAL_ACTION_HPP - -#include "../config.hpp" - -#include "duseltronik.hpp" -#include "seq.hpp" -#include "skip_control.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< template< typename... > class Action, typename... Rules > - struct action - { - using analyze_t = analysis::generic< analysis::rule_type::seq, Rules... >; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - return duseltronik< seq< Rules... >, A, M, Action, Control >::match( in, st... ); - } - }; - - template< template< typename... > class Action, typename... Rules > - inline constexpr bool skip_control< action< Action, Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/action_input.hpp b/include/tao/json/external/pegtl/internal/action_input.hpp deleted file mode 100644 index d4efaac4..00000000 --- a/include/tao/json/external/pegtl/internal/action_input.hpp +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_ACTION_INPUT_HPP -#define TAO_JSON_PEGTL_INTERNAL_ACTION_INPUT_HPP - -#include -#include -#include -#include - -#include "iterator.hpp" - -#include "../config.hpp" -#include "../position.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Input > - class action_input - { - public: - using input_t = Input; - using iterator_t = typename Input::iterator_t; - - action_input( const iterator_t& in_begin, const Input& in_input ) noexcept - : m_begin( in_begin ), - m_input( in_input ) - { - } - - action_input( const action_input& ) = delete; - action_input( action_input&& ) = delete; - - ~action_input() = default; - - action_input& operator=( const action_input& ) = delete; - action_input& operator=( action_input&& ) = delete; - - [[nodiscard]] const iterator_t& iterator() const noexcept - { - return m_begin; - } - - [[nodiscard]] const Input& input() const noexcept - { - return m_input; - } - - [[nodiscard]] const char* begin() const noexcept - { - if constexpr( std::is_same_v< iterator_t, const char* > ) { - return iterator(); - } - else { - return iterator().data; - } - } - - [[nodiscard]] const char* end() const noexcept - { - return input().current(); - } - - [[nodiscard]] bool empty() const noexcept - { - return begin() == end(); - } - - [[nodiscard]] std::size_t size() const noexcept - { - return std::size_t( end() - begin() ); - } - - [[nodiscard]] std::string string() const - { - return std::string( begin(), size() ); - } - - [[nodiscard]] std::string_view string_view() const noexcept - { - return std::string_view( begin(), size() ); - } - - [[nodiscard]] char peek_char( const std::size_t offset = 0 ) const noexcept - { - return begin()[ offset ]; - } - - [[nodiscard]] std::uint8_t peek_uint8( const std::size_t offset = 0 ) const noexcept - { - return static_cast< std::uint8_t >( peek_char( offset ) ); - } - - [[nodiscard]] TAO_JSON_PEGTL_NAMESPACE::position position() const - { - return input().position( iterator() ); // NOTE: Not efficient with lazy inputs. - } - - protected: - const iterator_t m_begin; - const Input& m_input; - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/alnum.hpp b/include/tao/json/external/pegtl/internal/alnum.hpp deleted file mode 100644 index 7a9821ba..00000000 --- a/include/tao/json/external/pegtl/internal/alnum.hpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_ALNUM_HPP -#define TAO_JSON_PEGTL_INTERNAL_ALNUM_HPP - -#include "../config.hpp" - -#include "peek_char.hpp" -#include "ranges.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - using alnum = ranges< peek_char, 'a', 'z', 'A', 'Z', '0', '9' >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/alpha.hpp b/include/tao/json/external/pegtl/internal/alpha.hpp deleted file mode 100644 index fd102025..00000000 --- a/include/tao/json/external/pegtl/internal/alpha.hpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_ALPHA_HPP -#define TAO_JSON_PEGTL_INTERNAL_ALPHA_HPP - -#include "../config.hpp" - -#include "peek_char.hpp" -#include "ranges.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - using alpha = ranges< peek_char, 'a', 'z', 'A', 'Z' >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/always_false.hpp b/include/tao/json/external/pegtl/internal/always_false.hpp deleted file mode 100644 index 0193a46d..00000000 --- a/include/tao/json/external/pegtl/internal/always_false.hpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_ALWAYS_FALSE_HPP -#define TAO_JSON_PEGTL_INTERNAL_ALWAYS_FALSE_HPP - -#include "../config.hpp" - -#include - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename... > - struct always_false - : std::false_type - { - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/any.hpp b/include/tao/json/external/pegtl/internal/any.hpp deleted file mode 100644 index d8174609..00000000 --- a/include/tao/json/external/pegtl/internal/any.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_ANY_HPP -#define TAO_JSON_PEGTL_INTERNAL_ANY_HPP - -#include "../config.hpp" - -#include "peek_char.hpp" -#include "skip_control.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Peek > - struct any; - - template<> - struct any< peek_char > - { - using analyze_t = analysis::generic< analysis::rule_type::any >; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.empty() ) ) - { - if( !in.empty() ) { - in.bump(); - return true; - } - return false; - } - }; - - template< typename Peek > - struct any - { - using analyze_t = analysis::generic< analysis::rule_type::any >; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( Peek::max_input_size ) ) ) - { - if( const std::size_t s = in.size( Peek::max_input_size ); s >= Peek::min_input_size ) { - if( const auto t = Peek::peek( in, s ) ) { - in.bump( t.size ); - return true; - } - } - return false; - } - }; - - template< typename Peek > - inline constexpr bool skip_control< any< Peek > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/apply.hpp b/include/tao/json/external/pegtl/internal/apply.hpp deleted file mode 100644 index 392bd6c1..00000000 --- a/include/tao/json/external/pegtl/internal/apply.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_APPLY_HPP -#define TAO_JSON_PEGTL_INTERNAL_APPLY_HPP - -#include "../config.hpp" - -#include "apply_single.hpp" -#include "skip_control.hpp" - -#include "../analysis/counted.hpp" -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename... Actions > - struct apply - { - using analyze_t = analysis::counted< analysis::rule_type::any, 0 >; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - if constexpr( ( A == apply_mode::action ) && ( sizeof...( Actions ) > 0 ) ) { - using action_t = typename Input::action_t; - const action_t i2( in.iterator(), in ); // No data -- range is from begin to begin. - return ( apply_single< Actions >::match( i2, st... ) && ... ); - } - else { -#if defined( _MSC_VER ) - (void)in; - (void)( (void)st, ... ); -#endif - return true; - } - } - }; - - template< typename... Actions > - inline constexpr bool skip_control< apply< Actions... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/apply0.hpp b/include/tao/json/external/pegtl/internal/apply0.hpp deleted file mode 100644 index 37a1eb6c..00000000 --- a/include/tao/json/external/pegtl/internal/apply0.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_APPLY0_HPP -#define TAO_JSON_PEGTL_INTERNAL_APPLY0_HPP - -#include "../config.hpp" - -#include "apply0_single.hpp" -#include "skip_control.hpp" - -#include "../analysis/counted.hpp" -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename... Actions > - struct apply0 - { - using analyze_t = analysis::counted< analysis::rule_type::any, 0 >; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& /*unused*/, States&&... st ) - { - if constexpr( A == apply_mode::action ) { - return ( apply0_single< Actions >::match( st... ) && ... ); - } - else { -#if defined( _MSC_VER ) - (void)( (void)st, ... ); -#endif - return true; - } - } - }; - - template< typename... Actions > - inline constexpr bool skip_control< apply0< Actions... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/apply0_single.hpp b/include/tao/json/external/pegtl/internal/apply0_single.hpp deleted file mode 100644 index 3d875bca..00000000 --- a/include/tao/json/external/pegtl/internal/apply0_single.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_APPLY0_SINGLE_HPP -#define TAO_JSON_PEGTL_INTERNAL_APPLY0_SINGLE_HPP - -#include "../config.hpp" - -#include - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Action > - struct apply0_single - { - template< typename... States > - [[nodiscard]] static auto match( States&&... st ) noexcept( noexcept( Action::apply0( st... ) ) ) - -> std::enable_if_t< std::is_same_v< decltype( Action::apply0( st... ) ), void >, bool > - { - Action::apply0( st... ); - return true; - } - - template< typename... States > - [[nodiscard]] static auto match( States&&... st ) noexcept( noexcept( Action::apply0( st... ) ) ) - -> std::enable_if_t< std::is_same_v< decltype( Action::apply0( st... ) ), bool >, bool > - { - return Action::apply0( st... ); - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/apply_single.hpp b/include/tao/json/external/pegtl/internal/apply_single.hpp deleted file mode 100644 index f3f1a483..00000000 --- a/include/tao/json/external/pegtl/internal/apply_single.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_APPLY_SINGLE_HPP -#define TAO_JSON_PEGTL_INTERNAL_APPLY_SINGLE_HPP - -#include "../config.hpp" - -#include - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Action > - struct apply_single - { - template< typename Input, typename... States > - [[nodiscard]] static auto match( const Input& in, States&&... st ) noexcept( noexcept( Action::apply( in, st... ) ) ) - -> std::enable_if_t< std::is_same_v< decltype( Action::apply( in, st... ) ), void >, bool > - { - Action::apply( in, st... ); - return true; - } - - template< typename Input, typename... States > - [[nodiscard]] static auto match( const Input& in, States&&... st ) noexcept( noexcept( Action::apply( in, st... ) ) ) - -> std::enable_if_t< std::is_same_v< decltype( Action::apply( in, st... ) ), bool >, bool > - { - return Action::apply( in, st... ); - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/at.hpp b/include/tao/json/external/pegtl/internal/at.hpp deleted file mode 100644 index 9fbe045e..00000000 --- a/include/tao/json/external/pegtl/internal/at.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_AT_HPP -#define TAO_JSON_PEGTL_INTERNAL_AT_HPP - -#include "../config.hpp" - -#include "skip_control.hpp" -#include "trivial.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename... Rules > - struct at; - - template<> - struct at<> - : trivial< true > - { - }; - - template< typename... Rules > - struct at - { - using analyze_t = analysis::generic< analysis::rule_type::opt, Rules... >; - - template< apply_mode, - rewind_mode, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - const auto m = in.template mark< rewind_mode::required >(); - return ( Control< Rules >::template match< apply_mode::nothing, rewind_mode::active, Action, Control >( in, st... ) && ... ); - } - }; - - template< typename... Rules > - inline constexpr bool skip_control< at< Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/bof.hpp b/include/tao/json/external/pegtl/internal/bof.hpp deleted file mode 100644 index 2b868709..00000000 --- a/include/tao/json/external/pegtl/internal/bof.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_BOF_HPP -#define TAO_JSON_PEGTL_INTERNAL_BOF_HPP - -#include "../config.hpp" - -#include "skip_control.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct bof - { - using analyze_t = analysis::generic< analysis::rule_type::opt >; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) noexcept - { - return in.byte() == 0; - } - }; - - template<> - inline constexpr bool skip_control< bof > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/bol.hpp b/include/tao/json/external/pegtl/internal/bol.hpp deleted file mode 100644 index cbbb7a6d..00000000 --- a/include/tao/json/external/pegtl/internal/bol.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_BOL_HPP -#define TAO_JSON_PEGTL_INTERNAL_BOL_HPP - -#include "../config.hpp" - -#include "skip_control.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct bol - { - using analyze_t = analysis::generic< analysis::rule_type::opt >; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) noexcept - { - return in.byte_in_line() == 0; - } - }; - - template<> - inline constexpr bool skip_control< bol > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/bump.hpp b/include/tao/json/external/pegtl/internal/bump.hpp deleted file mode 100644 index 86462712..00000000 --- a/include/tao/json/external/pegtl/internal/bump.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_BUMP_HPP -#define TAO_JSON_PEGTL_INTERNAL_BUMP_HPP - -#include "../config.hpp" - -#include "iterator.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - inline void bump( iterator& iter, const std::size_t count, const int ch ) noexcept - { - for( std::size_t i = 0; i < count; ++i ) { - if( iter.data[ i ] == ch ) { - ++iter.line; - iter.byte_in_line = 0; - } - else { - ++iter.byte_in_line; - } - } - iter.byte += count; - iter.data += count; - } - - inline void bump_in_this_line( iterator& iter, const std::size_t count ) noexcept - { - iter.data += count; - iter.byte += count; - iter.byte_in_line += count; - } - - inline void bump_to_next_line( iterator& iter, const std::size_t count ) noexcept - { - ++iter.line; - iter.byte += count; - iter.byte_in_line = 0; - iter.data += count; - } - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/bump_help.hpp b/include/tao/json/external/pegtl/internal/bump_help.hpp deleted file mode 100644 index 6bb89e42..00000000 --- a/include/tao/json/external/pegtl/internal/bump_help.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_BUMP_HELP_HPP -#define TAO_JSON_PEGTL_INTERNAL_BUMP_HELP_HPP - -#include -#include - -#include "../config.hpp" - -#include "result_on_found.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< result_on_found R, typename Input, typename Char, Char... Cs > - void bump_help( Input& in, const std::size_t count ) noexcept - { - if constexpr( ( ( Cs != Input::eol_t::ch ) && ... ) != bool( R ) ) { - in.bump( count ); - } - else { - in.bump_in_this_line( count ); - } - } - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/bytes.hpp b/include/tao/json/external/pegtl/internal/bytes.hpp deleted file mode 100644 index 72d37b97..00000000 --- a/include/tao/json/external/pegtl/internal/bytes.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_BYTES_HPP -#define TAO_JSON_PEGTL_INTERNAL_BYTES_HPP - -#include "../config.hpp" - -#include "skip_control.hpp" - -#include "../analysis/counted.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< unsigned Num > - struct bytes - { - using analyze_t = analysis::counted< analysis::rule_type::any, Num >; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( 0 ) ) ) - { - if( in.size( Num ) >= Num ) { - in.bump( Num ); - return true; - } - return false; - } - }; - - template< unsigned Num > - inline constexpr bool skip_control< bytes< Num > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/control.hpp b/include/tao/json/external/pegtl/internal/control.hpp deleted file mode 100644 index 3e80d98e..00000000 --- a/include/tao/json/external/pegtl/internal/control.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_CONTROL_HPP -#define TAO_JSON_PEGTL_INTERNAL_CONTROL_HPP - -#include "../config.hpp" - -#include "duseltronik.hpp" -#include "seq.hpp" -#include "skip_control.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< template< typename... > class Control, typename... Rules > - struct control - { - using analyze_t = analysis::generic< analysis::rule_type::seq, Rules... >; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - return duseltronik< seq< Rules... >, A, M, Action, Control >::match( in, st... ); - } - }; - - template< template< typename... > class Control, typename... Rules > - inline constexpr bool skip_control< control< Control, Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/cr_crlf_eol.hpp b/include/tao/json/external/pegtl/internal/cr_crlf_eol.hpp deleted file mode 100644 index 167aead1..00000000 --- a/include/tao/json/external/pegtl/internal/cr_crlf_eol.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_CR_CRLF_EOL_HPP -#define TAO_JSON_PEGTL_INTERNAL_CR_CRLF_EOL_HPP - -#include "../config.hpp" -#include "../eol_pair.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct cr_crlf_eol - { - static constexpr int ch = '\r'; - - template< typename Input > - [[nodiscard]] static eol_pair match( Input& in ) noexcept( noexcept( in.size( 2 ) ) ) - { - eol_pair p = { false, in.size( 2 ) }; - if( p.second ) { - if( in.peek_char() == '\r' ) { - in.bump_to_next_line( 1 + ( ( p.second > 1 ) && ( in.peek_char( 1 ) == '\n' ) ) ); - p.first = true; - } - } - return p; - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/cr_eol.hpp b/include/tao/json/external/pegtl/internal/cr_eol.hpp deleted file mode 100644 index 3726f434..00000000 --- a/include/tao/json/external/pegtl/internal/cr_eol.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_CR_EOL_HPP -#define TAO_JSON_PEGTL_INTERNAL_CR_EOL_HPP - -#include "../config.hpp" -#include "../eol_pair.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct cr_eol - { - static constexpr int ch = '\r'; - - template< typename Input > - [[nodiscard]] static eol_pair match( Input& in ) noexcept( noexcept( in.size( 1 ) ) ) - { - eol_pair p = { false, in.size( 1 ) }; - if( p.second ) { - if( in.peek_char() == '\r' ) { - in.bump_to_next_line(); - p.first = true; - } - } - return p; - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/crlf_eol.hpp b/include/tao/json/external/pegtl/internal/crlf_eol.hpp deleted file mode 100644 index 6d00310a..00000000 --- a/include/tao/json/external/pegtl/internal/crlf_eol.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_CRLF_EOL_HPP -#define TAO_JSON_PEGTL_INTERNAL_CRLF_EOL_HPP - -#include "../config.hpp" -#include "../eol_pair.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct crlf_eol - { - static constexpr int ch = '\n'; - - template< typename Input > - [[nodiscard]] static eol_pair match( Input& in ) noexcept( noexcept( in.size( 2 ) ) ) - { - eol_pair p = { false, in.size( 2 ) }; - if( p.second > 1 ) { - if( ( in.peek_char() == '\r' ) && ( in.peek_char( 1 ) == '\n' ) ) { - in.bump_to_next_line( 2 ); - p.first = true; - } - } - return p; - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/cstream_reader.hpp b/include/tao/json/external/pegtl/internal/cstream_reader.hpp deleted file mode 100644 index 9e639dbe..00000000 --- a/include/tao/json/external/pegtl/internal/cstream_reader.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_CSTREAM_READER_HPP -#define TAO_JSON_PEGTL_INTERNAL_CSTREAM_READER_HPP - -#include -#include -#include - -#include - -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct cstream_reader - { - explicit cstream_reader( std::FILE* s ) noexcept - : m_cstream( s ) - { - assert( m_cstream != nullptr ); - } - - [[nodiscard]] std::size_t operator()( char* buffer, const std::size_t length ) - { - if( const auto r = std::fread( buffer, 1, length, m_cstream ) ) { - return r; - } - if( std::feof( m_cstream ) != 0 ) { - return 0; - } - - // Please contact us if you know how to provoke the following exception. - // The example on cppreference.com doesn't work, at least not on macOS. - - // LCOV_EXCL_START - const auto ec = std::ferror( m_cstream ); - assert( ec != 0 ); - throw std::system_error( ec, std::system_category(), "fread() failed" ); - // LCOV_EXCL_STOP - } - - std::FILE* m_cstream; - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/cstring_reader.hpp b/include/tao/json/external/pegtl/internal/cstring_reader.hpp deleted file mode 100644 index 3dbf8e03..00000000 --- a/include/tao/json/external/pegtl/internal/cstring_reader.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_CSTRING_READER_HPP -#define TAO_JSON_PEGTL_INTERNAL_CSTRING_READER_HPP - -#include -#include - -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct cstring_reader - { - explicit cstring_reader( const char* zero_terminated ) noexcept - : m_cstring( zero_terminated ) - { - assert( m_cstring != nullptr ); - } - - [[nodiscard]] std::size_t operator()( char* buffer, const std::size_t length ) noexcept - { - std::size_t i = 0; - char c; - - while( ( i < length ) && ( ( c = m_cstring[ i ] ) != 0 ) ) { - *buffer++ = c; - ++i; - } - m_cstring += i; - return i; - } - - const char* m_cstring; - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/demangle.hpp b/include/tao/json/external/pegtl/internal/demangle.hpp deleted file mode 100644 index 6562e779..00000000 --- a/include/tao/json/external/pegtl/internal/demangle.hpp +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_DEMANGLE_HPP -#define TAO_JSON_PEGTL_INTERNAL_DEMANGLE_HPP - -#include -#include - -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ -#if defined( __clang__ ) - -#if defined( _LIBCPP_VERSION ) - - template< typename T > - [[nodiscard]] constexpr std::string_view demangle() noexcept - { - constexpr const std::string_view sv = __PRETTY_FUNCTION__; - constexpr const auto begin = sv.find( '=' ); - static_assert( begin != std::string_view::npos ); - return sv.substr( begin + 2, sv.size() - begin - 3 ); - } - -#else - - // When using libstdc++ with clang, std::string_view::find is not constexpr :( - template< char C > - constexpr const char* find( const char* p, std::size_t n ) noexcept - { - while( n ) { - if( *p == C ) { - return p; - } - ++p; - --n; - } - return nullptr; - } - - template< typename T > - [[nodiscard]] constexpr std::string_view demangle() noexcept - { - constexpr const std::string_view sv = __PRETTY_FUNCTION__; - constexpr const auto begin = find< '=' >( sv.data(), sv.size() ); - static_assert( begin != nullptr ); - return { begin + 2, sv.data() + sv.size() - begin - 3 }; - } - -#endif - -#elif defined( __GNUC__ ) - -#if( __GNUC__ == 7 ) - - // GCC 7 wrongly sometimes disallows __PRETTY_FUNCTION__ in constexpr functions, - // therefore we drop the 'constexpr' and hope for the best. - template< typename T > - [[nodiscard]] std::string_view demangle() noexcept - { - const std::string_view sv = __PRETTY_FUNCTION__; - const auto begin = sv.find( '=' ); - const auto tmp = sv.substr( begin + 2 ); - const auto end = tmp.rfind( ';' ); - return tmp.substr( 0, end ); - } - -#elif( __GNUC__ == 9 ) && ( __GNUC_MINOR__ < 3 ) - - // GCC 9.1 and 9.2 have a bug that leads to truncated __PRETTY_FUNCTION__ names, - // see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91155 - template< typename T > - [[nodiscard]] constexpr std::string_view demangle() noexcept - { - // fallback: requires RTTI, no demangling - return typeid( T ).name(); - } - -#else - - template< typename T > - [[nodiscard]] constexpr std::string_view demangle() noexcept - { - constexpr std::string_view sv = __PRETTY_FUNCTION__; - constexpr const auto begin = sv.find( '=' ); - static_assert( begin != std::string_view::npos ); - constexpr const auto tmp = sv.substr( begin + 2 ); - constexpr const auto end = tmp.rfind( ';' ); - static_assert( end != std::string_view::npos ); - return tmp.substr( 0, end ); - } - -#endif - -#elif defined( _MSC_VER ) - -#if( _MSC_VER < 1920 ) - - template< typename T > - [[nodiscard]] constexpr std::string_view demangle() noexcept - { - const std::string_view sv = __FUNCSIG__; - const auto begin = sv.find( "demangle<" ); - const auto tmp = sv.substr( begin + 9 ); - const auto end = tmp.rfind( '>' ); - return tmp.substr( 0, end ); - } - -#else - - template< typename T > - [[nodiscard]] constexpr std::string_view demangle() noexcept - { - constexpr std::string_view sv = __FUNCSIG__; - constexpr auto begin = sv.find( "demangle<" ); - static_assert( begin != std::string_view::npos ); - constexpr auto tmp = sv.substr( begin + 9 ); - constexpr auto end = tmp.rfind( '>' ); - static_assert( end != std::string_view::npos ); - return tmp.substr( 0, end ); - } - -#endif - -#else - - template< typename T > - [[nodiscard]] constexpr std::string_view demangle() noexcept - { - // fallback: requires RTTI, no demangling - return typeid( T ).name(); - } - -#endif - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/disable.hpp b/include/tao/json/external/pegtl/internal/disable.hpp deleted file mode 100644 index f756dddf..00000000 --- a/include/tao/json/external/pegtl/internal/disable.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_DISABLE_HPP -#define TAO_JSON_PEGTL_INTERNAL_DISABLE_HPP - -#include "../config.hpp" - -#include "duseltronik.hpp" -#include "seq.hpp" -#include "skip_control.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename... Rules > - struct disable - { - using analyze_t = analysis::generic< analysis::rule_type::seq, Rules... >; - - template< apply_mode, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - return duseltronik< seq< Rules... >, apply_mode::nothing, M, Action, Control >::match( in, st... ); - } - }; - - template< typename... Rules > - inline constexpr bool skip_control< disable< Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/discard.hpp b/include/tao/json/external/pegtl/internal/discard.hpp deleted file mode 100644 index 38bd4e94..00000000 --- a/include/tao/json/external/pegtl/internal/discard.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_DISCARD_HPP -#define TAO_JSON_PEGTL_INTERNAL_DISCARD_HPP - -#include "../config.hpp" - -#include "skip_control.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct discard - { - using analyze_t = analysis::generic< analysis::rule_type::opt >; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) noexcept - { - static_assert( noexcept( in.discard() ) ); - in.discard(); - return true; - } - }; - - template<> - inline constexpr bool skip_control< discard > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/dusel_mode.hpp b/include/tao/json/external/pegtl/internal/dusel_mode.hpp deleted file mode 100644 index 5d22837a..00000000 --- a/include/tao/json/external/pegtl/internal/dusel_mode.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_DUSEL_MODE_HPP -#define TAO_JSON_PEGTL_INTERNAL_DUSEL_MODE_HPP - -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - enum class dusel_mode : char - { - nothing = 0, - control = 1, - control_and_apply_void = 2, - control_and_apply_bool = 3, - control_and_apply0_void = 4, - control_and_apply0_bool = 5 - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/duseltronik.hpp b/include/tao/json/external/pegtl/internal/duseltronik.hpp deleted file mode 100644 index 7a02519a..00000000 --- a/include/tao/json/external/pegtl/internal/duseltronik.hpp +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_DUSELTRONIK_HPP -#define TAO_JSON_PEGTL_INTERNAL_DUSELTRONIK_HPP - -#include "../apply_mode.hpp" -#include "../config.hpp" -#include "../rewind_mode.hpp" - -#include "dusel_mode.hpp" - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4702 ) -#endif - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - dusel_mode = dusel_mode::nothing > - struct duseltronik; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control > - struct duseltronik< Rule, A, M, Action, Control, dusel_mode::nothing > - { - template< typename Input, typename... States > - [[nodiscard]] static auto match( Input& in, States&&... st ) - -> decltype( Rule::template match< A, M, Action, Control >( in, st... ) ) - { - return Rule::template match< A, M, Action, Control >( in, st... ); - } - - template< typename Input, typename... States, int = 1 > - [[nodiscard]] static auto match( Input& in, States&&... /*unused*/ ) - -> decltype( Rule::match( in ) ) - { - return Rule::match( in ); - } - }; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control > - struct duseltronik< Rule, A, M, Action, Control, dusel_mode::control > - { - template< typename Input, typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - Control< Rule >::start( static_cast< const Input& >( in ), st... ); - - if( duseltronik< Rule, A, M, Action, Control, dusel_mode::nothing >::match( in, st... ) ) { - Control< Rule >::success( static_cast< const Input& >( in ), st... ); - return true; - } - Control< Rule >::failure( static_cast< const Input& >( in ), st... ); - return false; - } - }; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control > - struct duseltronik< Rule, A, M, Action, Control, dusel_mode::control_and_apply_void > - { - template< typename Input, typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< rewind_mode::required >(); - - Control< Rule >::start( static_cast< const Input& >( in ), st... ); - - if( duseltronik< Rule, A, rewind_mode::active, Action, Control, dusel_mode::nothing >::match( in, st... ) ) { - Control< Rule >::template apply< Action >( m.iterator(), static_cast< const Input& >( in ), st... ); - Control< Rule >::success( static_cast< const Input& >( in ), st... ); - return m( true ); - } - Control< Rule >::failure( static_cast< const Input& >( in ), st... ); - return false; - } - }; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control > - struct duseltronik< Rule, A, M, Action, Control, dusel_mode::control_and_apply_bool > - { - template< typename Input, typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< rewind_mode::required >(); - - Control< Rule >::start( static_cast< const Input& >( in ), st... ); - - if( duseltronik< Rule, A, rewind_mode::active, Action, Control, dusel_mode::nothing >::match( in, st... ) ) { - if( Control< Rule >::template apply< Action >( m.iterator(), static_cast< const Input& >( in ), st... ) ) { - Control< Rule >::success( static_cast< const Input& >( in ), st... ); - return m( true ); - } - } - Control< Rule >::failure( static_cast< const Input& >( in ), st... ); - return false; - } - }; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control > - struct duseltronik< Rule, A, M, Action, Control, dusel_mode::control_and_apply0_void > - { - template< typename Input, typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - Control< Rule >::start( static_cast< const Input& >( in ), st... ); - - if( duseltronik< Rule, A, M, Action, Control, dusel_mode::nothing >::match( in, st... ) ) { - Control< Rule >::template apply0< Action >( static_cast< const Input& >( in ), st... ); - Control< Rule >::success( static_cast< const Input& >( in ), st... ); - return true; - } - Control< Rule >::failure( static_cast< const Input& >( in ), st... ); - return false; - } - }; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control > - struct duseltronik< Rule, A, M, Action, Control, dusel_mode::control_and_apply0_bool > - { - template< typename Input, typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< rewind_mode::required >(); - - Control< Rule >::start( static_cast< const Input& >( in ), st... ); - - if( duseltronik< Rule, A, rewind_mode::active, Action, Control, dusel_mode::nothing >::match( in, st... ) ) { - if( Control< Rule >::template apply0< Action >( static_cast< const Input& >( in ), st... ) ) { - Control< Rule >::success( static_cast< const Input& >( in ), st... ); - return m( true ); - } - } - Control< Rule >::failure( static_cast< const Input& >( in ), st... ); - return false; - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - -#endif diff --git a/include/tao/json/external/pegtl/internal/enable.hpp b/include/tao/json/external/pegtl/internal/enable.hpp deleted file mode 100644 index f21084bb..00000000 --- a/include/tao/json/external/pegtl/internal/enable.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_ENABLE_HPP -#define TAO_JSON_PEGTL_INTERNAL_ENABLE_HPP - -#include "../config.hpp" - -#include "duseltronik.hpp" -#include "seq.hpp" -#include "skip_control.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename... Rules > - struct enable - { - using analyze_t = analysis::generic< analysis::rule_type::seq, Rules... >; - - template< apply_mode, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - return duseltronik< seq< Rules... >, apply_mode::action, M, Action, Control >::match( in, st... ); - } - }; - - template< typename... Rules > - inline constexpr bool skip_control< enable< Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/endian.hpp b/include/tao/json/external/pegtl/internal/endian.hpp deleted file mode 100644 index 1d30df5a..00000000 --- a/include/tao/json/external/pegtl/internal/endian.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_ENDIAN_HPP -#define TAO_JSON_PEGTL_INTERNAL_ENDIAN_HPP - -#include -#include - -#include "../config.hpp" - -#if defined( _WIN32 ) && !defined( __MINGW32__ ) -#include "endian_win.hpp" -#else -#include "endian_gcc.hpp" -#endif - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename N > - [[nodiscard]] N h_to_be( const N n ) noexcept - { - return N( to_and_from_be< sizeof( N ) >::convert( n ) ); - } - - template< typename N > - [[nodiscard]] N be_to_h( const N n ) noexcept - { - return h_to_be( n ); - } - - template< typename N > - [[nodiscard]] N be_to_h( const void* p ) noexcept - { - N n; - std::memcpy( &n, p, sizeof( n ) ); - return internal::be_to_h( n ); - } - - template< typename N > - [[nodiscard]] N h_to_le( const N n ) noexcept - { - return N( to_and_from_le< sizeof( N ) >::convert( n ) ); - } - - template< typename N > - [[nodiscard]] N le_to_h( const N n ) noexcept - { - return h_to_le( n ); - } - - template< typename N > - [[nodiscard]] N le_to_h( const void* p ) noexcept - { - N n; - std::memcpy( &n, p, sizeof( n ) ); - return internal::le_to_h( n ); - } - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/endian_gcc.hpp b/include/tao/json/external/pegtl/internal/endian_gcc.hpp deleted file mode 100644 index 01677898..00000000 --- a/include/tao/json/external/pegtl/internal/endian_gcc.hpp +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_ENDIAN_GCC_HPP -#define TAO_JSON_PEGTL_INTERNAL_ENDIAN_GCC_HPP - -#include -#include - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ -#if !defined( __BYTE_ORDER__ ) -#error No byte order defined! -#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - - template< std::size_t S > - struct to_and_from_be - { - template< typename T > - [[nodiscard]] static T convert( const T n ) noexcept - { - return n; - } - }; - - template< std::size_t S > - struct to_and_from_le; - - template<> - struct to_and_from_le< 1 > - { - [[nodiscard]] static std::uint8_t convert( const std::uint8_t n ) noexcept - { - return n; - } - - [[nodiscard]] static std::int8_t convert( const std::int8_t n ) noexcept - { - return n; - } - }; - - template<> - struct to_and_from_le< 2 > - { - [[nodiscard]] static std::int16_t convert( const std::int16_t n ) noexcept - { - return static_cast< std::int16_t >( __builtin_bswap16( static_cast< std::uint16_t >( n ) ) ); - } - - [[nodiscard]] static std::uint16_t convert( const std::uint16_t n ) noexcept - { - return __builtin_bswap16( n ); - } - }; - - template<> - struct to_and_from_le< 4 > - { - [[nodiscard]] static float convert( float n ) noexcept - { - std::uint32_t u; - std::memcpy( &u, &n, 4 ); - u = convert( u ); - std::memcpy( &n, &u, 4 ); - return n; - } - - [[nodiscard]] static std::int32_t convert( const std::int32_t n ) noexcept - { - return static_cast< std::int32_t >( __builtin_bswap32( static_cast< std::uint32_t >( n ) ) ); - } - - [[nodiscard]] static std::uint32_t convert( const std::uint32_t n ) noexcept - { - return __builtin_bswap32( n ); - } - }; - - template<> - struct to_and_from_le< 8 > - { - [[nodiscard]] static double convert( double n ) noexcept - { - std::uint64_t u; - std::memcpy( &u, &n, 8 ); - u = convert( u ); - std::memcpy( &n, &u, 8 ); - return n; - } - - [[nodiscard]] static std::int64_t convert( const std::int64_t n ) noexcept - { - return static_cast< std::int64_t >( __builtin_bswap64( static_cast< std::uint64_t >( n ) ) ); - } - - [[nodiscard]] static std::uint64_t convert( const std::uint64_t n ) noexcept - { - return __builtin_bswap64( n ); - } - }; - -#define TAO_JSON_PEGTL_NATIVE_ORDER be -#define TAO_JSON_PEGTL_NATIVE_UTF16 utf16_be -#define TAO_JSON_PEGTL_NATIVE_UTF32 utf32_be - -#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - - template< std::size_t S > - struct to_and_from_le - { - template< typename T > - [[nodiscard]] static T convert( const T n ) noexcept - { - return n; - } - }; - - template< std::size_t S > - struct to_and_from_be; - - template<> - struct to_and_from_be< 1 > - { - [[nodiscard]] static std::int8_t convert( const std::int8_t n ) noexcept - { - return n; - } - - [[nodiscard]] static std::uint8_t convert( const std::uint8_t n ) noexcept - { - return n; - } - }; - - template<> - struct to_and_from_be< 2 > - { - [[nodiscard]] static std::int16_t convert( const std::int16_t n ) noexcept - { - return static_cast< std::int16_t >( __builtin_bswap16( static_cast< std::uint16_t >( n ) ) ); - } - - [[nodiscard]] static std::uint16_t convert( const std::uint16_t n ) noexcept - { - return __builtin_bswap16( n ); - } - }; - - template<> - struct to_and_from_be< 4 > - { - [[nodiscard]] static float convert( float n ) noexcept - { - std::uint32_t u; - std::memcpy( &u, &n, 4 ); - u = convert( u ); - std::memcpy( &n, &u, 4 ); - return n; - } - - [[nodiscard]] static std::int32_t convert( const std::int32_t n ) noexcept - { - return static_cast< std::int32_t >( __builtin_bswap32( static_cast< std::uint32_t >( n ) ) ); - } - - [[nodiscard]] static std::uint32_t convert( const std::uint32_t n ) noexcept - { - return __builtin_bswap32( n ); - } - }; - - template<> - struct to_and_from_be< 8 > - { - [[nodiscard]] static double convert( double n ) noexcept - { - std::uint64_t u; - std::memcpy( &u, &n, 8 ); - u = convert( u ); - std::memcpy( &n, &u, 8 ); - return n; - } - - [[nodiscard]] static std::int64_t convert( const std::int64_t n ) noexcept - { - return static_cast< std::int64_t >( __builtin_bswap64( static_cast< std::uint64_t >( n ) ) ); - } - - [[nodiscard]] static std::uint64_t convert( const std::uint64_t n ) noexcept - { - return __builtin_bswap64( n ); - } - }; - -#define TAO_JSON_PEGTL_NATIVE_ORDER le -#define TAO_JSON_PEGTL_NATIVE_UTF16 utf16_le -#define TAO_JSON_PEGTL_NATIVE_UTF32 utf32_le - -#else -#error Unknown host byte order! -#endif - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/endian_win.hpp b/include/tao/json/external/pegtl/internal/endian_win.hpp deleted file mode 100644 index 4ca5ad77..00000000 --- a/include/tao/json/external/pegtl/internal/endian_win.hpp +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_ENDIAN_WIN_HPP -#define TAO_JSON_PEGTL_INTERNAL_ENDIAN_WIN_HPP - -#include -#include -#include - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< std::size_t S > - struct to_and_from_le - { - template< typename T > - [[nodiscard]] static T convert( const T t ) noexcept - { - return t; - } - }; - - template< std::size_t S > - struct to_and_from_be; - - template<> - struct to_and_from_be< 1 > - { - [[nodiscard]] static std::int8_t convert( const std::int8_t n ) noexcept - { - return n; - } - - [[nodiscard]] static std::uint8_t convert( const std::uint8_t n ) noexcept - { - return n; - } - }; - - template<> - struct to_and_from_be< 2 > - { - [[nodiscard]] static std::int16_t convert( const std::int16_t n ) noexcept - { - return std::int16_t( _byteswap_ushort( std::uint16_t( n ) ) ); - } - - [[nodiscard]] static std::uint16_t convert( const std::uint16_t n ) noexcept - { - return _byteswap_ushort( n ); - } - }; - - template<> - struct to_and_from_be< 4 > - { - [[nodiscard]] static float convert( float n ) noexcept - { - std::uint32_t u; - std::memcpy( &u, &n, 4 ); - u = convert( u ); - std::memcpy( &n, &u, 4 ); - return n; - } - - [[nodiscard]] static std::int32_t convert( const std::int32_t n ) noexcept - { - return std::int32_t( _byteswap_ulong( std::uint32_t( n ) ) ); - } - - [[nodiscard]] static std::uint32_t convert( const std::uint32_t n ) noexcept - { - return _byteswap_ulong( n ); - } - }; - - template<> - struct to_and_from_be< 8 > - { - [[nodiscard]] static double convert( double n ) noexcept - { - std::uint64_t u; - std::memcpy( &u, &n, 8 ); - u = convert( u ); - std::memcpy( &n, &u, 8 ); - return n; - } - - [[nodiscard]] static std::int64_t convert( const std::int64_t n ) noexcept - { - return std::int64_t( _byteswap_uint64( std::uint64_t( n ) ) ); - } - - [[nodiscard]] static std::uint64_t convert( const std::uint64_t n ) noexcept - { - return _byteswap_uint64( n ); - } - }; - -#define TAO_JSON_PEGTL_NATIVE_ORDER le -#define TAO_JSON_PEGTL_NATIVE_UTF16 utf16_le -#define TAO_JSON_PEGTL_NATIVE_UTF32 utf32_le - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/eof.hpp b/include/tao/json/external/pegtl/internal/eof.hpp deleted file mode 100644 index a567efe8..00000000 --- a/include/tao/json/external/pegtl/internal/eof.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_EOF_HPP -#define TAO_JSON_PEGTL_INTERNAL_EOF_HPP - -#include "../config.hpp" - -#include "skip_control.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct eof - { - using analyze_t = analysis::generic< analysis::rule_type::opt >; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.empty() ) ) - { - return in.empty(); - } - }; - - template<> - inline constexpr bool skip_control< eof > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/eol.hpp b/include/tao/json/external/pegtl/internal/eol.hpp deleted file mode 100644 index e7478907..00000000 --- a/include/tao/json/external/pegtl/internal/eol.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_EOL_HPP -#define TAO_JSON_PEGTL_INTERNAL_EOL_HPP - -#include "../config.hpp" - -#include "skip_control.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct eol - { - using analyze_t = analysis::generic< analysis::rule_type::any >; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( Input::eol_t::match( in ) ) ) - { - return Input::eol_t::match( in ).first; - } - }; - - template<> - inline constexpr bool skip_control< eol > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/eolf.hpp b/include/tao/json/external/pegtl/internal/eolf.hpp deleted file mode 100644 index c708a379..00000000 --- a/include/tao/json/external/pegtl/internal/eolf.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_EOLF_HPP -#define TAO_JSON_PEGTL_INTERNAL_EOLF_HPP - -#include "../config.hpp" - -#include "skip_control.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct eolf - { - using analyze_t = analysis::generic< analysis::rule_type::opt >; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( Input::eol_t::match( in ) ) ) - { - const auto p = Input::eol_t::match( in ); - return p.first || ( !p.second ); - } - }; - - template<> - inline constexpr bool skip_control< eolf > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/file_mapper_posix.hpp b/include/tao/json/external/pegtl/internal/file_mapper_posix.hpp deleted file mode 100644 index 5d37f4d0..00000000 --- a/include/tao/json/external/pegtl/internal/file_mapper_posix.hpp +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_FILE_MAPPER_POSIX_HPP -#define TAO_JSON_PEGTL_INTERNAL_FILE_MAPPER_POSIX_HPP - -#include -#include - -#include - -#include "../config.hpp" - -#include "file_opener.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - class file_mapper - { - public: - explicit file_mapper( const char* filename ) - : file_mapper( file_opener( filename ) ) - { - } - - explicit file_mapper( const file_opener& reader ) - : m_size( reader.size() ), - m_data( static_cast< const char* >( ::mmap( nullptr, m_size, PROT_READ, MAP_PRIVATE, reader.m_fd, 0 ) ) ) - { - if( ( m_size != 0 ) && ( intptr_t( m_data ) == -1 ) ) { - const auto ec = errno; - throw std::system_error( ec, std::system_category(), reader.m_source ); - } - } - - file_mapper( const file_mapper& ) = delete; - file_mapper( file_mapper&& ) = delete; - - ~file_mapper() noexcept - { - // Legacy C interface requires pointer-to-mutable but does not write through the pointer. - ::munmap( const_cast< char* >( m_data ), m_size ); - } - - void operator=( const file_mapper& ) = delete; - void operator=( file_mapper&& ) = delete; - - [[nodiscard]] bool empty() const noexcept - { - return m_size == 0; - } - - [[nodiscard]] std::size_t size() const noexcept - { - return m_size; - } - - using iterator = const char*; - using const_iterator = const char*; - - [[nodiscard]] iterator data() const noexcept - { - return m_data; - } - - [[nodiscard]] iterator begin() const noexcept - { - return m_data; - } - - [[nodiscard]] iterator end() const noexcept - { - return m_data + m_size; - } - - private: - const std::size_t m_size; - const char* const m_data; - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/file_mapper_win32.hpp b/include/tao/json/external/pegtl/internal/file_mapper_win32.hpp deleted file mode 100644 index 41880e0f..00000000 --- a/include/tao/json/external/pegtl/internal/file_mapper_win32.hpp +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_FILE_MAPPER_WIN32_HPP -#define TAO_JSON_PEGTL_INTERNAL_FILE_MAPPER_WIN32_HPP - -#if !defined( NOMINMAX ) -#define NOMINMAX -#define TAO_JSON_PEGTL_NOMINMAX_WAS_DEFINED -#endif - -#if !defined( WIN32_LEAN_AND_MEAN ) -#define WIN32_LEAN_AND_MEAN -#define TAO_JSON_PEGTL_WIN32_LEAN_AND_MEAN_WAS_DEFINED -#endif - -#include - -#if defined( TAO_JSON_PEGTL_NOMINMAX_WAS_DEFINED ) -#undef NOMINMAX -#undef TAO_JSON_PEGTL_NOMINMAX_WAS_DEFINED -#endif - -#if defined( TAO_JSON_PEGTL_WIN32_LEAN_AND_MEAN_WAS_DEFINED ) -#undef WIN32_LEAN_AND_MEAN -#undef TAO_JSON_PEGTL_WIN32_LEAN_AND_MEAN_WAS_DEFINED -#endif - -#include - -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct win32_file_opener - { - explicit win32_file_opener( const char* filename ) - : m_source( filename ), - m_handle( open() ) - { - } - - win32_file_opener( const win32_file_opener& ) = delete; - win32_file_opener( win32_file_opener&& ) = delete; - - ~win32_file_opener() noexcept - { - ::CloseHandle( m_handle ); - } - - void operator=( const win32_file_opener& ) = delete; - void operator=( win32_file_opener&& ) = delete; - - [[nodiscard]] std::size_t size() const - { - LARGE_INTEGER size; - if( !::GetFileSizeEx( m_handle, &size ) ) { - const auto ec = ::GetLastError(); - throw std::system_error( ec, std::system_category(), std::string( "GetFileSizeEx(): " ) + m_source ); - } - return std::size_t( size.QuadPart ); - } - - const char* const m_source; - const HANDLE m_handle; - - private: - [[nodiscard]] HANDLE open() const - { - SetLastError( 0 ); - std::wstring ws( m_source, m_source + strlen( m_source ) ); - -#if( _WIN32_WINNT >= 0x0602 ) - const HANDLE handle = ::CreateFile2( ws.c_str(), - GENERIC_READ, - FILE_SHARE_READ, - OPEN_EXISTING, - nullptr ); - if( handle != INVALID_HANDLE_VALUE ) { - return handle; - } - const auto ec = ::GetLastError(); - throw std::system_error( ec, std::system_category(), std::string( "CreateFile2(): " ) + m_source ); -#else - const HANDLE handle = ::CreateFileW( ws.c_str(), - GENERIC_READ, - FILE_SHARE_READ, - nullptr, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - nullptr ); - if( handle != INVALID_HANDLE_VALUE ) { - return handle; - } - const auto ec = ::GetLastError(); - throw std::system_error( ec, std::system_category(), std::string( "CreateFileW(): " ) + m_source ); -#endif - } - }; - - struct win32_file_mapper - { - explicit win32_file_mapper( const char* filename ) - : win32_file_mapper( win32_file_opener( filename ) ) - { - } - - explicit win32_file_mapper( const win32_file_opener& reader ) - : m_size( reader.size() ), - m_handle( open( reader ) ) - { - } - - win32_file_mapper( const win32_file_mapper& ) = delete; - win32_file_mapper( win32_file_mapper&& ) = delete; - - ~win32_file_mapper() noexcept - { - ::CloseHandle( m_handle ); - } - - void operator=( const win32_file_mapper& ) = delete; - void operator=( win32_file_mapper&& ) = delete; - - const size_t m_size; - const HANDLE m_handle; - - private: - [[nodiscard]] HANDLE open( const win32_file_opener& reader ) const - { - const uint64_t file_size = reader.size(); - SetLastError( 0 ); - // Use `CreateFileMappingW` because a) we're not specifying a - // mapping name, so the character type is of no consequence, and - // b) it's defined in `memoryapi.h`, unlike - // `CreateFileMappingA`(?!) - const HANDLE handle = ::CreateFileMappingW( reader.m_handle, - nullptr, - PAGE_READONLY, - DWORD( file_size >> 32 ), - DWORD( file_size & 0xffffffff ), - nullptr ); - if( handle != NULL || file_size == 0 ) { - return handle; - } - const auto ec = ::GetLastError(); - throw std::system_error( ec, std::system_category(), std::string( "CreateFileMappingW(): " ) + reader.m_source ); - } - }; - - class file_mapper - { - public: - explicit file_mapper( const char* filename ) - : file_mapper( win32_file_mapper( filename ) ) - { - } - - explicit file_mapper( const win32_file_mapper& mapper ) - : m_size( mapper.m_size ), - m_data( static_cast< const char* >( ::MapViewOfFile( mapper.m_handle, - FILE_MAP_READ, - 0, - 0, - 0 ) ) ) - { - if( ( m_size != 0 ) && ( intptr_t( m_data ) == 0 ) ) { - const auto ec = ::GetLastError(); - throw std::system_error( ec, std::system_category(), "MapViewOfFile()" ); - } - } - - file_mapper( const file_mapper& ) = delete; - file_mapper( file_mapper&& ) = delete; - - ~file_mapper() noexcept - { - ::UnmapViewOfFile( LPCVOID( m_data ) ); - } - - void operator=( const file_mapper& ) = delete; - void operator=( file_mapper&& ) = delete; - - [[nodiscard]] bool empty() const noexcept - { - return m_size == 0; - } - - [[nodiscard]] std::size_t size() const noexcept - { - return m_size; - } - - using iterator = const char*; - using const_iterator = const char*; - - [[nodiscard]] iterator data() const noexcept - { - return m_data; - } - - [[nodiscard]] iterator begin() const noexcept - { - return m_data; - } - - [[nodiscard]] iterator end() const noexcept - { - return m_data + m_size; - } - - private: - const std::size_t m_size; - const char* const m_data; - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/file_opener.hpp b/include/tao/json/external/pegtl/internal/file_opener.hpp deleted file mode 100644 index 00209086..00000000 --- a/include/tao/json/external/pegtl/internal/file_opener.hpp +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_FILE_OPENER_HPP -#define TAO_JSON_PEGTL_INTERNAL_FILE_OPENER_HPP - -#include -#include -#include -#include - -#include -#include - -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct file_opener - { - explicit file_opener( const char* filename ) - : m_source( filename ), - m_fd( open() ) - { - } - - file_opener( const file_opener& ) = delete; - file_opener( file_opener&& ) = delete; - - ~file_opener() noexcept - { - ::close( m_fd ); - } - - void operator=( const file_opener& ) = delete; - void operator=( file_opener&& ) = delete; - - [[nodiscard]] std::size_t size() const - { - struct stat st; - errno = 0; - if( ::fstat( m_fd, &st ) < 0 ) { - const auto ec = errno; - throw std::system_error( ec, std::system_category(), m_source ); - } - return std::size_t( st.st_size ); - } - - const char* const m_source; - const int m_fd; - - private: - [[nodiscard]] int open() const - { - errno = 0; - const int fd = ::open( m_source, - O_RDONLY -#if defined( O_CLOEXEC ) - | O_CLOEXEC -#endif - ); - if( fd >= 0 ) { - return fd; - } - const auto ec = errno; - throw std::system_error( ec, std::system_category(), m_source ); - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/file_reader.hpp b/include/tao/json/external/pegtl/internal/file_reader.hpp deleted file mode 100644 index 92bfd5c5..00000000 --- a/include/tao/json/external/pegtl/internal/file_reader.hpp +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_FILE_READER_HPP -#define TAO_JSON_PEGTL_INTERNAL_FILE_READER_HPP - -#include -#include -#include -#include -#include - -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - [[nodiscard]] inline std::FILE* file_open( const char* filename ) - { - errno = 0; -#if defined( _MSC_VER ) - std::FILE* file; - if( ::fopen_s( &file, filename, "rb" ) == 0 ) -#elif defined( __MINGW32__ ) - if( auto* file = std::fopen( filename, "rb" ) ) -#else - if( auto* file = std::fopen( filename, "rbe" ) ) -#endif - { - return file; - } - const auto ec = errno; - throw std::system_error( ec, std::system_category(), filename ); - } - - struct file_close - { - void operator()( FILE* f ) const noexcept - { - std::fclose( f ); - } - }; - - class file_reader - { - public: - explicit file_reader( const char* filename ) - : m_source( filename ), - m_file( file_open( m_source ) ) - { - } - - file_reader( FILE* file, const char* filename ) noexcept - : m_source( filename ), - m_file( file ) - { - } - - file_reader( const file_reader& ) = delete; - file_reader( file_reader&& ) = delete; - - ~file_reader() = default; - - void operator=( const file_reader& ) = delete; - void operator=( file_reader&& ) = delete; - - [[nodiscard]] std::size_t size() const - { - errno = 0; - if( std::fseek( m_file.get(), 0, SEEK_END ) != 0 ) { - // LCOV_EXCL_START - const auto ec = errno; - throw std::system_error( ec, std::system_category(), m_source ); - // LCOV_EXCL_STOP - } - errno = 0; - const auto s = std::ftell( m_file.get() ); - if( s < 0 ) { - // LCOV_EXCL_START - const auto ec = errno; - throw std::system_error( ec, std::system_category(), m_source ); - // LCOV_EXCL_STOP - } - errno = 0; - if( std::fseek( m_file.get(), 0, SEEK_SET ) != 0 ) { - // LCOV_EXCL_START - const auto ec = errno; - throw std::system_error( ec, std::system_category(), m_source ); - // LCOV_EXCL_STOP - } - return std::size_t( s ); - } - - [[nodiscard]] std::string read() const - { - std::string nrv; - nrv.resize( size() ); - errno = 0; - if( !nrv.empty() && ( std::fread( &nrv[ 0 ], nrv.size(), 1, m_file.get() ) != 1 ) ) { - // LCOV_EXCL_START - const auto ec = errno; - throw std::system_error( ec, std::system_category(), m_source ); - // LCOV_EXCL_STOP - } - return nrv; - } - - private: - const char* const m_source; - const std::unique_ptr< std::FILE, file_close > m_file; - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/has_apply.hpp b/include/tao/json/external/pegtl/internal/has_apply.hpp deleted file mode 100644 index 93adec68..00000000 --- a/include/tao/json/external/pegtl/internal/has_apply.hpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_HAS_APPLY_HPP -#define TAO_JSON_PEGTL_INTERNAL_HAS_APPLY_HPP - -#include - -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename, typename, template< typename... > class, typename... > - struct has_apply - : std::false_type - {}; - - template< typename C, template< typename... > class Action, typename... S > - struct has_apply< C, decltype( C::template apply< Action >( std::declval< S >()... ) ), Action, S... > - : std::true_type - {}; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/has_apply0.hpp b/include/tao/json/external/pegtl/internal/has_apply0.hpp deleted file mode 100644 index 2c67c871..00000000 --- a/include/tao/json/external/pegtl/internal/has_apply0.hpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_HAS_APPLY0_HPP -#define TAO_JSON_PEGTL_INTERNAL_HAS_APPLY0_HPP - -#include - -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename, typename, template< typename... > class, typename... > - struct has_apply0 - : std::false_type - {}; - - template< typename C, template< typename... > class Action, typename... S > - struct has_apply0< C, decltype( C::template apply0< Action >( std::declval< S >()... ) ), Action, S... > - : std::true_type - {}; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/has_match.hpp b/include/tao/json/external/pegtl/internal/has_match.hpp deleted file mode 100644 index 017901b8..00000000 --- a/include/tao/json/external/pegtl/internal/has_match.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_HAS_MATCH_HPP -#define TAO_JSON_PEGTL_INTERNAL_HAS_MATCH_HPP - -#include -#include - -#include "../apply_mode.hpp" -#include "../config.hpp" -#include "../rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename, - typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - struct has_match - : std::false_type - {}; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - struct has_match< decltype( (void)Action< Rule >::template match< Rule, A, M, Action, Control >( std::declval< Input& >(), std::declval< States&& >()... ), void() ), Rule, A, M, Action, Control, Input, States... > - : std::true_type - {}; - - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - inline constexpr bool has_match_v = has_match< void, Rule, A, M, Action, Control, Input, States... >::value; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/identifier.hpp b/include/tao/json/external/pegtl/internal/identifier.hpp deleted file mode 100644 index 4e69b9f6..00000000 --- a/include/tao/json/external/pegtl/internal/identifier.hpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_IDENTIFIER_HPP -#define TAO_JSON_PEGTL_INTERNAL_IDENTIFIER_HPP - -#include "../config.hpp" - -#include "peek_char.hpp" -#include "ranges.hpp" -#include "seq.hpp" -#include "star.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - using identifier_first = ranges< peek_char, 'a', 'z', 'A', 'Z', '_' >; - using identifier_other = ranges< peek_char, 'a', 'z', 'A', 'Z', '0', '9', '_' >; - using identifier = seq< identifier_first, star< identifier_other > >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/if_apply.hpp b/include/tao/json/external/pegtl/internal/if_apply.hpp deleted file mode 100644 index a8a4eb0a..00000000 --- a/include/tao/json/external/pegtl/internal/if_apply.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_IF_APPLY_HPP -#define TAO_JSON_PEGTL_INTERNAL_IF_APPLY_HPP - -#include "../config.hpp" - -#include "apply_single.hpp" -#include "skip_control.hpp" - -#include "../analysis/counted.hpp" -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Rule, typename... Actions > - struct if_apply - { - using analyze_t = typename Rule::analyze_t; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - if constexpr( ( A == apply_mode::action ) && ( sizeof...( Actions ) != 0 ) ) { - using action_t = typename Input::action_t; - auto m = in.template mark< rewind_mode::required >(); - if( Control< Rule >::template match< apply_mode::action, rewind_mode::active, Action, Control >( in, st... ) ) { - const action_t i2( m.iterator(), in ); - return m( ( apply_single< Actions >::match( i2, st... ) && ... ) ); - } - return false; - } - else { - return Control< Rule >::template match< A, M, Action, Control >( in, st... ); - } - } - }; - - template< typename Rule, typename... Actions > - inline constexpr bool skip_control< if_apply< Rule, Actions... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/if_must.hpp b/include/tao/json/external/pegtl/internal/if_must.hpp deleted file mode 100644 index 067d4d51..00000000 --- a/include/tao/json/external/pegtl/internal/if_must.hpp +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_IF_MUST_HPP -#define TAO_JSON_PEGTL_INTERNAL_IF_MUST_HPP - -#include "../config.hpp" - -#include "must.hpp" -#include "skip_control.hpp" -#include "trivial.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/counted.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< bool Default, typename Cond, typename... Rules > - struct if_must - { - using analyze_t = analysis::counted< analysis::rule_type::seq, Default ? 0 : 1, Cond, must< Rules... > >; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - if( Control< Cond >::template match< A, M, Action, Control >( in, st... ) ) { - (void)( Control< must< Rules > >::template match< A, M, Action, Control >( in, st... ) && ... ); - return true; - } - return Default; - } - }; - - template< bool Default, typename Cond, typename... Rules > - inline constexpr bool skip_control< if_must< Default, Cond, Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/if_must_else.hpp b/include/tao/json/external/pegtl/internal/if_must_else.hpp deleted file mode 100644 index 0832772c..00000000 --- a/include/tao/json/external/pegtl/internal/if_must_else.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_IF_MUST_ELSE_HPP -#define TAO_JSON_PEGTL_INTERNAL_IF_MUST_ELSE_HPP - -#include "../config.hpp" - -#include "if_then_else.hpp" -#include "must.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Cond, typename Then, typename Else > - using if_must_else = if_then_else< Cond, must< Then >, must< Else > >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/if_then_else.hpp b/include/tao/json/external/pegtl/internal/if_then_else.hpp deleted file mode 100644 index 26c2623d..00000000 --- a/include/tao/json/external/pegtl/internal/if_then_else.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_IF_THEN_ELSE_HPP -#define TAO_JSON_PEGTL_INTERNAL_IF_THEN_ELSE_HPP - -#include "../config.hpp" - -#include "not_at.hpp" -#include "seq.hpp" -#include "skip_control.hpp" -#include "sor.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Cond, typename Then, typename Else > - struct if_then_else - { - using analyze_t = analysis::generic< analysis::rule_type::sor, seq< Cond, Then >, seq< not_at< Cond >, Else > >; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< M >(); - using m_t = decltype( m ); - - if( Control< Cond >::template match< A, rewind_mode::required, Action, Control >( in, st... ) ) { - return m( Control< Then >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) ); - } - return m( Control< Else >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) ); - } - }; - - template< typename Cond, typename Then, typename Else > - inline constexpr bool skip_control< if_then_else< Cond, Then, Else > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/input_pair.hpp b/include/tao/json/external/pegtl/internal/input_pair.hpp deleted file mode 100644 index b97f177d..00000000 --- a/include/tao/json/external/pegtl/internal/input_pair.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_INPUT_PAIR_HPP -#define TAO_JSON_PEGTL_INTERNAL_INPUT_PAIR_HPP - -#include - -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Data > - struct input_pair - { - Data data; - std::uint8_t size; - - using data_t = Data; - - explicit operator bool() const noexcept - { - return size > 0; - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/istream_reader.hpp b/include/tao/json/external/pegtl/internal/istream_reader.hpp deleted file mode 100644 index 25f5b7af..00000000 --- a/include/tao/json/external/pegtl/internal/istream_reader.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_ISTREAM_READER_HPP -#define TAO_JSON_PEGTL_INTERNAL_ISTREAM_READER_HPP - -#include -#include - -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct istream_reader - { - explicit istream_reader( std::istream& s ) noexcept - : m_istream( s ) - { - } - - [[nodiscard]] std::size_t operator()( char* buffer, const std::size_t length ) - { - m_istream.read( buffer, std::streamsize( length ) ); - - if( const auto r = m_istream.gcount() ) { - return std::size_t( r ); - } - if( m_istream.eof() ) { - return 0; - } - const auto ec = errno; - throw std::system_error( ec, std::system_category(), "std::istream::read() failed" ); - } - - std::istream& m_istream; - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/istring.hpp b/include/tao/json/external/pegtl/internal/istring.hpp deleted file mode 100644 index 6f21c570..00000000 --- a/include/tao/json/external/pegtl/internal/istring.hpp +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_ISTRING_HPP -#define TAO_JSON_PEGTL_INTERNAL_ISTRING_HPP - -#include - -#include "../config.hpp" - -#include "bump_help.hpp" -#include "result_on_found.hpp" -#include "skip_control.hpp" -#include "trivial.hpp" - -#include "../analysis/counted.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< char C > - inline constexpr bool is_alpha = ( ( 'a' <= C ) && ( C <= 'z' ) ) || ( ( 'A' <= C ) && ( C <= 'Z' ) ); - - template< char C > - [[nodiscard]] bool ichar_equal( const char c ) noexcept - { - if constexpr( is_alpha< C > ) { - return ( C | 0x20 ) == ( c | 0x20 ); - } - else { - return c == C; - } - } - - template< char... Cs > - [[nodiscard]] bool istring_equal( const char* r ) noexcept - { - return ( ichar_equal< Cs >( *r++ ) && ... ); - } - - template< char... Cs > - struct istring; - - template<> - struct istring<> - : trivial< true > - { - }; - - template< char... Cs > - struct istring - { - using analyze_t = analysis::counted< analysis::rule_type::any, sizeof...( Cs ) >; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( 0 ) ) ) - { - if( in.size( sizeof...( Cs ) ) >= sizeof...( Cs ) ) { - if( istring_equal< Cs... >( in.current() ) ) { - bump_help< result_on_found::success, Input, char, Cs... >( in, sizeof...( Cs ) ); - return true; - } - } - return false; - } - }; - - template< char... Cs > - inline constexpr bool skip_control< istring< Cs... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/iterator.hpp b/include/tao/json/external/pegtl/internal/iterator.hpp deleted file mode 100644 index cc2c96f3..00000000 --- a/include/tao/json/external/pegtl/internal/iterator.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_ITERATOR_HPP -#define TAO_JSON_PEGTL_INTERNAL_ITERATOR_HPP - -#include - -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct iterator - { - iterator() = default; - - explicit iterator( const char* in_data ) noexcept - : data( in_data ) - { - } - - iterator( const char* in_data, const std::size_t in_byte, const std::size_t in_line, const std::size_t in_byte_in_line ) noexcept - : data( in_data ), - byte( in_byte ), - line( in_line ), - byte_in_line( in_byte_in_line ) - { - } - - iterator( const iterator& ) = default; - iterator( iterator&& ) = default; - - ~iterator() = default; - - iterator& operator=( const iterator& ) = default; - iterator& operator=( iterator&& ) = default; - - void reset() noexcept - { - *this = iterator(); - } - - const char* data = nullptr; - - std::size_t byte = 0; - std::size_t line = 1; - std::size_t byte_in_line = 0; - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/lf_crlf_eol.hpp b/include/tao/json/external/pegtl/internal/lf_crlf_eol.hpp deleted file mode 100644 index aefef00a..00000000 --- a/include/tao/json/external/pegtl/internal/lf_crlf_eol.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_LF_CRLF_EOL_HPP -#define TAO_JSON_PEGTL_INTERNAL_LF_CRLF_EOL_HPP - -#include "../config.hpp" -#include "../eol_pair.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct lf_crlf_eol - { - static constexpr int ch = '\n'; - - template< typename Input > - [[nodiscard]] static eol_pair match( Input& in ) noexcept( noexcept( in.size( 2 ) ) ) - { - eol_pair p = { false, in.size( 2 ) }; - if( p.second ) { - const auto a = in.peek_char(); - if( a == '\n' ) { - in.bump_to_next_line(); - p.first = true; - } - else if( ( a == '\r' ) && ( p.second > 1 ) && ( in.peek_char( 1 ) == '\n' ) ) { - in.bump_to_next_line( 2 ); - p.first = true; - } - } - return p; - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/lf_eol.hpp b/include/tao/json/external/pegtl/internal/lf_eol.hpp deleted file mode 100644 index 6d8d418d..00000000 --- a/include/tao/json/external/pegtl/internal/lf_eol.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_LF_EOL_HPP -#define TAO_JSON_PEGTL_INTERNAL_LF_EOL_HPP - -#include "../config.hpp" -#include "../eol_pair.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct lf_eol - { - static constexpr int ch = '\n'; - - template< typename Input > - [[nodiscard]] static eol_pair match( Input& in ) noexcept( noexcept( in.size( 1 ) ) ) - { - eol_pair p = { false, in.size( 1 ) }; - if( p.second ) { - if( in.peek_char() == '\n' ) { - in.bump_to_next_line(); - p.first = true; - } - } - return p; - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/list.hpp b/include/tao/json/external/pegtl/internal/list.hpp deleted file mode 100644 index b9ef9353..00000000 --- a/include/tao/json/external/pegtl/internal/list.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_LIST_HPP -#define TAO_JSON_PEGTL_INTERNAL_LIST_HPP - -#include "../config.hpp" - -#include "seq.hpp" -#include "star.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Rule, typename Sep > - using list = seq< Rule, star< Sep, Rule > >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/list_must.hpp b/include/tao/json/external/pegtl/internal/list_must.hpp deleted file mode 100644 index ce5a505e..00000000 --- a/include/tao/json/external/pegtl/internal/list_must.hpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_LIST_MUST_HPP -#define TAO_JSON_PEGTL_INTERNAL_LIST_MUST_HPP - -#include "../config.hpp" - -#include "must.hpp" -#include "seq.hpp" -#include "star.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Rule, typename Sep > - using list_must = seq< Rule, star< Sep, must< Rule > > >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/list_tail.hpp b/include/tao/json/external/pegtl/internal/list_tail.hpp deleted file mode 100644 index 24195a14..00000000 --- a/include/tao/json/external/pegtl/internal/list_tail.hpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_LIST_TAIL_HPP -#define TAO_JSON_PEGTL_INTERNAL_LIST_TAIL_HPP - -#include "../config.hpp" - -#include "list.hpp" -#include "opt.hpp" -#include "seq.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Rule, typename Sep > - using list_tail = seq< list< Rule, Sep >, opt< Sep > >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/list_tail_pad.hpp b/include/tao/json/external/pegtl/internal/list_tail_pad.hpp deleted file mode 100644 index 531c66a3..00000000 --- a/include/tao/json/external/pegtl/internal/list_tail_pad.hpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_LIST_TAIL_PAD_HPP -#define TAO_JSON_PEGTL_INTERNAL_LIST_TAIL_PAD_HPP - -#include "../config.hpp" - -#include "list.hpp" -#include "opt.hpp" -#include "pad.hpp" -#include "seq.hpp" -#include "star.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Rule, typename Sep, typename Pad > - using list_tail_pad = seq< list< Rule, pad< Sep, Pad > >, opt< star< Pad >, Sep > >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/marker.hpp b/include/tao/json/external/pegtl/internal/marker.hpp deleted file mode 100644 index 4e7812c3..00000000 --- a/include/tao/json/external/pegtl/internal/marker.hpp +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_MARKER_HPP -#define TAO_JSON_PEGTL_INTERNAL_MARKER_HPP - -#include "../config.hpp" -#include "../rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Iterator, rewind_mode M > - class marker - { - public: - static constexpr rewind_mode next_rewind_mode = M; - - explicit marker( const Iterator& /*unused*/ ) noexcept - { - } - - marker( const marker& ) = delete; - marker( marker&& ) = delete; - - ~marker() = default; - - void operator=( const marker& ) = delete; - void operator=( marker&& ) = delete; - - [[nodiscard]] bool operator()( const bool result ) const noexcept - { - return result; - } - }; - - template< typename Iterator > - class marker< Iterator, rewind_mode::required > - { - public: - static constexpr rewind_mode next_rewind_mode = rewind_mode::active; - - explicit marker( Iterator& i ) noexcept - : m_saved( i ), - m_input( &i ) - { - } - - marker( const marker& ) = delete; - marker( marker&& ) = delete; - - ~marker() noexcept - { - if( m_input != nullptr ) { - ( *m_input ) = m_saved; - } - } - - void operator=( const marker& ) = delete; - void operator=( marker&& ) = delete; - - [[nodiscard]] bool operator()( const bool result ) noexcept - { - if( result ) { - m_input = nullptr; - return true; - } - return false; - } - - [[nodiscard]] const Iterator& iterator() const noexcept - { - return m_saved; - } - - private: - const Iterator m_saved; - Iterator* m_input; - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/missing_apply.hpp b/include/tao/json/external/pegtl/internal/missing_apply.hpp deleted file mode 100644 index 5a5483c7..00000000 --- a/include/tao/json/external/pegtl/internal/missing_apply.hpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_MISSING_APPLY_HPP -#define TAO_JSON_PEGTL_INTERNAL_MISSING_APPLY_HPP - -#include "../config.hpp" -#include "../rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Control, - template< typename... > - class Action, - typename Input, - typename... States > - void missing_apply( Input& in, States&&... st ) - { - auto m = in.template mark< rewind_mode::required >(); - (void)Control::template apply< Action >( m.iterator(), in, st... ); - } - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/missing_apply0.hpp b/include/tao/json/external/pegtl/internal/missing_apply0.hpp deleted file mode 100644 index de53e3e0..00000000 --- a/include/tao/json/external/pegtl/internal/missing_apply0.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_MISSING_APPLY0_HPP -#define TAO_JSON_PEGTL_INTERNAL_MISSING_APPLY0_HPP - -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Control, - template< typename... > - class Action, - typename Input, - typename... States > - void missing_apply0( Input& in, States&&... st ) - { - (void)Control::template apply0< Action >( in, st... ); - } - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/must.hpp b/include/tao/json/external/pegtl/internal/must.hpp deleted file mode 100644 index fd274aa4..00000000 --- a/include/tao/json/external/pegtl/internal/must.hpp +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_MUST_HPP -#define TAO_JSON_PEGTL_INTERNAL_MUST_HPP - -#include "../config.hpp" - -#include "raise.hpp" -#include "skip_control.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - // The general case applies must<> to each of the - // rules in the 'Rules' parameter pack individually. - - template< typename... Rules > - struct must - { - using analyze_t = analysis::generic< analysis::rule_type::seq, Rules... >; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - return ( Control< must< Rules > >::template match< A, M, Action, Control >( in, st... ) && ... ); - } - }; - - // While in theory the implementation for a single rule could - // be simplified to must< Rule > = sor< Rule, raise< Rule > >, this - // would result in some unnecessary run-time overhead. - - template< typename Rule > - struct must< Rule > - { - using analyze_t = typename Rule::analyze_t; - - template< apply_mode A, - rewind_mode, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - if( !Control< Rule >::template match< A, rewind_mode::dontcare, Action, Control >( in, st... ) ) { - (void)raise< Rule >::template match< A, rewind_mode::dontcare, Action, Control >( in, st... ); - } - return true; - } - }; - - template< typename... Rules > - inline constexpr bool skip_control< must< Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/not_at.hpp b/include/tao/json/external/pegtl/internal/not_at.hpp deleted file mode 100644 index 8db18427..00000000 --- a/include/tao/json/external/pegtl/internal/not_at.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_NOT_AT_HPP -#define TAO_JSON_PEGTL_INTERNAL_NOT_AT_HPP - -#include "../config.hpp" - -#include "skip_control.hpp" -#include "trivial.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename... Rules > - struct not_at; - - template<> - struct not_at<> - : trivial< false > - { - }; - - template< typename... Rules > - struct not_at - { - using analyze_t = analysis::generic< analysis::rule_type::opt, Rules... >; - - template< apply_mode, - rewind_mode, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - const auto m = in.template mark< rewind_mode::required >(); - return !( Control< Rules >::template match< apply_mode::nothing, rewind_mode::active, Action, Control >( in, st... ) && ... ); - } - }; - - template< typename... Rules > - inline constexpr bool skip_control< not_at< Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/one.hpp b/include/tao/json/external/pegtl/internal/one.hpp deleted file mode 100644 index 98cd0514..00000000 --- a/include/tao/json/external/pegtl/internal/one.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_ONE_HPP -#define TAO_JSON_PEGTL_INTERNAL_ONE_HPP - -#include - -#include "../config.hpp" - -#include "bump_help.hpp" -#include "result_on_found.hpp" -#include "skip_control.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< result_on_found R, typename Peek, typename Peek::data_t... Cs > - struct one - { - using analyze_t = analysis::generic< analysis::rule_type::any >; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( Peek::max_input_size ) ) ) - { - if( const std::size_t s = in.size( Peek::max_input_size ); s >= Peek::min_input_size ) { - if( const auto t = Peek::peek( in, s ) ) { - if( ( ( t.data == Cs ) || ... ) == bool( R ) ) { - bump_help< R, Input, typename Peek::data_t, Cs... >( in, t.size ); - return true; - } - } - } - return false; - } - }; - - template< result_on_found R, typename Peek, typename Peek::data_t... Cs > - inline constexpr bool skip_control< one< R, Peek, Cs... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/opt.hpp b/include/tao/json/external/pegtl/internal/opt.hpp deleted file mode 100644 index 8cd60756..00000000 --- a/include/tao/json/external/pegtl/internal/opt.hpp +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_OPT_HPP -#define TAO_JSON_PEGTL_INTERNAL_OPT_HPP - -#include - -#include "../config.hpp" - -#include "duseltronik.hpp" -#include "seq.hpp" -#include "skip_control.hpp" -#include "trivial.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename... Rules > - struct opt; - - template<> - struct opt<> - : trivial< true > - { - }; - - template< typename... Rules > - struct opt - { - using analyze_t = analysis::generic< analysis::rule_type::opt, Rules... >; - - template< apply_mode A, - rewind_mode, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - (void)duseltronik< seq< Rules... >, A, rewind_mode::required, Action, Control >::match( in, st... ); - return true; - } - }; - - template< typename... Rules > - inline constexpr bool skip_control< opt< Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/pad.hpp b/include/tao/json/external/pegtl/internal/pad.hpp deleted file mode 100644 index 18fed7c0..00000000 --- a/include/tao/json/external/pegtl/internal/pad.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_PAD_HPP -#define TAO_JSON_PEGTL_INTERNAL_PAD_HPP - -#include "../config.hpp" - -#include "seq.hpp" -#include "star.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Rule, typename Pad1, typename Pad2 = Pad1 > - using pad = seq< star< Pad1 >, Rule, star< Pad2 > >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/pad_opt.hpp b/include/tao/json/external/pegtl/internal/pad_opt.hpp deleted file mode 100644 index 933caed9..00000000 --- a/include/tao/json/external/pegtl/internal/pad_opt.hpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_PAD_OPT_HPP -#define TAO_JSON_PEGTL_INTERNAL_PAD_OPT_HPP - -#include "../config.hpp" - -#include "opt.hpp" -#include "seq.hpp" -#include "star.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Rule, typename Pad > - using pad_opt = seq< star< Pad >, opt< Rule, star< Pad > > >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/peek_char.hpp b/include/tao/json/external/pegtl/internal/peek_char.hpp deleted file mode 100644 index 88b94512..00000000 --- a/include/tao/json/external/pegtl/internal/peek_char.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_PEEK_CHAR_HPP -#define TAO_JSON_PEGTL_INTERNAL_PEEK_CHAR_HPP - -#include - -#include "../config.hpp" - -#include "input_pair.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct peek_char - { - using data_t = char; - using pair_t = input_pair< char >; - - static constexpr std::size_t min_input_size = 1; - static constexpr std::size_t max_input_size = 1; - - template< typename Input > - [[nodiscard]] static pair_t peek( const Input& in, const std::size_t /*unused*/ = 1 ) noexcept - { - return { in.peek_char(), 1 }; - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/peek_mask_uint.hpp b/include/tao/json/external/pegtl/internal/peek_mask_uint.hpp deleted file mode 100644 index 97248f0d..00000000 --- a/include/tao/json/external/pegtl/internal/peek_mask_uint.hpp +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_PEEK_MASK_UINT_HPP -#define TAO_JSON_PEGTL_INTERNAL_PEEK_MASK_UINT_HPP - -#include -#include - -#include "../config.hpp" - -#include "input_pair.hpp" -#include "read_uint.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename R, typename R::type M > - struct peek_mask_uint_impl - { - using data_t = typename R::type; - using pair_t = input_pair< data_t >; - - static constexpr std::size_t min_input_size = sizeof( data_t ); - static constexpr std::size_t max_input_size = sizeof( data_t ); - - template< typename Input > - [[nodiscard]] static pair_t peek( const Input& in, const std::size_t /*unused*/ ) noexcept - { - const data_t data = R::read( in.current() ) & M; - return { data, sizeof( data_t ) }; - } - }; - - template< std::uint16_t M > - using peek_mask_uint16_be = peek_mask_uint_impl< read_uint16_be, M >; - - template< std::uint16_t M > - using peek_mask_uint16_le = peek_mask_uint_impl< read_uint16_le, M >; - - template< std::uint32_t M > - using peek_mask_uint32_be = peek_mask_uint_impl< read_uint32_be, M >; - - template< std::uint32_t M > - using peek_mask_uint32_le = peek_mask_uint_impl< read_uint32_le, M >; - - template< std::uint64_t M > - using peek_mask_uint64_be = peek_mask_uint_impl< read_uint64_be, M >; - - template< std::uint64_t M > - using peek_mask_uint64_le = peek_mask_uint_impl< read_uint64_le, M >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/peek_mask_uint8.hpp b/include/tao/json/external/pegtl/internal/peek_mask_uint8.hpp deleted file mode 100644 index c64d0913..00000000 --- a/include/tao/json/external/pegtl/internal/peek_mask_uint8.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_PEEK_MASK_UINT8_HPP -#define TAO_JSON_PEGTL_INTERNAL_PEEK_MASK_UINT8_HPP - -#include -#include - -#include "../config.hpp" - -#include "input_pair.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< std::uint8_t M > - struct peek_mask_uint8 - { - using data_t = std::uint8_t; - using pair_t = input_pair< std::uint8_t >; - - static constexpr std::size_t min_input_size = 1; - static constexpr std::size_t max_input_size = 1; - - template< typename Input > - [[nodiscard]] static pair_t peek( const Input& in, const std::size_t /*unused*/ = 1 ) noexcept - { - return { std::uint8_t( in.peek_uint8() & M ), 1 }; - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/peek_uint.hpp b/include/tao/json/external/pegtl/internal/peek_uint.hpp deleted file mode 100644 index 95aaaabe..00000000 --- a/include/tao/json/external/pegtl/internal/peek_uint.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_PEEK_UINT_HPP -#define TAO_JSON_PEGTL_INTERNAL_PEEK_UINT_HPP - -#include -#include - -#include "../config.hpp" - -#include "input_pair.hpp" -#include "read_uint.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename R > - struct peek_uint_impl - { - using data_t = typename R::type; - using pair_t = input_pair< data_t >; - - static constexpr std::size_t min_input_size = sizeof( data_t ); - static constexpr std::size_t max_input_size = sizeof( data_t ); - - template< typename Input > - [[nodiscard]] static pair_t peek( const Input& in, const std::size_t /*unused*/ ) noexcept - { - const data_t data = R::read( in.current() ); - return { data, sizeof( data_t ) }; - } - }; - - using peek_uint16_be = peek_uint_impl< read_uint16_be >; - using peek_uint16_le = peek_uint_impl< read_uint16_le >; - - using peek_uint32_be = peek_uint_impl< read_uint32_be >; - using peek_uint32_le = peek_uint_impl< read_uint32_le >; - - using peek_uint64_be = peek_uint_impl< read_uint64_be >; - using peek_uint64_le = peek_uint_impl< read_uint64_le >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/peek_uint8.hpp b/include/tao/json/external/pegtl/internal/peek_uint8.hpp deleted file mode 100644 index 6f439b54..00000000 --- a/include/tao/json/external/pegtl/internal/peek_uint8.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_PEEK_UINT8_HPP -#define TAO_JSON_PEGTL_INTERNAL_PEEK_UINT8_HPP - -#include -#include - -#include "../config.hpp" - -#include "input_pair.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct peek_uint8 - { - using data_t = std::uint8_t; - using pair_t = input_pair< std::uint8_t >; - - static constexpr std::size_t min_input_size = 1; - static constexpr std::size_t max_input_size = 1; - - template< typename Input > - [[nodiscard]] static pair_t peek( const Input& in, const std::size_t /*unused*/ = 1 ) noexcept - { - return { in.peek_uint8(), 1 }; - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/peek_utf16.hpp b/include/tao/json/external/pegtl/internal/peek_utf16.hpp deleted file mode 100644 index c5172b45..00000000 --- a/include/tao/json/external/pegtl/internal/peek_utf16.hpp +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_PEEK_UTF16_HPP -#define TAO_JSON_PEGTL_INTERNAL_PEEK_UTF16_HPP - -#include - -#include "../config.hpp" - -#include "input_pair.hpp" -#include "read_uint.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename R > - struct peek_utf16_impl - { - using data_t = char32_t; - using pair_t = input_pair< char32_t >; - - using short_t = std::make_unsigned< char16_t >::type; - - static_assert( sizeof( short_t ) == 2 ); - static_assert( sizeof( char16_t ) == 2 ); - - static constexpr std::size_t min_input_size = 2; - static constexpr std::size_t max_input_size = 4; - - template< typename Input > - [[nodiscard]] static pair_t peek( const Input& in, const std::size_t s ) noexcept - { - const char32_t t = R::read( in.current() ); - if( ( t < 0xd800 ) || ( t > 0xdfff ) ) { - return { t, 2 }; - } - if( ( t >= 0xdc00 ) || ( s < 4 ) ) { - return { 0, 0 }; - } - const char32_t u = R::read( in.current() + 2 ); - if( ( u >= 0xdc00 ) && ( u <= 0xdfff ) ) { - const auto cp = ( ( ( t & 0x03ff ) << 10 ) | ( u & 0x03ff ) ) + 0x10000; - return { cp, 4 }; - } - return { 0, 0 }; - } - }; - - using peek_utf16_be = peek_utf16_impl< read_uint16_be >; - using peek_utf16_le = peek_utf16_impl< read_uint16_le >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/peek_utf32.hpp b/include/tao/json/external/pegtl/internal/peek_utf32.hpp deleted file mode 100644 index 32c2a721..00000000 --- a/include/tao/json/external/pegtl/internal/peek_utf32.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_PEEK_UTF32_HPP -#define TAO_JSON_PEGTL_INTERNAL_PEEK_UTF32_HPP - -#include - -#include "../config.hpp" - -#include "input_pair.hpp" -#include "read_uint.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename R > - struct peek_utf32_impl - { - using data_t = char32_t; - using pair_t = input_pair< char32_t >; - - static_assert( sizeof( char32_t ) == 4 ); - - static constexpr std::size_t min_input_size = 4; - static constexpr std::size_t max_input_size = 4; - - template< typename Input > - [[nodiscard]] static pair_t peek( const Input& in, const std::size_t /*unused*/ ) noexcept - { - const char32_t t = R::read( in.current() ); - if( ( t <= 0x10ffff ) && !( t >= 0xd800 && t <= 0xdfff ) ) { - return { t, 4 }; - } - return { 0, 0 }; - } - }; - - using peek_utf32_be = peek_utf32_impl< read_uint32_be >; - using peek_utf32_le = peek_utf32_impl< read_uint32_le >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/peek_utf8.hpp b/include/tao/json/external/pegtl/internal/peek_utf8.hpp deleted file mode 100644 index f9d50d96..00000000 --- a/include/tao/json/external/pegtl/internal/peek_utf8.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_PEEK_UTF8_HPP -#define TAO_JSON_PEGTL_INTERNAL_PEEK_UTF8_HPP - -#include "../config.hpp" - -#include "input_pair.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct peek_utf8 - { - using data_t = char32_t; - using pair_t = input_pair< char32_t >; - - static constexpr std::size_t min_input_size = 1; - static constexpr std::size_t max_input_size = 4; - - template< typename Input > - [[nodiscard]] static pair_t peek( const Input& in, const std::size_t s ) noexcept - { - char32_t c0 = in.peek_uint8(); - - if( ( c0 & 0x80 ) == 0 ) { - return { c0, 1 }; - } - return peek_impl( in, c0, s ); - } - - private: - template< typename Input > - [[nodiscard]] static pair_t peek_impl( const Input& in, char32_t c0, const std::size_t s ) noexcept - { - if( ( c0 & 0xE0 ) == 0xC0 ) { - if( s >= 2 ) { - const char32_t c1 = in.peek_uint8( 1 ); - if( ( c1 & 0xC0 ) == 0x80 ) { - c0 &= 0x1F; - c0 <<= 6; - c0 |= ( c1 & 0x3F ); - if( c0 >= 0x80 ) { - return { c0, 2 }; - } - } - } - } - else if( ( c0 & 0xF0 ) == 0xE0 ) { - if( s >= 3 ) { - const char32_t c1 = in.peek_uint8( 1 ); - const char32_t c2 = in.peek_uint8( 2 ); - if( ( ( c1 & 0xC0 ) == 0x80 ) && ( ( c2 & 0xC0 ) == 0x80 ) ) { - c0 &= 0x0F; - c0 <<= 6; - c0 |= ( c1 & 0x3F ); - c0 <<= 6; - c0 |= ( c2 & 0x3F ); - if( c0 >= 0x800 && !( c0 >= 0xD800 && c0 <= 0xDFFF ) ) { - return { c0, 3 }; - } - } - } - } - else if( ( c0 & 0xF8 ) == 0xF0 ) { - if( s >= 4 ) { - const char32_t c1 = in.peek_uint8( 1 ); - const char32_t c2 = in.peek_uint8( 2 ); - const char32_t c3 = in.peek_uint8( 3 ); - if( ( ( c1 & 0xC0 ) == 0x80 ) && ( ( c2 & 0xC0 ) == 0x80 ) && ( ( c3 & 0xC0 ) == 0x80 ) ) { - c0 &= 0x07; - c0 <<= 6; - c0 |= ( c1 & 0x3F ); - c0 <<= 6; - c0 |= ( c2 & 0x3F ); - c0 <<= 6; - c0 |= ( c3 & 0x3F ); - if( c0 >= 0x10000 && c0 <= 0x10FFFF ) { - return { c0, 4 }; - } - } - } - } - return { 0, 0 }; - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/pegtl_string.hpp b/include/tao/json/external/pegtl/internal/pegtl_string.hpp deleted file mode 100644 index 894b9d71..00000000 --- a/include/tao/json/external/pegtl/internal/pegtl_string.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_PEGTL_STRING_HPP -#define TAO_JSON_PEGTL_INTERNAL_PEGTL_STRING_HPP - -#include -#include - -#include "../ascii.hpp" -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - // Inspired by https://github.com/irrequietus/typestring - // Rewritten and reduced to what is needed for the PEGTL - // and to work with Visual Studio 2015. - - template< typename, typename, typename, typename, typename, typename, typename, typename > - struct string_join; - - template< template< char... > class S, char... C0s, char... C1s, char... C2s, char... C3s, char... C4s, char... C5s, char... C6s, char... C7s > - struct string_join< S< C0s... >, S< C1s... >, S< C2s... >, S< C3s... >, S< C4s... >, S< C5s... >, S< C6s... >, S< C7s... > > - { - using type = S< C0s..., C1s..., C2s..., C3s..., C4s..., C5s..., C6s..., C7s... >; - }; - - template< template< char... > class S, char, bool > - struct string_at - { - using type = S<>; - }; - - template< template< char... > class S, char C > - struct string_at< S, C, true > - { - using type = S< C >; - }; - - template< typename T, std::size_t S > - struct string_max_length - { - static_assert( S <= 512, "String longer than 512 (excluding terminating \\0)!" ); - using type = T; - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#define TAO_JSON_PEGTL_INTERNAL_EMPTY() -#define TAO_JSON_PEGTL_INTERNAL_DEFER( X ) X TAO_JSON_PEGTL_INTERNAL_EMPTY() -#define TAO_JSON_PEGTL_INTERNAL_EXPAND( ... ) __VA_ARGS__ - -#define TAO_JSON_PEGTL_INTERNAL_STRING_AT( S, x, n ) \ - TAO_JSON_PEGTL_NAMESPACE::internal::string_at< S, ( 0##n < ( sizeof( x ) / sizeof( char ) ) ) ? ( x )[ 0##n ] : 0, ( 0##n < ( sizeof( x ) / sizeof( char ) ) - 1 ) >::type - -#define TAO_JSON_PEGTL_INTERNAL_JOIN_8( M, S, x, n ) \ - TAO_JSON_PEGTL_NAMESPACE::internal::string_join< TAO_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##0 ), \ - TAO_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##1 ), \ - TAO_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##2 ), \ - TAO_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##3 ), \ - TAO_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##4 ), \ - TAO_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##5 ), \ - TAO_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##6 ), \ - TAO_JSON_PEGTL_INTERNAL_DEFER( M )( S, x, n##7 ) >::type - -#define TAO_JSON_PEGTL_INTERNAL_STRING_8( S, x, n ) \ - TAO_JSON_PEGTL_INTERNAL_JOIN_8( TAO_JSON_PEGTL_INTERNAL_STRING_AT, S, x, n ) - -#define TAO_JSON_PEGTL_INTERNAL_STRING_64( S, x, n ) \ - TAO_JSON_PEGTL_INTERNAL_JOIN_8( TAO_JSON_PEGTL_INTERNAL_STRING_8, S, x, n ) - -#define TAO_JSON_PEGTL_INTERNAL_STRING_512( S, x, n ) \ - TAO_JSON_PEGTL_INTERNAL_JOIN_8( TAO_JSON_PEGTL_INTERNAL_STRING_64, S, x, n ) - -#define TAO_JSON_PEGTL_INTERNAL_STRING( S, x ) \ - TAO_JSON_PEGTL_INTERNAL_EXPAND( \ - TAO_JSON_PEGTL_INTERNAL_EXPAND( \ - TAO_JSON_PEGTL_INTERNAL_EXPAND( \ - TAO_JSON_PEGTL_NAMESPACE::internal::string_max_length< TAO_JSON_PEGTL_INTERNAL_STRING_512( S, x, ), sizeof( x ) - 1 >::type ) ) ) - -#define TAO_JSON_PEGTL_STRING( x ) \ - TAO_JSON_PEGTL_INTERNAL_STRING( TAO_JSON_PEGTL_NAMESPACE::ascii::string, x ) - -#define TAO_JSON_PEGTL_ISTRING( x ) \ - TAO_JSON_PEGTL_INTERNAL_STRING( TAO_JSON_PEGTL_NAMESPACE::ascii::istring, x ) - -#define TAO_JSON_PEGTL_KEYWORD( x ) \ - TAO_JSON_PEGTL_INTERNAL_STRING( TAO_JSON_PEGTL_NAMESPACE::ascii::keyword, x ) - -#endif diff --git a/include/tao/json/external/pegtl/internal/plus.hpp b/include/tao/json/external/pegtl/internal/plus.hpp deleted file mode 100644 index 0f5c0cd3..00000000 --- a/include/tao/json/external/pegtl/internal/plus.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_PLUS_HPP -#define TAO_JSON_PEGTL_INTERNAL_PLUS_HPP - -#include - -#include "../config.hpp" - -#include "duseltronik.hpp" -#include "opt.hpp" -#include "seq.hpp" -#include "skip_control.hpp" -#include "star.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - // While plus<> could easily be implemented with - // seq< Rule, Rules ..., star< Rule, Rules ... > > we - // provide an explicit implementation to optimise away - // the otherwise created input mark. - - template< typename Rule, typename... Rules > - struct plus - { - using analyze_t = analysis::generic< analysis::rule_type::seq, Rule, Rules..., opt< plus > >; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - return seq< Rule, Rules... >::template match< A, M, Action, Control >( in, st... ) && star< Rule, Rules... >::template match< A, M, Action, Control >( in, st... ); - } - }; - - template< typename Rule, typename... Rules > - inline constexpr bool skip_control< plus< Rule, Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/raise.hpp b/include/tao/json/external/pegtl/internal/raise.hpp deleted file mode 100644 index 29d1c926..00000000 --- a/include/tao/json/external/pegtl/internal/raise.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_RAISE_HPP -#define TAO_JSON_PEGTL_INTERNAL_RAISE_HPP - -#include -#include -#include - -#include "../config.hpp" - -#include "skip_control.hpp" - -#include "../analysis/generic.hpp" -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename T > - struct raise - { - using analyze_t = analysis::generic< analysis::rule_type::any >; - -#if defined( _MSC_VER ) -#pragma warning( push ) -#pragma warning( disable : 4702 ) -#endif - template< apply_mode, - rewind_mode, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - Control< T >::raise( static_cast< const Input& >( in ), st... ); - throw std::logic_error( "code should be unreachable: Control< T >::raise() did not throw an exception" ); // LCOV_EXCL_LINE -#if defined( _MSC_VER ) -#pragma warning( pop ) -#endif - } - }; - - template< typename T > - inline constexpr bool skip_control< raise< T > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/range.hpp b/include/tao/json/external/pegtl/internal/range.hpp deleted file mode 100644 index 66f7d7c4..00000000 --- a/include/tao/json/external/pegtl/internal/range.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_RANGE_HPP -#define TAO_JSON_PEGTL_INTERNAL_RANGE_HPP - -#include "../config.hpp" - -#include "result_on_found.hpp" -#include "skip_control.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< result_on_found R, typename Peek, typename Peek::data_t Lo, typename Peek::data_t Hi > - struct range - { - static_assert( Lo <= Hi, "invalid range detected" ); - - using analyze_t = analysis::generic< analysis::rule_type::any >; - - template< int Eol > - static constexpr bool can_match_eol = ( ( ( Lo <= Eol ) && ( Eol <= Hi ) ) == bool( R ) ); - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( Peek::max_input_size ) ) ) - { - if( const std::size_t s = in.size( Peek::max_input_size ); s >= Peek::min_input_size ) { - if( const auto t = Peek::peek( in, s ) ) { - if( ( ( Lo <= t.data ) && ( t.data <= Hi ) ) == bool( R ) ) { - if constexpr( can_match_eol< Input::eol_t::ch > ) { - in.bump( t.size ); - } - else { - in.bump_in_this_line( t.size ); - } - return true; - } - } - } - return false; - } - }; - - template< result_on_found R, typename Peek, typename Peek::data_t Lo, typename Peek::data_t Hi > - inline constexpr bool skip_control< range< R, Peek, Lo, Hi > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/ranges.hpp b/include/tao/json/external/pegtl/internal/ranges.hpp deleted file mode 100644 index 3bc33d12..00000000 --- a/include/tao/json/external/pegtl/internal/ranges.hpp +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_RANGES_HPP -#define TAO_JSON_PEGTL_INTERNAL_RANGES_HPP - -#include "../config.hpp" - -#include "range.hpp" -#include "skip_control.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< int Eol, typename Char, Char... Cs > - struct ranges_impl; - - template< int Eol, typename Char > - struct ranges_impl< Eol, Char > - { - static constexpr bool can_match_eol = false; - - [[nodiscard]] static bool match( const Char /*unused*/ ) noexcept - { - return false; - } - }; - - template< int Eol, typename Char, Char Eq > - struct ranges_impl< Eol, Char, Eq > - { - static constexpr bool can_match_eol = ( Eq == Eol ); - - [[nodiscard]] static bool match( const Char c ) noexcept - { - return c == Eq; - } - }; - - template< int Eol, typename Char, Char Lo, Char Hi, Char... Cs > - struct ranges_impl< Eol, Char, Lo, Hi, Cs... > - { - static_assert( Lo <= Hi, "invalid range detected" ); - - static constexpr bool can_match_eol = ( ( ( Lo <= Eol ) && ( Eol <= Hi ) ) || ranges_impl< Eol, Char, Cs... >::can_match_eol ); - - [[nodiscard]] static bool match( const Char c ) noexcept - { - return ( ( Lo <= c ) && ( c <= Hi ) ) || ranges_impl< Eol, Char, Cs... >::match( c ); - } - }; - - template< typename Peek, typename Peek::data_t... Cs > - struct ranges - { - using analyze_t = analysis::generic< analysis::rule_type::any >; - - template< int Eol > - static constexpr bool can_match_eol = ranges_impl< Eol, typename Peek::data_t, Cs... >::can_match_eol; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( Peek::max_input_size ) ) ) - { - if( const std::size_t s = in.size( Peek::max_input_size ); s >= Peek::min_input_size ) { - if( const auto t = Peek::peek( in, s ) ) { - if( ranges_impl< Input::eol_t::ch, typename Peek::data_t, Cs... >::match( t.data ) ) { - if constexpr( can_match_eol< Input::eol_t::ch > ) { - in.bump( t.size ); - } - else { - in.bump_in_this_line( t.size ); - } - return true; - } - } - } - return false; - } - }; - - template< typename Peek, typename Peek::data_t Lo, typename Peek::data_t Hi > - struct ranges< Peek, Lo, Hi > - : range< result_on_found::success, Peek, Lo, Hi > - { - }; - - template< typename Peek, typename Peek::data_t... Cs > - inline constexpr bool skip_control< ranges< Peek, Cs... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/read_uint.hpp b/include/tao/json/external/pegtl/internal/read_uint.hpp deleted file mode 100644 index 817f5faa..00000000 --- a/include/tao/json/external/pegtl/internal/read_uint.hpp +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_READ_UINT_HPP -#define TAO_JSON_PEGTL_INTERNAL_READ_UINT_HPP - -#include - -#include "../config.hpp" - -#include "endian.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - struct read_uint16_be - { - using type = std::uint16_t; - - [[nodiscard]] static std::uint16_t read( const void* d ) noexcept - { - return be_to_h< std::uint16_t >( d ); - } - }; - - struct read_uint16_le - { - using type = std::uint16_t; - - [[nodiscard]] static std::uint16_t read( const void* d ) noexcept - { - return le_to_h< std::uint16_t >( d ); - } - }; - - struct read_uint32_be - { - using type = std::uint32_t; - - [[nodiscard]] static std::uint32_t read( const void* d ) noexcept - { - return be_to_h< std::uint32_t >( d ); - } - }; - - struct read_uint32_le - { - using type = std::uint32_t; - - [[nodiscard]] static std::uint32_t read( const void* d ) noexcept - { - return le_to_h< std::uint32_t >( d ); - } - }; - - struct read_uint64_be - { - using type = std::uint64_t; - - [[nodiscard]] static std::uint64_t read( const void* d ) noexcept - { - return be_to_h< std::uint64_t >( d ); - } - }; - - struct read_uint64_le - { - using type = std::uint64_t; - - [[nodiscard]] static std::uint64_t read( const void* d ) noexcept - { - return le_to_h< std::uint64_t >( d ); - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/rematch.hpp b/include/tao/json/external/pegtl/internal/rematch.hpp deleted file mode 100644 index 5f99f266..00000000 --- a/include/tao/json/external/pegtl/internal/rematch.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_REMATCH_HPP -#define TAO_JSON_PEGTL_INTERNAL_REMATCH_HPP - -#include "../config.hpp" - -#include "skip_control.hpp" - -#include "../apply_mode.hpp" -#include "../memory_input.hpp" -#include "../rewind_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Head, typename... Rules > - struct rematch; - - template< typename Head > - struct rematch< Head > - { - using analyze_t = typename Head::analyze_t; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - return Control< Head >::template match< A, M, Action, Control >( in, st... ); - } - }; - - template< typename Head, typename Rule, typename... Rules > - struct rematch< Head, Rule, Rules... > - { - using analyze_t = typename Head::analyze_t; // NOTE: Rule and Rules are ignored for analyze(). - - template< apply_mode A, - rewind_mode, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< rewind_mode::required >(); - - if( Control< Head >::template match< A, rewind_mode::active, Action, Control >( in, st... ) ) { - memory_input< Input::tracking_mode_v, typename Input::eol_t, typename Input::source_t > i2( m.iterator(), in.current(), in.source() ); - return m( ( Control< Rule >::template match< A, rewind_mode::active, Action, Control >( i2, st... ) && ... && ( i2.restart( m ), Control< Rules >::template match< A, rewind_mode::active, Action, Control >( i2, st... ) ) ) ); - } - return false; - } - }; - - template< typename Head, typename... Rules > - inline constexpr bool skip_control< rematch< Head, Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/rep.hpp b/include/tao/json/external/pegtl/internal/rep.hpp deleted file mode 100644 index 607e896c..00000000 --- a/include/tao/json/external/pegtl/internal/rep.hpp +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_REP_HPP -#define TAO_JSON_PEGTL_INTERNAL_REP_HPP - -#include "../config.hpp" - -#include "skip_control.hpp" -#include "trivial.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/counted.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< unsigned Num, typename... Rules > - struct rep; - - template< unsigned Num > - struct rep< Num > - : trivial< true > - { - }; - - template< typename Rule, typename... Rules > - struct rep< 0, Rule, Rules... > - : trivial< true > - { - }; - - template< unsigned Num, typename... Rules > - struct rep - { - using analyze_t = analysis::counted< analysis::rule_type::seq, Num, Rules... >; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< M >(); - using m_t = decltype( m ); - - for( unsigned i = 0; i != Num; ++i ) { - if( !( Control< Rules >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) && ... ) ) { - return false; - } - } - return m( true ); - } - }; - - template< unsigned Num, typename... Rules > - inline constexpr bool skip_control< rep< Num, Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/rep_min.hpp b/include/tao/json/external/pegtl/internal/rep_min.hpp deleted file mode 100644 index c279bae8..00000000 --- a/include/tao/json/external/pegtl/internal/rep_min.hpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_REP_MIN_HPP -#define TAO_JSON_PEGTL_INTERNAL_REP_MIN_HPP - -#include "../config.hpp" - -#include "rep.hpp" -#include "seq.hpp" -#include "star.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< unsigned Min, typename Rule, typename... Rules > - using rep_min = seq< rep< Min, Rule, Rules... >, star< Rule, Rules... > >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/rep_min_max.hpp b/include/tao/json/external/pegtl/internal/rep_min_max.hpp deleted file mode 100644 index b244c87e..00000000 --- a/include/tao/json/external/pegtl/internal/rep_min_max.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_REP_MIN_MAX_HPP -#define TAO_JSON_PEGTL_INTERNAL_REP_MIN_MAX_HPP - -#include - -#include "../config.hpp" - -#include "duseltronik.hpp" -#include "not_at.hpp" -#include "seq.hpp" -#include "skip_control.hpp" -#include "trivial.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/counted.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< unsigned Min, unsigned Max, typename... Rules > - struct rep_min_max; - - template< unsigned Min, unsigned Max > - struct rep_min_max< Min, Max > - : trivial< false > - { - static_assert( Min <= Max ); - }; - - template< typename Rule, typename... Rules > - struct rep_min_max< 0, 0, Rule, Rules... > - : not_at< Rule, Rules... > - { - }; - - template< unsigned Min, unsigned Max, typename... Rules > - struct rep_min_max - { - using analyze_t = analysis::counted< analysis::rule_type::seq, Min, Rules... >; - - static_assert( Min <= Max ); - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< M >(); - using m_t = decltype( m ); - - for( unsigned i = 0; i != Min; ++i ) { - if( !( Control< Rules >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) && ... ) ) { - return false; - } - } - for( unsigned i = Min; i != Max; ++i ) { - if( !duseltronik< seq< Rules... >, A, rewind_mode::required, Action, Control >::match( in, st... ) ) { - return m( true ); - } - } - return m( duseltronik< not_at< Rules... >, A, m_t::next_rewind_mode, Action, Control >::match( in, st... ) ); // NOTE that not_at<> will always rewind. - } - }; - - template< unsigned Min, unsigned Max, typename... Rules > - inline constexpr bool skip_control< rep_min_max< Min, Max, Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/rep_opt.hpp b/include/tao/json/external/pegtl/internal/rep_opt.hpp deleted file mode 100644 index 4e56902c..00000000 --- a/include/tao/json/external/pegtl/internal/rep_opt.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_REP_OPT_HPP -#define TAO_JSON_PEGTL_INTERNAL_REP_OPT_HPP - -#include "../config.hpp" - -#include "duseltronik.hpp" -#include "seq.hpp" -#include "skip_control.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< unsigned Max, typename... Rules > - struct rep_opt - { - using analyze_t = analysis::generic< analysis::rule_type::opt, Rules... >; - - template< apply_mode A, - rewind_mode, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - for( unsigned i = 0; ( i != Max ) && duseltronik< seq< Rules... >, A, rewind_mode::required, Action, Control >::match( in, st... ); ++i ) { - } - return true; - } - }; - - template< unsigned Max, typename... Rules > - inline constexpr bool skip_control< rep_opt< Max, Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/require.hpp b/include/tao/json/external/pegtl/internal/require.hpp deleted file mode 100644 index 21cb17e1..00000000 --- a/include/tao/json/external/pegtl/internal/require.hpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_REQUIRE_HPP -#define TAO_JSON_PEGTL_INTERNAL_REQUIRE_HPP - -#include "../config.hpp" - -#include "skip_control.hpp" -#include "trivial.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< unsigned Amount > - struct require; - - template<> - struct require< 0 > - : trivial< true > - { - }; - - template< unsigned Amount > - struct require - { - using analyze_t = analysis::generic< analysis::rule_type::opt >; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( 0 ) ) ) - { - return in.size( Amount ) >= Amount; - } - }; - - template< unsigned Amount > - inline constexpr bool skip_control< require< Amount > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/result_on_found.hpp b/include/tao/json/external/pegtl/internal/result_on_found.hpp deleted file mode 100644 index a6b8c241..00000000 --- a/include/tao/json/external/pegtl/internal/result_on_found.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_RESULT_ON_FOUND_HPP -#define TAO_JSON_PEGTL_INTERNAL_RESULT_ON_FOUND_HPP - -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - enum class result_on_found : bool - { - success = true, - failure = false - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/rules.hpp b/include/tao/json/external/pegtl/internal/rules.hpp deleted file mode 100644 index 3ff9eec8..00000000 --- a/include/tao/json/external/pegtl/internal/rules.hpp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_RULES_HPP -#define TAO_JSON_PEGTL_INTERNAL_RULES_HPP - -#include "action.hpp" -#include "alnum.hpp" -#include "alpha.hpp" -#include "any.hpp" -#include "apply.hpp" -#include "apply0.hpp" -#include "at.hpp" -#include "bof.hpp" -#include "bol.hpp" -#include "bytes.hpp" -#include "control.hpp" -#include "disable.hpp" -#include "discard.hpp" -#include "enable.hpp" -#include "eof.hpp" -#include "eol.hpp" -#include "eolf.hpp" -#include "identifier.hpp" -#include "if_apply.hpp" -#include "if_must.hpp" -#include "if_must_else.hpp" -#include "if_then_else.hpp" -#include "istring.hpp" -#include "list.hpp" -#include "list_must.hpp" -#include "list_tail.hpp" -#include "list_tail_pad.hpp" -#include "must.hpp" -#include "not_at.hpp" -#include "one.hpp" -#include "opt.hpp" -#include "pad.hpp" -#include "pad_opt.hpp" -#include "plus.hpp" -#include "raise.hpp" -#include "range.hpp" -#include "ranges.hpp" -#include "rematch.hpp" -#include "rep.hpp" -#include "rep_min.hpp" -#include "rep_min_max.hpp" -#include "rep_opt.hpp" -#include "require.hpp" -#include "seq.hpp" -#include "skip_control.hpp" -#include "sor.hpp" -#include "star.hpp" -#include "star_must.hpp" -#include "state.hpp" -#include "string.hpp" -#include "trivial.hpp" -#include "try_catch_type.hpp" -#include "until.hpp" - -#endif diff --git a/include/tao/json/external/pegtl/internal/seq.hpp b/include/tao/json/external/pegtl/internal/seq.hpp deleted file mode 100644 index 8528fec5..00000000 --- a/include/tao/json/external/pegtl/internal/seq.hpp +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_SEQ_HPP -#define TAO_JSON_PEGTL_INTERNAL_SEQ_HPP - -#include "../config.hpp" - -#include "skip_control.hpp" -#include "trivial.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename... Rules > - struct seq; - - template<> - struct seq<> - : trivial< true > - { - }; - - template< typename Rule > - struct seq< Rule > - { - using analyze_t = typename Rule::analyze_t; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - return Control< Rule >::template match< A, M, Action, Control >( in, st... ); - } - }; - - template< typename... Rules > - struct seq - { - using analyze_t = analysis::generic< analysis::rule_type::seq, Rules... >; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< M >(); - using m_t = decltype( m ); - return m( ( Control< Rules >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) && ... ) ); - } - }; - - template< typename... Rules > - inline constexpr bool skip_control< seq< Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/skip_control.hpp b/include/tao/json/external/pegtl/internal/skip_control.hpp deleted file mode 100644 index 7b3d6098..00000000 --- a/include/tao/json/external/pegtl/internal/skip_control.hpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_SKIP_CONTROL_HPP -#define TAO_JSON_PEGTL_INTERNAL_SKIP_CONTROL_HPP - -#include - -#include "../config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - // This class is a simple tagging mechanism. - // By default, skip_control< Rule > is 'false'. - // Each internal (!) rule that should be hidden - // from the control and action class' callbacks - // simply specializes skip_control<> to return - // 'true' for the above expression. - - template< typename Rule > - inline constexpr bool skip_control = false; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/sor.hpp b/include/tao/json/external/pegtl/internal/sor.hpp deleted file mode 100644 index 66ca2016..00000000 --- a/include/tao/json/external/pegtl/internal/sor.hpp +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_SOR_HPP -#define TAO_JSON_PEGTL_INTERNAL_SOR_HPP - -#include - -#include "../config.hpp" - -#include "skip_control.hpp" -#include "trivial.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename... Rules > - struct sor; - - template<> - struct sor<> - : trivial< false > - { - }; - - template< typename... Rules > - struct sor - : sor< std::index_sequence_for< Rules... >, Rules... > - { - }; - - template< std::size_t... Indices, typename... Rules > - struct sor< std::index_sequence< Indices... >, Rules... > - { - using analyze_t = analysis::generic< analysis::rule_type::sor, Rules... >; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - return ( Control< Rules >::template match< A, ( ( Indices == ( sizeof...( Rules ) - 1 ) ) ? M : rewind_mode::required ), Action, Control >( in, st... ) || ... ); - } - }; - - template< typename... Rules > - inline constexpr bool skip_control< sor< Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/star.hpp b/include/tao/json/external/pegtl/internal/star.hpp deleted file mode 100644 index 53795b94..00000000 --- a/include/tao/json/external/pegtl/internal/star.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_STAR_HPP -#define TAO_JSON_PEGTL_INTERNAL_STAR_HPP - -#include - -#include "../config.hpp" - -#include "seq.hpp" -#include "skip_control.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Rule, typename... Rules > - struct star - { - using analyze_t = analysis::generic< analysis::rule_type::opt, Rule, Rules..., star >; - - template< apply_mode A, - rewind_mode, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - while( seq< Rule, Rules... >::template match< A, rewind_mode::required, Action, Control >( in, st... ) ) { - } - return true; - } - }; - - template< typename Rule, typename... Rules > - inline constexpr bool skip_control< star< Rule, Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/star_must.hpp b/include/tao/json/external/pegtl/internal/star_must.hpp deleted file mode 100644 index eddec9f5..00000000 --- a/include/tao/json/external/pegtl/internal/star_must.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_STAR_MUST_HPP -#define TAO_JSON_PEGTL_INTERNAL_STAR_MUST_HPP - -#include "../config.hpp" - -#include "if_must.hpp" -#include "star.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Cond, typename... Rules > - using star_must = star< if_must< false, Cond, Rules... > >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/state.hpp b/include/tao/json/external/pegtl/internal/state.hpp deleted file mode 100644 index b87b8c9f..00000000 --- a/include/tao/json/external/pegtl/internal/state.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_STATE_HPP -#define TAO_JSON_PEGTL_INTERNAL_STATE_HPP - -#include "../config.hpp" - -#include "duseltronik.hpp" -#include "seq.hpp" -#include "skip_control.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename State, typename... Rules > - struct state - { - using analyze_t = analysis::generic< analysis::rule_type::seq, Rules... >; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - State s( static_cast< const Input& >( in ), st... ); - if( duseltronik< seq< Rules... >, A, M, Action, Control >::match( in, s ) ) { - s.success( static_cast< const Input& >( in ), st... ); - return true; - } - return false; - } - }; - - template< typename State, typename... Rules > - inline constexpr bool skip_control< state< State, Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/string.hpp b/include/tao/json/external/pegtl/internal/string.hpp deleted file mode 100644 index 229a1584..00000000 --- a/include/tao/json/external/pegtl/internal/string.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_STRING_HPP -#define TAO_JSON_PEGTL_INTERNAL_STRING_HPP - -#include -#include - -#include "../config.hpp" - -#include "bump_help.hpp" -#include "result_on_found.hpp" -#include "skip_control.hpp" -#include "trivial.hpp" - -#include "../analysis/counted.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - [[nodiscard]] inline bool unsafe_equals( const char* s, const std::initializer_list< char >& l ) noexcept - { - return std::memcmp( s, &*l.begin(), l.size() ) == 0; - } - - template< char... Cs > - struct string; - - template<> - struct string<> - : trivial< true > - { - }; - - template< char... Cs > - struct string - { - using analyze_t = analysis::counted< analysis::rule_type::any, sizeof...( Cs ) >; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) noexcept( noexcept( in.size( 0 ) ) ) - { - if( in.size( sizeof...( Cs ) ) >= sizeof...( Cs ) ) { - if( unsafe_equals( in.current(), { Cs... } ) ) { - bump_help< result_on_found::success, Input, char, Cs... >( in, sizeof...( Cs ) ); - return true; - } - } - return false; - } - }; - - template< char... Cs > - inline constexpr bool skip_control< string< Cs... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/trivial.hpp b/include/tao/json/external/pegtl/internal/trivial.hpp deleted file mode 100644 index 9be855cd..00000000 --- a/include/tao/json/external/pegtl/internal/trivial.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_TRIVIAL_HPP -#define TAO_JSON_PEGTL_INTERNAL_TRIVIAL_HPP - -#include "../config.hpp" - -#include "skip_control.hpp" - -#include "../analysis/counted.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< bool Result > - struct trivial - { - using analyze_t = analysis::counted< analysis::rule_type::any, unsigned( !Result ) >; - - template< typename Input > - [[nodiscard]] static bool match( Input& /*unused*/ ) noexcept - { - return Result; - } - }; - - template< bool Result > - inline constexpr bool skip_control< trivial< Result > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/try_catch_type.hpp b/include/tao/json/external/pegtl/internal/try_catch_type.hpp deleted file mode 100644 index 1ecf3ebd..00000000 --- a/include/tao/json/external/pegtl/internal/try_catch_type.hpp +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_TRY_CATCH_TYPE_HPP -#define TAO_JSON_PEGTL_INTERNAL_TRY_CATCH_TYPE_HPP - -#include - -#include "../config.hpp" - -#include "duseltronik.hpp" -#include "seq.hpp" -#include "skip_control.hpp" -#include "trivial.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Exception, typename... Rules > - struct try_catch_type; - - template< typename Exception > - struct try_catch_type< Exception > - : trivial< true > - { - }; - - template< typename Exception, typename... Rules > - struct try_catch_type - { - using analyze_t = analysis::generic< analysis::rule_type::seq, Rules... >; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< M >(); - using m_t = decltype( m ); - - try { - return m( duseltronik< seq< Rules... >, A, m_t::next_rewind_mode, Action, Control >::match( in, st... ) ); - } - catch( const Exception& ) { - return false; - } - } - }; - - template< typename Exception, typename... Rules > - inline constexpr bool skip_control< try_catch_type< Exception, Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/internal/until.hpp b/include/tao/json/external/pegtl/internal/until.hpp deleted file mode 100644 index e847585b..00000000 --- a/include/tao/json/external/pegtl/internal/until.hpp +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_INTERNAL_UNTIL_HPP -#define TAO_JSON_PEGTL_INTERNAL_UNTIL_HPP - -#include "../config.hpp" - -#include "bytes.hpp" -#include "eof.hpp" -#include "not_at.hpp" -#include "skip_control.hpp" -#include "star.hpp" - -#include "../apply_mode.hpp" -#include "../rewind_mode.hpp" - -#include "../analysis/generic.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::internal -{ - template< typename Cond, typename... Rules > - struct until; - - template< typename Cond > - struct until< Cond > - { - using analyze_t = analysis::generic< analysis::rule_type::seq, star< not_at< Cond >, not_at< eof >, bytes< 1 > >, Cond >; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< M >(); - - while( !Control< Cond >::template match< A, rewind_mode::required, Action, Control >( in, st... ) ) { - if( in.empty() ) { - return false; - } - in.bump(); - } - return m( true ); - } - }; - - template< typename Cond, typename... Rules > - struct until - { - using analyze_t = analysis::generic< analysis::rule_type::seq, star< not_at< Cond >, not_at< eof >, Rules... >, Cond >; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - auto m = in.template mark< M >(); - using m_t = decltype( m ); - - while( !Control< Cond >::template match< A, rewind_mode::required, Action, Control >( in, st... ) ) { - if( !( Control< Rules >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) && ... ) ) { - return false; - } - } - return m( true ); - } - }; - - template< typename Cond, typename... Rules > - inline constexpr bool skip_control< until< Cond, Rules... > > = true; - -} // namespace TAO_JSON_PEGTL_NAMESPACE::internal - -#endif diff --git a/include/tao/json/external/pegtl/istream_input.hpp b/include/tao/json/external/pegtl/istream_input.hpp deleted file mode 100644 index 5bd0be99..00000000 --- a/include/tao/json/external/pegtl/istream_input.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_ISTREAM_INPUT_HPP -#define TAO_JSON_PEGTL_ISTREAM_INPUT_HPP - -#include - -#include "buffer_input.hpp" -#include "config.hpp" -#include "eol.hpp" - -#include "internal/istream_reader.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - template< typename Eol = eol::lf_crlf, std::size_t Chunk = 64 > - struct istream_input - : buffer_input< internal::istream_reader, Eol, std::string, Chunk > - { - template< typename T > - istream_input( std::istream& in_stream, const std::size_t in_maximum, T&& in_source ) - : buffer_input< internal::istream_reader, Eol, std::string, Chunk >( std::forward< T >( in_source ), in_maximum, in_stream ) - { - } - }; - - template< typename... Ts > - istream_input( Ts&&... )->istream_input<>; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/match.hpp b/include/tao/json/external/pegtl/match.hpp deleted file mode 100644 index 2652bb92..00000000 --- a/include/tao/json/external/pegtl/match.hpp +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_MATCH_HPP -#define TAO_JSON_PEGTL_MATCH_HPP - -#include - -#include "apply_mode.hpp" -#include "config.hpp" -#include "nothing.hpp" -#include "require_apply.hpp" -#include "require_apply0.hpp" -#include "rewind_mode.hpp" - -#include "internal/dusel_mode.hpp" -#include "internal/duseltronik.hpp" -#include "internal/has_apply.hpp" -#include "internal/has_apply0.hpp" -#include "internal/missing_apply.hpp" -#include "internal/missing_apply0.hpp" -#include "internal/skip_control.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - template< typename Rule, - apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] bool match( Input& in, States&&... st ) - { - constexpr bool enable_control = !internal::skip_control< Rule >; - constexpr bool enable_action = enable_control && ( A == apply_mode::action ); - - using iterator_t = typename Input::iterator_t; - constexpr bool has_apply_void = enable_action && internal::has_apply< Control< Rule >, void, Action, const iterator_t&, const Input&, States... >::value; - constexpr bool has_apply_bool = enable_action && internal::has_apply< Control< Rule >, bool, Action, const iterator_t&, const Input&, States... >::value; - constexpr bool has_apply = has_apply_void || has_apply_bool; - - constexpr bool has_apply0_void = enable_action && internal::has_apply0< Control< Rule >, void, Action, const Input&, States... >::value; - constexpr bool has_apply0_bool = enable_action && internal::has_apply0< Control< Rule >, bool, Action, const Input&, States... >::value; - constexpr bool has_apply0 = has_apply0_void || has_apply0_bool; - - static_assert( !( has_apply && has_apply0 ), "both apply() and apply0() defined" ); - - constexpr bool is_nothing = std::is_base_of_v< nothing< Rule >, Action< Rule > >; - static_assert( !( has_apply && is_nothing ), "unexpected apply() defined" ); - static_assert( !( has_apply0 && is_nothing ), "unexpected apply0() defined" ); - - if constexpr( !has_apply && std::is_base_of_v< require_apply, Action< Rule > > ) { - internal::missing_apply< Control< Rule >, Action >( in, st... ); - } - - if constexpr( !has_apply0 && std::is_base_of_v< require_apply0, Action< Rule > > ) { - internal::missing_apply0< Control< Rule >, Action >( in, st... ); - } - - constexpr bool validate_nothing = std::is_base_of_v< maybe_nothing, Action< void > >; - constexpr bool is_maybe_nothing = std::is_base_of_v< maybe_nothing, Action< Rule > >; - static_assert( !enable_action || !validate_nothing || is_nothing || is_maybe_nothing || has_apply || has_apply0, "either apply() or apply0() must be defined" ); - - constexpr auto mode = static_cast< internal::dusel_mode >( enable_control + has_apply_void + 2 * has_apply_bool + 3 * has_apply0_void + 4 * has_apply0_bool ); - return internal::duseltronik< Rule, A, M, Action, Control, mode >::match( in, st... ); - } - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/memory_input.hpp b/include/tao/json/external/pegtl/memory_input.hpp deleted file mode 100644 index d2b5f44c..00000000 --- a/include/tao/json/external/pegtl/memory_input.hpp +++ /dev/null @@ -1,381 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_MEMORY_INPUT_HPP -#define TAO_JSON_PEGTL_MEMORY_INPUT_HPP - -#include -#include -#include -#include -#include -#include -#include - -#include "config.hpp" -#include "eol.hpp" -#include "normal.hpp" -#include "nothing.hpp" -#include "position.hpp" -#include "tracking_mode.hpp" - -#include "internal/action_input.hpp" -#include "internal/at.hpp" -#include "internal/bump.hpp" -#include "internal/eolf.hpp" -#include "internal/iterator.hpp" -#include "internal/marker.hpp" -#include "internal/until.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - namespace internal - { - template< tracking_mode, typename Eol, typename Source > - class memory_input_base; - - template< typename Eol, typename Source > - class memory_input_base< tracking_mode::eager, Eol, Source > - { - public: - using iterator_t = internal::iterator; - - template< typename T > - memory_input_base( const iterator_t& in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) - : m_begin( in_begin.data ), - m_current( in_begin ), - m_end( in_end ), - m_source( std::forward< T >( in_source ) ) - { - } - - template< typename T > - memory_input_base( const char* in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) - : m_begin( in_begin ), - m_current( in_begin ), - m_end( in_end ), - m_source( std::forward< T >( in_source ) ) - { - } - - memory_input_base( const memory_input_base& ) = delete; - memory_input_base( memory_input_base&& ) = delete; - - ~memory_input_base() = default; - - memory_input_base operator=( const memory_input_base& ) = delete; - memory_input_base operator=( memory_input_base&& ) = delete; - - [[nodiscard]] const char* current() const noexcept - { - return m_current.data; - } - - [[nodiscard]] const char* begin() const noexcept - { - return m_begin; - } - - [[nodiscard]] const char* end( const std::size_t /*unused*/ = 0 ) const noexcept - { - return m_end; - } - - [[nodiscard]] std::size_t byte() const noexcept - { - return m_current.byte; - } - - [[nodiscard]] std::size_t line() const noexcept - { - return m_current.line; - } - - [[nodiscard]] std::size_t byte_in_line() const noexcept - { - return m_current.byte_in_line; - } - - void bump( const std::size_t in_count = 1 ) noexcept - { - internal::bump( m_current, in_count, Eol::ch ); - } - - void bump_in_this_line( const std::size_t in_count = 1 ) noexcept - { - internal::bump_in_this_line( m_current, in_count ); - } - - void bump_to_next_line( const std::size_t in_count = 1 ) noexcept - { - internal::bump_to_next_line( m_current, in_count ); - } - - [[nodiscard]] TAO_JSON_PEGTL_NAMESPACE::position position( const iterator_t& it ) const - { - return TAO_JSON_PEGTL_NAMESPACE::position( it, m_source ); - } - - void restart( const std::size_t in_byte = 0, const std::size_t in_line = 1, const std::size_t in_byte_in_line = 0 ) - { - m_current.data = m_begin; - m_current.byte = in_byte; - m_current.line = in_line; - m_current.byte_in_line = in_byte_in_line; - } - - template< rewind_mode M > - void restart( const internal::marker< iterator_t, M >& m ) - { - m_current.data = m.iterator().data; - m_current.byte = m.iterator().byte; - m_current.line = m.iterator().line; - m_current.byte_in_line = m.iterator().byte_in_line; - } - - protected: - const char* const m_begin; - iterator_t m_current; - const char* const m_end; - const Source m_source; - }; - - template< typename Eol, typename Source > - class memory_input_base< tracking_mode::lazy, Eol, Source > - { - public: - using iterator_t = const char*; - - template< typename T > - memory_input_base( const internal::iterator& in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) - : m_begin( in_begin ), - m_current( in_begin.data ), - m_end( in_end ), - m_source( std::forward< T >( in_source ) ) - { - } - - template< typename T > - memory_input_base( const char* in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) - : m_begin( in_begin ), - m_current( in_begin ), - m_end( in_end ), - m_source( std::forward< T >( in_source ) ) - { - } - - memory_input_base( const memory_input_base& ) = delete; - memory_input_base( memory_input_base&& ) = delete; - - ~memory_input_base() = default; - - memory_input_base operator=( const memory_input_base& ) = delete; - memory_input_base operator=( memory_input_base&& ) = delete; - - [[nodiscard]] const char* current() const noexcept - { - return m_current; - } - - [[nodiscard]] const char* begin() const noexcept - { - return m_begin.data; - } - - [[nodiscard]] const char* end( const std::size_t /*unused*/ = 0 ) const noexcept - { - return m_end; - } - - [[nodiscard]] std::size_t byte() const noexcept - { - return std::size_t( current() - m_begin.data ); - } - - void bump( const std::size_t in_count = 1 ) noexcept - { - m_current += in_count; - } - - void bump_in_this_line( const std::size_t in_count = 1 ) noexcept - { - m_current += in_count; - } - - void bump_to_next_line( const std::size_t in_count = 1 ) noexcept - { - m_current += in_count; - } - - [[nodiscard]] TAO_JSON_PEGTL_NAMESPACE::position position( const iterator_t it ) const - { - internal::iterator c( m_begin ); - internal::bump( c, std::size_t( it - m_begin.data ), Eol::ch ); - return TAO_JSON_PEGTL_NAMESPACE::position( c, m_source ); - } - - void restart() - { - m_current = m_begin.data; - } - - template< rewind_mode M > - void restart( const internal::marker< iterator_t, M >& m ) - { - m_current = m.iterator(); - } - - protected: - const internal::iterator m_begin; - iterator_t m_current; - const char* const m_end; - const Source m_source; - }; - - } // namespace internal - - template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf, typename Source = std::string > - class memory_input - : public internal::memory_input_base< P, Eol, Source > - { - public: - static constexpr tracking_mode tracking_mode_v = P; - - using eol_t = Eol; - using source_t = Source; - - using typename internal::memory_input_base< P, Eol, Source >::iterator_t; - - using action_t = internal::action_input< memory_input >; - - using internal::memory_input_base< P, Eol, Source >::memory_input_base; - - template< typename T > - memory_input( const char* in_begin, const std::size_t in_size, T&& in_source ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) - : memory_input( in_begin, in_begin + in_size, std::forward< T >( in_source ) ) - { - } - - template< typename T > - memory_input( const std::string& in_string, T&& in_source ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) - : memory_input( in_string.data(), in_string.size(), std::forward< T >( in_source ) ) - { - } - - template< typename T > - memory_input( const std::string_view in_string, T&& in_source ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) - : memory_input( in_string.data(), in_string.size(), std::forward< T >( in_source ) ) - { - } - - template< typename T > - memory_input( std::string&&, T&& ) = delete; - - template< typename T > - memory_input( const char* in_begin, T&& in_source ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) - : memory_input( in_begin, std::strlen( in_begin ), std::forward< T >( in_source ) ) - { - } - - template< typename T > - memory_input( const char* in_begin, const char* in_end, T&& in_source, const std::size_t in_byte, const std::size_t in_line, const std::size_t in_byte_in_line ) noexcept( std::is_nothrow_constructible_v< Source, T&& > ) - : memory_input( { in_begin, in_byte, in_line, in_byte_in_line }, in_end, std::forward< T >( in_source ) ) - { - } - - memory_input( const memory_input& ) = delete; - memory_input( memory_input&& ) = delete; - - ~memory_input() = default; - - memory_input operator=( const memory_input& ) = delete; - memory_input operator=( memory_input&& ) = delete; - - [[nodiscard]] const Source& source() const noexcept - { - return this->m_source; - } - - [[nodiscard]] bool empty() const noexcept - { - return this->current() == this->end(); - } - - [[nodiscard]] std::size_t size( const std::size_t /*unused*/ = 0 ) const noexcept - { - return std::size_t( this->end() - this->current() ); - } - - [[nodiscard]] char peek_char( const std::size_t offset = 0 ) const noexcept - { - return this->current()[ offset ]; - } - - [[nodiscard]] std::uint8_t peek_uint8( const std::size_t offset = 0 ) const noexcept - { - return static_cast< std::uint8_t >( peek_char( offset ) ); - } - - [[nodiscard]] iterator_t& iterator() noexcept - { - return this->m_current; - } - - [[nodiscard]] const iterator_t& iterator() const noexcept - { - return this->m_current; - } - - using internal::memory_input_base< P, Eol, Source >::position; - - [[nodiscard]] TAO_JSON_PEGTL_NAMESPACE::position position() const - { - return position( iterator() ); - } - - void discard() const noexcept - { - } - - void require( const std::size_t /*unused*/ ) const noexcept - { - } - - template< rewind_mode M > - [[nodiscard]] internal::marker< iterator_t, M > mark() noexcept - { - return internal::marker< iterator_t, M >( iterator() ); - } - - [[nodiscard]] const char* at( const TAO_JSON_PEGTL_NAMESPACE::position& p ) const noexcept - { - return this->begin() + p.byte; - } - - [[nodiscard]] const char* begin_of_line( const TAO_JSON_PEGTL_NAMESPACE::position& p ) const noexcept - { - return at( p ) - p.byte_in_line; - } - - [[nodiscard]] const char* end_of_line( const TAO_JSON_PEGTL_NAMESPACE::position& p ) const noexcept - { - using input_t = memory_input< tracking_mode::lazy, Eol, const char* >; - input_t in( at( p ), this->end(), "" ); - using grammar = internal::until< internal::at< internal::eolf > >; - (void)normal< grammar >::match< apply_mode::nothing, rewind_mode::dontcare, nothing, normal >( in ); - return in.current(); - } - - [[nodiscard]] std::string_view line_at( const TAO_JSON_PEGTL_NAMESPACE::position& p ) const noexcept - { - const char* b = begin_of_line( p ); - return std::string_view( b, end_of_line( p ) - b ); - } - }; - - template< typename... Ts > - memory_input( Ts&&... )->memory_input<>; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/mmap_input.hpp b/include/tao/json/external/pegtl/mmap_input.hpp deleted file mode 100644 index 766df579..00000000 --- a/include/tao/json/external/pegtl/mmap_input.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_MMAP_INPUT_HPP -#define TAO_JSON_PEGTL_MMAP_INPUT_HPP - -#include -#include - -#include "config.hpp" -#include "eol.hpp" -#include "memory_input.hpp" -#include "tracking_mode.hpp" - -#if defined( __unix__ ) || ( defined( __APPLE__ ) && defined( __MACH__ ) ) -#include // Required for _POSIX_MAPPED_FILES -#endif - -#if defined( _POSIX_MAPPED_FILES ) -#include "internal/file_mapper_posix.hpp" -#elif defined( _WIN32 ) -#include "internal/file_mapper_win32.hpp" -#else -#endif - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - namespace internal - { - struct mmap_holder - { - const std::string filename; - const file_mapper data; - - template< typename T > - explicit mmap_holder( T&& in_filename ) - : filename( std::forward< T >( in_filename ) ), - data( filename.c_str() ) - { - } - - mmap_holder( const mmap_holder& ) = delete; - mmap_holder( mmap_holder&& ) = delete; - - ~mmap_holder() = default; - - void operator=( const mmap_holder& ) = delete; - void operator=( mmap_holder&& ) = delete; - }; - - } // namespace internal - - template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf > - struct mmap_input - : private internal::mmap_holder, - public memory_input< P, Eol, const char* > - { - template< typename T > - explicit mmap_input( T&& in_filename ) - : internal::mmap_holder( std::forward< T >( in_filename ) ), - memory_input< P, Eol, const char* >( data.begin(), data.end(), filename.c_str() ) - { - } - - mmap_input( const mmap_input& ) = delete; - mmap_input( mmap_input&& ) = delete; - - ~mmap_input() = default; - - void operator=( const mmap_input& ) = delete; - void operator=( mmap_input&& ) = delete; - }; - - template< typename... Ts > - explicit mmap_input( Ts&&... )->mmap_input<>; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/normal.hpp b/include/tao/json/external/pegtl/normal.hpp deleted file mode 100644 index 71f7545f..00000000 --- a/include/tao/json/external/pegtl/normal.hpp +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_NORMAL_HPP -#define TAO_JSON_PEGTL_NORMAL_HPP - -#include -#include -#include - -#include "apply_mode.hpp" -#include "config.hpp" -#include "match.hpp" -#include "parse_error.hpp" -#include "rewind_mode.hpp" - -#include "internal/demangle.hpp" -#include "internal/has_match.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - template< typename Rule > - struct normal - { - template< typename Input, typename... States > - static void start( const Input& /*unused*/, States&&... /*unused*/ ) noexcept - { - } - - template< typename Input, typename... States > - static void success( const Input& /*unused*/, States&&... /*unused*/ ) noexcept - { - } - - template< typename Input, typename... States > - static void failure( const Input& /*unused*/, States&&... /*unused*/ ) noexcept - { - } - - template< typename Input, typename... States > - static void raise( const Input& in, States&&... /*unused*/ ) - { - throw parse_error( "parse error matching " + std::string( internal::demangle< Rule >() ), in ); - } - - template< template< typename... > class Action, - typename Iterator, - typename Input, - typename... States > - static auto apply( const Iterator& begin, const Input& in, States&&... st ) noexcept( noexcept( Action< Rule >::apply( std::declval< const typename Input::action_t& >(), st... ) ) ) - -> decltype( Action< Rule >::apply( std::declval< const typename Input::action_t& >(), st... ) ) - { - const typename Input::action_t action_input( begin, in ); - return Action< Rule >::apply( action_input, st... ); - } - - template< template< typename... > class Action, - typename Input, - typename... States > - static auto apply0( const Input& /*unused*/, States&&... st ) noexcept( noexcept( Action< Rule >::apply0( st... ) ) ) - -> decltype( Action< Rule >::apply0( st... ) ) - { - return Action< Rule >::apply0( st... ); - } - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - if constexpr( internal::has_match_v< Rule, A, M, Action, Control, Input, States... > ) { - return Action< Rule >::template match< Rule, A, M, Action, Control >( in, st... ); - } - else { - return TAO_JSON_PEGTL_NAMESPACE::match< Rule, A, M, Action, Control >( in, st... ); - } - } - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/nothing.hpp b/include/tao/json/external/pegtl/nothing.hpp deleted file mode 100644 index 85d56033..00000000 --- a/include/tao/json/external/pegtl/nothing.hpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_NOTHING_HPP -#define TAO_JSON_PEGTL_NOTHING_HPP - -#include "config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - template< typename Rule > - struct nothing - { - }; - - using maybe_nothing = nothing< void >; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/parse.hpp b/include/tao/json/external/pegtl/parse.hpp deleted file mode 100644 index 9a777eb8..00000000 --- a/include/tao/json/external/pegtl/parse.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_PARSE_HPP -#define TAO_JSON_PEGTL_PARSE_HPP - -#include - -#include "apply_mode.hpp" -#include "config.hpp" -#include "normal.hpp" -#include "nothing.hpp" -#include "parse_error.hpp" -#include "rewind_mode.hpp" - -#include "internal/action_input.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - template< typename Rule, - template< typename... > class Action = nothing, - template< typename... > class Control = normal, - apply_mode A = apply_mode::action, - rewind_mode M = rewind_mode::required, - typename Input, - typename... States > - bool parse( Input&& in, States&&... st ) - { - return Control< Rule >::template match< A, M, Action, Control >( in, st... ); - } - - template< typename Rule, - template< typename... > class Action = nothing, - template< typename... > class Control = normal, - apply_mode A = apply_mode::action, - rewind_mode M = rewind_mode::required, - typename Outer, - typename Input, - typename... States > - bool parse_nested( const Outer& oi, Input&& in, States&&... st ) - { - try { - return parse< Rule, Action, Control, A, M >( in, st... ); - } - catch( parse_error& e ) { - e.positions.push_back( oi.position() ); - throw; - } - } - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/parse_error.hpp b/include/tao/json/external/pegtl/parse_error.hpp deleted file mode 100644 index c139155f..00000000 --- a/include/tao/json/external/pegtl/parse_error.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_PARSE_ERROR_HPP -#define TAO_JSON_PEGTL_PARSE_ERROR_HPP - -#include -#include -#include -#include -#include -#include - -#include "config.hpp" -#include "position.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - struct parse_error - : std::runtime_error - { - template< typename Msg > - parse_error( Msg&& msg, std::vector< position > in_positions ) - : std::runtime_error( std::forward< Msg >( msg ) ), - positions( std::move( in_positions ) ) - { - } - - template< typename Msg > - parse_error( Msg&& msg, const position& pos ) - : std::runtime_error( std::forward< Msg >( msg ) ), - positions( 1, pos ) - { - } - - template< typename Msg > - parse_error( Msg&& msg, position&& pos ) - : std::runtime_error( std::forward< Msg >( msg ) ) - { - positions.emplace_back( std::move( pos ) ); - } - - template< typename Msg, typename Input > - parse_error( Msg&& msg, const Input& in ) - : parse_error( std::forward< Msg >( msg ), in.position() ) - { - } - - std::vector< position > positions; - }; - - inline std::ostream& operator<<( std::ostream& o, const parse_error& e ) - { - for( auto it = e.positions.rbegin(); it != e.positions.rend(); ++it ) { - o << *it << ": "; - } - return o << e.what(); - } - - [[nodiscard]] inline std::string to_string( const parse_error& e ) - { - std::ostringstream o; - o << e; - return o.str(); - } - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/position.hpp b/include/tao/json/external/pegtl/position.hpp deleted file mode 100644 index a362741f..00000000 --- a/include/tao/json/external/pegtl/position.hpp +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_POSITION_HPP -#define TAO_JSON_PEGTL_POSITION_HPP - -#include -#include -#include -#include -#include - -#include "config.hpp" - -#include "internal/iterator.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - struct position - { - position() = delete; - - position( position&& p ) noexcept - : byte( p.byte ), - line( p.line ), - byte_in_line( p.byte_in_line ), - source( std::move( p.source ) ) - { - } - - position( const position& ) = default; - - position& operator=( position&& p ) noexcept - { - byte = p.byte; - line = p.line; - byte_in_line = p.byte_in_line; - source = std::move( p.source ); - return *this; - } - - position& operator=( const position& ) = default; - - template< typename T > - position( const internal::iterator& in_iter, T&& in_source ) - : byte( in_iter.byte ), - line( in_iter.line ), - byte_in_line( in_iter.byte_in_line ), - source( std::forward< T >( in_source ) ) - { - } - - ~position() = default; - - std::size_t byte; - std::size_t line; - std::size_t byte_in_line; - std::string source; - }; - - inline std::ostream& operator<<( std::ostream& o, const position& p ) - { - return o << p.source << ':' << p.line << ':' << p.byte_in_line << '(' << p.byte << ')'; - } - - [[nodiscard]] inline std::string to_string( const position& p ) - { - std::ostringstream o; - o << p; - return o.str(); - } - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/read_input.hpp b/include/tao/json/external/pegtl/read_input.hpp deleted file mode 100644 index 9e69d1b4..00000000 --- a/include/tao/json/external/pegtl/read_input.hpp +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_READ_INPUT_HPP -#define TAO_JSON_PEGTL_READ_INPUT_HPP - -#include - -#include "config.hpp" -#include "eol.hpp" -#include "string_input.hpp" -#include "tracking_mode.hpp" - -#include "internal/file_reader.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - namespace internal - { - struct filename_holder - { - const std::string filename; - - template< typename T > - explicit filename_holder( T&& in_filename ) - : filename( std::forward< T >( in_filename ) ) - { - } - - filename_holder( const filename_holder& ) = delete; - filename_holder( filename_holder&& ) = delete; - - ~filename_holder() = default; - - void operator=( const filename_holder& ) = delete; - void operator=( filename_holder&& ) = delete; - }; - - } // namespace internal - - template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf > - struct read_input - : private internal::filename_holder, - public string_input< P, Eol, const char* > - { - template< typename T > - explicit read_input( T&& in_filename ) - : internal::filename_holder( std::forward< T >( in_filename ) ), - string_input< P, Eol, const char* >( internal::file_reader( filename.c_str() ).read(), filename.c_str() ) - { - } - - template< typename T > - read_input( FILE* in_file, T&& in_filename ) - : internal::filename_holder( std::forward< T >( in_filename ) ), - string_input< P, Eol, const char* >( internal::file_reader( in_file, filename.c_str() ).read(), filename.c_str() ) - { - } - - read_input( const read_input& ) = delete; - read_input( read_input&& ) = delete; - - ~read_input() = default; - - void operator=( const read_input& ) = delete; - void operator=( read_input&& ) = delete; - }; - - template< typename... Ts > - explicit read_input( Ts&&... )->read_input<>; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/require_apply.hpp b/include/tao/json/external/pegtl/require_apply.hpp deleted file mode 100644 index fd9f15a9..00000000 --- a/include/tao/json/external/pegtl/require_apply.hpp +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_REQUIRE_APPLY_HPP -#define TAO_JSON_PEGTL_REQUIRE_APPLY_HPP - -#include "config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - struct require_apply - {}; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/require_apply0.hpp b/include/tao/json/external/pegtl/require_apply0.hpp deleted file mode 100644 index 41d8112f..00000000 --- a/include/tao/json/external/pegtl/require_apply0.hpp +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_REQUIRE_APPLY0_HPP -#define TAO_JSON_PEGTL_REQUIRE_APPLY0_HPP - -#include "config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - struct require_apply0 - {}; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/rewind_mode.hpp b/include/tao/json/external/pegtl/rewind_mode.hpp deleted file mode 100644 index f97096a9..00000000 --- a/include/tao/json/external/pegtl/rewind_mode.hpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_REWIND_MODE_HPP -#define TAO_JSON_PEGTL_REWIND_MODE_HPP - -#include "config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - enum class rewind_mode : char - { - active, - required, - dontcare - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/rules.hpp b/include/tao/json/external/pegtl/rules.hpp deleted file mode 100644 index 1029450b..00000000 --- a/include/tao/json/external/pegtl/rules.hpp +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_RULES_HPP -#define TAO_JSON_PEGTL_RULES_HPP - -#include "config.hpp" -#include "parse_error.hpp" - -#include "internal/rules.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - // clang-format off - template< typename... Actions > struct apply : internal::apply< Actions... > {}; - template< typename... Actions > struct apply0 : internal::apply0< Actions... > {}; - template< template< typename... > class Action, typename... Rules > struct action : internal::action< Action, Rules... > {}; - template< typename... Rules > struct at : internal::at< Rules... > {}; - struct bof : internal::bof {}; - struct bol : internal::bol {}; - template< unsigned Num > struct bytes : internal::bytes< Num > {}; - template< template< typename... > class Control, typename... Rules > struct control : internal::control< Control, Rules... > {}; - template< typename... Rules > struct disable : internal::disable< Rules... > {}; - struct discard : internal::discard {}; - template< typename... Rules > struct enable : internal::enable< Rules... > {}; - struct eof : internal::eof {}; - struct failure : internal::trivial< false > {}; - template< typename Rule, typename... Actions > struct if_apply : internal::if_apply< Rule, Actions... > {}; - template< typename Cond, typename... Thens > struct if_must : internal::if_must< false, Cond, Thens... > {}; - template< typename Cond, typename Then, typename Else > struct if_must_else : internal::if_must_else< Cond, Then, Else > {}; - template< typename Cond, typename Then, typename Else > struct if_then_else : internal::if_then_else< Cond, Then, Else > {}; - template< typename Rule, typename Sep, typename Pad = void > struct list : internal::list< Rule, internal::pad< Sep, Pad > > {}; - template< typename Rule, typename Sep > struct list< Rule, Sep, void > : internal::list< Rule, Sep > {}; - template< typename Rule, typename Sep, typename Pad = void > struct list_must : internal::list_must< Rule, internal::pad< Sep, Pad > > {}; - template< typename Rule, typename Sep > struct list_must< Rule, Sep, void > : internal::list_must< Rule, Sep > {}; - template< typename Rule, typename Sep, typename Pad = void > struct list_tail : internal::list_tail_pad< Rule, Sep, Pad > {}; - template< typename Rule, typename Sep > struct list_tail< Rule, Sep, void > : internal::list_tail< Rule, Sep > {}; - template< typename M, typename S > struct minus : internal::rematch< M, internal::not_at< S, internal::eof > > {}; - template< typename... Rules > struct must : internal::must< Rules... > {}; - template< typename... Rules > struct not_at : internal::not_at< Rules... > {}; - template< typename... Rules > struct opt : internal::opt< Rules... > {}; - template< typename Cond, typename... Rules > struct opt_must : internal::if_must< true, Cond, Rules... > {}; - template< typename Rule, typename Pad1, typename Pad2 = Pad1 > struct pad : internal::pad< Rule, Pad1, Pad2 > {}; - template< typename Rule, typename Pad > struct pad_opt : internal::pad_opt< Rule, Pad > {}; - template< typename Rule, typename... Rules > struct plus : internal::plus< Rule, Rules... > {}; - template< typename Exception > struct raise : internal::raise< Exception > {}; - template< typename Head, typename... Rules > struct rematch : internal::rematch< Head, Rules... > {}; - template< unsigned Num, typename... Rules > struct rep : internal::rep< Num, Rules... > {}; - template< unsigned Max, typename... Rules > struct rep_max : internal::rep_min_max< 0, Max, Rules... > {}; - template< unsigned Min, typename Rule, typename... Rules > struct rep_min : internal::rep_min< Min, Rule, Rules... > {}; - template< unsigned Min, unsigned Max, typename... Rules > struct rep_min_max : internal::rep_min_max< Min, Max, Rules... > {}; - template< unsigned Max, typename... Rules > struct rep_opt : internal::rep_opt< Max, Rules... > {}; - template< unsigned Amount > struct require : internal::require< Amount > {}; - template< typename... Rules > struct seq : internal::seq< Rules... > {}; - template< typename... Rules > struct sor : internal::sor< Rules... > {}; - template< typename Rule, typename... Rules > struct star : internal::star< Rule, Rules... > {}; - template< typename Cond, typename... Rules > struct star_must : internal::star_must< Cond, Rules... > {}; - template< typename State, typename... Rules > struct state : internal::state< State, Rules... > {}; - struct success : internal::trivial< true > {}; - template< typename... Rules > struct try_catch : internal::try_catch_type< parse_error, Rules... > {}; - template< typename Exception, typename... Rules > struct try_catch_type : internal::try_catch_type< Exception, Rules... > {}; - template< typename Cond, typename... Rules > struct until : internal::until< Cond, Rules... > {}; - // clang-format on - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/string_input.hpp b/include/tao/json/external/pegtl/string_input.hpp deleted file mode 100644 index 503be5e8..00000000 --- a/include/tao/json/external/pegtl/string_input.hpp +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_STRING_INPUT_HPP -#define TAO_JSON_PEGTL_STRING_INPUT_HPP - -#include -#include - -#include "config.hpp" -#include "eol.hpp" -#include "memory_input.hpp" -#include "tracking_mode.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - namespace internal - { - struct string_holder - { - const std::string data; - - template< typename T > - explicit string_holder( T&& in_data ) - : data( std::forward< T >( in_data ) ) - { - } - - string_holder( const string_holder& ) = delete; - string_holder( string_holder&& ) = delete; - - ~string_holder() = default; - - void operator=( const string_holder& ) = delete; - void operator=( string_holder&& ) = delete; - }; - - } // namespace internal - - template< tracking_mode P = tracking_mode::eager, typename Eol = eol::lf_crlf, typename Source = std::string > - struct string_input - : private internal::string_holder, - public memory_input< P, Eol, Source > - { - template< typename V, typename T, typename... Ts > - explicit string_input( V&& in_data, T&& in_source, Ts&&... ts ) - : internal::string_holder( std::forward< V >( in_data ) ), - memory_input< P, Eol, Source >( data.data(), data.size(), std::forward< T >( in_source ), std::forward< Ts >( ts )... ) - { - } - - string_input( const string_input& ) = delete; - string_input( string_input&& ) = delete; - - ~string_input() = default; - - void operator=( const string_input& ) = delete; - void operator=( string_input&& ) = delete; - }; - - template< typename... Ts > - explicit string_input( Ts&&... )->string_input<>; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/tracking_mode.hpp b/include/tao/json/external/pegtl/tracking_mode.hpp deleted file mode 100644 index cda9fe2b..00000000 --- a/include/tao/json/external/pegtl/tracking_mode.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_TRACKING_MODE_HPP -#define TAO_JSON_PEGTL_TRACKING_MODE_HPP - -#include "config.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - enum class tracking_mode : bool - { - eager, - lazy - }; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/uint16.hpp b/include/tao/json/external/pegtl/uint16.hpp deleted file mode 100644 index 64c47a1b..00000000 --- a/include/tao/json/external/pegtl/uint16.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_UINT16_HPP -#define TAO_JSON_PEGTL_UINT16_HPP - -#include "config.hpp" - -#include "internal/peek_mask_uint.hpp" -#include "internal/peek_uint.hpp" -#include "internal/result_on_found.hpp" -#include "internal/rules.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - namespace uint16_be - { - // clang-format off - struct any : internal::any< internal::peek_uint16_be > {}; - - template< std::uint16_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_uint16_be, Cs... > {}; - template< std::uint16_t Lo, std::uint16_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_uint16_be, Lo, Hi > {}; - template< std::uint16_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_uint16_be, Cs... > {}; - template< std::uint16_t Lo, std::uint16_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_uint16_be, Lo, Hi > {}; - template< std::uint16_t... Cs > struct ranges : internal::ranges< internal::peek_uint16_be, Cs... > {}; - template< std::uint16_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_uint16_be, Cs >... > {}; - - template< std::uint16_t M, std::uint16_t... Cs > struct mask_not_one : internal::one< internal::result_on_found::failure, internal::peek_mask_uint16_be< M >, Cs... > {}; - template< std::uint16_t M, std::uint16_t Lo, std::uint16_t Hi > struct mask_not_range : internal::range< internal::result_on_found::failure, internal::peek_mask_uint16_be< M >, Lo, Hi > {}; - template< std::uint16_t M, std::uint16_t... Cs > struct mask_one : internal::one< internal::result_on_found::success, internal::peek_mask_uint16_be< M >, Cs... > {}; - template< std::uint16_t M, std::uint16_t Lo, std::uint16_t Hi > struct mask_range : internal::range< internal::result_on_found::success, internal::peek_mask_uint16_be< M >, Lo, Hi > {}; - template< std::uint16_t M, std::uint16_t... Cs > struct mask_ranges : internal::ranges< internal::peek_mask_uint16_be< M >, Cs... > {}; - template< std::uint16_t M, std::uint16_t... Cs > struct mask_string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_mask_uint16_be< M >, Cs >... > {}; - // clang-format on - - } // namespace uint16_be - - namespace uint16_le - { - // clang-format off - struct any : internal::any< internal::peek_uint16_le > {}; - - template< std::uint16_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_uint16_le, Cs... > {}; - template< std::uint16_t Lo, std::uint16_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_uint16_le, Lo, Hi > {}; - template< std::uint16_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_uint16_le, Cs... > {}; - template< std::uint16_t Lo, std::uint16_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_uint16_le, Lo, Hi > {}; - template< std::uint16_t... Cs > struct ranges : internal::ranges< internal::peek_uint16_le, Cs... > {}; - template< std::uint16_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_uint16_le, Cs >... > {}; - - template< std::uint16_t M, std::uint16_t... Cs > struct mask_not_one : internal::one< internal::result_on_found::failure, internal::peek_mask_uint16_le< M >, Cs... > {}; - template< std::uint16_t M, std::uint16_t Lo, std::uint16_t Hi > struct mask_not_range : internal::range< internal::result_on_found::failure, internal::peek_mask_uint16_le< M >, Lo, Hi > {}; - template< std::uint16_t M, std::uint16_t... Cs > struct mask_one : internal::one< internal::result_on_found::success, internal::peek_mask_uint16_le< M >, Cs... > {}; - template< std::uint16_t M, std::uint16_t Lo, std::uint16_t Hi > struct mask_range : internal::range< internal::result_on_found::success, internal::peek_mask_uint16_le< M >, Lo, Hi > {}; - template< std::uint16_t M, std::uint16_t... Cs > struct mask_ranges : internal::ranges< internal::peek_mask_uint16_le< M >, Cs... > {}; - template< std::uint16_t M, std::uint16_t... Cs > struct mask_string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_mask_uint16_le< M >, Cs >... > {}; - // clang-format on - - } // namespace uint16_le - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/uint32.hpp b/include/tao/json/external/pegtl/uint32.hpp deleted file mode 100644 index 6345c463..00000000 --- a/include/tao/json/external/pegtl/uint32.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_UINT32_HPP -#define TAO_JSON_PEGTL_UINT32_HPP - -#include "config.hpp" - -#include "internal/peek_mask_uint.hpp" -#include "internal/peek_uint.hpp" -#include "internal/result_on_found.hpp" -#include "internal/rules.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - namespace uint32_be - { - // clang-format off - struct any : internal::any< internal::peek_uint32_be > {}; - - template< std::uint32_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_uint32_be, Cs... > {}; - template< std::uint32_t Lo, std::uint32_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_uint32_be, Lo, Hi > {}; - template< std::uint32_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_uint32_be, Cs... > {}; - template< std::uint32_t Lo, std::uint32_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_uint32_be, Lo, Hi > {}; - template< std::uint32_t... Cs > struct ranges : internal::ranges< internal::peek_uint32_be, Cs... > {}; - template< std::uint32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_uint32_be, Cs >... > {}; - - template< std::uint32_t M, std::uint32_t... Cs > struct mask_not_one : internal::one< internal::result_on_found::failure, internal::peek_mask_uint32_be< M >, Cs... > {}; - template< std::uint32_t M, std::uint32_t Lo, std::uint32_t Hi > struct mask_not_range : internal::range< internal::result_on_found::failure, internal::peek_mask_uint32_be< M >, Lo, Hi > {}; - template< std::uint32_t M, std::uint32_t... Cs > struct mask_one : internal::one< internal::result_on_found::success, internal::peek_mask_uint32_be< M >, Cs... > {}; - template< std::uint32_t M, std::uint32_t Lo, std::uint32_t Hi > struct mask_range : internal::range< internal::result_on_found::success, internal::peek_mask_uint32_be< M >, Lo, Hi > {}; - template< std::uint32_t M, std::uint32_t... Cs > struct mask_ranges : internal::ranges< internal::peek_mask_uint32_be< M >, Cs... > {}; - template< std::uint32_t M, std::uint32_t... Cs > struct mask_string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_mask_uint32_be< M >, Cs >... > {}; - // clang-format on - - } // namespace uint32_be - - namespace uint32_le - { - // clang-format off - struct any : internal::any< internal::peek_uint32_le > {}; - - template< std::uint32_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_uint32_le, Cs... > {}; - template< std::uint32_t Lo, std::uint32_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_uint32_le, Lo, Hi > {}; - template< std::uint32_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_uint32_le, Cs... > {}; - template< std::uint32_t Lo, std::uint32_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_uint32_le, Lo, Hi > {}; - template< std::uint32_t... Cs > struct ranges : internal::ranges< internal::peek_uint32_le, Cs... > {}; - template< std::uint32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_uint32_le, Cs >... > {}; - - template< std::uint32_t M, std::uint32_t... Cs > struct mask_not_one : internal::one< internal::result_on_found::failure, internal::peek_mask_uint32_le< M >, Cs... > {}; - template< std::uint32_t M, std::uint32_t Lo, std::uint32_t Hi > struct mask_not_range : internal::range< internal::result_on_found::failure, internal::peek_mask_uint32_le< M >, Lo, Hi > {}; - template< std::uint32_t M, std::uint32_t... Cs > struct mask_one : internal::one< internal::result_on_found::success, internal::peek_mask_uint32_le< M >, Cs... > {}; - template< std::uint32_t M, std::uint32_t Lo, std::uint32_t Hi > struct mask_range : internal::range< internal::result_on_found::success, internal::peek_mask_uint32_le< M >, Lo, Hi > {}; - template< std::uint32_t M, std::uint32_t... Cs > struct mask_ranges : internal::ranges< internal::peek_mask_uint32_le< M >, Cs... > {}; - template< std::uint32_t M, std::uint32_t... Cs > struct mask_string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_mask_uint32_le< M >, Cs >... > {}; - // clang-format on - - } // namespace uint32_le - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/uint64.hpp b/include/tao/json/external/pegtl/uint64.hpp deleted file mode 100644 index 64f358af..00000000 --- a/include/tao/json/external/pegtl/uint64.hpp +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_UINT64_HPP -#define TAO_JSON_PEGTL_UINT64_HPP - -#include "config.hpp" - -#include "internal/peek_mask_uint.hpp" -#include "internal/peek_uint.hpp" -#include "internal/result_on_found.hpp" -#include "internal/rules.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - namespace uint64_be - { - // clang-format off - struct any : internal::any< internal::peek_uint64_be > {}; - - template< std::uint64_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_uint64_be, Cs... > {}; - template< std::uint64_t Lo, std::uint64_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_uint64_be, Lo, Hi > {}; - template< std::uint64_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_uint64_be, Cs... > {}; - template< std::uint64_t Lo, std::uint64_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_uint64_be, Lo, Hi > {}; - template< std::uint64_t... Cs > struct ranges : internal::ranges< internal::peek_uint64_be, Cs... > {}; - template< std::uint64_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_uint64_be, Cs >... > {}; - - - template< std::uint64_t M, std::uint64_t... Cs > struct mask_not_one : internal::one< internal::result_on_found::failure, internal::peek_mask_uint64_be< M >, Cs... > {}; - template< std::uint64_t M, std::uint64_t Lo, std::uint64_t Hi > struct mask_not_range : internal::range< internal::result_on_found::failure, internal::peek_mask_uint64_be< M >, Lo, Hi > {}; - template< std::uint64_t M, std::uint64_t... Cs > struct mask_one : internal::one< internal::result_on_found::success, internal::peek_mask_uint64_be< M >, Cs... > {}; - template< std::uint64_t M, std::uint64_t Lo, std::uint64_t Hi > struct mask_range : internal::range< internal::result_on_found::success, internal::peek_mask_uint64_be< M >, Lo, Hi > {}; - template< std::uint64_t M, std::uint64_t... Cs > struct mask_ranges : internal::ranges< internal::peek_mask_uint64_be< M >, Cs... > {}; - template< std::uint64_t M, std::uint64_t... Cs > struct mask_string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_mask_uint64_be< M >, Cs >... > {}; - // clang-format on - - } // namespace uint64_be - - namespace uint64_le - { - // clang-format off - struct any : internal::any< internal::peek_uint64_le > {}; - - template< std::uint64_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_uint64_le, Cs... > {}; - template< std::uint64_t Lo, std::uint64_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_uint64_le, Lo, Hi > {}; - template< std::uint64_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_uint64_le, Cs... > {}; - template< std::uint64_t Lo, std::uint64_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_uint64_le, Lo, Hi > {}; - template< std::uint64_t... Cs > struct ranges : internal::ranges< internal::peek_uint64_le, Cs... > {}; - template< std::uint64_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_uint64_le, Cs >... > {}; - - template< std::uint64_t M, std::uint64_t... Cs > struct mask_not_one : internal::one< internal::result_on_found::failure, internal::peek_mask_uint64_le< M >, Cs... > {}; - template< std::uint64_t M, std::uint64_t Lo, std::uint64_t Hi > struct mask_not_range : internal::range< internal::result_on_found::failure, internal::peek_mask_uint64_le< M >, Lo, Hi > {}; - template< std::uint64_t M, std::uint64_t... Cs > struct mask_one : internal::one< internal::result_on_found::success, internal::peek_mask_uint64_le< M >, Cs... > {}; - template< std::uint64_t M, std::uint64_t Lo, std::uint64_t Hi > struct mask_range : internal::range< internal::result_on_found::success, internal::peek_mask_uint64_le< M >, Lo, Hi > {}; - template< std::uint64_t M, std::uint64_t... Cs > struct mask_ranges : internal::ranges< internal::peek_mask_uint64_le< M >, Cs... > {}; - template< std::uint64_t M, std::uint64_t... Cs > struct mask_string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_mask_uint64_le< M >, Cs >... > {}; - // clang-format on - - } // namespace uint64_le - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/uint8.hpp b/include/tao/json/external/pegtl/uint8.hpp deleted file mode 100644 index 35a8375d..00000000 --- a/include/tao/json/external/pegtl/uint8.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_UINT8_HPP -#define TAO_JSON_PEGTL_UINT8_HPP - -#include "config.hpp" - -#include "internal/peek_mask_uint8.hpp" -#include "internal/peek_uint8.hpp" -#include "internal/result_on_found.hpp" -#include "internal/rules.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::uint8 -{ - // clang-format off - struct any : internal::any< internal::peek_uint8 > {}; - - template< std::uint8_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_uint8, Cs... > {}; - template< std::uint8_t Lo, std::uint8_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_uint8, Lo, Hi > {}; - template< std::uint8_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_uint8, Cs... > {}; - template< std::uint8_t Lo, std::uint8_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_uint8, Lo, Hi > {}; - template< std::uint8_t... Cs > struct ranges : internal::ranges< internal::peek_uint8, Cs... > {}; - template< std::uint8_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_uint8, Cs >... > {}; - - template< std::uint8_t M, std::uint8_t... Cs > struct mask_not_one : internal::one< internal::result_on_found::failure, internal::peek_mask_uint8< M >, Cs... > {}; - template< std::uint8_t M, std::uint8_t Lo, std::uint8_t Hi > struct mask_not_range : internal::range< internal::result_on_found::failure, internal::peek_mask_uint8< M >, Lo, Hi > {}; - template< std::uint8_t M, std::uint8_t... Cs > struct mask_one : internal::one< internal::result_on_found::success, internal::peek_mask_uint8< M >, Cs... > {}; - template< std::uint8_t M, std::uint8_t Lo, std::uint8_t Hi > struct mask_range : internal::range< internal::result_on_found::success, internal::peek_mask_uint8< M >, Lo, Hi > {}; - template< std::uint8_t M, std::uint8_t... Cs > struct mask_ranges : internal::ranges< internal::peek_mask_uint8< M >, Cs... > {}; - template< std::uint8_t M, std::uint8_t... Cs > struct mask_string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_mask_uint8< M >, Cs >... > {}; - // clang-format on - -} // namespace TAO_JSON_PEGTL_NAMESPACE::uint8 - -#endif diff --git a/include/tao/json/external/pegtl/utf16.hpp b/include/tao/json/external/pegtl/utf16.hpp deleted file mode 100644 index 29f969f4..00000000 --- a/include/tao/json/external/pegtl/utf16.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_UTF16_HPP -#define TAO_JSON_PEGTL_UTF16_HPP - -#include "config.hpp" - -#include "internal/peek_utf16.hpp" -#include "internal/result_on_found.hpp" -#include "internal/rules.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - namespace utf16_be - { - // clang-format off - struct any : internal::any< internal::peek_utf16_be > {}; - struct bom : internal::one< internal::result_on_found::success, internal::peek_utf16_be, 0xfeff > {}; - template< char32_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_utf16_be, Cs... > {}; - template< char32_t Lo, char32_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_utf16_be, Lo, Hi > {}; - template< char32_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_utf16_be, Cs... > {}; - template< char32_t Lo, char32_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_utf16_be, Lo, Hi > {}; - template< char32_t... Cs > struct ranges : internal::ranges< internal::peek_utf16_be, Cs... > {}; - template< char32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_utf16_be, Cs >... > {}; - // clang-format on - - } // namespace utf16_be - - namespace utf16_le - { - // clang-format off - struct any : internal::any< internal::peek_utf16_le > {}; - struct bom : internal::one< internal::result_on_found::success, internal::peek_utf16_le, 0xfeff > {}; - template< char32_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_utf16_le, Cs... > {}; - template< char32_t Lo, char32_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_utf16_le, Lo, Hi > {}; - template< char32_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_utf16_le, Cs... > {}; - template< char32_t Lo, char32_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_utf16_le, Lo, Hi > {}; - template< char32_t... Cs > struct ranges : internal::ranges< internal::peek_utf16_le, Cs... > {}; - template< char32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_utf16_le, Cs >... > {}; - // clang-format on - - } // namespace utf16_le - - namespace utf16 = TAO_JSON_PEGTL_NATIVE_UTF16; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/utf32.hpp b/include/tao/json/external/pegtl/utf32.hpp deleted file mode 100644 index e6d54879..00000000 --- a/include/tao/json/external/pegtl/utf32.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_UTF32_HPP -#define TAO_JSON_PEGTL_UTF32_HPP - -#include "config.hpp" - -#include "internal/peek_utf32.hpp" -#include "internal/result_on_found.hpp" -#include "internal/rules.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE -{ - namespace utf32_be - { - // clang-format off - struct any : internal::any< internal::peek_utf32_be > {}; - struct bom : internal::one< internal::result_on_found::success, internal::peek_utf32_be, 0xfeff > {}; - template< char32_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_utf32_be, Cs... > {}; - template< char32_t Lo, char32_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_utf32_be, Lo, Hi > {}; - template< char32_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_utf32_be, Cs... > {}; - template< char32_t Lo, char32_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_utf32_be, Lo, Hi > {}; - template< char32_t... Cs > struct ranges : internal::ranges< internal::peek_utf32_be, Cs... > {}; - template< char32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_utf32_be, Cs >... > {}; - // clang-format on - - } // namespace utf32_be - - namespace utf32_le - { - // clang-format off - struct any : internal::any< internal::peek_utf32_le > {}; - struct bom : internal::one< internal::result_on_found::success, internal::peek_utf32_le, 0xfeff > {}; - template< char32_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_utf32_le, Cs... > {}; - template< char32_t Lo, char32_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_utf32_le, Lo, Hi > {}; - template< char32_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_utf32_le, Cs... > {}; - template< char32_t Lo, char32_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_utf32_le, Lo, Hi > {}; - template< char32_t... Cs > struct ranges : internal::ranges< internal::peek_utf32_le, Cs... > {}; - template< char32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_utf32_le, Cs >... > {}; - // clang-format on - - } // namespace utf32_le - - namespace utf32 = TAO_JSON_PEGTL_NATIVE_UTF32; - -} // namespace TAO_JSON_PEGTL_NAMESPACE - -#endif diff --git a/include/tao/json/external/pegtl/utf8.hpp b/include/tao/json/external/pegtl/utf8.hpp deleted file mode 100644 index 9589f5b0..00000000 --- a/include/tao/json/external/pegtl/utf8.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2014-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_UTF8_HPP -#define TAO_JSON_PEGTL_UTF8_HPP - -#include "config.hpp" - -#include "internal/peek_utf8.hpp" -#include "internal/result_on_found.hpp" -#include "internal/rules.hpp" - -namespace TAO_JSON_PEGTL_NAMESPACE::utf8 -{ - // clang-format off - struct any : internal::any< internal::peek_utf8 > {}; - struct bom : internal::one< internal::result_on_found::success, internal::peek_utf8, 0xfeff > {}; - template< char32_t... Cs > struct not_one : internal::one< internal::result_on_found::failure, internal::peek_utf8, Cs... > {}; - template< char32_t Lo, char32_t Hi > struct not_range : internal::range< internal::result_on_found::failure, internal::peek_utf8, Lo, Hi > {}; - template< char32_t... Cs > struct one : internal::one< internal::result_on_found::success, internal::peek_utf8, Cs... > {}; - template< char32_t Lo, char32_t Hi > struct range : internal::range< internal::result_on_found::success, internal::peek_utf8, Lo, Hi > {}; - template< char32_t... Cs > struct ranges : internal::ranges< internal::peek_utf8, Cs... > {}; - template< char32_t... Cs > struct string : internal::seq< internal::one< internal::result_on_found::success, internal::peek_utf8, Cs >... > {}; - // clang-format on - -} // namespace TAO_JSON_PEGTL_NAMESPACE::utf8 - -#endif diff --git a/include/tao/json/external/pegtl/version.hpp b/include/tao/json/external/pegtl/version.hpp deleted file mode 100644 index 9baf0bb9..00000000 --- a/include/tao/json/external/pegtl/version.hpp +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/ - -#ifndef TAO_JSON_PEGTL_VERSION_HPP -#define TAO_JSON_PEGTL_VERSION_HPP - -#define TAO_JSON_PEGTL_VERSION "3.0.0" - -#define TAO_JSON_PEGTL_VERSION_MAJOR 3 -#define TAO_JSON_PEGTL_VERSION_MINOR 0 -#define TAO_JSON_PEGTL_VERSION_PATCH 0 - -#endif diff --git a/include/tao/json/external/ryu.hpp b/include/tao/json/external/ryu.hpp deleted file mode 100644 index f3c01e22..00000000 --- a/include/tao/json/external/ryu.hpp +++ /dev/null @@ -1,1216 +0,0 @@ -// This header include/tao/json/external/ryu.hpp contains -// modified portions of the ulfjack/ryu library from -// https://github.com/ulfjack/ryu -// which is licensed as follows: - -// Copyright 2018 Ulf Adams -// -// The contents of this file may be used under the terms of the Apache License, -// Version 2.0. -// -// (See accompanying file LICENSE-Apache or copy at -// http://www.apache.org/licenses/LICENSE-2.0) -// -// Alternatively, the contents of this file may be used under the terms of -// the Boost Software License, Version 1.0. -// (See accompanying file LICENSE-Boost or copy at -// https://www.boost.org/LICENSE_1_0.txt) -// -// Unless required by applicable law or agreed to in writing, this software -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. - -#ifndef TAO_JSON_EXTERNAL_RYU_HPP -#define TAO_JSON_EXTERNAL_RYU_HPP - -// Runtime compiler options: -// -DRYU_ONLY_64_BIT_OPS Avoid using uint128_t or 64-bit intrinsics. Slower, -// depending on your compiler. -// - -// ABSL avoids uint128_t on Win32 even if __SIZEOF_INT128__ is defined. -// Let's do the same for now. -#if defined( __SIZEOF_INT128__ ) && !defined( _MSC_VER ) && !defined( RYU_ONLY_64_BIT_OPS ) -#define HAS_UINT128 -#elif defined( _MSC_VER ) && !defined( RYU_ONLY_64_BIT_OPS ) && defined( _M_X64 ) && !defined( __clang__ ) // https://bugs.llvm.org/show_bug.cgi?id=37755 -#define HAS_64_BIT_INTRINSICS -#include -#endif - -#include -#include -#include -#include - -#include "itoa.hpp" - -namespace tao::json::ryu -{ - // Returns e == 0 ? 1 : ceil(log_2(5^e)). - inline uint32_t pow5bits( const std::int32_t e ) - { - // This function has only been tested for 0 <= e <= 1500. - assert( e >= 0 ); - assert( e <= 1500 ); - return ( ( std::uint32_t( e ) * 1217359 ) >> 19 ) + 1; - } - - // Returns floor(log_10(2^e)). - inline std::int32_t log10Pow2( const std::int32_t e ) - { - // This function has only been tested for 0 <= e <= 1500. - assert( e >= 0 ); - assert( e <= 1500 ); - return std::int32_t( ( uint32_t( e ) * 78913 ) >> 18 ); - } - - // Returns floor(log_10(5^e)). - inline std::int32_t log10Pow5( const std::int32_t e ) - { - // This function has only been tested for 0 <= e <= 1500. - assert( e >= 0 ); - assert( e <= 1500 ); - return std::int32_t( ( std::uint32_t( e ) * 732923 ) >> 20 ); - } - -#if defined( HAS_UINT128 ) - - using uint128_t = __uint128_t; - -#elif defined( HAS_64_BIT_INTRINSICS ) - - inline std::uint64_t umul128( const std::uint64_t a, const std::uint64_t b, std::uint64_t& productHi ) - { - return _umul128( a, b, &productHi ); - } - - inline std::uint64_t shiftright128( const std::uint64_t lo, const std::uint64_t hi, const std::uint32_t dist ) - { - // For the __shiftright128 intrinsic, the shift value is always - // modulo 64. - // In the current implementation of the double-precision version - // of Ryu, the shift value is always < 64. (In the case - // RYU_OPTIMIZE_SIZE == 0, the shift value is in the range [50,58]. - // Otherwise in the range [2,59].) - // Check this here in case a future change requires larger shift - // values. In this case this function needs to be adjusted. - assert( dist < 64 ); - return __shiftright128( lo, hi, std::uint8_t( dist ) ); - } - -#else - - static inline std::uint64_t umul128( const std::uint64_t a, const std::uint64_t b, std::uint64_t& productHi ) - { - // The casts here help MSVC to avoid calls to the __allmul library function. - const std::uint32_t aLo = (std::uint32_t)a; - const std::uint32_t aHi = ( std::uint32_t )( a >> 32 ); - const std::uint32_t bLo = (std::uint32_t)b; - const std::uint32_t bHi = ( std::uint32_t )( b >> 32 ); - - const std::uint64_t b00 = (std::uint64_t)aLo * bLo; - const std::uint64_t b01 = (std::uint64_t)aLo * bHi; - const std::uint64_t b10 = (std::uint64_t)aHi * bLo; - const std::uint64_t b11 = (std::uint64_t)aHi * bHi; - - const std::uint64_t midSum = b01 + b10; - const std::uint64_t midCarry = midSum < b01; - - const std::uint64_t productLo = b00 + ( midSum << 32 ); - const std::uint64_t productLoCarry = productLo < b00; - - productHi = b11 + ( midSum >> 32 ) + ( midCarry << 32 ) + productLoCarry; - return productLo; - } - - static inline std::uint64_t shiftright128( const std::uint64_t lo, const std::uint64_t hi, const std::uint32_t dist ) - { - // We don't need to handle the case dist >= 64 here (see above). - assert( dist > 0 ); - assert( dist < 64 ); - return ( hi << ( 64 - dist ) ) | ( lo >> dist ); - } - -#endif - - // A table of all two-digit numbers. This is used to speed up decimal digit - // generation by copying pairs of digits into the final output. - // static const char digit_table[ 200 ] = { - // '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9' - // }; - // NOTE: Now uses itoa::s_pairs to prevent having the same data twice. - - // These tables are generated by PrintDoubleLookupTable. - static const std::uint64_t pow5_inv_split[ 292 ][ 2 ] = { - { 1u, 288230376151711744u }, - { 3689348814741910324u, 230584300921369395u }, - { 2951479051793528259u, 184467440737095516u }, - { 17118578500402463900u, 147573952589676412u }, - { 12632330341676300947u, 236118324143482260u }, - { 10105864273341040758u, 188894659314785808u }, - { 15463389048156653253u, 151115727451828646u }, - { 17362724847566824558u, 241785163922925834u }, - { 17579528692795369969u, 193428131138340667u }, - { 6684925324752475329u, 154742504910672534u }, - { 18074578149087781173u, 247588007857076054u }, - { 18149011334012135262u, 198070406285660843u }, - { 3451162622983977240u, 158456325028528675u }, - { 5521860196774363583u, 253530120045645880u }, - { 4417488157419490867u, 202824096036516704u }, - { 7223339340677503017u, 162259276829213363u }, - { 7867994130342094503u, 259614842926741381u }, - { 2605046489531765280u, 207691874341393105u }, - { 2084037191625412224u, 166153499473114484u }, - { 10713157136084480204u, 265845599156983174u }, - { 12259874523609494487u, 212676479325586539u }, - { 13497248433629505913u, 170141183460469231u }, - { 14216899864323388813u, 272225893536750770u }, - { 11373519891458711051u, 217780714829400616u }, - { 5409467098425058518u, 174224571863520493u }, - { 4965798542738183305u, 278759314981632789u }, - { 7661987648932456967u, 223007451985306231u }, - { 2440241304404055250u, 178405961588244985u }, - { 3904386087046488400u, 285449538541191976u }, - { 17880904128604832013u, 228359630832953580u }, - { 14304723302883865611u, 182687704666362864u }, - { 15133127457049002812u, 146150163733090291u }, - { 16834306301794583852u, 233840261972944466u }, - { 9778096226693756759u, 187072209578355573u }, - { 15201174610838826053u, 149657767662684458u }, - { 2185786488890659746u, 239452428260295134u }, - { 5437978005854438120u, 191561942608236107u }, - { 15418428848909281466u, 153249554086588885u }, - { 6222742084545298729u, 245199286538542217u }, - { 16046240111861969953u, 196159429230833773u }, - { 1768945645263844993u, 156927543384667019u }, - { 10209010661905972635u, 251084069415467230u }, - { 8167208529524778108u, 200867255532373784u }, - { 10223115638361732810u, 160693804425899027u }, - { 1599589762411131202u, 257110087081438444u }, - { 4969020624670815285u, 205688069665150755u }, - { 3975216499736652228u, 164550455732120604u }, - { 13739044029062464211u, 263280729171392966u }, - { 7301886408508061046u, 210624583337114373u }, - { 13220206756290269483u, 168499666669691498u }, - { 17462981995322520850u, 269599466671506397u }, - { 6591687966774196033u, 215679573337205118u }, - { 12652048002903177473u, 172543658669764094u }, - { 9175230360419352987u, 276069853871622551u }, - { 3650835473593572067u, 220855883097298041u }, - { 17678063637842498946u, 176684706477838432u }, - { 13527506561580357021u, 282695530364541492u }, - { 3443307619780464970u, 226156424291633194u }, - { 6443994910566282300u, 180925139433306555u }, - { 5155195928453025840u, 144740111546645244u }, - { 15627011115008661990u, 231584178474632390u }, - { 12501608892006929592u, 185267342779705912u }, - { 2622589484121723027u, 148213874223764730u }, - { 4196143174594756843u, 237142198758023568u }, - { 10735612169159626121u, 189713759006418854u }, - { 12277838550069611220u, 151771007205135083u }, - { 15955192865369467629u, 242833611528216133u }, - { 1696107848069843133u, 194266889222572907u }, - { 12424932722681605476u, 155413511378058325u }, - { 1433148282581017146u, 248661618204893321u }, - { 15903913885032455010u, 198929294563914656u }, - { 9033782293284053685u, 159143435651131725u }, - { 14454051669254485895u, 254629497041810760u }, - { 11563241335403588716u, 203703597633448608u }, - { 16629290697806691620u, 162962878106758886u }, - { 781423413297334329u, 260740604970814219u }, - { 4314487545379777786u, 208592483976651375u }, - { 3451590036303822229u, 166873987181321100u }, - { 5522544058086115566u, 266998379490113760u }, - { 4418035246468892453u, 213598703592091008u }, - { 10913125826658934609u, 170878962873672806u }, - { 10082303693170474728u, 273406340597876490u }, - { 8065842954536379782u, 218725072478301192u }, - { 17520720807854834795u, 174980057982640953u }, - { 5897060404116273733u, 279968092772225526u }, - { 1028299508551108663u, 223974474217780421u }, - { 15580034865808528224u, 179179579374224336u }, - { 17549358155809824511u, 286687326998758938u }, - { 2971440080422128639u, 229349861599007151u }, - { 17134547323305344204u, 183479889279205720u }, - { 13707637858644275364u, 146783911423364576u }, - { 14553522944347019935u, 234854258277383322u }, - { 4264120725993795302u, 187883406621906658u }, - { 10789994210278856888u, 150306725297525326u }, - { 9885293106962350374u, 240490760476040522u }, - { 529536856086059653u, 192392608380832418u }, - { 7802327114352668369u, 153914086704665934u }, - { 1415676938738538420u, 246262538727465495u }, - { 1132541550990830736u, 197010030981972396u }, - { 15663428499760305882u, 157608024785577916u }, - { 17682787970132668764u, 252172839656924666u }, - { 10456881561364224688u, 201738271725539733u }, - { 15744202878575200397u, 161390617380431786u }, - { 17812026976236499989u, 258224987808690858u }, - { 3181575136763469022u, 206579990246952687u }, - { 13613306553636506187u, 165263992197562149u }, - { 10713244041592678929u, 264422387516099439u }, - { 12259944048016053467u, 211537910012879551u }, - { 6118606423670932450u, 169230328010303641u }, - { 2411072648389671274u, 270768524816485826u }, - { 16686253377679378312u, 216614819853188660u }, - { 13349002702143502650u, 173291855882550928u }, - { 17669055508687693916u, 277266969412081485u }, - { 14135244406950155133u, 221813575529665188u }, - { 240149081334393137u, 177450860423732151u }, - { 11452284974360759988u, 283921376677971441u }, - { 5472479164746697667u, 227137101342377153u }, - { 11756680961281178780u, 181709681073901722u }, - { 2026647139541122378u, 145367744859121378u }, - { 18000030682233437097u, 232588391774594204u }, - { 18089373360528660001u, 186070713419675363u }, - { 3403452244197197031u, 148856570735740291u }, - { 16513570034941246220u, 238170513177184465u }, - { 13210856027952996976u, 190536410541747572u }, - { 3189987192878576934u, 152429128433398058u }, - { 1414630693863812771u, 243886605493436893u }, - { 8510402184574870864u, 195109284394749514u }, - { 10497670562401807014u, 156087427515799611u }, - { 9417575270359070576u, 249739884025279378u }, - { 14912757845771077107u, 199791907220223502u }, - { 4551508647133041040u, 159833525776178802u }, - { 10971762650154775986u, 255733641241886083u }, - { 16156107749607641435u, 204586912993508866u }, - { 9235537384944202825u, 163669530394807093u }, - { 11087511001168814197u, 261871248631691349u }, - { 12559357615676961681u, 209496998905353079u }, - { 13736834907283479668u, 167597599124282463u }, - { 18289587036911657145u, 268156158598851941u }, - { 10942320814787415393u, 214524926879081553u }, - { 16132554281313752961u, 171619941503265242u }, - { 11054691591134363444u, 274591906405224388u }, - { 16222450902391311402u, 219673525124179510u }, - { 12977960721913049122u, 175738820099343608u }, - { 17075388340318968271u, 281182112158949773u }, - { 2592264228029443648u, 224945689727159819u }, - { 5763160197165465241u, 179956551781727855u }, - { 9221056315464744386u, 287930482850764568u }, - { 14755542681855616155u, 230344386280611654u }, - { 15493782960226403247u, 184275509024489323u }, - { 1326979923955391628u, 147420407219591459u }, - { 9501865507812447252u, 235872651551346334u }, - { 11290841220991868125u, 188698121241077067u }, - { 1653975347309673853u, 150958496992861654u }, - { 10025058185179298811u, 241533595188578646u }, - { 4330697733401528726u, 193226876150862917u }, - { 14532604630946953951u, 154581500920690333u }, - { 1116074521063664381u, 247330401473104534u }, - { 4582208431592841828u, 197864321178483627u }, - { 14733813189500004432u, 158291456942786901u }, - { 16195403473716186445u, 253266331108459042u }, - { 5577625149489128510u, 202613064886767234u }, - { 8151448934333213131u, 162090451909413787u }, - { 16731667109675051333u, 259344723055062059u }, - { 17074682502481951390u, 207475778444049647u }, - { 6281048372501740465u, 165980622755239718u }, - { 6360328581260874421u, 265568996408383549u }, - { 8777611679750609860u, 212455197126706839u }, - { 10711438158542398211u, 169964157701365471u }, - { 9759603424184016492u, 271942652322184754u }, - { 11497031554089123517u, 217554121857747803u }, - { 16576322872755119460u, 174043297486198242u }, - { 11764721337440549842u, 278469275977917188u }, - { 16790474699436260520u, 222775420782333750u }, - { 13432379759549008416u, 178220336625867000u }, - { 3045063541568861850u, 285152538601387201u }, - { 17193446092222730773u, 228122030881109760u }, - { 13754756873778184618u, 182497624704887808u }, - { 18382503128506368341u, 145998099763910246u }, - { 3586563302416817083u, 233596959622256395u }, - { 2869250641933453667u, 186877567697805116u }, - { 17052795772514404226u, 149502054158244092u }, - { 12527077977055405469u, 239203286653190548u }, - { 17400360011128145022u, 191362629322552438u }, - { 2852241564676785048u, 153090103458041951u }, - { 15631632947708587046u, 244944165532867121u }, - { 8815957543424959314u, 195955332426293697u }, - { 18120812478965698421u, 156764265941034957u }, - { 14235904707377476180u, 250822825505655932u }, - { 4010026136418160298u, 200658260404524746u }, - { 17965416168102169531u, 160526608323619796u }, - { 2919224165770098987u, 256842573317791675u }, - { 2335379332616079190u, 205474058654233340u }, - { 1868303466092863352u, 164379246923386672u }, - { 6678634360490491686u, 263006795077418675u }, - { 5342907488392393349u, 210405436061934940u }, - { 4274325990713914679u, 168324348849547952u }, - { 10528270399884173809u, 269318958159276723u }, - { 15801313949391159694u, 215455166527421378u }, - { 1573004715287196786u, 172364133221937103u }, - { 17274202803427156150u, 275782613155099364u }, - { 17508711057483635243u, 220626090524079491u }, - { 10317620031244997871u, 176500872419263593u }, - { 12818843235250086271u, 282401395870821749u }, - { 13944423402941979340u, 225921116696657399u }, - { 14844887537095493795u, 180736893357325919u }, - { 15565258844418305359u, 144589514685860735u }, - { 6457670077359736959u, 231343223497377177u }, - { 16234182506113520537u, 185074578797901741u }, - { 9297997190148906106u, 148059663038321393u }, - { 11187446689496339446u, 236895460861314229u }, - { 12639306166338981880u, 189516368689051383u }, - { 17490142562555006151u, 151613094951241106u }, - { 2158786396894637579u, 242580951921985771u }, - { 16484424376483351356u, 194064761537588616u }, - { 9498190686444770762u, 155251809230070893u }, - { 11507756283569722895u, 248402894768113429u }, - { 12895553841597688639u, 198722315814490743u }, - { 17695140702761971558u, 158977852651592594u }, - { 17244178680193423523u, 254364564242548151u }, - { 10105994129412828495u, 203491651394038521u }, - { 4395446488788352473u, 162793321115230817u }, - { 10722063196803274280u, 260469313784369307u }, - { 1198952927958798777u, 208375451027495446u }, - { 15716557601334680315u, 166700360821996356u }, - { 17767794532651667857u, 266720577315194170u }, - { 14214235626121334286u, 213376461852155336u }, - { 7682039686155157106u, 170701169481724269u }, - { 1223217053622520399u, 273121871170758831u }, - { 15735968901865657612u, 218497496936607064u }, - { 16278123936234436413u, 174797997549285651u }, - { 219556594781725998u, 279676796078857043u }, - { 7554342905309201445u, 223741436863085634u }, - { 9732823138989271479u, 178993149490468507u }, - { 815121763415193074u, 286389039184749612u }, - { 11720143854957885429u, 229111231347799689u }, - { 13065463898708218666u, 183288985078239751u }, - { 6763022304224664610u, 146631188062591801u }, - { 3442138057275642729u, 234609900900146882u }, - { 13821756890046245153u, 187687920720117505u }, - { 11057405512036996122u, 150150336576094004u }, - { 6623802375033462826u, 240240538521750407u }, - { 16367088344252501231u, 192192430817400325u }, - { 13093670675402000985u, 153753944653920260u }, - { 2503129006933649959u, 246006311446272417u }, - { 13070549649772650937u, 196805049157017933u }, - { 17835137349301941396u, 157444039325614346u }, - { 2710778055689733971u, 251910462920982955u }, - { 2168622444551787177u, 201528370336786364u }, - { 5424246770383340065u, 161222696269429091u }, - { 1300097203129523457u, 257956314031086546u }, - { 15797473021471260058u, 206365051224869236u }, - { 8948629602435097724u, 165092040979895389u }, - { 3249760919670425388u, 264147265567832623u }, - { 9978506365220160957u, 211317812454266098u }, - { 15361502721659949412u, 169054249963412878u }, - { 2442311466204457120u, 270486799941460606u }, - { 16711244431931206989u, 216389439953168484u }, - { 17058344360286875914u, 173111551962534787u }, - { 12535955717491360170u, 276978483140055660u }, - { 10028764573993088136u, 221582786512044528u }, - { 15401709288678291155u, 177266229209635622u }, - { 9885339602917624555u, 283625966735416996u }, - { 4218922867592189321u, 226900773388333597u }, - { 14443184738299482427u, 181520618710666877u }, - { 4175850161155765295u, 145216494968533502u }, - { 10370709072591134795u, 232346391949653603u }, - { 15675264887556728482u, 185877113559722882u }, - { 5161514280561562140u, 148701690847778306u }, - { 879725219414678777u, 237922705356445290u }, - { 703780175531743021u, 190338164285156232u }, - { 11631070584651125387u, 152270531428124985u }, - { 162968861732249003u, 243632850284999977u }, - { 11198421533611530172u, 194906280227999981u }, - { 5269388412147313814u, 155925024182399985u }, - { 8431021459435702103u, 249480038691839976u }, - { 3055468352806651359u, 199584030953471981u }, - { 17201769941212962380u, 159667224762777584u }, - { 16454785461715008838u, 255467559620444135u }, - { 13163828369372007071u, 204374047696355308u }, - { 17909760324981426303u, 163499238157084246u }, - { 2830174816776909822u, 261598781051334795u }, - { 2264139853421527858u, 209279024841067836u }, - { 16568707141704863579u, 167423219872854268u }, - { 4373838538276319787u, 267877151796566830u }, - { 3499070830621055830u, 214301721437253464u }, - { 6488605479238754987u, 171441377149802771u }, - { 3003071137298187333u, 274306203439684434u }, - { 6091805724580460189u, 219444962751747547u }, - { 15941491023890099121u, 175555970201398037u }, - { 10748990379256517301u, 280889552322236860u }, - { 8599192303405213841u, 224711641857789488u }, - { 14258051472207991719u, 179769313486231590u }, - }; - - static const std::uint64_t pow5_split[ 326 ][ 2 ] = { - { 0u, 72057594037927936u }, - { 0u, 90071992547409920u }, - { 0u, 112589990684262400u }, - { 0u, 140737488355328000u }, - { 0u, 87960930222080000u }, - { 0u, 109951162777600000u }, - { 0u, 137438953472000000u }, - { 0u, 85899345920000000u }, - { 0u, 107374182400000000u }, - { 0u, 134217728000000000u }, - { 0u, 83886080000000000u }, - { 0u, 104857600000000000u }, - { 0u, 131072000000000000u }, - { 0u, 81920000000000000u }, - { 0u, 102400000000000000u }, - { 0u, 128000000000000000u }, - { 0u, 80000000000000000u }, - { 0u, 100000000000000000u }, - { 0u, 125000000000000000u }, - { 0u, 78125000000000000u }, - { 0u, 97656250000000000u }, - { 0u, 122070312500000000u }, - { 0u, 76293945312500000u }, - { 0u, 95367431640625000u }, - { 0u, 119209289550781250u }, - { 4611686018427387904u, 74505805969238281u }, - { 10376293541461622784u, 93132257461547851u }, - { 8358680908399640576u, 116415321826934814u }, - { 612489549322387456u, 72759576141834259u }, - { 14600669991935148032u, 90949470177292823u }, - { 13639151471491547136u, 113686837721616029u }, - { 3213881284082270208u, 142108547152020037u }, - { 4314518811765112832u, 88817841970012523u }, - { 781462496279003136u, 111022302462515654u }, - { 10200200157203529728u, 138777878078144567u }, - { 13292654125893287936u, 86736173798840354u }, - { 7392445620511834112u, 108420217248550443u }, - { 4628871007212404736u, 135525271560688054u }, - { 16728102434789916672u, 84703294725430033u }, - { 7075069988205232128u, 105879118406787542u }, - { 18067209522111315968u, 132348898008484427u }, - { 8986162942105878528u, 82718061255302767u }, - { 6621017659204960256u, 103397576569128459u }, - { 3664586055578812416u, 129246970711410574u }, - { 16125424340018921472u, 80779356694631608u }, - { 1710036351314100224u, 100974195868289511u }, - { 15972603494424788992u, 126217744835361888u }, - { 9982877184015493120u, 78886090522101180u }, - { 12478596480019366400u, 98607613152626475u }, - { 10986559581596820096u, 123259516440783094u }, - { 2254913720070624656u, 77037197775489434u }, - { 12042014186943056628u, 96296497219361792u }, - { 15052517733678820785u, 120370621524202240u }, - { 9407823583549262990u, 75231638452626400u }, - { 11759779479436578738u, 94039548065783000u }, - { 14699724349295723422u, 117549435082228750u }, - { 4575641699882439235u, 73468396926392969u }, - { 10331238143280436948u, 91835496157991211u }, - { 8302361660673158281u, 114794370197489014u }, - { 1154580038986672043u, 143492962746861268u }, - { 9944984561221445835u, 89683101716788292u }, - { 12431230701526807293u, 112103877145985365u }, - { 1703980321626345405u, 140129846432481707u }, - { 17205888765512323542u, 87581154020301066u }, - { 12283988920035628619u, 109476442525376333u }, - { 1519928094762372062u, 136845553156720417u }, - { 12479170105294952299u, 85528470722950260u }, - { 15598962631618690374u, 106910588403687825u }, - { 5663645234241199255u, 133638235504609782u }, - { 17374836326682913246u, 83523897190381113u }, - { 7883487353071477846u, 104404871487976392u }, - { 9854359191339347308u, 130506089359970490u }, - { 10770660513014479971u, 81566305849981556u }, - { 13463325641268099964u, 101957882312476945u }, - { 2994098996302961243u, 127447352890596182u }, - { 15706369927971514489u, 79654595556622613u }, - { 5797904354682229399u, 99568244445778267u }, - { 2635694424925398845u, 124460305557222834u }, - { 6258995034005762182u, 77787690973264271u }, - { 3212057774079814824u, 97234613716580339u }, - { 17850130272881932242u, 121543267145725423u }, - { 18073860448192289507u, 75964541966078389u }, - { 8757267504958198172u, 94955677457597987u }, - { 6334898362770359811u, 118694596821997484u }, - { 13182683513586250689u, 74184123013748427u }, - { 11866668373555425458u, 92730153767185534u }, - { 5609963430089506015u, 115912692208981918u }, - { 17341285199088104971u, 72445432630613698u }, - { 12453234462005355406u, 90556790788267123u }, - { 10954857059079306353u, 113195988485333904u }, - { 13693571323849132942u, 141494985606667380u }, - { 17781854114260483896u, 88434366004167112u }, - { 3780573569116053255u, 110542957505208891u }, - { 114030942967678664u, 138178696881511114u }, - { 4682955357782187069u, 86361685550944446u }, - { 15077066234082509644u, 107952106938680557u }, - { 5011274737320973344u, 134940133673350697u }, - { 14661261756894078100u, 84337583545844185u }, - { 4491519140835433913u, 105421979432305232u }, - { 5614398926044292391u, 131777474290381540u }, - { 12732371365632458552u, 82360921431488462u }, - { 6692092170185797382u, 102951151789360578u }, - { 17588487249587022536u, 128688939736700722u }, - { 15604490549419276989u, 80430587335437951u }, - { 14893927168346708332u, 100538234169297439u }, - { 14005722942005997511u, 125672792711621799u }, - { 15671105866394830300u, 78545495444763624u }, - { 1142138259283986260u, 98181869305954531u }, - { 15262730879387146537u, 122727336632443163u }, - { 7233363790403272633u, 76704585395276977u }, - { 13653390756431478696u, 95880731744096221u }, - { 3231680390257184658u, 119850914680120277u }, - { 4325643253124434363u, 74906821675075173u }, - { 10018740084832930858u, 93633527093843966u }, - { 3300053069186387764u, 117041908867304958u }, - { 15897591223523656064u, 73151193042065598u }, - { 10648616992549794273u, 91438991302581998u }, - { 4087399203832467033u, 114298739128227498u }, - { 14332621041645359599u, 142873423910284372u }, - { 18181260187883125557u, 89295889943927732u }, - { 4279831161144355331u, 111619862429909666u }, - { 14573160988285219972u, 139524828037387082u }, - { 13719911636105650386u, 87203017523366926u }, - { 7926517508277287175u, 109003771904208658u }, - { 684774848491833161u, 136254714880260823u }, - { 7345513307948477581u, 85159196800163014u }, - { 18405263671790372785u, 106448996000203767u }, - { 18394893571310578077u, 133061245000254709u }, - { 13802651491282805250u, 83163278125159193u }, - { 3418256308821342851u, 103954097656448992u }, - { 4272820386026678563u, 129942622070561240u }, - { 2670512741266674102u, 81214138794100775u }, - { 17173198981865506339u, 101517673492625968u }, - { 3019754653622331308u, 126897091865782461u }, - { 4193189667727651020u, 79310682416114038u }, - { 14464859121514339583u, 99138353020142547u }, - { 13469387883465536574u, 123922941275178184u }, - { 8418367427165960359u, 77451838296986365u }, - { 15134645302384838353u, 96814797871232956u }, - { 471562554271496325u, 121018497339041196u }, - { 9518098633274461011u, 75636560836900747u }, - { 7285937273165688360u, 94545701046125934u }, - { 18330793628311886258u, 118182126307657417u }, - { 4539216990053847055u, 73863828942285886u }, - { 14897393274422084627u, 92329786177857357u }, - { 4786683537745442072u, 115412232722321697u }, - { 14520892257159371055u, 72132645451451060u }, - { 18151115321449213818u, 90165806814313825u }, - { 8853836096529353561u, 112707258517892282u }, - { 1843923083806916143u, 140884073147365353u }, - { 12681666973447792349u, 88052545717103345u }, - { 2017025661527576725u, 110065682146379182u }, - { 11744654113764246714u, 137582102682973977u }, - { 422879793461572340u, 85988814176858736u }, - { 528599741826965425u, 107486017721073420u }, - { 660749677283706782u, 134357522151341775u }, - { 7330497575943398595u, 83973451344588609u }, - { 13774807988356636147u, 104966814180735761u }, - { 3383451930163631472u, 131208517725919702u }, - { 15949715511634433382u, 82005323578699813u }, - { 6102086334260878016u, 102506654473374767u }, - { 3015921899398709616u, 128133318091718459u }, - { 18025852251620051174u, 80083323807324036u }, - { 4085571240815512351u, 100104154759155046u }, - { 14330336087874166247u, 125130193448943807u }, - { 15873989082562435760u, 78206370905589879u }, - { 15230800334775656796u, 97757963631987349u }, - { 5203442363187407284u, 122197454539984187u }, - { 946308467778435600u, 76373409087490117u }, - { 5794571603150432404u, 95466761359362646u }, - { 16466586540792816313u, 119333451699203307u }, - { 7985773578781816244u, 74583407312002067u }, - { 5370530955049882401u, 93229259140002584u }, - { 6713163693812353001u, 116536573925003230u }, - { 18030785363914884337u, 72835358703127018u }, - { 13315109668038829614u, 91044198378908773u }, - { 2808829029766373305u, 113805247973635967u }, - { 17346094342490130344u, 142256559967044958u }, - { 6229622945628943561u, 88910349979403099u }, - { 3175342663608791547u, 111137937474253874u }, - { 13192550366365765242u, 138922421842817342u }, - { 3633657960551215372u, 86826513651760839u }, - { 18377130505971182927u, 108533142064701048u }, - { 4524669058754427043u, 135666427580876311u }, - { 9745447189362598758u, 84791517238047694u }, - { 2958436949848472639u, 105989396547559618u }, - { 12921418224165366607u, 132486745684449522u }, - { 12687572408530742033u, 82804216052780951u }, - { 11247779492236039638u, 103505270065976189u }, - { 224666310012885835u, 129381587582470237u }, - { 2446259452971747599u, 80863492239043898u }, - { 12281196353069460307u, 101079365298804872u }, - { 15351495441336825384u, 126349206623506090u }, - { 14206370669262903769u, 78968254139691306u }, - { 8534591299723853903u, 98710317674614133u }, - { 15279925143082205283u, 123387897093267666u }, - { 14161639232853766206u, 77117435683292291u }, - { 13090363022639819853u, 96396794604115364u }, - { 16362953778299774816u, 120495993255144205u }, - { 12532689120651053212u, 75309995784465128u }, - { 15665861400813816515u, 94137494730581410u }, - { 10358954714162494836u, 117671868413226763u }, - { 4168503687137865320u, 73544917758266727u }, - { 598943590494943747u, 91931147197833409u }, - { 5360365506546067587u, 114913933997291761u }, - { 11312142901609972388u, 143642417496614701u }, - { 9375932322719926695u, 89776510935384188u }, - { 11719915403399908368u, 112220638669230235u }, - { 10038208235822497557u, 140275798336537794u }, - { 10885566165816448877u, 87672373960336121u }, - { 18218643725697949000u, 109590467450420151u }, - { 18161618638695048346u, 136988084313025189u }, - { 13656854658398099168u, 85617552695640743u }, - { 12459382304570236056u, 107021940869550929u }, - { 1739169825430631358u, 133777426086938662u }, - { 14922039196176308311u, 83610891304336663u }, - { 14040862976792997485u, 104513614130420829u }, - { 3716020665709083144u, 130642017663026037u }, - { 4628355925281870917u, 81651261039391273u }, - { 10397130925029726550u, 102064076299239091u }, - { 8384727637859770284u, 127580095374048864u }, - { 5240454773662356427u, 79737559608780540u }, - { 6550568467077945534u, 99671949510975675u }, - { 3576524565420044014u, 124589936888719594u }, - { 6847013871814915412u, 77868710555449746u }, - { 17782139376623420074u, 97335888194312182u }, - { 13004302183924499284u, 121669860242890228u }, - { 17351060901807587860u, 76043662651806392u }, - { 3242082053549933210u, 95054578314757991u }, - { 17887660622219580224u, 118818222893447488u }, - { 11179787888887237640u, 74261389308404680u }, - { 13974734861109047050u, 92826736635505850u }, - { 8245046539531533005u, 116033420794382313u }, - { 16682369133275677888u, 72520887996488945u }, - { 7017903361312433648u, 90651109995611182u }, - { 17995751238495317868u, 113313887494513977u }, - { 8659630992836983623u, 141642359368142472u }, - { 5412269370523114764u, 88526474605089045u }, - { 11377022731581281359u, 110658093256361306u }, - { 4997906377621825891u, 138322616570451633u }, - { 14652906532082110942u, 86451635356532270u }, - { 9092761128247862869u, 108064544195665338u }, - { 2142579373455052779u, 135080680244581673u }, - { 12868327154477877747u, 84425425152863545u }, - { 2250350887815183471u, 105531781441079432u }, - { 2812938609768979339u, 131914726801349290u }, - { 6369772649532999991u, 82446704250843306u }, - { 17185587848771025797u, 103058380313554132u }, - { 3035240737254230630u, 128822975391942666u }, - { 6508711479211282048u, 80514359619964166u }, - { 17359261385868878368u, 100642949524955207u }, - { 17087390713908710056u, 125803686906194009u }, - { 3762090168551861929u, 78627304316371256u }, - { 4702612710689827411u, 98284130395464070u }, - { 15101637925217060072u, 122855162994330087u }, - { 16356052730901744401u, 76784476871456304u }, - { 1998321839917628885u, 95980596089320381u }, - { 7109588318324424010u, 119975745111650476u }, - { 13666864735807540814u, 74984840694781547u }, - { 12471894901332038114u, 93731050868476934u }, - { 6366496589810271835u, 117163813585596168u }, - { 3979060368631419896u, 73227383490997605u }, - { 9585511479216662775u, 91534229363747006u }, - { 2758517312166052660u, 114417786704683758u }, - { 12671518677062341634u, 143022233380854697u }, - { 1002170145522881665u, 89388895863034186u }, - { 10476084718758377889u, 111736119828792732u }, - { 13095105898447972362u, 139670149785990915u }, - { 5878598177316288774u, 87293843616244322u }, - { 16571619758500136775u, 109117304520305402u }, - { 11491152661270395161u, 136396630650381753u }, - { 264441385652915120u, 85247894156488596u }, - { 330551732066143900u, 106559867695610745u }, - { 5024875683510067779u, 133199834619513431u }, - { 10058076329834874218u, 83249896637195894u }, - { 3349223375438816964u, 104062370796494868u }, - { 4186529219298521205u, 130077963495618585u }, - { 14145795808130045513u, 81298727184761615u }, - { 13070558741735168987u, 101623408980952019u }, - { 11726512408741573330u, 127029261226190024u }, - { 7329070255463483331u, 79393288266368765u }, - { 13773023837756742068u, 99241610332960956u }, - { 17216279797195927585u, 124052012916201195u }, - { 8454331864033760789u, 77532508072625747u }, - { 5956228811614813082u, 96915635090782184u }, - { 7445286014518516353u, 121144543863477730u }, - { 9264989777501460624u, 75715339914673581u }, - { 16192923240304213684u, 94644174893341976u }, - { 1794409976670715490u, 118305218616677471u }, - { 8039035263060279037u, 73940761635423419u }, - { 5437108060397960892u, 92425952044279274u }, - { 16019757112352226923u, 115532440055349092u }, - { 788976158365366019u, 72207775034593183u }, - { 14821278253238871236u, 90259718793241478u }, - { 9303225779693813237u, 112824648491551848u }, - { 11629032224617266546u, 141030810614439810u }, - { 11879831158813179495u, 88144256634024881u }, - { 1014730893234310657u, 110180320792531102u }, - { 10491785653397664129u, 137725400990663877u }, - { 8863209042587234033u, 86078375619164923u }, - { 6467325284806654637u, 107597969523956154u }, - { 17307528642863094104u, 134497461904945192u }, - { 10817205401789433815u, 84060913690590745u }, - { 18133192770664180173u, 105076142113238431u }, - { 18054804944902837312u, 131345177641548039u }, - { 18201782118205355176u, 82090736025967524u }, - { 4305483574047142354u, 102613420032459406u }, - { 14605226504413703751u, 128266775040574257u }, - { 2210737537617482988u, 80166734400358911u }, - { 16598479977304017447u, 100208418000448638u }, - { 11524727934775246001u, 125260522500560798u }, - { 2591268940807140847u, 78287826562850499u }, - { 17074144231291089770u, 97859783203563123u }, - { 16730994270686474309u, 122324729004453904u }, - { 10456871419179046443u, 76452955627783690u }, - { 3847717237119032246u, 95566194534729613u }, - { 9421332564826178211u, 119457743168412016u }, - { 5888332853016361382u, 74661089480257510u }, - { 16583788103125227536u, 93326361850321887u }, - { 16118049110479146516u, 116657952312902359u }, - { 16991309721690548428u, 72911220195563974u }, - { 12015765115258409727u, 91139025244454968u }, - { 15019706394073012159u, 113923781555568710u }, - { 9551260955736489391u, 142404726944460888u }, - { 5969538097335305869u, 89002954340288055u }, - { 2850236603241744433u, 111253692925360069u }, - }; - -#define TAO_RYU_DOUBLE_MANTISSA_BITS 52 -#define TAO_RYU_DOUBLE_EXPONENT_BITS 11 - -#define TAO_RYU_DOUBLE_POW5_INV_BITCOUNT 122 -#define TAO_RYU_DOUBLE_POW5_BITCOUNT 121 - - inline std::int32_t pow5Factor( std::uint64_t value ) - { - for( std::int32_t count = 0; value > 0; ++count ) { - if( value % 5 != 0 ) { - return count; - } - value /= 5; - } - return 0; - } - - // Returns true if value is divisible by 5^p. - inline bool multipleOfPowerOf5( const std::uint64_t value, const std::int32_t p ) - { - // I tried a case distinction on p, but there was no performance difference. - return pow5Factor( value ) >= p; - } - - // We need a 64x128-bit multiplication and a subsequent 128-bit shift. - // Multiplication: - // The 64-bit factor is variable and passed in, the 128-bit factor comes - // from a lookup table. We know that the 64-bit factor only has 55 - // significant bits (i.e., the 9 topmost bits are zeros). The 128-bit - // factor only has 124 significant bits (i.e., the 4 topmost bits are - // zeros). - // Shift: - // In principle, the multiplication result requires 55+124=179 bits to - // represent. However, we then shift this value to the right by j, which is - // at least j >= 115, so the result is guaranteed to fit into 179-115=64 - // bits. This means that we only need the topmost 64 significant bits of - // the 64x128-bit multiplication. - // - // There are several ways to do this: - // 1. Best case: the compiler exposes a 128-bit type. - // We perform two 64x64-bit multiplications, add the higher 64 bits of the - // lower result to the higher result, and shift by j-64 bits. - // - // We explicitly cast from 64-bit to 128-bit, so the compiler can tell - // that these are only 64-bit inputs, and can map these to the best - // possible sequence of assembly instructions. - // x86-64 machines happen to have matching assembly instructions for - // 64x64-bit multiplications and 128-bit shifts. - // - // 2. Second best case: the compiler exposes intrinsics for the x86-64 assembly - // instructions mentioned in 1. - // - // 3. We only have 64x64 bit instructions that return the lower 64 bits of - // the result, i.e., we have to use plain C. - // Our inputs are less than the full width, so we have three options: - // a. Ignore this fact and just implement the intrinsics manually. - // b. Split both into 31-bit pieces, which guarantees no internal overflow, - // but requires extra work upfront (unless we change the lookup table). - // c. Split only the first factor into 31-bit pieces, which also guarantees - // no internal overflow, but requires extra work since the intermediate - // results are not perfectly aligned. -#if defined( HAS_UINT128 ) - - // Best case: use 128-bit type. - inline std::uint64_t mulShift( const std::uint64_t m, const std::uint64_t* const mul, const std::int32_t j ) - { - const uint128_t b0 = ( (uint128_t)m ) * mul[ 0 ]; - const uint128_t b2 = ( (uint128_t)m ) * mul[ 1 ]; - return ( std::uint64_t )( ( ( b0 >> 64 ) + b2 ) >> ( j - 64 ) ); - } - - inline std::uint64_t mulShiftAll( const std::uint64_t m, const std::uint64_t* const mul, const std::int32_t j, std::uint64_t* const vp, std::uint64_t* const vm, const std::uint32_t mmShift ) - { - // m <<= 2; - // uint128_t b0 = ((uint128_t) m) * mul[0]; // 0 - // uint128_t b2 = ((uint128_t) m) * mul[1]; // 64 - // - // uint128_t hi = (b0 >> 64) + b2; - // uint128_t lo = b0 & 0xffffffffffffffffull; - // uint128_t factor = (((uint128_t) mul[1]) << 64) + mul[0]; - // uint128_t vpLo = lo + (factor << 1); - // *vp = (uint64_t) ((hi + (vpLo >> 64)) >> (j - 64)); - // uint128_t vmLo = lo - (factor << mmShift); - // *vm = (uint64_t) ((hi + (vmLo >> 64) - (((uint128_t) 1ull) << 64)) >> (j - 64)); - // return (uint64_t) (hi >> (j - 64)); - *vp = mulShift( 4 * m + 2, mul, j ); - *vm = mulShift( 4 * m - 1 - mmShift, mul, j ); - return mulShift( 4 * m, mul, j ); - } - -#elif defined( HAS_64_BIT_INTRINSICS ) - - inline std::uint64_t mulShift( const std::uint64_t m, const std::uint64_t* const mul, const std::int32_t j ) - { - // m is maximum 55 bits - std::uint64_t high1; // 128 - const std::uint64_t low1 = umul128( m, mul[ 1 ], high1 ); // 64 - std::uint64_t high0; // 64 - umul128( m, mul[ 0 ], high0 ); // 0 - const std::uint64_t sum = high0 + low1; - if( sum < high0 ) { - ++high1; // overflow into high1 - } - return shiftright128( sum, high1, j - 64 ); - } - - inline std::uint64_t mulShiftAll( const std::uint64_t m, const std::uint64_t* const mul, const std::int32_t j, std::uint64_t* const vp, std::uint64_t* const vm, const std::uint32_t mmShift ) - { - *vp = mulShift( 4 * m + 2, mul, j ); - *vm = mulShift( 4 * m - 1 - mmShift, mul, j ); - return mulShift( 4 * m, mul, j ); - } - -#else // !defined( HAS_UINT128 ) && !defined( HAS_64_BIT_INTRINSICS ) - - static inline std::uint64_t mulShiftAll( std::uint64_t m, const std::uint64_t* const mul, const std::int32_t j, std::uint64_t* const vp, std::uint64_t* const vm, const std::uint32_t mmShift ) - { - m <<= 1; - // m is maximum 55 bits - std::uint64_t tmp; - const std::uint64_t lo = umul128( m, mul[ 0 ], tmp ); - std::uint64_t hi; - const std::uint64_t mid = tmp + umul128( m, mul[ 1 ], hi ); - hi += mid < tmp; // overflow into hi - - const std::uint64_t lo2 = lo + mul[ 0 ]; - const std::uint64_t mid2 = mid + mul[ 1 ] + ( lo2 < lo ); - const std::uint64_t hi2 = hi + ( mid2 < mid ); - *vp = shiftright128( mid2, hi2, j - 64 - 1 ); - - if( mmShift == 1 ) { - const std::uint64_t lo3 = lo - mul[ 0 ]; - const std::uint64_t mid3 = mid - mul[ 1 ] - ( lo3 > lo ); - const std::uint64_t hi3 = hi - ( mid3 > mid ); - *vm = shiftright128( mid3, hi3, j - 64 - 1 ); - } - else { - const std::uint64_t lo3 = lo + lo; - const std::uint64_t mid3 = mid + mid + ( lo3 < lo ); - const std::uint64_t hi3 = hi + hi + ( mid3 < mid ); - const std::uint64_t lo4 = lo3 - mul[ 0 ]; - const std::uint64_t mid4 = mid3 - mul[ 1 ] - ( lo4 > lo3 ); - const std::uint64_t hi4 = hi3 - ( mid4 > mid3 ); - *vm = shiftright128( mid4, hi4, j - 64 ); - } - return shiftright128( mid, hi, j - 64 - 1 ); - } - -#endif - - inline std::uint32_t decimalLength( const std::uint64_t v ) - { - // This is slightly faster than a loop. - // The average output length is 16.38 digits, so we check high-to-low. - // Function precondition: v is not an 18, 19, or 20-digit number. - // (17 digits are sufficient for round-tripping.) - assert( v < 100000000000000000L ); - if( v >= 10000000000000000L ) { - return 17; - } - if( v >= 1000000000000000L ) { - return 16; - } - if( v >= 100000000000000L ) { - return 15; - } - if( v >= 10000000000000L ) { - return 14; - } - if( v >= 1000000000000L ) { - return 13; - } - if( v >= 100000000000L ) { - return 12; - } - if( v >= 10000000000L ) { - return 11; - } - if( v >= 1000000000L ) { - return 10; - } - if( v >= 100000000L ) { - return 9; - } - if( v >= 10000000L ) { - return 8; - } - if( v >= 1000000L ) { - return 7; - } - if( v >= 100000L ) { - return 6; - } - if( v >= 10000L ) { - return 5; - } - if( v >= 1000L ) { - return 4; - } - if( v >= 100L ) { - return 3; - } - if( v >= 10L ) { - return 2; - } - return 1; - } - - inline std::uint32_t d2s_simplistic_step5( std::uint64_t output, std::int32_t exp, const std::int32_t olength, char* result ) - { - // TODO: Use digit_table? - - if( exp <= 0 ) { - std::memcpy( result, "0.", 2 ); - std::memset( result + 2, '0', -exp ); - const auto* end = itoa::u64toa( output, result + 2 - exp ); - return static_cast< std::uint32_t >( end - result ); - } - else if( exp >= olength ) { - itoa::u64toa( output, result ); // Return value MUST be result + olength - std::memset( result + olength, '0', exp + 2 - olength ); - result[ exp ] = '.'; - return exp + 2; - } - else { // ( exp > 0 ) && ( exp < olength ) - for( std::int32_t i = 0; i < olength - exp; ++i ) { - const std::uint32_t c = output % 10; - output /= 10; - result[ olength - i ] = char( '0' + c ); - } - result[ exp ] = '.'; - for( std::int32_t i = 0; i < exp; ++i ) { - const std::uint32_t c = output % 10; - output /= 10; - result[ exp - i - 1 ] = char( '0' + c ); - } - return olength + 1; - } - } - - inline std::uint32_t d2s_scientific_step5( std::uint64_t output, std::int32_t exp, const std::uint32_t olength, char* result ) - { - int index = olength; - - if( olength > 1 ) { - itoa::u64toa( output, result + 1 ); - result[ 0 ] = result[ 1 ]; - result[ 1 ] = '.'; - ++index; - } - else { - result[ 0 ] = char( '0' + output ); - } - if( exp ) { - result[ index++ ] = 'e'; - const auto end = itoa::i32toa( exp, result + index ); - return static_cast< std::uint32_t >( end - result ); - } - return index; - } - - inline std::uint32_t d2s_finite( const double f, char* result ) - { - // Step 1: Decode the floating-point number, and unify normalized and subnormal cases. - const std::uint32_t mantissaBits = TAO_RYU_DOUBLE_MANTISSA_BITS; - const std::uint32_t exponentBits = TAO_RYU_DOUBLE_EXPONENT_BITS; - const std::uint32_t offset = ( 1u << ( exponentBits - 1 ) ) - 1; - - std::uint64_t bits; - // This only works on little-endian architectures. - std::memcpy( &bits, &f, sizeof( double ) ); // TODO: Fix for big-endian! - - // Decode bits into sign, mantissa, and exponent. - const bool sign = ( ( bits >> ( mantissaBits + exponentBits ) ) & 1 ) != 0; - const std::uint64_t ieeeMantissa = bits & ( ( 1ull << mantissaBits ) - 1 ); - const std::uint32_t ieeeExponent = std::uint32_t( ( bits >> mantissaBits ) & ( ( 1u << exponentBits ) - 1 ) ); - - std::int32_t e2; - std::uint64_t m2; - - // NOTE: For taocpp/json this function assumes that f is finite! - // if (ieeeExponent == ((1u << exponentBits) - 1u)) { - // std::strcpy( result, (ieeeMantissa != 0) ? "NaN" : ( sign ? "-Infinity" : "Infinity" ) ); - // return std::strlen( result ); - // } else if (ieeeExponent == 0) { - // Case distinction; exit early for the easy cases. - if( ieeeExponent == 0 ) { - if( ieeeMantissa == 0 ) { - const std::uint32_t size = sign ? 4 : 3; - std::memcpy( result, &( "-0.0"[ 4 - size ] ), size ); - return size; - } - // We subtract 2 so that the bounds computation has 2 additional bits. - e2 = 1 - offset - mantissaBits - 2; - m2 = ieeeMantissa; - } - else { - e2 = ieeeExponent - offset - mantissaBits - 2; - m2 = ( 1ull << mantissaBits ) | ieeeMantissa; - } - const bool acceptBounds = ( m2 & 1 ) == 0; - - // Step 2: Determine the interval of legal decimal representations. - const std::uint64_t mv = 4 * m2; - // Implicit bool -> int conversion. True is 1, false is 0. - const std::uint32_t mmShift = ( m2 != ( 1ull << mantissaBits ) ) || ( ieeeExponent <= 1 ); - // We would compute mp and mm like this: - // std::uint64_t mp = 4 * m2 + 2; - // std::uint64_t mm = mv - 1 - mmShift; - - // Step 3: Convert to a decimal power base using 128-bit arithmetic. - std::uint64_t vr, vp, vm; - std::int32_t e10; - - bool vmIsTrailingZeros = false; - bool vrIsTrailingZeros = false; - - if( e2 >= 0 ) { - // I tried special-casing q == 0, but there was no effect on performance. - // This expression is slightly faster than max(0, log10Pow2(e2) - 1). - const std::int32_t q = log10Pow2( e2 ) - ( e2 > 3 ); - e10 = q; - const std::int32_t k = TAO_RYU_DOUBLE_POW5_INV_BITCOUNT + pow5bits( q ) - 1; - const std::int32_t i = -e2 + q + k; - vr = mulShiftAll( m2, pow5_inv_split[ q ], i, &vp, &vm, mmShift ); - if( q <= 21 ) { - // Only one of mp, mv, and mm can be a multiple of 5, if any. - if( mv % 5 == 0 ) { - vrIsTrailingZeros = multipleOfPowerOf5( mv, q ); - } - else { - if( acceptBounds ) { - // Same as min(e2 + (~mm & 1), pow5Factor(mm)) >= q - // <=> e2 + (~mm & 1) >= q && pow5Factor(mm) >= q - // <=> true && pow5Factor(mm) >= q, since e2 >= q. - vmIsTrailingZeros = multipleOfPowerOf5( mv - 1 - mmShift, q ); - } - else { - // Same as min(e2 + 1, pow5Factor(mp)) >= q. - vp -= multipleOfPowerOf5( mv + 2, q ); - } - } - } - } - else { - // This expression is slightly faster than max(0, log10Pow5(-e2) - 1). - const std::int32_t q = log10Pow5( -e2 ) - ( -e2 > 1 ); - e10 = q + e2; - const std::int32_t i = -e2 - q; - const std::int32_t k = pow5bits( i ) - TAO_RYU_DOUBLE_POW5_BITCOUNT; - const std::int32_t j = q - k; - vr = mulShiftAll( m2, pow5_split[ i ], j, &vp, &vm, mmShift ); - if( q <= 1 ) { - vrIsTrailingZeros = ( ~( std::uint32_t( mv ) ) & 1 ) >= std::uint32_t( q ); - if( acceptBounds ) { - vmIsTrailingZeros = ( ~( std::uint32_t( mv - 1 - mmShift ) ) & 1 ) >= std::uint32_t( q ); - } - else { - --vp; - } - } - else if( q < 63 ) { // TODO(ulfjack): Use a tighter bound here. - // We need to compute min(ntz(mv), pow5Factor(mv) - e2) >= q-1 - // <=> ntz(mv) >= q-1 && pow5Factor(mv) - e2 >= q-1 - // <=> ntz(mv) >= q-1 - // <=> (mv & ((1 << (q-1)) - 1)) == 0 - // We also need to make sure that the left shift does not overflow. - vrIsTrailingZeros = ( mv & ( ( 1ull << ( q - 1 ) ) - 1 ) ) == 0; - } - } - // Step 4: Find the shortest decimal representation in the interval of legal representations. - std::uint32_t removed = 0; - uint8_t lastRemovedDigit = 0; - std::uint64_t output; - // On average, we remove ~2 digits. - if( vmIsTrailingZeros || vrIsTrailingZeros ) { - // General case, which happens rarely (<1%). - while( vp / 10 > vm / 10 ) { -#ifdef __clang__ - // https://bugs.llvm.org/show_bug.cgi?id=23106 - // The compiler does not realize that vm % 10 can be computed from vm / 10 - // as vm - (vm / 10) * 10. - vmIsTrailingZeros &= vm - ( vm / 10 ) * 10 == 0; -#else - vmIsTrailingZeros &= vm % 10 == 0; -#endif - vrIsTrailingZeros &= lastRemovedDigit == 0; - lastRemovedDigit = std::uint8_t( vr % 10 ); - vr /= 10; - vp /= 10; - vm /= 10; - ++removed; - } - if( vmIsTrailingZeros ) { - while( vm % 10 == 0 ) { - vrIsTrailingZeros &= lastRemovedDigit == 0; - lastRemovedDigit = std::uint8_t( vr % 10 ); - vr /= 10; - vp /= 10; - vm /= 10; - ++removed; - } - } - if( vrIsTrailingZeros && ( lastRemovedDigit == 5 ) && ( vr % 2 == 0 ) ) { - // Round down not up if the number ends in X50000. - lastRemovedDigit = 4; - } - // We need to take vr+1 if vr is outside bounds or we need to round up. - output = vr + ( ( vr == vm && ( !acceptBounds || !vmIsTrailingZeros ) ) || ( lastRemovedDigit >= 5 ) ); - } - else { - // Specialized for the common case (>99%). - while( vp / 10 > vm / 10 ) { - lastRemovedDigit = std::uint8_t( vr % 10 ); - vr /= 10; - vp /= 10; - vm /= 10; - ++removed; - } - // We need to take vr+1 if vr is outside bounds or we need to round up. - output = vr + ( ( vr == vm ) || ( lastRemovedDigit >= 5 ) ); - } - // Step 5: Print the decimal representation. - - if( sign ) { - *result++ = '-'; - } - // The average output length is 16.38 digits. - const std::uint32_t olength = decimalLength( output ); - const std::int32_t exp = e10 + olength + removed; - - if( ( -6 < exp ) && ( exp < 22 ) ) { - return d2s_simplistic_step5( output, exp, olength, result ) + std::uint32_t( sign ); - } - else { - return d2s_scientific_step5( output, exp - 1, olength, result ) + std::uint32_t( sign ); - } - } - - inline void d2s_stream( std::ostream& o, const double f ) - { - char b[ 28 ]; - const auto s = d2s_finite( f, b ); - o.write( b, s ); - } - -} // namespace tao::json::ryu - -#endif diff --git a/include/tao/json/forward.hpp b/include/tao/json/forward.hpp deleted file mode 100644 index 1b0478f8..00000000 --- a/include/tao/json/forward.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_FORWARD_HPP -#define TAO_JSON_FORWARD_HPP - -namespace tao::json -{ - namespace events - { - class virtual_base; - - } // namespace events - - template< typename T, typename = void > - struct traits - {}; - - template< template< typename... > class Traits > - class basic_value; - - using value = basic_value< traits >; - - using producer_t = void ( * )( events::virtual_base&, const void* ); - - namespace internal - { - struct opaque_ptr_t - { - const void* data; - producer_t producer; - }; - - template< template< typename... > class Traits > - struct single; - - template< template< typename... > class Traits > - struct pair; - - } // namespace internal - -} // namespace tao::json - -#endif diff --git a/include/tao/json/from_file.hpp b/include/tao/json/from_file.hpp deleted file mode 100644 index 3f3c15ca..00000000 --- a/include/tao/json/from_file.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_FROM_FILE_HPP -#define TAO_JSON_FROM_FILE_HPP - -#include -#include - -#include "events/from_file.hpp" -#include "events/to_value.hpp" -#include "events/transformer.hpp" - -namespace tao::json -{ - template< template< typename... > class Traits, template< typename... > class... Transformers > - [[nodiscard]] basic_value< Traits > basic_from_file( const std::string& filename ) - { - events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; - events::from_file( consumer, filename ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers > - [[nodiscard]] value from_file( const std::string& filename ) - { - return basic_from_file< traits, Transformers... >( filename ); - } - -} // namespace tao::json - -#endif diff --git a/include/tao/json/from_input.hpp b/include/tao/json/from_input.hpp deleted file mode 100644 index c1093e12..00000000 --- a/include/tao/json/from_input.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_FROM_INPUT_HPP -#define TAO_JSON_FROM_INPUT_HPP - -#include -#include - -#include "events/from_input.hpp" -#include "events/to_value.hpp" -#include "events/transformer.hpp" - -namespace tao::json -{ - template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] basic_value< Traits > basic_from_input( Ts&&... ts ) - { - events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; - events::from_input( consumer, std::forward< Ts >( ts )... ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] value from_input( Ts&&... ts ) - { - return basic_from_input< traits, Transformers... >( std::forward< Ts >( ts )... ); - } - -} // namespace tao::json - -#endif diff --git a/include/tao/json/from_stream.hpp b/include/tao/json/from_stream.hpp deleted file mode 100644 index b1d0fd2f..00000000 --- a/include/tao/json/from_stream.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_FROM_STREAM_HPP -#define TAO_JSON_FROM_STREAM_HPP - -#include -#include -#include - -#include "events/from_stream.hpp" -#include "events/to_value.hpp" -#include "events/transformer.hpp" - -namespace tao::json -{ - template< template< typename... > class Traits, template< typename... > class... Transformers > - [[nodiscard]] basic_value< Traits > basic_from_stream( std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) - { - events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; - events::from_stream( consumer, stream, source, maximum_buffer_size ); - return std::move( consumer.value ); - } - - template< template< typename... > class Traits, template< typename... > class... Transformers > - [[nodiscard]] basic_value< Traits > basic_from_stream( std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) - { - return basic_from_stream< Traits, Transformers... >( stream, source.c_str(), maximum_buffer_size ); - } - - template< template< typename... > class... Transformers > - [[nodiscard]] value from_stream( std::istream& stream, const char* source, const std::size_t maximum_buffer_size = 4000 ) - { - return basic_from_stream< traits, Transformers... >( stream, source, maximum_buffer_size ); - } - - template< template< typename... > class... Transformers > - [[nodiscard]] value from_stream( std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) - { - return basic_from_stream< traits, Transformers... >( stream, source.c_str(), maximum_buffer_size ); - } - -} // namespace tao::json - -#endif diff --git a/include/tao/json/from_string.hpp b/include/tao/json/from_string.hpp deleted file mode 100644 index e2538a0e..00000000 --- a/include/tao/json/from_string.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_FROM_STRING_HPP -#define TAO_JSON_FROM_STRING_HPP - -#include -#include - -#include "events/from_string.hpp" -#include "events/to_value.hpp" -#include "events/transformer.hpp" - -namespace tao::json -{ - template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] basic_value< Traits > basic_from_string( Ts&&... ts ) - { - events::transformer< events::to_basic_value< Traits >, Transformers... > consumer; - events::from_string( consumer, std::forward< Ts >( ts )... ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] value from_string( Ts&&... ts ) - { - return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); - } - - inline namespace literals - { - [[nodiscard]] inline value operator"" _json( const char* data, const std::size_t size ) - { - return json::from_string( data, size, "literal" ); - } - - } // namespace literals - -} // namespace tao::json - -#endif diff --git a/include/tao/json/internal/action.hpp b/include/tao/json/internal/action.hpp deleted file mode 100644 index 9638f272..00000000 --- a/include/tao/json/internal/action.hpp +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_ACTION_HPP -#define TAO_JSON_INTERNAL_ACTION_HPP - -#include -#include - -#include "../external/pegtl/nothing.hpp" - -#include "grammar.hpp" -#include "number_state.hpp" -#include "unescape_action.hpp" - -namespace tao::json::internal -{ - template< typename Rule > - struct action - : pegtl::nothing< Rule > - {}; - - template<> - struct action< rules::null > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.null(); - } - }; - - template<> - struct action< rules::true_ > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.boolean( true ); - } - }; - - template<> - struct action< rules::false_ > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.boolean( false ); - } - }; - - template<> - struct action< rules::array::begin > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.begin_array(); - } - }; - - template<> - struct action< rules::array::element > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.element(); - } - }; - - template<> - struct action< rules::array::end > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.end_array(); - } - }; - - template<> - struct action< rules::object::begin > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.begin_object(); - } - }; - - template<> - struct action< rules::object::element > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.member(); - } - }; - - template<> - struct action< rules::object::end > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.end_object(); - } - }; - - template<> - struct action< rules::zero< false > > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.number( std::uint64_t( 0 ) ); - } - }; - - template<> - struct action< rules::zero< true > > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.number( std::int64_t( 0 ) ); - } - }; - - template<> - struct action< rules::esign > - { - template< typename Input, bool NEG > - static void apply( const Input& in, number_state< NEG >& result ) - { - result.eneg = ( in.peek_char() == '-' ); - } - }; - - template<> - struct action< rules::idigits > - { - template< typename Input, bool NEG > - static void apply( const Input& in, number_state< NEG >& result ) - { - const auto s = in.size(); - - if( s == 1 && in.peek_char() == '0' ) { - return; - } - - if( s > ( 1 << 20 ) ) { - throw pegtl::parse_error( "JSON number with 1 megabyte digits", in ); - } - - const auto c = ( std::min )( s, max_mantissa_digits ); - std::memcpy( result.mantissa, in.begin(), c ); - result.exponent10 += static_cast< typename number_state< NEG >::exponent10_t >( s - c ); - result.msize = static_cast< typename number_state< NEG >::msize_t >( c ); - - for( std::size_t i = c; i < s; ++i ) { - if( in.peek_char( i ) != '0' ) { - result.drop = true; - return; - } - } - } - }; - - template<> - struct action< rules::fdigits > - { - template< typename Input, bool NEG > - static void apply( const Input& in, number_state< NEG >& result ) - { - result.isfp = true; - - const auto* b = in.begin(); - const auto* e = in.end(); - - while( ( e > b ) && ( e[ -1 ] == '0' ) ) { - --e; - } - if( !result.msize ) { - while( ( b < e ) && ( b[ 0 ] == '0' ) ) { - ++b; - --result.exponent10; - } - } - const auto c = ( std::min )( std::size_t( e - b ), max_mantissa_digits - result.msize ); - std::memcpy( result.mantissa + result.msize, b, c ); - result.exponent10 -= static_cast< typename number_state< NEG >::exponent10_t >( c ); - result.msize += static_cast< typename number_state< NEG >::msize_t >( c ); - - for( const auto* r = b + c; r < e; ++r ) { - if( *r != '0' ) { - result.drop = true; - return; - } - } - } - }; - - template<> - struct action< rules::edigits > - { - template< typename Input, bool NEG > - static void apply( const Input& in, number_state< NEG >& result ) - { - result.isfp = true; - - const char* b = in.begin(); - - while( ( b < in.end() ) && ( b[ 0 ] == '0' ) ) { - ++b; - } - if( ( in.end() - b ) > 9 ) { - throw pegtl::parse_error( "JSON exponent has more than 9 significant digits", in ); - } - int exponent10 = 0; - - while( b < in.end() ) { - exponent10 = ( exponent10 * 10 ) + ( b[ 0 ] - '0' ); - ++b; - } - result.exponent10 += ( result.eneg ? -exponent10 : exponent10 ); - } - }; - - template< bool NEG > - struct action< rules::number< NEG > > - : pegtl::change_states< number_state< NEG > > - { - template< typename Input, typename Consumer > - static void success( const Input& /*unused*/, number_state< NEG >& state, Consumer& consumer ) - { - state.success( consumer ); - } - }; - - template<> - struct action< rules::string::content > - : pegtl::change_action_and_states< unescape_action, std::string > - { - template< typename Input, typename Consumer > - static void success( const Input& /*unused*/, std::string& unescaped, Consumer& consumer ) - { - consumer.string( std::move( unescaped ) ); - } - }; - - template<> - struct action< rules::key::content > - : pegtl::change_action_and_states< unescape_action, std::string > - { - template< typename Input, typename Consumer > - static void success( const Input& /*unused*/, std::string& unescaped, Consumer& consumer ) - { - consumer.key( std::move( unescaped ) ); - } - }; - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/internal/base64.hpp b/include/tao/json/internal/base64.hpp deleted file mode 100644 index 64130b05..00000000 --- a/include/tao/json/internal/base64.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_BASE64_HPP -#define TAO_JSON_INTERNAL_BASE64_HPP - -#include -#include - -namespace tao::json::internal -{ - template< typename T > - [[nodiscard]] std::string base64( const T& v ) - { - static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - std::string s; - s.reserve( ( v.size() + 2 ) / 3 * 4 ); - - unsigned cycle = 0; - unsigned encode = 0; - for( const auto c : v ) { - encode <<= 8; - encode += static_cast< unsigned char >( c ); - s += table[ ( encode >> ( ++cycle * 2 ) ) & 0x3f ]; - if( cycle == 3 ) { - cycle = 0; - s += table[ encode & 0x3f ]; - } - } - - switch( cycle ) { - case 0: - break; - - case 1: - s += table[ ( encode << 4 ) & 0x3f ]; - s += "=="; - break; - - case 2: - s += table[ ( encode << 2 ) & 0x3f ]; - s += '='; - break; - - default: - throw std::logic_error( "code should be unreachable" ); // LCOV_EXCL_LINE - } - - return s; - } - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/internal/base64url.hpp b/include/tao/json/internal/base64url.hpp deleted file mode 100644 index 5649ba0f..00000000 --- a/include/tao/json/internal/base64url.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_BASE64URL_HPP -#define TAO_JSON_INTERNAL_BASE64URL_HPP - -#include -#include - -namespace tao::json::internal -{ - template< typename T > - [[nodiscard]] std::string base64url( const T& v ) - { - static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - - std::string s; - s.reserve( ( v.size() + 2 ) / 3 * 4 ); - - unsigned cycle = 0; - unsigned encode = 0; - for( const auto c : v ) { - encode <<= 8; - encode += static_cast< unsigned char >( c ); - s += table[ ( encode >> ( ++cycle * 2 ) ) & 0x3f ]; - if( cycle == 3 ) { - cycle = 0; - s += table[ encode & 0x3f ]; - } - } - - switch( cycle ) { - case 0: - break; - - case 1: - s += table[ ( encode << 4 ) & 0x3f ]; - break; - - case 2: - s += table[ ( encode << 2 ) & 0x3f ]; - break; - - default: - throw std::logic_error( "code should be unreachable" ); // LCOV_EXCL_LINE - } - - return s; - } - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/internal/endian.hpp b/include/tao/json/internal/endian.hpp deleted file mode 100644 index 7448fb41..00000000 --- a/include/tao/json/internal/endian.hpp +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_ENDIAN_HPP -#define TAO_JSON_INTERNAL_ENDIAN_HPP - -#include -#include - -#if defined( _WIN32 ) && !defined( __MINGW32__ ) -#include "endian_win.hpp" -#else -#include "endian_gcc.hpp" -#endif - -namespace tao::json::internal -{ - template< typename N > - [[nodiscard]] N h_to_be( const N n ) noexcept - { - return N( to_and_from_be< sizeof( N ) >::convert( n ) ); - } - - template< typename N > - [[nodiscard]] N be_to_h( const N n ) noexcept - { - return h_to_be( n ); - } - - template< typename N > - [[nodiscard]] N be_to_h( const void* p ) noexcept - { - N n; - std::memcpy( &n, p, sizeof( n ) ); - return internal::be_to_h( n ); - } - - template< typename N > - [[nodiscard]] N h_to_le( const N n ) noexcept - { - return N( to_and_from_le< sizeof( N ) >::convert( n ) ); - } - - template< typename N > - [[nodiscard]] N le_to_h( const N n ) noexcept - { - return h_to_le( n ); - } - - template< typename N > - [[nodiscard]] N le_to_h( const void* p ) noexcept - { - N n; - std::memcpy( &n, p, sizeof( n ) ); - return internal::le_to_h( n ); - } - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/internal/endian_gcc.hpp b/include/tao/json/internal/endian_gcc.hpp deleted file mode 100644 index b1cdb9d2..00000000 --- a/include/tao/json/internal/endian_gcc.hpp +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_ENDIAN_GCC_HPP -#define TAO_JSON_INTERNAL_ENDIAN_GCC_HPP - -#include -#include - -namespace tao::json::internal -{ -#if not defined( __BYTE_ORDER__ ) -#error TODO -- what? -#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - - template< unsigned S > - struct to_and_from_be - { - template< typename T > - [[nodiscard]] static T convert( const T n ) noexcept - { - return n; - } - }; - - template< unsigned S > - struct to_and_from_le; - - template<> - struct to_and_from_le< 1 > - { - [[nodiscard]] static std::uint8_t convert( const std::uint8_t n ) noexcept - { - return n; - } - - [[nodiscard]] static std::int8_t convert( const std::int8_t n ) noexcept - { - return n; - } - }; - - template<> - struct to_and_from_le< 2 > - { - [[nodiscard]] static std::int16_t convert( const std::int16_t n ) noexcept - { - return __builtin_bswap16( n ); - } - - [[nodiscard]] static std::uint16_t convert( const std::uint16_t n ) noexcept - { - return __builtin_bswap16( n ); - } - }; - - template<> - struct to_and_from_le< 4 > - { - [[nodiscard]] static float convert( float n ) noexcept - { - std::uint32_t u; - std::memcpy( &u, &n, 4 ); - u = convert( u ); - std::memcpy( &n, &u, 4 ); - return n; - } - - [[nodiscard]] static std::int32_t convert( const std::int32_t n ) noexcept - { - return __builtin_bswap32( n ); - } - - [[nodiscard]] static std::uint32_t convert( const std::uint32_t n ) noexcept - { - return __builtin_bswap32( n ); - } - }; - - template<> - struct to_and_from_le< 8 > - { - [[nodiscard]] static double convert( double n ) noexcept - { - std::uint64_t u; - std::memcpy( &u, &n, 8 ); - u = convert( u ); - std::memcpy( &n, &u, 8 ); - return n; - } - - [[nodiscard]] static std::int64_t convert( const std::int64_t n ) noexcept - { - return __builtin_bswap64( n ); - } - - [[nodiscard]] static std::uint64_t convert( const std::uint64_t n ) noexcept - { - return __builtin_bswap64( n ); - } - }; - -#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - - template< unsigned S > - struct to_and_from_le - { - template< typename T > - [[nodiscard]] static T convert( const T n ) noexcept - { - return n; - } - }; - - template< unsigned S > - struct to_and_from_be; - - template<> - struct to_and_from_be< 1 > - { - [[nodiscard]] static std::int8_t convert( const std::int8_t n ) noexcept - { - return n; - } - - [[nodiscard]] static std::uint8_t convert( const std::uint8_t n ) noexcept - { - return n; - } - }; - - template<> - struct to_and_from_be< 2 > - { - [[nodiscard]] static std::int16_t convert( const std::int16_t n ) noexcept - { - return __builtin_bswap16( n ); - } - - [[nodiscard]] static std::uint16_t convert( const std::uint16_t n ) noexcept - { - return __builtin_bswap16( n ); - } - }; - - template<> - struct to_and_from_be< 4 > - { - [[nodiscard]] static float convert( float n ) noexcept - { - std::uint32_t u; - std::memcpy( &u, &n, 4 ); - u = convert( u ); - std::memcpy( &n, &u, 4 ); - return n; - } - - [[nodiscard]] static std::int32_t convert( const std::int32_t n ) noexcept - { - return __builtin_bswap32( n ); - } - - [[nodiscard]] static std::uint32_t convert( const std::uint32_t n ) noexcept - { - return __builtin_bswap32( n ); - } - }; - - template<> - struct to_and_from_be< 8 > - { - [[nodiscard]] static double convert( double n ) noexcept - { - std::uint64_t u; - std::memcpy( &u, &n, 8 ); - u = convert( u ); - std::memcpy( &n, &u, 8 ); - return n; - } - - [[nodiscard]] static std::uint64_t convert( const std::uint64_t n ) noexcept - { - return __builtin_bswap64( n ); - } - - [[nodiscard]] static std::int64_t convert( const std::int64_t n ) noexcept - { - return __builtin_bswap64( n ); - } - }; - -#else -#error Unknown host byte order! -#endif - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/internal/endian_win.hpp b/include/tao/json/internal/endian_win.hpp deleted file mode 100644 index bb0856ea..00000000 --- a/include/tao/json/internal/endian_win.hpp +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_ENDIAN_WIN_HPP -#define TAO_JSON_INTERNAL_ENDIAN_WIN_HPP - -#include -#include - -#include // TODO: Or is intrin.h the 'more correct' header for the _byteswap_foo() functions? - -namespace tao::json::internal -{ - template< unsigned S > - struct to_and_from_le - { - template< typename T > - [[nodiscard]] static T convert( const T t ) noexcept - { - return t; - } - }; - - template< unsigned S > - struct to_and_from_be; - - template<> - struct to_and_from_be< 1 > - { - [[nodiscard]] static std::int8_t convert( const std::int8_t n ) noexcept - { - return n; - } - - [[nodiscard]] static std::uint8_t convert( const std::uint8_t n ) noexcept - { - return n; - } - }; - - template<> - struct to_and_from_be< 2 > - { - [[nodiscard]] static std::int16_t convert( const std::int16_t n ) noexcept - { - return std::int16_t( _byteswap_ushort( std::uint16_t( n ) ) ); - } - - [[nodiscard]] static std::uint16_t convert( const std::uint16_t n ) noexcept - { - return _byteswap_ushort( n ); - } - }; - - template<> - struct to_and_from_be< 4 > - { - [[nodiscard]] static float convert( float n ) noexcept - { - std::uint32_t u; - std::memcpy( &u, &n, 4 ); - u = convert( u ); - std::memcpy( &n, &u, 4 ); - return n; - } - - [[nodiscard]] static std::int32_t convert( const std::int32_t n ) noexcept - { - return std::int32_t( _byteswap_ulong( std::uint32_t( n ) ) ); - } - - [[nodiscard]] static std::uint32_t convert( const std::uint32_t n ) noexcept - { - return _byteswap_ulong( n ); - } - }; - - template<> - struct to_and_from_be< 8 > - { - [[nodiscard]] static double convert( double n ) noexcept - { - std::uint64_t u; - std::memcpy( &u, &n, 8 ); - u = convert( u ); - std::memcpy( &n, &u, 8 ); - return n; - } - - [[nodiscard]] static std::int64_t convert( const std::int64_t n ) noexcept - { - return std::int64_t( _byteswap_uint64( std::uint64_t( n ) ) ); - } - - [[nodiscard]] static std::uint64_t convert( const std::uint64_t n ) noexcept - { - return _byteswap_uint64( n ); - } - }; - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/internal/errors.hpp b/include/tao/json/internal/errors.hpp deleted file mode 100644 index 6071a91d..00000000 --- a/include/tao/json/internal/errors.hpp +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_ERRORS_HPP -#define TAO_JSON_INTERNAL_ERRORS_HPP - -#include - -#include "../external/pegtl/normal.hpp" -#include "../external/pegtl/parse_error.hpp" - -#include "grammar.hpp" - -namespace tao::json::internal -{ - template< typename Rule > - struct errors - : pegtl::normal< Rule > - { - static const std::string error_message; - - template< typename Input, typename... States > - static void raise( const Input& in, States&&... /*unused*/ ) - { - throw pegtl::parse_error( error_message, in ); - } - - template< template< typename... > class Action, typename Iterator, typename Input, typename... States > - static auto apply( const Iterator& begin, const Input& in, States&&... st ) - -> decltype( Action< Rule >::apply( std::declval< const typename Input::action_t& >(), st... ) ) - { - try { - using action_t = typename Input::action_t; - const action_t action_input( begin, in ); - return Action< Rule >::apply( action_input, st... ); - } - catch( const pegtl::parse_error& ) { - throw; - } - catch( const std::exception& e ) { - throw pegtl::parse_error( e.what(), in ); - } - } - - template< template< typename... > class Action, typename Input, typename... States > - static auto apply0( const Input& in, States&&... st ) - -> decltype( Action< Rule >::apply0( st... ) ) - { - try { - return Action< Rule >::apply0( st... ); - } - catch( const pegtl::parse_error& ) { - throw; - } - catch( const std::exception& e ) { - throw pegtl::parse_error( e.what(), in ); - } - } - }; - - // clang-format off - template<> inline const std::string errors< rules::text >::error_message = "no valid JSON"; - - template<> inline const std::string errors< rules::end_array >::error_message = "incomplete array, expected ']'"; - template<> inline const std::string errors< rules::end_object >::error_message = "incomplete object, expected '}'"; - template<> inline const std::string errors< rules::member >::error_message = "expected member"; - template<> inline const std::string errors< rules::name_separator >::error_message = "expected ':'"; - template<> inline const std::string errors< rules::array_element >::error_message = "expected value"; - template<> inline const std::string errors< rules::value >::error_message = "expected value"; - template<> inline const std::string errors< rules::sor_value >::error_message = "expected value"; - - template<> inline const std::string errors< rules::edigits >::error_message = "expected at least one exponent digit"; - template<> inline const std::string errors< rules::fdigits >::error_message = "expected at least one fraction digit"; - template<> inline const std::string errors< rules::xdigit >::error_message = "incomplete universal character name"; - template<> inline const std::string errors< rules::escaped >::error_message = "unknown escape sequence"; - template<> inline const std::string errors< rules::unescaped >::error_message = "invalid unescaped character"; - template<> inline const std::string errors< rules::string::content >::error_message = "unterminated string"; - template<> inline const std::string errors< rules::key::content >::error_message = "unterminated key"; - - template<> inline const std::string errors< pegtl::eof >::error_message = "unexpected character after JSON value"; - // clang-format on - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/internal/escape.hpp b/include/tao/json/internal/escape.hpp deleted file mode 100644 index a6e68729..00000000 --- a/include/tao/json/internal/escape.hpp +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_ESCAPE_HPP -#define TAO_JSON_INTERNAL_ESCAPE_HPP - -#include -#include -#include -#include - -namespace tao::json::internal -{ - inline void escape( std::ostream& os, const std::string_view s ) - { - static const char* h = "0123456789abcdef"; - - const char* p = s.data(); - const char* l = p; - const char* const e = s.data() + s.size(); - while( p != e ) { - const unsigned char c = *p; - if( c == '\\' ) { - os.write( l, p - l ); - l = ++p; - os << "\\\\"; - } - else if( c == '"' ) { - os.write( l, p - l ); - l = ++p; - os << "\\\""; - } - else if( c < 32 ) { - os.write( l, p - l ); - l = ++p; - switch( c ) { - case '\b': - os << "\\b"; - break; - case '\f': - os << "\\f"; - break; - case '\n': - os << "\\n"; - break; - case '\r': - os << "\\r"; - break; - case '\t': - os << "\\t"; - break; - default: - os << "\\u00" << h[ ( c & 0xf0 ) >> 4 ] << h[ c & 0x0f ]; - } - } - else if( c == 127 ) { - os.write( l, p - l ); - l = ++p; - os << "\\u007f"; - } - else { - ++p; - } - } - os.write( l, p - l ); - } - - [[nodiscard]] inline std::string escape( const std::string_view s ) - { - std::ostringstream o; - escape( o, s ); - return o.str(); - } - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/internal/format.hpp b/include/tao/json/internal/format.hpp deleted file mode 100644 index 3bf72725..00000000 --- a/include/tao/json/internal/format.hpp +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_FORMAT_HPP -#define TAO_JSON_INTERNAL_FORMAT_HPP - -#include -#include -#include - -#include "escape.hpp" - -#include "../forward.hpp" -#include "../message_extension.hpp" -#include "../type.hpp" - -#include "../external/pegtl/internal/demangle.hpp" - -namespace tao::json::internal -{ - inline void to_stream( std::ostream& os, const bool v ) - { - os << ( v ? "true" : "false" ); - } - - inline void to_stream( std::ostream& os, const type t ) - { - os << to_string( t ); - } - - template< typename T > - void to_stream( std::ostream& os, const T& t ) - { - os << t; - } - - template< std::size_t N > - void to_stream( std::ostream& os, const char ( &t )[ N ] ) - { - os.write( t, N - 1 ); - } - - template< typename... Ts > - void format_to( std::ostream& oss, const Ts&... ts ) - { - ( internal::to_stream( oss, ts ), ... ); - } - - template< typename... Ts > - [[nodiscard]] std::string format( const Ts&... ts ) - { - std::ostringstream oss; - format_to( oss, ts... ); - return oss.str(); - } - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/internal/grammar.hpp b/include/tao/json/internal/grammar.hpp deleted file mode 100644 index b5919ae6..00000000 --- a/include/tao/json/internal/grammar.hpp +++ /dev/null @@ -1,229 +0,0 @@ -// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_GRAMMAR_HPP -#define TAO_JSON_INTERNAL_GRAMMAR_HPP - -#include "../external/pegtl.hpp" -#include "../external/pegtl/contrib/abnf.hpp" - -namespace tao::json::internal -{ - // clang-format off - namespace rules - { - using namespace pegtl; - - struct ws : one< ' ', '\t', '\n', '\r' > {}; - - template< typename R, typename P = ws > - using padr = pegtl::internal::seq< R, pegtl::internal::star< P > >; - - struct begin_array : padr< one< '[' > > {}; - struct begin_object : padr< one< '{' > > {}; - struct end_array : one< ']' > {}; - struct end_object : one< '}' > {}; - struct name_separator : pad< one< ':' >, ws > {}; - struct value_separator : padr< one< ',' > > {}; - struct element_separator : padr< one< ',' > > {}; - - struct false_ : pegtl::string< 'f', 'a', 'l', 's', 'e' > {}; - struct null : pegtl::string< 'n', 'u', 'l', 'l' > {}; - struct true_ : pegtl::string< 't', 'r', 'u', 'e' > {}; - - struct digits : plus< abnf::DIGIT > {}; - - struct esign : one< '-', '+' > {}; - - struct edigits : digits {}; - struct fdigits : digits {}; - struct idigits : digits {}; - - struct exp : seq< one< 'e', 'E' >, opt< esign >, must< edigits > > {}; - struct frac : if_must< one< '.' >, fdigits > {}; - - template< bool NEG > - struct number : seq< idigits, opt< frac >, opt< exp > > {}; - - struct xdigit : abnf::HEXDIG {}; - struct escaped_unicode : list< seq< one< 'u' >, rep< 4, must< xdigit > > >, one< '\\' > > {}; - - struct escaped_char : one< '"', '\\', '/', 'b', 'f', 'n', 'r', 't' > {}; - struct escaped : sor< escaped_char, escaped_unicode > {}; - - struct unescaped - { - using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) - { - bool result = false; - - while( const std::size_t s = in.size( 4 ) ) { - if( const auto t = pegtl::internal::peek_utf8::peek( in, s ) ) { - if( ( 0x20 <= t.data ) && ( t.data != '\\' ) && ( t.data != '"' ) ) { - in.bump_in_this_line( t.size ); - result = true; - continue; - } - } - break; - } - return result; - } - }; - - struct chars : if_must_else< one< '\\' >, escaped, unescaped > {}; - - struct string_content : until< at< one< '"' > >, chars > {}; - struct string : seq< one< '"' >, must< string_content >, any > - { - using content = string_content; - }; - - struct key_content : string_content {}; - struct key : seq< one< '"' >, must< key_content >, any > - { - using content = key_content; - }; - - struct value; - - struct array_element; - struct array_content : opt< list_must< array_element, element_separator > > {}; - struct array : seq< begin_array, array_content, must< end_array > > - { - using begin = begin_array; - using end = end_array; - using element = array_element; - using content = array_content; - }; - - struct member : if_must< key, name_separator, value > {}; - struct object_content : opt< list_must< member, value_separator > > {}; - struct object : seq< begin_object, object_content, must< end_object > > - { - using begin = begin_object; - using end = end_object; - using element = member; - using content = object_content; - }; - - template< bool NEG > - struct zero {}; - - struct sor_value - { - using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::sor, string, number< false >, object, array, false_, true_, null >; - - template< bool NEG, - apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match_zero( Input& in, States&&... st ) - { - if( in.size( 2 ) > 1 ) { - switch( in.peek_char( 1 ) ) { - case '.': - case 'e': - case 'E': - return Control< number< NEG > >::template match< A, M, Action, Control >( in, st... ); - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - throw pegtl::parse_error( "invalid leading zero", in ); - } - } - in.bump_in_this_line(); - Control< zero< NEG > >::template apply0< Action >( in, st... ); - return true; - } - - template< bool NEG, - apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match_number( Input& in, States&&... st ) - { - if( in.peek_char() == '0' ) { - if( !match_zero< NEG, A, rewind_mode::dontcare, Action, Control >( in, st... ) ) { - throw pegtl::parse_error( "incomplete number", in ); - } - return true; - } - return Control< number< NEG > >::template match< A, M, Action, Control >( in, st... ); - } - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match_impl( Input& in, States&&... st ) - { - switch( in.peek_char() ) { - case '"': return Control< string >::template match< A, M, Action, Control >( in, st... ); - case '{': return Control< object >::template match< A, M, Action, Control >( in, st... ); - case '[': return Control< array >::template match< A, M, Action, Control >( in, st... ); - case 'n': return Control< null >::template match< A, M, Action, Control >( in, st... ); - case 't': return Control< true_ >::template match< A, M, Action, Control >( in, st... ); - case 'f': return Control< false_ >::template match< A, M, Action, Control >( in, st... ); - - case '-': - in.bump_in_this_line(); - if( in.empty() || !match_number< true, A, rewind_mode::dontcare, Action, Control >( in, st... ) ) { - throw pegtl::parse_error( "incomplete number", in ); - } - return true; - - default: - return match_number< false, A, M, Action, Control >( in, st... ); - } - } - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - if( in.size( 2 ) && match_impl< A, M, Action, Control >( in, st... ) ) { - in.discard(); - return true; - } - return false; - } - }; - - struct value : padr< sor_value > {}; - struct array_element : value {}; - - struct text : seq< star< ws >, value > {}; - - } // namespace rules - - struct grammar : pegtl::must< rules::text, pegtl::eof > {}; - struct embedded : pegtl::must< rules::sor_value > {}; - // clang-format on - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/internal/hexdump.hpp b/include/tao/json/internal/hexdump.hpp deleted file mode 100644 index 5e87e76c..00000000 --- a/include/tao/json/internal/hexdump.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_HEXDUMP_HPP -#define TAO_JSON_INTERNAL_HEXDUMP_HPP - -#include - -namespace tao::json::internal -{ - template< typename T > - void hexdump( std::ostream& os, const T& v ) - { - static const char h[] = "0123456789ABCDEF"; - for( const auto b : v ) { - os.put( h[ static_cast< unsigned char >( b ) >> 4 ] ); - os.put( h[ static_cast< unsigned char >( b ) & 0xF ] ); - } - } - - template< typename T > - [[nodiscard]] std::string hexdump( const T& v ) - { - std::ostringstream os; - internal::hexdump( os, v ); - return os.str(); - } - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/internal/identity.hpp b/include/tao/json/internal/identity.hpp deleted file mode 100644 index 2f470e75..00000000 --- a/include/tao/json/internal/identity.hpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_IDENTITY_HPP -#define TAO_JSON_INTERNAL_IDENTITY_HPP - -#include - -namespace tao::internal -{ - template< typename T > - struct identity - { - using type = T; - }; - - template< typename T > - using identity_t = typename identity< T >::type; - -} // namespace tao::internal - -#endif diff --git a/include/tao/json/internal/number_state.hpp b/include/tao/json/internal/number_state.hpp deleted file mode 100644 index 07dfc829..00000000 --- a/include/tao/json/internal/number_state.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_NUMBER_STATE_HPP -#define TAO_JSON_INTERNAL_NUMBER_STATE_HPP - -#include -#include -#include -#include - -#include "../external/double.hpp" - -namespace tao::json::internal -{ - static const std::size_t max_mantissa_digits = 772; - - template< bool NEG > - struct number_state - { - using exponent10_t = std::int32_t; - using msize_t = std::uint16_t; - - number_state() = default; - - number_state( const number_state& ) = delete; - number_state( number_state&& ) = delete; - - ~number_state() = default; - - void operator=( const number_state& ) = delete; - void operator=( number_state&& ) = delete; - - exponent10_t exponent10 = 0; - msize_t msize = 0; // Excluding sign. - bool isfp = false; - bool eneg = false; - bool drop = false; - char mantissa[ max_mantissa_digits + 1 ]; - - template< typename Consumer > - void success( Consumer& consumer ) - { - if( !isfp && msize <= 20 ) { - mantissa[ msize ] = 0; - char* p; - errno = 0; - const std::uint64_t ull = std::strtoull( mantissa, &p, 10 ); - if( ( errno != ERANGE ) && ( p == mantissa + msize ) ) { - if constexpr( NEG ) { - if( ull < 9223372036854775808ULL ) { - consumer.number( -static_cast< std::int64_t >( ull ) ); - return; - } - if( ull == 9223372036854775808ULL ) { - consumer.number( static_cast< std::int64_t >( -9223372036854775807LL - 1 ) ); - return; - } - } - else { - consumer.number( ull ); - return; - } - } - } - if( drop ) { - mantissa[ msize++ ] = '1'; - --exponent10; - } - const auto d = double_conversion::Strtod( double_conversion::Vector< const char >( mantissa, msize ), exponent10 ); - if( !std::isfinite( d ) ) { - throw std::runtime_error( "invalid double value" ); - } - consumer.number( NEG ? -d : d ); - } - }; - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/internal/number_traits.hpp b/include/tao/json/internal/number_traits.hpp deleted file mode 100644 index 4025386b..00000000 --- a/include/tao/json/internal/number_traits.hpp +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_NUMBER_TRAITS_HPP -#define TAO_JSON_INTERNAL_NUMBER_TRAITS_HPP - -#include -#include - -#include "../forward.hpp" -#include "../message_extension.hpp" -#include "../type.hpp" - -#include "format.hpp" - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4702 ) -#endif - -namespace tao::json::internal -{ - template< typename T > - struct number_trait - { - template< template< typename... > class Traits > - [[nodiscard]] static T as( const basic_value< Traits >& v ) - { - switch( v.type() ) { - case type::SIGNED: - return static_cast< T >( v.get_signed() ); - case type::UNSIGNED: - return static_cast< T >( v.get_unsigned() ); - case type::DOUBLE: - return static_cast< T >( v.get_double() ); - default: - throw std::logic_error( internal::format( "invalid json type '", v.type(), "' for conversion to number", json::message_extension( v ) ) ); - } - } - }; - - template< typename T > - struct signed_trait - : number_trait< T > - { - template< template< typename... > class, typename Parts > - [[nodiscard]] static T consume( Parts& parser ) - { - return static_cast< T >( parser.number_signed() ); - } - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, const T i ) - { - c.number( std::int64_t( i ) ); - } - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const T i ) noexcept - { - v.set_signed( i ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const T rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::SIGNED: - return p.get_signed() == rhs; - case type::UNSIGNED: - return ( rhs >= 0 ) && ( p.get_unsigned() == static_cast< std::uint64_t >( rhs ) ); - case type::DOUBLE: - return p.get_double() == rhs; - default: - return false; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const T rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::SIGNED: - return p.get_signed() < rhs; - case type::UNSIGNED: - return ( rhs >= 0 ) && ( p.get_unsigned() < static_cast< std::uint64_t >( rhs ) ); - case type::DOUBLE: - return p.get_double() < rhs; - default: - return p.type() < type::SIGNED; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const T rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::SIGNED: - return p.get_signed() > rhs; - case type::UNSIGNED: - return ( rhs < 0 ) || ( p.get_unsigned() > static_cast< std::uint64_t >( rhs ) ); - case type::DOUBLE: - return p.get_double() > rhs; - default: - return p.type() > type::SIGNED; - } - } - }; - - template< typename T > - struct unsigned_trait - : number_trait< T > - { - template< template< typename... > class, typename Parts > - [[nodiscard]] static T consume( Parts& parser ) - { - return static_cast< T >( parser.number_unsigned() ); - } - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, const T i ) - { - c.number( std::uint64_t( i ) ); - } - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const T i ) noexcept - { - v.set_unsigned( i ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const T rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::SIGNED: { - const auto v = p.get_signed(); - return ( v >= 0 ) && ( static_cast< std::uint64_t >( v ) == rhs ); - } - case type::UNSIGNED: - return p.get_unsigned() == rhs; - case type::DOUBLE: - return p.get_double() == rhs; - default: - return false; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const T rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::SIGNED: { - const auto v = p.get_signed(); - return ( v < 0 ) || ( static_cast< std::uint64_t >( v ) < rhs ); - } - case type::UNSIGNED: - return p.get_unsigned() < rhs; - case type::DOUBLE: - return p.get_double() < rhs; - default: - return p.type() < type::UNSIGNED; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const T rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::SIGNED: { - const auto v = p.get_signed(); - return ( v >= 0 ) && ( static_cast< std::uint64_t >( v ) > rhs ); - } - case type::UNSIGNED: - return p.get_unsigned() > rhs; - case type::DOUBLE: - return p.get_double() > rhs; - default: - return p.type() > type::UNSIGNED; - } - } - }; - - template< typename T > - struct float_trait - : number_trait< T > - { - template< template< typename... > class, typename Parts > - [[nodiscard]] static T consume( Parts& parser ) - { - return static_cast< T >( parser.number_double() ); - } - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, const T f ) - { - c.number( double( f ) ); - } - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const T f ) noexcept - { - v.set_double( f ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const T rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::SIGNED: - return p.get_signed() == rhs; - case type::UNSIGNED: - return p.get_unsigned() == rhs; - case type::DOUBLE: - return p.get_double() == rhs; // TODO: Is it ok for overall semantics that NaN != NaN? - default: - return false; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const T rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::SIGNED: - return p.get_signed() < rhs; - case type::UNSIGNED: - return p.get_unsigned() < rhs; - case type::DOUBLE: - return p.get_double() < rhs; - default: - return p.type() < type::DOUBLE; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const T rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::SIGNED: - return p.get_signed() > rhs; - case type::UNSIGNED: - return p.get_unsigned() > rhs; - case type::DOUBLE: - return p.get_double() > rhs; - default: - return p.type() > type::DOUBLE; - } - } - }; - -} // namespace tao::json::internal - -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - -#endif diff --git a/include/tao/json/internal/pair.hpp b/include/tao/json/internal/pair.hpp deleted file mode 100644 index 1f15f8e2..00000000 --- a/include/tao/json/internal/pair.hpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_PAIR_HPP -#define TAO_JSON_INTERNAL_PAIR_HPP - -#include -#include -#include - -#include "../forward.hpp" - -namespace tao::json::internal -{ - template< template< typename... > class Traits > - struct pair - { - mutable std::string key; - mutable basic_value< Traits > value; - - template< typename U > - pair( U&& v ) - : key( Traits< std::decay_t< U > >::template default_key< Traits >::as_string() ), - value( std::forward< U >( v ) ) - {} - - template< typename U > - pair( U&& k, basic_value< Traits >&& v ) - : key( std::forward< U >( k ) ), - value( std::move( v ) ) - {} - - template< typename U > - pair( U&& k, const basic_value< Traits >& v ) - : key( std::forward< U >( k ) ), - value( v ) - {} - }; - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/internal/parse_util.hpp b/include/tao/json/internal/parse_util.hpp deleted file mode 100644 index 26961fe8..00000000 --- a/include/tao/json/internal/parse_util.hpp +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_PARSE_UTIL_HPP -#define TAO_JSON_INTERNAL_PARSE_UTIL_HPP - -#include - -#include "../external/pegtl/parse_error.hpp" -#include "../utf8.hpp" - -#include "endian.hpp" -#include "format.hpp" - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4702 ) -#endif - -namespace tao::json::internal -{ - template< typename Input > - void throw_on_empty( Input& in ) - { - if( in.empty() ) { - throw pegtl::parse_error( format( "unexpected end of input" ), in ); - } - } - - template< typename Input > - void throw_on_empty( Input& in, const std::size_t required ) - { - const auto available = in.size( required ); - if( available < required ) { - throw pegtl::parse_error( format( "unexpected end of input -- required ", required, " available ", available ), in ); - } - } - - template< typename Input > - [[nodiscard]] std::uint8_t peek_uint8( Input& in ) - { - throw_on_empty( in ); - return in.peek_uint8(); - } - - template< typename Input > - [[nodiscard]] char peek_char( Input& in ) - { - throw_on_empty( in ); - return in.peek_char(); - } - - template< typename Input > - [[nodiscard]] char read_char_unsafe( Input& in ) - { - const auto r = in.peek_char(); - in.bump_in_this_line( 1 ); - return r; - } - - template< typename Input > - [[nodiscard]] char read_char( Input& in ) - { - throw_on_empty( in ); - return read_char_unsafe( in ); - } - - template< utf8_mode U, typename Result, typename Input > - [[nodiscard]] Result read_string( Input& in, const std::size_t size ) - { - using value_t = typename Result::value_type; - json::internal::throw_on_empty( in, size ); - const auto* pointer = reinterpret_cast< const value_t* >( in.current() ); - const Result result( pointer, size ); - json::internal::consume_utf8_throws< U >( in, size ); - return result; - } - - template< typename Result, typename Number = Result, typename Input > - [[nodiscard]] Result read_big_endian_number( Input& in, const std::size_t extra = 0 ) - { - throw_on_empty( in, extra + sizeof( Number ) ); - const auto result = static_cast< Result >( be_to_h< Number >( in.current() + extra ) ); - in.bump_in_this_line( extra + sizeof( Number ) ); - return result; - } - - template< typename Integer > - [[nodiscard]] Integer hex_char_to_integer( const char c ) noexcept - { - if( ( '0' <= c ) && ( c <= '9' ) ) { - return static_cast< Integer >( c - '0' ); - } - if( ( 'a' <= c ) && ( c <= 'f' ) ) { - return static_cast< Integer >( c - 'a' + 10 ); - } - if( ( 'A' <= c ) && ( c <= 'F' ) ) { - return static_cast< Integer >( c - 'A' + 10 ); - } - // LCOV_EXCL_START - assert( false ); - return 0; - // LCOV_EXCL_STOP - } - -} // namespace tao::json::internal - -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - -#endif diff --git a/include/tao/json/internal/sha256.hpp b/include/tao/json/internal/sha256.hpp deleted file mode 100644 index 03bcd467..00000000 --- a/include/tao/json/internal/sha256.hpp +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_SHA256_HPP -#define TAO_JSON_INTERNAL_SHA256_HPP - -// Implements RFC 6234, SHA-256 - -#include -#include -#include -#include - -// RFC 6234, 3.d; see also http://stackoverflow.com/a/4209604/2073257 -#define ROR( x, N ) ( ( ( x ) >> ( N ) ) | ( ( x ) << ( 32 - ( N ) ) ) ) - -// RFC 6234, 5.1 -#define CH( x, y, z ) ( ( ( x ) & ( y ) ) ^ ( ~( x ) & ( z ) ) ) -#define MAJ( x, y, z ) ( ( ( x ) & ( y ) ) ^ ( ( x ) & ( z ) ) ^ ( ( y ) & ( z ) ) ) -#define BSIG0( x ) ( ROR( x, 2 ) ^ ROR( x, 13 ) ^ ROR( x, 22 ) ) -#define BSIG1( x ) ( ROR( x, 6 ) ^ ROR( x, 11 ) ^ ROR( x, 25 ) ) -#define SSIG0( x ) ( ROR( x, 7 ) ^ ROR( x, 18 ) ^ ( ( x ) >> 3 ) ) -#define SSIG1( x ) ( ROR( x, 17 ) ^ ROR( x, 19 ) ^ ( ( x ) >> 10 ) ) - -namespace tao::json::internal -{ - // RFC 6234, 5.1 - // clang-format off - static std::uint32_t K[ 64 ] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 - }; - // clang-format on - - class sha256 - { - private: - unsigned char M[ 64 ]; - std::uint64_t size; - - std::uint32_t H[ 8 ]; - - // RFC 6234, 6.2 - void process() noexcept - { - std::uint32_t W[ 64 ]; - - // step 1 - for( std::size_t t = 0, i = 0; t != 16; ++t, i += 4 ) { - W[ t ] = ( M[ i ] << 24 ) | ( M[ i + 1 ] << 16 ) | ( M[ i + 2 ] << 8 ) | ( M[ i + 3 ] ); - } - for( std::size_t t = 16; t != 64; ++t ) { - W[ t ] = SSIG1( W[ t - 2 ] ) + W[ t - 7 ] + SSIG0( W[ t - 15 ] ) + W[ t - 16 ]; - } - - // step 2 - std::uint32_t a, b, c, d, e, f, g, h; - a = H[ 0 ]; - b = H[ 1 ]; - c = H[ 2 ]; - d = H[ 3 ]; - e = H[ 4 ]; - f = H[ 5 ]; - g = H[ 6 ]; - h = H[ 7 ]; - - // step 3 - for( std::size_t t = 0; t != 64; ++t ) { - const std::uint32_t T1 = h + BSIG1( e ) + CH( e, f, g ) + K[ t ] + W[ t ]; - const std::uint32_t T2 = BSIG0( a ) + MAJ( a, b, c ); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - } - - // step 4 - H[ 0 ] += a; - H[ 1 ] += b; - H[ 2 ] += c; - H[ 3 ] += d; - H[ 4 ] += e; - H[ 5 ] += f; - H[ 6 ] += g; - H[ 7 ] += h; - } - - public: - sha256() noexcept - { - reset(); - } - - sha256( const sha256& ) = delete; - sha256( sha256&& ) = delete; - - ~sha256() = default; - - void operator=( const sha256& ) = delete; - void operator=( sha256&& ) = delete; - - void reset() noexcept - { - size = 0; - - // RFC 6234, 6.1 - H[ 0 ] = 0x6a09e667; - H[ 1 ] = 0xbb67ae85; - H[ 2 ] = 0x3c6ef372; - H[ 3 ] = 0xa54ff53a; - H[ 4 ] = 0x510e527f; - H[ 5 ] = 0x9b05688c; - H[ 6 ] = 0x1f83d9ab; - H[ 7 ] = 0x5be0cd19; - } - - void feed( const unsigned char c ) noexcept - { - M[ size++ % 64 ] = c; - if( ( size % 64 ) == 0 ) { - process(); - } - } - - void feed( const void* p, std::size_t s ) noexcept - { - auto* q = static_cast< const unsigned char* >( p ); - while( s != 0 ) { - feed( *q++ ); - --s; - } - } - - void feed( const std::string_view v ) noexcept - { - feed( v.data(), v.size() ); - } - - // RFC 6234, 4.1 - void store_unsafe( unsigned char* buffer ) noexcept - { - std::size_t i = size % 64; - if( i < 56 ) { - M[ i++ ] = 0x80; -#if defined( __GNUC__ ) && ( __GNUC__ >= 9 ) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Waggressive-loop-optimizations" -#endif - while( i < 56 ) { - M[ i++ ] = 0x00; - } -#if defined( __GNUC__ ) && ( __GNUC__ >= 9 ) -#pragma GCC diagnostic pop -#endif - } - else { - M[ i++ ] = 0x80; - while( i < 64 ) { - M[ i++ ] = 0x00; - } - process(); - std::memset( M, 0, 56 ); - } - - size *= 8; - - M[ 63 ] = static_cast< unsigned char >( size ); - M[ 62 ] = static_cast< unsigned char >( size >> 8 ); - M[ 61 ] = static_cast< unsigned char >( size >> 16 ); - M[ 60 ] = static_cast< unsigned char >( size >> 24 ); - M[ 59 ] = static_cast< unsigned char >( size >> 32 ); - M[ 58 ] = static_cast< unsigned char >( size >> 40 ); - M[ 57 ] = static_cast< unsigned char >( size >> 48 ); - M[ 56 ] = static_cast< unsigned char >( size >> 56 ); - - process(); - - for( std::size_t j = 0; j < 4; ++j ) { - buffer[ j ] = ( H[ 0 ] >> ( 24 - j * 8 ) ) & 0xff; - buffer[ j + 4 ] = ( H[ 1 ] >> ( 24 - j * 8 ) ) & 0xff; - buffer[ j + 8 ] = ( H[ 2 ] >> ( 24 - j * 8 ) ) & 0xff; - buffer[ j + 12 ] = ( H[ 3 ] >> ( 24 - j * 8 ) ) & 0xff; - buffer[ j + 16 ] = ( H[ 4 ] >> ( 24 - j * 8 ) ) & 0xff; - buffer[ j + 20 ] = ( H[ 5 ] >> ( 24 - j * 8 ) ) & 0xff; - buffer[ j + 24 ] = ( H[ 6 ] >> ( 24 - j * 8 ) ) & 0xff; - buffer[ j + 28 ] = ( H[ 7 ] >> ( 24 - j * 8 ) ) & 0xff; - } - } - - [[nodiscard]] std::string get() - { - std::string result( 32, '\0' ); - store_unsafe( reinterpret_cast< unsigned char* >( result.data() ) ); - return result; - } - }; - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/internal/single.hpp b/include/tao/json/internal/single.hpp deleted file mode 100644 index f56818c6..00000000 --- a/include/tao/json/internal/single.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_SINGLE_HPP -#define TAO_JSON_INTERNAL_SINGLE_HPP - -#include - -#include "../forward.hpp" - -#include "pair.hpp" - -namespace tao::json::internal -{ - template< template< typename... > class Traits > - struct single - { - mutable basic_value< Traits > value; - - template< typename U > - single( U&& v ) - : value( std::forward< U >( v ) ) - {} - - single( std::initializer_list< pair< Traits > >&& l ) - : value( std::move( l ) ) - {} - - single( const std::initializer_list< pair< Traits > >& l ) - : value( l ) - {} - - single( std::initializer_list< pair< Traits > >& l ) - : value( l ) - {} - }; - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/internal/string_t.hpp b/include/tao/json/internal/string_t.hpp deleted file mode 100644 index ba6c931c..00000000 --- a/include/tao/json/internal/string_t.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_STRING_T_HPP -#define TAO_JSON_INTERNAL_STRING_T_HPP - -#include -#include - -#include "../external/pegtl/internal/pegtl_string.hpp" - -namespace tao::json::internal -{ - template< char... Cs > - struct string_t - : pegtl::string< Cs... > - { - static constexpr const char value[] = { Cs..., 0 }; - - [[nodiscard]] static constexpr std::string_view as_string_view() noexcept - { - return std::string_view( value, sizeof...( Cs ) ); - } - - [[nodiscard]] static std::string as_string() - { - return std::string( value, sizeof...( Cs ) ); - } - }; - -} // namespace tao::json::internal - -#define TAO_JSON_STRING_T( VaLue ) TAO_JSON_PEGTL_INTERNAL_STRING( tao::json::internal::string_t, VaLue ) - -#endif diff --git a/include/tao/json/internal/type_traits.hpp b/include/tao/json/internal/type_traits.hpp deleted file mode 100644 index d34c9caa..00000000 --- a/include/tao/json/internal/type_traits.hpp +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_TYPE_TRAITS_HPP -#define TAO_JSON_INTERNAL_TYPE_TRAITS_HPP - -#include -#include - -#include "../forward.hpp" - -namespace tao::json::internal -{ - template< typename... Ts > - struct type_list - { - static constexpr std::size_t size = sizeof...( Ts ); - }; - - template< typename... > - struct merge_type_lists_t; - - template< typename... Ts > - struct merge_type_lists_t< type_list< Ts... > > - { - using list = type_list< Ts... >; - }; - - template< typename... Vs, typename... Ws, typename... Rs > - struct merge_type_lists_t< type_list< Vs... >, type_list< Ws... >, Rs... > - : merge_type_lists_t< type_list< Vs..., Ws... >, Rs... > - {}; - - template< typename... Ts > - using merge_type_lists = typename merge_type_lists_t< Ts... >::list; - - struct type_info_less - { - [[nodiscard]] bool operator()( const std::type_info* l, const std::type_info* r ) const - { - return l->before( *r ); - } - }; - - template< typename... > - inline constexpr bool has_as_impl = false; - - template< typename Trait, typename... Args > - inline constexpr bool has_as_impl< decltype( (void)Trait::as( std::declval< Args >()... ), void() ), Trait, Args... > = true; - - template< typename Trait, typename Value, typename... With > - inline constexpr bool has_as = has_as_impl< void, Trait, const Value&, With&... >; - - template< typename, template< typename... > typename, typename, typename... > - inline constexpr bool has_as_type_impl = false; - - template< template< typename... > typename Traits, typename T, typename... Args > - inline constexpr bool has_as_type_impl< decltype( (void)Traits< T >::template as_type< Traits, T >( std::declval< Args >()... ), void() ), Traits, T, Args... > = true; - - template< template< typename... > typename Traits, typename T, typename Value, typename... With > - inline constexpr bool has_as_type = has_as_type_impl< void, Traits, T, const Value&, With&... >; - - template< typename... > - inline constexpr bool has_to_impl = false; - - template< typename Trait, typename... Args > - inline constexpr bool has_to_impl< decltype( Trait::to( std::declval< Args >()... ), void() ), Trait, Args... > = true; - - template< typename Trait, typename Value, typename... With > - inline constexpr bool has_to = has_to_impl< void, Trait, const Value&, With&... >; - - template< template< typename... > class, typename, typename, typename = void > - inline constexpr bool has_consume_one = false; - - template< template< typename... > class Traits, typename P, typename U > - inline constexpr bool has_consume_one< Traits, P, U, decltype( (void)Traits< U >::template consume< Traits >( std::declval< P& >() ), void() ) > = true; - - template< template< typename... > class, typename, typename, typename = void > - inline constexpr bool has_consume_two = false; - - template< template< typename... > class Traits, typename P, typename U > - inline constexpr bool has_consume_two< Traits, P, U, decltype( (void)Traits< U >::template consume< Traits >( std::declval< P& >(), std::declval< U& >() ), void() ) > = true; - - template< template< typename... > class Traits, typename T, typename = void > - inline constexpr bool has_is_nothing = false; - - template< template< typename... > class Traits, typename T > - inline constexpr bool has_is_nothing< Traits, T, decltype( (void)Traits< T >::template is_nothing< Traits >( std::declval< const T& >() ), void() ) > = true; - - template< template< typename... > class Traits, typename T > - [[nodiscard]] std::enable_if_t< has_is_nothing< Traits, T >, bool > is_nothing( const T& t ) noexcept( noexcept( Traits< T >::template is_nothing< Traits >( t ) ) ) - { - return Traits< T >::template is_nothing< Traits >( t ); - } - - template< template< typename... > class Traits, typename T > - [[nodiscard]] std::enable_if_t< !has_is_nothing< Traits, T >, bool > is_nothing( const T& /*unused*/ ) noexcept - { - return false; - } - - template< template< typename... > class Traits, typename T, typename = void > - inline constexpr bool has_enable_implicit_constructor = false; - - template< template< typename... > class Traits, typename T > - inline constexpr bool has_enable_implicit_constructor< Traits, T, decltype( Traits< T >::enable_implicit_constructor, void() ) > = true; - - template< template< typename... > class Traits, typename T > - inline constexpr bool enable_implicit_constructor = Traits< std::conditional_t< has_enable_implicit_constructor< Traits, T >, T, void > >::enable_implicit_constructor; - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/internal/unescape_action.hpp b/include/tao/json/internal/unescape_action.hpp deleted file mode 100644 index b74fc30b..00000000 --- a/include/tao/json/internal/unescape_action.hpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_UNESCAPE_ACTION_HPP -#define TAO_JSON_INTERNAL_UNESCAPE_ACTION_HPP - -#include "../external/pegtl/contrib/unescape.hpp" -#include "../external/pegtl/nothing.hpp" - -#include "grammar.hpp" - -namespace tao::json::internal -{ - // clang-format off - template< typename Rule > struct unescape_action : pegtl::nothing< Rule > {}; - - template<> struct unescape_action< rules::escaped_unicode > : pegtl::unescape::unescape_j {}; - template<> struct unescape_action< rules::escaped_char > : pegtl::unescape::unescape_c< rules::escaped_char, '"', '\\', '/', '\b', '\f', '\n', '\r', '\t' > {}; - template<> struct unescape_action< rules::unescaped > : pegtl::unescape::append_all {}; - // clang-format on - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/internal/uri_fragment.hpp b/include/tao/json/internal/uri_fragment.hpp deleted file mode 100644 index acedcbba..00000000 --- a/include/tao/json/internal/uri_fragment.hpp +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_INTERNAL_URI_FRAGMENT_HPP -#define TAO_JSON_INTERNAL_URI_FRAGMENT_HPP - -#include -#include - -#include "../pointer.hpp" - -namespace tao::json::internal -{ - // clang-format off - const bool allowed_uri_fragment_characters[] = { - false, false, false, false, false, false, false, false, // 0 - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, // 16 - false, false, false, false, false, false, false, false, - false, true, false, false, true, false, true, true, // 32 - true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, // 48 - true, true, true, true, false, true, false, true, - true, true, true, true, true, true, true, true, // 64 - true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, // 80 - true, true, true, false, false, false, false, true, - false, true, true, true, true, true, true, true, // 96 - true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, // 112 - true, true, true, false, false, false, true, false, - false, false, false, false, false, false, false, false, // 128 - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false - }; - // clang-format on - - [[nodiscard]] inline char xdigit_value( const char c ) - { - // clang-format off - switch ( c ) { - case '0': return 0; - case '1': return 1; - case '2': return 2; - case '3': return 3; - case '4': return 4; - case '5': return 5; - case '6': return 6; - case '7': return 7; - case '8': return 8; - case '9': return 9; - case 'a': case 'A': return 10; - case 'b': case 'B': return 11; - case 'c': case 'C': return 12; - case 'd': case 'D': return 13; - case 'e': case 'E': return 14; - case 'f': case 'F': return 15; - default: - throw std::invalid_argument( "invalid URI Fragment escape sequence, '%' must be followed by two hexadecimal digits" ); - } - // clang-format on - } - - [[nodiscard]] inline pointer uri_fragment_to_pointer( const std::string_view v ) - { - pointer result; - if( v.empty() || v[ 0 ] != '#' ) { - throw std::invalid_argument( "invalid URI Fragment value, must begin with '#'" ); - } - if( v.size() > 1 ) { - const char* p = v.data() + 1; - const char* const e = v.data() + v.size(); - if( *p++ != '/' ) { - throw std::invalid_argument( "invalid JSON Pointer value, must be empty or begin with '/'" ); - } - std::string token; - while( p != e ) { - const char c = *p++; - switch( c ) { - // clang-format off - case '!': case '$': case '&': case '\'': case '(': case ')': case '*': case '+': case ',': case '-': case '.': - case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - case ':': case ';': case '=': case '?': case '@': - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': - case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': - case '_': - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': - case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': - // clang-format on - token += c; - continue; - - case '%': - if( p != e ) { - const char h1 = xdigit_value( *p++ ); - if( p != e ) { - const char h2 = xdigit_value( *p++ ); - token += static_cast< char >( h1 * 16 + h2 ); - continue; - } - } - throw std::invalid_argument( "invalid URI Fragment escape sequence, '%' must be followed by two hexadecimal digits" ); - - case '~': - if( p != e ) { - switch( *p++ ) { - case '0': - token += '~'; - continue; - case '1': - token += '/'; - continue; - } - } - throw std::invalid_argument( "invalid JSON Pointer escape sequence, '~' must be followed by '0' or '1'" ); - - case '/': - result += std::move( token ); - token.clear(); - continue; - - default: - throw std::invalid_argument( "invalid URI Fragment character" ); - } - } - result += std::move( token ); - } - return result; - } - - [[nodiscard]] inline std::string tokens_to_uri_fragment( std::vector< token >::const_iterator it, const std::vector< token >::const_iterator& end ) - { - static const char* hex = "0123456789ABCDEF"; - - std::string result = "#"; - while( it != end ) { - result += '/'; - for( const unsigned char c : it->key() ) { - switch( c ) { - case '~': - result += "~0"; - break; - case '/': - result += "~1"; - break; - default: - if( allowed_uri_fragment_characters[ c ] ) { - result += c; - } - else { - result += '%'; - result += hex[ c >> 4 ]; - result += hex[ c & 15 ]; - } - } - } - ++it; - } - return result; - } - - [[nodiscard]] inline std::string to_uri_fragment( const pointer& p ) - { - return tokens_to_uri_fragment( p.begin(), p.end() ); - } - -} // namespace tao::json::internal - -#endif diff --git a/include/tao/json/jaxn.hpp b/include/tao/json/jaxn.hpp deleted file mode 100644 index 10f40034..00000000 --- a/include/tao/json/jaxn.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_HPP -#define TAO_JSON_JAXN_HPP - -#include "../json.hpp" - -#include "jaxn/consume_file.hpp" -#include "jaxn/consume_string.hpp" -#include "jaxn/from_file.hpp" -#include "jaxn/from_input.hpp" -#include "jaxn/from_stream.hpp" -#include "jaxn/from_string.hpp" -#include "jaxn/parts_parser.hpp" -#include "jaxn/to_stream.hpp" -#include "jaxn/to_string.hpp" - -#endif diff --git a/include/tao/json/jaxn/consume_file.hpp b/include/tao/json/jaxn/consume_file.hpp deleted file mode 100644 index 1bf9a5bd..00000000 --- a/include/tao/json/jaxn/consume_file.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_CONSUME_FILE_HPP -#define TAO_JSON_JAXN_CONSUME_FILE_HPP - -#include - -#include "../external/pegtl/file_input.hpp" - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "parts_parser.hpp" - -namespace tao::json::jaxn -{ - template< typename T, template< typename... > class Traits = traits, typename F > - [[nodiscard]] T consume_file( F&& filename ) - { - jaxn::basic_parts_parser< pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); - return json::consume< T, Traits >( pp ); - } - - template< template< typename... > class Traits = traits, typename F, typename T > - void consume_file( F&& filename, T& t ) - { - jaxn::basic_parts_parser< pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); - json::consume< Traits >( pp, t ); - } - -} // namespace tao::json::jaxn - -#endif diff --git a/include/tao/json/jaxn/consume_string.hpp b/include/tao/json/jaxn/consume_string.hpp deleted file mode 100644 index 3051d0ec..00000000 --- a/include/tao/json/jaxn/consume_string.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_CONSUME_STRING_HPP -#define TAO_JSON_JAXN_CONSUME_STRING_HPP - -#include "../external/pegtl/string_input.hpp" - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "parts_parser.hpp" - -namespace tao::json::jaxn -{ - template< typename T, template< typename... > class Traits = traits, typename F > - [[nodiscard]] T consume_string( F&& string ) - { - jaxn::basic_parts_parser< pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); - return json::consume< T, Traits >( pp ); - } - - template< template< typename... > class Traits = traits, typename F, typename T > - void consume_string( F&& string, T& t ) - { - jaxn::basic_parts_parser< pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); - json::consume< Traits >( pp, t ); - } - -} // namespace tao::json::jaxn - -#endif diff --git a/include/tao/json/jaxn/events/from_file.hpp b/include/tao/json/jaxn/events/from_file.hpp deleted file mode 100644 index f645b594..00000000 --- a/include/tao/json/jaxn/events/from_file.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_EVENTS_FROM_FILE_HPP -#define TAO_JSON_JAXN_EVENTS_FROM_FILE_HPP - -#include - -#include "../internal/action.hpp" -#include "../internal/errors.hpp" -#include "../internal/grammar.hpp" - -#include "../../external/pegtl/file_input.hpp" - -namespace tao::json::jaxn::events -{ - // Events producer to parse a file containing a JAXN string representation. - - template< typename T, typename Consumer > - void from_file( Consumer& consumer, T&& filename ) - { - pegtl::file_input< pegtl::tracking_mode::lazy > in( std::forward< T >( filename ) ); - pegtl::parse< internal::grammar, internal::action, internal::errors >( in, consumer ); - } - -} // namespace tao::json::jaxn::events - -#endif diff --git a/include/tao/json/jaxn/events/from_input.hpp b/include/tao/json/jaxn/events/from_input.hpp deleted file mode 100644 index bb27cedc..00000000 --- a/include/tao/json/jaxn/events/from_input.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_EVENTS_FROM_INPUT_HPP -#define TAO_JSON_JAXN_EVENTS_FROM_INPUT_HPP - -#include - -#include "../../external/pegtl/parse.hpp" - -#include "../internal/action.hpp" -#include "../internal/errors.hpp" -#include "../internal/grammar.hpp" - -namespace tao::json::jaxn::events -{ - // Events producers that parse a JAXN string representation from a PEGTL input (or something compatible). - - template< typename Consumer, typename Input > - void from_input( Consumer& consumer, Input&& in ) - { - pegtl::parse< internal::grammar, internal::action, internal::errors >( std::forward< Input >( in ), consumer ); - } - - template< typename Consumer, typename Input > - void from_input_embedded( Consumer& consumer, Input&& in ) - { - pegtl::parse< internal::embedded, internal::action, internal::errors >( std::forward< Input >( in ), consumer ); - } - - template< typename Consumer, typename Outer, typename Input > - void from_input_nested( Consumer& consumer, const Outer& oi, Input&& in ) - { - pegtl::parse_nested< internal::grammar, internal::action, internal::errors >( oi, std::forward< Input >( in ), consumer ); - } - - template< typename Consumer, typename Outer, typename Input > - void from_input_embedded_nested( Consumer& consumer, const Outer& oi, Input&& in ) - { - pegtl::parse_nested< internal::embedded, internal::action, internal::errors >( oi, std::forward< Input >( in ), consumer ); - } - -} // namespace tao::json::jaxn::events - -#endif diff --git a/include/tao/json/jaxn/events/from_stream.hpp b/include/tao/json/jaxn/events/from_stream.hpp deleted file mode 100644 index 2c5984dd..00000000 --- a/include/tao/json/jaxn/events/from_stream.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_EVENTS_FROM_STREAM_HPP -#define TAO_JSON_JAXN_EVENTS_FROM_STREAM_HPP - -#include - -#include "../../external/pegtl/internal/istream_reader.hpp" -#include "../../external/pegtl/parse.hpp" - -#include "../internal/action.hpp" -#include "../internal/errors.hpp" -#include "../internal/grammar.hpp" - -namespace tao::json::jaxn::events -{ - template< typename Consumer > - void from_stream( Consumer& consumer, std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) - { - pegtl::istream_input in( stream, maximum_buffer_size, source ? source : "tao::json::events::jaxn::from_stream" ); - pegtl::parse< internal::grammar, internal::action, internal::errors >( in, consumer ); - } - - template< typename Consumer > - void from_stream( Consumer& consumer, std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) - { - from_stream( consumer, stream, source.c_str(), maximum_buffer_size ); - } - -} // namespace tao::json::jaxn::events - -#endif diff --git a/include/tao/json/jaxn/events/from_string.hpp b/include/tao/json/jaxn/events/from_string.hpp deleted file mode 100644 index ee20ca75..00000000 --- a/include/tao/json/jaxn/events/from_string.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_EVENTS_FROM_STRING_HPP -#define TAO_JSON_JAXN_EVENTS_FROM_STRING_HPP - -#include -#include - -#include "../../external/pegtl/memory_input.hpp" - -#include "from_input.hpp" - -namespace tao::json::jaxn::events -{ - // Events producer to parse a JAXN string representation. - - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) - { - pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::jaxn::events::from_string", byte, line, column ); - jaxn::events::from_input( consumer, std::move( in ) ); - } - - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) - { - jaxn::events::from_string( consumer, data, size, source.c_str(), byte, line, column ); - } - - template< typename Consumer, typename... Ts > - void from_string( Consumer& consumer, const std::string_view data, Ts&&... ts ) - { - jaxn::events::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); - } - -} // namespace tao::json::jaxn::events - -#endif diff --git a/include/tao/json/jaxn/events/to_pretty_stream.hpp b/include/tao/json/jaxn/events/to_pretty_stream.hpp deleted file mode 100644 index cff8895d..00000000 --- a/include/tao/json/jaxn/events/to_pretty_stream.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_EVENTS_TO_PRETTY_STREAM_HPP -#define TAO_JSON_JAXN_EVENTS_TO_PRETTY_STREAM_HPP - -#include "../../internal/hexdump.hpp" - -#include "../../external/ryu.hpp" - -#include "../../events/to_pretty_stream.hpp" - -#include "../is_identifier.hpp" - -namespace tao::json::jaxn::events -{ - // Events consumer to build a JAXN string representation. - - struct to_pretty_stream - : json::events::to_pretty_stream - { - using json::events::to_pretty_stream::to_pretty_stream; - - using json::events::to_pretty_stream::number; - - void number( const double v ) - { - next(); - if( !std::isfinite( v ) ) { - if( std::isnan( v ) ) { - os.write( "NaN", 3 ); - } - else if( v < 0 ) { - os.write( "-Infinity", 9 ); - } - else { - os.write( "Infinity", 8 ); - } - } - else { - ryu::d2s_stream( os, v ); - } - } - - void binary( const tao::binary_view v ) - { - next(); - os.put( '$' ); - json::internal::hexdump( os, v ); - } - - void key( const std::string_view v ) - { - if( jaxn::is_identifier( v ) ) { - next(); - os.write( v.data(), v.size() ); - } - else { - string( v ); - } - os.write( ": ", 2 ); - first = true; - after_key = true; - } - }; - -} // namespace tao::json::jaxn::events - -#endif diff --git a/include/tao/json/jaxn/events/to_stream.hpp b/include/tao/json/jaxn/events/to_stream.hpp deleted file mode 100644 index 0fd96ff7..00000000 --- a/include/tao/json/jaxn/events/to_stream.hpp +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_EVENTS_TO_STREAM_HPP -#define TAO_JSON_JAXN_EVENTS_TO_STREAM_HPP - -#include "../../events/to_stream.hpp" - -#include "../../external/ryu.hpp" - -#include "../../internal/hexdump.hpp" - -#include "../is_identifier.hpp" - -namespace tao::json::jaxn::events -{ - // Events consumer to build a JAXN string representation. - - struct to_stream - : json::events::to_stream - { - using json::events::to_stream::number; - using json::events::to_stream::to_stream; - - void number( const double v ) - { - next(); - if( !std::isfinite( v ) ) { - if( std::isnan( v ) ) { - os << "NaN"; - } - else if( v < 0 ) { - os << "-Infinity"; - } - else { - os << "Infinity"; - } - } - else { - ryu::d2s_stream( os, v ); - } - } - - void key( const std::string_view v ) - { - if( jaxn::is_identifier( v ) ) { - next(); - os.write( v.data(), v.size() ); - } - else { - string( v ); - } - os.put( ':' ); - first = true; - } - - void binary( const tao::binary_view v ) - { - next(); - os.put( '$' ); - json::internal::hexdump( os, v ); - } - }; - -} // namespace tao::json::jaxn::events - -#endif diff --git a/include/tao/json/jaxn/events/to_string.hpp b/include/tao/json/jaxn/events/to_string.hpp deleted file mode 100644 index 124c57da..00000000 --- a/include/tao/json/jaxn/events/to_string.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_EVENTS_TO_STRING_HPP -#define TAO_JSON_JAXN_EVENTS_TO_STRING_HPP - -#include -#include - -#include "to_stream.hpp" - -namespace tao::json::jaxn::events -{ - // Events consumer to build a JAXN string representation. - - struct to_string - : to_stream - { - std::ostringstream oss; - - to_string() - : to_stream( oss ) - {} - - [[nodiscard]] std::string value() const - { - return oss.str(); - } - }; - -} // namespace tao::json::jaxn::events - -#endif diff --git a/include/tao/json/jaxn/from_file.hpp b/include/tao/json/jaxn/from_file.hpp deleted file mode 100644 index 1406244a..00000000 --- a/include/tao/json/jaxn/from_file.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_FROM_FILE_HPP -#define TAO_JSON_JAXN_FROM_FILE_HPP - -#include -#include - -#include "../events/to_value.hpp" -#include "../events/transformer.hpp" - -#include "events/from_file.hpp" - -namespace tao::json::jaxn -{ - template< template< typename... > class Traits, template< typename... > class... Transformers > - [[nodiscard]] basic_value< Traits > basic_from_file( const std::string& filename ) - { - json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; - events::from_file( consumer, filename ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers > - [[nodiscard]] value from_file( const std::string& filename ) - { - return basic_from_file< traits, Transformers... >( filename ); - } - -} // namespace tao::json::jaxn - -#endif diff --git a/include/tao/json/jaxn/from_input.hpp b/include/tao/json/jaxn/from_input.hpp deleted file mode 100644 index f17f2143..00000000 --- a/include/tao/json/jaxn/from_input.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_FROM_INPUT_HPP -#define TAO_JSON_JAXN_FROM_INPUT_HPP - -#include -#include - -#include "../events/to_value.hpp" -#include "../events/transformer.hpp" - -#include "events/from_input.hpp" - -namespace tao::json::jaxn -{ - template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] basic_value< Traits > basic_from_input( Ts&&... ts ) - { - json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; - jaxn::events::from_input( consumer, std::forward< Ts >( ts )... ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] value from_input( Ts&&... ts ) - { - return basic_from_input< traits, Transformers... >( std::forward< Ts >( ts )... ); - } - -} // namespace tao::json::jaxn - -#endif diff --git a/include/tao/json/jaxn/from_stream.hpp b/include/tao/json/jaxn/from_stream.hpp deleted file mode 100644 index 615b657b..00000000 --- a/include/tao/json/jaxn/from_stream.hpp +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_FROM_STREAM_HPP -#define TAO_JSON_JAXN_FROM_STREAM_HPP - -#include -#include -#include - -#include "../value.hpp" - -#include "../events/to_value.hpp" -#include "../events/transformer.hpp" - -#include "events/from_stream.hpp" - -namespace tao::json::jaxn -{ - template< template< typename... > class Traits, template< typename... > class... Transformers > - [[nodiscard]] basic_value< Traits > basic_from_stream( std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) - { - json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; - events::from_stream( consumer, stream, source, maximum_buffer_size ); - return std::move( consumer.value ); - } - - template< template< typename... > class Traits, template< typename... > class... Transformers > - [[nodiscard]] basic_value< Traits > basic_from_stream( std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) - { - return basic_from_stream< Traits, Transformers... >( stream, source.c_str(), maximum_buffer_size ); - } - - template< template< typename... > class... Transformers > - [[nodiscard]] value from_stream( std::istream& stream, const char* source = nullptr, const std::size_t maximum_buffer_size = 4000 ) - { - return basic_from_stream< traits, Transformers... >( stream, source, maximum_buffer_size ); - } - - template< template< typename... > class... Transformers > - [[nodiscard]] value from_stream( std::istream& stream, const std::string& source, const std::size_t maximum_buffer_size = 4000 ) - { - return basic_from_stream< traits, Transformers... >( stream, source.c_str(), maximum_buffer_size ); - } - -} // namespace tao::json::jaxn - -#endif diff --git a/include/tao/json/jaxn/from_string.hpp b/include/tao/json/jaxn/from_string.hpp deleted file mode 100644 index cfc08a81..00000000 --- a/include/tao/json/jaxn/from_string.hpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_FROM_STRING_HPP -#define TAO_JSON_JAXN_FROM_STRING_HPP - -#include -#include - -#include "../events/to_value.hpp" -#include "../events/transformer.hpp" - -#include "events/from_string.hpp" - -namespace tao::json::jaxn -{ - template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] basic_value< Traits > basic_from_string( Ts&&... ts ) - { - json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; - events::from_string( consumer, std::forward< Ts >( ts )... ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] value from_string( Ts&&... ts ) - { - return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); - } - - inline namespace literals - { - [[nodiscard]] inline value operator"" _jaxn( const char* data, const std::size_t size ) - { - return jaxn::from_string( data, size, "literal" ); - } - - } // namespace literals - -} // namespace tao::json::jaxn - -#endif diff --git a/include/tao/json/jaxn/internal/action.hpp b/include/tao/json/jaxn/internal/action.hpp deleted file mode 100644 index f4f9fea1..00000000 --- a/include/tao/json/jaxn/internal/action.hpp +++ /dev/null @@ -1,355 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_INTERNAL_ACTION_HPP -#define TAO_JSON_JAXN_INTERNAL_ACTION_HPP - -#include -#include -#include -#include - -#include "../../external/pegtl/nothing.hpp" - -#include "../../internal/number_state.hpp" -#include "../../internal/parse_util.hpp" - -#include "bunescape_action.hpp" -#include "grammar.hpp" -#include "unescape_action.hpp" - -namespace tao::json::jaxn::internal -{ - template< typename Rule > - struct action - : pegtl::nothing< Rule > - {}; - - template<> - struct action< rules::null > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.null(); - } - }; - - template<> - struct action< rules::true_ > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.boolean( true ); - } - }; - - template<> - struct action< rules::false_ > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.boolean( false ); - } - }; - - template<> - struct action< rules::identifier > - { - template< typename Input, typename Consumer > - static void apply( const Input& in, Consumer& consumer ) - { - consumer.key( std::string_view( in.begin(), in.size() ) ); - } - }; - - template< bool NEG > - struct action< rules::hexnum< NEG > > - { - template< typename Input, typename Consumer > - static void apply( const Input& in, Consumer& consumer ) - { - std::uint64_t value = 0; - for( char c : in ) { - if( value & 0xF000000000000000 ) { - throw pegtl::parse_error( "JAXN hexadecimal number too large", in ); - } - value <<= 4; - value += json::internal::hex_char_to_integer< std::uint8_t >( c ); - } - if constexpr( NEG ) { - if( value < 9223372036854775808ULL ) { - consumer.number( -static_cast< std::int64_t >( value ) ); - } - else if( value == 9223372036854775808ULL ) { - consumer.number( static_cast< std::int64_t >( -9223372036854775807LL - 1 ) ); - } - else { - throw pegtl::parse_error( "JAXN hexadecimal number too large to negate", in ); - } - } - else { - consumer.number( value ); - } - } - }; - - template<> - struct action< rules::array::begin > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.begin_array(); - } - }; - - template<> - struct action< rules::array::element > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.element(); - } - }; - - template<> - struct action< rules::array::end > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.end_array(); - } - }; - - template<> - struct action< rules::object::begin > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.begin_object(); - } - }; - - template<> - struct action< rules::object::element > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.member(); - } - }; - - template<> - struct action< rules::object::end > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.end_object(); - } - }; - - template<> - struct action< rules::zero< false > > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.number( std::uint64_t( 0 ) ); - } - }; - - template<> - struct action< rules::zero< true > > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.number( std::int64_t( 0 ) ); - } - }; - - template<> - struct action< rules::nan > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.number( NAN ); - } - }; - - template<> - struct action< rules::infinity< false > > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.number( INFINITY ); - } - }; - - template<> - struct action< rules::infinity< true > > - { - template< typename Consumer > - static void apply0( Consumer& consumer ) - { - consumer.number( -INFINITY ); - } - }; - - template<> - struct action< rules::esign > - { - template< typename Input, bool NEG > - static void apply( const Input& in, json::internal::number_state< NEG >& result ) - { - result.eneg = ( in.peek_char() == '-' ); - } - }; - - template<> - struct action< rules::idigits > - { - template< typename Input, bool NEG > - static void apply( const Input& in, json::internal::number_state< NEG >& result ) - { - const auto s = in.size(); - - if( s == 1 && in.peek_char() == '0' ) { - return; - } - - if( s > ( 1 << 20 ) ) { - throw pegtl::parse_error( "JSON number with 1 megabyte digits", in ); - } - - const auto c = ( std::min )( s, json::internal::max_mantissa_digits ); - std::memcpy( result.mantissa, in.begin(), c ); - result.exponent10 += static_cast< typename json::internal::number_state< NEG >::exponent10_t >( s - c ); - result.msize = static_cast< typename json::internal::number_state< NEG >::msize_t >( c ); - - for( std::size_t i = c; i < s; ++i ) { - if( in.peek_char( i ) != '0' ) { - result.drop = true; - return; - } - } - } - }; - - template<> - struct action< rules::fdigits > - { - template< typename Input, bool NEG > - static void apply( const Input& in, json::internal::number_state< NEG >& result ) - { - result.isfp = true; - - const auto* b = in.begin(); - const auto* e = in.end(); - - while( ( e > b ) && ( e[ -1 ] == '0' ) ) { - --e; - } - if( !result.msize ) { - while( ( b < e ) && ( b[ 0 ] == '0' ) ) { - ++b; - --result.exponent10; - } - } - const auto c = ( std::min )( std::size_t( e - b ), json::internal::max_mantissa_digits - result.msize ); - std::memcpy( result.mantissa + result.msize, b, c ); - result.exponent10 -= static_cast< typename json::internal::number_state< NEG >::exponent10_t >( c ); - result.msize += static_cast< typename json::internal::number_state< NEG >::msize_t >( c ); - - for( const auto* r = b + c; r < e; ++r ) { - if( *r != '0' ) { - result.drop = true; - return; - } - } - } - }; - - template<> - struct action< rules::edigits > - { - template< typename Input, bool NEG > - static void apply( const Input& in, json::internal::number_state< NEG >& result ) - { - result.isfp = true; - - const char* b = in.begin(); - - while( ( b < in.end() ) && ( b[ 0 ] == '0' ) ) { - ++b; - } - if( ( in.end() - b ) > 9 ) { - throw pegtl::parse_error( "JSON exponent has more than 9 significant digits", in ); - } - int exponent10 = 0; - - while( b < in.end() ) { - exponent10 = ( exponent10 * 10 ) + ( b[ 0 ] - '0' ); - ++b; - } - result.exponent10 += ( result.eneg ? -exponent10 : exponent10 ); - } - }; - - template< bool NEG > - struct action< rules::number< NEG > > - : pegtl::change_states< tao::json::internal::number_state< NEG > > - { - template< typename Input, typename Consumer > - static void success( const Input& /*unused*/, tao::json::internal::number_state< NEG >& state, Consumer& consumer ) - { - state.success( consumer ); - } - }; - - template<> - struct action< rules::string > - : pegtl::change_action_and_states< unescape_action, std::string > - { - template< typename Input, typename Consumer > - static void success( const Input& /*unused*/, std::string& unescaped, Consumer& consumer ) - { - consumer.string( std::move( unescaped ) ); - } - }; - - template<> - struct action< rules::key > - : pegtl::change_action_and_states< unescape_action, std::string > - { - template< typename Input, typename Consumer > - static void success( const Input& /*unused*/, std::string& unescaped, Consumer& consumer ) - { - consumer.key( std::move( unescaped ) ); - } - }; - - template<> - struct action< rules::binary > - : pegtl::change_action_and_states< bunescape_action, std::vector< std::byte > > - { - template< typename Input, typename Consumer > - static void success( const Input& /*unused*/, std::vector< std::byte >& value, Consumer& consumer ) - { - consumer.binary( std::move( value ) ); - } - }; - -} // namespace tao::json::jaxn::internal - -#endif diff --git a/include/tao/json/jaxn/internal/bunescape_action.hpp b/include/tao/json/jaxn/internal/bunescape_action.hpp deleted file mode 100644 index 1cf981a5..00000000 --- a/include/tao/json/jaxn/internal/bunescape_action.hpp +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_INTERNAL_BUNESCAPE_ACTION_HPP -#define TAO_JSON_JAXN_INTERNAL_BUNESCAPE_ACTION_HPP - -#include -#include - -#include "../../external/pegtl/contrib/unescape.hpp" -#include "../../external/pegtl/nothing.hpp" - -#include "grammar.hpp" - -namespace tao::json::jaxn::internal -{ - template< typename Rule > - struct bunescape_action - : pegtl::nothing< Rule > - {}; - - template<> - struct bunescape_action< rules::bescaped_char > - { - template< typename Input > - static void apply( const Input& in, std::vector< std::byte >& value ) - { - switch( *in.begin() ) { - case '"': - value.push_back( std::byte( '"' ) ); - break; - - case '\'': - value.push_back( std::byte( '\'' ) ); - break; - - case '\\': - value.push_back( std::byte( '\\' ) ); - break; - - case '/': - value.push_back( std::byte( '/' ) ); - break; - - case 'b': - value.push_back( std::byte( '\b' ) ); - break; - - case 'f': - value.push_back( std::byte( '\f' ) ); - break; - - case 'n': - value.push_back( std::byte( '\n' ) ); - break; - - case 'r': - value.push_back( std::byte( '\r' ) ); - break; - - case 't': - value.push_back( std::byte( '\t' ) ); - break; - - case 'v': - value.push_back( std::byte( '\v' ) ); - break; - - case '0': - value.push_back( std::byte( '\0' ) ); - break; - - default: - throw pegtl::parse_error( "invalid character in unescape", in ); // LCOV_EXCL_LINE - } - } - }; - - template<> - struct bunescape_action< rules::bescaped_hexcode > - { - template< typename Input > - static void apply( const Input& in, std::vector< std::byte >& value ) - { - assert( !in.empty() ); // First character MUST be present, usually 'x'. - value.push_back( static_cast< std::byte >( pegtl::unescape::unhex_string< char >( in.begin() + 1, in.end() ) ) ); - } - }; - - template< char D > - struct bunescape_action< rules::bunescaped< D > > - { - template< typename Input > - static void apply( const Input& in, std::vector< std::byte >& value ) - { - const auto begin = reinterpret_cast< const std::byte* >( in.begin() ); - const auto end = begin + in.size(); - value.insert( value.end(), begin, end ); - } - }; - - template<> - struct bunescape_action< rules::bbyte > - { - template< typename Input > - static void apply( const Input& in, std::vector< std::byte >& value ) - { - value.push_back( static_cast< std::byte >( pegtl::unescape::unhex_string< char >( in.begin(), in.end() ) ) ); - } - }; - -} // namespace tao::json::jaxn::internal - -#endif diff --git a/include/tao/json/jaxn/internal/errors.hpp b/include/tao/json/jaxn/internal/errors.hpp deleted file mode 100644 index 607a143e..00000000 --- a/include/tao/json/jaxn/internal/errors.hpp +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_INTERNAL_ERRORS_HPP -#define TAO_JSON_JAXN_INTERNAL_ERRORS_HPP - -#include - -#include "../../external/pegtl/normal.hpp" -#include "../../external/pegtl/parse_error.hpp" - -#include "grammar.hpp" - -namespace tao::json::jaxn::internal -{ - template< typename Rule > - struct errors - : pegtl::normal< Rule > - { - static const std::string error_message; - - template< typename Input, typename... States > - static void raise( const Input& in, States&&... /*unused*/ ) - { - throw pegtl::parse_error( error_message, in ); - } - - template< template< typename... > class Action, typename Iterator, typename Input, typename... States > - static auto apply( const Iterator& begin, const Input& in, States&&... st ) - -> decltype( Action< Rule >::apply( std::declval< const typename Input::action_t& >(), st... ) ) - { - try { - using action_t = typename Input::action_t; - const action_t action_input( begin, in ); - return Action< Rule >::apply( action_input, st... ); - } - catch( const pegtl::parse_error& ) { - throw; - } - catch( const std::exception& e ) { - throw pegtl::parse_error( e.what(), in ); - } - } - - template< template< typename... > class Action, typename Input, typename... States > - static auto apply0( const Input& in, States&&... st ) - -> decltype( Action< Rule >::apply0( st... ) ) - { - try { - return Action< Rule >::apply0( st... ); - } - catch( const pegtl::parse_error& ) { - throw; - } - catch( const std::exception& e ) { - throw pegtl::parse_error( e.what(), in ); - } - } - }; - - // clang-format off - template<> inline const std::string errors< rules::text >::error_message = "no valid JAXN"; - - template<> inline const std::string errors< rules::comment >::error_message = "expected '*' or '/'"; - template<> inline const std::string errors< rules::line_comment_char >::error_message = "invalid character in line comment"; - template<> inline const std::string errors< rules::block_comment_char >::error_message = "invalid character in block comment"; - template<> inline const std::string errors< rules::end_block_comment >::error_message = "unterminated multi-line comment"; - - template<> inline const std::string errors< rules::end_array >::error_message = "incomplete array, expected value or ']'"; - template<> inline const std::string errors< rules::end_object >::error_message = "incomplete object, expected key or '}'"; - template<> inline const std::string errors< rules::name_separator >::error_message = "expected ':'"; - template<> inline const std::string errors< rules::value >::error_message = "expected value"; - template<> inline const std::string errors< rules::sor_value >::error_message = "expected value"; - - template<> inline const std::string errors< rules::edigits >::error_message = "expected at least one exponent digit"; - template<> inline const std::string errors< rules::fdigits >::error_message = "expected at least one fraction digit"; - template<> inline const std::string errors< rules::nan >::error_message = "invalid numeric literal"; - template<> inline const std::string errors< rules::infinity< false > >::error_message = "invalid numeric literal"; - template<> inline const std::string errors< rules::infinity< true > >::error_message = "invalid numeric literal"; - template<> inline const std::string errors< rules::hexnum< false > >::error_message = "expected at least one hexadecimal digit"; - template<> inline const std::string errors< rules::hexnum< true > >::error_message = "expected at least one hexadecimal digit"; - - template<> inline const std::string errors< rules::xdigit >::error_message = "incomplete universal character name"; - template<> inline const std::string errors< rules::escaped >::error_message = "unknown escape sequence in string"; - template<> inline const std::string errors< rules::chars< '"' > >::error_message = "invalid character in string"; - template<> inline const std::string errors< rules::chars< '\'' > >::error_message = "invalid character in string"; - template<> inline const std::string errors< rules::qstring_content< '"' > >::error_message = "unterminated string"; - template<> inline const std::string errors< rules::qstring_content< '\'' > >::error_message = "unterminated string"; - template<> inline const std::string errors< rules::mchars< '"' > >::error_message = "invalid character in multiline string"; - template<> inline const std::string errors< rules::mchars< '\'' > >::error_message = "invalid character in multiline string"; - template<> inline const std::string errors< rules::mqstring_content< '"' > >::error_message = "unterminated multiline string"; - template<> inline const std::string errors< rules::mqstring_content< '\'' > >::error_message = "unterminated multiline string"; - template<> inline const std::string errors< rules::string_fragment >::error_message = "expected string"; - - template<> inline const std::string errors< rules::bescaped >::error_message = "unknown escape sequence in binary string"; - template<> inline const std::string errors< rules::bchars< '"' > >::error_message = "invalid character in binary string"; - template<> inline const std::string errors< rules::bchars< '\'' > >::error_message = "invalid character in binary string"; - template<> inline const std::string errors< rules::bqstring_content< '"' > >::error_message = "unterminated binary string"; - template<> inline const std::string errors< rules::bqstring_content< '\'' > >::error_message = "unterminated binary string"; - template<> inline const std::string errors< rules::bvalue >::error_message = "expected binary"; - template<> inline const std::string errors< rules::bpart >::error_message = "expected a pair of hexadecimal digits"; - - template<> inline const std::string errors< pegtl::eof >::error_message = "unexpected character after JAXN value"; - // clang-format on - -} // namespace tao::json::jaxn::internal - -#endif diff --git a/include/tao/json/jaxn/internal/grammar.hpp b/include/tao/json/jaxn/internal/grammar.hpp deleted file mode 100644 index d0d55b70..00000000 --- a/include/tao/json/jaxn/internal/grammar.hpp +++ /dev/null @@ -1,375 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_INTERNAL_GRAMMAR_HPP -#define TAO_JSON_JAXN_INTERNAL_GRAMMAR_HPP - -#include - -#include "../../external/pegtl.hpp" -#include "../../external/pegtl/contrib/abnf.hpp" - -namespace tao::json::jaxn::internal -{ - // clang-format off - namespace rules - { - using namespace pegtl; - - struct line_comment_char : sor< one< '\t' >, utf8::ranges< 0x20, 0x7E, 0x80, 0x10FFFF > > {}; - struct line_comment : seq< one< '/' >, until< eolf, must< line_comment_char > > > {}; - - struct block_comment_char : sor< one< '\t' >, utf8::ranges< 0x20, 0x7E, 0x80, 0x10FFFF >, eol > {}; - struct end_block_comment : until< pegtl::string< '*', '/' >, must< block_comment_char > > {}; - struct block_comment : if_must< one< '*' >, end_block_comment > {}; - - struct comment : sor< line_comment, block_comment > {}; - - struct ws : sor< one< ' ', '\t', '\n', '\r' >, seq< one< '#' >, until< eolf > >, if_must< one< '/' >, comment > > {}; - - template< typename R, typename P = ws > - using padr = pegtl::internal::seq< R, pegtl::internal::star< P > >; - - struct begin_array : padr< one< '[' > > {}; - struct begin_object : padr< one< '{' > > {}; - struct end_array : one< ']' > {}; - struct end_object : one< '}' > {}; - struct name_separator : pad< one< ':' >, ws > {}; - struct value_separator : padr< one< ',' > > {}; - struct element_separator : padr< one< ',' > > {}; - struct value_concat : pad< one< '+' >, ws > {}; - - struct false_ : pegtl::string< 'f', 'a', 'l', 's', 'e' > {}; - struct null : pegtl::string< 'n', 'u', 'l', 'l' > {}; - struct true_ : pegtl::string< 't', 'r', 'u', 'e' > {}; - - struct nan : pegtl::string< 'N', 'a', 'N' > {}; - - template< bool NEG > - struct infinity : pegtl::string< 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y' > {}; - - template< bool NEG > - struct hexnum : plus< abnf::HEXDIG > {}; - - struct digits : plus< abnf::DIGIT > {}; - - struct esign : one< '-', '+' > {}; - - struct edigits : digits {}; - struct fdigits : digits {}; - struct idigits : digits {}; - - struct exp : seq< one< 'e', 'E' >, opt< esign >, must< edigits > > {}; - struct frac0 : seq< one< '.' >, opt< fdigits > > {}; - struct frac1 : if_must< one< '.' >, fdigits > {}; - - template< bool NEG > - struct number : seq< sor< seq< idigits, opt< frac0 > >, frac1 >, opt< exp > > {}; - - struct xdigit : abnf::HEXDIG {}; - struct escaped_unicode_code_point_content : seq< one< '{' >, plus< xdigit > > {}; - struct escaped_unicode_code_point : seq< one< 'u' >, escaped_unicode_code_point_content, one< '}' > > {}; - struct escaped_unicode : list< seq< one< 'u' >, rep< 4, xdigit > >, one< '\\' > > {}; - - struct escaped_char : one< '"', '\'', '\\', '/', 'b', 'f', 'n', 'r', 't', 'v', '0' > {}; - struct escaped : sor< escaped_char, escaped_unicode_code_point, escaped_unicode > {}; - - template< char D > - struct unescaped - { - using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) - { - bool result = false; - - while( const std::size_t s = in.size( 4 ) ) { - if( const auto t = pegtl::internal::peek_utf8::peek( in, s ) ) { - if( ( 0x20 <= t.data ) && ( t.data <= 0x10FFFF ) && ( t.data != '\\' ) && ( t.data != D ) && ( t.data != 0x7F ) ) { - in.bump_in_this_line( t.size ); - result = true; - continue; - } - } - return result; - } - throw pegtl::parse_error( "invalid character in string", in ); - } - }; - - template< char D > - struct chars : if_then_else< one< '\\' >, must< escaped >, unescaped< D > > {}; - - template< char D > - struct qstring_content : until< at< one< D > >, must< chars< D > > > {}; - - template< char D > - struct qstring : seq< one< D >, must< qstring_content< D > >, any > {}; - - template< char D > - struct mchars_non_eol - { - using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) - { - bool result = false; - - while( const std::size_t s = in.size( 4 ) ) { - if( const auto t = pegtl::internal::peek_utf8::peek( in, s ) ) { - if( ( ( 0x20 <= t.data ) && ( t.data <= 0x10FFFF ) && ( t.data != D ) && ( t.data != 0x7F ) ) || ( t.data == '\t' ) ) { - in.bump_in_this_line( t.size ); - result = true; - continue; - } - } - return result; - } - throw pegtl::parse_error( "invalid character in string", in ); - } - }; - - template< char D > - struct mchars : sor< mchars_non_eol< D >, one< D >, eol > {}; - - template< char D > - struct mqstring_content : until< at< three< D > >, must< mchars< D > > > {}; - - template< char D > - struct mqstring : seq< three< D >, opt< eol >, must< mqstring_content< D > >, any, any, any > {}; - - struct string_fragment : sor< mqstring< '"' >, mqstring< '\'' >, qstring< '"' >, qstring< '\'' > > {}; - - struct string : list_must< string_fragment, value_concat > {}; - - struct binary_prefix : one< '$' > {}; - - struct bescaped_hexcode : seq< one< 'x' >, rep< 2, must< xdigit > > > {}; - - struct bescaped_char : one< '"', '\'', '\\', '/', 'b', 'f', 'n', 'r', 't', 'v', '0' > {}; - struct bescaped : sor< bescaped_char, bescaped_hexcode > {}; - - template< char D > - struct bunescaped - { - using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; - - template< typename Input > - [[nodiscard]] static bool match( Input& in ) - { - bool result = false; - - while( !in.empty() ) { - const auto t = in.peek_char(); - if( ( 0x20 <= t ) && ( t <= 0x7E ) && ( t != '\\' ) && ( t != D ) ) { - in.bump_in_this_line( 1 ); - result = true; - continue; - } - return result; - } - throw pegtl::parse_error( "invalid character in binary string", in ); - } - }; - - template< char D > - struct bchars : if_then_else< one< '\\' >, must< bescaped >, bunescaped< D > > {}; - - template< char D > - struct bqstring_content : until< at< one< D > >, must< bchars< D > > > {}; - - template< char D > - struct bqstring : seq< one< D >, must< bqstring_content< D > >, any > {}; - - struct bstring : sor< bqstring< '"' >, bqstring< '\'' > > {}; - - struct bbyte : rep< 2, abnf::HEXDIG > {}; - - struct bpart : plus< bbyte > {}; - - struct bdirect : list_must< bpart, one< '.' > > {}; - - struct bvalue : seq< binary_prefix, opt< sor< bstring, bdirect > > > {}; - - struct binary : list_must< bvalue, value_concat > {}; - - struct value; - - struct array_element; - struct array_content : opt< list_tail< array_element, element_separator > > {}; - struct array : seq< begin_array, array_content, must< end_array > > - { - using begin = begin_array; - using end = end_array; - using element = array_element; - using content = array_content; - }; - - struct key : string {}; - - struct mkey : sor< key, identifier > {}; - struct member : if_must< mkey, name_separator, value > {}; - struct object_content : opt< list_tail< member, value_separator > > {}; - struct object : seq< begin_object, object_content, must< end_object > > - { - using begin = begin_object; - using end = end_object; - using element = member; - using content = object_content; - }; - - template< bool NEG > - struct zero : one< '0' > {}; - - struct sor_value - { - using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::sor, string, number< false >, object, array, false_, true_, null >; - - template< typename Rule, - apply_mode A, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match_must( Input& in, States&&... st ) - { - return Control< must< Rule > >::template match< A, rewind_mode::dontcare, Action, Control >( in, st... ); - } - - template< bool NEG, - apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match_zero( Input& in, States&&... st ) - { - if( in.size( 2 ) > 1 ) { - switch( in.peek_char( 1 ) ) { - case '.': - case 'e': - case 'E': - return Control< number< NEG > >::template match< A, M, Action, Control >( in, st... ); - - case 'x': - case 'X': - in.bump_in_this_line( 2 ); - return Control< must< hexnum< NEG > > >::template match< A, M, Action, Control >( in, st... ); - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - throw pegtl::parse_error( "invalid leading zero", in ); - } - } - return Control< zero< NEG > >::template match< A, M, Action, Control >( in, st... ); - } - - template< bool NEG, - apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match_number( Input& in, States&&... st ) - { - switch( in.peek_char() ) { - case 'N': - return Control< must< nan > >::template match< A, M, Action, Control >( in, st... ); - - case 'I': - return Control< must< infinity< NEG > > >::template match< A, M, Action, Control >( in, st... ); - - case '0': - if( !match_zero< NEG, A, rewind_mode::dontcare, Action, Control >( in, st... ) ) { - throw pegtl::parse_error( "incomplete number", in ); - } - return true; - - default: - return Control< number< NEG > >::template match< A, M, Action, Control >( in, st... ); - } - } - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match_impl( Input& in, States&&... st ) - { - switch( in.peek_char() ) { - case '{': return Control< object >::template match< A, M, Action, Control >( in, st... ); - case '[': return Control< array >::template match< A, M, Action, Control >( in, st... ); - case 'n': return Control< null >::template match< A, M, Action, Control >( in, st... ); - case 't': return Control< true_ >::template match< A, M, Action, Control >( in, st... ); - case 'f': return Control< false_ >::template match< A, M, Action, Control >( in, st... ); - - case '"': - case '\'': - return Control< string >::template match< A, M, Action, Control >( in, st... ); - - case '$': - return Control< binary >::template match< A, M, Action, Control >( in, st... ); - - case '+': - in.bump_in_this_line(); - if( in.empty() || !match_number< false, A, rewind_mode::dontcare, Action, Control >( in, st... ) ) { - throw pegtl::parse_error( "incomplete number", in ); - } - return true; - - case '-': - in.bump_in_this_line(); - if( in.empty() || !match_number< true, A, rewind_mode::dontcare, Action, Control >( in, st... ) ) { - throw pegtl::parse_error( "incomplete number", in ); - } - return true; - - default: - return match_number< false, A, M, Action, Control >( in, st... ); - } - } - - template< apply_mode A, - rewind_mode M, - template< typename... > class Action, - template< typename... > class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - if( in.size( 2 ) && match_impl< A, M, Action, Control >( in, st... ) ) { - in.discard(); - return true; - } - return false; - } - }; - - struct value : padr< sor_value > {}; - struct array_element : value {}; - - struct text : seq< star< ws >, value > {}; - - } // namespace rules - - struct grammar : pegtl::must< rules::text, pegtl::eof > {}; - struct embedded : pegtl::must< rules::sor_value > {}; - // clang-format on - -} // namespace tao::json::jaxn::internal - -#endif diff --git a/include/tao/json/jaxn/internal/integer.hpp b/include/tao/json/jaxn/internal/integer.hpp deleted file mode 100644 index b4b72dbc..00000000 --- a/include/tao/json/jaxn/internal/integer.hpp +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_INTERNAL_INTEGER_HPP -#define TAO_JSON_JAXN_INTERNAL_INTEGER_HPP - -#include -#include -#include - -#include -#include - -#include "../../external/pegtl.hpp" -#include "../../external/pegtl/contrib/integer.hpp" - -#include "../../internal/parse_util.hpp" - -namespace tao::json::jaxn::internal::integer -{ - struct unsigned_rule - : pegtl::if_then_else< pegtl::one< '0' >, pegtl::if_then_else< pegtl::one< 'x' >, pegtl::plus< pegtl::xdigit >, pegtl::not_at< pegtl::digit > >, pegtl::plus< pegtl::digit > > - { - // Unsigned hex or dec integer, no leading zeros for dec. - }; - - struct signed_rule - : pegtl::seq< pegtl::opt< pegtl::one< '-', '+' > >, unsigned_rule > - { - // Signed hex or dec integer, no leading zeros for dec. - }; - - [[nodiscard]] constexpr bool is_hex_digit( const char c ) noexcept - { - // We don't use std::isxdigit() because it might - // return true for other values on MS platforms? - - return ( ( '0' <= c ) && ( c <= '9' ) ) || ( ( 'a' <= c ) && ( c <= 'f' ) ) || ( ( 'A' <= c ) && ( c <= 'F' ) ); - } - - template< typename Integer, Integer Maximum = ( std::numeric_limits< Integer >::max )() > - [[nodiscard]] constexpr bool accumulate_hex_digit( Integer& result, const char xdigit ) noexcept - { - // Assumes that xdigit is an xdigit as per is_hex_digit(); returns false on overflow. - - static_assert( std::is_integral_v< Integer > ); - - constexpr Integer cutoff = Maximum / 16; - constexpr Integer cutlim = Maximum % 16; - - const Integer c = json::internal::hex_char_to_integer< Integer >( xdigit ); - - if( ( result > cutoff ) || ( ( result == cutoff ) && ( c > cutlim ) ) ) { - return false; - } - result *= 16; - result += c; - return true; - } - - template< typename Integer, Integer Maximum = ( std::numeric_limits< Integer >::max )() > - [[nodiscard]] constexpr bool accumulate_hex_digits( Integer& result, const std::string_view input ) noexcept - { - // Assumes input is a non-empty sequence of hex-digits; returns false on overflow. - - for( const auto c : input ) { - if( !accumulate_hex_digit< Integer, Maximum >( result, c ) ) { - return false; - } - } - return true; - } - - template< typename Integer, Integer Maximum = ( std::numeric_limits< Integer >::max )() > - [[nodiscard]] constexpr bool convert_hex_positive( Integer& result, const std::string_view input ) noexcept - { - // Assumes result == 0 and that input is a non-empty sequence of hex-digits; returns false on overflow. - - static_assert( std::is_integral_v< Integer > ); - return accumulate_hex_digits< Integer, Maximum >( result, input ); - } - - template< typename Signed > - [[nodiscard]] constexpr bool convert_hex_negative( Signed& result, const std::string_view input ) noexcept - { - // Assumes result == 0 and that input is a non-empty sequence of hex-digits; returns false on overflow. - - static_assert( std::is_signed_v< Signed > ); - using Unsigned = std::make_unsigned_t< Signed >; - constexpr Unsigned maximum = static_cast< Unsigned >( ( std::numeric_limits< Signed >::max )() ) + 1; - Unsigned temporary = 0; - if( accumulate_hex_digits< Unsigned, maximum >( temporary, input ) ) { - result = static_cast< Signed >( ~temporary ) + 1; - return true; - } - return false; - } - - template< typename Unsigned, Unsigned Maximum = ( std::numeric_limits< Unsigned >::max )() > - [[nodiscard]] constexpr bool convert_hex_unsigned( Unsigned& result, const std::string_view input ) noexcept - { - // Assumes result == 0 and that input is a non-empty sequence of hex-digits; returns false on overflow. - - static_assert( std::is_unsigned_v< Unsigned > ); - return accumulate_hex_digits< Unsigned, Maximum >( result, input ); - } - - template< typename Signed > - [[nodiscard]] constexpr bool convert_hex_signed( Signed& result, const std::string_view input ) noexcept - { - // Assumes result == 0 and that input is an optional sign followed by a "0x" and a non-empty sequence of hex-digits; returns false on overflow. - - static_assert( std::is_signed_v< Signed > ); - if( input[ 0 ] == '-' ) { - return convert_hex_negative< Signed >( result, std::string_view( input.data() + 3, input.size() - 3 ) ); - } - const auto offset = unsigned( input[ 0 ] == '+' ) + 2; // The "0x" prefix has length 2. - return convert_hex_positive< Signed >( result, std::string_view( input.data() + offset, input.size() - offset ) ); - } - - using unsigned_dec_action = pegtl::integer::unsigned_action; - - struct unsigned_hex_action - { - // Assumes that 'in' contains a non-empty sequence of ASCII hex-digits with "0x" prefix. - - template< typename Input > - static auto apply( const Input& in, std::uint64_t& st ) - { - auto sv = in.string_view(); - sv.remove_prefix( 2 ); - if( !convert_hex_unsigned( st, sv ) ) { - throw pegtl::parse_error( "unsigned hex integer overflow", in ); - } - } - }; - - template< typename Rule > - struct unsigned_action_action - : pegtl::nothing< Rule > - { - }; - - template<> - struct unsigned_action_action< pegtl::plus< pegtl::digit > > - : unsigned_dec_action - { - }; - - template<> - struct unsigned_action_action< pegtl::plus< pegtl::xdigit > > - { - template< typename Input, typename Unsigned > - static void apply( const Input& in, Unsigned& st ) - { - if( !convert_hex_unsigned( st, in.string_view() ) ) { - throw pegtl::parse_error( "unsigned hex integer overflow", in ); - } - } - }; - - struct unsigned_rule_with_action - { - using analyze_t = unsigned_rule::analyze_t; - - template< pegtl::apply_mode, - pegtl::rewind_mode, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input > - [[nodiscard]] static auto match( Input& in, std::uint64_t& st ) - { - return pegtl::parse< unsigned_rule, unsigned_action_action >( in, st ); // Throws on overflow. - } - }; - - using signed_dec_action = pegtl::integer::signed_action; - - struct signed_hex_action - { - // Assumes that 'in' contains a non-empty sequence of ASCII hex-digits, - // with optional leading sign before the "0x" prefix; when there is a - // sign, in.size() must be >= 4. - - template< typename Input > - static auto apply( const Input& in, std::int64_t& st ) - { - if( !convert_hex_signed( st, in.string_view() ) ) { - throw pegtl::parse_error( "signed hex integer overflow", in ); - } - } - }; - - template< typename Rule > - struct signed_action_action - : pegtl::nothing< Rule > - { - }; - - template<> - struct signed_action_action< pegtl::one< '-', '+' > > - { - template< typename Input, typename Signed > - static void apply( const Input& in, bool& negative, Signed& /*unused*/ ) - { - negative = ( in.peek_char() == '-' ); // TODO: Optimise with custom rule to prevent building marker and action_input for single char? - } - }; - - template<> - struct signed_action_action< pegtl::plus< pegtl::digit > > - { - template< typename Input, typename Signed > - static void apply( const Input& in, const bool negative, Signed& st ) - { - if( !( negative ? pegtl::integer::internal::convert_negative< Signed >( st, in.string_view() ) : pegtl::integer::internal::convert_positive< Signed >( st, in.string_view() ) ) ) { - throw pegtl::parse_error( "signed dec integer overflow", in ); - } - } - }; - - template<> - struct signed_action_action< pegtl::plus< pegtl::xdigit > > - { - template< typename Input, typename Signed > - static void apply( const Input& in, const bool negative, Signed& st ) - { - if( !( negative ? convert_hex_negative< Signed >( st, in.string_view() ) : convert_hex_positive< Signed >( st, in.string_view() ) ) ) { - throw pegtl::parse_error( "signed hex integer overflow", in ); - } - } - }; - - struct signed_rule_with_action - { - using analyze_t = signed_rule::analyze_t; - - template< pegtl::apply_mode, - pegtl::rewind_mode, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input > - [[nodiscard]] static auto match( Input& in, std::int64_t& st ) - { - bool negative = false; // Superfluous initialisation. - return pegtl::parse< signed_rule, signed_action_action >( in, negative, st ); // Throws on overflow. - } - }; - -} // namespace tao::json::jaxn::internal::integer - -#endif diff --git a/include/tao/json/jaxn/internal/unescape_action.hpp b/include/tao/json/jaxn/internal/unescape_action.hpp deleted file mode 100644 index 48b46bb5..00000000 --- a/include/tao/json/jaxn/internal/unescape_action.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_INTERNAL_UNESCAPE_ACTION_HPP -#define TAO_JSON_JAXN_INTERNAL_UNESCAPE_ACTION_HPP - -#include "../../external/pegtl/contrib/unescape.hpp" -#include "../../external/pegtl/nothing.hpp" - -#include "grammar.hpp" - -namespace tao::json::jaxn::internal -{ - // clang-format off - template< typename Rule > struct unescape_action : pegtl::nothing< Rule > {}; - - template<> struct unescape_action< rules::escaped_char > : pegtl::unescape::unescape_c< rules::escaped_char, '"', '\'', '\\', '/', '\b', '\f', '\n', '\r', '\t', '\v', '\0' > {}; - template<> struct unescape_action< rules::escaped_unicode > : pegtl::unescape::unescape_j {}; - template<> struct unescape_action< rules::escaped_unicode_code_point_content > : pegtl::unescape::unescape_u {}; - - template<> struct unescape_action< rules::identifier > : pegtl::unescape::append_all {}; // For parts_parser. - template< char D > struct unescape_action< rules::unescaped< D > > : pegtl::unescape::append_all {}; - template< char D > struct unescape_action< rules::mchars< D > > : pegtl::unescape::append_all {}; - // clang-format on - -} // namespace tao::json::jaxn::internal - -#endif diff --git a/include/tao/json/jaxn/is_identifier.hpp b/include/tao/json/jaxn/is_identifier.hpp deleted file mode 100644 index 8268c575..00000000 --- a/include/tao/json/jaxn/is_identifier.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_IS_IDENTIFIER_HPP -#define TAO_JSON_JAXN_IS_IDENTIFIER_HPP - -#include -#include - -namespace tao::json::jaxn -{ - [[nodiscard]] inline bool is_identifier( const std::string_view v ) noexcept - { - if( v.empty() || std::isdigit( v[ 0 ] ) ) { - return false; - } - for( const auto c : v ) { - if( !std::isalnum( c ) && c != '_' ) { - return false; - } - } - return true; - } - -} // namespace tao::json::jaxn - -#endif diff --git a/include/tao/json/jaxn/parts_parser.hpp b/include/tao/json/jaxn/parts_parser.hpp deleted file mode 100644 index 61240c32..00000000 --- a/include/tao/json/jaxn/parts_parser.hpp +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_PARTS_PARSER_HPP -#define TAO_JSON_JAXN_PARTS_PARSER_HPP - -#include "../parts_parser.hpp" - -#include "internal/action.hpp" -#include "internal/bunescape_action.hpp" -#include "internal/grammar.hpp" -#include "internal/integer.hpp" -#include "internal/unescape_action.hpp" - -namespace tao::json::jaxn -{ - namespace internal - { - namespace rules - { - struct double_rule - { - using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match_impl( Input& in, States&&... st ) - { - switch( in.peek_char() ) { - case '+': - in.bump_in_this_line(); - if( in.empty() || !sor_value::match_number< false, A, rewind_mode::dontcare, Action, Control >( in, st... ) ) { - throw pegtl::parse_error( "incomplete number", in ); - } - return true; - - case '-': - in.bump_in_this_line(); - if( in.empty() || !sor_value::match_number< true, A, rewind_mode::dontcare, Action, Control >( in, st... ) ) { - throw pegtl::parse_error( "incomplete number", in ); - } - return true; - - default: - return sor_value::match_number< false, A, M, Action, Control >( in, st... ); - } - } - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - return in.size( 2 ) && match_impl< A, M, Action, Control >( in, st... ); - } - }; - - } // namespace rules - - template< typename Rule > - struct double_action - : action< Rule > - {}; - - template< bool NEG > - struct double_action< rules::number< NEG > > - : pegtl::change_states< json::internal::number_state< NEG > > - { - template< typename Input, typename Consumer > - static void success( const Input& /*unused*/, json::internal::number_state< NEG >& state, Consumer& consumer ) - { - state.success( consumer ); - } - }; - - } // namespace internal - - // TODO: Optimise some of the simpler cases? - - template< typename Input = pegtl::string_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, std::string > > - class basic_parts_parser - { - public: - template< typename... Ts > - explicit basic_parts_parser( Ts&&... ts ) - : m_input( std::forward< Ts >( ts )... ) - { - pegtl::parse< json::internal::rules::wss >( m_input ); - } - - [[nodiscard]] bool empty() // noexcept( noexcept( m_input.empty() ) ) - { - return m_input.empty(); - } - - [[nodiscard]] bool null() - { - return pegtl::parse< pegtl::seq< json::internal::rules::null, json::internal::rules::wss > >( m_input ); - } - - [[nodiscard]] bool boolean() - { - bool r; - pegtl::parse< pegtl::must< json::internal::rules::boolean, json::internal::rules::wss > >( m_input, r ); - return r; - } - - [[nodiscard]] double number_double() - { - json::internal::double_state_and_consumer st; - pegtl::parse< pegtl::must< internal::rules::double_rule, json::internal::rules::wss >, internal::double_action >( m_input, st ); - return st.converted; - } - - [[nodiscard]] std::int64_t number_signed() - { - std::int64_t st = 0; - pegtl::parse< pegtl::must< internal::integer::signed_rule_with_action, json::internal::rules::wss > >( m_input, st ); - return st; - } - - [[nodiscard]] std::uint64_t number_unsigned() - { - std::uint64_t st = 0; - pegtl::parse< pegtl::must< internal::integer::unsigned_rule_with_action, json::internal::rules::wss > >( m_input, st ); - return st; - } - - [[nodiscard]] std::string string() - { - std::string unescaped; - pegtl::parse< pegtl::must< internal::rules::string, json::internal::rules::wss >, internal::unescape_action >( m_input, unescaped ); - return unescaped; - } - - // TODO: std::string_view string_view() that only works for strings without escape sequences? - - [[nodiscard]] std::vector< std::byte > binary() - { - std::vector< std::byte > data; - pegtl::parse< pegtl::must< internal::rules::binary, json::internal::rules::wss >, internal::bunescape_action >( m_input, data ); - return data; - } - - [[nodiscard]] std::string key() - { - std::string unescaped; - pegtl::parse< pegtl::must< internal::rules::mkey, json::internal::rules::wss, pegtl::one< ':' >, json::internal::rules::wss >, internal::unescape_action >( m_input, unescaped ); - return unescaped; - } - - // TODO: std::string_view key_view() that only works for identifiers (and possibly strings without escape sequences)? - - protected: - template< char C > - void parse_single_must() - { - pegtl::parse< pegtl::must< pegtl::one< C >, json::internal::rules::wss > >( m_input ); - } - - template< char C > - bool parse_single_test() - { - return pegtl::parse< pegtl::seq< pegtl::one< C >, json::internal::rules::wss > >( m_input ); - } - - struct state_t - { - std::size_t i = 0; - static constexpr std::size_t* size = nullptr; - }; - - public: - [[nodiscard]] state_t begin_array() - { - parse_single_must< '[' >(); - return state_t(); - } - - void end_array( state_t& /*unused*/ ) - { - parse_single_must< ']' >(); - } - - void element( state_t& p ) - { - if( p.i++ ) { - parse_single_must< ',' >(); - } - } - - [[nodiscard]] bool element_or_end_array( state_t& p ) - { - if( parse_single_test< ']' >() ) { - return false; - } - element( p ); - return true; - } - - [[nodiscard]] state_t begin_object() - { - parse_single_must< '{' >(); - return state_t(); - } - - void end_object( state_t& /*unused*/ ) - { - parse_single_must< '}' >(); - } - - void member( state_t& p ) - { - if( p.i++ ) { - parse_single_must< ',' >(); - } - } - - [[nodiscard]] bool member_or_end_object( state_t& p ) - { - if( parse_single_test< '}' >() ) { - return false; - } - member( p ); - return true; - } - - void skip_value() - { - pegtl::parse< pegtl::must< pegtl::json::value > >( m_input ); // Includes right-padding. - } - - [[nodiscard]] auto mark() // noexcept( noexcept( m_input.template mark< pegtl::rewind_mode::required >() ) ) - { - return m_input.template mark< pegtl::rewind_mode::required >(); - } - - template< typename T > - void throw_parse_error( T&& t ) const - { - throw pegtl::parse_error( std::forward< T >( t ), m_input ); - } - - protected: - Input m_input; - }; - - using parts_parser = basic_parts_parser<>; - -} // namespace tao::json::jaxn - -#endif diff --git a/include/tao/json/jaxn/to_stream.hpp b/include/tao/json/jaxn/to_stream.hpp deleted file mode 100644 index ba0a6a0c..00000000 --- a/include/tao/json/jaxn/to_stream.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_TO_STREAM_HPP -#define TAO_JSON_JAXN_TO_STREAM_HPP - -#include -#include - -#include "../value.hpp" - -#include "../events/from_value.hpp" -#include "../events/transformer.hpp" - -#include "events/to_pretty_stream.hpp" -#include "events/to_stream.hpp" - -namespace tao::json::jaxn -{ - template< template< typename... > class... Transformers, template< typename... > class Traits > - void to_stream( std::ostream& os, const basic_value< Traits >& v ) - { - json::events::transformer< events::to_stream, Transformers... > consumer( os ); - json::events::from_value( consumer, v ); - } - - template< template< typename... > class... Transformers, template< typename... > class Traits > - void to_stream( std::ostream& os, const basic_value< Traits >& v, const std::size_t indent ) - { - json::events::transformer< events::to_pretty_stream, Transformers... > consumer( os, indent ); - json::events::from_value( consumer, v ); - } - -} // namespace tao::json::jaxn - -#endif diff --git a/include/tao/json/jaxn/to_string.hpp b/include/tao/json/jaxn/to_string.hpp deleted file mode 100644 index 5b64c8cd..00000000 --- a/include/tao/json/jaxn/to_string.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_JAXN_TO_STRING_HPP -#define TAO_JSON_JAXN_TO_STRING_HPP - -#include - -#include "../value.hpp" - -#include "to_stream.hpp" - -namespace tao::json::jaxn -{ - template< template< typename... > class... Transformers, template< typename... > class Traits > - [[nodiscard]] std::string to_string( const basic_value< Traits >& v ) - { - std::ostringstream o; - jaxn::to_stream< Transformers... >( o, v ); - return o.str(); - } - - template< template< typename... > class... Transformers, template< typename... > class Traits > - [[nodiscard]] std::string to_string( const basic_value< Traits >& v, const unsigned indent ) - { - std::ostringstream o; - jaxn::to_stream< Transformers... >( o, v, indent ); - return o.str(); - } - -} // namespace tao::json::jaxn - -#endif diff --git a/include/tao/json/message_extension.hpp b/include/tao/json/message_extension.hpp deleted file mode 100644 index f524354b..00000000 --- a/include/tao/json/message_extension.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_MESSAGE_EXTENSION_HPP -#define TAO_JSON_MESSAGE_EXTENSION_HPP - -#include -#include - -namespace tao::json -{ - template< typename T, typename = void > - struct message_extension - { - const T& m_v; - - explicit message_extension( const T& v ) noexcept - : m_v( v ) - {} - - friend std::ostream& operator<<( std::ostream& os, const message_extension& /*unused*/ ) noexcept - { - return os; - } - }; - - template< typename T > - struct message_extension< T, decltype( std::declval< const T& >().public_base().append_message_extension( std::declval< std::ostream& >() ), void() ) > - { - const T& m_v; - - explicit message_extension( const T& v ) noexcept - : m_v( v ) - {} - - friend std::ostream& operator<<( std::ostream& os, const message_extension& v ) - { - os << ' '; - v.m_v.public_base().append_message_extension( os ); - return os; - } - }; - - template< typename T > - message_extension( const T& )->message_extension< T >; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/msgpack.hpp b/include/tao/json/msgpack.hpp deleted file mode 100644 index 8e9c4f73..00000000 --- a/include/tao/json/msgpack.hpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_MSGPACK_HPP -#define TAO_JSON_MSGPACK_HPP - -#include "../json.hpp" - -#include "msgpack/consume_file.hpp" -#include "msgpack/consume_string.hpp" -#include "msgpack/from_file.hpp" -#include "msgpack/from_input.hpp" -#include "msgpack/from_string.hpp" -#include "msgpack/parts_parser.hpp" -#include "msgpack/to_stream.hpp" -#include "msgpack/to_string.hpp" - -#endif diff --git a/include/tao/json/msgpack/consume_file.hpp b/include/tao/json/msgpack/consume_file.hpp deleted file mode 100644 index 3a8db14d..00000000 --- a/include/tao/json/msgpack/consume_file.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_MSGPACK_CONSUME_FILE_HPP -#define TAO_JSON_MSGPACK_CONSUME_FILE_HPP - -#include - -#include "../external/pegtl/file_input.hpp" - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "parts_parser.hpp" - -namespace tao::json::msgpack -{ - template< typename T, template< typename... > class Traits = traits, typename F > - [[nodiscard]] T consume_file( F&& filename ) - { - msgpack::basic_parts_parser< utf8_mode::check, pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); - return json::consume< T, Traits >( pp ); - } - - template< template< typename... > class Traits = traits, typename F, typename T > - void consume_file( F&& filename, T& t ) - { - msgpack::basic_parts_parser< utf8_mode::check, pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); - json::consume< Traits >( pp, t ); - } - -} // namespace tao::json::msgpack - -#endif diff --git a/include/tao/json/msgpack/consume_string.hpp b/include/tao/json/msgpack/consume_string.hpp deleted file mode 100644 index c27d62b8..00000000 --- a/include/tao/json/msgpack/consume_string.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_MSGPACK_CONSUME_STRING_HPP -#define TAO_JSON_MSGPACK_CONSUME_STRING_HPP - -#include "../external/pegtl/string_input.hpp" - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "parts_parser.hpp" - -namespace tao::json::msgpack -{ - template< typename T, template< typename... > class Traits = traits, typename F > - [[nodiscard]] T consume_string( F&& string ) - { - msgpack::basic_parts_parser< utf8_mode::check, pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); - return json::consume< T, Traits >( pp ); - } - - template< template< typename... > class Traits = traits, typename F, typename T > - void consume_string( F&& string, T& t ) - { - msgpack::basic_parts_parser< utf8_mode::check, pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); - json::consume< Traits >( pp, t ); - } - -} // namespace tao::json::msgpack - -#endif diff --git a/include/tao/json/msgpack/events/from_file.hpp b/include/tao/json/msgpack/events/from_file.hpp deleted file mode 100644 index aed9475f..00000000 --- a/include/tao/json/msgpack/events/from_file.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_MSGPACK_EVENTS_FROM_FILE_HPP -#define TAO_JSON_MSGPACK_EVENTS_FROM_FILE_HPP - -#include - -#include "../../external/pegtl/file_input.hpp" -#include "../../external/pegtl/parse.hpp" - -#include "../internal/grammar.hpp" - -namespace tao::json::msgpack::events -{ - // Events producer to parse a file containing a MSGPACK string representation. - - template< typename T, typename Consumer > - void from_file( Consumer& consumer, T&& filename ) - { - pegtl::file_input< pegtl::tracking_mode::lazy > in( std::forward< T >( filename ) ); - pegtl::parse< internal::grammar >( in, consumer ); - } - -} // namespace tao::json::msgpack::events - -#endif diff --git a/include/tao/json/msgpack/events/from_input.hpp b/include/tao/json/msgpack/events/from_input.hpp deleted file mode 100644 index 0e8be5aa..00000000 --- a/include/tao/json/msgpack/events/from_input.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_MSGPACK_EVENTS_FROM_INPUT_HPP -#define TAO_JSON_MSGPACK_EVENTS_FROM_INPUT_HPP - -#include - -#include "../../external/pegtl/parse.hpp" - -#include "../internal/grammar.hpp" - -namespace tao::json::msgpack::events -{ - // Events producers that parse MSGPACK from a PEGTL input (or something compatible). - - template< typename Consumer, typename Input > - void from_input( Consumer& consumer, Input&& in ) - { - pegtl::parse< msgpack::internal::grammar >( std::forward< Input >( in ), consumer ); - } - - template< typename Consumer, typename Input > - void from_input_embedded( Consumer& consumer, Input&& in ) - { - pegtl::parse< msgpack::internal::embedded >( std::forward< Input >( in ), consumer ); - } - - template< typename Consumer, typename Outer, typename Input > - void from_input_nested( Consumer& consumer, const Outer& oi, Input&& in ) - { - pegtl::parse_nested< msgpack::internal::grammar >( oi, std::forward< Input >( in ), consumer ); - } - - template< typename Consumer, typename Outer, typename Input > - void from_input_embedded_nested( Consumer& consumer, const Outer& oi, Input&& in ) - { - pegtl::parse_nested< msgpack::internal::embedded >( oi, std::forward< Input >( in ), consumer ); - } - -} // namespace tao::json::msgpack::events - -#endif diff --git a/include/tao/json/msgpack/events/from_string.hpp b/include/tao/json/msgpack/events/from_string.hpp deleted file mode 100644 index 7bcdf1dd..00000000 --- a/include/tao/json/msgpack/events/from_string.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_MSGPACK_EVENTS_FROM_STRING_HPP -#define TAO_JSON_MSGPACK_EVENTS_FROM_STRING_HPP - -#include -#include - -#include "../../external/pegtl/memory_input.hpp" - -#include "from_input.hpp" - -namespace tao::json::msgpack::events -{ - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t byte_in_line = 0 ) - { - pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::msgpack::from_string", byte, line, byte_in_line ); - msgpack::events::from_input( consumer, std::move( in ) ); - } - - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t byte_in_line = 0 ) - { - msgpack::events::from_string( consumer, data, size, source.c_str(), byte, line, byte_in_line ); - } - - template< typename Consumer, typename... Ts > - void from_string( Consumer& consumer, const std::string_view data, Ts&&... ts ) - { - msgpack::events::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); - } - -} // namespace tao::json::msgpack::events - -#endif diff --git a/include/tao/json/msgpack/events/to_stream.hpp b/include/tao/json/msgpack/events/to_stream.hpp deleted file mode 100644 index b41906ac..00000000 --- a/include/tao/json/msgpack/events/to_stream.hpp +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_MSGPACK_EVENTS_TO_STREAM_HPP -#define TAO_JSON_MSGPACK_EVENTS_TO_STREAM_HPP - -#include -#include -#include -#include -#include -#include -#include - -#include "../../binary_view.hpp" - -#include "../../internal/endian.hpp" - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4310 ) -#endif - -namespace tao::json::msgpack::events -{ - class to_stream - { - private: - std::ostream& os; - - public: - explicit to_stream( std::ostream& in_os ) noexcept - : os( in_os ) - {} - - void null() - { - os.put( char( 0xc0 ) ); - } - - void boolean( const bool v ) - { - os.put( char( 0xc2 ) + char( v ) ); - } - - template< typename Integer > - void number_impl( const unsigned char tag, const std::uint64_t v ) - { - os.put( char( tag ) ); - const Integer x = json::internal::h_to_be( Integer( v ) ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - - void number( const std::int64_t v ) - { - if( ( v >= -32 ) && ( v <= -1 ) ) { - const auto x = static_cast< std::int8_t >( v ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else if( ( v >= -128 ) && ( v <= 127 ) ) { - number_impl< std::uint8_t >( 0xd0, v ); - } - else if( ( v >= -32768 ) && ( v <= 32767 ) ) { - number_impl< std::uint16_t >( 0xd1, v ); - } - else if( ( v >= -2147483648LL ) && ( v <= 2147483647 ) ) { - number_impl< std::uint32_t >( 0xd2, v ); - } - else { - number_impl< std::uint64_t >( 0xd3, v ); - } - } - - void number( const std::uint64_t v ) - { - if( v <= 127 ) { - const auto x = static_cast< std::int8_t >( v ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else if( v <= 255 ) { - number_impl< std::uint8_t >( 0xcc, v ); - } - else if( v <= 65535 ) { - number_impl< std::uint16_t >( 0xcd, v ); - } - else if( v <= 4294967295UL ) { - number_impl< std::uint32_t >( 0xce, v ); - } - else { - number_impl< std::uint64_t >( 0xcf, v ); - } - } - - void number( const double v ) - { - os.put( char( 0xcb ) ); - const auto x = json::internal::h_to_be( v ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - - void string( const std::string_view v ) - { - if( v.size() <= 31 ) { - os.put( char( v.size() + 0xa0 ) ); - } - else if( v.size() <= 255 ) { - number_impl< std::uint8_t >( 0xd9, v.size() ); - } - else if( v.size() <= 65535 ) { - number_impl< std::uint16_t >( 0xda, v.size() ); - } - else if( v.size() <= 4294967295UL ) { - number_impl< std::uint32_t >( 0xdb, v.size() ); - } - else { - throw std::runtime_error( "string too long for msgpack" ); - } - os.write( v.data(), v.size() ); - } - - void binary( const tao::binary_view v ) - { - if( v.size() <= 255 ) { - number_impl< std::uint8_t >( 0xc4, v.size() ); - } - else if( v.size() <= 65535 ) { - number_impl< std::uint16_t >( 0xc5, v.size() ); - } - else if( v.size() <= 4294967295UL ) { - number_impl< std::uint32_t >( 0xc6, v.size() ); - } - else { - throw std::runtime_error( "binary too long for msgpack" ); - } - os.write( reinterpret_cast< const char* >( v.data() ), v.size() ); - } - - void begin_array() - { - throw std::runtime_error( "msgpack requires array size" ); - } - - void begin_array( const std::size_t size ) - { - if( size <= 15 ) { - os.put( char( 0x90 + size ) ); - } - else if( size <= 65535 ) { - number_impl< std::uint16_t >( 0xdc, size ); - } - else if( size <= 4294967295UL ) { - number_impl< std::uint32_t >( 0xdd, size ); - } - else { - throw std::runtime_error( "array too large for msgpack" ); - } - } - - void element() noexcept - {} - - void end_array() - { - assert( false ); // LCOV_EXCL_LINE - } - - void end_array( const std::size_t /*unused*/ ) noexcept - {} - - void begin_object() - { - throw std::runtime_error( "msgpack requires object size" ); - } - - void begin_object( const std::size_t size ) - { - if( size <= 15 ) { - os.put( char( 0x80 + size ) ); - } - else if( size <= 65535 ) { - number_impl< std::uint16_t >( 0xde, size ); - } - else if( size <= 4294967295UL ) { - number_impl< std::uint32_t >( 0xdf, size ); - } - else { - throw std::runtime_error( "array too large for msgpack" ); - } - } - - void key( const std::string_view v ) - { - string( v ); - } - - void member() noexcept - {} - - void end_object() - { - assert( false ); // LCOV_EXCL_LINE - } - - void end_object( const std::size_t /*unused*/ ) noexcept - {} - }; - -} // namespace tao::json::msgpack::events - -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - -#endif diff --git a/include/tao/json/msgpack/events/to_string.hpp b/include/tao/json/msgpack/events/to_string.hpp deleted file mode 100644 index 4560838c..00000000 --- a/include/tao/json/msgpack/events/to_string.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_MSGPACK_EVENTS_TO_STRING_HPP -#define TAO_JSON_MSGPACK_EVENTS_TO_STRING_HPP - -#include -#include - -#include "to_stream.hpp" - -namespace tao::json::msgpack::events -{ - struct to_string - : to_stream - { - std::ostringstream oss; - - to_string() - : to_stream( oss ) - {} - - [[nodiscard]] std::string value() const - { - return oss.str(); - } - }; - -} // namespace tao::json::msgpack::events - -#endif diff --git a/include/tao/json/msgpack/from_file.hpp b/include/tao/json/msgpack/from_file.hpp deleted file mode 100644 index 0ca12a54..00000000 --- a/include/tao/json/msgpack/from_file.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_MSGPACK_FROM_FILE_HPP -#define TAO_JSON_MSGPACK_FROM_FILE_HPP - -#include -#include - -#include "../events/to_value.hpp" -#include "../events/transformer.hpp" - -#include "events/from_file.hpp" - -namespace tao::json::msgpack -{ - template< template< typename... > class Traits, template< typename... > class... Transformers > - [[nodiscard]] basic_value< Traits > basic_from_file( const std::string& filename ) - { - json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; - events::from_file( consumer, filename ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers > - [[nodiscard]] value from_file( const std::string& filename ) - { - return basic_from_file< traits, Transformers... >( filename ); - } - -} // namespace tao::json::msgpack - -#endif diff --git a/include/tao/json/msgpack/from_input.hpp b/include/tao/json/msgpack/from_input.hpp deleted file mode 100644 index 9a8dd024..00000000 --- a/include/tao/json/msgpack/from_input.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_MSGPACK_FROM_INPUT_HPP -#define TAO_JSON_MSGPACK_FROM_INPUT_HPP - -#include -#include - -#include "../events/to_value.hpp" -#include "../events/transformer.hpp" - -#include "events/from_input.hpp" - -namespace tao::json::msgpack -{ - template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] basic_value< Traits > basic_from_input( Ts&&... ts ) - { - json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; - msgpack::events::from_input( consumer, std::forward< Ts >( ts )... ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] value from_input( Ts&&... ts ) - { - return basic_from_input< traits, Transformers... >( std::forward< Ts >( ts )... ); - } - -} // namespace tao::json::msgpack - -#endif diff --git a/include/tao/json/msgpack/from_string.hpp b/include/tao/json/msgpack/from_string.hpp deleted file mode 100644 index 61f7da93..00000000 --- a/include/tao/json/msgpack/from_string.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_MSGPACK_FROM_STRING_HPP -#define TAO_JSON_MSGPACK_FROM_STRING_HPP - -#include - -#include "../events/to_value.hpp" -#include "../events/transformer.hpp" - -#include "events/from_string.hpp" - -namespace tao::json::msgpack -{ - template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] basic_value< Traits > basic_from_string( Ts&&... ts ) - { - json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; - events::from_string( consumer, std::forward< Ts >( ts )... ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] value from_string( Ts&&... ts ) - { - return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); - } - -} // namespace tao::json::msgpack - -#endif diff --git a/include/tao/json/msgpack/internal/format.hpp b/include/tao/json/msgpack/internal/format.hpp deleted file mode 100644 index 6ad20b6c..00000000 --- a/include/tao/json/msgpack/internal/format.hpp +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_MSGPACK_INTERNAL_FORMAT_HPP -#define TAO_JSON_MSGPACK_INTERNAL_FORMAT_HPP - -#include - -namespace tao::json::msgpack::internal -{ - enum class format : std::uint8_t - { - POSITIVE_MAX = 0x7f, - FIXMAP_MIN = 0x80, - FIXMAP_MAX = 0x8f, - FIXARRAY_MIN = 0x90, - FIXARRAY_MAX = 0x9f, - FIXSTR_MIN = 0xa0, - FIXSTR_MAX = 0xbf, - NIL = 0xc0, - UNUSED = 0xc1, - BOOL_FALSE = 0xc2, - BOOL_TRUE = 0xc3, - BIN8 = 0xc4, - BIN16 = 0xc5, - BIN32 = 0xc6, - EXT8 = 0xc7, - EXT16 = 0xc8, - EXT32 = 0xc9, - FLOAT32 = 0xca, - FLOAT64 = 0xcb, - UINT8 = 0xcc, - UINT16 = 0xcd, - UINT32 = 0xce, - UINT64 = 0xcf, - INT8 = 0xd0, - INT16 = 0xd1, - INT32 = 0xd2, - INT64 = 0xd3, - FIXEXT1 = 0xd4, - FIXEXT2 = 0xd5, - FIXEXT4 = 0xd6, - FIXEXT8 = 0xd7, - FIXEXT16 = 0xd8, - STR8 = 0xd9, - STR16 = 0xda, - STR32 = 0xdb, - ARRAY16 = 0xdc, - ARRAY32 = 0xdd, - MAP16 = 0xde, - MAP32 = 0xdf, - NEGATIVE_MIN = 0xe0 - }; - -} // namespace tao::json::msgpack::internal - -#endif diff --git a/include/tao/json/msgpack/internal/grammar.hpp b/include/tao/json/msgpack/internal/grammar.hpp deleted file mode 100644 index 2f159853..00000000 --- a/include/tao/json/msgpack/internal/grammar.hpp +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_MSGPACK_INTERNAL_GRAMMAR_HPP -#define TAO_JSON_MSGPACK_INTERNAL_GRAMMAR_HPP - -#include -#include -#include - -#include "../../binary_view.hpp" -#include "../../external/pegtl.hpp" -#include "../../internal/format.hpp" -#include "../../internal/parse_util.hpp" -#include "../../utf8.hpp" - -#include "format.hpp" - -namespace tao::json::msgpack::internal -{ - template< utf8_mode U, typename Input > - [[nodiscard]] std::string_view read_string( Input& in ) - { - const auto b = json::internal::peek_uint8( in ); - if( ( std::uint8_t( format::FIXSTR_MIN ) <= b ) && ( b <= std::uint8_t( format::FIXSTR_MAX ) ) ) { - in.bump_in_this_line(); - return json::internal::read_string< U, std::string_view >( in, b - std::uint8_t( format::FIXSTR_MIN ) ); - } - switch( format( b ) ) { - case format::STR8: - return json::internal::read_string< U, std::string_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint8_t >( in, 1 ) ); - case format::STR16: - return json::internal::read_string< U, std::string_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint16_t >( in, 1 ) ); - case format::STR32: - return json::internal::read_string< U, std::string_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint32_t >( in, 1 ) ); - default: - throw pegtl::parse_error( "unexpected key type", in ); - } - } - - template< utf8_mode V > - struct data - { - using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; - - template< pegtl::apply_mode A, - pegtl::rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename Consumer > - [[nodiscard]] static bool match( Input& in, Consumer& consumer ) - { - if( !in.empty() ) { - parse_unsafe( in, consumer ); - return true; - } - return false; - } - - private: - template< typename Input, typename Consumer > - static void parse_unsafe( Input& in, Consumer& consumer ) - { - const auto b = in.peek_uint8(); - if( b <= std::uint8_t( format::POSITIVE_MAX ) ) { - consumer.number( std::uint64_t( b ) ); - in.bump_in_this_line(); - return; - } - if( b >= std::uint8_t( format::NEGATIVE_MIN ) ) { - consumer.number( std::int64_t( std::int8_t( b ) ) ); - in.bump_in_this_line(); - return; - } - if( ( std::uint8_t( format::FIXMAP_MIN ) <= b ) && ( b <= std::uint8_t( format::FIXMAP_MAX ) ) ) { - in.bump_in_this_line(); - parse_object( in, consumer, b - std::uint8_t( format::FIXMAP_MIN ) ); - return; - } - if( ( std::uint8_t( format::FIXARRAY_MIN ) <= b ) && ( b <= std::uint8_t( format::FIXARRAY_MAX ) ) ) { - in.bump_in_this_line(); - parse_array( in, consumer, b - std::uint8_t( format::FIXARRAY_MIN ) ); - return; - } - if( ( std::uint8_t( format::FIXSTR_MIN ) <= b ) && ( b <= std::uint8_t( format::FIXSTR_MAX ) ) ) { - in.bump_in_this_line(); - consumer.string( json::internal::read_string< V, std::string_view >( in, b - std::uint8_t( format::FIXSTR_MIN ) ) ); - return; - } - switch( format( b ) ) { - case format::NIL: - consumer.null(); - in.bump_in_this_line(); - return; - case format::UNUSED: - throw pegtl::parse_error( "unused first byte 0xc1", in ); - case format::BOOL_TRUE: - consumer.boolean( true ); - in.bump_in_this_line(); - return; - case format::BOOL_FALSE: - consumer.boolean( false ); - in.bump_in_this_line(); - return; - case format::BIN8: - consumer.binary( json::internal::read_string< utf8_mode::trust, tao::binary_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint8_t >( in, 1 ) ) ); - return; - case format::BIN16: - consumer.binary( json::internal::read_string< utf8_mode::trust, tao::binary_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint16_t >( in, 1 ) ) ); - return; - case format::BIN32: - consumer.binary( json::internal::read_string< utf8_mode::trust, tao::binary_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint32_t >( in, 1 ) ) ); - return; - case format::EXT8: - discard( in, json::internal::read_big_endian_number< std::size_t, std::uint8_t >( in, 1 ) + 1 ); - return; - case format::EXT16: - discard( in, json::internal::read_big_endian_number< std::size_t, std::uint16_t >( in, 1 ) + 1 ); - return; - case format::EXT32: - discard( in, json::internal::read_big_endian_number< std::size_t, std::uint32_t >( in, 1 ) + 1 ); - return; - case format::FLOAT32: - consumer.number( json::internal::read_big_endian_number< double, float >( in, 1 ) ); - return; - case format::FLOAT64: - consumer.number( json::internal::read_big_endian_number< double >( in, 1 ) ); - return; - case format::UINT8: - consumer.number( json::internal::read_big_endian_number< std::uint64_t, std::uint8_t >( in, 1 ) ); - return; - case format::UINT16: - consumer.number( json::internal::read_big_endian_number< std::uint64_t, std::uint16_t >( in, 1 ) ); - return; - case format::UINT32: - consumer.number( json::internal::read_big_endian_number< std::uint64_t, std::uint32_t >( in, 1 ) ); - return; - case format::UINT64: - consumer.number( json::internal::read_big_endian_number< std::uint64_t >( in, 1 ) ); - return; - case format::INT8: - consumer.number( json::internal::read_big_endian_number< std::int64_t, std::int8_t >( in, 1 ) ); - return; - case format::INT16: - consumer.number( json::internal::read_big_endian_number< std::int64_t, std::int16_t >( in, 1 ) ); - return; - case format::INT32: - consumer.number( json::internal::read_big_endian_number< std::int64_t, std::int32_t >( in, 1 ) ); - return; - case format::INT64: - consumer.number( json::internal::read_big_endian_number< std::int64_t >( in, 1 ) ); - return; - case format::FIXEXT1: - discard( in, 3 ); - return; - case format::FIXEXT2: - discard( in, 4 ); - return; - case format::FIXEXT4: - discard( in, 6 ); - return; - case format::FIXEXT8: - discard( in, 10 ); - return; - case format::FIXEXT16: - discard( in, 18 ); - return; - case format::STR8: - consumer.string( json::internal::read_string< V, std::string_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint8_t >( in, 1 ) ) ); - return; - case format::STR16: - consumer.string( json::internal::read_string< V, std::string_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint16_t >( in, 1 ) ) ); - return; - case format::STR32: - consumer.string( json::internal::read_string< V, std::string_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint32_t >( in, 1 ) ) ); - return; - case format::ARRAY16: - parse_array( in, consumer, json::internal::read_big_endian_number< std::size_t, std::uint16_t >( in, 1 ) ); - return; - case format::ARRAY32: - parse_array( in, consumer, json::internal::read_big_endian_number< std::size_t, std::uint32_t >( in, 1 ) ); - return; - case format::MAP16: - parse_object( in, consumer, json::internal::read_big_endian_number< std::size_t, std::uint16_t >( in, 1 ) ); - return; - case format::MAP32: - parse_object( in, consumer, json::internal::read_big_endian_number< std::size_t, std::uint32_t >( in, 1 ) ); - return; - default: - // LCOV_EXCL_START - assert( false ); - // LCOV_EXCL_STOP - } - } - - template< typename Input > - static void discard( Input& in, const std::size_t count ) - { - json::internal::throw_on_empty( in, count ); - in.bump_in_this_line( count ); - } - - template< typename Input, typename Consumer > - static void parse_array( Input& in, Consumer& consumer, const std::size_t size ) - { - consumer.begin_array( size ); - for( std::size_t i = 0; i < size; ++i ) { - json::internal::throw_on_empty( in ); - parse_unsafe( in, consumer ); - consumer.element(); - } - consumer.end_array( size ); - } - - template< typename Input, typename Consumer > - static void parse_object( Input& in, Consumer& consumer, const std::size_t size ) - { - consumer.begin_object( size ); - for( std::size_t i = 0; i < size; ++i ) { - consumer.key( read_string< V >( in ) ); - json::internal::throw_on_empty( in ); - parse_unsafe( in, consumer ); - consumer.member(); - } - consumer.end_object( size ); - } - }; - - template< utf8_mode V > - struct basic_grammar - : pegtl::must< data< V >, pegtl::eof > - { - }; - - template< utf8_mode V > - struct basic_embedded - : pegtl::must< data< V > > - { - }; - - using grammar = basic_grammar< utf8_mode::check >; - using embedded = basic_embedded< utf8_mode::check >; - -} // namespace tao::json::msgpack::internal - -#endif diff --git a/include/tao/json/msgpack/parts_parser.hpp b/include/tao/json/msgpack/parts_parser.hpp deleted file mode 100644 index 4810bccf..00000000 --- a/include/tao/json/msgpack/parts_parser.hpp +++ /dev/null @@ -1,311 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_MSGPACK_PARTS_PARSER_HPP -#define TAO_JSON_MSGPACK_PARTS_PARSER_HPP - -#include -#include - -#include "../events/discard.hpp" -#include "../external/pegtl/string_input.hpp" -#include "../utf8.hpp" - -#include "internal/format.hpp" -#include "internal/grammar.hpp" - -namespace tao::json::msgpack -{ - namespace internal - { - template< typename Input > - [[nodiscard]] format peek_format( Input& in ) - { - return format( json::internal::peek_uint8( in ) ); - } - - template< typename Input > - [[nodiscard]] bool read_boolean( Input& in ) - { - const auto b = internal::peek_format( in ); - switch( b ) { - case internal::format::BOOL_TRUE: - case internal::format::BOOL_FALSE: - in.bump_in_this_line( 1 ); - return bool( b & 1 ); - default: - throw pegtl::parse_error( "expected boolean", in ); - } - std::abort(); - } - - template< typename Input > - [[nodiscard]] tao::binary_view read_binary( Input& in ) - { - switch( peek_format( in ) ) { - case format::BIN8: - return json::internal::read_string< utf8_mode::trust, tao::binary_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint8_t >( in, 1 ) ); - case format::BIN16: - return json::internal::read_string< utf8_mode::trust, tao::binary_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint16_t >( in, 1 ) ); - case format::BIN32: - return json::internal::read_string< utf8_mode::trust, tao::binary_view >( in, json::internal::read_big_endian_number< std::size_t, std::uint32_t >( in, 1 ) ); - default: - throw pegtl::parse_error( "expected binary data", in ); - } - } - - [[nodiscard]] inline std::int64_t test_signed( const std::uint64_t i ) - { - if( ( i & ( std::uint64_t( 1 ) << 63 ) ) != 0 ) { - throw std::runtime_error( "integer overflow for signed" ); - } - return std::int64_t( i ); - } - - template< typename Input > - [[nodiscard]] std::int64_t read_signed( Input& in ) - { - const auto b = json::internal::peek_uint8( in ); - if( b <= std::uint8_t( format::POSITIVE_MAX ) ) { - in.bump_in_this_line(); - return std::int64_t( b ); - } - if( b >= std::uint8_t( format::NEGATIVE_MIN ) ) { - in.bump_in_this_line(); - return std::int64_t( std::int8_t( b ) ); - } - switch( format( b ) ) { - case format::UINT8: - return json::internal::read_big_endian_number< std::int64_t, std::uint8_t >( in, 1 ); - case format::UINT16: - return json::internal::read_big_endian_number< std::int64_t, std::uint16_t >( in, 1 ); - case format::UINT32: - return json::internal::read_big_endian_number< std::int64_t, std::uint32_t >( in, 1 ); - case format::UINT64: - return test_signed( json::internal::read_big_endian_number< std::uint64_t >( in, 1 ) ); - case format::INT8: - return json::internal::read_big_endian_number< std::int64_t, std::int8_t >( in, 1 ); - case format::INT16: - return json::internal::read_big_endian_number< std::int64_t, std::int16_t >( in, 1 ); - case format::INT32: - return json::internal::read_big_endian_number< std::int64_t, std::int32_t >( in, 1 ); - case format::INT64: - return json::internal::read_big_endian_number< std::int64_t >( in, 1 ); - default: - throw pegtl::parse_error( "expected signed number", in ); - } - } - - [[nodiscard]] inline std::uint64_t test_unsigned( const std::int64_t i ) - { - if( i < 0 ) { - throw std::runtime_error( "negative number for unsigned" ); - } - return std::uint64_t( i ); - } - - template< typename Input > - [[nodiscard]] std::uint64_t read_unsigned( Input& in ) - { - const auto b = json::internal::peek_uint8( in ); - if( b <= std::uint8_t( format::POSITIVE_MAX ) ) { - in.bump_in_this_line(); - return std::uint64_t( b ); - } - switch( format( b ) ) { - case format::UINT8: - return json::internal::read_big_endian_number< std::uint64_t, std::uint8_t >( in, 1 ); - case format::UINT16: - return json::internal::read_big_endian_number< std::uint64_t, std::uint16_t >( in, 1 ); - case format::UINT32: - return json::internal::read_big_endian_number< std::uint64_t, std::uint32_t >( in, 1 ); - case format::UINT64: - return json::internal::read_big_endian_number< std::uint64_t >( in, 1 ); - case format::INT8: - return test_unsigned( json::internal::read_big_endian_number< std::int64_t, std::int8_t >( in, 1 ) ); - case format::INT16: - return test_unsigned( json::internal::read_big_endian_number< std::int64_t, std::int16_t >( in, 1 ) ); - case format::INT32: - return test_unsigned( json::internal::read_big_endian_number< std::int64_t, std::int32_t >( in, 1 ) ); - case format::INT64: - return test_unsigned( json::internal::read_big_endian_number< std::int64_t >( in, 1 ) ); - default: - throw pegtl::parse_error( "expected positive number", in ); - } - } - - template< typename Input > - [[nodiscard]] double read_double( Input& in ) - { - switch( peek_format( in ) ) { - case format::FLOAT32: - return json::internal::read_big_endian_number< double, float >( in, 1 ); - case format::FLOAT64: - return json::internal::read_big_endian_number< double >( in, 1 ); - default: - throw pegtl::parse_error( "expected floating point number", in ); - } - } - - template< format Min, format Max, format S16, format S32, typename Input > - [[nodiscard]] std::size_t read_container_size( Input& in ) - { - const auto b = json::internal::peek_uint8( in ); - if( ( std::uint8_t( Min ) <= b ) && ( b <= std::uint8_t( Max ) ) ) { - in.bump_in_this_line(); - return state_t( b - std::uint8_t( Min ) ); - } - switch( format( b ) ) { - case S16: - return state_t( json::internal::read_big_endian_number< std::size_t, std::uint16_t >( in, 1 ) ); - case S32: - return state_t( json::internal::read_big_endian_number< std::size_t, std::uint32_t >( in, 1 ) ); - default: - throw pegtl::parse_error( "expected container", in ); - } - } - - } // namespace internal - - template< utf8_mode V = utf8_mode::check, typename Input = pegtl::string_input< pegtl::tracking_mode::lazy > > - class basic_parts_parser - { - public: - template< typename... Ts > - explicit basic_parts_parser( Ts&&... ts ) - : m_input( std::forward< Ts >( ts )... ) - {} - - [[nodiscard]] bool empty() - { - return m_input.empty(); - } - - [[nodiscard]] bool null() - { - if( internal::peek_format( m_input ) == internal::format::NIL ) { - m_input.bump_in_this_line( 1 ); - return true; - } - return false; - } - - [[nodiscard]] bool boolean() - { - return internal::read_boolean( m_input ); - } - - [[nodiscard]] std::string_view string() - { - return internal::read_string< V >( m_input ); - } - - [[nodiscard]] tao::binary_view binary() - { - return internal::read_binary( m_input ); - } - - [[nodiscard]] std::string_view key() - { - return internal::read_string< V >( m_input ); - } - - [[nodiscard]] std::int64_t number_signed() - { - return internal::read_signed( m_input ); - } - - [[nodiscard]] std::uint64_t number_unsigned() - { - return internal::read_unsigned( m_input ); - } - - [[nodiscard]] double number_double() - { - return internal::read_double( m_input ); - } - - struct state_t - { - explicit state_t( const std::size_t in_size ) - : size( in_size ) - {} - - std::size_t i = 0; - std::size_t size; - }; - - [[nodiscard]] state_t begin_array() - { - return state_t( internal::read_container_size< internal::format::FIXARRAY_MIN, internal::format::FIXARRAY_MAX, internal::format::ARRAY16, internal::format::ARRAY32 >( m_input ) ); - } - - [[nodiscard]] state_t begin_object() - { - return state_t( internal::read_container_size< internal::format::FIXMAP_MIN, internal::format::FIXMAP_MAX, internal::format::MAP16, internal::format::MAP32 >( m_input ) ); - } - - void end_array( state_t& p ) - { - if( p.size != p.i ) { - throw pegtl::parse_error( "array size mismatch", m_input ); - } - } - - void end_object( state_t& p ) - { - if( p.size != p.i ) { - throw pegtl::parse_error( "object size mismatch", m_input ); - } - } - - void element( state_t& p ) - { - if( p.i++ >= p.size ) { - throw pegtl::parse_error( "unexpected array end", m_input ); - } - } - - void member( state_t& p ) - { - if( p.i++ >= p.size ) { - throw pegtl::parse_error( "unexpected object end", m_input ); - } - } - - [[nodiscard]] bool element_or_end_array( state_t& p ) - { - return p.i++ < p.size; - } - - [[nodiscard]] bool member_or_end_object( state_t& p ) - { - return p.i++ < p.size; - } - - void skip_value() - { - json::events::discard consumer; // TODO: Optimise to not generate events (which requires preparing their - discarded - arguments)? - pegtl::parse< pegtl::must< internal::data< V > > >( m_input, consumer ); - } - - [[nodiscard]] auto mark() - { - return m_input.template mark< pegtl::rewind_mode::required >(); - } - - template< typename T > - void throw_parse_error( T&& t ) const - { - throw pegtl::parse_error( std::forward< T >( t ), m_input ); - } - - protected: - Input m_input; - }; - - using parts_parser = basic_parts_parser<>; - -} // namespace tao::json::msgpack - -#endif diff --git a/include/tao/json/msgpack/to_stream.hpp b/include/tao/json/msgpack/to_stream.hpp deleted file mode 100644 index 2c12f122..00000000 --- a/include/tao/json/msgpack/to_stream.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_MSGPACK_TO_STREAM_HPP -#define TAO_JSON_MSGPACK_TO_STREAM_HPP - -#include - -#include "../value.hpp" - -#include "../events/from_value.hpp" -#include "../events/transformer.hpp" - -#include "events/to_stream.hpp" - -namespace tao::json::msgpack -{ - template< template< typename... > class... Transformers, template< typename... > class Traits > - void to_stream( std::ostream& os, const basic_value< Traits >& v ) - { - json::events::transformer< events::to_stream, Transformers... > consumer( os ); - json::events::from_value( consumer, v ); - } - -} // namespace tao::json::msgpack - -#endif diff --git a/include/tao/json/msgpack/to_string.hpp b/include/tao/json/msgpack/to_string.hpp deleted file mode 100644 index ad22e1ef..00000000 --- a/include/tao/json/msgpack/to_string.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_MSGPACK_TO_STRING_HPP -#define TAO_JSON_MSGPACK_TO_STRING_HPP - -#include - -#include "../value.hpp" - -#include "../events/from_value.hpp" -#include "../events/transformer.hpp" - -#include "events/to_string.hpp" - -namespace tao::json::msgpack -{ - template< template< typename... > class... Transformers, template< typename... > class Traits > - [[nodiscard]] std::string to_string( const basic_value< Traits >& v ) - { - json::events::transformer< events::to_string, Transformers... > consumer; - json::events::from_value( consumer, v ); - return consumer.value(); - } - -} // namespace tao::json::msgpack - -#endif diff --git a/include/tao/json/operators.hpp b/include/tao/json/operators.hpp deleted file mode 100644 index d09edbe7..00000000 --- a/include/tao/json/operators.hpp +++ /dev/null @@ -1,494 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_OPERATORS_HPP -#define TAO_JSON_OPERATORS_HPP - -#include "basic_value.hpp" - -#include "internal/format.hpp" - -namespace tao::json -{ - template< template< typename... > class TraitsL, template< typename... > class TraitsR > - [[nodiscard]] bool operator==( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept - { - if( rhs.is_value_ptr() ) { - return lhs == rhs.skip_value_ptr(); - } - if( lhs.type() != rhs.type() ) { - switch( lhs.type() ) { - case type::VALUE_PTR: - return lhs.skip_value_ptr() == rhs; - - case type::SIGNED: - if( rhs.type() == type::UNSIGNED ) { - const auto v = lhs.get_signed(); - return ( v >= 0 ) && ( static_cast< std::uint64_t >( v ) == rhs.get_unsigned() ); - } - if( rhs.type() == type::DOUBLE ) { - return lhs.get_signed() == rhs.get_double(); - } - break; - - case type::UNSIGNED: - if( rhs.type() == type::SIGNED ) { - const auto v = rhs.get_signed(); - return ( v >= 0 ) && ( lhs.get_unsigned() == static_cast< std::uint64_t >( v ) ); - } - if( rhs.type() == type::DOUBLE ) { - return lhs.get_unsigned() == rhs.get_double(); - } - break; - - case type::DOUBLE: - if( rhs.type() == type::SIGNED ) { - return lhs.get_double() == rhs.get_signed(); - } - if( rhs.type() == type::UNSIGNED ) { - return lhs.get_double() == rhs.get_unsigned(); - } - break; - - case type::STRING: - if( rhs.type() == type::STRING_VIEW ) { - return lhs.get_string() == rhs.get_string_view(); - } - break; - - case type::STRING_VIEW: - if( rhs.type() == type::STRING ) { - return lhs.get_string_view() == rhs.get_string(); - } - break; - - case type::BINARY: - if( rhs.type() == type::BINARY_VIEW ) { - return tao::internal::binary_equal( lhs.get_binary(), rhs.get_binary_view() ); - } - break; - - case type::BINARY_VIEW: - if( rhs.type() == type::BINARY ) { - return tao::internal::binary_equal( lhs.get_binary_view(), rhs.get_binary() ); - } - break; - - case type::OPAQUE_PTR: - assert( lhs.type() != type::OPAQUE_PTR ); - break; - - default: - break; - } - assert( rhs.type() != type::OPAQUE_PTR ); - return false; - } - - switch( lhs.type() ) { - case type::UNINITIALIZED: - return true; - - case type::NULL_: - return true; - - case type::BOOLEAN: - return lhs.get_boolean() == rhs.get_boolean(); - - case type::SIGNED: - return lhs.get_signed() == rhs.get_signed(); - - case type::UNSIGNED: - return lhs.get_unsigned() == rhs.get_unsigned(); - - case type::DOUBLE: - return lhs.get_double() == rhs.get_double(); - - case type::STRING: - return lhs.get_string() == rhs.get_string(); - - case type::STRING_VIEW: - return lhs.get_string_view() == rhs.get_string_view(); - - case type::BINARY: - return lhs.get_binary() == rhs.get_binary(); - - case type::BINARY_VIEW: - return tao::internal::binary_equal( lhs.get_binary_view(), rhs.get_binary_view() ); - - case type::ARRAY: - return lhs.get_array() == rhs.get_array(); - - case type::OBJECT: - return lhs.get_object() == rhs.get_object(); - - case type::VALUE_PTR: - assert( lhs.type() != type::VALUE_PTR ); - break; // LCOV_EXCL_LINE - - case type::OPAQUE_PTR: - assert( lhs.type() != type::OPAQUE_PTR ); - break; // LCOV_EXCL_LINE - - case type::VALUELESS_BY_EXCEPTION: - assert( lhs.type() != type::VALUELESS_BY_EXCEPTION ); - break; // LCOV_EXCL_LINE - } - // LCOV_EXCL_START - assert( false ); - return false; - // LCOV_EXCL_STOP - } - - template< template< typename... > class Traits, int = 1 > // work-around for Visual C++ - [[nodiscard]] bool operator==( const basic_value< Traits >& lhs, tao::internal::identity_t< basic_value< Traits > > rhs ) noexcept - { - return lhs == rhs; - } - - template< template< typename... > class Traits, int = 2 > // work-around for Visual C++ - [[nodiscard]] bool operator==( tao::internal::identity_t< basic_value< Traits > > lhs, const basic_value< Traits >& rhs ) noexcept - { - return lhs == rhs; - } - - template< template< typename... > class Traits, typename T > - [[nodiscard]] bool operator==( const basic_value< Traits >& lhs, const std::optional< T >& rhs ) noexcept - { - static_assert( noexcept( Traits< std::optional< T > >::equal( lhs, rhs ) ), "equal must be noexcept" ); - return Traits< std::optional< T > >::equal( lhs, rhs ); - } - - template< typename T, template< typename... > class Traits > - [[nodiscard]] bool operator==( const std::optional< T >& lhs, const basic_value< Traits >& rhs ) noexcept - { - return rhs == lhs; - } - - template< template< typename... > class Traits, typename T > - [[nodiscard]] auto operator==( const basic_value< Traits >& lhs, const T& rhs ) noexcept -> decltype( Traits< std::decay_t< T > >::equal( lhs, rhs ) ) - { - using D = std::decay_t< T >; - static_assert( noexcept( Traits< D >::equal( lhs, rhs ) ), "equal must be noexcept" ); - return Traits< D >::equal( lhs, rhs ); - } - - template< typename T, template< typename... > class Traits > - [[nodiscard]] auto operator==( const T& lhs, const basic_value< Traits >& rhs ) noexcept -> decltype( Traits< std::decay_t< T > >::equal( rhs, lhs ) ) - { - return rhs == lhs; - } - - template< template< typename... > class TraitsL, template< typename... > class TraitsR > - [[nodiscard]] bool operator!=( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept - { - return !( lhs == rhs ); - } - - template< template< typename... > class Traits, typename T > - [[nodiscard]] bool operator!=( const basic_value< Traits >& lhs, const std::optional< T >& rhs ) noexcept - { - return !( lhs == rhs ); - } - - template< typename T, template< typename... > class Traits > - [[nodiscard]] bool operator!=( const std::optional< T >& lhs, const basic_value< Traits >& rhs ) noexcept - { - return !( rhs == lhs ); - } - - template< template< typename... > class Traits, typename T > - [[nodiscard]] bool operator!=( const basic_value< Traits >& lhs, const T& rhs ) noexcept - { - return !( lhs == rhs ); - } - - template< typename T, template< typename... > class Traits > - [[nodiscard]] bool operator!=( const T& lhs, const basic_value< Traits >& rhs ) noexcept - { - return !( lhs == rhs ); - } - - template< template< typename... > class TraitsL, template< typename... > class TraitsR > - [[nodiscard]] bool operator<( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept - { - if( rhs.is_value_ptr() ) { - return lhs < rhs.skip_value_ptr(); - } - if( lhs.type() != rhs.type() ) { - switch( lhs.type() ) { - case type::VALUE_PTR: - return lhs.skip_value_ptr() < rhs; - - case type::SIGNED: - if( rhs.type() == type::UNSIGNED ) { - const auto v = lhs.get_signed(); - return ( v < 0 ) || ( static_cast< std::uint64_t >( v ) < rhs.get_unsigned() ); - } - if( rhs.type() == type::DOUBLE ) { - return lhs.get_signed() < rhs.get_double(); - } - break; - - case type::UNSIGNED: - if( rhs.type() == type::SIGNED ) { - const auto v = rhs.get_signed(); - return ( v >= 0 ) && ( lhs.get_unsigned() < static_cast< std::uint64_t >( v ) ); - } - if( rhs.type() == type::DOUBLE ) { - return lhs.get_unsigned() < rhs.get_double(); - } - break; - - case type::DOUBLE: - if( rhs.type() == type::SIGNED ) { - return lhs.get_double() < rhs.get_signed(); - } - if( rhs.type() == type::UNSIGNED ) { - return lhs.get_double() < rhs.get_unsigned(); - } - break; - - case type::STRING: - if( rhs.type() == type::STRING_VIEW ) { - return lhs.get_string() < rhs.get_string_view(); - } - break; - - case type::STRING_VIEW: - if( rhs.type() == type::STRING ) { - return lhs.get_string_view() < rhs.get_string(); - } - break; - - case type::BINARY: - if( rhs.type() == type::BINARY_VIEW ) { - return tao::internal::binary_less( lhs.get_binary(), rhs.get_binary_view() ); - } - break; - - case type::BINARY_VIEW: - if( rhs.type() == type::BINARY ) { - return tao::internal::binary_less( lhs.get_binary_view(), rhs.get_binary() ); - } - break; - - case type::OPAQUE_PTR: - assert( lhs.type() != type::OPAQUE_PTR ); - break; - - default: - break; - } - assert( rhs.type() != type::OPAQUE_PTR ); - return lhs.type() < rhs.type(); - } - - switch( lhs.type() ) { - case type::UNINITIALIZED: - return false; - - case type::NULL_: - return false; - - case type::BOOLEAN: - return lhs.get_boolean() < rhs.get_boolean(); - - case type::SIGNED: - return lhs.get_signed() < rhs.get_signed(); - - case type::UNSIGNED: - return lhs.get_unsigned() < rhs.get_unsigned(); - - case type::DOUBLE: - return lhs.get_double() < rhs.get_double(); - - case type::STRING: - return lhs.get_string() < rhs.get_string(); - - case type::STRING_VIEW: - return lhs.get_string_view() < rhs.get_string_view(); - - case type::BINARY: - return lhs.get_binary() < rhs.get_binary(); - - case type::BINARY_VIEW: - return tao::internal::binary_less( lhs.get_binary_view(), rhs.get_binary_view() ); - - case type::ARRAY: - return lhs.get_array() < rhs.get_array(); - - case type::OBJECT: - return lhs.get_object() < rhs.get_object(); - - case type::VALUE_PTR: - assert( lhs.type() != type::VALUE_PTR ); - break; // LCOV_EXCL_LINE - - case type::OPAQUE_PTR: - assert( lhs.type() != type::OPAQUE_PTR ); - break; // LCOV_EXCL_LINE - - case type::VALUELESS_BY_EXCEPTION: - assert( lhs.type() != type::VALUELESS_BY_EXCEPTION ); - break; // LCOV_EXCL_LINE - } - // LCOV_EXCL_START - assert( false ); - return false; - // LCOV_EXCL_STOP - } - - template< template< typename... > class Traits, int = 1 > // work-around for Visual C++ - [[nodiscard]] bool operator<( const basic_value< Traits >& lhs, tao::internal::identity_t< basic_value< Traits > > rhs ) noexcept - { - return lhs < rhs; - } - - template< template< typename... > class Traits, int = 2 > // work-around for Visual C++ - [[nodiscard]] bool operator<( const tao::internal::identity_t< basic_value< Traits > > lhs, const basic_value< Traits >& rhs ) noexcept - { - return lhs < rhs; - } - - template< template< typename... > class Traits, typename T > - [[nodiscard]] bool operator<( const basic_value< Traits >& lhs, const std::optional< T >& rhs ) noexcept - { - static_assert( noexcept( Traits< std::optional< T > >::less_than( lhs, rhs ) ), "less_than must be noexcept" ); - return Traits< std::optional< T > >::less_than( lhs, rhs ); - } - - template< typename T, template< typename... > class Traits > - [[nodiscard]] bool operator<( const std::optional< T >& lhs, const basic_value< Traits >& rhs ) noexcept - { - static_assert( noexcept( Traits< std::optional< T > >::greater_than( rhs, lhs ) ), "greater_than must be noexcept" ); - return Traits< std::optional< T > >::greater_than( rhs, lhs ); - } - - template< template< typename... > class Traits, typename T > - [[nodiscard]] auto operator<( const basic_value< Traits >& lhs, const T& rhs ) noexcept -> decltype( Traits< std::decay_t< T > >::less_than( lhs, rhs ) ) - { - using D = std::decay_t< T >; - static_assert( noexcept( Traits< D >::less_than( lhs, rhs ) ), "less_than must be noexcept" ); - return Traits< D >::less_than( lhs, rhs ); - } - - template< typename T, template< typename... > class Traits > - [[nodiscard]] auto operator<( const T& lhs, const basic_value< Traits >& rhs ) noexcept -> decltype( Traits< std::decay_t< T > >::greater_than( rhs, lhs ) ) - { - using D = std::decay_t< T >; - static_assert( noexcept( Traits< D >::greater_than( rhs, lhs ) ), "greater_than must be noexcept" ); - return Traits< D >::greater_than( rhs, lhs ); - } - - template< template< typename... > class TraitsL, template< typename... > class TraitsR > - [[nodiscard]] bool operator>( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept - { - return rhs < lhs; - } - - template< template< typename... > class Traits > - [[nodiscard]] bool operator>( const basic_value< Traits >& lhs, tao::internal::identity_t< basic_value< Traits > > rhs ) noexcept - { - return rhs < lhs; - } - - template< template< typename... > class Traits > - [[nodiscard]] bool operator>( tao::internal::identity_t< basic_value< Traits > > lhs, const basic_value< Traits >& rhs ) noexcept - { - return rhs < lhs; - } - - template< template< typename... > class Traits, typename T > - [[nodiscard]] bool operator>( const basic_value< Traits >& lhs, const std::optional< T >& rhs ) noexcept - { - static_assert( noexcept( Traits< std::optional< T > >::greater_than( lhs, rhs ) ), "greater_than must be noexcept" ); - return Traits< std::optional< T > >::greater_than( lhs, rhs ); - } - - template< typename T, template< typename... > class Traits > - [[nodiscard]] bool operator>( const std::optional< T >& lhs, const basic_value< Traits >& rhs ) noexcept - { - static_assert( noexcept( Traits< std::optional< T > >::less_than( rhs, lhs ) ), "less_than must be noexcept" ); - return Traits< std::optional< T > >::less_than( rhs, lhs ); - } - - template< template< typename... > class Traits, typename T > - [[nodiscard]] auto operator>( const basic_value< Traits >& lhs, const T& rhs ) noexcept -> decltype( Traits< std::decay_t< T > >::greater_than( lhs, rhs ) ) - { - using D = std::decay_t< T >; - static_assert( noexcept( Traits< D >::greater_than( lhs, rhs ) ), "greater_than must be noexcept" ); - return Traits< D >::greater_than( lhs, rhs ); - } - - template< typename T, template< typename... > class Traits > - [[nodiscard]] auto operator>( const T& lhs, const basic_value< Traits >& rhs ) noexcept -> decltype( Traits< std::decay_t< T > >::less_than( rhs, lhs ) ) - { - using D = std::decay_t< T >; - static_assert( noexcept( Traits< D >::less_than( rhs, lhs ) ), "less_than must be noexcept" ); - return Traits< D >::less_than( rhs, lhs ); - } - - template< template< typename... > class TraitsL, template< typename... > class TraitsR > - [[nodiscard]] bool operator<=( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept - { - return !( lhs > rhs ); - } - - template< template< typename... > class Traits, typename T > - [[nodiscard]] bool operator<=( const basic_value< Traits >& lhs, const std::optional< T >& rhs ) noexcept - { - return !( lhs > rhs ); - } - - template< typename T, template< typename... > class Traits > - [[nodiscard]] bool operator<=( const std::optional< T >& lhs, const basic_value< Traits >& rhs ) noexcept - { - return !( lhs > rhs ); - } - - template< template< typename... > class Traits, typename T > - [[nodiscard]] bool operator<=( const basic_value< Traits >& lhs, const T& rhs ) noexcept - { - return !( lhs > rhs ); - } - - template< typename T, template< typename... > class Traits > - [[nodiscard]] bool operator<=( const T& lhs, const basic_value< Traits >& rhs ) noexcept - { - return !( lhs > rhs ); - } - - template< template< typename... > class TraitsL, template< typename... > class TraitsR > - [[nodiscard]] bool operator>=( const basic_value< TraitsL >& lhs, const basic_value< TraitsR >& rhs ) noexcept - { - return !( lhs < rhs ); - } - - template< template< typename... > class Traits, typename T > - [[nodiscard]] bool operator>=( const basic_value< Traits >& lhs, const std::optional< T >& rhs ) noexcept - { - return !( lhs < rhs ); - } - - template< typename T, template< typename... > class Traits > - [[nodiscard]] bool operator>=( const std::optional< T >& lhs, const basic_value< Traits >& rhs ) noexcept - { - return !( lhs < rhs ); - } - - template< template< typename... > class Traits, typename T > - [[nodiscard]] bool operator>=( const basic_value< Traits >& lhs, const T& rhs ) noexcept - { - return !( lhs < rhs ); - } - - template< typename T, template< typename... > class Traits > - [[nodiscard]] bool operator>=( const T& lhs, const basic_value< Traits >& rhs ) noexcept - { - return !( lhs < rhs ); - } - -} // namespace tao::json - -#endif diff --git a/include/tao/json/parts_parser.hpp b/include/tao/json/parts_parser.hpp deleted file mode 100644 index e6c37c8a..00000000 --- a/include/tao/json/parts_parser.hpp +++ /dev/null @@ -1,306 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_PARTS_PARSER_HPP -#define TAO_JSON_PARTS_PARSER_HPP - -#include "external/pegtl.hpp" -#include "external/pegtl/contrib/integer.hpp" -#include "external/pegtl/contrib/json.hpp" - -#include "internal/action.hpp" -#include "internal/format.hpp" -#include "internal/grammar.hpp" -#include "internal/number_state.hpp" -#include "internal/unescape_action.hpp" - -namespace tao::json -{ - namespace internal - { - namespace rules - { - struct wss - : pegtl::star< ws > - {}; - - struct boolean - { - using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; - - template< pegtl::apply_mode, - pegtl::rewind_mode, - template< typename... > - class, - template< typename... > - class, - typename Input > - [[nodiscard]] static bool match( Input& in, bool& st ) noexcept( noexcept( in.size( 5 ) ) ) - { - const auto s = in.size( 5 ); - if( s >= 5 ) { - if( std::memcmp( in.current(), "false", 5 ) == 0 ) { - in.bump_in_this_line( 5 ); - st = false; - return true; - } - } - if( s >= 4 ) { - if( std::memcmp( in.current(), "true", 4 ) == 0 ) { - in.bump_in_this_line( 4 ); - st = true; - return true; - } - } - return false; - } - }; - - struct double_rule - { - using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match_impl( Input& in, States&&... st ) - { - switch( in.peek_char() ) { - case '-': - in.bump_in_this_line(); - if( in.empty() || !sor_value::match_number< true, A, rewind_mode::dontcare, Action, Control >( in, st... ) ) { - throw pegtl::parse_error( "incomplete number", in ); - } - return true; - - default: - return sor_value::match_number< false, A, M, Action, Control >( in, st... ); - } - } - - template< apply_mode A, - rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename... States > - [[nodiscard]] static bool match( Input& in, States&&... st ) - { - return in.size( 2 ) && match_impl< A, M, Action, Control >( in, st... ); - } - }; - - } // namespace rules - - template< typename Rule > - struct double_action - : action< Rule > - {}; - - template< bool NEG > - struct double_action< rules::number< NEG > > - : pegtl::change_states< number_state< NEG > > - { - template< typename Input, typename Consumer > - static void success( const Input& /*unused*/, number_state< NEG >& state, Consumer& consumer ) - { - state.success( consumer ); - } - }; - - struct double_state_and_consumer - { - void number( const double d ) - { - converted = d; - } - - void number( const std::int64_t i ) - { - converted = double( i ); - } - - void number( const std::uint64_t u ) - { - converted = double( u ); - } - - double converted = 0.0; // TODO: Remove superfluous initialisation when we manage to shup up the warnings on all compilers. - }; - - } // namespace internal - - // TODO: Optimise some of the simpler cases? - - template< typename Input = pegtl::string_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, std::string > > - class basic_parts_parser - { - public: - template< typename... Ts > - explicit basic_parts_parser( Ts&&... ts ) - : m_input( std::forward< Ts >( ts )... ) - { - pegtl::parse< internal::rules::wss >( m_input ); - } - - [[nodiscard]] bool empty() - { - return m_input.empty(); - } - - [[nodiscard]] bool null() - { - return pegtl::parse< pegtl::seq< internal::rules::null, internal::rules::wss > >( m_input ); - } - - [[nodiscard]] bool boolean() - { - bool r; - pegtl::parse< pegtl::must< internal::rules::boolean, internal::rules::wss > >( m_input, r ); - return r; - } - - [[nodiscard]] double number_double() - { - internal::double_state_and_consumer st; - pegtl::parse< pegtl::must< internal::rules::double_rule, internal::rules::wss >, internal::double_action >( m_input, st ); - return st.converted; - } - - [[nodiscard]] std::int64_t number_signed() - { - std::int64_t st = 0; // TODO: Remove superfluous initialisation when we manage to shup up the warnings on all compilers. - pegtl::parse< pegtl::must< pegtl::integer::signed_rule_with_action, internal::rules::wss > >( m_input, st ); - return st; - } - - [[nodiscard]] std::uint64_t number_unsigned() - { - std::uint64_t st = 0; // TODO: Remove superfluous initialisation when we manage to shup up the warnings on all compilers. - pegtl::parse< pegtl::must< pegtl::integer::unsigned_rule_with_action, internal::rules::wss > >( m_input, st ); - return st; - } - - [[nodiscard]] std::string string() - { - std::string unescaped; - pegtl::parse< pegtl::must< internal::rules::string, internal::rules::wss >, internal::unescape_action >( m_input, unescaped ); - return unescaped; - } - - [[nodiscard]] std::vector< std::byte > binary() - { - throw std::runtime_error( "json format does not support binary" ); - } - - [[nodiscard]] std::string key() - { - std::string unescaped; - pegtl::parse< pegtl::must< internal::rules::string, internal::rules::wss, pegtl::one< ':' >, internal::rules::wss >, internal::unescape_action >( m_input, unescaped ); - return unescaped; - } - - template< char C > - void parse_single_must() - { - pegtl::parse< pegtl::must< pegtl::one< C >, internal::rules::wss > >( m_input ); - } - - template< char C > - [[nodiscard]] bool parse_single_test() - { - return pegtl::parse< pegtl::seq< pegtl::one< C >, internal::rules::wss > >( m_input ); - } - - struct state_t - { - std::size_t i = 0; - static constexpr std::size_t* size = nullptr; - }; - - [[nodiscard]] state_t begin_array() - { - parse_single_must< '[' >(); - return state_t(); - } - - void end_array( state_t& /*unused*/ ) - { - parse_single_must< ']' >(); - } - - void element( state_t& p ) - { - if( p.i++ ) { - parse_single_must< ',' >(); - } - } - - [[nodiscard]] bool element_or_end_array( state_t& p ) - { - if( parse_single_test< ']' >() ) { - return false; - } - element( p ); - return true; - } - - [[nodiscard]] state_t begin_object() - { - parse_single_must< '{' >(); - return state_t(); - } - - void end_object( state_t& /*unused*/ ) - { - parse_single_must< '}' >(); - } - - void member( state_t& p ) - { - if( p.i++ ) { - parse_single_must< ',' >(); - } - } - - [[nodiscard]] bool member_or_end_object( state_t& p ) - { - if( parse_single_test< '}' >() ) { - return false; - } - member( p ); - return true; - } - - void skip_value() - { - pegtl::parse< pegtl::must< pegtl::json::value > >( m_input ); // Includes standard JSON right-padding. - } - - [[nodiscard]] auto mark() - { - return m_input.template mark< pegtl::rewind_mode::required >(); - } - - template< typename T > - void throw_parse_error( T&& t ) const - { - throw pegtl::parse_error( std::forward< T >( t ), m_input ); - } - - protected: - Input m_input; - }; - - using parts_parser = basic_parts_parser<>; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/pointer.hpp b/include/tao/json/pointer.hpp deleted file mode 100644 index 38360a13..00000000 --- a/include/tao/json/pointer.hpp +++ /dev/null @@ -1,432 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_POINTER_HPP -#define TAO_JSON_POINTER_HPP - -#include -#include -#include -#include -#include -#include -#include - -#include "type.hpp" - -#include "external/pegtl.hpp" -#include "internal/format.hpp" - -namespace tao::json -{ - namespace internal - { - template< std::size_t = sizeof( std::size_t ) > - struct token_to_index; - - template<> - struct token_to_index< 4 > - { - [[nodiscard]] static std::size_t convert( const std::string& key ) noexcept - { - if( !key.empty() && key.size() <= 10 ) { - if( key == "0" ) { - return 0; - } - if( ( key[ 0 ] != '0' ) && ( key.find_first_not_of( "0123456789" ) == std::string::npos ) ) { - if( key.size() < 10 || key < "4294967296" ) { - return static_cast< std::size_t >( std::stoul( key ) ); - } - } - } - return std::string::npos; - } - }; - - template<> - struct token_to_index< 8 > - { - [[nodiscard]] static std::size_t convert( const std::string& key ) noexcept - { - if( !key.empty() && key.size() <= 20 ) { - if( key == "0" ) { - return 0; - } - if( ( key[ 0 ] != '0' ) && ( key.find_first_not_of( "0123456789" ) == std::string::npos ) ) { - if( key.size() < 20 || key < "18446744073709551616" ) { - return static_cast< std::size_t >( std::stoull( key ) ); - } - } - } - return std::string::npos; - } - }; - - } // namespace internal - - // RFC 6901 - class token - { - private: - std::size_t m_index; - std::string m_key; - - public: - explicit token( const std::string& in_key ) - : m_index( internal::token_to_index<>::convert( in_key ) ), - m_key( in_key ) - {} - - explicit token( std::string&& in_key ) noexcept - : m_index( internal::token_to_index<>::convert( in_key ) ), - m_key( std::move( in_key ) ) - {} - - explicit token( const std::size_t in_index ) - : m_index( in_index ), - m_key( std::to_string( m_index ) ) - {} - - token( const token& ) = default; - token( token&& v ) noexcept - : m_index( v.m_index ), - m_key( std::move( v.m_key ) ) - {} - - ~token() = default; - - token& operator=( const token& ) = default; - token& operator=( token&& v ) noexcept - { - m_index = v.m_index; - m_key = std::move( v.m_key ); - return *this; - } - - [[nodiscard]] bool has_index() const noexcept - { - return m_index != std::string::npos; - } - - [[nodiscard]] const std::string& key() const noexcept - { - return m_key; - } - - [[nodiscard]] std::size_t index() const - { - if( !has_index() ) { - throw std::invalid_argument( internal::format( "unable to resolve json pointer with array, token '", m_key, "' is not an index" ) ); - } - return m_index; - } - - [[nodiscard]] friend bool operator==( const token& lhs, const token& rhs ) noexcept - { - return lhs.m_key == rhs.m_key; - } - - [[nodiscard]] friend bool operator<( const token& lhs, const token& rhs ) noexcept - { - return lhs.m_key < rhs.m_key; - } - }; - - namespace internal - { - // clang-format off - struct pointer_zero : pegtl::one< '0' > {}; - struct pointer_one : pegtl::one< '1' > {}; - struct pointer_tilde : pegtl::one< '~' > {}; - struct pointer_escaped : pegtl::sor< pointer_zero, pointer_one > {}; - struct pointer_slash : pegtl::one< '/' > {}; - struct pointer_char : pegtl::utf8::not_one< '/' > {}; - struct pointer_escape : pegtl::if_must< pointer_tilde, pointer_escaped > {}; - struct pointer_token : pegtl::star< pegtl::sor< pointer_escape, pointer_char > > {}; - struct pointer_rule : pegtl::until< pegtl::eof, pegtl::must< pointer_slash, pointer_token > > {}; - struct pointer_grammar : pegtl::must< pointer_rule > {}; - // clang-format on - - template< typename Rule > - struct pointer_action - : pegtl::nothing< Rule > - {}; - - template<> - struct pointer_action< pointer_zero > - { - static void apply0( std::vector< token >& /*unused*/, std::string& t ) - { - t += '~'; - } - }; - - template<> - struct pointer_action< pointer_one > - { - static void apply0( std::vector< token >& /*unused*/, std::string& t ) - { - t += '/'; - } - }; - - template<> - struct pointer_action< pointer_char > - { - template< typename Input > - static void apply( const Input& in, std::vector< token >& /*unused*/, std::string& t ) - { - t.append( in.begin(), in.size() ); - } - }; - - template<> - struct pointer_action< pointer_token > - { - static void apply0( std::vector< token >& v, std::string& t ) - { - v.emplace_back( std::move( t ) ); - t.clear(); - } - }; - - } // namespace internal - - class pointer - : public std::vector< token > - { - private: - void parse( const std::string& v ) - { - std::string t; - pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > in( v, "parse()" ); - pegtl::parse< internal::pointer_grammar, internal::pointer_action >( in, vector(), t ); - } - - public: - pointer() = default; - pointer( const pointer& ) = default; - pointer( pointer&& p ) = default; - - explicit pointer( const std::string& v ) - { - parse( v ); - } - - pointer( const std::initializer_list< token >& l ) - : std::vector< token >( l ) - {} - - ~pointer() = default; - - pointer& operator=( const pointer& ) = default; - pointer& operator=( pointer&& p ) = default; - - pointer& operator=( const std::string& v ) - { - clear(); - parse( v ); - return *this; - } - - pointer& operator=( const std::initializer_list< token >& l ) - { - vector() = l; - return *this; - } - - [[nodiscard]] explicit operator bool() const noexcept - { - return !empty(); - } - - void push_back() = delete; - - void pop_back() - { - assert( !empty() ); - vector().pop_back(); - } - - [[nodiscard]] bool is_prefix_of( const pointer& other ) const noexcept - { - if( other.size() >= size() ) { - return std::equal( begin(), end(), other.begin() ); - } - return false; - } - - [[nodiscard]] std::vector< token >& vector() noexcept - { - return static_cast< std::vector< token >& >( *this ); - } - - [[nodiscard]] const std::vector< token >& vector() const noexcept - { - return static_cast< const std::vector< token >& >( *this ); - } - }; - - [[nodiscard]] inline bool operator==( const pointer& lhs, const pointer& rhs ) noexcept - { - return lhs.vector() == rhs.vector(); - } - - [[nodiscard]] inline bool operator<( const pointer& lhs, const pointer& rhs ) noexcept - { - return lhs.vector() < rhs.vector(); - } - - [[nodiscard]] inline bool operator!=( const pointer& lhs, const pointer& rhs ) noexcept - { - return !( lhs == rhs ); - } - - [[nodiscard]] inline bool operator>( const pointer& lhs, const pointer& rhs ) noexcept - { - return rhs < lhs; - } - - [[nodiscard]] inline bool operator<=( const pointer& lhs, const pointer& rhs ) noexcept - { - return !( rhs < lhs ); - } - - [[nodiscard]] inline bool operator>=( const pointer& lhs, const pointer& rhs ) noexcept - { - return !( lhs < rhs ); - } - - inline pointer& operator+=( pointer& lhs, const std::string& rhs ) - { - lhs.emplace_back( rhs ); - return lhs; - } - - inline pointer& operator+=( pointer& lhs, std::string&& rhs ) - { - lhs.emplace_back( std::move( rhs ) ); - return lhs; - } - - inline pointer& operator+=( pointer& lhs, const std::size_t rhs ) - { - lhs.emplace_back( rhs ); - return lhs; - } - - [[nodiscard]] inline pointer operator+( const pointer& p, const std::string& v ) - { - pointer nrv( p ); - nrv += v; - return nrv; - } - - [[nodiscard]] inline pointer operator+( const pointer& p, std::string&& v ) - { - pointer nrv( p ); - nrv += std::move( v ); - return nrv; - } - - [[nodiscard]] inline pointer operator+( const pointer& p, const std::size_t i ) - { - pointer nrv( p ); - nrv += i; - return nrv; - } - - namespace internal - { - [[nodiscard]] inline std::string tokens_to_string( std::vector< token >::const_iterator it, const std::vector< token >::const_iterator& end ) - { - std::string result; - while( it != end ) { - result += '/'; - for( const char c : it->key() ) { - switch( c ) { - case '~': - result += "~0"; - break; - case '/': - result += "~1"; - break; - default: - result += c; - } - } - ++it; - } - return result; - } - - [[nodiscard]] inline std::runtime_error invalid_type( const std::vector< token >::const_iterator& begin, const std::vector< token >::const_iterator& end ) - { - return std::runtime_error( internal::format( "unable to resolve JSON Pointer '", tokens_to_string( begin, end ), "' -- value type is neither 'object' nor 'array'" ) ); - } - - template< typename T > - [[nodiscard]] T& pointer_at( T* v, const std::vector< token >::const_iterator& begin, const std::vector< token >::const_iterator& end ) - { - for( auto it = begin; it != end; ++it ) { - switch( v->type() ) { - case type::ARRAY: - v = &v->at( it->index() ); - break; - case type::OBJECT: - v = &v->at( it->key() ); - break; - default: - throw invalid_type( begin, std::next( it ) ); - } - } - return *v; - } - - template< typename T > - [[nodiscard]] T* pointer_find( T* v, const std::vector< token >::const_iterator& begin, const std::vector< token >::const_iterator& end ) - { - for( auto it = begin; v && ( it != end ); ++it ) { - switch( v->type() ) { - case type::ARRAY: - v = v->find( it->index() ); - break; - case type::OBJECT: - v = v->find( it->key() ); - break; - default: - throw invalid_type( begin, std::next( it ) ); - } - } - return v; - } - - } // namespace internal - - [[nodiscard]] inline std::string to_string( const pointer& p ) - { - return internal::tokens_to_string( p.begin(), p.end() ); - } - - [[nodiscard]] inline std::string to_string( pointer& p ) - { - return internal::tokens_to_string( p.begin(), p.end() ); - } - - [[nodiscard]] inline std::string to_string( pointer&& p ) - { - return internal::tokens_to_string( p.begin(), p.end() ); - } - - inline namespace literals - { - [[nodiscard]] inline pointer operator"" _json_pointer( const char* data, const std::size_t size ) - { - return pointer( { data, size } ); - } - - } // namespace literals - -} // namespace tao::json - -#endif diff --git a/include/tao/json/produce.hpp b/include/tao/json/produce.hpp deleted file mode 100644 index d3713f92..00000000 --- a/include/tao/json/produce.hpp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_PRODUCE_HPP -#define TAO_JSON_PRODUCE_HPP - -#include -#include -#include -#include - -#include "forward.hpp" - -#include "events/produce.hpp" -#include "events/to_pretty_stream.hpp" -#include "events/to_stream.hpp" -#include "events/to_string.hpp" -#include "events/to_value.hpp" - -namespace tao::json::produce -{ - template< template< typename... > class Traits = traits, typename T > - [[nodiscard]] basic_value< Traits > to_value( T&& t ) - { - events::to_basic_value< Traits > consumer; - events::produce< Traits >( consumer, std::forward< T >( t ) ); - return std::move( consumer.value ); - } - - template< template< typename... > class Traits = traits, typename T > - void to_stream( std::ostream& os, const T& t ) - { - events::to_stream consumer( os ); - events::produce< Traits >( consumer, t ); - } - - template< template< typename... > class Traits = traits, typename T > - void to_stream( std::ostream& os, const T& t, const std::size_t indent ) - { - events::to_pretty_stream consumer( os, indent ); - events::produce< Traits >( consumer, t ); - } - - template< template< typename... > class Traits = traits, typename T, typename S > - void to_stream( std::ostream& os, const T& t, const std::size_t indent, S&& eol ) - { - events::to_pretty_stream consumer( os, indent, std::forward< S >( eol ) ); - events::produce< Traits >( consumer, t ); - } - - template< template< typename... > class Traits = traits, typename... Ts > - [[nodiscard]] std::string to_string( Ts&&... ts ) - { - std::ostringstream oss; - to_stream< Traits >( oss, std::forward< Ts >( ts )... ); - return oss.str(); - } - -} // namespace tao::json::produce - -#endif diff --git a/include/tao/json/self_contained.hpp b/include/tao/json/self_contained.hpp deleted file mode 100644 index 22673852..00000000 --- a/include/tao/json/self_contained.hpp +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_SELF_CONTAINED_HPP -#define TAO_JSON_SELF_CONTAINED_HPP - -#include "events/to_value.hpp" -#include "events/virtual_ref.hpp" - -#include "value.hpp" - -namespace tao::json -{ - // recursively checks for the existence - // of VALUE_PTR or OPAQUE_PTR nodes, STRING_VIEW or BINARY_VIEW, - // returns true is no such nodes were found. - - template< template< typename... > class Traits > - [[nodiscard]] bool is_self_contained( const basic_value< Traits >& v ) noexcept - { - switch( v.type() ) { - case type::UNINITIALIZED: - return true; - - case type::NULL_: - case type::BOOLEAN: - case type::SIGNED: - case type::UNSIGNED: - case type::DOUBLE: - case type::STRING: - case type::BINARY: - return true; - - case type::STRING_VIEW: - case type::BINARY_VIEW: - return false; - - case type::ARRAY: - for( auto& e : v.get_array() ) { - if( !is_self_contained( e ) ) { - return false; - } - } - return true; - - case type::OBJECT: - for( auto& e : v.get_object() ) { - if( !is_self_contained( e.second ) ) { - return false; - } - } - return true; - - case type::VALUE_PTR: - return false; - - case type::OPAQUE_PTR: - return false; - - case type::VALUELESS_BY_EXCEPTION: - return true; - } - // LCOV_EXCL_START - assert( false ); - return false; - // LCOV_EXCL_STOP - } - - // Removes all VALUE_PTR and OPAQUE_PTR nodes, - // recursively, by copying/generating their content; - // replaces STRING_VIEW and BINARY_VIEW with STRING - // and BINARY, respectively, with a copy of the data. - - template< template< typename... > class Traits > - void make_self_contained( basic_value< Traits >& v ) - { - switch( v.type() ) { - case type::UNINITIALIZED: - return; - - case type::NULL_: - case type::BOOLEAN: - case type::SIGNED: - case type::UNSIGNED: - case type::DOUBLE: - case type::STRING: - case type::BINARY: - return; - - case type::STRING_VIEW: - v.emplace_string( v.get_string_view() ); - return; - - case type::BINARY_VIEW: { - const auto xv = v.get_binary_view(); - v.emplace_binary( xv.begin(), xv.end() ); - return; - } - - case type::ARRAY: - for( auto& e : v.get_array() ) { - make_self_contained( e ); - } - return; - - case type::OBJECT: - for( auto& e : v.get_object() ) { - make_self_contained( e.second ); - } - return; - - case type::VALUE_PTR: - v = *v.get_value_ptr(); - make_self_contained( v ); - return; - - case type::OPAQUE_PTR: { - const auto& q = v.get_opaque_ptr(); - events::to_basic_value< Traits > consumer; - events::virtual_ref< events::to_basic_value< Traits > > ref( consumer ); - q.producer( ref, q.data ); - consumer.value.public_base() = std::move( v.public_base() ); - v = std::move( consumer.value ); - return; - } - - case type::VALUELESS_BY_EXCEPTION: - return; - } - throw std::logic_error( "invalid value for tao::json::type" ); // LCOV_EXCL_LINE - } - - template< template< typename... > class Traits > - [[nodiscard]] basic_value< Traits > self_contained_copy( const basic_value< Traits >& v ) - { - basic_value< Traits > r( &v ); - make_self_contained( r ); - return r; - } - -} // namespace tao::json - -#endif diff --git a/include/tao/json/span.hpp b/include/tao/json/span.hpp deleted file mode 100644 index bcdb61e2..00000000 --- a/include/tao/json/span.hpp +++ /dev/null @@ -1,568 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_SPAN_HPP -#define TAO_JSON_SPAN_HPP - -#if !defined( TAO_JSON_USE_STD_SPAN ) && ( __cplusplus > 201703L ) && defined( __has_include ) -// clang-format off -#if __has_include() -// clang-format on -#define TAO_JSON_USE_STD_SPAN -#endif -#endif - -#if defined( TAO_JSON_USE_STD_SPAN ) - -#include - -namespace tao -{ - using std::dynamic_extent; - using std::span; - - using std::as_bytes; - using std::as_writable_bytes; - -} // namespace tao - -#else - -#include -#include -#include -#include -#include -#include -#include - -namespace tao -{ - inline constexpr std::size_t dynamic_extent = std::numeric_limits< std::size_t >::max(); - - template< typename ElementType, std::size_t Extent = dynamic_extent > - class span; - - namespace internal - { - template< typename > - struct is_span_impl - : std::false_type - {}; - - template< typename ElementType, std::size_t Extent > - struct is_span_impl< span< ElementType, Extent > > - : std::true_type - {}; - - template< typename T > - using is_span = is_span_impl< std::remove_cv_t< T > >; - - template< typename > - struct is_std_array_impl - : std::false_type - {}; - - template< typename T, std::size_t N > - struct is_std_array_impl< std::array< T, N > > - : std::true_type - {}; - - template< typename T > - using is_std_array = is_std_array_impl< std::remove_cv_t< T > >; - - template< typename T, typename ElementType > - using is_span_compatible_ptr = std::is_convertible< T ( * )[], ElementType ( * )[] >; - - template< typename, typename, typename = void > - struct is_span_compatible_container - : std::false_type - {}; - - template< typename Container, typename ElementType > - struct is_span_compatible_container< Container, - ElementType, - std::void_t< - std::enable_if_t< !is_span< Container >::value >, - std::enable_if_t< !is_std_array< Container >::value >, - std::enable_if_t< !std::is_array_v< Container > >, - decltype( std::data( std::declval< Container >() ) ), - decltype( std::size( std::declval< Container >() ) ), - std::enable_if_t< is_span_compatible_ptr< std::remove_pointer_t< decltype( std::data( std::declval< Container& >() ) ) >, ElementType >::value > > > - : std::true_type - {}; - - } // namespace internal - - template< typename ElementType, std::size_t Extent > - class span - { - public: - static_assert( !std::is_abstract_v< ElementType > ); - - using element_type = ElementType; - using value_type = std::remove_cv_t< ElementType >; - using index_type = std::size_t; - using difference_type = std::ptrdiff_t; - using pointer = element_type*; - using const_pointer = const element_type*; - using reference = element_type&; - using const_reference = const element_type&; - using iterator = pointer; - using const_iterator = const_pointer; - using reverse_iterator = std::reverse_iterator< iterator >; - using const_reverse_iterator = std::reverse_iterator< const_iterator >; - - static constexpr index_type extent = Extent; - - template< typename T = void, typename = std::enable_if_t< Extent == 0, T > > - constexpr span() noexcept - : m_data( nullptr ) - {} - - constexpr span( pointer ptr, index_type count ) noexcept - : m_data( ptr ) - { - assert( count == Extent ); - } - - constexpr span( pointer first, pointer last ) noexcept - : m_data( first ) - { - assert( std::distance( first, last ) == Extent ); - } - - constexpr span( element_type ( &arr )[ Extent ] ) noexcept - : m_data( arr ) - {} - - template< std::size_t N, typename = std::enable_if_t< ( N == Extent ) && tao::internal::is_span_compatible_ptr< value_type, ElementType >::value > > - constexpr span( std::array< value_type, N >& arr ) noexcept - : m_data( arr.data() ) - {} - - template< std::size_t N, typename = std::enable_if_t< ( N == Extent ) && tao::internal::is_span_compatible_ptr< const value_type, ElementType >::value > > - constexpr span( const std::array< value_type, N >& arr ) noexcept - : m_data( arr.data() ) - {} - - constexpr span( const span& other ) = default; - - template< typename OtherElementType, typename = std::enable_if_t< tao::internal::is_span_compatible_ptr< OtherElementType, ElementType >::value > > - constexpr span( const span< OtherElementType, Extent >& s ) noexcept - : m_data( s.data() ) - {} - - ~span() = default; - - constexpr span& operator=( const span& ) = default; - - constexpr index_type size() const noexcept - { - return Extent; - } - - constexpr index_type size_bytes() const noexcept - { - return Extent * sizeof( element_type ); - } - - [[nodiscard]] constexpr bool empty() const noexcept - { - return Extent == 0; - } - - constexpr reference operator[]( index_type idx ) const noexcept - { - assert( idx < Extent ); - return *( data() + idx ); - } - - constexpr reference front() const noexcept - { - assert( Extent != 0 ); - return *data(); - } - - constexpr reference back() const noexcept - { - assert( Extent != 0 ); - return *( data() + ( Extent - 1 ) ); - } - - constexpr pointer data() const noexcept - { - return m_data; - } - - constexpr iterator begin() const noexcept - { - return data(); - } - - constexpr const_iterator cbegin() const noexcept - { - return data(); - } - - constexpr iterator end() const noexcept - { - return data() + Extent; - } - - constexpr const_iterator cend() const noexcept - { - return data() + Extent; - } - - constexpr reverse_iterator rbegin() const noexcept - { - return reverse_iterator( end() ); - } - - constexpr reverse_iterator rend() const noexcept - { - return reverse_iterator( begin() ); - } - - constexpr const_reverse_iterator crbegin() const noexcept - { - return const_reverse_iterator( cend() ); - } - - constexpr const_reverse_iterator crend() const noexcept - { - return const_reverse_iterator( cbegin() ); - } - - friend constexpr iterator begin( span s ) noexcept - { - return s.begin(); - } - - friend constexpr iterator end( span s ) noexcept - { - return s.end(); - } - - template< std::size_t Count > - constexpr span< element_type, Count > first() const noexcept - { - static_assert( Count <= Extent ); - return { data(), Count }; - } - - template< std::size_t Count > - constexpr span< element_type, Count > last() const noexcept - { - static_assert( Count <= Extent ); - return { data() + ( Extent - Count ), Count }; - } - - template< std::size_t Offset, std::size_t Count = dynamic_extent > - constexpr auto subspan() const - -> span< element_type, ( ( Count != dynamic_extent ) ? Count : ( Extent - Offset ) ) > - { - static_assert( Offset <= Extent ); - static_assert( ( Count == dynamic_extent ) || ( Count <= ( Extent - Offset ) ) ); - return { data() + Offset, ( Count != dynamic_extent ) ? Count : ( Extent - Offset ) }; - } - - constexpr span< element_type, dynamic_extent > first( index_type count ) const - { - assert( count <= Extent ); - return { data(), count }; - } - - constexpr span< element_type, dynamic_extent > last( index_type count ) const - { - assert( count <= Extent ); - return { data() + Extent - count, count }; - } - - constexpr span< element_type, dynamic_extent > subspan( index_type offset, index_type count = dynamic_extent ) const - { - assert( offset <= Extent ); - assert( ( count == dynamic_extent ) || ( count <= ( Extent - offset ) ) ); - return { data() + offset, ( count != dynamic_extent ) ? count : ( Extent - offset ) }; - } - - private: - pointer m_data; - }; - - template< typename ElementType > - class span< ElementType, dynamic_extent > - { - public: - static_assert( !std::is_abstract_v< ElementType > ); - - using element_type = ElementType; - using value_type = std::remove_cv_t< ElementType >; - using index_type = std::size_t; - using difference_type = std::ptrdiff_t; - using pointer = element_type*; - using const_pointer = const element_type*; - using reference = element_type&; - using const_reference = const element_type&; - using iterator = pointer; - using const_iterator = const_pointer; - using reverse_iterator = std::reverse_iterator< iterator >; - using const_reverse_iterator = std::reverse_iterator< const_iterator >; - - static constexpr index_type extent = dynamic_extent; - - constexpr span() noexcept - : m_data( nullptr ), m_size( 0 ) - {} - - constexpr span( pointer ptr, index_type count ) noexcept - : m_data( ptr ), m_size( count ) - {} - - constexpr span( pointer first, pointer last ) noexcept - : m_data( first ), m_size( std::distance( first, last ) ) - {} - - template< std::size_t N > - constexpr span( element_type ( &arr )[ N ] ) noexcept - : m_data( arr ), m_size( N ) - {} - - template< std::size_t N, typename = std::enable_if_t< tao::internal::is_span_compatible_ptr< value_type, ElementType >::value > > - constexpr span( std::array< value_type, N >& arr ) noexcept - : m_data( arr.data() ), m_size( N ) - {} - - template< std::size_t N, typename = std::enable_if_t< tao::internal::is_span_compatible_ptr< const value_type, ElementType >::value > > - constexpr span( const std::array< value_type, N >& arr ) noexcept - : m_data( arr.data() ), m_size( N ) - {} - - template< typename Container, typename = std::enable_if_t< tao::internal::is_span_compatible_container< Container, ElementType >::value > > - constexpr span( Container& cont ) - : m_data( std::data( cont ) ), m_size( std::size( cont ) ) - {} - - template< typename Container, typename = std::enable_if_t< tao::internal::is_span_compatible_container< const Container, ElementType >::value > > - constexpr span( const Container& cont ) - : m_data( std::data( cont ) ), m_size( std::size( cont ) ) - {} - - constexpr span( const span& other ) = default; - - template< typename OtherElementType, std::size_t OtherExtent, typename = std::enable_if_t< tao::internal::is_span_compatible_ptr< OtherElementType, ElementType >::value > > - constexpr span( const span< OtherElementType, OtherExtent >& s ) noexcept - : m_data( s.data() ), m_size( s.size() ) - {} - - ~span() = default; - - constexpr span& operator=( const span& ) = default; - - constexpr index_type size() const noexcept - { - return m_size; - } - - constexpr index_type size_bytes() const noexcept - { - return size() * sizeof( element_type ); - } - - [[nodiscard]] constexpr bool empty() const noexcept - { - return size() == 0; - } - - constexpr reference operator[]( index_type idx ) const noexcept - { - assert( idx < size() ); - return *( data() + idx ); - } - - constexpr reference front() const noexcept - { - assert( !empty() ); - return *data(); - } - - constexpr reference back() const noexcept - { - assert( !empty() ); - return *( data() + ( size() - 1 ) ); - } - - constexpr pointer data() const noexcept - { - return m_data; - } - - constexpr iterator begin() const noexcept - { - return data(); - } - - constexpr const_iterator cbegin() const noexcept - { - return data(); - } - - constexpr iterator end() const noexcept - { - return data() + size(); - } - - constexpr const_iterator cend() const noexcept - { - return data() + size(); - } - - constexpr reverse_iterator rbegin() const noexcept - { - return reverse_iterator( end() ); - } - - constexpr reverse_iterator rend() const noexcept - { - return reverse_iterator( begin() ); - } - - constexpr const_reverse_iterator crbegin() const noexcept - { - return const_reverse_iterator( cend() ); - } - - constexpr const_reverse_iterator crend() const noexcept - { - return const_reverse_iterator( cbegin() ); - } - - friend constexpr iterator begin( span s ) noexcept - { - return s.begin(); - } - - friend constexpr iterator end( span s ) noexcept - { - return s.end(); - } - - template< std::size_t Count > - constexpr span< element_type, Count > first() const noexcept - { - assert( Count <= size() ); - return { data(), Count }; - } - - template< std::size_t Count > - constexpr span< element_type, Count > last() const noexcept - { - assert( Count <= size() ); - return { data() + ( size() - Count ), Count }; - } - - template< std::size_t Offset, std::size_t Count = dynamic_extent > - constexpr auto subspan() const - -> span< element_type, ( ( Count != dynamic_extent ) ? Count : dynamic_extent ) > - { - assert( Offset <= size() ); - assert( ( Count == dynamic_extent ) || ( Count <= ( size() - Offset ) ) ); - return { data() + Offset, ( Count != dynamic_extent ) ? Count : ( size() - Offset ) }; - } - - constexpr span< element_type, dynamic_extent > first( index_type count ) const - { - assert( count <= size() ); - return { data(), count }; - } - - constexpr span< element_type, dynamic_extent > last( index_type count ) const - { - assert( count <= size() ); - return { data() + size() - count, count }; - } - - constexpr span< element_type, dynamic_extent > subspan( index_type offset, index_type count = dynamic_extent ) const - { - assert( offset <= size() ); - assert( ( count == dynamic_extent ) || ( count <= ( size() - offset ) ) ); - return { data() + offset, ( count != dynamic_extent ) ? count : ( size() - offset ) }; - } - - private: - pointer m_data; - index_type m_size; - }; - - template< typename ElementType, std::size_t Extent > - auto as_bytes( span< ElementType, Extent > s ) noexcept - -> span< const std::byte, ( ( Extent == dynamic_extent ) ? dynamic_extent : ( sizeof( ElementType ) * Extent ) ) > - { - return { reinterpret_cast< const std::byte* >( s.data() ), s.size_bytes() }; - } - - template< typename ElementType, std::size_t Extent, typename = std::enable_if_t< !std::is_const_v< ElementType > > > - auto as_writable_bytes( span< ElementType, Extent > s ) noexcept - -> span< std::byte, ( ( Extent == dynamic_extent ) ? dynamic_extent : ( sizeof( ElementType ) * Extent ) ) > - { - return { reinterpret_cast< std::byte* >( s.data() ), s.size_bytes() }; - } - - // deduction guides - template< typename T, std::size_t N > - span( T ( & )[ N ] )->span< T, N >; - - template< typename T, std::size_t N > - span( std::array< T, N >& )->span< T, N >; - - template< typename T, std::size_t N > - span( const std::array< T, N >& )->span< const T, N >; - - template< typename Container > - span( Container& )->span< typename Container::value_type >; - - template< typename Container > - span( const Container& )->span< const typename Container::value_type >; - -} // namespace tao - -namespace std -{ -#if defined( __clang__ ) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wmismatched-tags" -#endif - - template< typename ElementType, size_t Extent > - struct tuple_size< tao::span< ElementType, Extent > > - : integral_constant< size_t, Extent > - {}; - - template< typename ElementType > - struct tuple_size< tao::span< ElementType, tao::dynamic_extent > >; // not defined - - template< size_t I, typename ElementType, size_t Extent > - struct tuple_element< I, tao::span< ElementType, Extent > > - { - static_assert( ( Extent != tao::dynamic_extent ) && ( I < Extent ) ); - using type = ElementType; - }; - -#if defined( __clang__ ) -#pragma clang diagnostic pop -#endif - - // TODO: this is probably illegal. keep it? - template< size_t I, typename ElementType, size_t Extent > - constexpr ElementType& get( tao::span< ElementType, Extent > s ) noexcept - { - static_assert( ( Extent != tao::dynamic_extent ) && ( I < Extent ) ); - return s[ I ]; - } - -} // namespace std - -#endif - -#endif diff --git a/include/tao/json/stream.hpp b/include/tao/json/stream.hpp deleted file mode 100644 index 13fda705..00000000 --- a/include/tao/json/stream.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_STREAM_HPP -#define TAO_JSON_STREAM_HPP - -#include -#include -#include - -#include "to_stream.hpp" -#include "value.hpp" - -#include "internal/format.hpp" - -namespace tao::json -{ - // Use ostream << std::setw( n ) for pretty-printing with indent n. - - template< template< typename... > class Traits > - std::ostream& operator<<( std::ostream& o, const basic_value< Traits >& v ) - { - const auto w = o.width( 0 ); - if( w > 0 ) { - if( w >= 256 ) { - throw std::runtime_error( internal::format( "indentation ", w, " larger than 255" ) ); - } - json::to_stream( o, v, static_cast< std::size_t >( w ) ); - } - else { - json::to_stream( o, v ); - } - return o; - } - -} // namespace tao::json - -#endif diff --git a/include/tao/json/to_stream.hpp b/include/tao/json/to_stream.hpp deleted file mode 100644 index 62b2dae5..00000000 --- a/include/tao/json/to_stream.hpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_TO_STREAM_HPP -#define TAO_JSON_TO_STREAM_HPP - -#include -#include -#include - -#include "events/from_value.hpp" -#include "events/to_pretty_stream.hpp" -#include "events/to_stream.hpp" -#include "events/transformer.hpp" -#include "value.hpp" - -namespace tao::json -{ - template< template< typename... > class... Transformers, template< typename... > class Traits > - void to_stream( std::ostream& os, const basic_value< Traits >& v ) - { - events::transformer< events::to_stream, Transformers... > consumer( os ); - events::from_value( consumer, v ); - } - - template< template< typename... > class... Transformers, template< typename... > class Traits > - void to_stream( std::ostream& os, const basic_value< Traits >& v, const std::size_t indent ) - { - events::transformer< events::to_pretty_stream, Transformers... > consumer( os, indent ); - events::from_value( consumer, v ); - } - - template< template< typename... > class... Transformers, template< typename... > class Traits, typename S > - void to_stream( std::ostream& os, const basic_value< Traits >& v, const std::size_t indent, S&& eol ) - { - events::transformer< events::to_pretty_stream, Transformers... > consumer( os, indent, std::forward< S >( eol ) ); - events::from_value( consumer, v ); - } - -} // namespace tao::json - -#endif diff --git a/include/tao/json/to_string.hpp b/include/tao/json/to_string.hpp deleted file mode 100644 index 9dd8f5cf..00000000 --- a/include/tao/json/to_string.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_TO_STRING_HPP -#define TAO_JSON_TO_STRING_HPP - -#include - -#include "to_stream.hpp" - -namespace tao::json -{ - template< template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] std::string to_string( Ts&&... ts ) - { - std::ostringstream o; - json::to_stream< Transformers... >( o, std::forward< Ts >( ts )... ); - return o.str(); - } - -} // namespace tao::json - -#endif diff --git a/include/tao/json/traits.hpp b/include/tao/json/traits.hpp deleted file mode 100644 index b19d6bb8..00000000 --- a/include/tao/json/traits.hpp +++ /dev/null @@ -1,971 +0,0 @@ -// Copyright (c) 2016-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_TRAITS_HPP -#define TAO_JSON_TRAITS_HPP - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "binary_view.hpp" -#include "consume.hpp" -#include "forward.hpp" -#include "type.hpp" - -#include "events/from_value.hpp" -#include "events/produce.hpp" - -#include "internal/format.hpp" -#include "internal/identity.hpp" -#include "internal/number_traits.hpp" -#include "internal/string_t.hpp" -#include "internal/type_traits.hpp" - -#include "external/pegtl/internal/pegtl_string.hpp" - -#define TAO_JSON_DEFAULT_KEY( x ) \ - template< template< typename... > class Traits > \ - using default_key = TAO_JSON_STRING_T( x ) - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4702 ) -#endif - -namespace tao::json -{ - namespace internal - { - struct empty_base - {}; - - } // namespace internal - - // Traits< void > is special and configures the basic_value class template - template<> - struct traits< void > - { - static constexpr bool enable_implicit_constructor = true; - - template< typename > - using public_base = internal::empty_base; - }; - - template<> - struct traits< uninitialized_t > - { - static constexpr bool enable_implicit_constructor = true; - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& /*unused*/, uninitialized_t /*unused*/ ) noexcept - {} - - template< template< typename... > class Traits > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, uninitialized_t /*unused*/ ) noexcept - { - return lhs.skip_value_ptr().is_uninitialized(); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool less_than( const basic_value< Traits >& /*unused*/, uninitialized_t /*unused*/ ) noexcept - { - return false; // Because std::underlying_type_t< tao::json::type > is unsigned and type::uninitialized is 0. - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, uninitialized_t /*unused*/ ) noexcept - { - return lhs.skip_value_ptr().type() > type::UNINITIALIZED; - } - }; - - template<> - struct traits< null_t > - { - static constexpr bool enable_implicit_constructor = true; - - template< template< typename... > class Traits > - [[nodiscard]] static null_t as( const basic_value< Traits >& v ) - { - return v.get_null(); - } - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, null_t /*unused*/ ) noexcept - { - v.set_null(); - } - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, const null_t /*unused*/ ) - { - c.null(); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, null_t /*unused*/ ) noexcept - { - return lhs.skip_value_ptr().is_null(); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, null_t /*unused*/ ) noexcept - { - return lhs.skip_value_ptr().type() < type::NULL_; - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, null_t /*unused*/ ) noexcept - { - return lhs.skip_value_ptr().type() > type::NULL_; - } - }; - - template<> - struct traits< bool > - { - template< template< typename... > class Traits > - [[nodiscard]] static bool as( const basic_value< Traits >& v ) - { - return v.get_boolean(); - } - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const bool b ) noexcept - { - v.set_boolean( b ); - } - - template< template< typename... > class, typename Producer > - [[nodiscard]] static bool consume( Producer& parser ) - { - return parser.boolean(); - } - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, const bool b ) - { - c.boolean( b ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const bool rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - return p.is_boolean() && ( p.get_boolean() == rhs ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const bool rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - return ( p.type() < type::BOOLEAN ) || ( p.is_boolean() && ( p.get_boolean() < rhs ) ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const bool rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - return ( p.type() > type::BOOLEAN ) || ( p.is_boolean() && ( p.get_boolean() > rhs ) ); - } - }; - - // clang-format off - template<> struct traits< signed char > : internal::signed_trait< signed char > {}; - template<> struct traits< signed short > : internal::signed_trait< signed short > {}; - template<> struct traits< signed int > : internal::signed_trait< signed int > {}; - template<> struct traits< signed long > : internal::signed_trait< signed long > {}; - template<> struct traits< signed long long > : internal::signed_trait< signed long long > {}; - - template<> struct traits< unsigned char > : internal::unsigned_trait< unsigned char > {}; - template<> struct traits< unsigned short > : internal::unsigned_trait< unsigned short > {}; - template<> struct traits< unsigned int > : internal::unsigned_trait< unsigned int > {}; - template<> struct traits< unsigned long > : internal::unsigned_trait< unsigned long > {}; - template<> struct traits< unsigned long long > : internal::unsigned_trait< unsigned long long > {}; - - template<> struct traits< float > : internal::float_trait< float > {}; - template<> struct traits< double > : internal::float_trait< double > {}; - // clang-format on - - template<> - struct traits< empty_string_t > - { - static constexpr bool enable_implicit_constructor = true; - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, empty_string_t /*unused*/ ) noexcept - { - v.emplace_string(); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, empty_string_t /*unused*/ ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::STRING: - return p.get_string().empty(); - case type::STRING_VIEW: - return p.get_string_view().empty(); - default: - return false; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, empty_string_t /*unused*/ ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::STRING: - case type::STRING_VIEW: - return false; - default: - return p.type() < type::STRING; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, empty_string_t /*unused*/ ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::STRING: - return !p.get_string().empty(); - case type::STRING_VIEW: - return !p.get_string_view().empty(); - default: - return p.type() > type::STRING; - } - } - }; - - template<> - struct traits< empty_binary_t > - { - static constexpr bool enable_implicit_constructor = true; - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, empty_binary_t /*unused*/ ) noexcept - { - v.emplace_binary(); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, empty_binary_t /*unused*/ ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::BINARY: - return p.get_binary().empty(); - case type::BINARY_VIEW: - return p.get_binary_view().empty(); - default: - return false; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, empty_binary_t /*unused*/ ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::BINARY: - case type::BINARY_VIEW: - return false; - default: - return p.type() < type::BINARY; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, empty_binary_t /*unused*/ ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::BINARY: - return !p.get_binary().empty(); - case type::BINARY_VIEW: - return !p.get_binary_view().empty(); - default: - return p.type() > type::BINARY; - } - } - }; - - template<> - struct traits< empty_array_t > - { - static constexpr bool enable_implicit_constructor = true; - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, empty_array_t /*unused*/ ) noexcept - { - v.emplace_array(); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, empty_array_t /*unused*/ ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - return p.is_array() && p.get_array().empty(); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, empty_array_t /*unused*/ ) noexcept - { - return lhs.skip_value_ptr().type() < type::ARRAY; - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, empty_array_t /*unused*/ ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - return ( p.type() > type::ARRAY ) || ( p.is_array() && !p.get_array().empty() ); - } - }; - - template<> - struct traits< empty_object_t > - { - static constexpr bool enable_implicit_constructor = true; - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, empty_object_t /*unused*/ ) noexcept - { - v.emplace_object(); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, empty_object_t /*unused*/ ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - return p.is_object() && p.get_object().empty(); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, empty_object_t /*unused*/ ) noexcept - { - return lhs.skip_value_ptr().type() < type::OBJECT; - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, empty_object_t /*unused*/ ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - return ( p.type() > type::OBJECT ) || ( p.is_object() && !p.get_object().empty() ); - } - }; - - template<> - struct traits< std::string > - { - template< template< typename... > class Traits > - [[nodiscard]] static std::string as( const basic_value< Traits >& v ) - { - switch( v.type() ) { - case type::STRING: - return v.get_string(); - case type::STRING_VIEW: - return std::string( v.get_string_view() ); - default: - throw std::logic_error( internal::format( "invalid json type '", v.type(), "' for conversion to std::string", json::message_extension( v ) ) ); - } - } - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const std::string& s ) - { - v.set_string( s ); - } - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, std::string&& s ) noexcept - { - v.set_string( std::move( s ) ); - } - - template< template< typename... > class, typename Producer > - [[nodiscard]] static std::string consume( Producer& parser ) - { - return parser.string(); - } - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, const std::string& s ) - { - c.string( s ); - } - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, std::string&& s ) - { - c.string( std::move( s ) ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const std::string& rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::STRING: - return p.get_string() == rhs; - case type::STRING_VIEW: - return p.get_string_view() == rhs; - default: - return false; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const std::string& rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::STRING: - return p.get_string() < rhs; - case type::STRING_VIEW: - return p.get_string_view() < rhs; - default: - return p.type() < type::STRING; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const std::string& rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::STRING: - return p.get_string() > rhs; - case type::STRING_VIEW: - return p.get_string_view() > rhs; - default: - return p.type() > type::STRING; - } - } - }; - - template<> - struct traits< std::string_view > - { - template< template< typename... > class Traits > - [[nodiscard]] static std::string_view as( const basic_value< Traits >& v ) - { - switch( v.type() ) { - case type::STRING: - return v.get_string(); - case type::STRING_VIEW: - return v.get_string_view(); - default: - throw std::logic_error( internal::format( "invalid json type '", v.type(), "' for conversion to std::string_view", json::message_extension( v ) ) ); - } - } - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const std::string_view sv ) - { - v.emplace_string( sv ); - } - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, const std::string_view sv ) - { - c.string( sv ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const std::string_view rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::STRING: - return p.get_string() == rhs; - case type::STRING_VIEW: - return p.get_string_view() == rhs; - default: - return false; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const std::string_view rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::STRING: - return p.get_string() < rhs; - case type::STRING_VIEW: - return p.get_string_view() < rhs; - default: - return p.type() < type::STRING; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const std::string_view rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::STRING: - return p.get_string() > rhs; - case type::STRING_VIEW: - return p.get_string_view() > rhs; - default: - return p.type() > type::STRING; - } - } - }; - - template<> - struct traits< const char* > - { - template< template< typename... > class Traits > - [[nodiscard]] static const char* as( const basic_value< Traits >& v ) - { - return v.get_string().c_str(); // String views might not be '\0'-terminated. - } - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const char* s ) - { - v.emplace_string( s ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const char* rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::STRING: - return p.get_string() == rhs; - case type::STRING_VIEW: - return p.get_string_view() == rhs; - default: - return false; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const char* rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::STRING: - return p.get_string() < rhs; - case type::STRING_VIEW: - return p.get_string_view() < rhs; - default: - return p.type() < type::STRING; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const char* rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::STRING: - return p.get_string() > rhs; - case type::STRING_VIEW: - return p.get_string_view() > rhs; - default: - return p.type() > type::STRING; - } - } - }; - - template<> - struct traits< const std::string& > - { - template< template< typename... > class Traits > - [[nodiscard]] static const std::string& as( const basic_value< Traits >& v ) - { - return v.get_string(); - } - }; - - template<> - struct traits< std::vector< std::byte > > - { - template< template< typename... > class Traits > - [[nodiscard]] static std::vector< std::byte > as( const basic_value< Traits >& v ) - { - switch( v.type() ) { - case type::BINARY: - return v.get_binary(); - case type::BINARY_VIEW: { - const auto xv = v.get_binary_view(); - return std::vector< std::byte >( xv.begin(), xv.end() ); - } - default: - throw std::logic_error( internal::format( "invalid json type '", v.type(), "' for conversion to std::vector< std::byte >", json::message_extension( v ) ) ); - } - } - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const std::vector< std::byte >& x ) - { - v.set_binary( x ); - } - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, std::vector< std::byte >&& x ) noexcept - { - v.set_binary( std::move( x ) ); - } - - template< template< typename... > class, typename Producer > - [[nodiscard]] static std::vector< std::byte > consume( Producer& parser ) - { - return parser.binary(); - } - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, const std::vector< std::byte >& x ) - { - c.binary( x ); - } - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, std::vector< std::byte >&& x ) - { - c.binary( std::move( x ) ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const std::vector< std::byte >& rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::BINARY: - return p.get_binary() == rhs; - case type::BINARY_VIEW: - return tao::internal::binary_equal( p.get_binary_view(), rhs ); - default: - return false; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const std::vector< std::byte >& rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::BINARY: - return p.get_binary() < rhs; - case type::BINARY_VIEW: - return tao::internal::binary_less( p.get_binary_view(), rhs ); - default: - return p.type() < type::BINARY; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const std::vector< std::byte >& rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::BINARY: - return p.get_binary() > rhs; - case type::BINARY_VIEW: - return tao::internal::binary_less( rhs, p.get_binary_view() ); - default: - return p.type() > type::BINARY; - } - } - }; - - template<> - struct traits< tao::binary_view > - { - template< template< typename... > class Traits > - [[nodiscard]] static tao::binary_view as( const basic_value< Traits >& v ) - { - switch( v.type() ) { - case type::BINARY: - return v.get_binary(); - case type::BINARY_VIEW: - return v.get_binary_view(); - default: - throw std::logic_error( internal::format( "invalid json type '", v.type(), "' for conversion to tao::binary_view", json::message_extension( v ) ) ); - } - } - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const tao::binary_view xv ) - { - v.emplace_binary( xv.begin(), xv.end() ); - } - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, const tao::binary_view xv ) - { - c.binary( xv ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const tao::binary_view rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::BINARY: - return tao::internal::binary_equal( p.get_binary(), rhs ); - case type::BINARY_VIEW: - return tao::internal::binary_equal( p.get_binary_view(), rhs ); - default: - return false; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const tao::binary_view rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::BINARY: - return tao::internal::binary_less( p.get_binary(), rhs ); - case type::BINARY_VIEW: - return tao::internal::binary_less( p.get_binary_view(), rhs ); - default: - return p.type() < type::BINARY; - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const tao::binary_view rhs ) noexcept - { - const auto& p = lhs.skip_value_ptr(); - switch( p.type() ) { - case type::BINARY: - return tao::internal::binary_less( rhs, p.get_binary() ); - case type::BINARY_VIEW: - return tao::internal::binary_less( rhs, p.get_binary_view() ); - default: - return p.type() > type::BINARY; - } - } - }; - - template<> - struct traits< const std::vector< std::byte >& > - { - template< template< typename... > class Traits > - [[nodiscard]] static const std::vector< std::byte >& as( const basic_value< Traits >& v ) - { - return v.get_binary(); - } - }; - - template< template< typename... > class Traits > - struct traits< basic_value< Traits > > - { - template< template< typename... > class, typename Consumer > - static void produce( Consumer& c, const basic_value< Traits >& v ) - { - events::from_value( c, v ); - } - - template< template< typename... > class, typename Consumer > - static void produce( Consumer& c, basic_value< Traits >&& v ) - { - events::from_value( c, std::move( v ) ); - } - }; - - template< template< typename... > class Traits > - struct traits< std::vector< basic_value< Traits > > > - { - static void assign( basic_value< Traits >& v, const std::vector< basic_value< Traits > >& a ) - { - v.set_array( a ); - } - - static void assign( basic_value< Traits >& v, std::vector< basic_value< Traits > >&& a ) noexcept - { - v.set_array( std::move( a ) ); - } - - template< template< typename... > class, typename Consumer > - static void produce( Consumer& c, const std::vector< basic_value< Traits > >& a ) - { - c.begin_array( a.size() ); - for( const auto& i : a ) { - Traits< basic_value< Traits > >::produce( c, i ); - c.element(); - } - c.end_array( a.size() ); - } - - template< template< typename... > class, typename Consumer > - static void produce( Consumer& c, std::vector< basic_value< Traits > >&& a ) - { - c.begin_array( a.size() ); - for( auto&& i : a ) { - Traits< basic_value< Traits > >::produce( c, std::move( i ) ); - c.element(); - } - c.end_array( a.size() ); - } - }; - - template< template< typename... > class Traits > - struct traits< std::map< std::string, basic_value< Traits >, std::less<> > > - { - static void assign( basic_value< Traits >& v, const std::map< std::string, basic_value< Traits >, std::less<> >& o ) - { - v.set_object( std::move( o ) ); - } - - static void assign( basic_value< Traits >& v, std::map< std::string, basic_value< Traits >, std::less<> >&& o ) noexcept - { - v.set_object( std::move( o ) ); - } - - template< template< typename... > class, typename Consumer > - static void produce( Consumer& c, const std::map< std::string, basic_value< Traits >, std::less<> >& o ) - { - c.begin_object( o.size() ); - for( const auto& i : o ) { - c.key( i.first ); - Traits< basic_value< Traits > >::produce( c, i.second ); - c.member(); - } - c.end_object( o.size() ); - } - - template< template< typename... > class, typename Consumer > - static void produce( Consumer& c, std::map< std::string, basic_value< Traits >, std::less<> >&& o ) - { - c.begin_object( o.size() ); - for( auto&& i : o ) { - c.key( std::move( i.first ) ); - Traits< basic_value< Traits > >::produce( c, std::move( i.second ) ); - c.member(); - } - c.end_object( o.size() ); - } - }; - - template< template< typename... > class Traits > - struct traits< const basic_value< Traits >* > - { - static void assign( basic_value< Traits >& v, const basic_value< Traits >* p ) noexcept - { - v.set_value_ptr( p ); - } - - template< template< typename... > class TraitsLL > - [[nodiscard]] static bool equal( const basic_value< TraitsLL >& lhs, const basic_value< Traits >* rhs ) noexcept - { - assert( rhs ); - return lhs == *rhs; - } - - template< template< typename... > class TraitsLL > - [[nodiscard]] static bool less_than( const basic_value< TraitsLL >& lhs, const basic_value< Traits >* rhs ) noexcept - { - assert( rhs ); - return lhs < *rhs; - } - - template< template< typename... > class TraitsLL > - [[nodiscard]] static bool greater_than( const basic_value< TraitsLL >& lhs, const basic_value< Traits >* rhs ) noexcept - { - assert( rhs ); - return lhs > *rhs; - } - }; - - template< template< typename... > class Traits > - struct traits< basic_value< Traits >* > - : traits< const basic_value< Traits >* > - { - }; - - template< typename T > - struct traits< std::optional< T > > - { - template< template< typename... > class Traits > - using default_key = typename Traits< T >::template default_key< Traits >; - - template< template< typename... > class Traits > - [[nodiscard]] static bool is_nothing( const std::optional< T >& o ) - { - return ( !bool( o ) ) || internal::is_nothing< Traits >( *o ); // TODO: Only query o? - } - - template< template< typename... > class Traits > - [[nodiscard]] static std::optional< T > as( const basic_value< Traits >& v ) - { - if( v == null ) { - return std::nullopt; - } - return v.template as< T >(); - } - - template< template< typename... > class Traits > - static void assign( basic_value< Traits >& v, const std::optional< T >& o ) - { - if( o ) { - v.assign( *o ); - } - else { - v.set_null(); - } - } - - template< template< typename... > class Traits, typename Producer > - [[nodiscard]] static std::optional< T > consume( Producer& parser ) - { - if( parser.null() ) { - return std::nullopt; - } - return json::consume< T, Traits >( parser ); - } - - template< template< typename... > class Traits, typename Consumer > - static void produce( Consumer& c, const std::optional< T >& o ) - { - if( o ) { - json::events::produce< Traits >( c, *o ); - } - else { - json::events::produce< Traits >( c, null ); - } - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool equal( const basic_value< Traits >& lhs, const std::optional< T >& rhs ) noexcept - { - return rhs ? ( lhs == *rhs ) : ( lhs == null ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool less_than( const basic_value< Traits >& lhs, const std::optional< T >& rhs ) noexcept - { - return rhs ? ( lhs < *rhs ) : ( lhs < null ); - } - - template< template< typename... > class Traits > - [[nodiscard]] static bool greater_than( const basic_value< Traits >& lhs, const std::optional< T >& rhs ) noexcept - { - return rhs ? ( lhs > *rhs ) : ( lhs > null ); - } - }; - -} // namespace tao::json - -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - -#endif diff --git a/include/tao/json/type.hpp b/include/tao/json/type.hpp deleted file mode 100644 index bb25d29c..00000000 --- a/include/tao/json/type.hpp +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2015-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_TYPE_HPP -#define TAO_JSON_TYPE_HPP - -#include -#include -#include -#include - -#include "binary_view.hpp" - -namespace tao::json -{ - enum class type : std::size_t - { - UNINITIALIZED = 0, - NULL_, - BOOLEAN, - SIGNED, - UNSIGNED, - DOUBLE, - STRING, - STRING_VIEW, - BINARY, - BINARY_VIEW, - ARRAY, - OBJECT, - VALUE_PTR, - OPAQUE_PTR, - - VALUELESS_BY_EXCEPTION = std::variant_npos - }; - - constexpr std::string_view to_string( const type t ) - { - switch( t ) { - case type::UNINITIALIZED: - return "uninitialized"; - case type::NULL_: - return "null"; - case type::BOOLEAN: - return "boolean"; - case type::SIGNED: - return "signed"; - case type::UNSIGNED: - return "unsigned"; - case type::DOUBLE: - return "double"; - case type::STRING: - return "string"; - case type::STRING_VIEW: - return "string_view"; - case type::BINARY: - return "binary"; - case type::BINARY_VIEW: - return "binary_view"; - case type::ARRAY: - return "array"; - case type::OBJECT: - return "object"; - case type::VALUE_PTR: - return "value_ptr"; - case type::OPAQUE_PTR: - return "opaque_ptr"; - case type::VALUELESS_BY_EXCEPTION: - return "valueless_by_exception"; - } - return "unknown"; - } - - struct null_t - { - explicit constexpr null_t( int /*unused*/ ) {} - }; - - struct empty_string_t - { - explicit constexpr empty_string_t( int /*unused*/ ) {} - }; - - struct empty_binary_t - { - explicit constexpr empty_binary_t( int /*unused*/ ) {} - }; - - struct empty_array_t - { - explicit constexpr empty_array_t( int /*unused*/ ) {} - }; - - struct empty_object_t - { - constexpr explicit empty_object_t( int /*unused*/ ) {} - }; - - struct uninitialized_t - {}; - - constexpr null_t null{ 0 }; - - constexpr empty_string_t empty_string{ 0 }; - constexpr empty_binary_t empty_binary{ 0 }; - constexpr empty_array_t empty_array{ 0 }; - constexpr empty_object_t empty_object{ 0 }; - - constexpr uninitialized_t uninitialized; - -} // namespace tao::json - -#endif diff --git a/include/tao/json/ubjson.hpp b/include/tao/json/ubjson.hpp deleted file mode 100644 index bce51858..00000000 --- a/include/tao/json/ubjson.hpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_UBJSON_HPP -#define TAO_JSON_UBJSON_HPP - -#include "../json.hpp" - -#include "ubjson/consume_file.hpp" -#include "ubjson/consume_string.hpp" -#include "ubjson/from_file.hpp" -#include "ubjson/from_input.hpp" -#include "ubjson/from_string.hpp" -#include "ubjson/parts_parser.hpp" -#include "ubjson/to_stream.hpp" -#include "ubjson/to_string.hpp" - -#endif diff --git a/include/tao/json/ubjson/consume_file.hpp b/include/tao/json/ubjson/consume_file.hpp deleted file mode 100644 index 1252222b..00000000 --- a/include/tao/json/ubjson/consume_file.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_UBJSON_CONSUME_FILE_HPP -#define TAO_JSON_UBJSON_CONSUME_FILE_HPP - -#include - -#include "../external/pegtl/file_input.hpp" - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "parts_parser.hpp" - -namespace tao::json::ubjson -{ - template< typename T, template< typename... > class Traits = traits, typename F > - [[nodiscard]] T consume_file( F&& filename ) - { - ubjson::basic_parts_parser< 1 << 24, utf8_mode::check, pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); - return json::consume< T, Traits >( pp ); - } - - template< template< typename... > class Traits = traits, typename F, typename T > - void consume_file( F&& filename, T& t ) - { - ubjson::basic_parts_parser< 1 << 24, utf8_mode::check, pegtl::file_input< pegtl::tracking_mode::lazy > > pp( std::forward< F >( filename ) ); - json::consume< Traits >( pp, t ); - } - -} // namespace tao::json::ubjson - -#endif diff --git a/include/tao/json/ubjson/consume_string.hpp b/include/tao/json/ubjson/consume_string.hpp deleted file mode 100644 index 72d1ecdc..00000000 --- a/include/tao/json/ubjson/consume_string.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_UBJSON_CONSUME_STRING_HPP -#define TAO_JSON_UBJSON_CONSUME_STRING_HPP - -#include "../external/pegtl/string_input.hpp" - -#include "../consume.hpp" -#include "../forward.hpp" - -#include "parts_parser.hpp" - -namespace tao::json::ubjson -{ - template< typename T, template< typename... > class Traits = traits, typename F > - [[nodiscard]] T consume_string( F&& string ) - { - ubjson::basic_parts_parser< 1 << 24, utf8_mode::check, pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); - return json::consume< T, Traits >( pp ); - } - - template< template< typename... > class Traits = traits, typename F, typename T > - void consume_string( F&& string, T& t ) - { - ubjson::basic_parts_parser< 1 << 24, utf8_mode::check, pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > > pp( string, __FUNCTION__ ); - json::consume< Traits >( pp, t ); - } - -} // namespace tao::json::ubjson - -#endif diff --git a/include/tao/json/ubjson/events/from_file.hpp b/include/tao/json/ubjson/events/from_file.hpp deleted file mode 100644 index 580e4a63..00000000 --- a/include/tao/json/ubjson/events/from_file.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_UBJSON_EVENTS_FROM_FILE_HPP -#define TAO_JSON_UBJSON_EVENTS_FROM_FILE_HPP - -#include - -#include "../../external/pegtl/file_input.hpp" -#include "../../external/pegtl/parse.hpp" - -#include "../internal/grammar.hpp" - -namespace tao::json::ubjson::events -{ - // Events producer to parse a file containing a UBJSON string representation. - - template< typename T, typename Consumer > - void from_file( Consumer& consumer, T&& filename ) - { - pegtl::file_input< pegtl::tracking_mode::lazy > in( std::forward< T >( filename ) ); - pegtl::parse< internal::grammar >( in, consumer ); - } - -} // namespace tao::json::ubjson::events - -#endif diff --git a/include/tao/json/ubjson/events/from_input.hpp b/include/tao/json/ubjson/events/from_input.hpp deleted file mode 100644 index 3fa4ac3f..00000000 --- a/include/tao/json/ubjson/events/from_input.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_UBJSON_EVENTS_FROM_INPUT_HPP -#define TAO_JSON_UBJSON_EVENTS_FROM_INPUT_HPP - -#include - -#include "../../external/pegtl/parse.hpp" - -#include "../internal/grammar.hpp" - -namespace tao::json::ubjson::events -{ - // Events producers that parse UBJSON from a PEGTL input (or something compatible). - - template< typename Consumer, typename Input > - void from_input( Consumer& consumer, Input&& in ) - { - pegtl::parse< ubjson::internal::grammar >( std::forward< Input >( in ), consumer ); - } - - template< typename Consumer, typename Input > - void from_input_embedded( Consumer& consumer, Input&& in ) - { - pegtl::parse< ubjson::internal::embedded >( std::forward< Input >( in ), consumer ); - } - - template< typename Consumer, typename Outer, typename Input > - void from_input_nested( Consumer& consumer, const Outer& oi, Input&& in ) - { - pegtl::parse_nested< ubjson::internal::grammar >( oi, std::forward< Input >( in ), consumer ); - } - - template< typename Consumer, typename Outer, typename Input > - void from_input_embedded_nested( Consumer& consumer, const Outer& oi, Input&& in ) - { - pegtl::parse_nested< ubjson::internal::embedded >( oi, std::forward< Input >( in ), consumer ); - } - -} // namespace tao::json::ubjson::events - -#endif diff --git a/include/tao/json/ubjson/events/from_string.hpp b/include/tao/json/ubjson/events/from_string.hpp deleted file mode 100644 index de605b76..00000000 --- a/include/tao/json/ubjson/events/from_string.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_UBJSON_EVENTS_FROM_STRING_HPP -#define TAO_JSON_UBJSON_EVENTS_FROM_STRING_HPP - -#include -#include - -#include "../../external/pegtl/memory_input.hpp" - -#include "from_input.hpp" - -namespace tao::json::ubjson::events -{ - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const char* source = nullptr, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t byte_in_line = 0 ) - { - pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > in( data, data + size, source ? source : "tao::json::ubjson::from_string", byte, line, byte_in_line ); - ubjson::events::from_input( consumer, std::move( in ) ); - } - - template< typename Consumer > - void from_string( Consumer& consumer, const char* data, const std::size_t size, const std::string& source, const std::size_t byte = 0, const std::size_t line = 1, const std::size_t column = 0 ) - { - ubjson::events::from_string( consumer, data, size, source.c_str(), byte, line, column ); - } - - template< typename Consumer, typename... Ts > - void from_string( Consumer& consumer, const std::string_view data, Ts&&... ts ) - { - ubjson::events::from_string( consumer, data.data(), data.size(), std::forward< Ts >( ts )... ); - } - -} // namespace tao::json::ubjson::events - -#endif diff --git a/include/tao/json/ubjson/events/to_stream.hpp b/include/tao/json/ubjson/events/to_stream.hpp deleted file mode 100644 index 4bc32c3c..00000000 --- a/include/tao/json/ubjson/events/to_stream.hpp +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_UBJSON_EVENTS_TO_STREAM_HPP -#define TAO_JSON_UBJSON_EVENTS_TO_STREAM_HPP - -#include -#include -#include -#include -#include - -#include "../../binary_view.hpp" - -#include "../../internal/endian.hpp" - -namespace tao::json::ubjson::events -{ - class to_stream - { - private: - std::ostream& os; - - public: - explicit to_stream( std::ostream& in_os ) noexcept - : os( in_os ) - {} - - void null() - { - os.put( 'Z' ); - } - - void boolean( const bool v ) - { - os.put( v ? 'T' : 'F' ); - } - - void number( const std::int64_t v ) - { - if( ( v >= -128 ) && ( v <= 127 ) ) { - os.put( 'i' ); - const auto x = static_cast< std::int8_t >( v ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else if( ( v >= -32768 ) && ( v <= 32767 ) ) { - os.put( 'I' ); - const std::uint16_t x = json::internal::h_to_be( std::uint16_t( v ) ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else if( ( v >= -2147483648LL ) && ( v <= 2147483647LL ) ) { - os.put( 'l' ); - const std::uint32_t x = json::internal::h_to_be( std::uint32_t( v ) ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else { - os.put( 'L' ); - const std::uint64_t x = json::internal::h_to_be( std::uint64_t( v ) ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - } - - void number( const std::uint64_t v ) - { - if( v <= 255 ) { - os.put( 'U' ); - const auto x = static_cast< std::uint8_t >( v ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else if( v <= 32767 ) { - os.put( 'I' ); - const std::uint16_t x = json::internal::h_to_be( std::uint16_t( v ) ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else if( v <= 2147483647UL ) { - os.put( 'l' ); - const std::uint32_t x = json::internal::h_to_be( std::uint32_t( v ) ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else if( v <= 9223372036854775807ULL ) { - os.put( 'L' ); - const std::uint64_t x = json::internal::h_to_be( v ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - else { - os.put( 'H' ); - os.put( 'U' ); - os.put( char( 19 ) + char( v >= 10000000000000000000ULL ) ); - os << v; - } - } - - void number( const double v ) - { - os.put( 'D' ); - const double x = json::internal::h_to_be( v ); - os.write( reinterpret_cast< const char* >( &x ), sizeof( x ) ); - } - - void string( const std::string_view v ) - { - if( ( v.size() == 1 ) && ( ( v[ 0 ] & 0x80 ) == 0 ) ) { - os.put( 'C' ); - os.put( v[ 0 ] ); - } - else { - os.put( 'S' ); - number( std::uint64_t( v.size() ) ); - os.write( v.data(), v.size() ); - } - } - - void binary( const tao::binary_view v ) - { - // NOTE: UBJSON encodes binary data as 'strongly typed array of uint8 values'. - os.write( "[$U#", 4 ); - number( std::uint64_t( v.size() ) ); - os.write( reinterpret_cast< const char* >( v.data() ), v.size() ); - } - - void begin_array() - { - os.put( '[' ); - } - - void begin_array( const std::size_t size ) - { - os.write( "[#", 2 ); - number( std::uint64_t( size ) ); - } - - void element() noexcept - {} - - void end_array() - { - os.put( ']' ); - } - - void end_array( const std::size_t /*unused*/ ) noexcept - {} - - void begin_object() - { - os.put( '{' ); - } - - void begin_object( const std::size_t size ) - { - os.write( "{#", 2 ); - number( std::uint64_t( size ) ); - } - - void key( const std::string_view v ) - { - number( std::uint64_t( v.size() ) ); - os.write( v.data(), v.size() ); - } - - void member() noexcept - {} - - void end_object() - { - os.put( '}' ); - } - - void end_object( const std::size_t /*unused*/ ) noexcept - {} - }; - -} // namespace tao::json::ubjson::events - -#endif diff --git a/include/tao/json/ubjson/events/to_string.hpp b/include/tao/json/ubjson/events/to_string.hpp deleted file mode 100644 index fbd8bbd6..00000000 --- a/include/tao/json/ubjson/events/to_string.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_UBJSON_EVENTS_TO_STRING_HPP -#define TAO_JSON_UBJSON_EVENTS_TO_STRING_HPP - -#include -#include - -#include "to_stream.hpp" - -namespace tao::json::ubjson::events -{ - struct to_string - : to_stream - { - std::ostringstream oss; - - to_string() - : to_stream( oss ) - {} - - [[nodiscard]] std::string value() const - { - return oss.str(); - } - }; - -} // namespace tao::json::ubjson::events - -#endif diff --git a/include/tao/json/ubjson/from_file.hpp b/include/tao/json/ubjson/from_file.hpp deleted file mode 100644 index 2f26c939..00000000 --- a/include/tao/json/ubjson/from_file.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_UBJSON_FROM_FILE_HPP -#define TAO_JSON_UBJSON_FROM_FILE_HPP - -#include -#include - -#include "../events/to_value.hpp" -#include "../events/transformer.hpp" - -#include "events/from_file.hpp" - -namespace tao::json::ubjson -{ - template< template< typename... > class Traits, template< typename... > class... Transformers > - [[nodiscard]] basic_value< Traits > basic_from_file( const std::string& filename ) - { - json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; - events::from_file( consumer, filename ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers > - [[nodiscard]] value from_file( const std::string& filename ) - { - return basic_from_file< traits, Transformers... >( filename ); - } - -} // namespace tao::json::ubjson - -#endif diff --git a/include/tao/json/ubjson/from_input.hpp b/include/tao/json/ubjson/from_input.hpp deleted file mode 100644 index 9d798007..00000000 --- a/include/tao/json/ubjson/from_input.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2019-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_UBJSON_FROM_INPUT_HPP -#define TAO_JSON_UBJSON_FROM_INPUT_HPP - -#include -#include - -#include "../events/to_value.hpp" -#include "../events/transformer.hpp" - -#include "events/from_input.hpp" - -namespace tao::json::ubjson -{ - template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] basic_value< Traits > basic_from_input( Ts&&... ts ) - { - json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; - ubjson::events::from_input( consumer, std::forward< Ts >( ts )... ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] value from_input( Ts&&... ts ) - { - return basic_from_input< traits, Transformers... >( std::forward< Ts >( ts )... ); - } - -} // namespace tao::json::ubjson - -#endif diff --git a/include/tao/json/ubjson/from_string.hpp b/include/tao/json/ubjson/from_string.hpp deleted file mode 100644 index 1c415680..00000000 --- a/include/tao/json/ubjson/from_string.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_UBJSON_FROM_STRING_HPP -#define TAO_JSON_UBJSON_FROM_STRING_HPP - -#include - -#include "../events/to_value.hpp" -#include "../events/transformer.hpp" - -#include "events/from_string.hpp" - -namespace tao::json::ubjson -{ - template< template< typename... > class Traits, template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] basic_value< Traits > basic_from_string( Ts&&... ts ) - { - json::events::transformer< json::events::to_basic_value< Traits >, Transformers... > consumer; - events::from_string( consumer, std::forward< Ts >( ts )... ); - return std::move( consumer.value ); - } - - template< template< typename... > class... Transformers, typename... Ts > - [[nodiscard]] value from_string( Ts&&... ts ) - { - return basic_from_string< traits, Transformers... >( std::forward< Ts >( ts )... ); - } - -} // namespace tao::json::ubjson - -#endif diff --git a/include/tao/json/ubjson/internal/grammar.hpp b/include/tao/json/ubjson/internal/grammar.hpp deleted file mode 100644 index 5f262fb5..00000000 --- a/include/tao/json/ubjson/internal/grammar.hpp +++ /dev/null @@ -1,413 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_UBJSON_INTERNAL_GRAMMAR_HPP -#define TAO_JSON_UBJSON_INTERNAL_GRAMMAR_HPP - -#include -#include - -#include "../../binary_view.hpp" -#include "../../internal/action.hpp" -#include "../../internal/endian.hpp" -#include "../../internal/errors.hpp" -#include "../../internal/grammar.hpp" -#include "../../internal/parse_util.hpp" -#include "../../utf8.hpp" - -#include "marker.hpp" - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4702 ) -#endif - -namespace tao::json -{ - namespace ubjson::internal - { - struct number - { - using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; - - template< pegtl::apply_mode A, - pegtl::rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename Consumer > - [[nodiscard]] static bool match( Input& in, Consumer& consumer ) - { - if( in.size( 2 ) && match_unsafe< A, M, Action, Control >( in, consumer ) ) { - in.discard(); - return true; - } - return false; - } - - private: - template< pegtl::apply_mode A, - pegtl::rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename Consumer > - [[nodiscard]] static bool match_unsafe( Input& in, Consumer& consumer ) - { - if( in.peek_char() == '-' ) { - in.bump_in_this_line(); - if( in.empty() || !json::internal::rules::sor_value::match_number< true, A, pegtl::rewind_mode::dontcare, Action, Control >( in, consumer ) ) { - throw pegtl::parse_error( "incomplete ubjson high-precision number", in ); - } - return true; - } - return json::internal::rules::sor_value::match_number< false, A, M, Action, Control >( in, consumer ); - } - }; - - } // namespace ubjson::internal - - namespace internal - { - // clang-format off - template<> inline const std::string errors< ubjson::internal::number >::error_message = "invalid ubjson high-precision number"; - // clang-format on - - } // namespace internal - - namespace ubjson::internal - { - template< typename Input > - [[nodiscard]] marker peek_marker( Input& in ) - { - return marker( json::internal::peek_char( in ) ); - } - - template< typename Input > - [[nodiscard]] marker read_marker( Input& in ) - { - return marker( json::internal::read_char( in ) ); - } - - template< typename Input > - [[nodiscard]] marker read_marker_unsafe( Input& in ) - { - return marker( json::internal::read_char_unsafe( in ) ); - } - - template< typename Input > - [[nodiscard]] std::int64_t read_size_read( Input& in ) - { - switch( const auto c = read_marker( in ) ) { - case marker::INT8: - return json::internal::read_big_endian_number< std::int64_t, std::int8_t >( in ); - case marker::UINT8: - return json::internal::read_big_endian_number< std::int64_t, std::uint8_t >( in ); - case marker::INT16: - return json::internal::read_big_endian_number< std::int64_t, std::int16_t >( in ); - case marker::INT32: - return json::internal::read_big_endian_number< std::int64_t, std::int32_t >( in ); - case marker::INT64: - return json::internal::read_big_endian_number< std::int64_t >( in ); - default: - throw pegtl::parse_error( "unknown ubjson size type " + std::to_string( unsigned( c ) ), in ); - } - } - - template< std::size_t L, typename Input > - [[nodiscard]] std::size_t read_size( Input& in ) - { - const auto s = read_size_read( in ); - if( s < 0 ) { - throw pegtl::parse_error( "negative ubjson size " + std::to_string( s ), in ); - } - const auto t = static_cast< std::uint64_t >( s ); - if( t > static_cast< std::uint64_t >( L ) ) { - throw pegtl::parse_error( "ubjson size exceeds limit " + std::to_string( t ), in ); - } - return static_cast< std::size_t >( t ); - } - - template< typename Result, typename Input > - [[nodiscard]] Result read_char( Input& in ) - { - if( in.empty() || ( in.peek_uint8( 0 ) > 127 ) ) { - throw pegtl::parse_error( "missing or invalid ubjson char", in ); - } - Result result( in.current(), 1 ); - in.bump_in_this_line( 1 ); - return result; - } - - template< std::size_t L, utf8_mode U, typename Result, typename Input > - [[nodiscard]] Result read_string( Input& in ) - { - const auto size = read_size< L >( in ); - return json::internal::read_string< U, Result >( in, size ); - } - - template< std::size_t L, utf8_mode V > - struct data - { - using analyze_t = pegtl::analysis::generic< pegtl::analysis::rule_type::any >; - - template< pegtl::apply_mode A, - pegtl::rewind_mode M, - template< typename... > - class Action, - template< typename... > - class Control, - typename Input, - typename Consumer > - [[nodiscard]] static bool match( Input& in, Consumer& consumer ) - { - if( !in.empty() ) { - parse_unsafe( in, consumer ); - return true; - } - return false; - } - - private: - template< typename Input, typename Consumer > - static void parse( Input& in, Consumer& consumer ) - { - parse( in, consumer, read_marker( in ) ); - } - - template< typename Input, typename Consumer > - static void parse_unsafe( Input& in, Consumer& consumer ) - { - parse( in, consumer, read_marker_unsafe( in ) ); - } - - template< typename Input, typename Consumer > - static void parse( Input& in, Consumer& consumer, const marker c ) - { - switch( c ) { - case marker::NULL_: - consumer.null(); - break; - case marker::TRUE_: - consumer.boolean( true ); - break; - case marker::FALSE_: - consumer.boolean( false ); - break; - case marker::INT8: - consumer.number( json::internal::read_big_endian_number< std::int64_t, std::int8_t >( in ) ); - break; - case marker::UINT8: - consumer.number( json::internal::read_big_endian_number< std::uint64_t, std::uint8_t >( in ) ); - break; - case marker::INT16: - consumer.number( json::internal::read_big_endian_number< std::int64_t, std::int16_t >( in ) ); - break; - case marker::INT32: - consumer.number( json::internal::read_big_endian_number< std::int64_t, std::int32_t >( in ) ); - break; - case marker::INT64: - consumer.number( json::internal::read_big_endian_number< std::int64_t >( in ) ); - break; - case marker::FLOAT32: - consumer.number( json::internal::read_big_endian_number< double, float >( in ) ); - break; - case marker::FLOAT64: - consumer.number( json::internal::read_big_endian_number< double >( in ) ); - break; - case marker::HIGH_PRECISION: - parse_high_precision( in, consumer ); - break; - case marker::CHAR: - consumer.string( read_char< std::string_view >( in ) ); - break; - case marker::STRING: - consumer.string( read_string< L, V, std::string_view >( in ) ); - break; - case marker::BEGIN_ARRAY: - parse_array( in, consumer ); - break; - case marker::BEGIN_OBJECT: - parse_object( in, consumer ); - break; - case marker::NO_OP: - throw pegtl::parse_error( "unsupported ubjson no-op", in ); - default: - throw pegtl::parse_error( "unknown ubjson type " + std::to_string( unsigned( c ) ), in ); - } - } - - template< typename Input, typename Consumer > - static void parse_high_precision( Input& in, Consumer& consumer ) - { - const auto size = read_size< L >( in ); - json::internal::throw_on_empty( in, size ); - pegtl::memory_input< pegtl::tracking_mode::lazy, pegtl::eol::lf_crlf, const char* > i2( in.current(), in.current() + size, "UBJSON" ); - pegtl::parse_nested< pegtl::must< number, pegtl::eof >, json::internal::action, json::internal::errors >( in, i2, consumer ); - in.bump_in_this_line( size ); - } - - template< typename Input, typename Consumer > - static void parse_array( Input& in, Consumer& consumer ) - { - switch( peek_marker( in ) ) { - case marker::CONTAINER_SIZE: - in.bump_in_this_line( 1 ); - parse_sized_array( in, consumer ); - break; - case marker::CONTAINER_TYPE: - in.bump_in_this_line( 1 ); - parse_typed_array( in, consumer ); - break; - default: - parse_basic_array( in, consumer ); - break; - } - } - - template< typename Input, typename Consumer > - static void parse_sized_array( Input& in, Consumer& consumer ) - { - const auto size = read_size< L >( in ); - consumer.begin_array( size ); - for( std::size_t i = 0; i < size; ++i ) { - parse( in, consumer ); - consumer.element(); - } - consumer.end_array( size ); - } - - template< typename Input, typename Consumer > - static void parse_typed_array( Input& in, Consumer& consumer ) - { - const auto c = read_marker( in ); - if( read_marker( in ) != marker::CONTAINER_SIZE ) { - throw pegtl::parse_error( "ubjson array type not followed by size", in ); - } - if( c == marker::UINT8 ) { - // NOTE: UBJSON encodes binary data as 'strongly typed array of uint8 values'. - consumer.binary( read_string< L, utf8_mode::trust, tao::binary_view >( in ) ); - return; - } - const auto size = read_size< L >( in ); - consumer.begin_array( size ); - for( std::size_t i = 0; i < size; ++i ) { - parse( in, consumer, c ); - consumer.element(); - } - consumer.end_array( size ); - } - - template< typename Input, typename Consumer > - static void parse_basic_array( Input& in, Consumer& consumer ) - { - consumer.begin_array(); - while( peek_marker( in ) != marker::END_ARRAY ) { - parse_unsafe( in, consumer ); - consumer.element(); - } - in.bump_in_this_line( 1 ); - consumer.end_array(); - } - - template< typename Input, typename Consumer > - static void parse_key( Input& in, Consumer& consumer ) - { - consumer.key( read_string< L, V, std::string_view >( in ) ); - } - - template< typename Input, typename Consumer > - static void parse_object( Input& in, Consumer& consumer ) - { - switch( peek_marker( in ) ) { - case marker::CONTAINER_SIZE: - in.bump_in_this_line( 1 ); - parse_sized_object( in, consumer ); - break; - case marker::CONTAINER_TYPE: - in.bump_in_this_line( 1 ); - parse_typed_object( in, consumer ); - break; - default: - parse_basic_object( in, consumer ); - break; - } - } - - template< typename Input, typename Consumer > - static void parse_sized_object( Input& in, Consumer& consumer ) - { - const auto size = read_size< L >( in ); - consumer.begin_object( size ); - for( std::size_t i = 0; i < size; ++i ) { - parse_key( in, consumer ); - parse( in, consumer ); - consumer.member(); - } - consumer.end_object( size ); - } - - template< typename Input, typename Consumer > - static void parse_typed_object( Input& in, Consumer& consumer ) - { - const auto c = read_marker( in ); - if( read_marker( in ) != marker::CONTAINER_SIZE ) { - throw pegtl::parse_error( "ubjson object type not followed by size", in ); - } - const auto size = read_size< L >( in ); - consumer.begin_object( size ); - for( std::size_t i = 0; i < size; ++i ) { - parse_key( in, consumer ); - parse( in, consumer, c ); - consumer.member(); - } - consumer.end_object( size ); - } - - template< typename Input, typename Consumer > - static void parse_basic_object( Input& in, Consumer& consumer ) - { - consumer.begin_object(); - while( peek_marker( in ) != marker::END_OBJECT ) { - parse_key( in, consumer ); - parse( in, consumer ); - consumer.member(); - } - in.bump_in_this_line( 1 ); - consumer.end_object(); - } - }; - - struct nops - : pegtl::star< pegtl::one< char( marker::NO_OP ) > > - { - }; - - template< std::size_t L, utf8_mode V > - struct basic_grammar - : pegtl::must< nops, data< L, V >, nops, pegtl::eof > - { - }; - - template< std::size_t L, utf8_mode V > - struct basic_embedded - : pegtl::must< data< L, V > > - { - }; - - using grammar = basic_grammar< 1 << 24, utf8_mode::check >; - using embedded = basic_embedded< 1 << 24, utf8_mode::check >; - - } // namespace ubjson::internal - -} // namespace tao::json - -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - -#endif diff --git a/include/tao/json/ubjson/internal/marker.hpp b/include/tao/json/ubjson/internal/marker.hpp deleted file mode 100644 index 3b6d242b..00000000 --- a/include/tao/json/ubjson/internal/marker.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_UBJSON_INTERNAL_MARKER_HPP -#define TAO_JSON_UBJSON_INTERNAL_MARKER_HPP - -#include - -namespace tao::json::ubjson::internal -{ - enum class marker : char - { - NULL_ = 'Z', - - NO_OP = 'N', - - TRUE_ = 'T', - FALSE_ = 'F', - - INT8 = 'i', - UINT8 = 'U', - INT16 = 'I', - INT32 = 'l', - INT64 = 'L', - - FLOAT32 = 'd', - FLOAT64 = 'D', - - HIGH_PRECISION = 'H', - - CHAR = 'C', - STRING = 'S', - - BEGIN_ARRAY = '[', - END_ARRAY = ']', - - BEGIN_OBJECT = '{', - END_OBJECT = '}', - - CONTAINER_SIZE = '#', - CONTAINER_TYPE = '$' - }; - -} // namespace tao::json::ubjson::internal - -#endif diff --git a/include/tao/json/ubjson/parts_parser.hpp b/include/tao/json/ubjson/parts_parser.hpp deleted file mode 100644 index 4f53ce08..00000000 --- a/include/tao/json/ubjson/parts_parser.hpp +++ /dev/null @@ -1,393 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_UBJSON_PARTS_PARSER_HPP -#define TAO_JSON_UBJSON_PARTS_PARSER_HPP - -#include -#include - -#include "../events/discard.hpp" -#include "../external/pegtl/string_input.hpp" -#include "../utf8.hpp" - -#include "internal/grammar.hpp" - -namespace tao::json::ubjson -{ - namespace internal - { - template< typename Input > - [[nodiscard]] bool read_boolean( Input& in ) - { - const auto b = peek_marker( in ); - switch( b ) { - case marker::TRUE_: - in.bump_in_this_line( 1 ); - return true; - case marker::FALSE_: - in.bump_in_this_line( 1 ); - return false; - default: - throw pegtl::parse_error( "expected boolean", in ); - } - std::abort(); - } - - template< typename Input > - [[nodiscard]] std::int64_t read_signed( Input& in ) - { - const auto b = peek_marker( in ); - switch( format( b ) ) { - case marker::INT8: - return json::internal::read_big_endian_number< std::int64_t, std::int8_t >( in, 1 ); - case marker::UINT8: - return json::internal::read_big_endian_number< std::int64_t, std::uint8_t >( in, 1 ); - case marker::INT16: - return json::internal::read_big_endian_number< std::int64_t, std::int16_t >( in, 1 ); - case marker::INT32: - return json::internal::read_big_endian_number< std::int64_t, std::int32_t >( in, 1 ); - case marker::INT64: - return json::internal::read_big_endian_number< std::int64_t >( in, 1 ); - default: - throw pegtl::parse_error( "expected signed number", in ); - } - } - - [[nodiscard]] inline std::uint64_t test_unsigned( const std::int64_t i ) - { - if( i < 0 ) { - throw std::runtime_error( "negative number for unsigned" ); - } - return std::uint64_t( i ); - } - - template< typename Input > - [[nodiscard]] std::uint64_t read_unsigned( Input& in ) - { - const auto b = peek_marker( in ); - switch( b ) { - case marker::INT8: - return test_unsigned( json::internal::read_big_endian_number< std::int64_t, std::int8_t >( in, 1 ) ); - case marker::UINT8: - return json::internal::read_big_endian_number< std::uint64_t, std::uint8_t >( in, 1 ); - case marker::INT16: - return test_unsigned( json::internal::read_big_endian_number< std::int64_t, std::int16_t >( in, 1 ) ); - case marker::INT32: - return test_unsigned( json::internal::read_big_endian_number< std::int64_t, std::int32_t >( in, 1 ) ); - case marker::INT64: - return test_unsigned( json::internal::read_big_endian_number< std::int64_t >( in, 1 ) ); - default: - throw pegtl::parse_error( "expected positive number", in ); - } - } - - template< typename Input > - [[nodiscard]] double read_double( Input& in ) - { - switch( peek_marker( in ) ) { - case marker::FLOAT32: - return json::internal::read_big_endian_number< double, float >( in, 1 ); - case marker::FLOAT64: - return json::internal::read_big_endian_number< double >( in, 1 ); - default: - throw pegtl::parse_error( "expected floating point number", in ); - } - } - - template< utf8_mode V, typename Result, typename Input > - [[nodiscard]] Result read_string_or_char( Input& in ) - { - const auto b = read_marker( in ); - switch( b ) { - case marker::CHAR: - return internal::read_char< Result >( in ); - case marker::STRING: - return internal::read_string< V, Result >( in ); - default: - throw pegtl::parse_error( "expected string (or char)", in ); - } - } - - } // namespace internal - - template< std::size_t L, utf8_mode V = utf8_mode::check, typename Input = pegtl::string_input< pegtl::tracking_mode::lazy > > - class basic_parts_parser - { - public: - template< typename... Ts > - explicit basic_parts_parser( Ts&&... ts ) - : m_input( std::forward< Ts >( ts )... ) - {} - - [[nodiscard]] bool empty() - { - return m_input.empty(); - } - - [[nodiscard]] bool null() - { - if( internal::peek_marker( m_input ) == internal::marker::NULL_ ) { - m_input.bump_in_this_line( 1 ); - return true; - } - return false; - } - - [[nodiscard]] bool boolean() - { - return internal::read_boolean( m_input ); - } - - void check_marker( const internal::marker m, const char* e ) - { - const auto b = internal::peek_marker( m_input ); - if( b != m ) { - throw pegtl::parse_error( e, m_input ); - } - m_input.bump_in_this_line(); - } - - [[nodiscard]] std::string_view string() - { - return internal::read_string_or_char< V, std::string_view >( m_input ); - } - - [[nodiscard]] tao::binary_view binary() - { - check_marker( internal::marker::BEGIN_ARRAY, "expected array for binary" ); - check_marker( internal::marker::CONTAINER_TYPE, "expected typed array for binary" ); - check_marker( internal::marker::UINT8, "expected type uint8 for array for binary" ); - check_marker( internal::marker::CONTAINER_SIZE, "expected sized array for binary" ); - const auto size = internal::read_size< L >( m_input ); - return json::internal::read_string< utf8_mode::trust, tao::binary_view >( m_input, size ); - } - - [[nodiscard]] std::string_view key() - { - return string(); - } - - [[nodiscard]] std::int64_t number_signed() - { - return internal::read_signed( m_input ); - } - - [[nodiscard]] std::uint64_t number_unsigned() - { - return internal::read_unsigned( m_input ); - } - - [[nodiscard]] double number_double() - { - return internal::read_double( m_input ); - } - - struct state_t - { - state_t() = default; - - explicit state_t( const std::size_t in_size ) - : size( in_size ) - {} - - std::size_t i = 0; - std::optional< std::size_t > size; - }; - - template< internal::marker Begin, internal::marker End > - [[nodiscard]] state_t begin_container( const char* e ) - { - check_marker( Begin, e ); - const auto b = internal::peek_marker( m_input ); - switch( b ) { - case End: - return state_t( 0 ); - case internal::marker::CONTAINER_TYPE: - throw pegtl::parse_error( "typed ubjson containers not implemented", m_input ); - case internal::marker::CONTAINER_SIZE: - m_input.bump_in_this_line( 1 ); - return state_t( number_unsigned() ); - default: - return state_t(); - } - } - - [[nodiscard]] state_t begin_array() - { - return begin_container< internal::marker::BEGIN_ARRAY, internal::marker::END_ARRAY >( "expected array" ); - } - - [[nodiscard]] state_t begin_object() - { - return begin_container< internal::marker::BEGIN_OBJECT, internal::marker::END_OBJECT >( "expected object" ); - } - - void end_array_sized( const state_t& p ) - { - if( *p.size != p.i ) { - throw pegtl::parse_error( "array size mismatch", m_input ); - } - } - - void end_object_sized( const state_t& p ) - { - if( *p.size != p.i ) { - throw pegtl::parse_error( "object size mismatch", m_input ); - } - } - - void end_array_indefinite( const state_t& /*unused*/ ) - { - if( internal::peek_marker( m_input ) != internal::marker::END_ARRAY ) { - throw pegtl::parse_error( "array not at end", m_input ); - } - m_input.bump_in_this_line( 1 ); - } - - void end_object_indefinite( const state_t& /*unused*/ ) - { - if( internal::peek_marker( m_input ) != internal::marker::END_OBJECT ) { - throw pegtl::parse_error( "object not at end", m_input ); - } - m_input.bump_in_this_line( 1 ); - } - - void end_array( const state_t& p ) - { - if( p.size ) { - end_array_sized( p ); - } - else { - end_array_indefinite( p ); - } - } - - void end_object( const state_t& p ) - { - if( p.size ) { - end_object_sized( p ); - } - else { - end_object_indefinite( p ); - } - } - - void element_sized( state_t& p ) - { - if( p.i++ >= *p.size ) { - throw pegtl::parse_error( "unexpected array end", m_input ); - } - } - - void member_sized( state_t& p ) - { - if( p.i++ >= *p.size ) { - throw pegtl::parse_error( "unexpected object end", m_input ); - } - } - - void element_indefinite( state_t& /*unused*/ ) - { - if( internal::peek_marker( m_input ) == internal::marker::END_ARRAY ) { - throw pegtl::parse_error( "unexpected array end", m_input ); - } - } - - void member_indefinite( state_t& /*unused*/ ) - { - if( internal::peek_marker( m_input ) == internal::marker::END_OBJECT ) { - throw pegtl::parse_error( "unexpected object end", m_input ); - } - } - - void element( state_t& p ) - { - if( p.size ) { - element_sized( p ); - } - else { - element_indefinite( p ); - } - } - - void member( state_t& p ) - { - if( p.size ) { - member_sized( p ); - } - else { - member_indefinite( p ); - } - } - - [[nodiscard]] bool element_or_end_array_sized( state_t& p ) - { - return p.i++ < *p.size; - } - - [[nodiscard]] bool member_or_end_object_sized( state_t& p ) - { - return p.i++ < *p.size; - } - - [[nodiscard]] bool element_or_end_array_indefinite( const state_t& /*unused*/ ) - { - if( internal::peek_marker( m_input ) == internal::marker::END_ARRAY ) { - m_input.bump_in_this_line( 1 ); - return false; - } - return true; - } - - [[nodiscard]] bool member_or_end_object_indefinite( const state_t& /*unused*/ ) - { - if( internal::peek_marker( m_input ) == internal::marker::END_OBJECT ) { - m_input.bump_in_this_line( 1 ); - return false; - } - return true; - } - - [[nodiscard]] bool element_or_end_array( state_t& p ) - { - if( p.size ) { - return element_or_end_array_sized( p ); - } - return element_or_end_array_indefinite( p ); - } - - [[nodiscard]] bool member_or_end_object( state_t& p ) - { - if( p.size ) { - return member_or_end_object_sized( p ); - } - return member_or_end_object_indefinite( p ); - } - - void skip_value() - { - json::events::discard consumer; // TODO: Optimise to not generate events (which requires preparing their - discarded - arguments)? - pegtl::parse< pegtl::must< internal::data< L, V > > >( m_input, consumer ); - } - - [[nodiscard]] auto mark() - { - return m_input.template mark< pegtl::rewind_mode::required >(); - } - - template< typename T > - void throw_parse_error( T&& t ) const - { - throw pegtl::parse_error( std::forward< T >( t ), m_input ); - } - - protected: - Input m_input; - }; - - using parts_parser = basic_parts_parser< 1 << 24 >; - -} // namespace tao::json::ubjson - -#endif diff --git a/include/tao/json/ubjson/to_stream.hpp b/include/tao/json/ubjson/to_stream.hpp deleted file mode 100644 index d278f07f..00000000 --- a/include/tao/json/ubjson/to_stream.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_UBJSON_TO_STREAM_HPP -#define TAO_JSON_UBJSON_TO_STREAM_HPP - -#include - -#include "../value.hpp" - -#include "../events/from_value.hpp" -#include "../events/non_finite_to_null.hpp" -#include "../events/transformer.hpp" - -#include "events/to_stream.hpp" - -namespace tao::json::ubjson -{ - template< template< typename... > class... Transformers, template< typename... > class Traits > - void to_stream( std::ostream& os, const basic_value< Traits >& v ) - { - json::events::transformer< events::to_stream, Transformers..., json::events::non_finite_to_null > consumer( os ); - json::events::from_value( consumer, v ); - } - -} // namespace tao::json::ubjson - -#endif diff --git a/include/tao/json/ubjson/to_string.hpp b/include/tao/json/ubjson/to_string.hpp deleted file mode 100644 index 7afe0cb8..00000000 --- a/include/tao/json/ubjson/to_string.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_UBJSON_TO_STRING_HPP -#define TAO_JSON_UBJSON_TO_STRING_HPP - -#include - -#include "../value.hpp" - -#include "../events/from_value.hpp" -#include "../events/non_finite_to_null.hpp" -#include "../events/transformer.hpp" - -#include "events/to_string.hpp" - -namespace tao::json::ubjson -{ - template< template< typename... > class... Transformers, template< typename... > class Traits > - [[nodiscard]] std::string to_string( const basic_value< Traits >& v ) - { - json::events::transformer< events::to_string, Transformers..., json::events::non_finite_to_null > consumer; - json::events::from_value( consumer, v ); - return consumer.value(); - } - -} // namespace tao::json::ubjson - -#endif diff --git a/include/tao/json/utf8.hpp b/include/tao/json/utf8.hpp deleted file mode 100644 index 18f139fe..00000000 --- a/include/tao/json/utf8.hpp +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_UTF8_HPP -#define TAO_JSON_UTF8_HPP - -#include "external/pegtl/memory_input.hpp" -#include "external/pegtl/parse.hpp" -#include "external/pegtl/rules.hpp" -#include "external/pegtl/utf8.hpp" - -namespace tao::json -{ - enum class utf8_mode : bool - { - check, - trust - }; - - namespace internal - { - template< typename Input > - bool consume_utf8_impl( Input& in, const std::size_t todo ) - { - std::size_t i = 0; - while( i < todo ) { - const auto p = pegtl::internal::peek_utf8::peek( in, pegtl::internal::peek_utf8::max_input_size ).size; - if( ( p == 0 ) || ( ( i += p ) > todo ) ) { - return false; - } - in.bump_in_this_line( p ); - } - return true; - } - - template< utf8_mode M, typename Input > - void consume_utf8_throws( Input& in, const std::size_t todo ) - { - if constexpr( M == utf8_mode::trust ) { - in.bump_in_this_line( todo ); - } - else if( !consume_utf8_impl( in, todo ) ) { - throw pegtl::parse_error( "invalid utf8", in ); - } - } - - inline bool validate_utf8_nothrow( const std::string_view sv ) noexcept - { - pegtl::memory_input in( sv, "validate_utf8" ); - return consume_utf8_impl( in, sv.size() ); - } - - } // namespace internal - -} // namespace tao::json - -#endif diff --git a/include/tao/json/value.hpp b/include/tao/json/value.hpp deleted file mode 100644 index df8453ec..00000000 --- a/include/tao/json/value.hpp +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2017-2020 Dr. Colin Hirsch and Daniel Frey -// Please see LICENSE for license or visit https://github.com/taocpp/json/ - -#ifndef TAO_JSON_VALUE_HPP -#define TAO_JSON_VALUE_HPP - -#include "basic_value.hpp" -#include "forward.hpp" -#include "operators.hpp" -#include "traits.hpp" - -#endif From 63591037e2d29f6cfdd9f3bf37e7ab49a1348496 Mon Sep 17 00:00:00 2001 From: Jan Christoph Uhde Date: Mon, 17 Feb 2020 20:55:28 +0100 Subject: [PATCH 7/7] Try to restore travis build. --- .gitignore | 1 + .travis.yml | 6 ++++++ CMakeLists.txt | 12 +++++++++++- scripts/travis-build.sh | 5 ++++- 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 054f1ccf..3cee37df 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ bench vpack-to-json json-to-vpack +taocpp-json core AsmTest *.o diff --git a/.travis.yml b/.travis.yml index 627a0bbc..53495a16 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,6 +46,7 @@ matrix: - build_type=Release - SANITIZER=false - CXX_STANDARD=17 + - TAO=ON addons: apt: packages: ['gcc-8', 'g++-8', 'cmake'] @@ -92,6 +93,7 @@ matrix: #build settings - build_type=Release - CXX_STANDARD=17 + - TAO=ON addons: apt: sources: @@ -105,12 +107,16 @@ matrix: compiler: clang env: - build_type=Release + - TAO=ON install: + - git clone https://github.com/taocpp/json.git taocpp-json + - ( cd taocpp-json; git checkout 631095f4bfa45c63af5ccc1cb35ea16eb9ead450; ) - export CXX=$CXX - export CC=$CC - export CXX_STANDARD=${CXX_STANDARD:-17} - export BUILD_TYPE=${build_type} + - export TAO=${TAO:-OFF} - cmake --version - $CXX --version diff --git a/CMakeLists.txt b/CMakeLists.txt index ea801917..d775f421 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,15 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Mo option(BuildVelocyPackExamples "Build examples" ON) option(Maintainer "Build maintainer tools" OFF) +option(TaoJson "Add support for taocpp::json" OFF) + +if(TaoJson) + if(NOT TARGET taocpp::json) + set(TAOCPP_JSON_BUILD_TESTS OFF CACHE BOOL "Build test programs" FORCE) + set(TAOCPP_JSON_BUILD_EXAMPLES OFF CACHE BOOL "Build example programs" FORCE) + add_subdirectory(taocpp-json EXCLUDE_FROM_ALL) + endif() +endif() set(HashType "xxhash" CACHE STRING "Hash type (fasthash, xxhash)" ) @@ -44,7 +53,7 @@ set(VELOCY_SOURCE src/Iterator.cpp src/Options.cpp src/Parser.cpp - src/TaoParser.cpp + $<$:src/TaoParser.cpp> src/Serializable.cpp src/Slice.cpp src/SliceStaticData.cpp @@ -80,6 +89,7 @@ message(STATUS "Building with hash type: ${HashType}") add_library(velocypack STATIC ${VELOCY_SOURCE}) target_include_directories(velocypack PRIVATE src) target_include_directories(velocypack PUBLIC include) +target_link_libraries(velocypack PUBLIC $<$:taocpp::json>) if(Maintainer) add_executable(buildVersion scripts/build-version.cpp) diff --git a/scripts/travis-build.sh b/scripts/travis-build.sh index 18128f6c..381c0754 100755 --- a/scripts/travis-build.sh +++ b/scripts/travis-build.sh @@ -16,14 +16,17 @@ if [[ $TRAVIS_OS_NAME == "linux" ]]; then fi echo "Building with C++ Standard $CXX_STANDARD" +echo "TaoJson support: $TAO" mkdir -p build && cd build || ferr "could not create build dir" +set -x cmake -DCMAKE_BUILD_TYPE=Release -DHashType=xxhash \ -DBuildTests=ON -DBuildLargeTests=OFF -DBuildVelocyPackExamples=ON \ - -DBuildTools=ON -DEnableSSE=OFF \ + -DBuildTools=ON -DEnableSSE=OFF -DTaoJson="$TAO" \ -DCMAKE_CXX_STANDARD=${CXX_STANDARD} \ .. || ferr "failed to configure" +set +x make -j $threads || ferr "failed to build" echo Done.