From 9d22372cc93333fc36dc809367e7a1f1e16ef2a3 Mon Sep 17 00:00:00 2001 From: rychale Date: Mon, 1 Mar 2021 22:40:51 +0300 Subject: [PATCH] Make dom::document_stream::iterator copyable and default-constructible by holding pointer to document_stream instead of ref (#1463) Co-authored-by: Alexey Rychkov --- include/simdjson/dom/document_stream-inl.h | 34 ++++++++++++---------- include/simdjson/dom/document_stream.h | 19 +++++++++--- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/include/simdjson/dom/document_stream-inl.h b/include/simdjson/dom/document_stream-inl.h index 107dac79..feff9e17 100644 --- a/include/simdjson/dom/document_stream-inl.h +++ b/include/simdjson/dom/document_stream-inl.h @@ -121,28 +121,32 @@ simdjson_really_inline document_stream::~document_stream() noexcept { #endif } +simdjson_really_inline document_stream::iterator::iterator() noexcept + : stream{nullptr}, finished{true} { +} + simdjson_really_inline document_stream::iterator document_stream::begin() noexcept { start(); // If there are no documents, we're finished. - return iterator(*this, error == EMPTY); + return iterator(this, error == EMPTY); } simdjson_really_inline document_stream::iterator document_stream::end() noexcept { - return iterator(*this, true); + return iterator(this, true); } -simdjson_really_inline document_stream::iterator::iterator(document_stream& _stream, bool is_end) noexcept +simdjson_really_inline document_stream::iterator::iterator(document_stream* _stream, bool is_end) noexcept : stream{_stream}, finished{is_end} { } -simdjson_really_inline simdjson_result document_stream::iterator::operator*() noexcept { +simdjson_really_inline document_stream::iterator::reference document_stream::iterator::operator*() noexcept { // Note that in case of error, we do not yet mark // the iterator as "finished": this detection is done // in the operator++ function since it is possible // to call operator++ repeatedly while omitting // calls to operator*. - if (stream.error) { return stream.error; } - return stream.parser->doc.root(); + if (stream->error) { return stream->error; } + return stream->parser->doc.root(); } simdjson_really_inline document_stream::iterator& document_stream::iterator::operator++() noexcept { @@ -156,16 +160,16 @@ simdjson_really_inline document_stream::iterator& document_stream::iterator::ope // // Note that setting finished = true is essential otherwise // we would enter an infinite loop. - if (stream.error) { finished = true; } - // Note that stream.error() is guarded against error conditions - // (it will immediately return if stream.error casts to false). - // In effect, this next function does nothing when (stream.error) + if (stream->error) { finished = true; } + // Note that stream->error() is guarded against error conditions + // (it will immediately return if stream->error casts to false). + // In effect, this next function does nothing when (stream->error) // is true (hence the risk of an infinite loop). - stream.next(); + stream->next(); // If that was the last document, we're finished. // It is the only type of error we do not want to appear // in operator*. - if (stream.error == EMPTY) { finished = true; } + if (stream->error == EMPTY) { finished = true; } // If we had any other kind of error (not EMPTY) then we want // to pass it along to the operator* and we cannot mark the result // as "finished" just yet. @@ -205,12 +209,12 @@ inline void document_stream::start() noexcept { } simdjson_really_inline size_t document_stream::iterator::current_index() const noexcept { - return stream.doc_index; + return stream->doc_index; } simdjson_really_inline std::string_view document_stream::iterator::source() const noexcept { - size_t next_doc_index = stream.batch_start + stream.parser->implementation->structural_indexes[stream.parser->implementation->next_structural_index]; - return std::string_view(reinterpret_cast(stream.buf) + current_index(), next_doc_index - current_index() - 1); + size_t next_doc_index = stream->batch_start + stream->parser->implementation->structural_indexes[stream->parser->implementation->next_structural_index]; + return std::string_view(reinterpret_cast(stream->buf) + current_index(), next_doc_index - current_index() - 1); } diff --git a/include/simdjson/dom/document_stream.h b/include/simdjson/dom/document_stream.h index c725d90f..31856167 100644 --- a/include/simdjson/dom/document_stream.h +++ b/include/simdjson/dom/document_stream.h @@ -93,12 +93,23 @@ public: */ class iterator { public: + using value_type = simdjson_result; + using reference = value_type; + + using difference_type = std::ptrdiff_t; + + using iterator_category = std::input_iterator_tag; + + /** + * Default contructor. + */ + simdjson_really_inline iterator() noexcept; /** * Get the current document (or error). */ - simdjson_really_inline simdjson_result operator*() noexcept; + simdjson_really_inline reference operator*() noexcept; /** - * Advance to the next document. + * Advance to the next document (prefix). */ inline iterator& operator++() noexcept; /** @@ -144,9 +155,9 @@ public: simdjson_really_inline std::string_view source() const noexcept; private: - simdjson_really_inline iterator(document_stream &s, bool finished) noexcept; + simdjson_really_inline iterator(document_stream *s, bool finished) noexcept; /** The document_stream we're iterating through. */ - document_stream& stream; + document_stream* stream; /** Whether we're finished or not. */ bool finished; friend class document_stream;