jsoncons 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. checksums.yaml +7 -0
  2. data/ext/jsoncons/extconf.rb +43 -0
  3. data/ext/jsoncons/jsoncons.cpp +161 -0
  4. data/ext/jsoncons/jsoncons.h +10 -0
  5. data/jsoncons.gemspec +44 -0
  6. data/lib/jsoncons/jsoncons/examples/input/address-book.json +13 -0
  7. data/lib/jsoncons/jsoncons/examples/input/books.json +28 -0
  8. data/lib/jsoncons/jsoncons/examples/input/countries.json +7 -0
  9. data/lib/jsoncons/jsoncons/examples/input/employees.json +30 -0
  10. data/lib/jsoncons/jsoncons/examples/input/jsonschema/name.json +15 -0
  11. data/lib/jsoncons/jsoncons/examples/input/multiple-json-objects.json +3 -0
  12. data/lib/jsoncons/jsoncons/examples/input/sales.csv +6 -0
  13. data/lib/jsoncons/jsoncons/examples/input/store.json +28 -0
  14. data/lib/jsoncons/jsoncons/examples/input/tasks.csv +6 -0
  15. data/lib/jsoncons/jsoncons/include/jsoncons/allocator_holder.hpp +38 -0
  16. data/lib/jsoncons/jsoncons/include/jsoncons/basic_json.hpp +5905 -0
  17. data/lib/jsoncons/jsoncons/include/jsoncons/bigint.hpp +1611 -0
  18. data/lib/jsoncons/jsoncons/include/jsoncons/byte_string.hpp +820 -0
  19. data/lib/jsoncons/jsoncons/include/jsoncons/config/binary_config.hpp +226 -0
  20. data/lib/jsoncons/jsoncons/include/jsoncons/config/compiler_support.hpp +375 -0
  21. data/lib/jsoncons/jsoncons/include/jsoncons/config/jsoncons_config.hpp +309 -0
  22. data/lib/jsoncons/jsoncons/include/jsoncons/config/version.hpp +40 -0
  23. data/lib/jsoncons/jsoncons/include/jsoncons/conv_error.hpp +218 -0
  24. data/lib/jsoncons/jsoncons/include/jsoncons/decode_json.hpp +209 -0
  25. data/lib/jsoncons/jsoncons/include/jsoncons/decode_traits.hpp +651 -0
  26. data/lib/jsoncons/jsoncons/include/jsoncons/detail/endian.hpp +44 -0
  27. data/lib/jsoncons/jsoncons/include/jsoncons/detail/grisu3.hpp +312 -0
  28. data/lib/jsoncons/jsoncons/include/jsoncons/detail/optional.hpp +483 -0
  29. data/lib/jsoncons/jsoncons/include/jsoncons/detail/parse_number.hpp +1133 -0
  30. data/lib/jsoncons/jsoncons/include/jsoncons/detail/span.hpp +188 -0
  31. data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_view.hpp +537 -0
  32. data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_wrapper.hpp +370 -0
  33. data/lib/jsoncons/jsoncons/include/jsoncons/detail/write_number.hpp +567 -0
  34. data/lib/jsoncons/jsoncons/include/jsoncons/encode_json.hpp +315 -0
  35. data/lib/jsoncons/jsoncons/include/jsoncons/encode_traits.hpp +378 -0
  36. data/lib/jsoncons/jsoncons/include/jsoncons/json.hpp +18 -0
  37. data/lib/jsoncons/jsoncons/include/jsoncons/json_array.hpp +324 -0
  38. data/lib/jsoncons/jsoncons/include/jsoncons/json_content_handler.hpp +12 -0
  39. data/lib/jsoncons/jsoncons/include/jsoncons/json_cursor.hpp +448 -0
  40. data/lib/jsoncons/jsoncons/include/jsoncons/json_decoder.hpp +420 -0
  41. data/lib/jsoncons/jsoncons/include/jsoncons/json_encoder.hpp +1587 -0
  42. data/lib/jsoncons/jsoncons/include/jsoncons/json_error.hpp +156 -0
  43. data/lib/jsoncons/jsoncons/include/jsoncons/json_exception.hpp +241 -0
  44. data/lib/jsoncons/jsoncons/include/jsoncons/json_filter.hpp +653 -0
  45. data/lib/jsoncons/jsoncons/include/jsoncons/json_fwd.hpp +23 -0
  46. data/lib/jsoncons/jsoncons/include/jsoncons/json_object.hpp +1772 -0
  47. data/lib/jsoncons/jsoncons/include/jsoncons/json_options.hpp +862 -0
  48. data/lib/jsoncons/jsoncons/include/jsoncons/json_parser.hpp +2900 -0
  49. data/lib/jsoncons/jsoncons/include/jsoncons/json_reader.hpp +731 -0
  50. data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros.hpp +1072 -0
  51. data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros_deprecated.hpp +144 -0
  52. data/lib/jsoncons/jsoncons/include/jsoncons/json_type.hpp +206 -0
  53. data/lib/jsoncons/jsoncons/include/jsoncons/json_type_traits.hpp +1830 -0
  54. data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor.hpp +1560 -0
  55. data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor2.hpp +2079 -0
  56. data/lib/jsoncons/jsoncons/include/jsoncons/pretty_print.hpp +89 -0
  57. data/lib/jsoncons/jsoncons/include/jsoncons/ser_context.hpp +62 -0
  58. data/lib/jsoncons/jsoncons/include/jsoncons/sink.hpp +289 -0
  59. data/lib/jsoncons/jsoncons/include/jsoncons/source.hpp +777 -0
  60. data/lib/jsoncons/jsoncons/include/jsoncons/source_adaptor.hpp +148 -0
  61. data/lib/jsoncons/jsoncons/include/jsoncons/staj2_cursor.hpp +1189 -0
  62. data/lib/jsoncons/jsoncons/include/jsoncons/staj_cursor.hpp +1254 -0
  63. data/lib/jsoncons/jsoncons/include/jsoncons/staj_iterator.hpp +449 -0
  64. data/lib/jsoncons/jsoncons/include/jsoncons/tag_type.hpp +245 -0
  65. data/lib/jsoncons/jsoncons/include/jsoncons/text_source_adaptor.hpp +144 -0
  66. data/lib/jsoncons/jsoncons/include/jsoncons/traits_extension.hpp +884 -0
  67. data/lib/jsoncons/jsoncons/include/jsoncons/typed_array_view.hpp +250 -0
  68. data/lib/jsoncons/jsoncons/include/jsoncons/unicode_traits.hpp +1330 -0
  69. data/lib/jsoncons/jsoncons/include/jsoncons/uri.hpp +635 -0
  70. data/lib/jsoncons/jsoncons/include/jsoncons/value_converter.hpp +340 -0
  71. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson.hpp +23 -0
  72. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_cursor.hpp +320 -0
  73. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_decimal128.hpp +865 -0
  74. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_encoder.hpp +585 -0
  75. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_error.hpp +103 -0
  76. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_oid.hpp +245 -0
  77. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_options.hpp +75 -0
  78. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_parser.hpp +645 -0
  79. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_reader.hpp +92 -0
  80. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_type.hpp +44 -0
  81. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/decode_bson.hpp +201 -0
  82. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/encode_bson.hpp +144 -0
  83. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor.hpp +26 -0
  84. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor.hpp +351 -0
  85. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor2.hpp +265 -0
  86. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_detail.hpp +93 -0
  87. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_encoder.hpp +1766 -0
  88. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_error.hpp +105 -0
  89. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_options.hpp +113 -0
  90. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_parser.hpp +1942 -0
  91. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_reader.hpp +116 -0
  92. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/decode_cbor.hpp +203 -0
  93. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/encode_cbor.hpp +151 -0
  94. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv.hpp +17 -0
  95. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_cursor.hpp +358 -0
  96. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_encoder.hpp +954 -0
  97. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_error.hpp +85 -0
  98. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_options.hpp +973 -0
  99. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_parser.hpp +2099 -0
  100. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_reader.hpp +348 -0
  101. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_serializer.hpp +12 -0
  102. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/decode_csv.hpp +208 -0
  103. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/encode_csv.hpp +122 -0
  104. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath.hpp +5215 -0
  105. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath_error.hpp +215 -0
  106. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch.hpp +579 -0
  107. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch_error.hpp +121 -0
  108. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/expression.hpp +3329 -0
  109. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/flatten.hpp +432 -0
  110. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_location.hpp +445 -0
  111. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_query.hpp +115 -0
  112. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath.hpp +13 -0
  113. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_error.hpp +240 -0
  114. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_expression.hpp +2612 -0
  115. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_selector.hpp +1322 -0
  116. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer.hpp +1577 -0
  117. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer_error.hpp +119 -0
  118. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/format_validator.hpp +968 -0
  119. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/json_validator.hpp +120 -0
  120. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema.hpp +13 -0
  121. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_error.hpp +105 -0
  122. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_version.hpp +18 -0
  123. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator.hpp +1745 -0
  124. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator_factory.hpp +556 -0
  125. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_draft7.hpp +198 -0
  126. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_location.hpp +200 -0
  127. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_version.hpp +35 -0
  128. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/subschema.hpp +144 -0
  129. data/lib/jsoncons/jsoncons/include/jsoncons_ext/mergepatch/mergepatch.hpp +103 -0
  130. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/decode_msgpack.hpp +202 -0
  131. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/encode_msgpack.hpp +142 -0
  132. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack.hpp +24 -0
  133. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor.hpp +343 -0
  134. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor2.hpp +259 -0
  135. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_encoder.hpp +753 -0
  136. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_error.hpp +94 -0
  137. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_options.hpp +74 -0
  138. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_parser.hpp +748 -0
  139. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_reader.hpp +116 -0
  140. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_type.hpp +63 -0
  141. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/decode_ubjson.hpp +201 -0
  142. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/encode_ubjson.hpp +142 -0
  143. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson.hpp +23 -0
  144. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_cursor.hpp +307 -0
  145. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_encoder.hpp +502 -0
  146. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_error.hpp +100 -0
  147. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_options.hpp +87 -0
  148. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_parser.hpp +880 -0
  149. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_reader.hpp +92 -0
  150. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_type.hpp +43 -0
  151. data/lib/jsoncons/version.rb +5 -0
  152. data/lib/jsoncons.rb +33 -0
  153. data/test/jsoncons_test.rb +108 -0
  154. data/test/test_helper.rb +7 -0
  155. metadata +268 -0
@@ -0,0 +1,585 @@
1
+ // Copyright 2018 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_BSON_BSON_ENCODER_HPP
8
+ #define JSONCONS_BSON_BSON_ENCODER_HPP
9
+
10
+ #include <string>
11
+ #include <vector>
12
+ #include <limits> // std::numeric_limits
13
+ #include <memory>
14
+ #include <utility> // std::move
15
+ #include <jsoncons/json_exception.hpp>
16
+ #include <jsoncons/json_visitor.hpp>
17
+ #include <jsoncons/config/jsoncons_config.hpp>
18
+ #include <jsoncons/sink.hpp>
19
+ #include <jsoncons/detail/parse_number.hpp>
20
+ #include <jsoncons_ext/bson/bson_type.hpp>
21
+ #include <jsoncons_ext/bson/bson_error.hpp>
22
+ #include <jsoncons_ext/bson/bson_options.hpp>
23
+ #include <jsoncons_ext/bson/bson_decimal128.hpp>
24
+ #include <jsoncons_ext/bson/bson_oid.hpp>
25
+
26
+ namespace jsoncons { namespace bson {
27
+
28
+ template<class Sink=jsoncons::binary_stream_sink,class Allocator=std::allocator<char>>
29
+ class basic_bson_encoder final : public basic_json_visitor<char>
30
+ {
31
+ enum class decimal_parse_state { start, integer, exp1, exp2, fraction1 };
32
+ static constexpr int64_t nanos_in_milli = 1000000;
33
+ static constexpr int64_t nanos_in_second = 1000000000;
34
+ static constexpr int64_t millis_in_second = 1000;
35
+ public:
36
+ using allocator_type = Allocator;
37
+ using char_type = char;
38
+ using typename basic_json_visitor<char>::string_view_type;
39
+ using sink_type = Sink;
40
+
41
+ private:
42
+ struct stack_item
43
+ {
44
+ jsoncons::bson::bson_container_type type_;
45
+ std::size_t offset_;
46
+ std::size_t name_offset_;
47
+ std::size_t index_;
48
+
49
+ stack_item(jsoncons::bson::bson_container_type type, std::size_t offset) noexcept
50
+ : type_(type), offset_(offset), name_offset_(0), index_(0)
51
+ {
52
+ }
53
+
54
+ std::size_t offset() const
55
+ {
56
+ return offset_;
57
+ }
58
+
59
+ std::size_t member_offset() const
60
+ {
61
+ return name_offset_;
62
+ }
63
+
64
+ void member_offset(std::size_t offset)
65
+ {
66
+ name_offset_ = offset;
67
+ }
68
+
69
+ std::size_t next_index()
70
+ {
71
+ return index_++;
72
+ }
73
+
74
+ bool is_object() const
75
+ {
76
+ return type_ == jsoncons::bson::bson_container_type::document;
77
+ }
78
+
79
+
80
+ };
81
+
82
+ sink_type sink_;
83
+ const bson_encode_options options_;
84
+ allocator_type alloc_;
85
+
86
+ std::vector<stack_item> stack_;
87
+ std::vector<uint8_t> buffer_;
88
+ int nesting_depth_;
89
+
90
+ // Noncopyable and nonmoveable
91
+ basic_bson_encoder(const basic_bson_encoder&) = delete;
92
+ basic_bson_encoder& operator=(const basic_bson_encoder&) = delete;
93
+ public:
94
+ explicit basic_bson_encoder(Sink&& sink,
95
+ const Allocator& alloc = Allocator())
96
+ : basic_bson_encoder(std::forward<Sink>(sink),
97
+ bson_encode_options(),
98
+ alloc)
99
+ {
100
+ }
101
+
102
+ explicit basic_bson_encoder(Sink&& sink,
103
+ const bson_encode_options& options,
104
+ const Allocator& alloc = Allocator())
105
+ : sink_(std::forward<Sink>(sink)),
106
+ options_(options),
107
+ alloc_(alloc),
108
+ nesting_depth_(0)
109
+ {
110
+ }
111
+
112
+ ~basic_bson_encoder() noexcept
113
+ {
114
+ sink_.flush();
115
+ }
116
+
117
+ void reset()
118
+ {
119
+ stack_.clear();
120
+ buffer_.clear();
121
+ nesting_depth_ = 0;
122
+ }
123
+
124
+ void reset(Sink&& sink)
125
+ {
126
+ sink_ = std::move(sink);
127
+ reset();
128
+ }
129
+
130
+ private:
131
+ // Implementing methods
132
+
133
+ void visit_flush() override
134
+ {
135
+ sink_.flush();
136
+ }
137
+
138
+ bool visit_begin_object(semantic_tag, const ser_context&, std::error_code& ec) override
139
+ {
140
+ if (JSONCONS_UNLIKELY(++nesting_depth_ > options_.max_nesting_depth()))
141
+ {
142
+ ec = bson_errc::max_nesting_depth_exceeded;
143
+ return false;
144
+ }
145
+ if (buffer_.size() > 0)
146
+ {
147
+ if (stack_.empty())
148
+ {
149
+ ec = bson_errc::expected_bson_document;
150
+ return false;
151
+ }
152
+ before_value(jsoncons::bson::bson_type::document_type);
153
+ }
154
+
155
+ stack_.emplace_back(jsoncons::bson::bson_container_type::document, buffer_.size());
156
+ buffer_.insert(buffer_.end(), sizeof(int32_t), 0);
157
+
158
+ return true;
159
+ }
160
+
161
+ bool visit_end_object(const ser_context&, std::error_code&) override
162
+ {
163
+ JSONCONS_ASSERT(!stack_.empty());
164
+ --nesting_depth_;
165
+
166
+ buffer_.push_back(0x00);
167
+
168
+ std::size_t length = buffer_.size() - stack_.back().offset();
169
+ binary::native_to_little(static_cast<uint32_t>(length), buffer_.begin()+stack_.back().offset());
170
+
171
+ stack_.pop_back();
172
+ if (stack_.empty())
173
+ {
174
+ for (auto c : buffer_)
175
+ {
176
+ sink_.push_back(c);
177
+ }
178
+ }
179
+ return true;
180
+ }
181
+
182
+ bool visit_begin_array(semantic_tag, const ser_context&, std::error_code& ec) override
183
+ {
184
+ if (JSONCONS_UNLIKELY(++nesting_depth_ > options_.max_nesting_depth()))
185
+ {
186
+ ec = bson_errc::max_nesting_depth_exceeded;
187
+ return false;
188
+ }
189
+ if (buffer_.size() > 0)
190
+ {
191
+ if (stack_.empty())
192
+ {
193
+ ec = bson_errc::expected_bson_document;
194
+ return false;
195
+ }
196
+ before_value(jsoncons::bson::bson_type::array_type);
197
+ }
198
+ stack_.emplace_back(jsoncons::bson::bson_container_type::array, buffer_.size());
199
+ buffer_.insert(buffer_.end(), sizeof(int32_t), 0);
200
+ return true;
201
+ }
202
+
203
+ bool visit_end_array(const ser_context&, std::error_code&) override
204
+ {
205
+ JSONCONS_ASSERT(!stack_.empty());
206
+ --nesting_depth_;
207
+
208
+ buffer_.push_back(0x00);
209
+
210
+ std::size_t length = buffer_.size() - stack_.back().offset();
211
+ binary::native_to_little(static_cast<uint32_t>(length), buffer_.begin()+stack_.back().offset());
212
+
213
+ stack_.pop_back();
214
+ if (stack_.empty())
215
+ {
216
+ for (auto c : buffer_)
217
+ {
218
+ sink_.push_back(c);
219
+ }
220
+ }
221
+ return true;
222
+ }
223
+
224
+ bool visit_key(const string_view_type& name, const ser_context&, std::error_code&) override
225
+ {
226
+ stack_.back().member_offset(buffer_.size());
227
+ buffer_.push_back(0x00); // reserve space for code
228
+ for (auto c : name)
229
+ {
230
+ buffer_.push_back(c);
231
+ }
232
+ buffer_.push_back(0x00);
233
+ return true;
234
+ }
235
+
236
+ bool visit_null(semantic_tag tag, const ser_context&, std::error_code& ec) override
237
+ {
238
+ if (stack_.empty())
239
+ {
240
+ ec = bson_errc::expected_bson_document;
241
+ return false;
242
+ }
243
+ switch (tag)
244
+ {
245
+ case semantic_tag::undefined:
246
+ before_value(jsoncons::bson::bson_type::undefined_type);
247
+ break;
248
+ default:
249
+ before_value(jsoncons::bson::bson_type::null_type);
250
+ break;
251
+ }
252
+ return true;
253
+ }
254
+
255
+ bool visit_bool(bool val, semantic_tag, const ser_context&, std::error_code& ec) override
256
+ {
257
+ if (stack_.empty())
258
+ {
259
+ ec = bson_errc::expected_bson_document;
260
+ return false;
261
+ }
262
+ before_value(jsoncons::bson::bson_type::bool_type);
263
+ if (val)
264
+ {
265
+ buffer_.push_back(0x01);
266
+ }
267
+ else
268
+ {
269
+ buffer_.push_back(0x00);
270
+ }
271
+
272
+ return true;
273
+ }
274
+
275
+ bool visit_string(const string_view_type& sv, semantic_tag tag, const ser_context&, std::error_code& ec) override
276
+ {
277
+ if (stack_.empty())
278
+ {
279
+ ec = bson_errc::expected_bson_document;
280
+ return false;
281
+ }
282
+
283
+ switch (tag)
284
+ {
285
+ case semantic_tag::float128:
286
+ {
287
+ before_value(jsoncons::bson::bson_type::decimal128_type);
288
+ decimal128_t dec;
289
+ auto rc = decimal128_from_chars(sv.data(), sv.data()+sv.size(), dec);
290
+ if (rc.ec != std::errc())
291
+ {
292
+ ec = bson_errc::invalid_decimal128_string;
293
+ return false;
294
+ }
295
+ binary::native_to_little(dec.low,std::back_inserter(buffer_));
296
+ binary::native_to_little(dec.high,std::back_inserter(buffer_));
297
+ break;
298
+ }
299
+ case semantic_tag::id:
300
+ {
301
+ before_value(jsoncons::bson::bson_type::object_id_type);
302
+ oid_t oid(sv);
303
+ for (auto b : oid)
304
+ {
305
+ buffer_.push_back(b);
306
+ }
307
+ break;
308
+ }
309
+ case semantic_tag::regex:
310
+ {
311
+ before_value(jsoncons::bson::bson_type::regex_type);
312
+ std::size_t first = sv.find_first_of('/');
313
+ std::size_t last = sv.find_last_of('/');
314
+ if (first == string_view::npos || last == string_view::npos || first == last)
315
+ {
316
+ ec = bson_errc::invalid_regex_string;
317
+ return false;
318
+ }
319
+ string_view regex = sv.substr(first+1,last-1);
320
+ for (auto c : regex)
321
+ {
322
+ buffer_.push_back(c);
323
+ }
324
+ buffer_.push_back(0x00);
325
+ string_view options = sv.substr(last+1);
326
+ for (auto c : options)
327
+ {
328
+ buffer_.push_back(c);
329
+ }
330
+ buffer_.push_back(0x00);
331
+ break;
332
+ }
333
+ default:
334
+ switch (tag)
335
+ {
336
+ case semantic_tag::code:
337
+ before_value(jsoncons::bson::bson_type::javascript_type);
338
+ break;
339
+ default:
340
+ before_value(jsoncons::bson::bson_type::string_type);
341
+ break;
342
+ }
343
+ std::size_t offset = buffer_.size();
344
+ buffer_.insert(buffer_.end(), sizeof(int32_t), 0);
345
+ std::size_t string_offset = buffer_.size();
346
+ auto sink = unicode_traits::validate(sv.data(), sv.size());
347
+ if (sink.ec != unicode_traits::conv_errc())
348
+ {
349
+ ec = bson_errc::invalid_utf8_text_string;
350
+ return false;
351
+ }
352
+ for (auto c : sv)
353
+ {
354
+ buffer_.push_back(c);
355
+ }
356
+ buffer_.push_back(0x00);
357
+ std::size_t length = buffer_.size() - string_offset;
358
+ binary::native_to_little(static_cast<uint32_t>(length), buffer_.begin()+offset);
359
+ break;
360
+ }
361
+
362
+ return true;
363
+ }
364
+
365
+ bool visit_byte_string(const byte_string_view& b,
366
+ semantic_tag,
367
+ const ser_context&,
368
+ std::error_code& ec) override
369
+ {
370
+ if (stack_.empty())
371
+ {
372
+ ec = bson_errc::expected_bson_document;
373
+ return false;
374
+ }
375
+ before_value(jsoncons::bson::bson_type::binary_type);
376
+
377
+ std::size_t offset = buffer_.size();
378
+ buffer_.insert(buffer_.end(), sizeof(int32_t), 0);
379
+ std::size_t string_offset = buffer_.size();
380
+
381
+ buffer_.push_back(0x80); // default subtype
382
+
383
+ for (auto c : b)
384
+ {
385
+ buffer_.push_back(c);
386
+ }
387
+ std::size_t length = buffer_.size() - string_offset - 1;
388
+ binary::native_to_little(static_cast<uint32_t>(length), buffer_.begin()+offset);
389
+
390
+ return true;
391
+ }
392
+
393
+ bool visit_byte_string(const byte_string_view& b,
394
+ uint64_t ext_tag,
395
+ const ser_context&,
396
+ std::error_code& ec) override
397
+ {
398
+ if (stack_.empty())
399
+ {
400
+ ec = bson_errc::expected_bson_document;
401
+ return false;
402
+ }
403
+ before_value(jsoncons::bson::bson_type::binary_type);
404
+
405
+ std::size_t offset = buffer_.size();
406
+ buffer_.insert(buffer_.end(), sizeof(int32_t), 0);
407
+ std::size_t string_offset = buffer_.size();
408
+
409
+ buffer_.push_back(static_cast<uint8_t>(ext_tag)); // default subtype
410
+
411
+ for (auto c : b)
412
+ {
413
+ buffer_.push_back(c);
414
+ }
415
+ std::size_t length = buffer_.size() - string_offset - 1;
416
+ binary::native_to_little(static_cast<uint32_t>(length), buffer_.begin()+offset);
417
+
418
+ return true;
419
+ }
420
+
421
+ bool visit_int64(int64_t val,
422
+ semantic_tag tag,
423
+ const ser_context&,
424
+ std::error_code& ec) override
425
+ {
426
+ static constexpr int64_t min_value_div_1000 = (std::numeric_limits<int64_t>::min)() / 1000;
427
+ static constexpr int64_t max_value_div_1000 = (std::numeric_limits<int64_t>::max)() / 1000;
428
+ if (stack_.empty())
429
+ {
430
+ ec = bson_errc::expected_bson_document;
431
+ return false;
432
+ }
433
+
434
+ switch (tag)
435
+ {
436
+ case semantic_tag::epoch_second:
437
+ if (val < min_value_div_1000)
438
+ {
439
+ ec = bson_errc::datetime_too_small;
440
+ return false;
441
+ }
442
+ if (val > max_value_div_1000)
443
+ {
444
+ ec = bson_errc::datetime_too_large;
445
+ return false;
446
+ }
447
+ before_value(jsoncons::bson::bson_type::datetime_type);
448
+ binary::native_to_little(val*millis_in_second,std::back_inserter(buffer_));
449
+ return true;
450
+ case semantic_tag::epoch_milli:
451
+ before_value(jsoncons::bson::bson_type::datetime_type);
452
+ binary::native_to_little(val,std::back_inserter(buffer_));
453
+ return true;
454
+ case semantic_tag::epoch_nano:
455
+ before_value(jsoncons::bson::bson_type::datetime_type);
456
+ if (val != 0)
457
+ {
458
+ val /= nanos_in_milli;
459
+ }
460
+ binary::native_to_little(static_cast<int64_t>(val),std::back_inserter(buffer_));
461
+ return true;
462
+ default:
463
+ {
464
+ if (val >= (std::numeric_limits<int32_t>::lowest)() && val <= (std::numeric_limits<int32_t>::max)())
465
+ {
466
+ before_value(jsoncons::bson::bson_type::int32_type);
467
+ binary::native_to_little(static_cast<uint32_t>(val),std::back_inserter(buffer_));
468
+ }
469
+ else
470
+ {
471
+ before_value(jsoncons::bson::bson_type::int64_type);
472
+ binary::native_to_little(static_cast<int64_t>(val),std::back_inserter(buffer_));
473
+ }
474
+ return true;
475
+ }
476
+ }
477
+ }
478
+
479
+ bool visit_uint64(uint64_t val,
480
+ semantic_tag tag,
481
+ const ser_context&,
482
+ std::error_code& ec) override
483
+ {
484
+ static constexpr uint64_t max_value_div_1000 = (std::numeric_limits<uint64_t>::max)() / 1000;
485
+ if (stack_.empty())
486
+ {
487
+ ec = bson_errc::expected_bson_document;
488
+ return false;
489
+ }
490
+
491
+ switch (tag)
492
+ {
493
+ case semantic_tag::epoch_second:
494
+ if (val > max_value_div_1000)
495
+ {
496
+ ec = bson_errc::datetime_too_large;
497
+ return false;
498
+ }
499
+ before_value(jsoncons::bson::bson_type::datetime_type);
500
+ binary::native_to_little(static_cast<int64_t>(val*millis_in_second),std::back_inserter(buffer_));
501
+ return true;
502
+ case semantic_tag::epoch_milli:
503
+ before_value(jsoncons::bson::bson_type::datetime_type);
504
+ binary::native_to_little(static_cast<int64_t>(val),std::back_inserter(buffer_));
505
+ return true;
506
+ case semantic_tag::epoch_nano:
507
+ before_value(jsoncons::bson::bson_type::datetime_type);
508
+ if (val != 0)
509
+ {
510
+ val /= nanos_in_second;
511
+ }
512
+ binary::native_to_little(static_cast<int64_t>(val),std::back_inserter(buffer_));
513
+ return true;
514
+ default:
515
+ {
516
+ bool more;
517
+ if (val <= static_cast<uint64_t>((std::numeric_limits<int32_t>::max)()))
518
+ {
519
+ before_value(jsoncons::bson::bson_type::int32_type);
520
+ binary::native_to_little(static_cast<uint32_t>(val),std::back_inserter(buffer_));
521
+ more = true;
522
+ }
523
+ else if (val <= static_cast<uint64_t>((std::numeric_limits<int64_t>::max)()))
524
+ {
525
+ before_value(jsoncons::bson::bson_type::int64_type);
526
+ binary::native_to_little(static_cast<uint64_t>(val),std::back_inserter(buffer_));
527
+ more = true;
528
+ }
529
+ else
530
+ {
531
+ ec = bson_errc::number_too_large;
532
+ more = false;
533
+ }
534
+ return more;
535
+ }
536
+ }
537
+ }
538
+
539
+ bool visit_double(double val,
540
+ semantic_tag,
541
+ const ser_context&,
542
+ std::error_code& ec) override
543
+ {
544
+ if (stack_.empty())
545
+ {
546
+ ec = bson_errc::expected_bson_document;
547
+ return false;
548
+ }
549
+ before_value(jsoncons::bson::bson_type::double_type);
550
+ binary::native_to_little(val,std::back_inserter(buffer_));
551
+ return true;
552
+ }
553
+
554
+ void before_value(uint8_t code)
555
+ {
556
+ JSONCONS_ASSERT(!stack_.empty());
557
+ if (stack_.back().is_object())
558
+ {
559
+ buffer_[stack_.back().member_offset()] = code;
560
+ }
561
+ else
562
+ {
563
+ buffer_.push_back(code);
564
+ std::string name = std::to_string(stack_.back().next_index());
565
+ buffer_.insert(buffer_.end(), name.begin(), name.end());
566
+ buffer_.push_back(0x00);
567
+ }
568
+ }
569
+ };
570
+
571
+ using bson_stream_encoder = basic_bson_encoder<jsoncons::binary_stream_sink>;
572
+ using bson_bytes_encoder = basic_bson_encoder<jsoncons::bytes_sink<std::vector<uint8_t>>>;
573
+
574
+ #if !defined(JSONCONS_NO_DEPRECATED)
575
+ template<class Sink=jsoncons::binary_stream_sink>
576
+ using basic_bson_serializer = basic_bson_encoder<Sink>;
577
+
578
+ JSONCONS_DEPRECATED_MSG("Instead, use bson_stream_encoder") typedef bson_stream_encoder bson_encoder;
579
+ JSONCONS_DEPRECATED_MSG("Instead, use bson_stream_encoder") typedef bson_stream_encoder bson_serializer;
580
+ JSONCONS_DEPRECATED_MSG("Instead, use bson_bytes_encoder") typedef bson_bytes_encoder bson_buffer_serializer;
581
+
582
+ #endif
583
+
584
+ }}
585
+ #endif
@@ -0,0 +1,103 @@
1
+ /// Copyright 2018 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_BSON_BSON_ERROR_HPP
8
+ #define JSONCONS_BSON_BSON_ERROR_HPP
9
+
10
+ #include <system_error>
11
+ #include <jsoncons/config/jsoncons_config.hpp>
12
+
13
+ namespace jsoncons { namespace bson {
14
+
15
+ enum class bson_errc
16
+ {
17
+ success = 0,
18
+ unexpected_eof = 1,
19
+ source_error,
20
+ invalid_utf8_text_string,
21
+ max_nesting_depth_exceeded,
22
+ string_length_is_non_positive,
23
+ length_is_negative,
24
+ number_too_large,
25
+ invalid_decimal128_string,
26
+ datetime_too_small,
27
+ datetime_too_large,
28
+ expected_bson_document,
29
+ invalid_regex_string,
30
+ size_mismatch,
31
+ unknown_type
32
+ };
33
+
34
+ class bson_error_category_impl
35
+ : public std::error_category
36
+ {
37
+ public:
38
+ const char* name() const noexcept override
39
+ {
40
+ return "jsoncons/bson";
41
+ }
42
+ std::string message(int ev) const override
43
+ {
44
+ switch (static_cast<bson_errc>(ev))
45
+ {
46
+ case bson_errc::unexpected_eof:
47
+ return "Unexpected end of file";
48
+ case bson_errc::source_error:
49
+ return "Source error";
50
+ case bson_errc::invalid_utf8_text_string:
51
+ return "Illegal UTF-8 encoding in text string";
52
+ case bson_errc::max_nesting_depth_exceeded:
53
+ return "Data item nesting exceeds limit in options";
54
+ case bson_errc::string_length_is_non_positive:
55
+ return "Request for the length of a string returned a non-positive result";
56
+ case bson_errc::length_is_negative:
57
+ return "Request for the length of a binary returned a negative result";
58
+ case bson_errc::unknown_type:
59
+ return "An unknown type was found in the stream";
60
+ case bson_errc::number_too_large:
61
+ return "Number too large";
62
+ case bson_errc::invalid_decimal128_string:
63
+ return "Invalid decimal128 string";
64
+ case bson_errc::datetime_too_large:
65
+ return "datetime too large";
66
+ case bson_errc::datetime_too_small:
67
+ return "datetime too small";
68
+ case bson_errc::expected_bson_document:
69
+ return "Expected BSON document";
70
+ case bson_errc::invalid_regex_string:
71
+ return "Invalid regex string";
72
+ case bson_errc::size_mismatch:
73
+ return "Document or array size doesn't match bytes read";
74
+ default:
75
+ return "Unknown BSON parser error";
76
+ }
77
+ }
78
+ };
79
+
80
+ inline
81
+ const std::error_category& bson_error_category()
82
+ {
83
+ static bson_error_category_impl instance;
84
+ return instance;
85
+ }
86
+
87
+ inline
88
+ std::error_code make_error_code(bson_errc result)
89
+ {
90
+ return std::error_code(static_cast<int>(result),bson_error_category());
91
+ }
92
+
93
+
94
+ }}
95
+
96
+ namespace std {
97
+ template<>
98
+ struct is_error_code_enum<jsoncons::bson::bson_errc> : public true_type
99
+ {
100
+ };
101
+ }
102
+
103
+ #endif