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