Ensure only leaf values can push the iterator

This commit is contained in:
John Keiser 2020-08-31 13:09:19 -07:00
parent fb93109c2d
commit 6a855f528b
2 changed files with 36 additions and 17 deletions

View File

@ -19,11 +19,13 @@ simdjson_really_inline json_iterator &json_iterator::operator=(json_iterator &&o
return *this; return *this;
} }
simdjson_really_inline json_iterator::json_iterator(ondemand::parser *_parser) noexcept simdjson_really_inline json_iterator::json_iterator(ondemand::parser *_parser) noexcept
: token_iterator(_parser->dom_parser.buf, _parser->dom_parser.structural_indexes.get()), parser{_parser} : token_iterator(_parser->dom_parser.buf, _parser->dom_parser.structural_indexes.get()),
parser{_parser},
current_string_buf_loc{parser->string_buf.get()},
active_lease_depth{0}
{ {
// Release the string buf so it can be reused by the next document // Release the string buf so it can be reused by the next document
logger::log_headers(); logger::log_headers();
current_string_buf_loc = parser->string_buf.get();
} }
simdjson_really_inline json_iterator::~json_iterator() noexcept = default; simdjson_really_inline json_iterator::~json_iterator() noexcept = default;
@ -261,7 +263,10 @@ simdjson_really_inline bool json_iterator::is_alive() const noexcept {
} }
simdjson_really_inline json_iterator_ref json_iterator::borrow() noexcept { simdjson_really_inline json_iterator_ref json_iterator::borrow() noexcept {
return json_iterator_ref(this); SIMDJSON_ASSUME(active_lease_depth == 0);
const uint32_t child_depth = 1;
active_lease_depth = child_depth;
return json_iterator_ref(this, child_depth);
} }
// //
@ -269,48 +274,58 @@ simdjson_really_inline json_iterator_ref json_iterator::borrow() noexcept {
// //
simdjson_really_inline json_iterator_ref::json_iterator_ref() noexcept = default; simdjson_really_inline json_iterator_ref::json_iterator_ref() noexcept = default;
simdjson_really_inline json_iterator_ref::json_iterator_ref(json_iterator_ref &&other) noexcept simdjson_really_inline json_iterator_ref::json_iterator_ref(json_iterator_ref &&other) noexcept
: iter{std::forward<json_iterator_ref>(other).iter} : iter{std::exchange(other.iter, nullptr)},
lease_depth{other.lease_depth}
{ {
other.iter = nullptr;
} }
simdjson_really_inline json_iterator_ref &json_iterator_ref::operator=(json_iterator_ref &&other) noexcept { simdjson_really_inline json_iterator_ref &json_iterator_ref::operator=(json_iterator_ref &&other) noexcept {
iter = std::forward<json_iterator_ref>(other).iter; SIMDJSON_ASSUME(!is_active());
other.iter = nullptr; iter = std::exchange(other.iter, nullptr);
lease_depth = other.lease_depth;
return *this; return *this;
} }
simdjson_really_inline json_iterator_ref::json_iterator_ref(json_iterator *_iter) noexcept simdjson_really_inline json_iterator_ref::json_iterator_ref(json_iterator *_iter, uint32_t _lease_depth) noexcept
: iter{_iter} : iter{_iter},
lease_depth{_lease_depth}
{ {
SIMDJSON_ASSUME(is_active());
} }
simdjson_really_inline json_iterator_ref::~json_iterator_ref() noexcept { simdjson_really_inline json_iterator_ref::~json_iterator_ref() noexcept {
// The caller MUST consume their value and release the iterator before they die // The caller MUST consume their value and release the iterator before they die
SIMDJSON_ASSUME(!iter); SIMDJSON_ASSUME(!is_alive());
} }
simdjson_really_inline json_iterator_ref json_iterator_ref::borrow() noexcept { simdjson_really_inline json_iterator_ref json_iterator_ref::borrow() noexcept {
return json_iterator_ref(iter); SIMDJSON_ASSUME(is_active());
const uint32_t child_depth = lease_depth + 1;
iter->active_lease_depth = child_depth;
return json_iterator_ref(iter, child_depth);
} }
simdjson_really_inline void json_iterator_ref::release() noexcept { simdjson_really_inline void json_iterator_ref::release() noexcept {
SIMDJSON_ASSUME(is_alive()); SIMDJSON_ASSUME(is_active());
iter->active_lease_depth = lease_depth - 1;
iter = nullptr; iter = nullptr;
} }
simdjson_really_inline json_iterator *json_iterator_ref::operator->() noexcept { simdjson_really_inline json_iterator *json_iterator_ref::operator->() noexcept {
SIMDJSON_ASSUME(is_alive()); SIMDJSON_ASSUME(is_active());
return iter; return iter;
} }
simdjson_really_inline json_iterator &json_iterator_ref::operator*() noexcept { simdjson_really_inline json_iterator &json_iterator_ref::operator*() noexcept {
SIMDJSON_ASSUME(is_alive()); SIMDJSON_ASSUME(is_active());
return *iter; return *iter;
} }
simdjson_really_inline const json_iterator &json_iterator_ref::operator*() const noexcept { simdjson_really_inline const json_iterator &json_iterator_ref::operator*() const noexcept {
SIMDJSON_ASSUME(is_alive()); SIMDJSON_ASSUME(is_active());
return *iter; return *iter;
} }
simdjson_really_inline bool json_iterator_ref::is_alive() const noexcept { simdjson_really_inline bool json_iterator_ref::is_alive() const noexcept {
return iter != nullptr; return iter != nullptr;
} }
simdjson_really_inline bool json_iterator_ref::is_active() const noexcept {
return is_alive() && lease_depth == iter->active_lease_depth;
}
} // namespace ondemand } // namespace ondemand

View File

@ -137,6 +137,7 @@ public:
protected: protected:
ondemand::parser *parser{}; ondemand::parser *parser{};
uint8_t *current_string_buf_loc{}; uint8_t *current_string_buf_loc{};
uint32_t active_lease_depth{};
simdjson_really_inline json_iterator(ondemand::parser *parser) noexcept; simdjson_really_inline json_iterator(ondemand::parser *parser) noexcept;
template<int N> template<int N>
@ -150,6 +151,7 @@ protected:
friend class value; friend class value;
friend class raw_json_string; friend class raw_json_string;
friend class parser; friend class parser;
friend class json_iterator_ref;
friend simdjson_really_inline void logger::log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta) noexcept; friend simdjson_really_inline void logger::log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta) noexcept;
}; // json_iterator }; // json_iterator
@ -170,10 +172,12 @@ public:
simdjson_really_inline const json_iterator &operator*() const noexcept; simdjson_really_inline const json_iterator &operator*() const noexcept;
simdjson_really_inline bool is_alive() const noexcept; simdjson_really_inline bool is_alive() const noexcept;
simdjson_really_inline bool is_active() const noexcept;
private: private:
simdjson_really_inline json_iterator_ref(json_iterator *iter) noexcept; simdjson_really_inline json_iterator_ref(json_iterator *iter, uint32_t lease_depth) noexcept;
json_iterator *iter; json_iterator *iter{};
uint32_t lease_depth{};
friend class json_iterator; friend class json_iterator;
}; // class json_iterator_ref }; // class json_iterator_ref