/src/jsoncons/include/jsoncons/staj_cursor.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_STAJ_CURSOR_HPP |
8 | | #define JSONCONS_STAJ_CURSOR_HPP |
9 | | |
10 | | #include <array> // std::array |
11 | | #include <cstddef> |
12 | | #include <cstdint> |
13 | | #include <functional> // std::function |
14 | | #include <ios> |
15 | | #include <memory> // std::allocator |
16 | | #include <system_error> |
17 | | |
18 | | #include <jsoncons/config/jsoncons_config.hpp> |
19 | | #include <jsoncons/allocator_set.hpp> |
20 | | #include <jsoncons/json_parser.hpp> |
21 | | #include <jsoncons/json_type.hpp> |
22 | | #include <jsoncons/json_visitor.hpp> |
23 | | #include <jsoncons/semantic_tag.hpp> |
24 | | #include <jsoncons/ser_util.hpp> |
25 | | #include <jsoncons/sink.hpp> |
26 | | #include <jsoncons/staj_event.hpp> |
27 | | #include <jsoncons/typed_array_view.hpp> |
28 | | #include <jsoncons/utility/bigint.hpp> |
29 | | #include <jsoncons/utility/write_number.hpp> |
30 | | #include <jsoncons/utility/conversion.hpp> |
31 | | |
32 | | namespace jsoncons { |
33 | | |
34 | | // basic_staj_visitor |
35 | | |
36 | | enum class staj_cursor_state |
37 | | { |
38 | | typed_array = 1, |
39 | | multi_dim, |
40 | | shape |
41 | | }; |
42 | | |
43 | | template <typename CharT> |
44 | | class basic_staj_visitor : public basic_json_visitor<CharT> |
45 | | { |
46 | | using super_type = basic_json_visitor<CharT>; |
47 | | public: |
48 | | using char_type = CharT; |
49 | | using typename super_type::string_view_type; |
50 | | private: |
51 | | basic_staj_event<CharT> event_; |
52 | | |
53 | | staj_cursor_state state_; |
54 | | typed_array_view data_; |
55 | | jsoncons::span<const size_t> shape_; |
56 | | std::size_t index_{0}; |
57 | | public: |
58 | | basic_staj_visitor() |
59 | 3.11k | : event_(staj_event_type::null_value), |
60 | 3.11k | state_(), data_(), shape_() |
61 | 3.11k | { |
62 | 3.11k | } |
63 | | |
64 | | ~basic_staj_visitor() = default; |
65 | | |
66 | | void reset() |
67 | | { |
68 | | event_ = staj_event_type::null_value; |
69 | | state_ = {}; |
70 | | data_ = {}; |
71 | | shape_ = {}; |
72 | | index_ = 0; |
73 | | } |
74 | | |
75 | | const basic_staj_event<CharT>& event() const |
76 | 1.83k | { |
77 | 1.83k | return event_; |
78 | 1.83k | } |
79 | | |
80 | | bool in_available() const |
81 | | { |
82 | | return state_ != staj_cursor_state(); |
83 | | } |
84 | | |
85 | | void send_available(std::error_code& ec) |
86 | | { |
87 | | switch (state_) |
88 | | { |
89 | | case staj_cursor_state::typed_array: |
90 | | advance_typed_array(ec); |
91 | | break; |
92 | | case staj_cursor_state::multi_dim: |
93 | | case staj_cursor_state::shape: |
94 | | advance_multi_dim(ec); |
95 | | break; |
96 | | default: |
97 | | break; |
98 | | } |
99 | | } |
100 | | |
101 | | bool is_typed_array() const |
102 | | { |
103 | | return data_.type() != typed_array_type(); |
104 | | } |
105 | | |
106 | | staj_cursor_state state() const |
107 | | { |
108 | | return state_; |
109 | | } |
110 | | |
111 | | void advance_typed_array(std::error_code& ec) |
112 | | { |
113 | | if (is_typed_array()) |
114 | | { |
115 | | if (index_ < data_.size()) |
116 | | { |
117 | | switch (data_.type()) |
118 | | { |
119 | | case typed_array_type::uint8_value: |
120 | | { |
121 | | this->uint64_value(data_.data(uint8_array_arg)[index_], semantic_tag::none, ser_context(), ec); |
122 | | break; |
123 | | } |
124 | | case typed_array_type::uint16_value: |
125 | | { |
126 | | this->uint64_value(data_.data(uint16_array_arg)[index_], semantic_tag::none, ser_context(), ec); |
127 | | break; |
128 | | } |
129 | | case typed_array_type::uint32_value: |
130 | | { |
131 | | this->uint64_value(data_.data(uint32_array_arg)[index_], semantic_tag::none, ser_context(), ec); |
132 | | break; |
133 | | } |
134 | | case typed_array_type::uint64_value: |
135 | | { |
136 | | this->uint64_value(data_.data(uint64_array_arg)[index_], semantic_tag::none, ser_context(), ec); |
137 | | break; |
138 | | } |
139 | | case typed_array_type::int8_value: |
140 | | { |
141 | | this->int64_value(data_.data(int8_array_arg)[index_], semantic_tag::none, ser_context(), ec); |
142 | | break; |
143 | | } |
144 | | case typed_array_type::int16_value: |
145 | | { |
146 | | this->int64_value(data_.data(int16_array_arg)[index_], semantic_tag::none, ser_context(), ec); |
147 | | break; |
148 | | } |
149 | | case typed_array_type::int32_value: |
150 | | { |
151 | | this->int64_value(data_.data(int32_array_arg)[index_], semantic_tag::none, ser_context(), ec); |
152 | | break; |
153 | | } |
154 | | case typed_array_type::int64_value: |
155 | | { |
156 | | this->int64_value(data_.data(int64_array_arg)[index_], semantic_tag::none, ser_context(), ec); |
157 | | break; |
158 | | } |
159 | | case typed_array_type::half_value: |
160 | | { |
161 | | this->half_value(data_.data(half_array_arg)[index_], semantic_tag::none, ser_context(), ec); |
162 | | break; |
163 | | } |
164 | | case typed_array_type::float_value: |
165 | | { |
166 | | this->double_value(data_.data(float_array_arg)[index_], semantic_tag::none, ser_context(), ec); |
167 | | break; |
168 | | } |
169 | | case typed_array_type::double_value: |
170 | | { |
171 | | this->double_value(data_.data(double_array_arg)[index_], semantic_tag::none, ser_context(), ec); |
172 | | break; |
173 | | } |
174 | | default: |
175 | | break; |
176 | | } |
177 | | ++index_; |
178 | | } |
179 | | else |
180 | | { |
181 | | this->end_array(); |
182 | | state_ = staj_cursor_state(); |
183 | | data_ = typed_array_view(); |
184 | | index_ = 0; |
185 | | } |
186 | | } |
187 | | } |
188 | | |
189 | | void advance_multi_dim(std::error_code& ec) |
190 | | { |
191 | | if (shape_.size() != 0) |
192 | | { |
193 | | if (state_ == staj_cursor_state::multi_dim) |
194 | | { |
195 | | this->begin_array(shape_.size(), semantic_tag::none, ser_context(), ec); |
196 | | state_ = staj_cursor_state::shape; |
197 | | } |
198 | | else if (index_ < shape_.size()) |
199 | | { |
200 | | this->uint64_value(shape_[index_], semantic_tag::none, ser_context(), ec); |
201 | | ++index_; |
202 | | } |
203 | | else |
204 | | { |
205 | | state_ = staj_cursor_state(); |
206 | | this->end_array(ser_context(), ec); |
207 | | shape_ = jsoncons::span<const size_t>(); |
208 | | index_ = 0; |
209 | | } |
210 | | } |
211 | | } |
212 | | |
213 | | void dump(basic_json_visitor<CharT>& visitor, const ser_context& context, std::error_code& ec) |
214 | | { |
215 | | if (is_typed_array()) |
216 | | { |
217 | | if (index_ != 0) |
218 | | { |
219 | | event().send_json_event(visitor, context, ec); |
220 | | const std::size_t len = data_.size(); |
221 | | switch (data_.type()) |
222 | | { |
223 | | case typed_array_type::uint8_value: |
224 | | { |
225 | | for (auto i = index_; i < len; ++i) |
226 | | { |
227 | | visitor.uint64_value(data_.data(uint8_array_arg)[i]); |
228 | | } |
229 | | break; |
230 | | } |
231 | | case typed_array_type::uint16_value: |
232 | | { |
233 | | for (auto i = index_; i < len; ++i) |
234 | | { |
235 | | visitor.uint64_value(data_.data(uint16_array_arg)[i]); |
236 | | } |
237 | | break; |
238 | | } |
239 | | case typed_array_type::uint32_value: |
240 | | { |
241 | | for (auto i = index_; i < len; ++i) |
242 | | { |
243 | | visitor.uint64_value(data_.data(uint32_array_arg)[i]); |
244 | | } |
245 | | break; |
246 | | } |
247 | | case typed_array_type::uint64_value: |
248 | | { |
249 | | for (auto i = index_; i < len; ++i) |
250 | | { |
251 | | visitor.uint64_value(data_.data(uint64_array_arg)[i]); |
252 | | } |
253 | | break; |
254 | | } |
255 | | case typed_array_type::int8_value: |
256 | | { |
257 | | for (auto i = index_; i < len; ++i) |
258 | | { |
259 | | visitor.int64_value(data_.data(int8_array_arg)[i]); |
260 | | } |
261 | | break; |
262 | | } |
263 | | case typed_array_type::int16_value: |
264 | | { |
265 | | for (auto i = index_; i < len; ++i) |
266 | | { |
267 | | visitor.int64_value(data_.data(int16_array_arg)[i]); |
268 | | } |
269 | | break; |
270 | | } |
271 | | case typed_array_type::int32_value: |
272 | | { |
273 | | for (auto i = index_; i < len; ++i) |
274 | | { |
275 | | visitor.int64_value(data_.data(int32_array_arg)[i]); |
276 | | } |
277 | | break; |
278 | | } |
279 | | case typed_array_type::int64_value: |
280 | | { |
281 | | for (auto i = index_; i < len; ++i) |
282 | | { |
283 | | visitor.int64_value(data_.data(int64_array_arg)[i]); |
284 | | } |
285 | | break; |
286 | | } |
287 | | case typed_array_type::float_value: |
288 | | { |
289 | | for (auto i = index_; i < len; ++i) |
290 | | { |
291 | | visitor.double_value(data_.data(float_array_arg)[i]); |
292 | | } |
293 | | break; |
294 | | } |
295 | | case typed_array_type::double_value: |
296 | | { |
297 | | for (auto i = index_; i < len; ++i) |
298 | | { |
299 | | visitor.double_value(data_.data(double_array_arg)[i]); |
300 | | } |
301 | | break; |
302 | | } |
303 | | default: |
304 | | break; |
305 | | } |
306 | | |
307 | | state_ = staj_cursor_state(); |
308 | | data_ = typed_array_view(); |
309 | | index_ = 0; |
310 | | } |
311 | | else |
312 | | { |
313 | | switch (data_.type()) |
314 | | { |
315 | | case typed_array_type::uint8_value: |
316 | | { |
317 | | visitor.typed_array(data_.data(uint8_array_arg)); |
318 | | break; |
319 | | } |
320 | | case typed_array_type::uint16_value: |
321 | | { |
322 | | visitor.typed_array(data_.data(uint16_array_arg)); |
323 | | break; |
324 | | } |
325 | | case typed_array_type::uint32_value: |
326 | | { |
327 | | visitor.typed_array(data_.data(uint32_array_arg)); |
328 | | break; |
329 | | } |
330 | | case typed_array_type::uint64_value: |
331 | | { |
332 | | visitor.typed_array(data_.data(uint64_array_arg)); |
333 | | break; |
334 | | } |
335 | | case typed_array_type::int8_value: |
336 | | { |
337 | | visitor.typed_array(data_.data(int8_array_arg)); |
338 | | break; |
339 | | } |
340 | | case typed_array_type::int16_value: |
341 | | { |
342 | | visitor.typed_array(data_.data(int16_array_arg)); |
343 | | break; |
344 | | } |
345 | | case typed_array_type::int32_value: |
346 | | { |
347 | | visitor.typed_array(data_.data(int32_array_arg)); |
348 | | break; |
349 | | } |
350 | | case typed_array_type::int64_value: |
351 | | { |
352 | | visitor.typed_array(data_.data(int64_array_arg)); |
353 | | break; |
354 | | } |
355 | | case typed_array_type::float_value: |
356 | | { |
357 | | visitor.typed_array(data_.data(float_array_arg)); |
358 | | break; |
359 | | } |
360 | | case typed_array_type::double_value: |
361 | | { |
362 | | visitor.typed_array(data_.data(double_array_arg)); |
363 | | break; |
364 | | } |
365 | | default: |
366 | | break; |
367 | | } |
368 | | |
369 | | state_ = staj_cursor_state(); |
370 | | data_ = typed_array_view(); |
371 | | } |
372 | | } |
373 | | else |
374 | | { |
375 | | event().send_json_event(visitor, context, ec); |
376 | | } |
377 | | } |
378 | | |
379 | | private: |
380 | | static constexpr bool accept(const basic_staj_event<CharT>&, const ser_context&) |
381 | | { |
382 | | return true; |
383 | | } |
384 | | |
385 | | JSONCONS_VISITOR_RETURN_TYPE visit_begin_object(semantic_tag tag, const ser_context&, std::error_code&) override |
386 | 1 | { |
387 | 1 | event_ = basic_staj_event<CharT>(staj_event_type::begin_object, tag); |
388 | 1 | JSONCONS_VISITOR_RETURN; |
389 | 1 | } |
390 | | |
391 | | JSONCONS_VISITOR_RETURN_TYPE visit_begin_object(std::size_t length, semantic_tag tag, const ser_context&, std::error_code&) override |
392 | 0 | { |
393 | 0 | event_ = basic_staj_event<CharT>(staj_event_type::begin_object, length, tag); |
394 | 0 | JSONCONS_VISITOR_RETURN; |
395 | 0 | } |
396 | | |
397 | | JSONCONS_VISITOR_RETURN_TYPE visit_end_object(const ser_context&, std::error_code&) override |
398 | 0 | { |
399 | 0 | event_ = basic_staj_event<CharT>(staj_event_type::end_object); |
400 | 0 | JSONCONS_VISITOR_RETURN; |
401 | 0 | } |
402 | | |
403 | | JSONCONS_VISITOR_RETURN_TYPE visit_begin_array(semantic_tag tag, const ser_context&, std::error_code&) override |
404 | 1 | { |
405 | 1 | event_ = basic_staj_event<CharT>(staj_event_type::begin_array, tag); |
406 | 1 | JSONCONS_VISITOR_RETURN; |
407 | 1 | } |
408 | | |
409 | | JSONCONS_VISITOR_RETURN_TYPE visit_begin_array(std::size_t length, semantic_tag tag, const ser_context&, std::error_code&) override |
410 | 0 | { |
411 | 0 | event_ = basic_staj_event<CharT>(staj_event_type::begin_array, length, tag); |
412 | 0 | JSONCONS_VISITOR_RETURN; |
413 | 0 | } |
414 | | |
415 | | JSONCONS_VISITOR_RETURN_TYPE visit_end_array(const ser_context&, std::error_code&) override |
416 | 0 | { |
417 | 0 | event_ = basic_staj_event<CharT>(staj_event_type::end_array); |
418 | 0 | JSONCONS_VISITOR_RETURN; |
419 | 0 | } |
420 | | |
421 | | JSONCONS_VISITOR_RETURN_TYPE visit_key(const string_view_type& name, const ser_context&, std::error_code&) override |
422 | 0 | { |
423 | 0 | event_ = basic_staj_event<CharT>(name, staj_event_type::key); |
424 | 0 | JSONCONS_VISITOR_RETURN; |
425 | 0 | } |
426 | | |
427 | | JSONCONS_VISITOR_RETURN_TYPE visit_null(semantic_tag tag, const ser_context&, std::error_code&) override |
428 | 2 | { |
429 | 2 | event_ = basic_staj_event<CharT>(staj_event_type::null_value, tag); |
430 | 2 | JSONCONS_VISITOR_RETURN; |
431 | 2 | } |
432 | | |
433 | | JSONCONS_VISITOR_RETURN_TYPE visit_bool(bool value, semantic_tag tag, const ser_context&, std::error_code&) override |
434 | 5 | { |
435 | 5 | event_ = basic_staj_event<CharT>(value, tag); |
436 | 5 | JSONCONS_VISITOR_RETURN; |
437 | 5 | } |
438 | | |
439 | | JSONCONS_VISITOR_RETURN_TYPE visit_string(const string_view_type& s, semantic_tag tag, const ser_context&, std::error_code&) override |
440 | 380 | { |
441 | 380 | event_ = basic_staj_event<CharT>(s, staj_event_type::string_value, tag); |
442 | 380 | JSONCONS_VISITOR_RETURN; |
443 | 380 | } |
444 | | |
445 | | JSONCONS_VISITOR_RETURN_TYPE visit_byte_string(const byte_string_view& s, |
446 | | semantic_tag tag, |
447 | | const ser_context&, |
448 | | std::error_code&) override |
449 | 0 | { |
450 | 0 | event_ = basic_staj_event<CharT>(s, staj_event_type::byte_string_value, tag); |
451 | 0 | JSONCONS_VISITOR_RETURN; |
452 | 0 | } |
453 | | |
454 | | JSONCONS_VISITOR_RETURN_TYPE visit_byte_string(const byte_string_view& s, |
455 | | uint64_t ext_tag, |
456 | | const ser_context&, |
457 | | std::error_code&) override |
458 | 0 | { |
459 | 0 | event_ = basic_staj_event<CharT>(s, staj_event_type::byte_string_value, ext_tag); |
460 | 0 | JSONCONS_VISITOR_RETURN; |
461 | 0 | } |
462 | | |
463 | | JSONCONS_VISITOR_RETURN_TYPE visit_uint64(uint64_t value, |
464 | | semantic_tag tag, |
465 | | const ser_context&, |
466 | | std::error_code&) override |
467 | 263 | { |
468 | 263 | event_ = basic_staj_event<CharT>(value, tag); |
469 | 263 | JSONCONS_VISITOR_RETURN; |
470 | 263 | } |
471 | | |
472 | | JSONCONS_VISITOR_RETURN_TYPE visit_int64(int64_t value, |
473 | | semantic_tag tag, |
474 | | const ser_context&, |
475 | | std::error_code&) override |
476 | 261 | { |
477 | 261 | event_ = basic_staj_event<CharT>(value, tag); |
478 | 261 | JSONCONS_VISITOR_RETURN; |
479 | 261 | } |
480 | | |
481 | | JSONCONS_VISITOR_RETURN_TYPE visit_half(uint16_t value, |
482 | | semantic_tag tag, |
483 | | const ser_context&, |
484 | | std::error_code&) override |
485 | 0 | { |
486 | 0 | event_ = basic_staj_event<CharT>(half_arg, value, tag); |
487 | 0 | JSONCONS_VISITOR_RETURN; |
488 | 0 | } |
489 | | |
490 | | JSONCONS_VISITOR_RETURN_TYPE visit_double(double value, |
491 | | semantic_tag tag, |
492 | | const ser_context&, |
493 | | std::error_code&) override |
494 | 924 | { |
495 | 924 | event_ = basic_staj_event<CharT>(value, tag); |
496 | 924 | JSONCONS_VISITOR_RETURN; |
497 | 924 | } |
498 | | |
499 | | JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const uint8_t>& v, |
500 | | semantic_tag tag, |
501 | | const ser_context& context, |
502 | | std::error_code& ec) override |
503 | 0 | { |
504 | 0 | state_ = staj_cursor_state::typed_array; |
505 | 0 | data_ = typed_array_view(v.data(), v.size()); |
506 | 0 | index_ = 0; |
507 | 0 | this->begin_array(tag, context, ec); |
508 | 0 | JSONCONS_VISITOR_RETURN; |
509 | 0 | } |
510 | | |
511 | | JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const uint16_t>& data, |
512 | | semantic_tag tag, |
513 | | const ser_context& context, |
514 | | std::error_code& ec) override |
515 | 0 | { |
516 | 0 | state_ = staj_cursor_state::typed_array; |
517 | 0 | data_ = typed_array_view(data.data(), data.size()); |
518 | 0 | index_ = 0; |
519 | 0 | this->begin_array(tag, context, ec); |
520 | 0 | JSONCONS_VISITOR_RETURN; |
521 | 0 | } |
522 | | |
523 | | JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const uint32_t>& data, |
524 | | semantic_tag tag, |
525 | | const ser_context& context, |
526 | | std::error_code& ec) override |
527 | 0 | { |
528 | 0 | state_ = staj_cursor_state::typed_array; |
529 | 0 | data_ = typed_array_view(data.data(), data.size()); |
530 | 0 | index_ = 0; |
531 | 0 | this->begin_array(tag, context, ec); |
532 | 0 | JSONCONS_VISITOR_RETURN; |
533 | 0 | } |
534 | | |
535 | | JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const uint64_t>& data, |
536 | | semantic_tag tag, |
537 | | const ser_context& context, |
538 | | std::error_code& ec) override |
539 | 0 | { |
540 | 0 | state_ = staj_cursor_state::typed_array; |
541 | 0 | data_ = typed_array_view(data.data(), data.size()); |
542 | 0 | index_ = 0; |
543 | 0 | this->begin_array(tag, context, ec); |
544 | 0 | JSONCONS_VISITOR_RETURN; |
545 | 0 | } |
546 | | |
547 | | JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const int8_t>& data, |
548 | | semantic_tag tag, |
549 | | const ser_context& context, |
550 | | std::error_code& ec) override |
551 | 0 | { |
552 | 0 | state_ = staj_cursor_state::typed_array; |
553 | 0 | data_ = typed_array_view(data.data(), data.size()); |
554 | 0 | index_ = 0; |
555 | 0 | this->begin_array(tag, context, ec); |
556 | 0 | JSONCONS_VISITOR_RETURN; |
557 | 0 | } |
558 | | |
559 | | JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const int16_t>& data, |
560 | | semantic_tag tag, |
561 | | const ser_context& context, |
562 | | std::error_code& ec) override |
563 | 0 | { |
564 | 0 | state_ = staj_cursor_state::typed_array; |
565 | 0 | data_ = typed_array_view(data.data(), data.size()); |
566 | 0 | index_ = 0; |
567 | 0 | this->begin_array(tag, context, ec); |
568 | 0 | JSONCONS_VISITOR_RETURN; |
569 | 0 | } |
570 | | |
571 | | JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const int32_t>& data, |
572 | | semantic_tag tag, |
573 | | const ser_context& context, |
574 | | std::error_code& ec) override |
575 | 0 | { |
576 | 0 | state_ = staj_cursor_state::typed_array; |
577 | 0 | data_ = typed_array_view(data.data(), data.size()); |
578 | 0 | index_ = 0; |
579 | 0 | this->begin_array(tag, context, ec); |
580 | 0 | JSONCONS_VISITOR_RETURN; |
581 | 0 | } |
582 | | |
583 | | JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const int64_t>& data, |
584 | | semantic_tag tag, |
585 | | const ser_context& context, |
586 | | std::error_code& ec) override |
587 | 0 | { |
588 | 0 | state_ = staj_cursor_state::typed_array; |
589 | 0 | data_ = typed_array_view(data.data(), data.size()); |
590 | 0 | index_ = 0; |
591 | 0 | this->begin_array(tag, context, ec); |
592 | 0 | JSONCONS_VISITOR_RETURN; |
593 | 0 | } |
594 | | |
595 | | JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(half_arg_t, const jsoncons::span<const uint16_t>& data, |
596 | | semantic_tag tag, |
597 | | const ser_context& context, |
598 | | std::error_code& ec) override |
599 | 0 | { |
600 | 0 | state_ = staj_cursor_state::typed_array; |
601 | 0 | data_ = typed_array_view(data.data(), data.size()); |
602 | 0 | index_ = 0; |
603 | 0 | this->begin_array(tag, context, ec); |
604 | 0 | JSONCONS_VISITOR_RETURN; |
605 | 0 | } |
606 | | |
607 | | JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const float>& data, |
608 | | semantic_tag tag, |
609 | | const ser_context& context, |
610 | | std::error_code& ec) override |
611 | 0 | { |
612 | 0 | state_ = staj_cursor_state::typed_array; |
613 | 0 | data_ = typed_array_view(data.data(), data.size()); |
614 | 0 | index_ = 0; |
615 | 0 | this->begin_array(tag, context, ec); |
616 | 0 | JSONCONS_VISITOR_RETURN; |
617 | 0 | } |
618 | | |
619 | | JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const double>& data, |
620 | | semantic_tag tag, |
621 | | const ser_context& context, |
622 | | std::error_code& ec) override |
623 | 0 | { |
624 | 0 | state_ = staj_cursor_state::typed_array; |
625 | 0 | data_ = typed_array_view(data.data(), data.size()); |
626 | 0 | index_ = 0; |
627 | 0 | this->begin_array(tag, context, ec); |
628 | 0 | JSONCONS_VISITOR_RETURN; |
629 | 0 | } |
630 | | /* |
631 | | JSONCONS_VISITOR_RETURN_TYPE visit_typed_array(const jsoncons::span<const float128_type>&, |
632 | | semantic_tag, |
633 | | const ser_context&, |
634 | | std::error_code&) override |
635 | | { |
636 | | JSONCONS_VISITOR_RETURN; |
637 | | } |
638 | | */ |
639 | | JSONCONS_VISITOR_RETURN_TYPE visit_begin_multi_dim(const jsoncons::span<const size_t>& shape, |
640 | | semantic_tag tag, |
641 | | const ser_context& context, |
642 | | std::error_code& ec) override |
643 | 0 | { |
644 | 0 | state_ = staj_cursor_state::multi_dim; |
645 | 0 | shape_ = shape; |
646 | 0 | this->begin_array(2, tag, context, ec); |
647 | 0 | JSONCONS_VISITOR_RETURN; |
648 | 0 | } |
649 | | |
650 | | JSONCONS_VISITOR_RETURN_TYPE visit_end_multi_dim(const ser_context& context, |
651 | | std::error_code& ec) override |
652 | 0 | { |
653 | 0 | this->end_array(context, ec); |
654 | 0 | JSONCONS_VISITOR_RETURN; |
655 | 0 | } |
656 | | |
657 | | void visit_flush() override |
658 | 1.83k | { |
659 | 1.83k | } |
660 | | }; |
661 | | |
662 | | |
663 | | // basic_staj_cursor |
664 | | |
665 | | template <typename CharT> |
666 | | class basic_staj_cursor |
667 | | { |
668 | | public: |
669 | 3.11k | virtual ~basic_staj_cursor() = default; |
670 | | |
671 | | virtual void array_expected(std::error_code& ec) |
672 | 0 | { |
673 | 0 | if (!(current().event_type() == staj_event_type::begin_array || current().event_type() == staj_event_type::byte_string_value)) |
674 | 0 | { |
675 | 0 | ec = conv_errc::not_vector; |
676 | 0 | } |
677 | 0 | } |
678 | | |
679 | | virtual bool done() const = 0; |
680 | | |
681 | | virtual const basic_staj_event<CharT>& current() const = 0; |
682 | | |
683 | | virtual void read_to(basic_json_visitor<CharT>& visitor) = 0; |
684 | | |
685 | | virtual void read_to(basic_json_visitor<CharT>& visitor, |
686 | | std::error_code& ec) = 0; |
687 | | |
688 | | virtual void next() = 0; |
689 | | |
690 | | virtual void next(std::error_code& ec) = 0; |
691 | | |
692 | | virtual const ser_context& context() const = 0; |
693 | | |
694 | | virtual std::size_t line() const = 0; |
695 | | |
696 | | virtual std::size_t column() const = 0; |
697 | | |
698 | | }; |
699 | | |
700 | | template <typename CharT> |
701 | | class basic_staj_filter_view : basic_staj_cursor<CharT> |
702 | | { |
703 | | basic_staj_cursor<CharT>* cursor_; |
704 | | std::function<bool(const basic_staj_event<CharT>&, const ser_context&)> pred_; |
705 | | public: |
706 | | basic_staj_filter_view(basic_staj_cursor<CharT>& cursor, |
707 | | std::function<bool(const basic_staj_event<CharT>&, const ser_context&)> pred) |
708 | | : cursor_(std::addressof(cursor)), pred_(pred) |
709 | | { |
710 | | while (!done() && !pred_(current(),context())) |
711 | | { |
712 | | cursor_->next(); |
713 | | } |
714 | | } |
715 | | |
716 | | bool done() const override |
717 | | { |
718 | | return cursor_->done(); |
719 | | } |
720 | | |
721 | | const basic_staj_event<CharT>& current() const override |
722 | | { |
723 | | return cursor_->current(); |
724 | | } |
725 | | |
726 | | void read_to(basic_json_visitor<CharT>& visitor) override |
727 | | { |
728 | | cursor_->read_to(visitor); |
729 | | } |
730 | | |
731 | | void read_to(basic_json_visitor<CharT>& visitor, |
732 | | std::error_code& ec) override |
733 | | { |
734 | | cursor_->read_to(visitor, ec); |
735 | | } |
736 | | |
737 | | void next() override |
738 | | { |
739 | | cursor_->next(); |
740 | | while (!done() && !pred_(current(),context())) |
741 | | { |
742 | | cursor_->next(); |
743 | | } |
744 | | } |
745 | | |
746 | | void next(std::error_code& ec) override |
747 | | { |
748 | | cursor_->next(ec); |
749 | | while (!done() && !pred_(current(),context()) && !ec) |
750 | | { |
751 | | cursor_->next(ec); |
752 | | } |
753 | | } |
754 | | |
755 | | const ser_context& context() const override |
756 | | { |
757 | | return cursor_->context(); |
758 | | } |
759 | | |
760 | | std::size_t line() const override |
761 | | { |
762 | | return cursor_->line(); |
763 | | } |
764 | | |
765 | | std::size_t column() const override |
766 | | { |
767 | | return cursor_->column(); |
768 | | } |
769 | | |
770 | | friend |
771 | | basic_staj_filter_view<CharT> operator|(basic_staj_filter_view& cursor, |
772 | | std::function<bool(const basic_staj_event<CharT>&, const ser_context&)> pred) |
773 | | { |
774 | | return basic_staj_filter_view<CharT>(cursor, pred); |
775 | | } |
776 | | }; |
777 | | |
778 | | template <typename Json,typename Alloc,typename TempAlloc> |
779 | | read_result<Json> to_json_single(const allocator_set<Alloc,TempAlloc>& aset, |
780 | | basic_staj_cursor<typename Json::char_type>& cursor) |
781 | | { |
782 | | using result_type = read_result<Json>; |
783 | | |
784 | | std::error_code ec; |
785 | | switch (cursor.current().event_type()) |
786 | | { |
787 | | case staj_event_type::string_value: |
788 | | { |
789 | | auto sv = cursor.current().template get<jsoncons::basic_string_view<typename Json::char_type>>(ec); |
790 | | if (ec) return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
791 | | return result_type{jsoncons::make_obj_using_allocator<Json>(aset.get_allocator(), |
792 | | sv.data(), sv.length(), cursor.current().tag())}; |
793 | | } |
794 | | case staj_event_type::byte_string_value: |
795 | | { |
796 | | auto j = jsoncons::make_obj_using_allocator<Json>(aset.get_allocator(), |
797 | | byte_string_arg, cursor.current().template get<byte_string_view>(ec), cursor.current().tag()); |
798 | | return !ec ? result_type(std::move(j)) : result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
799 | | } |
800 | | case staj_event_type::null_value: |
801 | | { |
802 | | return result_type(Json{null_arg, semantic_tag::none}); |
803 | | } |
804 | | case staj_event_type::bool_value: |
805 | | { |
806 | | auto j = Json{cursor.current().template get<bool>(ec), cursor.current().tag()}; |
807 | | return !ec ? result_type(std::move(j)) : result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
808 | | } |
809 | | case staj_event_type::int64_value: |
810 | | { |
811 | | auto j = Json{cursor.current().template get<std::int64_t>(ec), cursor.current().tag()}; |
812 | | return !ec ? result_type(std::move(j)) : result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
813 | | } |
814 | | case staj_event_type::uint64_value: |
815 | | { |
816 | | auto j = Json{cursor.current().template get<std::uint64_t>(ec), cursor.current().tag()}; |
817 | | return !ec ? result_type(std::move(j)) : result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
818 | | } |
819 | | case staj_event_type::half_value: |
820 | | { |
821 | | auto j = Json{half_arg, cursor.current().template get<std::uint16_t>(ec), cursor.current().tag()}; |
822 | | return !ec ? result_type(std::move(j)) : result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
823 | | } |
824 | | case staj_event_type::double_value: |
825 | | { |
826 | | auto j = Json{cursor.current().template get<double>(ec), cursor.current().tag()}; |
827 | | return !ec ? result_type(std::move(j)) : result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
828 | | } |
829 | | default: |
830 | | return result_type(jsoncons::unexpect, conv_errc::conversion_failed, cursor.line(), cursor.column()); |
831 | | } |
832 | | } |
833 | | |
834 | | template <typename Json, typename Alloc, typename TempAlloc> |
835 | | read_result<Json> to_json_container(const allocator_set<Alloc,TempAlloc>& aset, |
836 | | basic_staj_cursor<typename Json::char_type>& cursor) |
837 | | { |
838 | | using result_type = read_result<Json>; |
839 | | using json_ptr_allocator_type = typename std::allocator_traits<TempAlloc>:: template rebind_alloc<Json*>; |
840 | | using char_type = typename Json::char_type; |
841 | | using char_allocator_type = typename std::allocator_traits<TempAlloc>:: template rebind_alloc<char_type>; |
842 | | using key_type = std::basic_string<char_type,std::char_traits<char_type>, char_allocator_type>; |
843 | | |
844 | | std::error_code ec; |
845 | | |
846 | | auto cont = cursor.current().event_type() == staj_event_type::begin_object ? |
847 | | jsoncons::make_obj_using_allocator<Json>(aset.get_allocator(), json_object_arg, semantic_tag::none) : |
848 | | jsoncons::make_obj_using_allocator<Json>(aset.get_allocator(), json_array_arg, semantic_tag::none); |
849 | | std::vector<Json*,json_ptr_allocator_type> stack(aset.get_temp_allocator()); |
850 | | stack.push_back(std::addressof(cont)); |
851 | | key_type key(aset.get_temp_allocator()); |
852 | | if (cursor.current().event_type() == staj_event_type::begin_object) |
853 | | { |
854 | | goto begin_object; |
855 | | } |
856 | | goto begin_array; |
857 | | |
858 | | begin_object: |
859 | | cursor.next(ec); |
860 | | if (JSONCONS_UNLIKELY(ec)) |
861 | | { |
862 | | return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
863 | | } |
864 | | while (!cursor.done() && !stack.empty()) |
865 | | { |
866 | | switch (cursor.current().event_type()) |
867 | | { |
868 | | case staj_event_type::begin_object: |
869 | | { |
870 | | auto result = stack.back()->try_emplace(key, json_object_arg); |
871 | | stack.push_back(std::addressof(result.first->value())); |
872 | | goto begin_object; |
873 | | } |
874 | | case staj_event_type::begin_array: |
875 | | { |
876 | | auto result = stack.back()->try_emplace(key, json_array_arg); |
877 | | stack.push_back(std::addressof(result.first->value())); |
878 | | goto begin_array; |
879 | | } |
880 | | case staj_event_type::key: |
881 | | { |
882 | | auto sv = cursor.current().template get<basic_string_view<char_type>>(ec); |
883 | | if (JSONCONS_UNLIKELY(ec)) |
884 | | { |
885 | | return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
886 | | } |
887 | | key = key_type(sv.data(), sv.length(), aset.get_temp_allocator()); |
888 | | break; |
889 | | } |
890 | | case staj_event_type::string_value: |
891 | | stack.back()->try_emplace(key, cursor.current().template get<jsoncons::basic_string_view<char_type>>(ec), cursor.current().tag()); |
892 | | if (JSONCONS_UNLIKELY(ec)) |
893 | | { |
894 | | return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
895 | | } |
896 | | break; |
897 | | case staj_event_type::byte_string_value: |
898 | | stack.back()->try_emplace(key, byte_string_arg, cursor.current().template get<byte_string_view>(ec), cursor.current().tag()); |
899 | | if (JSONCONS_UNLIKELY(ec)) |
900 | | { |
901 | | return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
902 | | } |
903 | | break; |
904 | | case staj_event_type::null_value: |
905 | | stack.back()->try_emplace(key, null_arg); |
906 | | break; |
907 | | case staj_event_type::bool_value: |
908 | | stack.back()->try_emplace(key, cursor.current().template get<bool>(ec), cursor.current().tag()); |
909 | | if (JSONCONS_UNLIKELY(ec)) |
910 | | { |
911 | | return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
912 | | } |
913 | | break; |
914 | | case staj_event_type::int64_value: |
915 | | stack.back()->try_emplace(key, cursor.current().template get<std::int64_t>(ec), cursor.current().tag()); |
916 | | if (JSONCONS_UNLIKELY(ec)) |
917 | | { |
918 | | return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
919 | | } |
920 | | break; |
921 | | case staj_event_type::uint64_value: |
922 | | stack.back()->try_emplace(key, cursor.current().template get<std::uint64_t>(ec), cursor.current().tag()); |
923 | | if (JSONCONS_UNLIKELY(ec)) |
924 | | { |
925 | | return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
926 | | } |
927 | | break; |
928 | | case staj_event_type::half_value: |
929 | | stack.back()->try_emplace(key, half_arg, cursor.current().template get<std::uint16_t>(ec), cursor.current().tag()); |
930 | | if (JSONCONS_UNLIKELY(ec)) |
931 | | { |
932 | | return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
933 | | } |
934 | | break; |
935 | | case staj_event_type::double_value: |
936 | | stack.back()->try_emplace(key, cursor.current().template get<double>(ec), cursor.current().tag()); |
937 | | if (JSONCONS_UNLIKELY(ec)) |
938 | | { |
939 | | return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
940 | | } |
941 | | break; |
942 | | case staj_event_type::end_object: |
943 | | stack.pop_back(); |
944 | | if (stack.empty()) |
945 | | { |
946 | | return result_type(std::move(cont)); |
947 | | } |
948 | | if (stack.back()->type() == json_type::object) |
949 | | { |
950 | | goto begin_object; |
951 | | } |
952 | | goto begin_array; |
953 | | break; |
954 | | default: |
955 | | return result_type(jsoncons::unexpect, conv_errc::conversion_failed, cursor.line(), cursor.column()); |
956 | | } |
957 | | cursor.next(ec); |
958 | | if (JSONCONS_UNLIKELY(ec)) |
959 | | { |
960 | | return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
961 | | } |
962 | | } |
963 | | return result_type(std::move(cont)); |
964 | | |
965 | | begin_array: |
966 | | cursor.next(ec); |
967 | | if (JSONCONS_UNLIKELY(ec)) |
968 | | { |
969 | | return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
970 | | } |
971 | | while (!cursor.done() && !stack.empty()) |
972 | | { |
973 | | switch (cursor.current().event_type()) |
974 | | { |
975 | | case staj_event_type::begin_object: |
976 | | { |
977 | | auto& result = stack.back()->emplace_back(json_object_arg); |
978 | | stack.push_back(std::addressof(result)); |
979 | | goto begin_object; |
980 | | } |
981 | | case staj_event_type::begin_array: |
982 | | { |
983 | | auto& result = stack.back()->emplace_back(json_array_arg); |
984 | | stack.push_back(std::addressof(result)); |
985 | | goto begin_array; |
986 | | } |
987 | | case staj_event_type::string_value: |
988 | | stack.back()->emplace_back(cursor.current().template get<jsoncons::basic_string_view<char_type>>(ec), cursor.current().tag()); |
989 | | if (JSONCONS_UNLIKELY(ec)) |
990 | | { |
991 | | return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
992 | | } |
993 | | break; |
994 | | case staj_event_type::byte_string_value: |
995 | | stack.back()->emplace_back(byte_string_arg, cursor.current().template get<byte_string_view>(ec), cursor.current().tag()); |
996 | | if (JSONCONS_UNLIKELY(ec)) |
997 | | { |
998 | | return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
999 | | } |
1000 | | break; |
1001 | | case staj_event_type::null_value: |
1002 | | stack.back()->emplace_back(null_arg); |
1003 | | break; |
1004 | | case staj_event_type::bool_value: |
1005 | | stack.back()->emplace_back(cursor.current().template get<bool>(ec), cursor.current().tag()); |
1006 | | if (JSONCONS_UNLIKELY(ec)) |
1007 | | { |
1008 | | return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
1009 | | } |
1010 | | break; |
1011 | | case staj_event_type::int64_value: |
1012 | | stack.back()->emplace_back(cursor.current().template get<std::int64_t>(ec), cursor.current().tag()); |
1013 | | if (JSONCONS_UNLIKELY(ec)) |
1014 | | { |
1015 | | return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
1016 | | } |
1017 | | break; |
1018 | | case staj_event_type::uint64_value: |
1019 | | stack.back()->emplace_back(cursor.current().template get<std::uint64_t>(ec), cursor.current().tag()); |
1020 | | if (JSONCONS_UNLIKELY(ec)) |
1021 | | { |
1022 | | return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
1023 | | } |
1024 | | break; |
1025 | | case staj_event_type::half_value: |
1026 | | stack.back()->emplace_back(half_arg, cursor.current().template get<std::uint16_t>(ec), cursor.current().tag()); |
1027 | | if (JSONCONS_UNLIKELY(ec)) |
1028 | | { |
1029 | | return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
1030 | | } |
1031 | | break; |
1032 | | case staj_event_type::double_value: |
1033 | | stack.back()->emplace_back(cursor.current().template get<double>(ec), cursor.current().tag()); |
1034 | | if (JSONCONS_UNLIKELY(ec)) |
1035 | | { |
1036 | | return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
1037 | | } |
1038 | | break; |
1039 | | case staj_event_type::end_array: |
1040 | | stack.pop_back(); |
1041 | | if (stack.empty()) |
1042 | | { |
1043 | | return cont; |
1044 | | } |
1045 | | if (stack.back()->type() == json_type::object) |
1046 | | { |
1047 | | goto begin_object; |
1048 | | } |
1049 | | goto begin_array; |
1050 | | break; |
1051 | | default: |
1052 | | return result_type(jsoncons::unexpect, conv_errc::conversion_failed, cursor.line(), cursor.column()); |
1053 | | } |
1054 | | cursor.next(ec); |
1055 | | if (JSONCONS_UNLIKELY(ec)) |
1056 | | { |
1057 | | return result_type(jsoncons::unexpect, ec, cursor.line(), cursor.column()); |
1058 | | } |
1059 | | } |
1060 | | |
1061 | | JSONCONS_UNREACHABLE(); |
1062 | | } |
1063 | | |
1064 | | template <typename Json, typename Alloc, typename TempAlloc> |
1065 | | read_result<Json> try_to_json(const allocator_set<Alloc,TempAlloc>& aset, |
1066 | | basic_staj_cursor<typename Json::char_type>& cursor) |
1067 | | { |
1068 | | using result_type = read_result<Json>; |
1069 | | |
1070 | | if (JSONCONS_UNLIKELY(is_end_container(cursor.current().event_type()))) |
1071 | | { |
1072 | | return result_type(jsoncons::unexpect, conv_errc::conversion_failed, cursor.line(), cursor.column()); |
1073 | | } |
1074 | | if (!is_begin_container(cursor.current().event_type())) |
1075 | | { |
1076 | | return to_json_single<Json>(aset, cursor); |
1077 | | } |
1078 | | return to_json_container<Json>(aset, cursor); |
1079 | | } |
1080 | | |
1081 | | template <typename Json> |
1082 | | read_result<Json> try_to_json(basic_staj_cursor<typename Json::char_type>& cursor) |
1083 | | { |
1084 | | return try_to_json<Json>(allocator_set<typename Json::allocator_type, std::allocator<char>>(), cursor); |
1085 | | } |
1086 | | |
1087 | | using staj_event = basic_staj_event<char>; |
1088 | | using wstaj_event = basic_staj_event<wchar_t>; |
1089 | | |
1090 | | using staj_cursor = basic_staj_cursor<char>; |
1091 | | using wstaj_cursor = basic_staj_cursor<wchar_t>; |
1092 | | |
1093 | | using staj_filter_view = basic_staj_filter_view<char>; |
1094 | | using wstaj_filter_view = basic_staj_filter_view<wchar_t>; |
1095 | | |
1096 | | } // namespace jsoncons |
1097 | | |
1098 | | #endif // JSONCONS_STAJ_CURSOR_HPP |
1099 | | |