jsoncons 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/jsoncons/extconf.rb +43 -0
- data/ext/jsoncons/jsoncons.cpp +161 -0
- data/ext/jsoncons/jsoncons.h +10 -0
- data/jsoncons.gemspec +44 -0
- data/lib/jsoncons/jsoncons/examples/input/address-book.json +13 -0
- data/lib/jsoncons/jsoncons/examples/input/books.json +28 -0
- data/lib/jsoncons/jsoncons/examples/input/countries.json +7 -0
- data/lib/jsoncons/jsoncons/examples/input/employees.json +30 -0
- data/lib/jsoncons/jsoncons/examples/input/jsonschema/name.json +15 -0
- data/lib/jsoncons/jsoncons/examples/input/multiple-json-objects.json +3 -0
- data/lib/jsoncons/jsoncons/examples/input/sales.csv +6 -0
- data/lib/jsoncons/jsoncons/examples/input/store.json +28 -0
- data/lib/jsoncons/jsoncons/examples/input/tasks.csv +6 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/allocator_holder.hpp +38 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/basic_json.hpp +5905 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/bigint.hpp +1611 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/byte_string.hpp +820 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/binary_config.hpp +226 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/compiler_support.hpp +375 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/jsoncons_config.hpp +309 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/version.hpp +40 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/conv_error.hpp +218 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/decode_json.hpp +209 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/decode_traits.hpp +651 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/endian.hpp +44 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/grisu3.hpp +312 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/optional.hpp +483 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/parse_number.hpp +1133 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/span.hpp +188 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_view.hpp +537 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_wrapper.hpp +370 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/write_number.hpp +567 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/encode_json.hpp +315 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/encode_traits.hpp +378 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json.hpp +18 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_array.hpp +324 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_content_handler.hpp +12 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_cursor.hpp +448 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_decoder.hpp +420 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_encoder.hpp +1587 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_error.hpp +156 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_exception.hpp +241 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_filter.hpp +653 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_fwd.hpp +23 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_object.hpp +1772 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_options.hpp +862 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_parser.hpp +2900 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_reader.hpp +731 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros.hpp +1072 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros_deprecated.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_type.hpp +206 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_type_traits.hpp +1830 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor.hpp +1560 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor2.hpp +2079 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/pretty_print.hpp +89 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/ser_context.hpp +62 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/sink.hpp +289 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/source.hpp +777 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/source_adaptor.hpp +148 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/staj2_cursor.hpp +1189 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/staj_cursor.hpp +1254 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/staj_iterator.hpp +449 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/tag_type.hpp +245 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/text_source_adaptor.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/traits_extension.hpp +884 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/typed_array_view.hpp +250 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/unicode_traits.hpp +1330 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/uri.hpp +635 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/value_converter.hpp +340 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson.hpp +23 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_cursor.hpp +320 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_decimal128.hpp +865 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_encoder.hpp +585 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_error.hpp +103 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_oid.hpp +245 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_options.hpp +75 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_parser.hpp +645 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_reader.hpp +92 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_type.hpp +44 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/decode_bson.hpp +201 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/encode_bson.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor.hpp +26 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor.hpp +351 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor2.hpp +265 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_detail.hpp +93 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_encoder.hpp +1766 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_error.hpp +105 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_options.hpp +113 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_parser.hpp +1942 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_reader.hpp +116 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/decode_cbor.hpp +203 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/encode_cbor.hpp +151 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv.hpp +17 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_cursor.hpp +358 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_encoder.hpp +954 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_error.hpp +85 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_options.hpp +973 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_parser.hpp +2099 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_reader.hpp +348 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_serializer.hpp +12 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/decode_csv.hpp +208 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/encode_csv.hpp +122 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath.hpp +5215 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath_error.hpp +215 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch.hpp +579 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch_error.hpp +121 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/expression.hpp +3329 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/flatten.hpp +432 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_location.hpp +445 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_query.hpp +115 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath.hpp +13 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_error.hpp +240 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_expression.hpp +2612 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_selector.hpp +1322 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer.hpp +1577 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer_error.hpp +119 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/format_validator.hpp +968 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/json_validator.hpp +120 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema.hpp +13 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_error.hpp +105 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_version.hpp +18 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator.hpp +1745 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator_factory.hpp +556 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_draft7.hpp +198 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_location.hpp +200 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_version.hpp +35 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/subschema.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/mergepatch/mergepatch.hpp +103 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/decode_msgpack.hpp +202 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/encode_msgpack.hpp +142 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack.hpp +24 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor.hpp +343 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor2.hpp +259 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_encoder.hpp +753 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_error.hpp +94 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_options.hpp +74 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_parser.hpp +748 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_reader.hpp +116 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_type.hpp +63 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/decode_ubjson.hpp +201 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/encode_ubjson.hpp +142 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson.hpp +23 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_cursor.hpp +307 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_encoder.hpp +502 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_error.hpp +100 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_options.hpp +87 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_parser.hpp +880 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_reader.hpp +92 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_type.hpp +43 -0
- data/lib/jsoncons/version.rb +5 -0
- data/lib/jsoncons.rb +33 -0
- data/test/jsoncons_test.rb +108 -0
- data/test/test_helper.rb +7 -0
- metadata +268 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// Copyright 2017 Daniel Parker
|
|
2
|
+
// Distributed under the Boost license, Version 1.0.
|
|
3
|
+
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
4
|
+
|
|
5
|
+
// See https://github.com/danielaparker/jsoncons for latest version
|
|
6
|
+
|
|
7
|
+
#ifndef JSONCONS_MSGPACK_MSGPACK_READER_HPP
|
|
8
|
+
#define JSONCONS_MSGPACK_MSGPACK_READER_HPP
|
|
9
|
+
|
|
10
|
+
#include <string>
|
|
11
|
+
#include <vector>
|
|
12
|
+
#include <memory>
|
|
13
|
+
#include <utility> // std::move
|
|
14
|
+
#include <jsoncons/json.hpp>
|
|
15
|
+
#include <jsoncons/source.hpp>
|
|
16
|
+
#include <jsoncons/json_visitor.hpp>
|
|
17
|
+
#include <jsoncons/config/jsoncons_config.hpp>
|
|
18
|
+
#include <jsoncons_ext/msgpack/msgpack_type.hpp>
|
|
19
|
+
#include <jsoncons_ext/msgpack/msgpack_error.hpp>
|
|
20
|
+
#include <jsoncons_ext/msgpack/msgpack_parser.hpp>
|
|
21
|
+
|
|
22
|
+
namespace jsoncons { namespace msgpack {
|
|
23
|
+
|
|
24
|
+
template <class Source,class Allocator=std::allocator<char>>
|
|
25
|
+
class basic_msgpack_reader
|
|
26
|
+
{
|
|
27
|
+
using char_type = char;
|
|
28
|
+
|
|
29
|
+
basic_msgpack_parser<Source,Allocator> parser_;
|
|
30
|
+
basic_json_visitor2_to_visitor_adaptor<char_type,Allocator> adaptor_;
|
|
31
|
+
json_visitor2& visitor_;
|
|
32
|
+
public:
|
|
33
|
+
template <class Sourceable>
|
|
34
|
+
basic_msgpack_reader(Sourceable&& source,
|
|
35
|
+
json_visitor& visitor,
|
|
36
|
+
const Allocator alloc)
|
|
37
|
+
: basic_msgpack_reader(std::forward<Sourceable>(source),
|
|
38
|
+
visitor,
|
|
39
|
+
msgpack_decode_options(),
|
|
40
|
+
alloc)
|
|
41
|
+
{
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
template <class Sourceable>
|
|
45
|
+
basic_msgpack_reader(Sourceable&& source,
|
|
46
|
+
json_visitor& visitor,
|
|
47
|
+
const msgpack_decode_options& options = msgpack_decode_options(),
|
|
48
|
+
const Allocator alloc=Allocator())
|
|
49
|
+
: parser_(std::forward<Sourceable>(source), options, alloc),
|
|
50
|
+
adaptor_(visitor, alloc), visitor_(adaptor_)
|
|
51
|
+
{
|
|
52
|
+
}
|
|
53
|
+
template <class Sourceable>
|
|
54
|
+
basic_msgpack_reader(Sourceable&& source,
|
|
55
|
+
json_visitor2& visitor,
|
|
56
|
+
const Allocator alloc)
|
|
57
|
+
: basic_msgpack_reader(std::forward<Sourceable>(source),
|
|
58
|
+
visitor,
|
|
59
|
+
msgpack_decode_options(),
|
|
60
|
+
alloc)
|
|
61
|
+
{
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
template <class Sourceable>
|
|
65
|
+
basic_msgpack_reader(Sourceable&& source,
|
|
66
|
+
json_visitor2& visitor,
|
|
67
|
+
const msgpack_decode_options& options = msgpack_decode_options(),
|
|
68
|
+
const Allocator alloc=Allocator())
|
|
69
|
+
: parser_(std::forward<Sourceable>(source), options, alloc),
|
|
70
|
+
visitor_(visitor)
|
|
71
|
+
{
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
void read()
|
|
75
|
+
{
|
|
76
|
+
std::error_code ec;
|
|
77
|
+
read(ec);
|
|
78
|
+
if (ec)
|
|
79
|
+
{
|
|
80
|
+
JSONCONS_THROW(ser_error(ec,line(),column()));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
void read(std::error_code& ec)
|
|
85
|
+
{
|
|
86
|
+
parser_.reset();
|
|
87
|
+
parser_.parse(visitor_, ec);
|
|
88
|
+
if (ec)
|
|
89
|
+
{
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
std::size_t line() const
|
|
95
|
+
{
|
|
96
|
+
return parser_.line();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
std::size_t column() const
|
|
100
|
+
{
|
|
101
|
+
return parser_.column();
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
using msgpack_stream_reader = basic_msgpack_reader<jsoncons::binary_stream_source>;
|
|
106
|
+
|
|
107
|
+
using msgpack_bytes_reader = basic_msgpack_reader<jsoncons::bytes_source>;
|
|
108
|
+
|
|
109
|
+
#if !defined(JSONCONS_NO_DEPRECATED)
|
|
110
|
+
JSONCONS_DEPRECATED_MSG("Instead, use msgpack_stream_reader") typedef msgpack_stream_reader msgpack_reader;
|
|
111
|
+
JSONCONS_DEPRECATED_MSG("Instead, use msgpack_bytes_reader") typedef msgpack_bytes_reader msgpack_buffer_reader;
|
|
112
|
+
#endif
|
|
113
|
+
|
|
114
|
+
}}
|
|
115
|
+
|
|
116
|
+
#endif
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Copyright 2013 Daniel Parker
|
|
2
|
+
// Distributed under the Boost license, Version 1.0.
|
|
3
|
+
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
4
|
+
|
|
5
|
+
// See https://github.com/danielaparker/jsoncons for latest version
|
|
6
|
+
|
|
7
|
+
#ifndef JSONCONS_MSGPACK_MSGPACK_TYPE_HPP
|
|
8
|
+
#define JSONCONS_MSGPACK_MSGPACK_TYPE_HPP
|
|
9
|
+
|
|
10
|
+
#include <string>
|
|
11
|
+
#include <memory>
|
|
12
|
+
#include <jsoncons/config/jsoncons_config.hpp>
|
|
13
|
+
|
|
14
|
+
namespace jsoncons { namespace msgpack {
|
|
15
|
+
|
|
16
|
+
namespace msgpack_type
|
|
17
|
+
{
|
|
18
|
+
const uint8_t positive_fixint_base_type = 0x00;
|
|
19
|
+
const uint8_t nil_type = 0xc0;
|
|
20
|
+
const uint8_t false_type = 0xc2;
|
|
21
|
+
const uint8_t true_type = 0xc3;
|
|
22
|
+
const uint8_t float32_type = 0xca;
|
|
23
|
+
const uint8_t float64_type = 0xcb;
|
|
24
|
+
const uint8_t uint8_type = 0xcc;
|
|
25
|
+
const uint8_t uint16_type = 0xcd;
|
|
26
|
+
const uint8_t uint32_type = 0xce;
|
|
27
|
+
const uint8_t uint64_type = 0xcf;
|
|
28
|
+
const uint8_t int8_type = 0xd0;
|
|
29
|
+
const uint8_t int16_type = 0xd1;
|
|
30
|
+
const uint8_t int32_type = 0xd2;
|
|
31
|
+
const uint8_t int64_type = 0xd3;
|
|
32
|
+
|
|
33
|
+
const uint8_t fixmap_base_type = 0x80;
|
|
34
|
+
const uint8_t fixarray_base_type = 0x90;
|
|
35
|
+
const uint8_t fixstr_base_type = 0xa0;
|
|
36
|
+
const uint8_t str8_type = 0xd9;
|
|
37
|
+
const uint8_t str16_type = 0xda;
|
|
38
|
+
const uint8_t str32_type = 0xdb;
|
|
39
|
+
|
|
40
|
+
const uint8_t bin8_type = 0xc4; // 0xC4
|
|
41
|
+
const uint8_t bin16_type = 0xc5;
|
|
42
|
+
const uint8_t bin32_type = 0xc6;
|
|
43
|
+
|
|
44
|
+
const uint8_t fixext1_type = 0xd4;
|
|
45
|
+
const uint8_t fixext2_type = 0xd5;
|
|
46
|
+
const uint8_t fixext4_type = 0xd6;
|
|
47
|
+
const uint8_t fixext8_type = 0xd7;
|
|
48
|
+
const uint8_t fixext16_type = 0xd8;
|
|
49
|
+
const uint8_t ext8_type = 0xc7; // 0xC4
|
|
50
|
+
const uint8_t ext16_type = 0xc8;
|
|
51
|
+
const uint8_t ext32_type = 0xc9;
|
|
52
|
+
|
|
53
|
+
const uint8_t array16_type = 0xdc;
|
|
54
|
+
const uint8_t array32_type = 0xdd;
|
|
55
|
+
const uint8_t map16_type = 0xde;
|
|
56
|
+
const uint8_t map32_type = 0xdf;
|
|
57
|
+
const uint8_t negative_fixint_base_type = 0xe0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
} // namespace msgpack
|
|
61
|
+
} // namespace jsoncons
|
|
62
|
+
|
|
63
|
+
#endif
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
// Copyright 2013 Daniel Parker
|
|
2
|
+
// Distributed under the Boost license, Version 1.0.
|
|
3
|
+
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
4
|
+
|
|
5
|
+
// See https://github.com/danielaparker/jsoncons for latest version
|
|
6
|
+
|
|
7
|
+
#ifndef JSONCONS_UBJSON_DECODE_UBJSON_HPP
|
|
8
|
+
#define JSONCONS_UBJSON_DECODE_UBJSON_HPP
|
|
9
|
+
|
|
10
|
+
#include <string>
|
|
11
|
+
#include <vector>
|
|
12
|
+
#include <memory>
|
|
13
|
+
#include <type_traits> // std::enable_if
|
|
14
|
+
#include <istream> // std::basic_istream
|
|
15
|
+
#include <jsoncons/json.hpp>
|
|
16
|
+
#include <jsoncons/config/jsoncons_config.hpp>
|
|
17
|
+
#include <jsoncons_ext/ubjson/ubjson_reader.hpp>
|
|
18
|
+
#include <jsoncons_ext/ubjson/ubjson_cursor.hpp>
|
|
19
|
+
|
|
20
|
+
namespace jsoncons {
|
|
21
|
+
namespace ubjson {
|
|
22
|
+
|
|
23
|
+
template<class T, class Source>
|
|
24
|
+
typename std::enable_if<traits_extension::is_basic_json<T>::value &&
|
|
25
|
+
traits_extension::is_byte_sequence<Source>::value,T>::type
|
|
26
|
+
decode_ubjson(const Source& v,
|
|
27
|
+
const ubjson_decode_options& options = ubjson_decode_options())
|
|
28
|
+
{
|
|
29
|
+
jsoncons::json_decoder<T> decoder;
|
|
30
|
+
auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
|
|
31
|
+
basic_ubjson_reader<jsoncons::bytes_source> reader(v, adaptor, options);
|
|
32
|
+
reader.read();
|
|
33
|
+
if (!decoder.is_valid())
|
|
34
|
+
{
|
|
35
|
+
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
|
36
|
+
}
|
|
37
|
+
return decoder.get_result();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
template<class T, class Source>
|
|
41
|
+
typename std::enable_if<!traits_extension::is_basic_json<T>::value &&
|
|
42
|
+
traits_extension::is_byte_sequence<Source>::value,T>::type
|
|
43
|
+
decode_ubjson(const Source& v,
|
|
44
|
+
const ubjson_decode_options& options = ubjson_decode_options())
|
|
45
|
+
{
|
|
46
|
+
basic_ubjson_cursor<bytes_source> cursor(v, options);
|
|
47
|
+
json_decoder<basic_json<char,sorted_policy>> decoder{};
|
|
48
|
+
|
|
49
|
+
std::error_code ec;
|
|
50
|
+
T val = decode_traits<T,char>::decode(cursor, decoder, ec);
|
|
51
|
+
if (ec)
|
|
52
|
+
{
|
|
53
|
+
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
|
54
|
+
}
|
|
55
|
+
return val;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
template<class T>
|
|
59
|
+
typename std::enable_if<traits_extension::is_basic_json<T>::value,T>::type
|
|
60
|
+
decode_ubjson(std::istream& is,
|
|
61
|
+
const ubjson_decode_options& options = ubjson_decode_options())
|
|
62
|
+
{
|
|
63
|
+
jsoncons::json_decoder<T> decoder;
|
|
64
|
+
auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
|
|
65
|
+
ubjson_stream_reader reader(is, adaptor, options);
|
|
66
|
+
reader.read();
|
|
67
|
+
if (!decoder.is_valid())
|
|
68
|
+
{
|
|
69
|
+
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
|
70
|
+
}
|
|
71
|
+
return decoder.get_result();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
template<class T>
|
|
75
|
+
typename std::enable_if<!traits_extension::is_basic_json<T>::value,T>::type
|
|
76
|
+
decode_ubjson(std::istream& is,
|
|
77
|
+
const ubjson_decode_options& options = ubjson_decode_options())
|
|
78
|
+
{
|
|
79
|
+
basic_ubjson_cursor<binary_stream_source> cursor(is, options);
|
|
80
|
+
json_decoder<basic_json<char,sorted_policy>> decoder{};
|
|
81
|
+
|
|
82
|
+
std::error_code ec;
|
|
83
|
+
T val = decode_traits<T,char>::decode(cursor, decoder, ec);
|
|
84
|
+
if (ec)
|
|
85
|
+
{
|
|
86
|
+
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
|
87
|
+
}
|
|
88
|
+
return val;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
template<class T, class InputIt>
|
|
92
|
+
typename std::enable_if<traits_extension::is_basic_json<T>::value,T>::type
|
|
93
|
+
decode_ubjson(InputIt first, InputIt last,
|
|
94
|
+
const ubjson_decode_options& options = ubjson_decode_options())
|
|
95
|
+
{
|
|
96
|
+
jsoncons::json_decoder<T> decoder;
|
|
97
|
+
auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
|
|
98
|
+
basic_ubjson_reader<binary_iterator_source<InputIt>> reader(binary_iterator_source<InputIt>(first, last), adaptor, options);
|
|
99
|
+
reader.read();
|
|
100
|
+
if (!decoder.is_valid())
|
|
101
|
+
{
|
|
102
|
+
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
|
103
|
+
}
|
|
104
|
+
return decoder.get_result();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
template<class T, class InputIt>
|
|
108
|
+
typename std::enable_if<!traits_extension::is_basic_json<T>::value,T>::type
|
|
109
|
+
decode_ubjson(InputIt first, InputIt last,
|
|
110
|
+
const ubjson_decode_options& options = ubjson_decode_options())
|
|
111
|
+
{
|
|
112
|
+
basic_ubjson_cursor<binary_iterator_source<InputIt>> cursor(binary_iterator_source<InputIt>(first, last), options);
|
|
113
|
+
json_decoder<basic_json<char,sorted_policy>> decoder{};
|
|
114
|
+
|
|
115
|
+
std::error_code ec;
|
|
116
|
+
T val = decode_traits<T,char>::decode(cursor, decoder, ec);
|
|
117
|
+
if (ec)
|
|
118
|
+
{
|
|
119
|
+
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
|
120
|
+
}
|
|
121
|
+
return val;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// With leading allocator parameter
|
|
125
|
+
|
|
126
|
+
template<class T, class Source, class TempAllocator>
|
|
127
|
+
typename std::enable_if<traits_extension::is_basic_json<T>::value &&
|
|
128
|
+
traits_extension::is_byte_sequence<Source>::value,T>::type
|
|
129
|
+
decode_ubjson(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
|
130
|
+
const Source& v,
|
|
131
|
+
const ubjson_decode_options& options = ubjson_decode_options())
|
|
132
|
+
{
|
|
133
|
+
json_decoder<T,TempAllocator> decoder(temp_alloc);
|
|
134
|
+
auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
|
|
135
|
+
basic_ubjson_reader<jsoncons::bytes_source,TempAllocator> reader(v, adaptor, options, temp_alloc);
|
|
136
|
+
reader.read();
|
|
137
|
+
if (!decoder.is_valid())
|
|
138
|
+
{
|
|
139
|
+
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
|
140
|
+
}
|
|
141
|
+
return decoder.get_result();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
template<class T, class Source, class TempAllocator>
|
|
145
|
+
typename std::enable_if<!traits_extension::is_basic_json<T>::value &&
|
|
146
|
+
traits_extension::is_byte_sequence<Source>::value,T>::type
|
|
147
|
+
decode_ubjson(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
|
148
|
+
const Source& v,
|
|
149
|
+
const ubjson_decode_options& options = ubjson_decode_options())
|
|
150
|
+
{
|
|
151
|
+
basic_ubjson_cursor<bytes_source,TempAllocator> cursor(v, options, temp_alloc);
|
|
152
|
+
json_decoder<basic_json<char,sorted_policy,TempAllocator>,TempAllocator> decoder(temp_alloc, temp_alloc);
|
|
153
|
+
|
|
154
|
+
std::error_code ec;
|
|
155
|
+
T val = decode_traits<T,char>::decode(cursor, decoder, ec);
|
|
156
|
+
if (ec)
|
|
157
|
+
{
|
|
158
|
+
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
|
159
|
+
}
|
|
160
|
+
return val;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
template<class T,class TempAllocator>
|
|
164
|
+
typename std::enable_if<traits_extension::is_basic_json<T>::value,T>::type
|
|
165
|
+
decode_ubjson(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
|
166
|
+
std::istream& is,
|
|
167
|
+
const ubjson_decode_options& options = ubjson_decode_options())
|
|
168
|
+
{
|
|
169
|
+
json_decoder<T,TempAllocator> decoder(temp_alloc);
|
|
170
|
+
auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
|
|
171
|
+
basic_ubjson_reader<jsoncons::binary_stream_source,TempAllocator> reader(is, adaptor, options, temp_alloc);
|
|
172
|
+
reader.read();
|
|
173
|
+
if (!decoder.is_valid())
|
|
174
|
+
{
|
|
175
|
+
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
|
176
|
+
}
|
|
177
|
+
return decoder.get_result();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
template<class T,class TempAllocator>
|
|
181
|
+
typename std::enable_if<!traits_extension::is_basic_json<T>::value,T>::type
|
|
182
|
+
decode_ubjson(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
|
183
|
+
std::istream& is,
|
|
184
|
+
const ubjson_decode_options& options = ubjson_decode_options())
|
|
185
|
+
{
|
|
186
|
+
basic_ubjson_cursor<binary_stream_source,TempAllocator> cursor(is, options, temp_alloc);
|
|
187
|
+
json_decoder<basic_json<char,sorted_policy,TempAllocator>,TempAllocator> decoder(temp_alloc, temp_alloc);
|
|
188
|
+
|
|
189
|
+
std::error_code ec;
|
|
190
|
+
T val = decode_traits<T,char>::decode(cursor, decoder, ec);
|
|
191
|
+
if (ec)
|
|
192
|
+
{
|
|
193
|
+
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
|
194
|
+
}
|
|
195
|
+
return val;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
} // ubjson
|
|
199
|
+
} // jsoncons
|
|
200
|
+
|
|
201
|
+
#endif
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// Copyright 2013 Daniel Parker
|
|
2
|
+
// Distributed under the Boost license, Version 1.0.
|
|
3
|
+
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
4
|
+
|
|
5
|
+
// See https://github.com/danielaparker/jsoncons for latest version
|
|
6
|
+
|
|
7
|
+
#ifndef JSONCONS_UBJSON_ENCODE_UBJSON_HPP
|
|
8
|
+
#define JSONCONS_UBJSON_ENCODE_UBJSON_HPP
|
|
9
|
+
|
|
10
|
+
#include <string>
|
|
11
|
+
#include <vector>
|
|
12
|
+
#include <memory>
|
|
13
|
+
#include <type_traits> // std::enable_if
|
|
14
|
+
#include <istream> // std::basic_istream
|
|
15
|
+
#include <jsoncons/json.hpp>
|
|
16
|
+
#include <jsoncons/config/jsoncons_config.hpp>
|
|
17
|
+
#include <jsoncons_ext/ubjson/ubjson_encoder.hpp>
|
|
18
|
+
#include <jsoncons_ext/ubjson/ubjson_reader.hpp>
|
|
19
|
+
|
|
20
|
+
namespace jsoncons {
|
|
21
|
+
namespace ubjson {
|
|
22
|
+
|
|
23
|
+
template<class T, class Container>
|
|
24
|
+
typename std::enable_if<traits_extension::is_basic_json<T>::value &&
|
|
25
|
+
traits_extension::is_back_insertable_byte_container<Container>::value,void>::type
|
|
26
|
+
encode_ubjson(const T& j,
|
|
27
|
+
Container& v,
|
|
28
|
+
const ubjson_encode_options& options = ubjson_encode_options())
|
|
29
|
+
{
|
|
30
|
+
using char_type = typename T::char_type;
|
|
31
|
+
basic_ubjson_encoder<jsoncons::bytes_sink<Container>> encoder(v, options);
|
|
32
|
+
auto adaptor = make_json_visitor_adaptor<basic_json_visitor<char_type>>(encoder);
|
|
33
|
+
j.dump(adaptor);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
template<class T, class Container>
|
|
37
|
+
typename std::enable_if<!traits_extension::is_basic_json<T>::value &&
|
|
38
|
+
traits_extension::is_back_insertable_byte_container<Container>::value,void>::type
|
|
39
|
+
encode_ubjson(const T& val,
|
|
40
|
+
Container& v,
|
|
41
|
+
const ubjson_encode_options& options = ubjson_encode_options())
|
|
42
|
+
{
|
|
43
|
+
basic_ubjson_encoder<jsoncons::bytes_sink<Container>> encoder(v, options);
|
|
44
|
+
std::error_code ec;
|
|
45
|
+
encode_traits<T,char>::encode(val, encoder, json(), ec);
|
|
46
|
+
if (ec)
|
|
47
|
+
{
|
|
48
|
+
JSONCONS_THROW(ser_error(ec));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
template<class T>
|
|
53
|
+
typename std::enable_if<traits_extension::is_basic_json<T>::value,void>::type
|
|
54
|
+
encode_ubjson(const T& j,
|
|
55
|
+
std::ostream& os,
|
|
56
|
+
const ubjson_encode_options& options = ubjson_encode_options())
|
|
57
|
+
{
|
|
58
|
+
using char_type = typename T::char_type;
|
|
59
|
+
ubjson_stream_encoder encoder(os, options);
|
|
60
|
+
auto adaptor = make_json_visitor_adaptor<basic_json_visitor<char_type>>(encoder);
|
|
61
|
+
j.dump(adaptor);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
template<class T>
|
|
65
|
+
typename std::enable_if<!traits_extension::is_basic_json<T>::value,void>::type
|
|
66
|
+
encode_ubjson(const T& val,
|
|
67
|
+
std::ostream& os,
|
|
68
|
+
const ubjson_encode_options& options = ubjson_encode_options())
|
|
69
|
+
{
|
|
70
|
+
ubjson_stream_encoder encoder(os, options);
|
|
71
|
+
std::error_code ec;
|
|
72
|
+
encode_traits<T,char>::encode(val, encoder, json(), ec);
|
|
73
|
+
if (ec)
|
|
74
|
+
{
|
|
75
|
+
JSONCONS_THROW(ser_error(ec));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// with temp_allocator_arg_t
|
|
80
|
+
|
|
81
|
+
template<class T, class Container, class TempAllocator>
|
|
82
|
+
typename std::enable_if<traits_extension::is_basic_json<T>::value &&
|
|
83
|
+
traits_extension::is_back_insertable_byte_container<Container>::value,void>::type
|
|
84
|
+
encode_ubjson(temp_allocator_arg_t, const TempAllocator& temp_alloc,const T& j,
|
|
85
|
+
Container& v,
|
|
86
|
+
const ubjson_encode_options& options = ubjson_encode_options())
|
|
87
|
+
{
|
|
88
|
+
using char_type = typename T::char_type;
|
|
89
|
+
basic_ubjson_encoder<jsoncons::bytes_sink<Container>,TempAllocator> encoder(v, options, temp_alloc);
|
|
90
|
+
auto adaptor = make_json_visitor_adaptor<basic_json_visitor<char_type>>(encoder);
|
|
91
|
+
j.dump(adaptor);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
template<class T, class Container, class TempAllocator>
|
|
95
|
+
typename std::enable_if<!traits_extension::is_basic_json<T>::value &&
|
|
96
|
+
traits_extension::is_back_insertable_byte_container<Container>::value,void>::type
|
|
97
|
+
encode_ubjson(temp_allocator_arg_t, const TempAllocator& temp_alloc,const T& val,
|
|
98
|
+
Container& v,
|
|
99
|
+
const ubjson_encode_options& options = ubjson_encode_options())
|
|
100
|
+
{
|
|
101
|
+
basic_ubjson_encoder<jsoncons::bytes_sink<Container>,TempAllocator> encoder(v, options, temp_alloc);
|
|
102
|
+
std::error_code ec;
|
|
103
|
+
encode_traits<T,char>::encode(val, encoder, json(), ec);
|
|
104
|
+
if (ec)
|
|
105
|
+
{
|
|
106
|
+
JSONCONS_THROW(ser_error(ec));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
template<class T,class TempAllocator>
|
|
111
|
+
typename std::enable_if<traits_extension::is_basic_json<T>::value,void>::type
|
|
112
|
+
encode_ubjson(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
|
113
|
+
const T& j,
|
|
114
|
+
std::ostream& os,
|
|
115
|
+
const ubjson_encode_options& options = ubjson_encode_options())
|
|
116
|
+
{
|
|
117
|
+
using char_type = typename T::char_type;
|
|
118
|
+
basic_ubjson_encoder<jsoncons::binary_stream_sink,TempAllocator> encoder(os, options, temp_alloc);
|
|
119
|
+
auto adaptor = make_json_visitor_adaptor<basic_json_visitor<char_type>>(encoder);
|
|
120
|
+
j.dump(adaptor);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
template<class T,class TempAllocator>
|
|
124
|
+
typename std::enable_if<!traits_extension::is_basic_json<T>::value,void>::type
|
|
125
|
+
encode_ubjson(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
|
126
|
+
const T& val,
|
|
127
|
+
std::ostream& os,
|
|
128
|
+
const ubjson_encode_options& options = ubjson_encode_options())
|
|
129
|
+
{
|
|
130
|
+
basic_ubjson_encoder<jsoncons::binary_stream_sink,TempAllocator> encoder(os, options, temp_alloc);
|
|
131
|
+
std::error_code ec;
|
|
132
|
+
encode_traits<T,char>::encode(val, encoder, json(), ec);
|
|
133
|
+
if (ec)
|
|
134
|
+
{
|
|
135
|
+
JSONCONS_THROW(ser_error(ec));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
} // ubjson
|
|
140
|
+
} // jsoncons
|
|
141
|
+
|
|
142
|
+
#endif
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Copyright 2013 Daniel Parker
|
|
2
|
+
// Distributed under the Boost license, Version 1.0.
|
|
3
|
+
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
4
|
+
|
|
5
|
+
// See https://github.com/danielaparker/jsoncons for latest version
|
|
6
|
+
|
|
7
|
+
#ifndef JSONCONS_UBJSON_UBJSON_HPP
|
|
8
|
+
#define JSONCONS_UBJSON_UBJSON_HPP
|
|
9
|
+
|
|
10
|
+
#include <string>
|
|
11
|
+
#include <vector>
|
|
12
|
+
#include <memory>
|
|
13
|
+
#include <type_traits> // std::enable_if
|
|
14
|
+
#include <istream> // std::basic_istream
|
|
15
|
+
#include <jsoncons/json.hpp>
|
|
16
|
+
#include <jsoncons/config/jsoncons_config.hpp>
|
|
17
|
+
#include <jsoncons_ext/ubjson/ubjson_encoder.hpp>
|
|
18
|
+
#include <jsoncons_ext/ubjson/ubjson_reader.hpp>
|
|
19
|
+
#include <jsoncons_ext/ubjson/ubjson_cursor.hpp>
|
|
20
|
+
#include <jsoncons_ext/ubjson/encode_ubjson.hpp>
|
|
21
|
+
#include <jsoncons_ext/ubjson/decode_ubjson.hpp>
|
|
22
|
+
|
|
23
|
+
#endif
|