1 #include <iostream>
2 #include "simdjson.h"
3
4 using namespace std;
5 using namespace simdjson;
6 using error_code=simdjson::error_code;
7
basics_1()8 void basics_1() {
9 const char *filename = "x.txt";
10
11 dom::parser parser;
12 dom::element doc = parser.load(filename); // load and parse a file
13
14 cout << doc;
15 }
16
basics_2()17 void basics_2() {
18 dom::parser parser;
19 dom::element doc = parser.parse("[1,2,3]"_padded); // parse a string
20
21 cout << doc;
22 }
23
basics_dom_1()24 void basics_dom_1() {
25 auto cars_json = R"( [
26 { "make": "Toyota", "model": "Camry", "year": 2018, "tire_pressure": [ 40.1, 39.9, 37.7, 40.4 ] },
27 { "make": "Kia", "model": "Soul", "year": 2012, "tire_pressure": [ 30.1, 31.0, 28.6, 28.7 ] },
28 { "make": "Toyota", "model": "Tercel", "year": 1999, "tire_pressure": [ 29.8, 30.0, 30.2, 30.5 ] }
29 ] )"_padded;
30 dom::parser parser;
31
32 // Parse and iterate through each car
33 for (dom::object car : parser.parse(cars_json)) {
34 // Accessing a field by name
35 cout << "Make/Model: " << car["make"] << "/" << car["model"] << endl;
36
37 // Casting a JSON element to an integer
38 uint64_t year = car["year"];
39 cout << "- This car is " << 2020 - year << "years old." << endl;
40
41 // Iterating through an array of floats
42 double total_tire_pressure = 0;
43 for (double tire_pressure : car["tire_pressure"]) {
44 total_tire_pressure += tire_pressure;
45 }
46 cout << "- Average tire pressure: " << (total_tire_pressure / 4) << endl;
47
48 // Writing out all the information about the car
49 for (auto field : car) {
50 cout << "- " << field.key << ": " << field.value << endl;
51 }
52 }
53 }
54
parse_many_truncated()55 void parse_many_truncated() {
56 auto json = R"([1,2,3] {"1":1,"2":3,"4":4} {"key":"intentionally unclosed string )"_padded;
57 simdjson::dom::parser parser;
58 simdjson::dom::document_stream stream;
59 auto error = parser.parse_many(json,json.size()).get(stream);
60 if(error) { std::cerr << error << std::endl; return; }
61 for(auto doc : stream) {
62 std::cout << doc << std::endl;
63 }
64 std::cout << stream.truncated_bytes() << " bytes "<< std::endl; // returns 39 bytes
65 }
66
67 void basics_dom_2() {
68 auto cars_json = R"( [
69 { "make": "Toyota", "model": "Camry", "year": 2018, "tire_pressure": [ 40.1, 39.9, 37.7, 40.4 ] },
70 { "make": "Kia", "model": "Soul", "year": 2012, "tire_pressure": [ 30.1, 31.0, 28.6, 28.7 ] },
71 { "make": "Toyota", "model": "Tercel", "year": 1999, "tire_pressure": [ 29.8, 30.0, 30.2, 30.5 ] }
72 ] )"_padded;
73 dom::parser parser;
74 dom::element cars = parser.parse(cars_json);
75 cout << cars.at_pointer("/0/tire_pressure/1") << endl; // Prints 39.9
76 for (dom::element car_element : cars) {
77 dom::object car;
78 simdjson::error_code error;
79 if ((error = car_element.get(car))) { std::cerr << error << std::endl; return; }
80 double x = car.at_pointer("/tire_pressure/1");
81 cout << x << endl; // Prints 39.9, 31 and 30
82 }
83 }
84
85 void basics_dom_3() {
86 auto abstract_json = R"( [
87 { "12345" : {"a":12.34, "b":56.78, "c": 9998877} },
88 { "12545" : {"a":11.44, "b":12.78, "c": 11111111} }
89 ] )"_padded;
90 dom::parser parser;
91
92 // Parse and iterate through an array of objects
93 for (dom::object obj : parser.parse(abstract_json)) {
94 for(const auto key_value : obj) {
95 cout << "key: " << key_value.key << " : ";
96 dom::object innerobj = key_value.value;
97 cout << "a: " << double(innerobj["a"]) << ", ";
98 cout << "b: " << double(innerobj["b"]) << ", ";
99 cout << "c: " << int64_t(innerobj["c"]) << endl;
100 }
101 }
102 }
103
104 void basics_dom_4() {
105 auto abstract_json = R"(
106 { "str" : { "123" : {"abc" : 3.14 } } } )"_padded;
107 dom::parser parser;
108 double v = parser.parse(abstract_json)["str"]["123"]["abc"];
109 cout << "number: " << v << endl;
110 }
111
112 namespace ondemand_treewalk {
113 // We use a template function because we need to
114 // support both ondemand::value and ondemand::document
115 // as a parameter type. Note that we move the values.
116 template <class T>
117 void recursive_print_json(T&& element) {
118 bool add_comma;
119 switch (element.type()) {
120 case ondemand::json_type::array:
121 cout << "[";
122 add_comma = false;
123 for (auto child : element.get_array()) {
124 if (add_comma) {
125 cout << ",";
126 }
127 // We need the call to value() to get
128 // an ondemand::value type.
129 recursive_print_json(child.value());
130 add_comma = true;
131 }
132 cout << "]";
133 break;
134 case ondemand::json_type::object:
135 cout << "{";
136 add_comma = false;
137 for (auto field : element.get_object()) {
138 if (add_comma) {
139 cout << ",";
140 }
141 // key() returns the unescaped key, if we
142 // want the escaped key, we should do
143 // field.unescaped_key().
144 cout << "\"" << field.key() << "\": ";
145 recursive_print_json(field.value());
146 add_comma = true;
147 }
148 cout << "}";
149 break;
150 case ondemand::json_type::number:
151 // assume it fits in a double
152 cout << element.get_double();
153 break;
154 case ondemand::json_type::string:
155 // get_string() would return escaped string, but
156 // we are happy with unescaped string.
157 cout << "\"" << element.get_raw_json_string() << "\"";
158 break;
159 case ondemand::json_type::boolean:
160 cout << element.get_bool();
161 break;
162 case ondemand::json_type::null:
163 cout << "null";
164 break;
165 }
166 }
167
basics_treewalk()168 void basics_treewalk() {
169 ondemand::parser parser;
170 auto json = padded_string::load("twitter.json");
171 recursive_print_json(parser.iterate(json));
172 }
173
174 }
175
176 namespace treewalk_1 {
print_json(dom::element element)177 void print_json(dom::element element) {
178 switch (element.type()) {
179 case dom::element_type::ARRAY:
180 cout << "[";
181 for (dom::element child : dom::array(element)) {
182 print_json(child);
183 cout << ",";
184 }
185 cout << "]";
186 break;
187 case dom::element_type::OBJECT:
188 cout << "{";
189 for (dom::key_value_pair field : dom::object(element)) {
190 cout << "\"" << field.key << "\": ";
191 print_json(field.value);
192 }
193 cout << "}";
194 break;
195 case dom::element_type::INT64:
196 cout << int64_t(element) << endl;
197 break;
198 case dom::element_type::UINT64:
199 cout << uint64_t(element) << endl;
200 break;
201 case dom::element_type::DOUBLE:
202 cout << double(element) << endl;
203 break;
204 case dom::element_type::STRING:
205 cout << std::string_view(element) << endl;
206 break;
207 case dom::element_type::BOOL:
208 cout << bool(element) << endl;
209 break;
210 case dom::element_type::NULL_VALUE:
211 cout << "null" << endl;
212 break;
213 }
214 }
215
basics_treewalk_1()216 void basics_treewalk_1() {
217 dom::parser parser;
218 print_json(parser.load("twitter.json"));
219 }
220 }
221
222 #ifdef SIMDJSON_CPLUSPLUS17
basics_cpp17_1()223 void basics_cpp17_1() {
224 padded_string json = R"( { "foo": 1, "bar": 2 } )"_padded;
225 dom::parser parser;
226 dom::object object;
227 auto error = parser.parse(json).get(object);
228 if (error) { cerr << error << endl; return; }
229 for (auto [key, value] : object) {
230 cout << key << " = " << value << endl;
231 }
232 }
233 #endif
234
basics_cpp17_2()235 void basics_cpp17_2() {
236 // C++ 11 version for comparison
237 padded_string json = R"( { "foo": 1, "bar": 2 } )"_padded;
238 dom::parser parser;
239 dom::object object;
240 auto error = parser.parse(json).get(object);
241 if (error) { cerr << error << endl; return; }
242 for (dom::key_value_pair field : object) {
243 cout << field.key << " = " << field.value << endl;
244 }
245 }
246
basics_ndjson()247 void basics_ndjson() {
248 dom::parser parser;
249 for (dom::element doc : parser.load_many("x.txt")) {
250 cout << doc["foo"] << endl;
251 }
252 // Prints 1 2 3
253 }
254
basics_ndjson_parse_many()255 void basics_ndjson_parse_many() {
256 dom::parser parser;
257 auto json = R"({ "foo": 1 }
258 { "foo": 2 }
259 { "foo": 3 })"_padded;
260 dom::document_stream docs = parser.parse_many(json);
261 for (dom::element doc : docs) {
262 cout << doc["foo"] << endl;
263 }
264 }
implementation_selection_1()265 void implementation_selection_1() {
266 cout << "simdjson v" << STRINGIFY(SIMDJSON_VERSION) << endl;
267 cout << "Detected the best implementation for your machine: " << simdjson::active_implementation->name();
268 cout << "(" << simdjson::active_implementation->description() << ")" << endl;
269 }
270
unescaped_key()271 void unescaped_key() {
272 auto json = R"({"k\u0065y": 1})"_padded;
273 ondemand::parser parser;
274 auto doc = parser.iterate(json);
275 ondemand::object object = doc.get_object();
276 for(auto field : object) {
277 // parses and writes out the key, after unescaping it,
278 // to a string buffer. This should be expected to be much
279 // more costly than accessing the raw string ("key()").
280 std::string_view keyv = field.unescaped_key();
281 if(keyv == "key") {
282 std::cout << uint64_t(field.value());
283 }
284 // You can access the raw value like so:
285 // ondemand::raw_json_string keyv = field.key();
286 // if(keyv == R"(k\u0065y)") {
287 }
288 }
289
implementation_selection_2()290 void implementation_selection_2() {
291 for (auto implementation : simdjson::available_implementations) {
292 cout << implementation->name() << ": " << implementation->description() << endl;
293 }
294 }
295
implementation_selection_2_safe()296 void implementation_selection_2_safe() {
297 for (auto implementation : simdjson::available_implementations) {
298 if(implementation->supported_by_runtime_system()) {
299 cout << implementation->name() << ": " << implementation->description() << endl;
300 }
301 }
302 }
implementation_selection_3()303 void implementation_selection_3() {
304 cout << simdjson::available_implementations["fallback"]->description() << endl;
305 }
306
implementation_selection_safe()307 void implementation_selection_safe() {
308 auto my_implementation = simdjson::available_implementations["haswell"];
309 if(! my_implementation) { exit(1); }
310 if(! my_implementation->supported_by_runtime_system()) { exit(1); }
311 simdjson::active_implementation = my_implementation;
312 }
313
implementation_selection_4()314 void implementation_selection_4() {
315 // Use the fallback implementation, even though my machine is fast enough for anything
316 simdjson::active_implementation = simdjson::available_implementations["fallback"];
317 }
318
ondemand_performance_1()319 void ondemand_performance_1() {
320 ondemand::parser parser;
321
322 // This initializes buffers big enough to handle this JSON.
323 auto json = "[ true, false ]"_padded;
324 auto doc = parser.iterate(json);
325 for(bool i : doc.get_array()) {
326 cout << i << endl;
327 }
328
329
330 // This reuses the existing buffers
331 auto number_json = "[1, 2, 3]"_padded;
332 doc = parser.iterate(number_json);
333 for(int64_t i : doc.get_array()) {
334 cout << i << endl;
335 }
336 }
337
performance_1()338 void performance_1() {
339 dom::parser parser;
340
341 // This initializes buffers and a document big enough to handle this JSON.
342 dom::element doc = parser.parse("[ true, false ]"_padded);
343 cout << doc << endl;
344
345 // This reuses the existing buffers, and reuses and *overwrites* the old document
346 doc = parser.parse("[1, 2, 3]"_padded);
347 cout << doc << endl;
348
349 // This also reuses the existing buffers, and reuses and *overwrites* the old document
350 dom::element doc2 = parser.parse("true"_padded);
351 // Even if you keep the old reference around, doc and doc2 refer to the same document.
352 cout << doc << endl;
353 cout << doc2 << endl;
354 }
355
356 #ifdef SIMDJSON_CPLUSPLUS17
357 SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
358 // The web_request part of this is aspirational, so we compile as much as we can here
performance_2()359 void performance_2() {
360 dom::parser parser(1000*1000); // Never grow past documents > 1MB
361 /* for (web_request request : listen()) */ {
362 dom::element doc;
363 auto body = "1"_padded; /*request.body*/
364 auto error = parser.parse(body/*request.body*/).get(doc);
365 // If the document was above our limit, emit 413 = payload too large
366 if (error == CAPACITY) { /* request.respond(413); continue; */ }
367 // ...
368 }
369 }
370
371 // The web_request part of this is aspirational, so we compile as much as we can here
performance_3()372 void performance_3() {
373 dom::parser parser(0); // This parser will refuse to automatically grow capacity
374 auto error = parser.allocate(1000*1000); // This allocates enough capacity to handle documents <= 1MB
375 if (error) { cerr << error << endl; exit(1); }
376
377 /* for (web_request request : listen()) */ {
378 dom::element doc;
379 auto body = "1"_padded;/*request.body*/
380 auto error = parser.parse(body).get(doc);
381 // If the document was above our limit, emit 413 = payload too large
382 if (error == CAPACITY) { /* request.respond(413); continue; */ }
383 // ...
384 }
385 }
386 SIMDJSON_POP_DISABLE_WARNINGS
387 #endif
388
minify()389 void minify() {
390 const char * some_string = "[ 1, 2, 3, 4] ";
391 size_t length = std::strlen(some_string);
392 std::unique_ptr<char[]> buffer{new char[length]};
393 size_t new_length{};
394 auto error = simdjson::minify(some_string, length, buffer.get(), new_length);
395 if(error != simdjson::SUCCESS) {
396 std::cerr << "error " << error << std::endl;
397 abort();
398 } else {
399 const char * expected_string = "[1,2,3,4]";
400 size_t expected_length = std::strlen(expected_string);
401 if(expected_length != new_length) {
402 std::cerr << "mismatched length (error) " << std::endl;
403 abort();
404 }
405 for(size_t i = 0; i < new_length; i++) {
406 if(expected_string[i] != buffer.get()[i]) {
407 std::cerr << "mismatched content (error) " << std::endl;
408 abort();
409 }
410 }
411 }
412 }
413
is_correct()414 bool is_correct() {
415 const char * some_string = "[ 1, 2, 3, 4] ";
416 size_t length = std::strlen(some_string);
417 bool is_ok = simdjson::validate_utf8(some_string, length);
418 return is_ok;
419 }
420
is_correct_string_view()421 bool is_correct_string_view() {
422 const char * some_string = "[ 1, 2, 3, 4] ";
423 size_t length = std::strlen(some_string);
424 std::string_view v(some_string, length);
425 bool is_ok = simdjson::validate_utf8(v);
426 return is_ok;
427 }
428
is_correct_string()429 bool is_correct_string() {
430 const std::string some_string = "[ 1, 2, 3, 4] ";
431 bool is_ok = simdjson::validate_utf8(some_string);
432 return is_ok;
433 }
434
parse_documentation()435 void parse_documentation() {
436 const char *json = R"({"key":"value"})";
437 const size_t json_len = std::strlen(json);
438 simdjson::dom::parser parser;
439 simdjson::dom::element element = parser.parse(json, json_len);
440 // Next line is to avoid unused warning.
441 (void)element;
442 }
443
444
parse_documentation_lowlevel()445 void parse_documentation_lowlevel() {
446 // Such low-level code is not generally recommended. Please
447 // see parse_documentation() instead.
448 // Motivation: https://github.com/simdjson/simdjson/issues/1175
449 const char *json = R"({"key":"value"})";
450 const size_t json_len = std::strlen(json);
451 std::unique_ptr<char[]> padded_json_copy{new char[json_len + SIMDJSON_PADDING]};
452 std::memcpy(padded_json_copy.get(), json, json_len);
453 std::memset(padded_json_copy.get() + json_len, '\0', SIMDJSON_PADDING);
454 simdjson::dom::parser parser;
455 simdjson::dom::element element = parser.parse(padded_json_copy.get(), json_len, false);
456 // Next line is to avoid unused warning.
457 (void)element;
458 }
459
main()460 int main() {
461 basics_dom_1();
462 basics_dom_2();
463 basics_dom_3();
464 basics_dom_4();
465 minify();
466 return 0;
467 }
468