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
}
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<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
// 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<const char*>(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<const char*>(stream->buf) + current_index(), next_doc_index - current_index() - 1);
}

View File

@ -93,12 +93,23 @@ public:
*/
class iterator {
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).
*/
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;
/**
@ -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;