Skip to content

Commit 89599a3

Browse files
committed
Remove the need to skip
1 parent 542b633 commit 89599a3

12 files changed

Lines changed: 270 additions & 230 deletions

File tree

include/simdjson/internal/json_iterator.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ namespace internal {
88

99
class json_iterator {
1010
public:
11-
really_inline json_iterator(const uint32_t *_structural_index, const uint8_t *_buf, uint8_t *_string_buf)
12-
: structural_index{_structural_index}, buf{_buf}, string_buf{_string_buf} {}
11+
really_inline json_iterator(const uint32_t *_structural_index, const uint8_t *_buf, uint8_t *_string_buf, int _depth)
12+
: structural_index{_structural_index}, buf{_buf}, string_buf{_string_buf}, depth{_depth} {}
1313
json_iterator() = delete;
1414
really_inline const uint8_t * advance() noexcept { return &buf[*(structural_index++)]; }
1515
really_inline const uint8_t * get() const noexcept { return &buf[*structural_index]; }
16+
really_inline const uint8_t * prev() noexcept { return &buf[*(--structural_index)]; }
17+
really_inline const uint8_t * next() noexcept { return &buf[*(++structural_index)]; }
1618
really_inline const uint8_t * peek_prev() const noexcept { return &buf[*(structural_index-1)]; }
1719
really_inline const uint8_t * peek_next() const noexcept { return &buf[*(structural_index+1)]; }
1820

@@ -30,6 +32,7 @@ class json_iterator {
3032
* potentially copy over each other
3133
*/
3234
uint8_t *string_buf;
35+
int depth;
3336
}; // class structurals
3437

3538
} // namespace internal

include/simdjson/stream/array-inl.h

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,44 +12,51 @@ namespace stream {
1212
// array
1313
//
1414
really_inline array::array(internal::json_iterator &_json) noexcept
15-
: json{_json} {
15+
: json(_json) {
1616
}
17-
really_inline array::iterator array::begin() noexcept {
18-
return iterator(json, true);
17+
really_inline array_iterator array::begin() noexcept {
18+
return array_iterator(json, true);
1919
}
20-
really_inline array::iterator array::end() noexcept {
21-
return iterator(json, false);
20+
really_inline array_iterator array::end() noexcept {
21+
return array_iterator(json, false);
2222
}
2323

2424
//
25-
// array::iterator
25+
// array_iterator
2626
//
27-
really_inline array::iterator::iterator(internal::json_iterator &_json, bool _at_start) noexcept
28-
: json{_json}, at_start{_at_start} {
27+
really_inline array_iterator::array_iterator(internal::json_iterator &json, bool _at_start) noexcept
28+
: value(json), depth{json.depth}, at_start{_at_start} {
2929
}
30-
really_inline simdjson_result<element> array::iterator::operator*() noexcept {
30+
really_inline simdjson_result<element&> array_iterator::operator*() noexcept {
3131
// Check the comma
3232
error_code error;
3333
if (at_start) {
34-
internal::logger::log_event("first array", json, true);
34+
internal::logger::log_event("first array", value.json, true);
3535
at_start = false; // If we're at the start, there's no comma to check.
3636
error = SUCCESS;
3737
} else {
38-
internal::logger::log_event("next array", json);
39-
error = *json.advance() == ',' ? SUCCESS : TAPE_ERROR;
40-
if (error) { internal::logger::log_error("missing ,", json); }
38+
internal::logger::log_event("next array", value.json);
39+
error = *value.json.advance() == ',' ? SUCCESS : TAPE_ERROR;
40+
if (error) { internal::logger::log_error("missing ,", value.json); }
4141
}
4242

43-
return { element(json), error };
43+
return { value, error };
4444
}
45-
really_inline array::iterator &array::iterator::operator++() noexcept {
45+
really_inline array_iterator &array_iterator::operator++() noexcept {
4646
return *this;
4747
}
48-
really_inline bool array::iterator::operator!=(const array::iterator &) noexcept {
48+
really_inline bool array_iterator::operator!=(const array_iterator &) noexcept {
49+
// Finish the previous value if it wasn't finished already
50+
if (!at_start) {
51+
// If finish() fails, it's because it found a stray } or ]
52+
if (!value.finish(depth)) {
53+
return true;
54+
}
55+
}
4956
// Stop if we hit ]
50-
if (*json.get() == ']') {
51-
internal::logger::log_end_event("array", json);
52-
json.advance();
57+
if (*value.json.get() == ']') {
58+
internal::logger::log_end_event("array", value.json);
59+
value.json.advance();
5360
return false;
5461
}
5562
return true;
@@ -67,11 +74,11 @@ really_inline simdjson_result<stream::array>::simdjson_result(stream::array &&va
6774

6875
#if SIMDJSON_EXCEPTIONS
6976

70-
really_inline stream::array::iterator simdjson_result<stream::array>::begin() noexcept(false) {
77+
really_inline stream::array_iterator simdjson_result<stream::array>::begin() noexcept(false) {
7178
if (error()) { throw simdjson_error(error()); }
7279
return first.begin();
7380
}
74-
really_inline stream::array::iterator simdjson_result<stream::array>::end() noexcept(false) {
81+
really_inline stream::array_iterator simdjson_result<stream::array>::end() noexcept(false) {
7582
if (error()) { throw simdjson_error(error()); }
7683
return first.end();
7784
}

include/simdjson/stream/array.h

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,49 +4,52 @@
44
#include "simdjson/common_defs.h"
55
#include "simdjson/error.h"
66
#include "simdjson/internal/json_iterator.h"
7+
#include "simdjson/stream/element.h"
78

89
namespace simdjson {
910
namespace stream {
1011

11-
class element;
12-
1312
class array {
1413
public:
15-
class iterator {
16-
public:
17-
really_inline simdjson_result<element> operator*() noexcept;
18-
really_inline iterator &operator++() noexcept;
19-
really_inline bool operator!=(const iterator &other) noexcept;
20-
private:
21-
really_inline iterator(internal::json_iterator &json, bool at_start) noexcept;
22-
23-
/** The iterator. This will be updated by element, array and object iterators and get methods */
24-
internal::json_iterator &json;
25-
/**
26-
* true if we're at the beginning.
27-
*
28-
* This sorta sucks, but the C++ iterator interface doesn't offer any clever ways to differentiate
29-
* the first iteration of a loop from subsequent iterations. We are left with hoping that the
30-
* compiler will notice at_start gets set to false.
31-
*/
32-
bool at_start{true};
33-
34-
friend class array;
35-
}; // class iterator
36-
37-
really_inline iterator begin() noexcept;
38-
really_inline iterator end() noexcept;
14+
really_inline array_iterator begin() noexcept;
15+
really_inline array_iterator end() noexcept;
3916

4017
private:
4118
really_inline array(internal::json_iterator &json) noexcept;
19+
4220
internal::json_iterator &json;
21+
22+
friend class array_iterator;
4323
friend class element;
4424
friend class document;
4525
friend class simdjson_result<array>;
46-
friend class simdjson_result<element>;
26+
friend class simdjson_result<element&>;
4727
friend class simdjson_result<document>;
4828
}; // class array
4929

30+
class array_iterator {
31+
public:
32+
really_inline simdjson_result<element&> operator*() noexcept;
33+
really_inline array_iterator &operator++() noexcept;
34+
really_inline bool operator!=(const array_iterator &other) noexcept;
35+
private:
36+
really_inline array_iterator(internal::json_iterator &json, bool at_start) noexcept;
37+
38+
element value;
39+
int depth;
40+
41+
/**
42+
* true if we're at the beginning.
43+
*
44+
* This sorta sucks, but the C++ array_iterator interface doesn't offer any clever ways to differentiate
45+
* the first iteration of a loop from subsequent iterations. We are left with hoping that the
46+
* compiler will notice at_start gets set to false.
47+
*/
48+
bool at_start{true};
49+
50+
friend class array;
51+
}; // class array_iterator
52+
5053
} // namespace stream
5154

5255
/** The result of a JSON navigation that may fail. */
@@ -57,8 +60,8 @@ struct simdjson_result<stream::array> : public internal::simdjson_result_base<st
5760
really_inline simdjson_result(stream::array &&value, error_code error) noexcept; ///< @private
5861

5962
#if SIMDJSON_EXCEPTIONS
60-
really_inline stream::array::iterator begin() noexcept(false);
61-
really_inline stream::array::iterator end() noexcept(false);
63+
really_inline stream::array_iterator begin() noexcept(false);
64+
really_inline stream::array_iterator end() noexcept(false);
6265
#endif
6366
};
6467

include/simdjson/stream/document-inl.h

Lines changed: 29 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -11,75 +11,66 @@ namespace stream {
1111
// document
1212
//
1313
really_inline document::document(const dom::parser &parser, const uint8_t *buf) noexcept
14-
: json{&parser.implementation->structural_indexes[0], buf, parser.doc.string_buf.get()} {
15-
}
16-
17-
really_inline element document::root() noexcept {
18-
return element(json);
14+
: json{&parser.implementation->structural_indexes[0], buf, parser.doc.string_buf.get(), 0},
15+
root{json} {
1916
}
2017

2118
really_inline simdjson_result<array> document::get_array() noexcept {
22-
return root().get_array();
19+
return root.get_array();
2320
}
2421
really_inline simdjson_result<object> document::get_object() noexcept {
25-
return root().get_object();
22+
return root.get_object();
2623
}
2724
really_inline simdjson_result<raw_json_string> document::get_raw_json_string() noexcept {
28-
return root().get_raw_json_string();
25+
return root.get_raw_json_string();
2926
}
3027
// really_inline simdjson_result<std::string_view> document::get_string() noexcept {
31-
// return root().get_string();
28+
// return root.get_string();
3229
// }
3330
// really_inline simdjson_result<double> document::get_double() noexcept {
34-
// return root().get_double();
31+
// return root.get_double();
3532
// }
3633
really_inline simdjson_result<uint64_t> document::get_uint64() noexcept {
37-
return root().get_uint64();
34+
return root.get_uint64();
3835
}
3936
really_inline simdjson_result<int64_t> document::get_int64() noexcept {
40-
return root().get_int64();
37+
return root.get_int64();
4138
}
4239
// really_inline simdjson_result<bool> document::get_bool() noexcept {
43-
// return root().get_bool();
40+
// return root.get_bool();
4441
// }
4542

46-
// TODO users should never have to call this for things to work. Figure out how to make it happen
47-
// in destructors or some other automatic mechanism.
48-
inline error_code document::skip() noexcept {
49-
return root().skip();
50-
}
51-
5243
#if SIMDJSON_EXCEPTIONS
5344
really_inline document::operator array() noexcept(false) {
54-
return root();
45+
return root;
5546
}
5647
really_inline document::operator object() noexcept(false) {
57-
return root();
48+
return root;
5849
}
5950
really_inline document::operator raw_json_string() noexcept(false) {
60-
return root();
51+
return root;
6152
}
6253
// really_inline document::operator std::string_view() noexcept(false) {
63-
// return root();
54+
// return root;
6455
// }
6556
// really_inline document::operator double() noexcept(false) {
66-
// return root();
57+
// return root;
6758
// }
6859
really_inline document::operator uint64_t() noexcept(false) {
69-
return root();
60+
return root;
7061
}
7162
really_inline document::operator int64_t() noexcept(false) {
72-
return root();
63+
return root;
7364
}
7465
// really_inline element::operator bool() noexcept(false) {
75-
// return root();
66+
// return root;
7667
// }
7768

78-
really_inline array::iterator document::begin() noexcept(false) {
79-
return get_array().begin();
69+
really_inline array_iterator document::begin() noexcept(false) {
70+
return root.begin();
8071
}
81-
really_inline array::iterator document::end() noexcept(false) {
82-
return get_array().end();
72+
really_inline array_iterator document::end() noexcept(false) {
73+
return root.end();
8374
}
8475
#endif // SIMDJSON_EXCEPTIONS
8576

@@ -93,10 +84,6 @@ really_inline simdjson_result<stream::document>::simdjson_result(stream::documen
9384
really_inline simdjson_result<stream::document>::simdjson_result(stream::document &&value, error_code error) noexcept
9485
: internal::simdjson_result_base<stream::document>(std::forward<stream::document>(value), error) {}
9586

96-
really_inline simdjson_result<stream::element> simdjson_result<stream::document>::root() noexcept {
97-
return { first.json, error() };
98-
}
99-
10087
really_inline simdjson_result<stream::array> simdjson_result<stream::document>::get_array() & noexcept {
10188
return root().get_array();
10289
}
@@ -122,10 +109,6 @@ really_inline simdjson_result<int64_t> simdjson_result<stream::document>::get_in
122109
// return root().get_bool();
123110
// }
124111

125-
really_inline error_code simdjson_result<stream::document>::skip() noexcept {
126-
return root().skip();
127-
}
128-
129112
#if SIMDJSON_EXCEPTIONS
130113
really_inline simdjson_result<stream::document>::operator stream::array() noexcept(false) {
131114
return root();
@@ -152,17 +135,15 @@ really_inline simdjson_result<stream::document>::operator int64_t() noexcept(fal
152135
// return root();
153136
// }
154137

155-
really_inline stream::array::iterator simdjson_result<stream::document>::begin() & noexcept(false) {
156-
printf("begin\n");
138+
really_inline stream::array_iterator simdjson_result<stream::document>::begin() & noexcept(false) {
157139
return root().begin();
158140
}
159-
really_inline stream::array::iterator simdjson_result<stream::document>::end() & noexcept(false) {
160-
// We don't call get_array because it advances the iterator, and we already did that in begin()
161-
// Here we assume the open array was already checked by begin()
162-
printf("end\n");
163-
auto result = root().end();
164-
printf("end2\n");
165-
return result;
141+
really_inline stream::array_iterator simdjson_result<stream::document>::end() & noexcept(false) {
142+
return root().end();
143+
}
144+
145+
really_inline simdjson_result<stream::element&> simdjson_result<stream::document>::root() noexcept {
146+
return { first.root, error() };
166147
}
167148

168149
#endif // SIMDJSON_EXCEPTIONS

include/simdjson/stream/document.h

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ class document {
2626
really_inline simdjson_result<int64_t> get_int64() noexcept;
2727
// really_inline simdjson_result<bool> get_bool() noexcept;
2828

29-
really_inline error_code skip() noexcept;
30-
3129
#if SIMDJSON_EXCEPTIONS
3230
really_inline operator array() noexcept(false);
3331
really_inline operator object() noexcept(false);
@@ -38,16 +36,15 @@ class document {
3836
really_inline operator int64_t() noexcept(false);
3937
// really_inline operator bool() noexcept(false);
4038

41-
really_inline array::iterator begin() noexcept(false);
42-
really_inline array::iterator end() noexcept(false);
39+
really_inline array_iterator begin() noexcept(false);
40+
really_inline array_iterator end() noexcept(false);
4341
#endif // SIMDJSON_EXCEPTIONS
4442

4543
protected:
4644
really_inline document(const dom::parser &parser, const uint8_t *buf) noexcept;
4745

48-
really_inline element root() noexcept;
49-
5046
internal::json_iterator json;
47+
element root;
5148

5249
friend class dom::parser;
5350
friend class simdjson_result<document>;
@@ -71,8 +68,6 @@ struct simdjson_result<stream::document> : public internal::simdjson_result_base
7168
really_inline simdjson_result<int64_t> get_int64() noexcept;
7269
// really_inline simdjson_result<bool> get_bool() noexcept;
7370

74-
really_inline error_code skip() noexcept;
75-
7671
#if SIMDJSON_EXCEPTIONS
7772
really_inline operator stream::array() noexcept(false);
7873
really_inline operator stream::object() noexcept(false);
@@ -83,11 +78,12 @@ struct simdjson_result<stream::document> : public internal::simdjson_result_base
8378
really_inline operator int64_t() noexcept(false);
8479
// really_inline operator bool() noexcept(false);
8580

86-
really_inline stream::array::iterator begin() & noexcept(false);
87-
really_inline stream::array::iterator end() & noexcept(false);
81+
really_inline stream::array_iterator begin() & noexcept(false);
82+
really_inline stream::array_iterator end() & noexcept(false);
8883
#endif // SIMDJSON_EXCEPTIONS
8984

90-
really_inline simdjson_result<stream::element> root() noexcept;
85+
private:
86+
really_inline simdjson_result<stream::element&> root() noexcept;
9187
};
9288

9389
} // namespace simdjson

0 commit comments

Comments
 (0)