aboutsummaryrefslogtreecommitdiff
path: root/include/jsoncons/staj_iterator.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/jsoncons/staj_iterator.hpp')
-rw-r--r--include/jsoncons/staj_iterator.hpp449
1 files changed, 449 insertions, 0 deletions
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 <new> // placement new
+#include <memory>
+#include <string>
+#include <stdexcept>
+#include <system_error>
+#include <ios>
+#include <iterator> // std::input_iterator_tag
+#include <jsoncons/json_exception.hpp>
+#include <jsoncons/staj_cursor.hpp>
+#include <jsoncons/basic_json.hpp>
+#include <jsoncons/decode_traits.hpp>
+
+namespace jsoncons {
+
+ template <class T, class Json>
+ class staj_array_view;
+
+ template<class T, class Json>
+ class staj_array_iterator
+ {
+ using char_type = typename Json::char_type;
+
+ staj_array_view<T, Json>* 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<T, Json>& 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<T, Json>& 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<T,char_type>::decode(*view_->cursor_, view_->decoder_, ec);
+ }
+ JSONCONS_CATCH(const conv_error&)
+ {
+ eptr_ = std::current_exception();
+ }
+ }
+ }
+ }
+ };
+
+ template <class Key,class Json,class T=Json>
+ class staj_object_view;
+
+ template <class Key, class T, class Json>
+ class staj_object_iterator
+ {
+ using char_type = typename Json::char_type;
+
+ staj_object_view<Key, T, Json>* view_;
+ std::exception_ptr eptr_;
+ public:
+ using key_type = std::basic_string<char_type>;
+ using value_type = std::pair<key_type,T>;
+ 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<Key, T, Json>& 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<Key, T, Json>& 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<key_type>();
+ 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<T,char_type>::decode(*view_->cursor_, view_->decoder_, ec));
+ }
+ JSONCONS_CATCH(const conv_error&)
+ {
+ eptr_ = std::current_exception();
+ }
+ }
+ }
+ }
+ };
+
+ // staj_array_view
+
+ template <class T, class Json>
+ class staj_array_view
+ {
+ friend class staj_array_iterator<T, Json>;
+ public:
+ using char_type = typename Json::char_type;
+ using iterator = staj_array_iterator<T, Json>;
+ private:
+ basic_staj_cursor<char_type>* cursor_;
+ json_decoder<Json> decoder_;
+ jsoncons::optional<T> value_;
+ public:
+ staj_array_view(basic_staj_cursor<char_type>& cursor)
+ : cursor_(std::addressof(cursor))
+ {
+ }
+
+ iterator begin()
+ {
+ return staj_array_iterator<T, Json>(*this);
+ }
+
+ iterator end()
+ {
+ return staj_array_iterator<T, Json>();
+ }
+ };
+
+ // staj_object_view
+
+ template <class Key, class T, class Json>
+ class staj_object_view
+ {
+ friend class staj_object_iterator<Key,T,Json>;
+ public:
+ using char_type = typename Json::char_type;
+ using iterator = staj_object_iterator<Key,T,Json>;
+ using key_type = std::basic_string<char_type>;
+ using value_type = std::pair<key_type,T>;
+ private:
+ basic_staj_cursor<char_type>* cursor_;
+ json_decoder<Json> decoder_;
+ jsoncons::optional<value_type> key_value_;
+ public:
+ staj_object_view(basic_staj_cursor<char_type>& cursor)
+ : cursor_(std::addressof(cursor))
+ {
+ }
+
+ iterator begin()
+ {
+ return staj_object_iterator<Key,T,Json>(*this);
+ }
+
+ iterator end()
+ {
+ return staj_object_iterator<Key,T,Json>();
+ }
+ };
+
+ template <class T, class CharT, class Json=typename std::conditional<type_traits::is_basic_json<T>::value,T,basic_json<CharT>>::type>
+ staj_array_view<T, Json> staj_array(basic_staj_cursor<CharT>& cursor)
+ {
+ return staj_array_view<T, Json>(cursor);
+ }
+
+ template <class Key, class T, class CharT, class Json=typename std::conditional<type_traits::is_basic_json<T>::value,T,basic_json<CharT>>::type>
+ staj_object_view<Key, T, Json> staj_object(basic_staj_cursor<CharT>& cursor)
+ {
+ return staj_object_view<Key, T, Json>(cursor);
+ }
+
+#if !defined(JSONCONS_NO_DEPRECATED)
+ template <class T, class CharT, class Json=typename std::conditional<type_traits::is_basic_json<T>::value,T,basic_json<CharT>>::type>
+ JSONCONS_DEPRECATED_MSG("Instead, use staj_array()")
+ staj_array_view<T, Json> make_array_iterator(basic_staj_cursor<CharT>& cursor)
+ {
+ return staj_array_view<T, Json>(cursor);
+ }
+
+ template <class T, class CharT, class Json=typename std::conditional<type_traits::is_basic_json<T>::value,T,basic_json<CharT>>::type>
+ JSONCONS_DEPRECATED_MSG("Instead, use staj_object()")
+ staj_object_view<std::basic_string<CharT>, T, Json> make_object_iterator(basic_staj_cursor<CharT>& cursor)
+ {
+ return staj_object_view<std::basic_string<CharT>, T, Json>(cursor);
+ }
+#endif
+
+} // namespace jsoncons
+
+#endif
+