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