/src/jsoncons/include/jsoncons_ext/bson/bson_parser.hpp
Line | Count | Source |
1 | | // Copyright 2013-2026 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_BSON_BSON_PARSER_HPP |
8 | | #define JSONCONS_EXT_BSON_BSON_PARSER_HPP |
9 | | |
10 | | #include <cstddef> |
11 | | #include <cstdint> |
12 | | #include <memory> |
13 | | #include <string> |
14 | | #include <system_error> |
15 | | #include <utility> // std::move |
16 | | #include <vector> |
17 | | |
18 | | #include <jsoncons/config/compiler_support.hpp> |
19 | | #include <jsoncons/config/jsoncons_config.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/bson/bson_decimal128.hpp> |
29 | | #include <jsoncons_ext/bson/bson_error.hpp> |
30 | | #include <jsoncons_ext/bson/bson_oid.hpp> |
31 | | #include <jsoncons_ext/bson/bson_options.hpp> |
32 | | #include <jsoncons_ext/bson/bson_type.hpp> |
33 | | |
34 | | namespace jsoncons { |
35 | | namespace bson { |
36 | | |
37 | | enum class parse_mode {root,accept,document,array,value}; |
38 | | |
39 | | struct parse_state |
40 | | { |
41 | | parse_mode mode; |
42 | | std::size_t length; |
43 | | std::size_t pos; |
44 | | uint8_t type; |
45 | | std::size_t index{0}; |
46 | | |
47 | | parse_state(parse_mode mode_, std::size_t length_, std::size_t pos_, uint8_t type_ = 0) noexcept |
48 | 209k | : mode(mode_), length(length_), pos(pos_), type(type_) |
49 | 209k | { |
50 | 209k | } |
51 | | |
52 | | parse_state(const parse_state&) = default; |
53 | | parse_state(parse_state&&) = default; |
54 | | parse_state& operator=(const parse_state&) = default; |
55 | | parse_state& operator=(parse_state&&) = default; |
56 | | }; |
57 | | |
58 | | template <typename Source,typename TempAlloc =std::allocator<char>> |
59 | | class basic_bson_parser : public ser_context |
60 | | { |
61 | | using char_type = char; |
62 | | using char_traits_type = std::char_traits<char>; |
63 | | using temp_allocator_type = TempAlloc; |
64 | | using char_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<char_type>; |
65 | | using byte_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<uint8_t>; |
66 | | using parse_state_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<parse_state>; |
67 | | using string_type = std::basic_string<char,std::char_traits<char>,char_allocator_type>; |
68 | | |
69 | | bool more_{true}; |
70 | | bool done_{false}; |
71 | | bool cursor_mode_{false}; |
72 | | int mark_level_{0}; |
73 | | |
74 | | Source source_; |
75 | | int max_nesting_depth_; |
76 | | std::vector<uint8_t,byte_allocator_type> bytes_buffer_; |
77 | | string_type name_buffer_; |
78 | | string_type text_buffer_; |
79 | | std::vector<parse_state,parse_state_allocator_type> state_stack_; |
80 | | public: |
81 | | template <typename Sourceable> |
82 | | basic_bson_parser(Sourceable&& source, |
83 | | const bson_decode_options& options = bson_decode_options(), |
84 | | const TempAlloc& temp_alloc = TempAlloc()) |
85 | 9.27k | : source_(std::forward<Sourceable>(source)), |
86 | 9.27k | max_nesting_depth_(options.max_nesting_depth()), |
87 | 9.27k | bytes_buffer_(temp_alloc), |
88 | 9.27k | name_buffer_(temp_alloc), |
89 | 9.27k | text_buffer_(temp_alloc), |
90 | 9.27k | state_stack_(temp_alloc) |
91 | 9.27k | { |
92 | 9.27k | state_stack_.emplace_back(parse_mode::root,0,0); |
93 | 9.27k | } jsoncons::bson::basic_bson_parser<jsoncons::stream_source<unsigned char, std::__1::allocator<unsigned char> >, std::__1::allocator<char> >::basic_bson_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::bson::bson_decode_options const&, std::__1::allocator<char> const&) Line | Count | Source | 85 | 4.83k | : source_(std::forward<Sourceable>(source)), | 86 | 4.83k | max_nesting_depth_(options.max_nesting_depth()), | 87 | 4.83k | bytes_buffer_(temp_alloc), | 88 | 4.83k | name_buffer_(temp_alloc), | 89 | 4.83k | text_buffer_(temp_alloc), | 90 | 4.83k | state_stack_(temp_alloc) | 91 | 4.83k | { | 92 | 4.83k | state_stack_.emplace_back(parse_mode::root,0,0); | 93 | 4.83k | } |
jsoncons::bson::basic_bson_parser<jsoncons::stream_source<unsigned char, std::__1::allocator<unsigned char> >, std::__1::allocator<char> >::basic_bson_parser<std::__1::basic_istream<char, std::__1::char_traits<char> >&>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, jsoncons::bson::bson_decode_options const&, std::__1::allocator<char> const&) Line | Count | Source | 85 | 4.43k | : source_(std::forward<Sourceable>(source)), | 86 | 4.43k | max_nesting_depth_(options.max_nesting_depth()), | 87 | 4.43k | bytes_buffer_(temp_alloc), | 88 | 4.43k | name_buffer_(temp_alloc), | 89 | 4.43k | text_buffer_(temp_alloc), | 90 | 4.43k | state_stack_(temp_alloc) | 91 | 4.43k | { | 92 | 4.43k | state_stack_.emplace_back(parse_mode::root,0,0); | 93 | 4.43k | } |
|
94 | | |
95 | | void restart() |
96 | | { |
97 | | more_ = true; |
98 | | } |
99 | | |
100 | | void reset() |
101 | 9.27k | { |
102 | 9.27k | more_ = true; |
103 | 9.27k | done_ = false; |
104 | 9.27k | bytes_buffer_.clear(); |
105 | 9.27k | name_buffer_.clear(); |
106 | 9.27k | text_buffer_.clear(); |
107 | 9.27k | state_stack_.clear(); |
108 | 9.27k | state_stack_.emplace_back(parse_mode::root,0,0); |
109 | 9.27k | } |
110 | | |
111 | | template <typename Sourceable> |
112 | | void reset(Sourceable&& source) |
113 | | { |
114 | | source_ = std::forward<Sourceable>(source); |
115 | | reset(); |
116 | | } |
117 | | |
118 | | void cursor_mode(bool value) |
119 | | { |
120 | | cursor_mode_ = value; |
121 | | } |
122 | | |
123 | | int level() const |
124 | 52.8k | { |
125 | 52.8k | return static_cast<int>(state_stack_.size()); |
126 | 52.8k | } |
127 | | |
128 | | int mark_level() const |
129 | | { |
130 | | return mark_level_; |
131 | | } |
132 | | |
133 | | void mark_level(int value) |
134 | | { |
135 | | mark_level_ = value; |
136 | | } |
137 | | |
138 | | bool done() const |
139 | | { |
140 | | return done_; |
141 | | } |
142 | | |
143 | | bool stopped() const |
144 | | { |
145 | | return !more_; |
146 | | } |
147 | | |
148 | | std::size_t line() const override |
149 | 4.42k | { |
150 | 4.42k | return 0; |
151 | 4.42k | } |
152 | | |
153 | | std::size_t column() const override |
154 | 4.42k | { |
155 | 4.42k | return source_.position(); |
156 | 4.42k | } |
157 | | |
158 | | void array_expected(json_visitor& visitor, std::error_code& ec) |
159 | | { |
160 | | if (state_stack_.size() == 2 && state_stack_.back().mode == parse_mode::document) |
161 | | { |
162 | | state_stack_.back().mode = parse_mode::array; |
163 | | visitor.begin_array(semantic_tag::none, *this, ec); |
164 | | more_ = !cursor_mode_; |
165 | | } |
166 | | } |
167 | | |
168 | | void parse(json_visitor& visitor, std::error_code& ec) |
169 | 9.27k | { |
170 | 9.27k | if (JSONCONS_UNLIKELY(source_.is_error())) |
171 | 0 | { |
172 | 0 | ec = bson_errc::source_error; |
173 | 0 | more_ = false; |
174 | 0 | return; |
175 | 0 | } |
176 | | |
177 | 39.1M | while (!done_ && more_) |
178 | 39.1M | { |
179 | 39.1M | switch (state_stack_.back().mode) |
180 | 39.1M | { |
181 | 9.27k | case parse_mode::root: |
182 | 9.27k | state_stack_.back().mode = parse_mode::accept; |
183 | 9.27k | begin_document(visitor, ec); |
184 | 9.27k | break; |
185 | 10.7M | case parse_mode::document: |
186 | 10.7M | { |
187 | 10.7M | uint8_t type; |
188 | 10.7M | std::size_t n = source_.read(&type, 1); |
189 | 10.7M | state_stack_.back().pos += n; |
190 | 10.7M | if (JSONCONS_UNLIKELY(n != 1)) |
191 | 2.73k | { |
192 | 2.73k | ec = bson_errc::unexpected_eof; |
193 | 2.73k | more_ = false; |
194 | 2.73k | return; |
195 | 2.73k | } |
196 | 10.7M | if (type != 0x00) |
197 | 10.7M | { |
198 | 10.7M | read_e_name(visitor,jsoncons::bson::bson_container_type::document,ec); |
199 | 10.7M | state_stack_.back().mode = parse_mode::value; |
200 | 10.7M | state_stack_.back().type = type; |
201 | 10.7M | } |
202 | 35.2k | else |
203 | 35.2k | { |
204 | 35.2k | end_document(visitor,ec); |
205 | 35.2k | } |
206 | 10.7M | break; |
207 | 10.7M | } |
208 | 17.6M | case parse_mode::array: |
209 | 17.6M | { |
210 | 17.6M | uint8_t type; |
211 | 17.6M | std::size_t n = source_.read(&type, 1); |
212 | 17.6M | state_stack_.back().pos += n; |
213 | 17.6M | if (JSONCONS_UNLIKELY(n != 1)) |
214 | 414 | { |
215 | 414 | ec = bson_errc::unexpected_eof; |
216 | 414 | more_ = false; |
217 | 414 | return; |
218 | 414 | } |
219 | 17.6M | if (type != 0x00) |
220 | 17.6M | { |
221 | 17.6M | read_e_name(visitor,jsoncons::bson::bson_container_type::array,ec); |
222 | 17.6M | read_value(visitor, type, ec); |
223 | 17.6M | } |
224 | 17.6k | else |
225 | 17.6k | { |
226 | 17.6k | end_array(visitor,ec); |
227 | 17.6k | } |
228 | 17.6M | break; |
229 | 17.6M | } |
230 | 10.7M | case parse_mode::value: |
231 | 10.7M | state_stack_.back().mode = parse_mode::document; |
232 | 10.7M | read_value(visitor,state_stack_.back().type,ec); |
233 | 10.7M | break; |
234 | 26 | case parse_mode::accept: |
235 | 26 | { |
236 | 26 | JSONCONS_ASSERT(state_stack_.size() == 1); |
237 | 26 | state_stack_.clear(); |
238 | 26 | more_ = false; |
239 | 26 | done_ = true; |
240 | 26 | visitor.flush(); |
241 | 26 | break; |
242 | 26 | } |
243 | 39.1M | } |
244 | 39.1M | } |
245 | 9.27k | } |
246 | | |
247 | | private: |
248 | | |
249 | | void begin_document(json_visitor& visitor, std::error_code& ec) |
250 | 110k | { |
251 | 110k | if (JSONCONS_UNLIKELY(static_cast<int>(state_stack_.size()) > max_nesting_depth_)) |
252 | 5 | { |
253 | 5 | ec = bson_errc::max_nesting_depth_exceeded; |
254 | 5 | more_ = false; |
255 | 5 | return; |
256 | 5 | } |
257 | | |
258 | 110k | uint8_t buf[sizeof(int32_t)]; |
259 | 110k | std::size_t n = source_.read(buf, sizeof(int32_t)); |
260 | 110k | if (JSONCONS_UNLIKELY(n != sizeof(int32_t))) |
261 | 98 | { |
262 | 98 | ec = bson_errc::unexpected_eof; |
263 | 98 | more_ = false; |
264 | 98 | return; |
265 | 98 | } |
266 | | |
267 | 109k | auto length = binary::little_to_native<int32_t>(buf, sizeof(buf)); |
268 | | |
269 | 109k | visitor.begin_object(semantic_tag::none, *this, ec); |
270 | 109k | more_ = !cursor_mode_; |
271 | 109k | state_stack_.emplace_back(parse_mode::document,length,n); |
272 | 109k | } |
273 | | |
274 | | void end_document(json_visitor& visitor, std::error_code& ec) |
275 | 35.2k | { |
276 | 35.2k | JSONCONS_ASSERT(state_stack_.size() >= 2); |
277 | | |
278 | 35.2k | visitor.end_object(*this,ec); |
279 | 35.2k | more_ = !cursor_mode_; |
280 | 35.2k | if (level() == mark_level_) |
281 | 0 | { |
282 | 0 | more_ = false; |
283 | 0 | } |
284 | 35.2k | if (JSONCONS_UNLIKELY(state_stack_.back().pos != state_stack_.back().length)) |
285 | 2.50k | { |
286 | 2.50k | ec = bson_errc::size_mismatch; |
287 | 2.50k | more_ = false; |
288 | 2.50k | return; |
289 | 2.50k | } |
290 | 32.7k | std::size_t pos = state_stack_.back().pos; |
291 | 32.7k | state_stack_.pop_back(); |
292 | 32.7k | state_stack_.back().pos += pos; |
293 | 32.7k | } |
294 | | |
295 | | void begin_array(json_visitor& visitor, std::error_code& ec) |
296 | 911k | { |
297 | 911k | if (JSONCONS_UNLIKELY(static_cast<int>(state_stack_.size()) > max_nesting_depth_)) |
298 | 3 | { |
299 | 3 | ec = bson_errc::max_nesting_depth_exceeded; |
300 | 3 | more_ = false; |
301 | 3 | return; |
302 | 3 | } |
303 | 911k | uint8_t buf[sizeof(int32_t)]; |
304 | 911k | std::size_t n = source_.read(buf, sizeof(int32_t)); |
305 | 911k | if (JSONCONS_UNLIKELY(n != sizeof(int32_t))) |
306 | 78 | { |
307 | 78 | ec = bson_errc::unexpected_eof; |
308 | 78 | more_ = false; |
309 | 78 | return; |
310 | 78 | } |
311 | 911k | auto length = binary::little_to_native<int32_t>(buf, sizeof(buf)); |
312 | | |
313 | 911k | visitor.begin_array(semantic_tag::none, *this, ec); |
314 | 911k | more_ = !cursor_mode_; |
315 | 911k | if (JSONCONS_UNLIKELY(ec)) |
316 | 830k | { |
317 | 830k | return; |
318 | 830k | } |
319 | 81.0k | state_stack_.emplace_back(parse_mode::array, length, n); |
320 | 81.0k | } |
321 | | |
322 | | void end_array(json_visitor& visitor, std::error_code& ec) |
323 | 17.6k | { |
324 | 17.6k | JSONCONS_ASSERT(state_stack_.size() >= 2); |
325 | | |
326 | 17.6k | visitor.end_array(*this, ec); |
327 | 17.6k | more_ = !cursor_mode_; |
328 | 17.6k | if (level() == mark_level_) |
329 | 0 | { |
330 | 0 | more_ = false; |
331 | 0 | } |
332 | 17.6k | if (JSONCONS_UNLIKELY(state_stack_.back().pos != state_stack_.back().length)) |
333 | 569 | { |
334 | 569 | ec = bson_errc::size_mismatch; |
335 | 569 | more_ = false; |
336 | 569 | return; |
337 | 569 | } |
338 | 17.0k | std::size_t pos = state_stack_.back().pos; |
339 | 17.0k | state_stack_.pop_back(); |
340 | 17.0k | state_stack_.back().pos += pos; |
341 | 17.0k | } |
342 | | |
343 | | void read_e_name(json_visitor& visitor, jsoncons::bson::bson_container_type type, std::error_code& ec) |
344 | 28.3M | { |
345 | 28.3M | name_buffer_.clear(); |
346 | 28.3M | read_cstring(name_buffer_, ec); |
347 | 28.3M | if (JSONCONS_UNLIKELY(ec)) |
348 | 1.12M | { |
349 | 1.12M | return; |
350 | 1.12M | } |
351 | 27.1M | if (type == jsoncons::bson::bson_container_type::document) |
352 | 9.58M | { |
353 | 9.58M | auto result = unicode_traits::validate(name_buffer_.data(),name_buffer_.size()); |
354 | 9.58M | if (JSONCONS_UNLIKELY(result.ec != unicode_traits::conv_errc())) |
355 | 246 | { |
356 | 246 | ec = bson_errc::invalid_utf8_text_string; |
357 | 246 | more_ = false; |
358 | 246 | return; |
359 | 246 | } |
360 | 9.58M | visitor.key(jsoncons::basic_string_view<char>(name_buffer_.data(),name_buffer_.length()), *this, ec); |
361 | 9.58M | more_ = !cursor_mode_; |
362 | 9.58M | } |
363 | 27.1M | } |
364 | | |
365 | | void read_value(json_visitor& visitor, uint8_t type, std::error_code& ec) |
366 | 28.3M | { |
367 | 28.3M | switch (type) |
368 | 28.3M | { |
369 | 16.4k | case jsoncons::bson::bson_type::double_type: |
370 | 16.4k | { |
371 | 16.4k | uint8_t buf[sizeof(double)]; |
372 | 16.4k | std::size_t n = source_.read(buf, sizeof(double)); |
373 | 16.4k | state_stack_.back().pos += n; |
374 | 16.4k | if (JSONCONS_UNLIKELY(n != sizeof(double))) |
375 | 22 | { |
376 | 22 | ec = bson_errc::unexpected_eof; |
377 | 22 | more_ = false; |
378 | 22 | return; |
379 | 22 | } |
380 | 16.4k | double res = binary::little_to_native<double>(buf, sizeof(buf)); |
381 | 16.4k | visitor.double_value(res, semantic_tag::none, *this, ec); |
382 | 16.4k | more_ = !cursor_mode_; |
383 | 16.4k | break; |
384 | 16.4k | } |
385 | 2.23k | case jsoncons::bson::bson_type::symbol_type: |
386 | 4.42k | case jsoncons::bson::bson_type::min_key_type: |
387 | 8.42k | case jsoncons::bson::bson_type::max_key_type: |
388 | 11.1k | case jsoncons::bson::bson_type::string_type: |
389 | 11.1k | { |
390 | 11.1k | text_buffer_.clear(); |
391 | 11.1k | read_string(text_buffer_, ec); |
392 | 11.1k | if (JSONCONS_UNLIKELY(ec)) |
393 | 1.05k | { |
394 | 1.05k | return; |
395 | 1.05k | } |
396 | 10.1k | auto result = unicode_traits::validate(text_buffer_.data(), text_buffer_.size()); |
397 | 10.1k | if (JSONCONS_UNLIKELY(result.ec != unicode_traits::conv_errc())) |
398 | 66 | { |
399 | 66 | ec = bson_errc::invalid_utf8_text_string; |
400 | 66 | more_ = false; |
401 | 66 | return; |
402 | 66 | } |
403 | 10.0k | visitor.string_value(text_buffer_, semantic_tag::none, *this, ec); |
404 | 10.0k | more_ = !cursor_mode_; |
405 | 10.0k | break; |
406 | 10.1k | } |
407 | 3.06k | case jsoncons::bson::bson_type::javascript_type: |
408 | 3.06k | { |
409 | 3.06k | text_buffer_.clear(); |
410 | 3.06k | read_string(text_buffer_, ec); |
411 | 3.06k | if (JSONCONS_UNLIKELY(ec)) |
412 | 357 | { |
413 | 357 | return; |
414 | 357 | } |
415 | 2.71k | auto result = unicode_traits::validate(text_buffer_.data(), text_buffer_.size()); |
416 | 2.71k | if (JSONCONS_UNLIKELY(result.ec != unicode_traits::conv_errc())) |
417 | 93 | { |
418 | 93 | ec = bson_errc::invalid_utf8_text_string; |
419 | 93 | more_ = false; |
420 | 93 | return; |
421 | 93 | } |
422 | 2.61k | visitor.string_value(text_buffer_, semantic_tag::code, *this, ec); |
423 | 2.61k | more_ = !cursor_mode_; |
424 | 2.61k | break; |
425 | 2.71k | } |
426 | 37.6k | case jsoncons::bson::bson_type::regex_type: |
427 | 37.6k | { |
428 | 37.6k | text_buffer_.clear(); |
429 | 37.6k | text_buffer_.push_back('/'); |
430 | 37.6k | read_cstring(text_buffer_, ec); |
431 | 37.6k | if (JSONCONS_UNLIKELY(ec)) |
432 | 17.9k | { |
433 | 17.9k | return; |
434 | 17.9k | } |
435 | 19.7k | text_buffer_.push_back('/'); |
436 | 19.7k | read_cstring(text_buffer_, ec); |
437 | 19.7k | if (JSONCONS_UNLIKELY(ec)) |
438 | 66 | { |
439 | 66 | return; |
440 | 66 | } |
441 | 19.6k | visitor.string_value(text_buffer_, semantic_tag::regex, *this, ec); |
442 | 19.6k | more_ = !cursor_mode_; |
443 | 19.6k | break; |
444 | 19.7k | } |
445 | 100k | case jsoncons::bson::bson_type::document_type: |
446 | 100k | { |
447 | 100k | begin_document(visitor,ec); |
448 | 100k | break; |
449 | 19.7k | } |
450 | | |
451 | 911k | case jsoncons::bson::bson_type::array_type: |
452 | 911k | { |
453 | 911k | begin_array(visitor,ec); |
454 | 911k | break; |
455 | 19.7k | } |
456 | 50.0k | case jsoncons::bson::bson_type::undefined_type: |
457 | 50.0k | { |
458 | 50.0k | visitor.null_value(semantic_tag::undefined, *this, ec); |
459 | 50.0k | more_ = !cursor_mode_; |
460 | 50.0k | break; |
461 | 19.7k | } |
462 | 26.8M | case jsoncons::bson::bson_type::null_type: |
463 | 26.8M | { |
464 | 26.8M | visitor.null_value(semantic_tag::none, *this, ec); |
465 | 26.8M | more_ = !cursor_mode_; |
466 | 26.8M | break; |
467 | 19.7k | } |
468 | 48.3k | case jsoncons::bson::bson_type::bool_type: |
469 | 48.3k | { |
470 | 48.3k | uint8_t c; |
471 | 48.3k | std::size_t n = source_.read(&c, 1); |
472 | 48.3k | state_stack_.back().pos += n; |
473 | 48.3k | if (JSONCONS_UNLIKELY(n != 1)) |
474 | 13 | { |
475 | 13 | ec = bson_errc::unexpected_eof; |
476 | 13 | more_ = false; |
477 | 13 | return; |
478 | 13 | } |
479 | 48.3k | visitor.bool_value(c != 0, semantic_tag::none, *this, ec); |
480 | 48.3k | more_ = !cursor_mode_; |
481 | 48.3k | break; |
482 | 48.3k | } |
483 | 94.1k | case jsoncons::bson::bson_type::int32_type: |
484 | 94.1k | { |
485 | 94.1k | uint8_t buf[sizeof(int32_t)]; |
486 | 94.1k | std::size_t n = source_.read(buf, sizeof(int32_t)); |
487 | 94.1k | state_stack_.back().pos += n; |
488 | 94.1k | if (JSONCONS_UNLIKELY(n != sizeof(int32_t))) |
489 | 15 | { |
490 | 15 | ec = bson_errc::unexpected_eof; |
491 | 15 | more_ = false; |
492 | 15 | return; |
493 | 15 | } |
494 | 94.1k | auto val = binary::little_to_native<int32_t>(buf, sizeof(buf)); |
495 | 94.1k | visitor.int64_value(val, semantic_tag::none, *this, ec); |
496 | 94.1k | more_ = !cursor_mode_; |
497 | 94.1k | break; |
498 | 94.1k | } |
499 | | |
500 | 15.0k | case jsoncons::bson::bson_type::timestamp_type: |
501 | 15.0k | { |
502 | 15.0k | uint8_t buf[sizeof(uint64_t)]; |
503 | 15.0k | std::size_t n = source_.read(buf, sizeof(uint64_t)); |
504 | 15.0k | state_stack_.back().pos += n; |
505 | 15.0k | if (JSONCONS_UNLIKELY(n != sizeof(uint64_t))) |
506 | 25 | { |
507 | 25 | ec = bson_errc::unexpected_eof; |
508 | 25 | more_ = false; |
509 | 25 | return; |
510 | 25 | } |
511 | 15.0k | auto val = binary::little_to_native<uint64_t>(buf, sizeof(buf)); |
512 | 15.0k | visitor.uint64_value(val, semantic_tag::none, *this, ec); |
513 | 15.0k | more_ = !cursor_mode_; |
514 | 15.0k | break; |
515 | 15.0k | } |
516 | | |
517 | 30.7k | case jsoncons::bson::bson_type::int64_type: |
518 | 30.7k | { |
519 | 30.7k | uint8_t buf[sizeof(int64_t)]; |
520 | 30.7k | std::size_t n = source_.read(buf, sizeof(int64_t)); |
521 | 30.7k | state_stack_.back().pos += n; |
522 | 30.7k | if (JSONCONS_UNLIKELY(n != sizeof(int64_t))) |
523 | 17 | { |
524 | 17 | ec = bson_errc::unexpected_eof; |
525 | 17 | more_ = false; |
526 | 17 | return; |
527 | 17 | } |
528 | 30.7k | auto val = binary::little_to_native<int64_t>(buf, sizeof(buf)); |
529 | 30.7k | visitor.int64_value(val, semantic_tag::none, *this, ec); |
530 | 30.7k | more_ = !cursor_mode_; |
531 | 30.7k | break; |
532 | 30.7k | } |
533 | | |
534 | 11.2k | case jsoncons::bson::bson_type::datetime_type: |
535 | 11.2k | { |
536 | 11.2k | uint8_t buf[sizeof(int64_t)]; |
537 | 11.2k | std::size_t n = source_.read(buf, sizeof(int64_t)); |
538 | 11.2k | state_stack_.back().pos += n; |
539 | 11.2k | if (JSONCONS_UNLIKELY(n != sizeof(int64_t))) |
540 | 23 | { |
541 | 23 | ec = bson_errc::unexpected_eof; |
542 | 23 | more_ = false; |
543 | 23 | return; |
544 | 23 | } |
545 | 11.2k | auto val = binary::little_to_native<int64_t>(buf, sizeof(buf)); |
546 | 11.2k | visitor.int64_value(val, semantic_tag::epoch_milli, *this, ec); |
547 | 11.2k | more_ = !cursor_mode_; |
548 | 11.2k | break; |
549 | 11.2k | } |
550 | 52.0k | case jsoncons::bson::bson_type::binary_type: |
551 | 52.0k | { |
552 | 52.0k | uint8_t buf[sizeof(int32_t)]; |
553 | 52.0k | std::size_t n = source_.read(buf, sizeof(int32_t)); |
554 | 52.0k | state_stack_.back().pos += n; |
555 | 52.0k | if (JSONCONS_UNLIKELY(n != sizeof(int32_t))) |
556 | 18 | { |
557 | 18 | ec = bson_errc::unexpected_eof; |
558 | 18 | more_ = false; |
559 | 18 | return; |
560 | 18 | } |
561 | 52.0k | const auto len = binary::little_to_native<int32_t>(buf, sizeof(buf)); |
562 | 52.0k | if (JSONCONS_UNLIKELY(len < 0)) |
563 | 115 | { |
564 | 115 | ec = bson_errc::length_is_negative; |
565 | 115 | more_ = false; |
566 | 115 | return; |
567 | 115 | } |
568 | 51.9k | uint8_t subtype; |
569 | 51.9k | n = source_.read(&subtype, 1); |
570 | 51.9k | state_stack_.back().pos += n; |
571 | 51.9k | if (JSONCONS_UNLIKELY(n != 1)) |
572 | 25 | { |
573 | 25 | ec = bson_errc::unexpected_eof; |
574 | 25 | more_ = false; |
575 | 25 | return; |
576 | 25 | } |
577 | | |
578 | 51.8k | bytes_buffer_.clear(); |
579 | 51.8k | n = source_reader<Source>::read(source_, bytes_buffer_, len); |
580 | 51.8k | state_stack_.back().pos += n; |
581 | 51.8k | if (JSONCONS_UNLIKELY(n != static_cast<std::size_t>(len))) |
582 | 675 | { |
583 | 675 | ec = bson_errc::unexpected_eof; |
584 | 675 | more_ = false; |
585 | 675 | return; |
586 | 675 | } |
587 | | |
588 | 51.2k | visitor.byte_string_value(bytes_buffer_, |
589 | 51.2k | subtype, |
590 | 51.2k | *this, |
591 | 51.2k | ec); |
592 | 51.2k | more_ = !cursor_mode_; |
593 | 51.2k | break; |
594 | 51.8k | } |
595 | 92.4k | case jsoncons::bson::bson_type::decimal128_type: |
596 | 92.4k | { |
597 | 92.4k | uint8_t buf[sizeof(uint64_t)*2]; |
598 | 92.4k | std::size_t n = source_.read(buf, sizeof(buf)); |
599 | 92.4k | state_stack_.back().pos += n; |
600 | 92.4k | if (JSONCONS_UNLIKELY(n != sizeof(buf))) |
601 | 37 | { |
602 | 37 | ec = bson_errc::unexpected_eof; |
603 | 37 | more_ = false; |
604 | 37 | return; |
605 | 37 | } |
606 | | |
607 | 92.4k | decimal128_t dec; |
608 | 92.4k | dec.low = binary::little_to_native<uint64_t>(buf, sizeof(uint64_t)); |
609 | 92.4k | dec.high = binary::little_to_native<uint64_t>(buf+sizeof(uint64_t), sizeof(uint64_t)); |
610 | | |
611 | 92.4k | text_buffer_.clear(); |
612 | 92.4k | text_buffer_.resize(bson::decimal128_limits::buf_size); |
613 | 92.4k | auto r = bson::decimal128_to_chars(&text_buffer_[0], &text_buffer_[0]+text_buffer_.size(), dec); |
614 | 92.4k | visitor.string_value(string_view(text_buffer_.data(),static_cast<std::size_t>(r.ptr-text_buffer_.data())), semantic_tag::float128, *this, ec); |
615 | 92.4k | more_ = !cursor_mode_; |
616 | 92.4k | break; |
617 | 92.4k | } |
618 | 18.5k | case jsoncons::bson::bson_type::object_id_type: |
619 | 18.5k | { |
620 | 18.5k | uint8_t buf[12]; |
621 | 18.5k | std::size_t n = source_.read(buf, sizeof(buf)); |
622 | 18.5k | state_stack_.back().pos += n; |
623 | 18.5k | if (JSONCONS_UNLIKELY(n != sizeof(buf))) |
624 | 30 | { |
625 | 30 | ec = bson_errc::unexpected_eof; |
626 | 30 | more_ = false; |
627 | 30 | return; |
628 | 30 | } |
629 | | |
630 | 18.5k | oid_t oid(buf); |
631 | 18.5k | to_string(oid, text_buffer_); |
632 | | |
633 | 18.5k | visitor.string_value(text_buffer_, semantic_tag::id, *this, ec); |
634 | 18.5k | more_ = !cursor_mode_; |
635 | 18.5k | break; |
636 | 18.5k | } |
637 | 286 | default: |
638 | 286 | { |
639 | 286 | ec = bson_errc::unknown_type; |
640 | 286 | more_ = false; |
641 | 286 | return; |
642 | 18.5k | } |
643 | 28.3M | } |
644 | 28.3M | } |
645 | | |
646 | | void read_cstring(string_type& buffer, std::error_code& ec) |
647 | 28.3M | { |
648 | 28.3M | uint8_t c = 0xff; |
649 | 83.9M | while (true) |
650 | 83.9M | { |
651 | 83.9M | std::size_t n = source_.read(&c, 1); |
652 | 83.9M | state_stack_.back().pos += n; |
653 | 83.9M | if (JSONCONS_UNLIKELY(n != 1)) |
654 | 634 | { |
655 | 634 | ec = bson_errc::unexpected_eof; |
656 | 634 | more_ = false; |
657 | 634 | return; |
658 | 634 | } |
659 | 83.9M | if (c == 0) |
660 | 28.3M | { |
661 | 28.3M | break; |
662 | 28.3M | } |
663 | 55.5M | buffer.push_back(c); |
664 | 55.5M | } |
665 | 28.3M | } |
666 | | |
667 | | void read_string(string_type& buffer, std::error_code& ec) |
668 | 14.2k | { |
669 | 14.2k | uint8_t buf[sizeof(int32_t)]; |
670 | 14.2k | std::size_t n = source_.read(buf, sizeof(int32_t)); |
671 | 14.2k | state_stack_.back().pos += n; |
672 | 14.2k | if (JSONCONS_UNLIKELY(n != sizeof(int32_t))) |
673 | 222 | { |
674 | 222 | ec = bson_errc::unexpected_eof; |
675 | 222 | more_ = false; |
676 | 222 | return; |
677 | 222 | } |
678 | 14.0k | auto len = binary::little_to_native<int32_t>(buf, sizeof(buf)); |
679 | 14.0k | if (JSONCONS_UNLIKELY(len < 1)) |
680 | 104 | { |
681 | 104 | ec = bson_errc::string_length_is_non_positive; |
682 | 104 | more_ = false; |
683 | 104 | return; |
684 | 104 | } |
685 | | |
686 | 13.9k | std::size_t size = static_cast<std::size_t>(len) - static_cast<std::size_t>(1); |
687 | 13.9k | n = source_reader<Source>::read(source_, buffer, size); |
688 | 13.9k | state_stack_.back().pos += n; |
689 | | |
690 | 13.9k | if (JSONCONS_UNLIKELY(n != size)) |
691 | 397 | { |
692 | 397 | ec = bson_errc::unexpected_eof; |
693 | 397 | more_ = false; |
694 | 397 | return; |
695 | 397 | } |
696 | 13.5k | uint8_t c; |
697 | 13.5k | n = source_.read(&c, 1); |
698 | 13.5k | state_stack_.back().pos += n; |
699 | 13.5k | if (JSONCONS_UNLIKELY(n != 1)) |
700 | 55 | { |
701 | 55 | ec = bson_errc::unexpected_eof; |
702 | 55 | more_ = false; |
703 | 55 | return; |
704 | 55 | } |
705 | 13.5k | } |
706 | | }; |
707 | | |
708 | | } // namespace bson |
709 | | } // namespace jsoncons |
710 | | |
711 | | #endif // JSONCONS_EXT_BSON_BSON_PARSER_HPP |