Make dom::document_stream::iterator copyable and default-constructible by holding pointer to document_stream instead of ref (#1463)

Co-authored-by: Alexey Rychkov <arychkov@defytrading.com>
This commit is contained in:
rychale 2021-03-01 22:40:51 +03:00 committed by GitHub
parent a3d3e347a2
commit 9d22372cc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 19 deletions

View File

@ -121,28 +121,32 @@ simdjson_really_inline document_stream::~document_stream() noexcept {
#endif #endif
} }
simdjson_really_inline document_stream::iterator::iterator() noexcept
: stream{nullptr}, finished{true} {
}
simdjson_really_inline document_stream::iterator document_stream::begin() noexcept { simdjson_really_inline document_stream::iterator document_stream::begin() noexcept {
start(); start();
// If there are no documents, we're finished. // 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 { 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} { : stream{_stream}, finished{is_end} {
} }
simdjson_really_inline simdjson_result<element> 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 // Note that in case of error, we do not yet mark
// the iterator as "finished": this detection is done // the iterator as "finished": this detection is done
// in the operator++ function since it is possible // in the operator++ function since it is possible
// to call operator++ repeatedly while omitting // to call operator++ repeatedly while omitting
// calls to operator*. // calls to operator*.
if (stream.error) { return stream.error; } if (stream->error) { return stream->error; }
return stream.parser->doc.root(); return stream->parser->doc.root();
} }
simdjson_really_inline document_stream::iterator& document_stream::iterator::operator++() noexcept { 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 // Note that setting finished = true is essential otherwise
// we would enter an infinite loop. // we would enter an infinite loop.
if (stream.error) { finished = true; } if (stream->error) { finished = true; }
// Note that stream.error() is guarded against error conditions // Note that stream->error() is guarded against error conditions
// (it will immediately return if stream.error casts to false). // (it will immediately return if stream->error casts to false).
// In effect, this next function does nothing when (stream.error) // In effect, this next function does nothing when (stream->error)
// is true (hence the risk of an infinite loop). // is true (hence the risk of an infinite loop).
stream.next(); stream->next();
// If that was the last document, we're finished. // If that was the last document, we're finished.
// It is the only type of error we do not want to appear // It is the only type of error we do not want to appear
// in operator*. // 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 // 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 // to pass it along to the operator* and we cannot mark the result
// as "finished" just yet. // 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 { 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 { 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]; 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<const char*>(stream.buf) + current_index(), next_doc_index - current_index() - 1); return std::string_view(reinterpret_cast<const char*>(stream->buf) + current_index(), next_doc_index - current_index() - 1);
} }

View File

@ -93,12 +93,23 @@ public:
*/ */
class iterator { class iterator {
public: public:
using value_type = simdjson_result<element>;
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). * Get the current document (or error).
*/ */
simdjson_really_inline simdjson_result<element> operator*() noexcept; simdjson_really_inline reference operator*() noexcept;
/** /**
* Advance to the next document. * Advance to the next document (prefix).
*/ */
inline iterator& operator++() noexcept; inline iterator& operator++() noexcept;
/** /**
@ -144,9 +155,9 @@ public:
simdjson_really_inline std::string_view source() const noexcept; simdjson_really_inline std::string_view source() const noexcept;
private: 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. */ /** The document_stream we're iterating through. */
document_stream& stream; document_stream* stream;
/** Whether we're finished or not. */ /** Whether we're finished or not. */
bool finished; bool finished;
friend class document_stream; friend class document_stream;