/src/jsoncons/include/jsoncons_ext/ubjson/ubjson_parser.hpp
Line | Count | Source |
1 | | // Copyright 2013-2025 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_EXT_UBJSON_UBJSON_PARSER_HPP |
8 | | #define JSONCONS_EXT_UBJSON_UBJSON_PARSER_HPP |
9 | | |
10 | | #include <cstddef> |
11 | | #include <cstdint> |
12 | | #include <memory> |
13 | | #include <string> |
14 | | #include <system_error> |
15 | | #include <vector> |
16 | | #include <utility> // std::move |
17 | | |
18 | | #include <jsoncons/config/jsoncons_config.hpp> |
19 | | #include <jsoncons/utility/read_number.hpp> |
20 | | #include <jsoncons/json_type.hpp> |
21 | | #include <jsoncons/json_visitor.hpp> |
22 | | #include <jsoncons/semantic_tag.hpp> |
23 | | #include <jsoncons/ser_util.hpp> |
24 | | #include <jsoncons/source.hpp> |
25 | | #include <jsoncons/utility/binary.hpp> |
26 | | #include <jsoncons/utility/unicode_traits.hpp> |
27 | | |
28 | | #include <jsoncons_ext/ubjson/ubjson_error.hpp> |
29 | | #include <jsoncons_ext/ubjson/ubjson_options.hpp> |
30 | | #include <jsoncons_ext/ubjson/ubjson_type.hpp> |
31 | | |
32 | | namespace jsoncons { |
33 | | namespace ubjson { |
34 | | |
35 | | enum class parse_mode {root,accept,array,indefinite_array,strongly_typed_array,map_key,map_value,strongly_typed_map_key,strongly_typed_map_value,indefinite_map_key,indefinite_map_value}; |
36 | | |
37 | | struct parse_state |
38 | | { |
39 | | parse_mode mode; |
40 | | std::size_t length{0}; |
41 | | uint8_t type; |
42 | | std::size_t index{0}; |
43 | | |
44 | | parse_state(parse_mode mode, std::size_t length, uint8_t type = 0) noexcept |
45 | 11.6M | : mode(mode), length(length), type(type) |
46 | 11.6M | { |
47 | 11.6M | } |
48 | | |
49 | | parse_state(const parse_state&) = default; |
50 | | parse_state(parse_state&&) = default; |
51 | | }; |
52 | | |
53 | | template <typename Source,typename Allocator=std::allocator<char>> |
54 | | class basic_ubjson_parser : public ser_context |
55 | | { |
56 | | using char_type = char; |
57 | | using char_traits_type = std::char_traits<char>; |
58 | | using temp_allocator_type = Allocator; |
59 | | using char_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<char_type>; |
60 | | using byte_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<uint8_t>; |
61 | | using parse_state_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<parse_state>; |
62 | | |
63 | | bool more_{true}; |
64 | | bool done_{false}; |
65 | | int nesting_depth_{0}; |
66 | | bool cursor_mode_{false}; |
67 | | int mark_level_{0}; |
68 | | |
69 | | Source source_; |
70 | | int max_nesting_depth_; |
71 | | std::size_t max_items_; |
72 | | std::basic_string<char,std::char_traits<char>,char_allocator_type> text_buffer_; |
73 | | std::vector<parse_state,parse_state_allocator_type> state_stack_; |
74 | | public: |
75 | | template <typename Sourceable> |
76 | | basic_ubjson_parser(Sourceable&& source, |
77 | | const ubjson_decode_options& options = ubjson_decode_options(), |
78 | | const Allocator& alloc = Allocator()) |
79 | 744 | : source_(std::forward<Sourceable>(source)), |
80 | 744 | max_nesting_depth_(options.max_nesting_depth()), |
81 | 744 | max_items_(options.max_items()), |
82 | 744 | text_buffer_(alloc), |
83 | 744 | state_stack_(alloc) |
84 | 744 | { |
85 | 744 | state_stack_.emplace_back(parse_mode::root,0); |
86 | 744 | } jsoncons::ubjson::basic_ubjson_parser<jsoncons::stream_source<unsigned char, std::__1::allocator<unsigned char> >, std::__1::allocator<char> >::basic_ubjson_parser<std::__1::basic_istringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(std::__1::basic_istringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, jsoncons::ubjson::ubjson_decode_options const&, std::__1::allocator<char> const&) Line | Count | Source | 79 | 282 | : source_(std::forward<Sourceable>(source)), | 80 | 282 | max_nesting_depth_(options.max_nesting_depth()), | 81 | 282 | max_items_(options.max_items()), | 82 | 282 | text_buffer_(alloc), | 83 | 282 | state_stack_(alloc) | 84 | 282 | { | 85 | 282 | state_stack_.emplace_back(parse_mode::root,0); | 86 | 282 | } |
jsoncons::ubjson::basic_ubjson_parser<jsoncons::stream_source<unsigned char, std::__1::allocator<unsigned char> >, std::__1::allocator<char> >::basic_ubjson_parser<std::__1::basic_istream<char, std::__1::char_traits<char> >&>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, jsoncons::ubjson::ubjson_decode_options const&, std::__1::allocator<char> const&) Line | Count | Source | 79 | 462 | : source_(std::forward<Sourceable>(source)), | 80 | 462 | max_nesting_depth_(options.max_nesting_depth()), | 81 | 462 | max_items_(options.max_items()), | 82 | 462 | text_buffer_(alloc), | 83 | 462 | state_stack_(alloc) | 84 | 462 | { | 85 | 462 | state_stack_.emplace_back(parse_mode::root,0); | 86 | 462 | } |
|
87 | | |
88 | | void restart() |
89 | | { |
90 | | more_ = true; |
91 | | } |
92 | | |
93 | | void reset() |
94 | 744 | { |
95 | 744 | more_ = true; |
96 | 744 | done_ = false; |
97 | 744 | text_buffer_.clear(); |
98 | 744 | state_stack_.clear(); |
99 | 744 | state_stack_.emplace_back(parse_mode::root,0,uint8_t(0)); |
100 | 744 | nesting_depth_ = 0; |
101 | 744 | } |
102 | | |
103 | | template <typename Sourceable> |
104 | | void reset(Sourceable&& source) |
105 | | { |
106 | | source_ = std::forward<Sourceable>(source); |
107 | | reset(); |
108 | | } |
109 | | |
110 | | void cursor_mode(bool value) |
111 | | { |
112 | | cursor_mode_ = value; |
113 | | } |
114 | | |
115 | | int level() const |
116 | 11.6M | { |
117 | 11.6M | return static_cast<int>(state_stack_.size()); |
118 | 11.6M | } |
119 | | |
120 | | int mark_level() const |
121 | | { |
122 | | return mark_level_; |
123 | | } |
124 | | |
125 | | void mark_level(int value) |
126 | | { |
127 | | mark_level_ = value; |
128 | | } |
129 | | |
130 | | bool done() const |
131 | | { |
132 | | return done_; |
133 | | } |
134 | | |
135 | | bool stopped() const |
136 | | { |
137 | | return !more_; |
138 | | } |
139 | | |
140 | | std::size_t line() const override |
141 | 336 | { |
142 | 336 | return 0; |
143 | 336 | } |
144 | | |
145 | | std::size_t column() const override |
146 | 336 | { |
147 | 336 | return source_.position(); |
148 | 336 | } |
149 | | |
150 | | void parse(json_visitor& visitor, std::error_code& ec) |
151 | 744 | { |
152 | 64.8M | while (!done_ && more_) |
153 | 64.8M | { |
154 | 64.8M | switch (state_stack_.back().mode) |
155 | 64.8M | { |
156 | 133k | case parse_mode::array: |
157 | 133k | { |
158 | 133k | if (state_stack_.back().index < state_stack_.back().length) |
159 | 27.5k | { |
160 | 27.5k | ++state_stack_.back().index; |
161 | 27.5k | read_type_and_value(visitor, ec); |
162 | 27.5k | if (JSONCONS_UNLIKELY(ec)) |
163 | 2 | { |
164 | 2 | return; |
165 | 2 | } |
166 | 27.5k | } |
167 | 105k | else |
168 | 105k | { |
169 | 105k | end_array(visitor, ec); |
170 | 105k | } |
171 | 133k | break; |
172 | 133k | } |
173 | 24.5M | case parse_mode::strongly_typed_array: |
174 | 24.5M | { |
175 | 24.5M | if (state_stack_.back().index < state_stack_.back().length) |
176 | 24.5M | { |
177 | 24.5M | ++state_stack_.back().index; |
178 | 24.5M | read_value(visitor, state_stack_.back().type, ec); |
179 | 24.5M | if (JSONCONS_UNLIKELY(ec)) |
180 | 166 | { |
181 | 166 | return; |
182 | 166 | } |
183 | 24.5M | } |
184 | 27.0k | else |
185 | 27.0k | { |
186 | 27.0k | end_array(visitor, ec); |
187 | 27.0k | } |
188 | 24.5M | break; |
189 | 24.5M | } |
190 | 24.5M | case parse_mode::indefinite_array: |
191 | 22.2M | { |
192 | 22.2M | auto c = source_.peek(); |
193 | 22.2M | if (JSONCONS_UNLIKELY(c.eof)) |
194 | 53 | { |
195 | 53 | ec = ubjson_errc::unexpected_eof; |
196 | 53 | more_ = false; |
197 | 53 | return; |
198 | 53 | } |
199 | 22.2M | if (c.value == jsoncons::ubjson::ubjson_type::end_array_marker) |
200 | 6.80M | { |
201 | 6.80M | source_.ignore(1); |
202 | 6.80M | end_array(visitor, ec); |
203 | 6.80M | if (JSONCONS_UNLIKELY(ec)) |
204 | 0 | { |
205 | 0 | return; |
206 | 0 | } |
207 | 6.80M | } |
208 | 15.4M | else |
209 | 15.4M | { |
210 | 15.4M | if (++state_stack_.back().index > max_items_) |
211 | 0 | { |
212 | 0 | ec = ubjson_errc::max_items_exceeded; |
213 | 0 | more_ = false; |
214 | 0 | return; |
215 | 0 | } |
216 | 15.4M | read_type_and_value(visitor, ec); |
217 | 15.4M | if (JSONCONS_UNLIKELY(ec)) |
218 | 105 | { |
219 | 105 | return; |
220 | 105 | } |
221 | 15.4M | } |
222 | 22.2M | break; |
223 | 22.2M | } |
224 | 22.2M | case parse_mode::map_key: |
225 | 17.5k | { |
226 | 17.5k | if (state_stack_.back().index < state_stack_.back().length) |
227 | 11.9k | { |
228 | 11.9k | ++state_stack_.back().index; |
229 | 11.9k | read_key(visitor, ec); |
230 | 11.9k | if (JSONCONS_UNLIKELY(ec)) |
231 | 5 | { |
232 | 5 | return; |
233 | 5 | } |
234 | 11.9k | state_stack_.back().mode = parse_mode::map_value; |
235 | 11.9k | } |
236 | 5.58k | else |
237 | 5.58k | { |
238 | 5.58k | end_object(visitor, ec); |
239 | 5.58k | } |
240 | 17.5k | break; |
241 | 17.5k | } |
242 | 17.5k | case parse_mode::map_value: |
243 | 11.9k | { |
244 | 11.9k | state_stack_.back().mode = parse_mode::map_key; |
245 | 11.9k | read_type_and_value(visitor, ec); |
246 | 11.9k | if (JSONCONS_UNLIKELY(ec)) |
247 | 8 | { |
248 | 8 | return; |
249 | 8 | } |
250 | 11.9k | break; |
251 | 11.9k | } |
252 | 153k | case parse_mode::strongly_typed_map_key: |
253 | 153k | { |
254 | 153k | if (state_stack_.back().index < state_stack_.back().length) |
255 | 57.9k | { |
256 | 57.9k | ++state_stack_.back().index; |
257 | 57.9k | read_key(visitor, ec); |
258 | 57.9k | if (JSONCONS_UNLIKELY(ec)) |
259 | 5 | { |
260 | 5 | return; |
261 | 5 | } |
262 | 57.9k | state_stack_.back().mode = parse_mode::strongly_typed_map_value; |
263 | 57.9k | } |
264 | 95.1k | else |
265 | 95.1k | { |
266 | 95.1k | end_object(visitor, ec); |
267 | 95.1k | } |
268 | 153k | break; |
269 | 153k | } |
270 | 153k | case parse_mode::strongly_typed_map_value: |
271 | 57.9k | { |
272 | 57.9k | state_stack_.back().mode = parse_mode::strongly_typed_map_key; |
273 | 57.9k | read_value(visitor, state_stack_.back().type, ec); |
274 | 57.9k | if (JSONCONS_UNLIKELY(ec)) |
275 | 1 | { |
276 | 1 | return; |
277 | 1 | } |
278 | 57.9k | break; |
279 | 57.9k | } |
280 | 11.0M | case parse_mode::indefinite_map_key: |
281 | 11.0M | { |
282 | 11.0M | auto c = source_.peek(); |
283 | 11.0M | if (JSONCONS_UNLIKELY(c.eof)) |
284 | 19 | { |
285 | 19 | ec = ubjson_errc::unexpected_eof; |
286 | 19 | more_ = false; |
287 | 19 | return; |
288 | 19 | } |
289 | 11.0M | if (c.value == jsoncons::ubjson::ubjson_type::end_object_marker) |
290 | 4.56M | { |
291 | 4.56M | source_.ignore(1); |
292 | 4.56M | end_object(visitor, ec); |
293 | 4.56M | if (JSONCONS_UNLIKELY(ec)) |
294 | 0 | { |
295 | 0 | return; |
296 | 0 | } |
297 | 4.56M | } |
298 | 6.50M | else |
299 | 6.50M | { |
300 | 6.50M | if (++state_stack_.back().index > max_items_) |
301 | 0 | { |
302 | 0 | ec = ubjson_errc::max_items_exceeded; |
303 | 0 | more_ = false; |
304 | 0 | return; |
305 | 0 | } |
306 | 6.50M | read_key(visitor, ec); |
307 | 6.50M | if (JSONCONS_UNLIKELY(ec)) |
308 | 97 | { |
309 | 97 | return; |
310 | 97 | } |
311 | 6.50M | state_stack_.back().mode = parse_mode::indefinite_map_value; |
312 | 6.50M | } |
313 | 11.0M | break; |
314 | 11.0M | } |
315 | 11.0M | case parse_mode::indefinite_map_value: |
316 | 6.50M | { |
317 | 6.50M | state_stack_.back().mode = parse_mode::indefinite_map_key; |
318 | 6.50M | read_type_and_value(visitor, ec); |
319 | 6.50M | if (JSONCONS_UNLIKELY(ec)) |
320 | 61 | { |
321 | 61 | return; |
322 | 61 | } |
323 | 6.50M | break; |
324 | 6.50M | } |
325 | 6.50M | case parse_mode::root: |
326 | 744 | { |
327 | 744 | state_stack_.back().mode = parse_mode::accept; |
328 | 744 | read_type_and_value(visitor, ec); |
329 | 744 | if (JSONCONS_UNLIKELY(ec)) |
330 | 79 | { |
331 | 79 | return; |
332 | 79 | } |
333 | 665 | break; |
334 | 744 | } |
335 | 665 | case parse_mode::accept: |
336 | 143 | { |
337 | 143 | JSONCONS_ASSERT(state_stack_.size() == 1); |
338 | 143 | state_stack_.clear(); |
339 | 143 | more_ = false; |
340 | 143 | done_ = true; |
341 | 143 | visitor.flush(); |
342 | 143 | break; |
343 | 143 | } |
344 | 64.8M | } |
345 | 64.8M | } |
346 | 744 | } |
347 | | private: |
348 | | void read_type_and_value(json_visitor& visitor, std::error_code& ec) |
349 | 22.0M | { |
350 | 22.0M | if (source_.is_error()) |
351 | 0 | { |
352 | 0 | ec = ubjson_errc::source_error; |
353 | 0 | more_ = false; |
354 | 0 | return; |
355 | 0 | } |
356 | | |
357 | 22.0M | uint8_t b; |
358 | 22.0M | if (source_.read(&b, 1) == 0) |
359 | 30 | { |
360 | 30 | ec = ubjson_errc::unexpected_eof; |
361 | 30 | more_ = false; |
362 | 30 | return; |
363 | 30 | } |
364 | 22.0M | read_value(visitor, b, ec); |
365 | 22.0M | } |
366 | | |
367 | | void read_value(json_visitor& visitor, uint8_t type, std::error_code& ec) |
368 | 46.6M | { |
369 | 46.6M | switch (type) |
370 | 46.6M | { |
371 | 17.5M | case jsoncons::ubjson::ubjson_type::null_type: |
372 | 17.5M | { |
373 | 17.5M | visitor.null_value(semantic_tag::none, *this, ec); |
374 | 17.5M | more_ = !cursor_mode_; |
375 | 17.5M | break; |
376 | 0 | } |
377 | 496k | case jsoncons::ubjson::ubjson_type::no_op_type: |
378 | 496k | { |
379 | 496k | break; |
380 | 0 | } |
381 | 2.99M | case jsoncons::ubjson::ubjson_type::true_type: |
382 | 2.99M | { |
383 | 2.99M | visitor.bool_value(true, semantic_tag::none, *this, ec); |
384 | 2.99M | more_ = !cursor_mode_; |
385 | 2.99M | break; |
386 | 0 | } |
387 | 2.22M | case jsoncons::ubjson::ubjson_type::false_type: |
388 | 2.22M | { |
389 | 2.22M | visitor.bool_value(false, semantic_tag::none, *this, ec); |
390 | 2.22M | more_ = !cursor_mode_; |
391 | 2.22M | break; |
392 | 0 | } |
393 | 2.11M | case jsoncons::ubjson::ubjson_type::int8_type: |
394 | 2.11M | { |
395 | 2.11M | uint8_t buf[sizeof(int8_t)]; |
396 | 2.11M | if (source_.read(buf, sizeof(int8_t)) != sizeof(int8_t)) |
397 | 14 | { |
398 | 14 | ec = ubjson_errc::unexpected_eof; |
399 | 14 | more_ = false; |
400 | 14 | return; |
401 | 14 | } |
402 | 2.11M | int8_t val = binary::big_to_native<int8_t>(buf, sizeof(buf)); |
403 | 2.11M | visitor.int64_value(val, semantic_tag::none, *this, ec); |
404 | 2.11M | more_ = !cursor_mode_; |
405 | 2.11M | break; |
406 | 2.11M | } |
407 | 2.32M | case jsoncons::ubjson::ubjson_type::uint8_type: |
408 | 2.32M | { |
409 | 2.32M | uint8_t b; |
410 | 2.32M | if (source_.read(&b, 1) == 0) |
411 | 13 | { |
412 | 13 | ec = ubjson_errc::unexpected_eof; |
413 | 13 | more_ = false; |
414 | 13 | return; |
415 | 13 | } |
416 | 2.32M | visitor.uint64_value(b, semantic_tag::none, *this, ec); |
417 | 2.32M | more_ = !cursor_mode_; |
418 | 2.32M | break; |
419 | 2.32M | } |
420 | 851k | case jsoncons::ubjson::ubjson_type::int16_type: |
421 | 851k | { |
422 | 851k | uint8_t buf[sizeof(int16_t)]; |
423 | 851k | if (source_.read(buf, sizeof(int16_t)) != sizeof(int16_t)) |
424 | 7 | { |
425 | 7 | ec = ubjson_errc::unexpected_eof; |
426 | 7 | more_ = false; |
427 | 7 | return; |
428 | 7 | } |
429 | 851k | int16_t val = binary::big_to_native<int16_t>(buf, sizeof(buf)); |
430 | 851k | visitor.int64_value(val, semantic_tag::none, *this, ec); |
431 | 851k | more_ = !cursor_mode_; |
432 | 851k | break; |
433 | 851k | } |
434 | 115k | case jsoncons::ubjson::ubjson_type::int32_type: |
435 | 115k | { |
436 | 115k | uint8_t buf[sizeof(int32_t)]; |
437 | 115k | if (source_.read(buf, sizeof(int32_t)) != sizeof(int32_t)) |
438 | 6 | { |
439 | 6 | ec = ubjson_errc::unexpected_eof; |
440 | 6 | more_ = false; |
441 | 6 | return; |
442 | 6 | } |
443 | 115k | int32_t val = binary::big_to_native<int32_t>(buf, sizeof(buf)); |
444 | 115k | visitor.int64_value(val, semantic_tag::none, *this, ec); |
445 | 115k | more_ = !cursor_mode_; |
446 | 115k | break; |
447 | 115k | } |
448 | 32.2k | case jsoncons::ubjson::ubjson_type::int64_type: |
449 | 32.2k | { |
450 | 32.2k | uint8_t buf[sizeof(int64_t)]; |
451 | 32.2k | if (source_.read(buf, sizeof(int64_t)) != sizeof(int64_t)) |
452 | 6 | { |
453 | 6 | ec = ubjson_errc::unexpected_eof; |
454 | 6 | more_ = false; |
455 | 6 | return; |
456 | 6 | } |
457 | 32.2k | int64_t val = binary::big_to_native<int64_t>(buf, sizeof(buf)); |
458 | 32.2k | visitor.int64_value(val, semantic_tag::none, *this, ec); |
459 | 32.2k | more_ = !cursor_mode_; |
460 | 32.2k | break; |
461 | 32.2k | } |
462 | 215k | case jsoncons::ubjson::ubjson_type::float32_type: |
463 | 215k | { |
464 | 215k | uint8_t buf[sizeof(float)]; |
465 | 215k | if (source_.read(buf, sizeof(float)) != sizeof(float)) |
466 | 11 | { |
467 | 11 | ec = ubjson_errc::unexpected_eof; |
468 | 11 | more_ = false; |
469 | 11 | return; |
470 | 11 | } |
471 | 215k | float val = binary::big_to_native<float>(buf, sizeof(buf)); |
472 | 215k | visitor.double_value(val, semantic_tag::none, *this, ec); |
473 | 215k | more_ = !cursor_mode_; |
474 | 215k | break; |
475 | 215k | } |
476 | 1.87k | case jsoncons::ubjson::ubjson_type::float64_type: |
477 | 1.87k | { |
478 | 1.87k | uint8_t buf[sizeof(double)]; |
479 | 1.87k | if (source_.read(buf, sizeof(double)) != sizeof(double)) |
480 | 0 | { |
481 | 0 | ec = ubjson_errc::unexpected_eof; |
482 | 0 | more_ = false; |
483 | 0 | return; |
484 | 0 | } |
485 | 1.87k | double val = binary::big_to_native<double>(buf, sizeof(buf)); |
486 | 1.87k | visitor.double_value(val, semantic_tag::none, *this, ec); |
487 | 1.87k | more_ = !cursor_mode_; |
488 | 1.87k | break; |
489 | 1.87k | } |
490 | 6.06M | case jsoncons::ubjson::ubjson_type::char_type: |
491 | 6.06M | { |
492 | 6.06M | text_buffer_.clear(); |
493 | 6.06M | if (source_reader<Source>::read(source_,text_buffer_,1) != 1) |
494 | 33 | { |
495 | 33 | ec = ubjson_errc::unexpected_eof; |
496 | 33 | more_ = false; |
497 | 33 | return; |
498 | 33 | } |
499 | 6.06M | auto result = unicode_traits::validate(text_buffer_.data(),text_buffer_.size()); |
500 | 6.06M | if (result.ec != unicode_traits::conv_errc()) |
501 | 3 | { |
502 | 3 | ec = ubjson_errc::invalid_utf8_text_string; |
503 | 3 | more_ = false; |
504 | 3 | return; |
505 | 3 | } |
506 | 6.06M | visitor.string_value(text_buffer_, semantic_tag::none, *this, ec); |
507 | 6.06M | more_ = !cursor_mode_; |
508 | 6.06M | break; |
509 | 6.06M | } |
510 | 14.5k | case jsoncons::ubjson::ubjson_type::string_type: |
511 | 14.5k | { |
512 | 14.5k | std::size_t length = get_length(ec); |
513 | 14.5k | if (JSONCONS_UNLIKELY(ec)) |
514 | 1 | { |
515 | 1 | return; |
516 | 1 | } |
517 | 14.5k | text_buffer_.clear(); |
518 | 14.5k | if (source_reader<Source>::read(source_,text_buffer_,length) != length) |
519 | 13 | { |
520 | 13 | ec = ubjson_errc::unexpected_eof; |
521 | 13 | more_ = false; |
522 | 13 | return; |
523 | 13 | } |
524 | 14.5k | auto result = unicode_traits::validate(text_buffer_.data(),text_buffer_.size()); |
525 | 14.5k | if (result.ec != unicode_traits::conv_errc()) |
526 | 17 | { |
527 | 17 | ec = ubjson_errc::invalid_utf8_text_string; |
528 | 17 | more_ = false; |
529 | 17 | return; |
530 | 17 | } |
531 | 14.5k | visitor.string_value(jsoncons::basic_string_view<char>(text_buffer_.data(),text_buffer_.length()), semantic_tag::none, *this, ec); |
532 | 14.5k | more_ = !cursor_mode_; |
533 | 14.5k | break; |
534 | 14.5k | } |
535 | 9.02k | case jsoncons::ubjson::ubjson_type::high_precision_number_type: |
536 | 9.02k | { |
537 | 9.02k | std::size_t length = get_length(ec); |
538 | 9.02k | if (JSONCONS_UNLIKELY(ec)) |
539 | 1 | { |
540 | 1 | return; |
541 | 1 | } |
542 | 9.01k | text_buffer_.clear(); |
543 | 9.01k | if (source_reader<Source>::read(source_,text_buffer_,length) != length) |
544 | 29 | { |
545 | 29 | ec = ubjson_errc::unexpected_eof; |
546 | 29 | more_ = false; |
547 | 29 | return; |
548 | 29 | } |
549 | 8.99k | if (jsoncons::is_base10(text_buffer_.data(),text_buffer_.length())) |
550 | 186 | { |
551 | 186 | visitor.string_value(jsoncons::basic_string_view<char>(text_buffer_.data(),text_buffer_.length()), semantic_tag::bigint, *this, ec); |
552 | 186 | more_ = !cursor_mode_; |
553 | 186 | } |
554 | 8.80k | else |
555 | 8.80k | { |
556 | 8.80k | visitor.string_value(jsoncons::basic_string_view<char>(text_buffer_.data(),text_buffer_.length()), semantic_tag::bigdec, *this, ec); |
557 | 8.80k | more_ = !cursor_mode_; |
558 | 8.80k | } |
559 | 8.99k | break; |
560 | 9.01k | } |
561 | 6.98M | case jsoncons::ubjson::ubjson_type::start_array_marker: |
562 | 6.98M | { |
563 | 6.98M | begin_array(visitor,ec); |
564 | 6.98M | break; |
565 | 9.01k | } |
566 | 4.66M | case jsoncons::ubjson::ubjson_type::start_object_marker: |
567 | 4.66M | { |
568 | 4.66M | begin_object(visitor, ec); |
569 | 4.66M | break; |
570 | 9.01k | } |
571 | 99 | default: |
572 | 99 | { |
573 | 99 | ec = ubjson_errc::unknown_type; |
574 | 99 | break; |
575 | 9.01k | } |
576 | 46.6M | } |
577 | 46.6M | if (JSONCONS_UNLIKELY(ec)) |
578 | 238 | { |
579 | 238 | more_ = false; |
580 | 238 | } |
581 | 46.6M | } |
582 | | |
583 | | void begin_array(json_visitor& visitor, std::error_code& ec) |
584 | 6.98M | { |
585 | 6.98M | if (JSONCONS_UNLIKELY(++nesting_depth_ > max_nesting_depth_)) |
586 | 3 | { |
587 | 3 | ec = ubjson_errc::max_nesting_depth_exceeded; |
588 | 3 | more_ = false; |
589 | 3 | return; |
590 | 3 | } |
591 | | |
592 | 6.98M | auto c = source_.peek(); |
593 | 6.98M | if (JSONCONS_UNLIKELY(c.eof)) |
594 | 20 | { |
595 | 20 | ec = ubjson_errc::unexpected_eof; |
596 | 20 | more_ = false; |
597 | 20 | return; |
598 | 20 | } |
599 | 6.98M | if (c.value == jsoncons::ubjson::ubjson_type::type_marker) |
600 | 45.4k | { |
601 | 45.4k | source_.ignore(1); |
602 | 45.4k | uint8_t b; |
603 | 45.4k | if (source_.read(&b, 1) == 0) |
604 | 8 | { |
605 | 8 | ec = ubjson_errc::unexpected_eof; |
606 | 8 | more_ = false; |
607 | 8 | return; |
608 | 8 | } |
609 | 45.3k | c = source_.peek(); |
610 | 45.3k | if (JSONCONS_UNLIKELY(c.eof)) |
611 | 9 | { |
612 | 9 | ec = ubjson_errc::unexpected_eof; |
613 | 9 | more_ = false; |
614 | 9 | return; |
615 | 9 | } |
616 | 45.3k | if (c.value == jsoncons::ubjson::ubjson_type::count_marker) |
617 | 45.3k | { |
618 | 45.3k | source_.ignore(1); |
619 | 45.3k | std::size_t length = get_length(ec); |
620 | 45.3k | if (JSONCONS_UNLIKELY(ec)) |
621 | 9 | { |
622 | 9 | return; |
623 | 9 | } |
624 | 45.3k | if (length > max_items_) |
625 | 0 | { |
626 | 0 | ec = ubjson_errc::max_items_exceeded; |
627 | 0 | more_ = false; |
628 | 0 | return; |
629 | 0 | } |
630 | 45.3k | state_stack_.emplace_back(parse_mode::strongly_typed_array,length,b); |
631 | 45.3k | visitor.begin_array(length, semantic_tag::none, *this, ec); |
632 | 45.3k | more_ = !cursor_mode_; |
633 | 45.3k | } |
634 | 1 | else |
635 | 1 | { |
636 | 1 | ec = ubjson_errc::count_required_after_type; |
637 | 1 | more_ = false; |
638 | 1 | return; |
639 | 1 | } |
640 | 45.3k | } |
641 | 6.93M | else if (c.value == jsoncons::ubjson::ubjson_type::count_marker) |
642 | 105k | { |
643 | 105k | source_.ignore(1); |
644 | 105k | std::size_t length = get_length(ec); |
645 | 105k | if (JSONCONS_UNLIKELY(ec)) |
646 | 9 | { |
647 | 9 | return; |
648 | 9 | } |
649 | 105k | if (length > max_items_) |
650 | 1 | { |
651 | 1 | ec = ubjson_errc::max_items_exceeded; |
652 | 1 | more_ = false; |
653 | 1 | return; |
654 | 1 | } |
655 | 105k | state_stack_.emplace_back(parse_mode::array,length); |
656 | 105k | visitor.begin_array(length, semantic_tag::none, *this, ec); |
657 | 105k | more_ = !cursor_mode_; |
658 | 105k | } |
659 | 6.83M | else |
660 | 6.83M | { |
661 | 6.83M | state_stack_.emplace_back(parse_mode::indefinite_array,0); |
662 | 6.83M | visitor.begin_array(semantic_tag::none, *this, ec); |
663 | 6.83M | more_ = !cursor_mode_; |
664 | 6.83M | } |
665 | 6.98M | } |
666 | | |
667 | | void end_array(json_visitor& visitor, std::error_code& ec) |
668 | 6.93M | { |
669 | 6.93M | --nesting_depth_; |
670 | | |
671 | 6.93M | visitor.end_array(*this, ec); |
672 | 6.93M | more_ = !cursor_mode_; |
673 | 6.93M | if (level() == mark_level_) |
674 | 0 | { |
675 | 0 | more_ = false; |
676 | 0 | } |
677 | 6.93M | state_stack_.pop_back(); |
678 | 6.93M | } |
679 | | |
680 | | void begin_object(json_visitor& visitor, std::error_code& ec) |
681 | 4.66M | { |
682 | 4.66M | if (JSONCONS_UNLIKELY(++nesting_depth_ > max_nesting_depth_)) |
683 | 0 | { |
684 | 0 | ec = ubjson_errc::max_nesting_depth_exceeded; |
685 | 0 | more_ = false; |
686 | 0 | return; |
687 | 0 | } |
688 | | |
689 | 4.66M | auto c = source_.peek(); |
690 | 4.66M | if (JSONCONS_UNLIKELY(c.eof)) |
691 | 25 | { |
692 | 25 | ec = ubjson_errc::unexpected_eof; |
693 | 25 | more_ = false; |
694 | 25 | return; |
695 | 25 | } |
696 | 4.66M | if (c.value == jsoncons::ubjson::ubjson_type::type_marker) |
697 | 95.1k | { |
698 | 95.1k | source_.ignore(1); |
699 | 95.1k | uint8_t b; |
700 | 95.1k | if (source_.read(&b, 1) == 0) |
701 | 9 | { |
702 | 9 | ec = ubjson_errc::unexpected_eof; |
703 | 9 | more_ = false; |
704 | 9 | return; |
705 | 9 | } |
706 | 95.1k | c = source_.peek(); |
707 | 95.1k | if (JSONCONS_UNLIKELY(c.eof)) |
708 | 7 | { |
709 | 7 | ec = ubjson_errc::unexpected_eof; |
710 | 7 | more_ = false; |
711 | 7 | return; |
712 | 7 | } |
713 | 95.1k | if (c.value == jsoncons::ubjson::ubjson_type::count_marker) |
714 | 95.1k | { |
715 | 95.1k | source_.ignore(1); |
716 | 95.1k | std::size_t length = get_length(ec); |
717 | 95.1k | if (JSONCONS_UNLIKELY(ec)) |
718 | 8 | { |
719 | 8 | return; |
720 | 8 | } |
721 | 95.1k | if (length > max_items_) |
722 | 9 | { |
723 | 9 | ec = ubjson_errc::max_items_exceeded; |
724 | 9 | more_ = false; |
725 | 9 | return; |
726 | 9 | } |
727 | 95.1k | state_stack_.emplace_back(parse_mode::strongly_typed_map_key,length,b); |
728 | 95.1k | visitor.begin_object(length, semantic_tag::none, *this, ec); |
729 | 95.1k | more_ = !cursor_mode_; |
730 | 95.1k | } |
731 | 1 | else |
732 | 1 | { |
733 | 1 | ec = ubjson_errc::count_required_after_type; |
734 | 1 | more_ = false; |
735 | 1 | return; |
736 | 1 | } |
737 | 95.1k | } |
738 | 4.57M | else |
739 | 4.57M | { |
740 | 4.57M | c = source_.peek(); |
741 | 4.57M | if (JSONCONS_UNLIKELY(c.eof)) |
742 | 0 | { |
743 | 0 | ec = ubjson_errc::unexpected_eof; |
744 | 0 | more_ = false; |
745 | 0 | return; |
746 | 0 | } |
747 | 4.57M | if (c.value == jsoncons::ubjson::ubjson_type::count_marker) |
748 | 6.39k | { |
749 | 6.39k | source_.ignore(1); |
750 | 6.39k | std::size_t length = get_length(ec); |
751 | 6.39k | if (JSONCONS_UNLIKELY(ec)) |
752 | 5 | { |
753 | 5 | return; |
754 | 5 | } |
755 | 6.39k | if (length > max_items_) |
756 | 2 | { |
757 | 2 | ec = ubjson_errc::max_items_exceeded; |
758 | 2 | more_ = false; |
759 | 2 | return; |
760 | 2 | } |
761 | 6.38k | state_stack_.emplace_back(parse_mode::map_key,length); |
762 | 6.38k | visitor.begin_object(length, semantic_tag::none, *this, ec); |
763 | 6.38k | more_ = !cursor_mode_; |
764 | 6.38k | } |
765 | 4.56M | else |
766 | 4.56M | { |
767 | 4.56M | state_stack_.emplace_back(parse_mode::indefinite_map_key,0); |
768 | 4.56M | visitor.begin_object(semantic_tag::none, *this, ec); |
769 | 4.56M | more_ = !cursor_mode_; |
770 | 4.56M | } |
771 | 4.57M | } |
772 | 4.66M | } |
773 | | |
774 | | void end_object(json_visitor& visitor, std::error_code& ec) |
775 | 4.66M | { |
776 | 4.66M | --nesting_depth_; |
777 | 4.66M | visitor.end_object(*this, ec); |
778 | 4.66M | more_ = !cursor_mode_; |
779 | 4.66M | if (level() == mark_level_) |
780 | 0 | { |
781 | 0 | more_ = false; |
782 | 0 | } |
783 | 4.66M | state_stack_.pop_back(); |
784 | 4.66M | } |
785 | | |
786 | | std::size_t get_length(std::error_code& ec) |
787 | 6.85M | { |
788 | 6.85M | std::size_t length = 0; |
789 | 6.85M | uint8_t type; |
790 | 6.85M | if (source_.read(&type, 1) == 0) |
791 | 30 | { |
792 | 30 | ec = ubjson_errc::unexpected_eof; |
793 | 30 | more_ = false; |
794 | 30 | return length; |
795 | 30 | } |
796 | 6.85M | switch (type) |
797 | 6.85M | { |
798 | 1.41M | case jsoncons::ubjson::ubjson_type::int8_type: |
799 | 1.41M | { |
800 | 1.41M | uint8_t buf[sizeof(int8_t)]; |
801 | 1.41M | if (source_.read(buf, sizeof(int8_t)) != sizeof(int8_t)) |
802 | 1 | { |
803 | 1 | ec = ubjson_errc::unexpected_eof; |
804 | 1 | more_ = false; |
805 | 1 | return length; |
806 | 1 | } |
807 | 1.41M | int8_t val = binary::big_to_native<int8_t>(buf, sizeof(buf)); |
808 | 1.41M | if (val >= 0) |
809 | 1.41M | { |
810 | 1.41M | length = val; |
811 | 1.41M | } |
812 | 0 | else |
813 | 0 | { |
814 | 0 | ec = ubjson_errc::length_is_negative; |
815 | 0 | more_ = false; |
816 | 0 | return length; |
817 | 0 | } |
818 | 1.41M | break; |
819 | 1.41M | } |
820 | 5.42M | case jsoncons::ubjson::ubjson_type::uint8_type: |
821 | 5.42M | { |
822 | 5.42M | uint8_t b; |
823 | 5.42M | if (source_.read(&b, 1) == 0) |
824 | 0 | { |
825 | 0 | ec = ubjson_errc::unexpected_eof; |
826 | 0 | more_ = false; |
827 | 0 | return length; |
828 | 0 | } |
829 | 5.42M | length = b; |
830 | 5.42M | break; |
831 | 5.42M | } |
832 | 15.4k | case jsoncons::ubjson::ubjson_type::int16_type: |
833 | 15.4k | { |
834 | 15.4k | uint8_t buf[sizeof(int16_t)]; |
835 | 15.4k | if (source_.read(buf, sizeof(int16_t)) != sizeof(int16_t)) |
836 | 0 | { |
837 | 0 | ec = ubjson_errc::unexpected_eof; |
838 | 0 | more_ = false; |
839 | 0 | return length; |
840 | 0 | } |
841 | 15.4k | int16_t val = binary::big_to_native<int16_t>(buf, sizeof(buf)); |
842 | 15.4k | if (val >= 0) |
843 | 15.4k | { |
844 | 15.4k | length = val; |
845 | 15.4k | } |
846 | 0 | else |
847 | 0 | { |
848 | 0 | ec = ubjson_errc::length_is_negative; |
849 | 0 | more_ = false; |
850 | 0 | return length; |
851 | 0 | } |
852 | 15.4k | break; |
853 | 15.4k | } |
854 | 15.4k | case jsoncons::ubjson::ubjson_type::int32_type: |
855 | 874 | { |
856 | 874 | uint8_t buf[sizeof(int32_t)]; |
857 | 874 | if (source_.read(buf, sizeof(int32_t)) != sizeof(int32_t)) |
858 | 0 | { |
859 | 0 | ec = ubjson_errc::unexpected_eof; |
860 | 0 | more_ = false; |
861 | 0 | return length; |
862 | 0 | } |
863 | 874 | int32_t val = binary::big_to_native<int32_t>(buf, sizeof(buf)); |
864 | 874 | if (val >= 0) |
865 | 874 | { |
866 | 874 | length = static_cast<std::size_t>(val); |
867 | 874 | } |
868 | 0 | else |
869 | 0 | { |
870 | 0 | ec = ubjson_errc::length_is_negative; |
871 | 0 | more_ = false; |
872 | 0 | return length; |
873 | 0 | } |
874 | 874 | break; |
875 | 874 | } |
876 | 874 | case jsoncons::ubjson::ubjson_type::int64_type: |
877 | 112 | { |
878 | 112 | uint8_t buf[sizeof(int64_t)]; |
879 | 112 | if (source_.read(buf, sizeof(int64_t)) != sizeof(int64_t)) |
880 | 0 | { |
881 | 0 | ec = ubjson_errc::unexpected_eof; |
882 | 0 | more_ = false; |
883 | 0 | return length; |
884 | 0 | } |
885 | 112 | int64_t val = binary::big_to_native<int64_t>(buf, sizeof(buf)); |
886 | 112 | if (val >= 0) |
887 | 112 | { |
888 | 112 | length = (std::size_t)val; |
889 | 112 | if (length != (uint64_t)val) |
890 | 0 | { |
891 | 0 | ec = ubjson_errc::number_too_large; |
892 | 0 | more_ = false; |
893 | 0 | return length; |
894 | 0 | } |
895 | 112 | } |
896 | 0 | else |
897 | 0 | { |
898 | 0 | ec = ubjson_errc::length_is_negative; |
899 | 0 | more_ = false; |
900 | 0 | return length; |
901 | 0 | } |
902 | 112 | break; |
903 | 112 | } |
904 | 112 | default: |
905 | 45 | { |
906 | 45 | ec = ubjson_errc::length_must_be_integer; |
907 | 45 | more_ = false; |
908 | 45 | return length; |
909 | 112 | } |
910 | 6.85M | } |
911 | 6.85M | return length; |
912 | 6.85M | } |
913 | | |
914 | | void read_key(json_visitor& visitor, std::error_code& ec) |
915 | 6.57M | { |
916 | 6.57M | std::size_t length = get_length(ec); |
917 | 6.57M | if (JSONCONS_UNLIKELY(ec)) |
918 | 43 | { |
919 | 43 | ec = ubjson_errc::key_expected; |
920 | 43 | more_ = false; |
921 | 43 | return; |
922 | 43 | } |
923 | 6.57M | text_buffer_.clear(); |
924 | 6.57M | if (source_reader<Source>::read(source_,text_buffer_,length) != length) |
925 | 44 | { |
926 | 44 | ec = ubjson_errc::unexpected_eof; |
927 | 44 | more_ = false; |
928 | 44 | return; |
929 | 44 | } |
930 | | |
931 | 6.57M | auto result = unicode_traits::validate(text_buffer_.data(),text_buffer_.size()); |
932 | 6.57M | if (result.ec != unicode_traits::conv_errc()) |
933 | 20 | { |
934 | 20 | ec = ubjson_errc::invalid_utf8_text_string; |
935 | 20 | more_ = false; |
936 | 20 | return; |
937 | 20 | } |
938 | 6.57M | visitor.key(jsoncons::basic_string_view<char>(text_buffer_.data(),text_buffer_.length()), *this, ec); |
939 | 6.57M | more_ = !cursor_mode_; |
940 | 6.57M | } |
941 | | }; |
942 | | |
943 | | } // namespace ubjson |
944 | | } // namespace jsoncons |
945 | | |
946 | | #endif |