From 1d055261b4144dbf86b2658437015b15d4dd9bff Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 4 Sep 2022 00:32:56 +0100 Subject: initial --- include/jsoncons/staj_iterator.hpp | 449 +++++++++++++++++++++++++++++++++++++ 1 file changed, 449 insertions(+) create mode 100644 include/jsoncons/staj_iterator.hpp (limited to 'include/jsoncons/staj_iterator.hpp') diff --git a/include/jsoncons/staj_iterator.hpp b/include/jsoncons/staj_iterator.hpp new file mode 100644 index 0000000..a6897f7 --- /dev/null +++ b/include/jsoncons/staj_iterator.hpp @@ -0,0 +1,449 @@ +// Copyright 2018 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_STAJ_ITERATOR_HPP +#define JSONCONS_STAJ_ITERATOR_HPP + +#include // placement new +#include +#include +#include +#include +#include +#include // std::input_iterator_tag +#include +#include +#include +#include + +namespace jsoncons { + + template + class staj_array_view; + + template + class staj_array_iterator + { + using char_type = typename Json::char_type; + + staj_array_view* view_; + std::exception_ptr eptr_; + + public: + using value_type = T; + using difference_type = std::ptrdiff_t; + using pointer = T*; + using reference = T&; + using iterator_category = std::input_iterator_tag; + + staj_array_iterator() noexcept + : view_(nullptr) + { + } + + staj_array_iterator(staj_array_view& view) + : view_(std::addressof(view)) + { + if (view_->cursor_->current().event_type() == staj_event_type::begin_array) + { + next(); + } + else + { + view_->cursor_ = nullptr; + } + } + + staj_array_iterator(staj_array_view& view, + std::error_code& ec) + : view_(std::addressof(view)) + { + if (view_->cursor_->current().event_type() == staj_event_type::begin_array) + { + next(ec); + if (ec) {view_ = nullptr;} + } + else + { + view_ = nullptr; + } + } + + ~staj_array_iterator() noexcept + { + } + + bool has_value() const + { + return !eptr_; + } + + const T& operator*() const + { + if (eptr_) + { + std::rethrow_exception(eptr_); + } + else + { + return *view_->value_; + } + } + + const T* operator->() const + { + if (eptr_) + { + std::rethrow_exception(eptr_); + } + else + { + return view_->value_.operator->(); + } + } + + staj_array_iterator& operator++() + { + next(); + return *this; + } + + staj_array_iterator& increment(std::error_code& ec) + { + next(ec); + if (ec) {view_ = nullptr;} + return *this; + } + + staj_array_iterator operator++(int) // postfix increment + { + staj_array_iterator temp(*this); + next(); + return temp; + } + + friend bool operator==(const staj_array_iterator& a, const staj_array_iterator& b) + { + return (!a.view_ && !b.view_) + || (!a.view_ && b.done()) + || (!b.view_ && a.done()); + } + + friend bool operator!=(const staj_array_iterator& a, const staj_array_iterator& b) + { + return !(a == b); + } + + private: + + bool done() const + { + return view_->cursor_->done() || view_->cursor_->current().event_type() == staj_event_type::end_array; + } + + void next() + { + std::error_code ec; + next(ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec, view_->cursor_->context().line(), view_->cursor_->context().column())); + } + } + + void next(std::error_code& ec) + { + using char_type = typename Json::char_type; + + if (!done()) + { + view_->cursor_->next(ec); + if (ec) + { + return; + } + if (!done()) + { + eptr_ = std::exception_ptr(); + JSONCONS_TRY + { + view_->value_ = decode_traits::decode(*view_->cursor_, view_->decoder_, ec); + } + JSONCONS_CATCH(const conv_error&) + { + eptr_ = std::current_exception(); + } + } + } + } + }; + + template + class staj_object_view; + + template + class staj_object_iterator + { + using char_type = typename Json::char_type; + + staj_object_view* view_; + std::exception_ptr eptr_; + public: + using key_type = std::basic_string; + using value_type = std::pair; + using difference_type = std::ptrdiff_t; + using pointer = value_type*; + using reference = value_type&; + using iterator_category = std::input_iterator_tag; + + public: + + staj_object_iterator() noexcept + : view_(nullptr) + { + } + + staj_object_iterator(staj_object_view& view) + : view_(std::addressof(view)) + { + if (view_->cursor_->current().event_type() == staj_event_type::begin_object) + { + next(); + } + else + { + view_ = nullptr; + } + } + + staj_object_iterator(staj_object_view& view, + std::error_code& ec) + : view_(std::addressof(view)) + { + if (view_->cursor_->current().event_type() == staj_event_type::begin_object) + { + next(ec); + if (ec) {view_ = nullptr;} + } + else + { + view_ = nullptr; + } + } + + ~staj_object_iterator() noexcept + { + } + + bool has_value() const + { + return !eptr_; + } + + const value_type& operator*() const + { + if (eptr_) + { + std::rethrow_exception(eptr_); + } + else + { + return *view_->key_value_; + } + } + + const value_type* operator->() const + { + if (eptr_) + { + std::rethrow_exception(eptr_); + } + else + { + return view_->key_value_.operator->(); + } + } + + staj_object_iterator& operator++() + { + next(); + return *this; + } + + staj_object_iterator& increment(std::error_code& ec) + { + next(ec); + if (ec) + { + view_ = nullptr; + } + return *this; + } + + staj_object_iterator operator++(int) // postfix increment + { + staj_object_iterator temp(*this); + next(); + return temp; + } + + friend bool operator==(const staj_object_iterator& a, const staj_object_iterator& b) + { + return (!a.view_ && !b.view_) + || (!a.view_ && b.done()) + || (!b.view_ && a.done()); + } + + friend bool operator!=(const staj_object_iterator& a, const staj_object_iterator& b) + { + return !(a == b); + } + + private: + + bool done() const + { + return view_->cursor_->done() || view_->cursor_->current().event_type() == staj_event_type::end_object; + } + + void next() + { + std::error_code ec; + next(ec); + if (ec) + { + JSONCONS_THROW(ser_error(ec, view_->cursor_->context().line(), view_->cursor_->context().column())); + } + } + + void next(std::error_code& ec) + { + using char_type = typename Json::char_type; + + view_->cursor_->next(ec); + if (ec) + { + return; + } + if (!done()) + { + JSONCONS_ASSERT(view_->cursor_->current().event_type() == staj_event_type::key); + auto key = view_->cursor_->current(). template get(); + view_->cursor_->next(ec); + if (ec) + { + return; + } + if (!done()) + { + eptr_ = std::exception_ptr(); + JSONCONS_TRY + { + view_->key_value_ = value_type(std::move(key),decode_traits::decode(*view_->cursor_, view_->decoder_, ec)); + } + JSONCONS_CATCH(const conv_error&) + { + eptr_ = std::current_exception(); + } + } + } + } + }; + + // staj_array_view + + template + class staj_array_view + { + friend class staj_array_iterator; + public: + using char_type = typename Json::char_type; + using iterator = staj_array_iterator; + private: + basic_staj_cursor* cursor_; + json_decoder decoder_; + jsoncons::optional value_; + public: + staj_array_view(basic_staj_cursor& cursor) + : cursor_(std::addressof(cursor)) + { + } + + iterator begin() + { + return staj_array_iterator(*this); + } + + iterator end() + { + return staj_array_iterator(); + } + }; + + // staj_object_view + + template + class staj_object_view + { + friend class staj_object_iterator; + public: + using char_type = typename Json::char_type; + using iterator = staj_object_iterator; + using key_type = std::basic_string; + using value_type = std::pair; + private: + basic_staj_cursor* cursor_; + json_decoder decoder_; + jsoncons::optional key_value_; + public: + staj_object_view(basic_staj_cursor& cursor) + : cursor_(std::addressof(cursor)) + { + } + + iterator begin() + { + return staj_object_iterator(*this); + } + + iterator end() + { + return staj_object_iterator(); + } + }; + + template ::value,T,basic_json>::type> + staj_array_view staj_array(basic_staj_cursor& cursor) + { + return staj_array_view(cursor); + } + + template ::value,T,basic_json>::type> + staj_object_view staj_object(basic_staj_cursor& cursor) + { + return staj_object_view(cursor); + } + +#if !defined(JSONCONS_NO_DEPRECATED) + template ::value,T,basic_json>::type> + JSONCONS_DEPRECATED_MSG("Instead, use staj_array()") + staj_array_view make_array_iterator(basic_staj_cursor& cursor) + { + return staj_array_view(cursor); + } + + template ::value,T,basic_json>::type> + JSONCONS_DEPRECATED_MSG("Instead, use staj_object()") + staj_object_view, T, Json> make_object_iterator(basic_staj_cursor& cursor) + { + return staj_object_view, T, Json>(cursor); + } +#endif + +} // namespace jsoncons + +#endif + -- cgit v1.2.3