1 #include "simdjson.h"
2 #include "test_ondemand.h"
3 
4 using namespace simdjson;
5 
6 namespace array_tests {
7   using namespace std;
8   using simdjson::ondemand::json_type;
issue1588()9   bool issue1588() {
10     TEST_START();
11     const auto json = R"({
12     "nodes" : [
13         {
14             "rotation" : [
15                 0.16907575726509094,
16                 0.7558803558349609,
17                 -0.27217137813568115,
18                 0.570947527885437
19             ],
20             "translation" : [
21                 4.076245307922363,
22                 5.903861999511719,
23                 -1.0054539442062378
24             ]
25         },
26         {
27             "camera" : 0,
28             "rotation" : [
29                 -0.7071067690849304,
30                 0,
31                 0,
32                 0.7071067690849304
33             ]
34         },
35         {
36             "children" : [
37                 1
38             ],
39             "translation" : [
40                 7.358891487121582,
41                 4.958309173583984,
42                 6.925790786743164
43             ]
44         },
45         {
46             "mesh" : 1,
47             "scale" : [
48                 4.7498908042907715,
49                 4.7498908042907715,
50                 4.7498908042907715
51             ]
52         }
53     ]
54 })"_padded;
55     // we query 'rotation', 'scale', 'translation' in sequence
56     const bool expected_value[][3] = { {true, false, true},
57       {true, false, false}, {false, false, true}, {false, true, false} };
58 
59     SUBTEST("ondemand::issue1588::sequence", test_ondemand_doc(json, [&](auto doc_result) {
60       ondemand::array array;
61       ASSERT_SUCCESS( doc_result["nodes"].get(array) );
62 
63       size_t i=0;
64       for (auto value : array) {
65         ondemand::object current_object;
66         ASSERT_SUCCESS( value.get_object().get(current_object) );
67         simdjson::ondemand::array rotation;
68         if(expected_value[i][0]) {
69           ASSERT_SUCCESS( current_object["rotation"].get(rotation) );
70         } else {
71           ASSERT_ERROR( current_object["rotation"].get(rotation), NO_SUCH_FIELD );
72         }
73         simdjson::ondemand::array scale;
74         if(expected_value[i][1]) {
75           ASSERT_SUCCESS( current_object["scale"].get(scale) );
76         } else {
77           ASSERT_ERROR( current_object["scale"].get(scale), NO_SUCH_FIELD );
78         }
79         simdjson::ondemand::array translation;
80         if(expected_value[i][2]) {
81           ASSERT_SUCCESS( current_object["translation"].get(translation) );
82         } else {
83           ASSERT_ERROR( current_object["translation"].get(translation), NO_SUCH_FIELD );
84         }
85         i++;
86       }
87       ASSERT_EQUAL(i, 4);
88       return true;
89     }));
90     SUBTEST("ondemand::issue1588::originalcode", test_ondemand_doc(json, [&](auto doc_result) {
91       int count_nodes = 0;
92       simdjson::ondemand::array doc_nodes;
93       auto error = doc_result["nodes"].get(doc_nodes);
94       ASSERT_SUCCESS( error );
95       for (auto node_iterator : doc_nodes) {
96         ondemand::object node_obj;
97         ASSERT_SUCCESS( node_iterator.get_object().get(node_obj) );
98         simdjson::ondemand::array rotation;
99         std::cout << "checking rotation" << std::endl;
100         if(expected_value[count_nodes][0]) {
101           ASSERT_SUCCESS( node_obj["rotation"].get(rotation) );
102         } else {
103           ASSERT_ERROR( node_obj["rotation"].get(rotation), NO_SUCH_FIELD );
104         }
105 
106         simdjson::ondemand::array scale;
107         std::cout << "checking scale" << std::endl;
108         if(expected_value[count_nodes][1]) {
109           ASSERT_SUCCESS( node_obj["scale"].get(scale) );
110         } else {
111           ASSERT_ERROR( node_obj["scale"].get(scale), NO_SUCH_FIELD );
112         }
113 
114         simdjson::ondemand::array translation;
115         std::cout << "checking translation" << std::endl;
116         if (!error) { std::cout << "translation!\n"; }
117          if(expected_value[count_nodes][2]) {
118           ASSERT_SUCCESS( node_obj["translation"].get(translation) );
119         } else {
120           ASSERT_ERROR( node_obj["translation"].get(translation), NO_SUCH_FIELD );
121         }
122 
123         ++count_nodes;
124       }
125       ASSERT_EQUAL(count_nodes, 4);
126       return true;
127     }));
128     TEST_SUCCEED();
129   }
130 
iterate_complex_array_count()131   bool iterate_complex_array_count() {
132     TEST_START();
133     ondemand::parser parser;
134     auto cars_json = R"( { "zero":[], "test":[ { "val1":1, "val2":2 }, { "val1":1, "val2":2 } ] }   )"_padded;
135     ondemand::document doc;
136     ASSERT_SUCCESS(parser.iterate(cars_json).get(doc));
137     ondemand::array firstmyarray;
138     ondemand::array secondmyarray;
139     ASSERT_SUCCESS(doc.find_field("zero").get_array().get(firstmyarray));
140     size_t count{0};
141     ASSERT_SUCCESS(firstmyarray.count_elements().get(count));
142     ASSERT_EQUAL(count, 0);
143     size_t new_count{0};
144     for(simdjson_unused auto elem: firstmyarray) { new_count++; }
145     ASSERT_EQUAL(new_count, 0);
146     ASSERT_SUCCESS(doc.find_field("test").get_array().get(secondmyarray));
147     ASSERT_SUCCESS(secondmyarray.count_elements().get(count));
148     ASSERT_EQUAL(count, 2);
149     new_count = 0;
150     for(simdjson_unused auto elem: secondmyarray) { new_count++; }
151     ASSERT_EQUAL(count, new_count);
152     TEST_SUCCEED();
153   }
154 
iterate_sub_array_count()155   bool iterate_sub_array_count() {
156     TEST_START();
157     ondemand::parser parser;
158     auto key_value_json = R"( { "test":[ 1,2,3], "joe": [1,2] }   )"_padded;
159     ondemand::document doc;
160     ASSERT_SUCCESS(parser.iterate(key_value_json).get(doc));
161     ondemand::object obj;
162     ASSERT_SUCCESS(doc.get_object().get(obj));
163     ondemand::value v;
164     ASSERT_SUCCESS(doc.find_field("test").get(v));
165     size_t count;
166     ASSERT_SUCCESS(v.count_elements().get(count));
167     ASSERT_EQUAL(count, 3);
168     ASSERT_SUCCESS(doc.find_field("joe").get(v));
169     ASSERT_SUCCESS(v.count_elements().get(count));
170     ASSERT_EQUAL(count, 2);
171     TEST_SUCCEED();
172   }
173 
iterate_array_count()174   bool iterate_array_count() {
175     TEST_START();
176     const auto json = R"([ 1, 10, 100 ])"_padded;
177     const vector<uint64_t> expected_value = { 1, 10, 100 };
178 
179     SUBTEST("ondemand::count_elements", test_ondemand_doc(json, [&](auto doc_result) {
180       ondemand::array array;
181       ASSERT_RESULT( doc_result.type(), json_type::array );
182       ASSERT_SUCCESS( doc_result.get_array().get(array) );
183       size_t count;
184       ASSERT_SUCCESS( array.count_elements().get(count) );
185       ASSERT_EQUAL(count, expected_value.size());
186       return true;
187     }));
188     SUBTEST("ondemand::count_elements_and_decode", test_ondemand_doc(json, [&](auto doc_result) {
189       ondemand::array array;
190       ASSERT_RESULT( doc_result.type(), json_type::array );
191       ASSERT_SUCCESS( doc_result.get(array) );
192       size_t count;
193       ASSERT_SUCCESS( array.count_elements().get(count) );
194       ASSERT_EQUAL(count, expected_value.size());
195       size_t i = 0;
196       std::vector<uint64_t> receiver(count);
197       for (auto value : array) {
198         uint64_t actual;
199         ASSERT_SUCCESS( value.get(actual) );
200         ASSERT_EQUAL(actual, expected_value[i]);
201         receiver[i] = actual;
202         i++;
203       }
204       return true;
205     }));
206     TEST_SUCCEED();
207   }
208 
209 
iterate_empty_array_count()210   bool iterate_empty_array_count() {
211     TEST_START();
212     const auto json = R"([])"_padded;
213 
214     SUBTEST("ondemand::count_elements", test_ondemand_doc(json, [&](auto doc_result) {
215       ondemand::array array;
216       ASSERT_RESULT( doc_result.type(), json_type::array );
217       ASSERT_SUCCESS( doc_result.get_array().get(array) );
218       size_t count;
219       ASSERT_SUCCESS( array.count_elements().get(count) );
220       ASSERT_EQUAL(count, 0);
221       return true;
222     }));
223     SUBTEST("ondemand::count_elements_and_decode", test_ondemand_doc(json, [&](auto doc_result) {
224       ondemand::array array;
225       ASSERT_RESULT( doc_result.type(), json_type::array );
226       ASSERT_SUCCESS( doc_result.get(array) );
227       size_t count;
228       ASSERT_SUCCESS( array.count_elements().get(count) );
229       ASSERT_EQUAL(count, 0);
230       size_t i = 0;
231       std::vector<uint64_t> receiver(count);
232       for (auto value : array) {
233         uint64_t actual;
234         ASSERT_SUCCESS( value.get(actual) );
235         i++;
236       }
237       ASSERT_EQUAL(i, 0);
238       return true;
239     }));
240     TEST_SUCCEED();
241   }
242 
iterate_bad_array_count()243   bool iterate_bad_array_count() {
244     TEST_START();
245     const auto badjson = R"([ 1, 10 100 ])"_padded;
246 
247 
248     SUBTEST("ondemand::count_elements", test_ondemand_doc(badjson, [&](auto doc_result) {
249       ondemand::array array;
250       ASSERT_RESULT( doc_result.type(), json_type::array );
251       ASSERT_SUCCESS( doc_result.get(array) );
252       size_t count;
253       auto e = array.count_elements().get(count);
254       if( e != TAPE_ERROR) {
255         std::cout << e << "\n";
256         std::cout << "expected: " << TAPE_ERROR << "\n";
257         std::cout << "count = " << count << "\n";
258         return false;
259       }
260       return true;
261     }));
262     TEST_SUCCEED();
263   }
iterate_document_array_count()264   bool iterate_document_array_count() {
265     TEST_START();
266     auto empty = R"( [] )"_padded;
267     SUBTEST("ondemand::empty_doc_array", test_ondemand_doc(empty, [&](auto doc_result) {
268         size_t count;
269         ASSERT_RESULT( doc_result.type(), json_type::array );
270         ASSERT_SUCCESS( doc_result.count_elements().get(count) );
271         ASSERT_EQUAL( count, 0 );
272         return true;
273     }));
274     auto basic = R"( [-1.234, 100000000000000, null, [1,2,3], {"t":true, "f":false}] )"_padded;
275     SUBTEST("ondemand::basic_doc_array", test_ondemand_doc(basic, [&](auto doc_result) {
276         size_t count;
277         ASSERT_RESULT( doc_result.type(), json_type::array );
278         ASSERT_SUCCESS( doc_result.count_elements().get(count) );
279         ASSERT_EQUAL( count, 5 );
280         return true;
281     }));
282     TEST_SUCCEED();
283   }
iterate_bad_document_array_count()284   bool iterate_bad_document_array_count() {
285     TEST_START();
286     padded_string bad_jsons[2] = {R"( [1, 10 1000] )"_padded, R"( [1.23, 2.34 )"_padded};
287     std::string names[2] = {"missing_comma", "missing_bracket"};
288     simdjson::error_code errors[2] = {TAPE_ERROR, INCOMPLETE_ARRAY_OR_OBJECT};
289     size_t count{0};
290 
291     for (auto name : names) {
292       SUBTEST("ondemand::" + name, test_ondemand_doc(bad_jsons[count], [&](auto doc_result) {
293         ASSERT_RESULT( doc_result.type(), json_type::array );
294         ASSERT_ERROR(doc_result.count_elements(), errors[count]);
295         return true;
296       }));
297       count++;
298     }
299     ASSERT_EQUAL(count, 2);
300     TEST_SUCCEED();
301   }
iterate_document_array()302   bool iterate_document_array() {
303     TEST_START();
304     const auto json = R"([ 1, 10, 100 ])"_padded;
305     const uint64_t expected_value[] = { 1, 10, 100 };
306 
307     SUBTEST("ondemand::array", test_ondemand_doc(json, [&](auto doc_result) {
308       ondemand::array array;
309       ASSERT_RESULT( doc_result.type(), json_type::array );
310       ASSERT_SUCCESS( doc_result.get(array) );
311 
312       size_t i = 0;
313       for (auto value : array) {
314         int64_t actual;
315         ASSERT_SUCCESS( value.get(actual) );
316         ASSERT_EQUAL(actual, expected_value[i]);
317         i++;
318       }
319       ASSERT_EQUAL(i*sizeof(int64_t), sizeof(expected_value));
320       return true;
321     }));
322 
323     SUBTEST("ondemand::array-document-rewind", test_ondemand_doc(json, [&](auto doc_result) {
324       ondemand::array array;
325       ASSERT_RESULT( doc_result.type(), json_type::array );
326       ASSERT_SUCCESS( doc_result.get(array) );
327 
328       size_t i = 0;
329       for (auto value : array) { (void)value; i++; }
330       ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
331       std::vector<int64_t> container(i); // container of size 'i'.
332 
333       doc_result.rewind();
334       ASSERT_RESULT( doc_result.type(), json_type::array );
335       ASSERT_SUCCESS( doc_result.get(array) );
336       i = 0;
337       for (auto value : array) {
338         int64_t actual;
339         ASSERT_SUCCESS( value.get(actual) );
340         container[i] = actual;
341         i++;
342       }
343       ASSERT_EQUAL(i * sizeof(int64_t), sizeof(expected_value));
344       for(size_t j = 0; j < sizeof(expected_value)/sizeof(int64_t); j++) {
345         ASSERT_EQUAL(container[j], expected_value[j]);
346       }
347       return true;
348     }));
349     SUBTEST("ondemand::array-rewind", test_ondemand_doc(json, [&](auto doc_result) {
350       ondemand::array array;
351       ASSERT_RESULT( doc_result.type(), json_type::array );
352       ASSERT_SUCCESS( doc_result.get(array) );
353 
354       size_t i = 0;
355       for (auto value : array) { (void)value; i++; }
356       ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
357       std::vector<int64_t> container(i); // container of size 'i'.
358 
359       array.reset();
360       i = 0;
361       for (auto value : array) {
362         int64_t actual;
363         ASSERT_SUCCESS( value.get(actual) );
364         container[i] = actual;
365         i++;
366       }
367       ASSERT_EQUAL(i * sizeof(int64_t), sizeof(expected_value));
368       for(size_t j = 0; j < sizeof(expected_value)/sizeof(int64_t); j++) {
369         ASSERT_EQUAL(container[j], expected_value[j]);
370       }
371       return true;
372     }));
373     SUBTEST("simdjson_result<ondemand::array>", test_ondemand_doc(json, [&](auto doc_result) {
374       simdjson_result<ondemand::array> array = doc_result.get_array();
375       ASSERT_RESULT( doc_result.type(), json_type::array );
376       size_t i=0;
377       for (simdjson_unused auto value : array) { int64_t actual; ASSERT_SUCCESS( value.get(actual) ); ASSERT_EQUAL(actual, expected_value[i]); i++; }
378       ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
379       return true;
380     }));
381 
382     SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc_result) {
383       ondemand::document doc;
384       ASSERT_SUCCESS( std::move(doc_result).get(doc) );
385       ASSERT_RESULT( doc.type(), json_type::array );
386       size_t i=0;
387       for (simdjson_unused auto value : doc) { int64_t actual; ASSERT_SUCCESS( value.get(actual) ); ASSERT_EQUAL(actual, expected_value[i]); i++; }
388       ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
389       return true;
390     }));
391     SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
392       size_t i=0;
393       ASSERT_RESULT( doc_result.type(), json_type::array );
394       for (simdjson_unused auto value : doc_result) { int64_t actual; ASSERT_SUCCESS( value.get(actual) ); ASSERT_EQUAL(actual, expected_value[i]); i++; }
395       ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
396       return true;
397     }));
398     TEST_SUCCEED();
399   }
empty_rewind()400   bool empty_rewind() {
401     TEST_START();
402     const auto json = R"( [] )"_padded;
403     ondemand::parser parser;
404     ondemand::document doc;
405     ASSERT_SUCCESS(parser.iterate(json).get(doc));
406     ondemand::array arr;
407     ASSERT_SUCCESS(doc.get_array().get(arr));
408     for(simdjson_unused auto i : arr) {
409       TEST_FAIL("should be empty?");
410     }
411     arr.reset();
412     for(simdjson_unused auto i : arr) {
413       TEST_FAIL("should be empty?");
414     }
415     TEST_SUCCEED();
416   }
count_empty(simdjson::ondemand::array arr)417   bool count_empty(simdjson::ondemand::array arr) {
418     size_t count;
419     ASSERT_SUCCESS(arr.count_elements().get(count));
420     ASSERT_EQUAL(count, 0);
421     bool is_empty;
422     ASSERT_SUCCESS(arr.is_empty().get(is_empty));
423     ASSERT_TRUE(is_empty);
424     return true;
425   }
value_to_array(simdjson::ondemand::value val)426   bool value_to_array(simdjson::ondemand::value val) {
427     ondemand::json_type t;
428     ASSERT_SUCCESS(val.type().get(t));
429     ASSERT_EQUAL(t, ondemand::json_type::array);
430     simdjson::ondemand::array arr;
431     ASSERT_SUCCESS(val.get_array().get(arr));
432     if(count_empty(arr) != true) { return false; }
433     return true;
434   }
empty_rewind_convoluted()435   bool empty_rewind_convoluted() {
436     TEST_START();
437     const auto json = R"( [] )"_padded;
438     ondemand::parser parser;
439     ondemand::document doc;
440     ASSERT_SUCCESS(parser.iterate(json).get(doc));
441     ondemand::value val;
442     ASSERT_SUCCESS(doc.get_value().get(val));
443     if(!value_to_array(val)) { return false; }
444     TEST_SUCCEED();
445   }
446 #if SIMDJSON_EXCEPTIONS
value_to_array_except(simdjson::ondemand::value val)447   bool value_to_array_except(simdjson::ondemand::value val) {
448     ondemand::json_type t = val.type();
449     ASSERT_EQUAL(t, ondemand::json_type::array);
450     if(count_empty(simdjson::ondemand::array(val)) != true) { return false; }
451     return true;
452   }
empty_rewind_convoluted_with_exceptions()453   bool empty_rewind_convoluted_with_exceptions() {
454     TEST_START();
455     const auto json = R"( [] )"_padded;
456     ondemand::parser parser;
457     ondemand::document doc;
458     ASSERT_SUCCESS(parser.iterate(json).get(doc));
459     ondemand::value val;
460     ASSERT_SUCCESS(doc.get_value().get(val));
461     if(value_to_array_except(val) != true) { return false; }
462     TEST_SUCCEED();
463   }
464 #endif
iterate_array()465   bool iterate_array() {
466     TEST_START();
467     const auto json = R"( [ [ 1, 10, 100 ] ] )"_padded;
468     const uint64_t expected_value[] = { 1, 10, 100 };
469 
470     SUBTEST("ondemand::array", test_ondemand_doc(json, [&](auto doc_result) {
471       bool found = false;
472       for (simdjson_result<ondemand::value> array_result : doc_result) {
473         ASSERT_TRUE(!found); found = true;
474 
475         ondemand::array array;
476         ASSERT_RESULT( array_result.type(), json_type::array );
477         ASSERT_SUCCESS( array_result.get(array) );
478 
479         size_t i=0;
480         for (auto value : array) {
481           int64_t actual;
482           ASSERT_SUCCESS( value.get(actual) );
483           ASSERT_EQUAL(actual, expected_value[i]);
484           i++;
485         }
486         ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
487       }
488         ASSERT_TRUE(found);
489       return true;
490     }));
491 
492     SUBTEST("simdjson_result<ondemand::array>", test_ondemand_doc(json, [&](auto doc_result) {
493       bool found = false;
494       for (simdjson_result<ondemand::value> array_result : doc_result) {
495         ASSERT_TRUE(!found); found = true;
496 
497         ondemand::array array;
498         ASSERT_RESULT( array_result.type(), json_type::array );
499         ASSERT_SUCCESS( array_result.get(array) );
500 
501         size_t i=0;
502         for (simdjson_unused auto value : array) { int64_t actual; ASSERT_SUCCESS( value.get(actual) ); ASSERT_EQUAL(actual, expected_value[i]); i++; }
503         ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
504       }
505       ASSERT_TRUE(found);
506       return true;
507     }));
508 
509     SUBTEST("ondemand::value", test_ondemand_doc(json, [&](auto doc_result) {
510       bool found = false;
511       for (simdjson_result<ondemand::value> array_result : doc_result) {
512         ASSERT_TRUE(!found); found = true;
513 
514         ondemand::value array;
515         ASSERT_SUCCESS( std::move(array_result).get(array) );
516         ASSERT_RESULT( array.type(), json_type::array );
517         size_t i=0;
518         for (simdjson_unused auto value : array) { int64_t actual; ASSERT_SUCCESS( value.get(actual) ); ASSERT_EQUAL(actual, expected_value[i]); i++; }
519         ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
520       }
521       ASSERT_TRUE(found);
522       return true;
523     }));
524     SUBTEST("simdjson_result<ondemand::value>", test_ondemand_doc(json, [&](auto doc_result) {
525       bool found = false;
526       for (simdjson_result<ondemand::value> array_result : doc_result) {
527         ASSERT_TRUE(!found); found = true;
528 
529         size_t i=0;
530         ASSERT_RESULT( array_result.type(), json_type::array );
531         for (simdjson_unused auto value : array_result) { int64_t actual; ASSERT_SUCCESS( value.get(actual) ); ASSERT_EQUAL(actual, expected_value[i]); i++; }
532         ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
533       }
534       ASSERT_TRUE(found);
535       return true;
536     }));
537     TEST_SUCCEED();
538   }
539 
iterate_array_partial_children()540   bool iterate_array_partial_children() {
541     TEST_START();
542     auto json = R"(
543       [
544         0,
545         [],
546         {},
547         { "x": 3, "y": 33 },
548         { "x": 4, "y": 44 },
549         { "x": 5, "y": 55 },
550         { "x": 6, "y": 66 },
551         [ 7, 77, 777 ],
552         [ 8, 88, 888 ],
553         { "a": [ { "b": [ 9, 99 ], "c": 999 }, 9999 ], "d": 99999 },
554         10
555       ]
556     )"_padded;
557     SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
558       size_t i = 0;
559       for (auto value : doc_result) {
560         ASSERT_SUCCESS(value);
561 
562         switch (i) {
563           case 0: {
564             std::cout << "  - After ignoring empty scalar ..." << std::endl;
565             break;
566           }
567           case 1: {
568             std::cout << "  - After ignoring empty array ..." << std::endl;
569             break;
570           }
571           case 2: {
572             std::cout << "  - After ignoring empty object ..." << std::endl;
573             break;
574           }
575           // Break after using first value in child object
576           case 3: {
577             for (auto child_field : value.get_object()) {
578               ondemand::raw_json_string k;
579               ASSERT_SUCCESS( child_field.key().get(k) );
580               ASSERT_EQUAL(k, "x");
581               uint64_t x;
582               ASSERT_SUCCESS( child_field.value().get(x) );
583               ASSERT_EQUAL(x, 3);
584               break; // Break after the first value
585             }
586             std::cout << "  - After using first value in child object ..." << std::endl;
587             break;
588           }
589 
590           // Break without using first value in child object
591           case 4: {
592             for (auto child_field : value.get_object()) {
593               ondemand::raw_json_string k;
594               ASSERT_SUCCESS( child_field.key().get(k) );
595               ASSERT_EQUAL(k, "x");
596               break;
597             }
598             std::cout << "  - After reaching (but not using) first value in child object ..." << std::endl;
599             break;
600           }
601 
602           // Only look up one field in child object
603           case 5: {
604             uint64_t x;
605             ASSERT_SUCCESS( value["x"].get(x) );
606             ASSERT_EQUAL( x, 5 );
607             std::cout << "  - After looking up one field in child object ..." << std::endl;
608             break;
609           }
610 
611           // Only look up one field in child object, but don't use it
612           case 6: {
613             ASSERT_SUCCESS( value["x"] );
614             std::cout << "  - After looking up (but not using) one field in child object ..." << std::endl;
615             break;
616           }
617 
618           // Break after first value in child array
619           case 7: {
620             for (auto child_value : value) {
621               uint64_t x;
622               ASSERT_SUCCESS( child_value.get(x) );
623               ASSERT_EQUAL( x, 7 );
624               break;
625             }
626             std::cout << "  - After using first value in child array ..." << std::endl;
627             break;
628           }
629 
630           // Break without using first value in child array
631           case 8: {
632             for (auto child_value : value) {
633               ASSERT_SUCCESS(child_value);
634               break;
635             }
636             std::cout << "  - After reaching (but not using) first value in child array ..." << std::endl;
637             break;
638           }
639 
640           // Break out of multiple child loops
641           case 9: {
642             for (auto child1 : value.get_object()) {
643               for (auto child2 : child1.value().get_array()) {
644                 for (auto child3 : child2.get_object()) {
645                   for (auto child4 : child3.value().get_array()) {
646                     uint64_t x;
647                     ASSERT_SUCCESS( child4.get(x) );
648                     ASSERT_EQUAL( x, 9 );
649                     break;
650                   }
651                   break;
652                 }
653                 break;
654               }
655               break;
656             }
657             std::cout << "  - After breaking out of quadruply-nested arrays and objects ..." << std::endl;
658             break;
659           }
660 
661           // Test the actual value
662           case 10: {
663             uint64_t actual_value;
664             ASSERT_SUCCESS( value.get(actual_value) );
665             ASSERT_EQUAL( actual_value, 10 );
666             break;
667           }
668         }
669 
670         i++;
671       }
672       ASSERT_EQUAL( i, 11 ); // Make sure we found all the keys we expected
673       return true;
674     }));
675     return true;
676   }
677 
iterate_empty_array()678   bool iterate_empty_array() {
679     TEST_START();
680     auto json = "[]"_padded;
681     SUBTEST("ondemand::array", test_ondemand_doc(json, [&](auto doc_result) {
682       ondemand::array array;
683       ASSERT_SUCCESS( doc_result.get(array) );
684       for (simdjson_unused auto value : array) { TEST_FAIL("Unexpected value"); }
685       return true;
686     }));
687     SUBTEST("simdjson_result<ondemand::array>", test_ondemand_doc(json, [&](auto doc_result) {
688       simdjson_result<ondemand::array> array_result = doc_result.get_array();
689       for (simdjson_unused auto value : array_result) { TEST_FAIL("Unexpected value"); }
690       return true;
691     }));
692     SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc_result) {
693       ondemand::document doc;
694       ASSERT_SUCCESS( std::move(doc_result).get(doc) );
695       for (simdjson_unused auto value : doc) { TEST_FAIL("Unexpected value"); }
696       return true;
697     }));
698     SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
699       for (simdjson_unused auto value : doc_result) { TEST_FAIL("Unexpected value"); }
700       return true;
701     }));
702     SUBTEST("ondemand::array-document-rewind", test_ondemand_doc(json, [&](auto doc_result) {
703       ondemand::array array;
704       ASSERT_RESULT( doc_result.type(), json_type::array );
705       ASSERT_SUCCESS( doc_result.get(array) );
706 
707       size_t i = 0;
708       for (auto value : array) { (void) value; i++; }
709       ASSERT_EQUAL(i, 0);
710 
711       doc_result.rewind();
712       ASSERT_RESULT( doc_result.type(), json_type::array );
713       ASSERT_SUCCESS( doc_result.get(array) );
714       i = 0;
715       for (auto value : array) { (void) value; i++; }
716       ASSERT_EQUAL(i, 0);
717       return true;
718     }));
719     SUBTEST("ondemand::array-rewind", test_ondemand_doc(json, [&](auto doc_result) {
720       ondemand::array array;
721       ASSERT_RESULT( doc_result.type(), json_type::array );
722       ASSERT_SUCCESS( doc_result.get(array) );
723 
724       size_t i = 0;
725       for (auto value : array) { (void) value; i++; }
726       ASSERT_EQUAL(i, 0);
727 
728       array.reset();
729       i = 0;
730       for (auto value : array) { (void) value; i++; }
731       ASSERT_EQUAL(i, 0);
732       return true;
733     }));
734     TEST_SUCCEED();
735   }
736 
737 #if SIMDJSON_EXCEPTIONS
738 
iterate_array_exception()739   bool iterate_array_exception() {
740     TEST_START();
741     auto json = R"([ 1, 10, 100 ])"_padded;
742     const uint64_t expected_value[] = { 1, 10, 100 };
743 
744     ASSERT_TRUE(test_ondemand_doc(json, [&](auto doc_result) {
745       size_t i=0;
746       for (int64_t actual : doc_result) { ASSERT_EQUAL(actual, expected_value[i]); i++; }
747       ASSERT_EQUAL(i*sizeof(uint64_t), sizeof(expected_value));
748       return true;
749     }));
750     TEST_SUCCEED();
751   }
752 
iterate_empty_object_exception()753   bool iterate_empty_object_exception() {
754     TEST_START();
755     auto json = R"({})"_padded;
756 
757     ASSERT_TRUE(test_ondemand_doc(json, [&](auto doc_result) {
758       for (simdjson_unused ondemand::field field : doc_result.get_object()) {
759         TEST_FAIL("Unexpected field");
760       }
761       return true;
762     }));
763 
764     TEST_SUCCEED();
765   }
766 
iterate_empty_array_exception()767   bool iterate_empty_array_exception() {
768     TEST_START();
769     auto json = "[]"_padded;
770 
771     ASSERT_TRUE(test_ondemand_doc(json, [&](auto doc_result) {
772       for (simdjson_unused ondemand::value value : doc_result) { TEST_FAIL("Unexpected value"); }
773       return true;
774     }));
775 
776     TEST_SUCCEED();
777   }
778 
779 #endif // SIMDJSON_EXCEPTIONS
780 
run()781   bool run() {
782     return
783            empty_rewind_convoluted() &&
784            empty_rewind() &&
785            iterate_empty_array_count() &&
786            iterate_sub_array_count() &&
787            iterate_complex_array_count() &&
788            iterate_bad_array_count() &&
789            iterate_array_count() &&
790            issue1588() &&
791            iterate_array() &&
792            iterate_document_array_count() &&
793            iterate_bad_document_array_count() &&
794            iterate_document_array() &&
795            iterate_empty_array() &&
796            iterate_array_partial_children() &&
797 #if SIMDJSON_EXCEPTIONS
798            empty_rewind_convoluted_with_exceptions() &&
799            iterate_array_exception() &&
800 #endif // SIMDJSON_EXCEPTIONS
801            true;
802   }
803 
804 } // namespace dom_api_tests
805 
main(int argc,char * argv[])806 int main(int argc, char *argv[]) {
807   return test_main(argc, argv, array_tests::run);
808 }
809