jsoncons 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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