json_iterator * -> json_iterator_ref

This commit is contained in:
John Keiser 2020-08-30 07:07:12 -07:00
parent 283ac3191f
commit 0ddff4ec7d
11 changed files with 117 additions and 48 deletions

View File

@ -41,18 +41,18 @@ namespace ondemand {
//
simdjson_really_inline array::array() noexcept = default;
simdjson_really_inline array::array(json_iterator *_iter, bool has_value) noexcept
: iter{_iter}, has_next{has_value}, error{SUCCESS}
simdjson_really_inline array::array(json_iterator_ref &&_iter, bool has_value) noexcept
: iter{std::forward<json_iterator_ref>(_iter)}, has_next{has_value}, error{SUCCESS}
{
}
simdjson_really_inline array::array(array &&other) noexcept
: iter{other.iter}, has_next{other.has_next}, error{other.error}
: iter{std::forward<array>(other).iter}, has_next{other.has_next}, error{other.error}
{
// Terminate the other iterator
other.has_next = false;
}
simdjson_really_inline array &array::operator=(array &&other) noexcept {
iter = other.iter;
iter = std::forward<array>(other).iter;
has_next = other.has_next;
error = other.error;
// Terminate the other iterator
@ -67,13 +67,13 @@ simdjson_really_inline array::~array() noexcept {
}
}
simdjson_really_inline simdjson_result<array> array::start(json_iterator *iter) noexcept {
simdjson_really_inline simdjson_result<array> array::start(json_iterator_ref &&iter) noexcept {
bool has_value;
SIMDJSON_TRY( iter->start_array().get(has_value) );
return array(iter, has_value);
return array(std::forward<json_iterator_ref>(iter), has_value);
}
simdjson_really_inline array array::started(json_iterator *iter) noexcept {
return array(iter, iter->started_array());
simdjson_really_inline array array::started(json_iterator_ref &&iter) noexcept {
return array(std::forward<json_iterator_ref>(iter), iter->started_array());
}
simdjson_really_inline array::iterator array::begin() noexcept {
return *this;
@ -96,7 +96,7 @@ simdjson_really_inline array::iterator &array::iterator::operator=(const array::
simdjson_really_inline simdjson_result<value> array::iterator::operator*() noexcept {
if (a->error) { return a->report_error(); }
return value::start(a->iter);
return value::start(a->iter.borrow());
}
simdjson_really_inline bool array::iterator::operator==(const array::iterator &) noexcept {
return !a->has_next;

View File

@ -53,13 +53,13 @@ protected:
* @param doc The document containing the array.
* @error INCORRECT_TYPE if the iterator is not at [.
*/
static simdjson_really_inline simdjson_result<array> start(json_iterator *iter) noexcept;
static simdjson_really_inline simdjson_result<array> start(json_iterator_ref &&iter) noexcept;
/**
* Begin array iteration.
*
* @param doc The document containing the array. The iterator must be just after the opening `[`.
*/
static simdjson_really_inline array started(json_iterator *iter) noexcept;
static simdjson_really_inline array started(json_iterator_ref &&iter) noexcept;
/**
* Report the current error and set finished so it won't be reported again.
@ -73,7 +73,7 @@ protected:
* reflect the array's depth. The iterator must be just after the opening `[`.
* @param has_value Whether the array has a value (false means empty array).
*/
simdjson_really_inline array(json_iterator *iter, bool has_value) noexcept;
simdjson_really_inline array(json_iterator_ref &&iter, bool has_value) noexcept;
/**
* Document containing this array.
@ -81,7 +81,7 @@ protected:
* PERF NOTE: expected to be elided in favor of the parent document: this is set when the array
* is first used, and never changes afterwards.
*/
json_iterator *iter{};
json_iterator_ref iter{};
/**
* Whether we have anything to yield.
*

View File

@ -4,7 +4,7 @@ namespace ondemand {
simdjson_really_inline document::document(document &&other) noexcept = default;
simdjson_really_inline document &document::operator=(document &&other) noexcept = default;
simdjson_really_inline document::document(ondemand::json_iterator && _iter) noexcept
simdjson_really_inline document::document(ondemand::json_iterator &&_iter) noexcept
: iter(std::forward<json_iterator>(_iter))
{
logger::log_start_value(iter, "document");
@ -20,7 +20,7 @@ simdjson_really_inline value document::as_value() noexcept {
logger::log_error(iter, "Document value can only be used once! ondemand::document is a forward-only input iterator.");
abort(); // TODO is there anything softer we can do? I'd rather not make this a simdjson_result just for user error.
}
return value::start(&iter);
return value::start(iter.borrow());
}
simdjson_really_inline simdjson_result<array> document::get_array() & noexcept { return as_value().get_array(); }

View File

@ -12,15 +12,15 @@ simdjson_really_inline field::field(raw_json_string key, ondemand::value &&value
{
}
simdjson_really_inline simdjson_result<field> field::start(json_iterator *iter) noexcept {
simdjson_really_inline simdjson_result<field> field::start(json_iterator_ref &&iter) noexcept {
raw_json_string key;
SIMDJSON_TRY( iter->field_key().get(key) );
SIMDJSON_TRY( iter->field_value() );
return field::start(iter, key);
return field::start(std::forward<json_iterator_ref>(iter), key);
}
simdjson_really_inline simdjson_result<field> field::start(json_iterator *iter, raw_json_string key) noexcept {
return field(key, value::start(iter));
simdjson_really_inline simdjson_result<field> field::start(json_iterator_ref &&iter, raw_json_string key) noexcept {
return field(key, value::start(std::forward<json_iterator_ref>(iter)));
}
simdjson_really_inline raw_json_string field::key() const noexcept {

View File

@ -19,8 +19,8 @@ public:
simdjson_really_inline ondemand::value &value() noexcept;
protected:
simdjson_really_inline field(raw_json_string key, ondemand::value &&value) noexcept;
static simdjson_really_inline simdjson_result<field> start(json_iterator *iter) noexcept;
static simdjson_really_inline simdjson_result<field> start(json_iterator *iter, raw_json_string key) noexcept;
static simdjson_really_inline simdjson_result<field> start(json_iterator_ref &&iter) noexcept;
static simdjson_really_inline simdjson_result<field> start(json_iterator_ref &&iter, raw_json_string key) noexcept;
friend struct simdjson_result<field>;
friend class object;
};

View File

@ -260,6 +260,41 @@ simdjson_really_inline bool json_iterator::is_alive() const noexcept {
return parser;
}
simdjson_really_inline json_iterator_ref json_iterator::borrow() noexcept {
return json_iterator_ref(this);
}
//
// json_iterator_ref
//
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 = default;
simdjson_really_inline json_iterator_ref &json_iterator_ref::operator=(json_iterator_ref &&other) noexcept = default;
simdjson_really_inline json_iterator_ref::json_iterator_ref(json_iterator *_iter) noexcept
: iter{_iter}
{
}
simdjson_really_inline json_iterator_ref::~json_iterator_ref() noexcept = default;
simdjson_really_inline json_iterator_ref json_iterator_ref::borrow() noexcept {
return json_iterator_ref(iter);
}
simdjson_really_inline json_iterator *json_iterator_ref::operator->() noexcept {
return iter;
}
simdjson_really_inline json_iterator &json_iterator_ref::operator*() noexcept {
return *iter;
}
simdjson_really_inline const json_iterator &json_iterator_ref::operator*() const noexcept {
return *iter;
}
simdjson_really_inline bool json_iterator_ref::is_alive() const noexcept {
return iter != nullptr;
}
} // namespace ondemand
} // namespace SIMDJSON_IMPLEMENTATION
} // namespace {

View File

@ -2,6 +2,8 @@ namespace {
namespace SIMDJSON_IMPLEMENTATION {
namespace ondemand {
class json_iterator_ref;
/**
* Iterates through JSON, with structure-sensitive algorithms.
*
@ -140,6 +142,8 @@ protected:
template<int N>
SIMDJSON_WARN_UNUSED simdjson_really_inline bool advance_to_buffer(uint8_t (&buf)[N]) noexcept;
simdjson_really_inline json_iterator_ref borrow() noexcept;
friend class document;
friend class object;
friend class array;
@ -147,7 +151,31 @@ protected:
friend class raw_json_string;
friend class parser;
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
class json_iterator_ref {
public:
simdjson_really_inline json_iterator_ref() noexcept;
simdjson_really_inline json_iterator_ref(json_iterator_ref &&other) noexcept;
simdjson_really_inline json_iterator_ref &operator=(json_iterator_ref &&other) noexcept;
simdjson_really_inline json_iterator_ref(const json_iterator_ref &other) noexcept = delete;
simdjson_really_inline json_iterator_ref &operator=(const json_iterator_ref &other) noexcept = delete;
simdjson_really_inline ~json_iterator_ref() noexcept;
simdjson_really_inline json_iterator_ref borrow() noexcept;
simdjson_really_inline json_iterator *operator->() noexcept;
simdjson_really_inline json_iterator &operator*() noexcept;
simdjson_really_inline const json_iterator &operator*() const noexcept;
simdjson_really_inline bool is_alive() const noexcept;
private:
simdjson_really_inline json_iterator_ref(json_iterator *iter) noexcept;
json_iterator *iter;
friend class json_iterator;
}; // class json_iterator_ref
} // namespace ondemand
} // namespace SIMDJSON_IMPLEMENTATION

View File

@ -44,18 +44,18 @@ namespace ondemand {
//
simdjson_really_inline object::object() noexcept = default;
simdjson_really_inline object::object(json_iterator *_iter, bool _has_value) noexcept
: iter{_iter}, has_next{_has_value}, at_start{true}, error{SUCCESS}
simdjson_really_inline object::object(json_iterator_ref &&_iter, bool _has_value) noexcept
: iter{std::forward<json_iterator_ref>(_iter)}, has_next{_has_value}, at_start{true}, error{SUCCESS}
{
}
simdjson_really_inline object::object(object &&other) noexcept
: iter{other.iter}, has_next{other.has_next}, at_start{other.at_start}, error{other.error}
: iter{std::forward<object>(other).iter}, has_next{other.has_next}, at_start{other.at_start}, error{other.error}
{
// Terminate the other iterator
other.has_next = false;
}
simdjson_really_inline object &object::operator=(object &&other) noexcept {
iter = other.iter;
iter = std::forward<object>(other).iter;
has_next = other.has_next;
at_start = other.at_start;
error = other.error;
@ -91,7 +91,7 @@ simdjson_really_inline simdjson_result<value> object::operator[](const std::stri
// Check if it matches
if (actual_key == key) {
logger::log_event(*iter, "match", key, -2);
return value::start(iter);
return value::start(iter.borrow());
}
logger::log_event(*iter, "no match", key, -2);
iter->skip(); // Skip the value entirely
@ -102,13 +102,13 @@ simdjson_really_inline simdjson_result<value> object::operator[](const std::stri
return NO_SUCH_FIELD;
}
simdjson_really_inline simdjson_result<object> object::start(json_iterator *iter) noexcept {
simdjson_really_inline simdjson_result<object> object::start(json_iterator_ref &&iter) noexcept {
bool has_value;
SIMDJSON_TRY( iter->start_object().get(has_value) );
return object(iter, has_value);
return object(std::forward<json_iterator_ref>(iter), has_value);
}
simdjson_really_inline object object::started(json_iterator *iter) noexcept {
return object(iter, iter->started_object());
simdjson_really_inline object object::started(json_iterator_ref &&iter) noexcept {
return object(std::forward<json_iterator_ref>(iter), iter->started_object());
}
simdjson_really_inline object::iterator object::begin() noexcept {
return *this;
@ -135,7 +135,7 @@ simdjson_really_inline object::iterator &object::iterator::operator=(const objec
simdjson_really_inline simdjson_result<field> object::iterator::operator*() noexcept {
if (o->error) { return o->report_error(); }
if (o->at_start) { o->at_start = false; }
return field::start(o->iter);
return field::start(o->iter.borrow());
}
simdjson_really_inline bool object::iterator::operator==(const object::iterator &) noexcept {
return !o->has_next;

View File

@ -51,8 +51,8 @@ protected:
* @param doc The document containing the object. The iterator must be just after the opening `{`.
* @param error If this is not SUCCESS, creates an error chained object.
*/
static simdjson_really_inline simdjson_result<object> start(json_iterator *iter) noexcept;
static simdjson_really_inline object started(json_iterator *iter) noexcept;
static simdjson_really_inline simdjson_result<object> start(json_iterator_ref &&iter) noexcept;
static simdjson_really_inline object started(json_iterator_ref &&iter) noexcept;
/**
* Internal object creation. Call object::begin(doc) instead of this.
@ -62,7 +62,7 @@ protected:
* @param is_empty Whether this container is empty or not.
* @param error The error to report. If the error is not SUCCESS, this is an error chained object.
*/
simdjson_really_inline object(json_iterator *_iter, bool is_empty) noexcept;
simdjson_really_inline object(json_iterator_ref &&_iter, bool is_empty) noexcept;
simdjson_really_inline error_code report_error() noexcept;
@ -72,7 +72,7 @@ protected:
* PERF NOTE: expected to be elided in favor of the parent document: this is set when the object
* is first used, and never changes afterwards.
*/
json_iterator *iter{};
json_iterator_ref iter{};
/**
* Whether we have anything to yield.
*

View File

@ -3,17 +3,23 @@ namespace SIMDJSON_IMPLEMENTATION {
namespace ondemand {
simdjson_really_inline value::value() noexcept = default;
simdjson_really_inline value::value(value &&other) noexcept {
*this = std::forward<value>(other);
simdjson_really_inline value::value(value &&other) noexcept
: iter{std::forward<value>(other).iter},
json{other.json}
{
other.json = nullptr;
};
simdjson_really_inline value &value::operator=(value &&other) noexcept {
iter = other.iter;
iter = std::forward<value>(other).iter;
json = other.json;
other.json = nullptr;
return *this;
}
simdjson_really_inline value::value(json_iterator *_iter, const uint8_t *_json) noexcept : iter{_iter}, json{_json} {
SIMDJSON_ASSUME(iter != nullptr);
simdjson_really_inline value::value(json_iterator_ref && _iter, const uint8_t *_json) noexcept
: iter{std::forward<json_iterator_ref>(_iter)},
json{_json}
{
SIMDJSON_ASSUME(iter.is_alive());
SIMDJSON_ASSUME(json != nullptr);
}
@ -32,8 +38,8 @@ simdjson_really_inline value::~value() noexcept {
}
}
simdjson_really_inline value value::start(json_iterator *iter) noexcept {
return { iter, iter->advance() };
simdjson_really_inline value value::start(json_iterator_ref &&iter) noexcept {
return { std::forward<json_iterator_ref>(iter), iter->advance() };
}
simdjson_really_inline simdjson_result<array> value::get_array() noexcept {
@ -42,7 +48,7 @@ simdjson_really_inline simdjson_result<array> value::get_array() noexcept {
return INCORRECT_TYPE;
}
json = nullptr; // Communicate that we have handled the value PERF TODO elided, right?
return array::started(iter);
return array::started(std::move(iter));
}
simdjson_really_inline simdjson_result<object> value::get_object() noexcept {
if (*json != '{') {
@ -50,7 +56,7 @@ simdjson_really_inline simdjson_result<object> value::get_object() noexcept {
return INCORRECT_TYPE;
}
json = nullptr; // Communicate that we have handled the value PERF TODO elided, right?
return object::started(iter);
return object::started(std::move(iter));
}
simdjson_really_inline simdjson_result<raw_json_string> value::get_raw_json_string() noexcept {
log_value("string");

View File

@ -59,7 +59,7 @@ protected:
*
* Use value::read() instead of this.
*/
simdjson_really_inline value(json_iterator *iter, const uint8_t *json) noexcept;
simdjson_really_inline value(json_iterator_ref &&iter, const uint8_t *json) noexcept;
/**
* Read a value.
@ -68,12 +68,12 @@ protected:
*
* @param doc The document containing the value. Iterator must be at the value start position.
*/
static simdjson_really_inline value start(json_iterator *iter) noexcept;
static simdjson_really_inline value start(json_iterator_ref &&iter) noexcept;
simdjson_really_inline void log_value(const char *type) const noexcept;
simdjson_really_inline void log_error(const char *message) const noexcept;
json_iterator *iter{}; // For the string buffer (if we need it)
json_iterator_ref iter{}; // For the string buffer (if we need it)
const uint8_t *json{}; // The JSON text of the value
friend class document;