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,635 @@
1
+ // Copyright 2020 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_URI_HPP
8
+ #define JSONCONS_URI_HPP
9
+
10
+ #include <string> // std::string
11
+ #include <algorithm>
12
+ #include <sstream>
13
+ #include <jsoncons/config/jsoncons_config.hpp>
14
+ #include <jsoncons/json_exception.hpp>
15
+
16
+ namespace jsoncons {
17
+
18
+ class uri
19
+ {
20
+ using part_type = std::pair<std::size_t,std::size_t>;
21
+
22
+ std::string uri_;
23
+ part_type scheme_;
24
+ part_type userinfo_;
25
+ part_type host_;
26
+ part_type port_;
27
+ part_type path_;
28
+ part_type query_;
29
+ part_type fragment_;
30
+ public:
31
+
32
+ uri() = default;
33
+
34
+ uri(const std::string& uri)
35
+ {
36
+ *this = parse(uri);
37
+ }
38
+
39
+ uri(jsoncons::string_view scheme,
40
+ jsoncons::string_view userinfo,
41
+ jsoncons::string_view host,
42
+ jsoncons::string_view port,
43
+ jsoncons::string_view path,
44
+ jsoncons::string_view query,
45
+ jsoncons::string_view fragment)
46
+ {
47
+ if (!scheme.empty())
48
+ {
49
+ uri_.append(std::string(scheme));
50
+ scheme_.second = uri_.length();
51
+ }
52
+ if (!userinfo.empty() || !host.empty() || !port.empty())
53
+ {
54
+ if (!scheme.empty())
55
+ {
56
+ uri_.append("://");
57
+ }
58
+
59
+ if (!userinfo.empty())
60
+ {
61
+ userinfo_.first = uri_.length();
62
+ uri_.append(std::string(userinfo));
63
+ userinfo_.second = uri_.length();
64
+ uri_.append("@");
65
+ }
66
+ else
67
+ {
68
+ userinfo_.first = userinfo_.second = uri_.length();
69
+ }
70
+
71
+ if (!host.empty())
72
+ {
73
+ host_.first = uri_.length();
74
+ uri_.append(std::string(host));
75
+ host_.second = uri_.length();
76
+ }
77
+ else
78
+ {
79
+ JSONCONS_THROW(json_runtime_error<std::invalid_argument>("uri error."));
80
+ }
81
+
82
+ if (!port.empty())
83
+ {
84
+ uri_.append(":");
85
+ port_.first = uri_.length();
86
+ uri_.append(std::string(port));
87
+ port_.second = uri_.length();
88
+ }
89
+ else
90
+ {
91
+ port_.first = port_.second = uri_.length();
92
+ }
93
+ }
94
+ else
95
+ {
96
+ userinfo_.first = userinfo_.second = uri_.length();
97
+ host_.first = host_.second = uri_.length();
98
+ port_.first = port_.second = uri_.length();
99
+ if (!scheme.empty())
100
+ {
101
+ if (!path.empty() || !query.empty() || !fragment.empty())
102
+ {
103
+ uri_.append(":");
104
+ }
105
+ else
106
+ {
107
+ JSONCONS_THROW(json_runtime_error<std::invalid_argument>("uri error."));
108
+ }
109
+ }
110
+ }
111
+
112
+ if (!path.empty())
113
+ {
114
+ // if the URI is not opaque and the path is not already prefixed
115
+ // with a '/', add one.
116
+ path_.first = uri_.length();
117
+ if (!host.empty() && (path.front() != '/'))
118
+ {
119
+ uri_.push_back('/');
120
+ }
121
+ uri_.append(std::string(path));
122
+ path_.second = uri_.length();
123
+ }
124
+ else
125
+ {
126
+ path_.first = path_.second = uri_.length();
127
+ }
128
+
129
+ if (!query.empty())
130
+ {
131
+ uri_.append("?");
132
+ query_.first = uri_.length();
133
+ uri_.append(std::string(query));
134
+ query_.second = uri_.length();
135
+ }
136
+ else
137
+ {
138
+ query_.first = query_.second = uri_.length();
139
+ }
140
+
141
+ if (!fragment.empty())
142
+ {
143
+ uri_.append("#");
144
+ fragment_.first = uri_.length();
145
+ uri_.append(std::string(fragment));
146
+ fragment_.second = uri_.length();
147
+ }
148
+ else
149
+ {
150
+ fragment_.first = fragment_.second = uri_.length();
151
+ }
152
+ }
153
+
154
+ const std::string& string() const
155
+ {
156
+ return uri_;
157
+ }
158
+
159
+ bool is_absolute() const noexcept
160
+ {
161
+ return scheme_.first != scheme_.second;
162
+ }
163
+
164
+ bool is_opaque() const noexcept
165
+ {
166
+ return is_absolute() && !authority().empty();
167
+ }
168
+
169
+ string_view base() const noexcept { return string_view(uri_.data()+scheme_.first,(path_.second-scheme_.first)); }
170
+
171
+ string_view scheme() const noexcept { return string_view(uri_.data()+scheme_.first,(scheme_.second-scheme_.first)); }
172
+
173
+ string_view userinfo() const noexcept { return string_view(uri_.data()+userinfo_.first,(userinfo_.second-userinfo_.first)); }
174
+
175
+ string_view host() const noexcept { return string_view(uri_.data()+host_.first,(host_.second-host_.first)); }
176
+
177
+ string_view port() const noexcept { return string_view(uri_.data()+port_.first,(port_.second-port_.first)); }
178
+
179
+ string_view path() const noexcept { return string_view(uri_.data()+path_.first,(path_.second-path_.first)); }
180
+
181
+ string_view query() const noexcept { return string_view(uri_.data()+query_.first,(query_.second-query_.first)); }
182
+
183
+ string_view fragment() const noexcept { return string_view(uri_.data()+fragment_.first,(fragment_.second-fragment_.first)); }
184
+
185
+ string_view authority() const noexcept { return string_view(uri_.data()+userinfo_.first,(port_.second-userinfo_.first)); }
186
+
187
+ uri resolve(const uri& base) const
188
+ {
189
+ // This implementation uses the psuedo-code given in
190
+ // http://tools.ietf.org/html/rfc3986#section-5.2.2
191
+
192
+ if (is_absolute() && !is_opaque())
193
+ {
194
+ return *this;
195
+ }
196
+
197
+ if (is_opaque())
198
+ {
199
+ return *this;
200
+ }
201
+
202
+ std::string userinfo, host, port, path, query, fragment;
203
+
204
+ if (!authority().empty())
205
+ {
206
+ // g -> http://g
207
+ if (!this->userinfo().empty())
208
+ {
209
+ userinfo = std::string(this->userinfo());
210
+ }
211
+
212
+ if (!this->host().empty())
213
+ {
214
+ host = std::string(this->host());
215
+ }
216
+
217
+ if (!this->port().empty())
218
+ {
219
+ port = std::string(this->port());
220
+ }
221
+
222
+ if (!this->path().empty())
223
+ {
224
+ path = remove_dot_segments(this->path());
225
+ }
226
+
227
+ if (!this->query().empty())
228
+ {
229
+ query = std::string(this->query());
230
+ }
231
+ }
232
+ else
233
+ {
234
+ if (this->path().empty())
235
+ {
236
+ if (!base.path().empty())
237
+ {
238
+ path = std::string(base.path());
239
+ }
240
+
241
+ if (!this->query().empty())
242
+ {
243
+ query = std::string(this->query());
244
+ }
245
+ else if (!base.query().empty())
246
+ {
247
+ query = std::string(base.query());
248
+ }
249
+ }
250
+ else
251
+ {
252
+ if (this->path().front() == '/')
253
+ {
254
+ path = remove_dot_segments(this->path());
255
+ }
256
+ else
257
+ {
258
+ path = merge_paths(base, *this);
259
+ }
260
+
261
+ if (!this->query().empty())
262
+ {
263
+ query = std::string(this->query());
264
+ }
265
+ }
266
+
267
+ if (!base.userinfo().empty())
268
+ {
269
+ userinfo = std::string(base.userinfo());
270
+ }
271
+
272
+ if (!base.host().empty())
273
+ {
274
+ host = std::string(base.host());
275
+ }
276
+
277
+ if (!base.port().empty())
278
+ {
279
+ port = std::string(base.port());
280
+ }
281
+ }
282
+
283
+ if (!this->fragment().empty())
284
+ {
285
+ fragment = std::string(this->fragment());
286
+ }
287
+
288
+ return uri(std::string(base.scheme()), userinfo, host, port, path, query, fragment);
289
+ }
290
+
291
+ int compare(const uri& other) const
292
+ {
293
+ int result = scheme().compare(other.scheme());
294
+ if (result != 0) return result;
295
+ result = userinfo().compare(other.userinfo());
296
+ if (result != 0) return result;
297
+ result = host().compare(other.host());
298
+ if (result != 0) return result;
299
+ result = port().compare(other.port());
300
+ if (result != 0) return result;
301
+ result = path().compare(other.path());
302
+ if (result != 0) return result;
303
+ result = query().compare(other.query());
304
+ if (result != 0) return result;
305
+ result = fragment().compare(other.fragment());
306
+
307
+ return result;
308
+ }
309
+
310
+ friend bool operator==(const uri& lhs, const uri& rhs)
311
+ {
312
+ return lhs.compare(rhs) == 0;
313
+ }
314
+
315
+ friend bool operator!=(const uri& lhs, const uri& rhs)
316
+ {
317
+ return lhs.compare(rhs) != 0;
318
+ }
319
+
320
+ friend bool operator<(const uri& lhs, const uri& rhs)
321
+ {
322
+ return lhs.compare(rhs) < 0;
323
+ }
324
+
325
+ friend bool operator<=(const uri& lhs, const uri& rhs)
326
+ {
327
+ return lhs.compare(rhs) <= 0;
328
+ }
329
+
330
+ friend bool operator>(const uri& lhs, const uri& rhs)
331
+ {
332
+ return lhs.compare(rhs) > 0;
333
+ }
334
+
335
+ friend bool operator>=(const uri& lhs, const uri& rhs)
336
+ {
337
+ return lhs.compare(rhs) >= 0;
338
+ }
339
+
340
+ private:
341
+ enum class parse_state {expect_scheme,
342
+ expect_first_slash,
343
+ expect_second_slash,
344
+ expect_authority,
345
+ expect_host_ipv6,
346
+ expect_userinfo,
347
+ expect_host,
348
+ expect_port,
349
+ expect_path,
350
+ expect_query,
351
+ expect_fragment};
352
+
353
+ uri(const std::string& uri, part_type scheme, part_type userinfo,
354
+ part_type host, part_type port, part_type path,
355
+ part_type query, part_type fragment)
356
+ : uri_(uri), scheme_(scheme), userinfo_(userinfo),
357
+ host_(host), port_(port), path_(path),
358
+ query_(query), fragment_(fragment)
359
+ {
360
+ }
361
+
362
+ static uri parse(const std::string& s)
363
+ {
364
+ part_type scheme;
365
+ part_type userinfo;
366
+ part_type host;
367
+ part_type port;
368
+ part_type path;
369
+ part_type query;
370
+ part_type fragment;
371
+
372
+ std::size_t start = 0;
373
+
374
+ parse_state state = parse_state::expect_scheme;
375
+ for (std::size_t i = 0; i < s.size(); ++i)
376
+ {
377
+ char c = s[i];
378
+ switch (state)
379
+ {
380
+ case parse_state::expect_scheme:
381
+ switch (c)
382
+ {
383
+ case ':':
384
+ scheme = std::make_pair(start,i);
385
+ state = parse_state::expect_first_slash;
386
+ start = i;
387
+ break;
388
+ case '#':
389
+ userinfo = std::make_pair(start,start);
390
+ host = std::make_pair(start,start);
391
+ port = std::make_pair(start,start);
392
+ path = std::make_pair(start,i);
393
+ query = std::make_pair(i,i);
394
+ state = parse_state::expect_fragment;
395
+ start = i+1;
396
+ break;
397
+ default:
398
+ break;
399
+ }
400
+ break;
401
+ case parse_state::expect_first_slash:
402
+ switch (c)
403
+ {
404
+ case '/':
405
+ state = parse_state::expect_second_slash;
406
+ break;
407
+ default:
408
+ start = i;
409
+ state = parse_state::expect_path;
410
+ break;
411
+ }
412
+ break;
413
+ case parse_state::expect_second_slash:
414
+ switch (c)
415
+ {
416
+ case '/':
417
+ state = parse_state::expect_authority;
418
+ start = i+1;
419
+ break;
420
+ default:
421
+ break;
422
+ }
423
+ break;
424
+ case parse_state::expect_authority:
425
+ switch (c)
426
+ {
427
+ case '[':
428
+ state = parse_state::expect_host_ipv6;
429
+ start = i+1;
430
+ break;
431
+ default:
432
+ state = parse_state::expect_userinfo;
433
+ start = i;
434
+ --i;
435
+ break;
436
+ }
437
+ break;
438
+ case parse_state::expect_host_ipv6:
439
+ switch (c)
440
+ {
441
+ case ']':
442
+ userinfo = std::make_pair(start,start);
443
+ host = std::make_pair(start,i);
444
+ port = std::make_pair(i,i);
445
+ state = parse_state::expect_path;
446
+ start = i+1;
447
+ break;
448
+ default:
449
+ break;
450
+ }
451
+ break;
452
+ case parse_state::expect_userinfo:
453
+ switch (c)
454
+ {
455
+ case '@':
456
+ userinfo = std::make_pair(start,i);
457
+ state = parse_state::expect_host;
458
+ start = i+1;
459
+ break;
460
+ case ':':
461
+ userinfo = std::make_pair(start,start);
462
+ host = std::make_pair(start,i);
463
+ state = parse_state::expect_port;
464
+ start = i+1;
465
+ break;
466
+ case '/':
467
+ userinfo = std::make_pair(start,start);
468
+ host = std::make_pair(start,i);
469
+ port = std::make_pair(i,i);
470
+ state = parse_state::expect_path;
471
+ start = i;
472
+ break;
473
+ default:
474
+ break;
475
+ }
476
+ break;
477
+ case parse_state::expect_host:
478
+ switch (c)
479
+ {
480
+ case ':':
481
+ host = std::make_pair(start,i);
482
+ state = parse_state::expect_port;
483
+ start = i+1;
484
+ break;
485
+ default:
486
+ break;
487
+ }
488
+ break;
489
+ case parse_state::expect_port:
490
+ switch (c)
491
+ {
492
+ case '/':
493
+ port = std::make_pair(start,i);
494
+ state = parse_state::expect_path;
495
+ start = i;
496
+ break;
497
+ default:
498
+ break;
499
+ }
500
+ break;
501
+ case parse_state::expect_path:
502
+ switch (c)
503
+ {
504
+ case '?':
505
+ path = std::make_pair(start,i);
506
+ state = parse_state::expect_query;
507
+ start = i+1;
508
+ break;
509
+ case '#':
510
+ path = std::make_pair(start,i);
511
+ query = std::make_pair(start,start);
512
+ state = parse_state::expect_fragment;
513
+ start = i+1;
514
+ break;
515
+ default:
516
+ break;
517
+ }
518
+ break;
519
+ case parse_state::expect_query:
520
+ switch (c)
521
+ {
522
+ case '#':
523
+ query = std::make_pair(start,i);
524
+ state = parse_state::expect_fragment;
525
+ start = i+1;
526
+ break;
527
+ default:
528
+ break;
529
+ }
530
+ break;
531
+ case parse_state::expect_fragment:
532
+ break;
533
+ }
534
+ }
535
+ switch (state)
536
+ {
537
+ case parse_state::expect_scheme:
538
+ userinfo = std::make_pair(start,start);
539
+ host = std::make_pair(start,start);
540
+ port = std::make_pair(start,start);
541
+ path = std::make_pair(start,s.size());
542
+ break;
543
+ case parse_state::expect_userinfo:
544
+ userinfo = std::make_pair(start,start);
545
+ host = std::make_pair(start,start);
546
+ port = std::make_pair(start,start);
547
+ path = std::make_pair(start,s.size());
548
+ break;
549
+ case parse_state::expect_path:
550
+ path = std::make_pair(start,s.size());
551
+ break;
552
+ case parse_state::expect_query:
553
+ query = std::make_pair(start,s.size());
554
+ break;
555
+ case parse_state::expect_fragment:
556
+ fragment = std::make_pair(start,s.size());
557
+ break;
558
+ default:
559
+ JSONCONS_THROW(std::invalid_argument("Invalid uri"));
560
+ break;
561
+ }
562
+
563
+ return uri(s, scheme, userinfo, host, port, path, query, fragment);
564
+ }
565
+
566
+ static std::string remove_dot_segments(const jsoncons::string_view& input)
567
+ {
568
+ std::string result = std::string(input);
569
+ /*
570
+ std::size_t pos = 0;
571
+ while (pos < input.size())
572
+ {
573
+ if (input.compare(0, 3, "../"))
574
+ {
575
+ network_boost::erase_head(input, 3);
576
+ } else if (network_boost::starts_with(input, "./")) {
577
+ network_boost::erase_head(input, 2);
578
+ } else if (network_boost::starts_with(input, "/./")) {
579
+ network_boost::replace_head(input, 3, "/");
580
+ } else if (input == "/.") {
581
+ network_boost::replace_head(input, 2, "/");
582
+ } else if (network_boost::starts_with(input, "/../")) {
583
+ network_boost::erase_head(input, 3);
584
+ remove_last_segment(result);
585
+ } else if (network_boost::starts_with(input, "/..")) {
586
+ network_boost::replace_head(input, 3, "/");
587
+ remove_last_segment(result);
588
+ } else if (network_boost::algorithm::all(input, [](char ch) { return ch == '.'; })) {
589
+ input.clear();
590
+ }
591
+ else {
592
+ int n = (input.front() == '/')? 1 : 0;
593
+ auto slash = network_boost::find_nth(input, "/", n);
594
+ result.append(std::begin(input), std::begin(slash));
595
+ input.erase(std::begin(input), std::begin(slash));
596
+ }
597
+ }
598
+ */
599
+ return result;
600
+ }
601
+
602
+ static std::string merge_paths(const uri& base, const uri& relative)
603
+ {
604
+ std::string result;
605
+
606
+ if (base.path().empty())
607
+ {
608
+ result = "/";
609
+ }
610
+ else
611
+ {
612
+ const auto& base_path = base.path();
613
+ auto last_slash = base_path.rfind('/');
614
+ result.append(std::string(base_path.substr(0,last_slash+1)));
615
+ }
616
+ if (!relative.path().empty())
617
+ {
618
+ result.append(relative.path().begin(), relative.path().end());
619
+ }
620
+ return remove_dot_segments(jsoncons::string_view(result));
621
+ }
622
+
623
+ static void remove_last_segment(std::string& path)
624
+ {
625
+ auto last_slash = path.rfind('/');
626
+ if (last_slash != std::string::npos)
627
+ {
628
+ path.erase(last_slash);
629
+ }
630
+ }
631
+ };
632
+
633
+ } // namespace jsoncons
634
+
635
+ #endif