aboutsummaryrefslogtreecommitdiff
path: root/include/jsoncons/json_array.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/jsoncons/json_array.hpp')
-rw-r--r--include/jsoncons/json_array.hpp324
1 files changed, 324 insertions, 0 deletions
diff --git a/include/jsoncons/json_array.hpp b/include/jsoncons/json_array.hpp
new file mode 100644
index 0000000..5877f4d
--- /dev/null
+++ b/include/jsoncons/json_array.hpp
@@ -0,0 +1,324 @@
+// Copyright 2013 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_JSON_ARRAY_HPP
+#define JSONCONS_JSON_ARRAY_HPP
+
+#include <string>
+#include <vector>
+#include <exception>
+#include <cstring>
+#include <algorithm> // std::sort, std::stable_sort, std::lower_bound, std::unique
+#include <utility>
+#include <initializer_list>
+#include <iterator> // std::iterator_traits
+#include <memory> // std::allocator
+#include <utility> // std::move
+#include <cassert> // assert
+#include <type_traits> // std::enable_if
+#include <jsoncons/json_exception.hpp>
+#include <jsoncons/allocator_holder.hpp>
+
+namespace jsoncons {
+
+ // json_array
+
+ template <class Json,template<typename,typename> class SequenceContainer = std::vector>
+ class json_array : public allocator_holder<typename Json::allocator_type>
+ {
+ public:
+ using allocator_type = typename Json::allocator_type;
+ using value_type = Json;
+ private:
+ using value_allocator_type = typename std::allocator_traits<allocator_type>:: template rebind_alloc<value_type>;
+ using value_container_type = SequenceContainer<value_type,value_allocator_type>;
+ value_container_type elements_;
+ public:
+ using iterator = typename value_container_type::iterator;
+ using const_iterator = typename value_container_type::const_iterator;
+ using reference = typename std::iterator_traits<iterator>::reference;
+ using const_reference = typename std::iterator_traits<const_iterator>::reference;
+
+ using allocator_holder<allocator_type>::get_allocator;
+
+ json_array()
+ {
+ }
+
+ explicit json_array(const allocator_type& alloc)
+ : allocator_holder<allocator_type>(alloc),
+ elements_(value_allocator_type(alloc))
+ {
+ }
+
+ explicit json_array(std::size_t n,
+ const allocator_type& alloc = allocator_type())
+ : allocator_holder<allocator_type>(alloc),
+ elements_(n,Json(),value_allocator_type(alloc))
+ {
+ }
+
+ explicit json_array(std::size_t n,
+ const Json& value,
+ const allocator_type& alloc = allocator_type())
+ : allocator_holder<allocator_type>(alloc),
+ elements_(n,value,value_allocator_type(alloc))
+ {
+ }
+
+ template <class InputIterator>
+ json_array(InputIterator begin, InputIterator end, const allocator_type& alloc = allocator_type())
+ : allocator_holder<allocator_type>(alloc),
+ elements_(begin,end,value_allocator_type(alloc))
+ {
+ }
+ json_array(const json_array& val)
+ : allocator_holder<allocator_type>(val.get_allocator()),
+ elements_(val.elements_)
+ {
+ }
+ json_array(const json_array& val, const allocator_type& alloc)
+ : allocator_holder<allocator_type>(alloc),
+ elements_(val.elements_,value_allocator_type(alloc))
+ {
+ }
+
+ json_array(json_array&& val) noexcept
+ : allocator_holder<allocator_type>(val.get_allocator()),
+ elements_(std::move(val.elements_))
+ {
+ }
+ json_array(json_array&& val, const allocator_type& alloc)
+ : allocator_holder<allocator_type>(alloc),
+ elements_(std::move(val.elements_),value_allocator_type(alloc))
+ {
+ }
+
+ json_array(const std::initializer_list<Json>& init,
+ const allocator_type& alloc = allocator_type())
+ : allocator_holder<allocator_type>(alloc),
+ elements_(init,value_allocator_type(alloc))
+ {
+ }
+ ~json_array() noexcept
+ {
+ flatten_and_destroy();
+ }
+
+ reference back()
+ {
+ return elements_.back();
+ }
+
+ const_reference back() const
+ {
+ return elements_.back();
+ }
+
+ void pop_back()
+ {
+ elements_.pop_back();
+ }
+
+ bool empty() const
+ {
+ return elements_.empty();
+ }
+
+ void swap(json_array<Json>& val) noexcept
+ {
+ elements_.swap(val.elements_);
+ }
+
+ std::size_t size() const {return elements_.size();}
+
+ std::size_t capacity() const {return elements_.capacity();}
+
+ void clear() {elements_.clear();}
+
+ void shrink_to_fit()
+ {
+ for (std::size_t i = 0; i < elements_.size(); ++i)
+ {
+ elements_[i].shrink_to_fit();
+ }
+ elements_.shrink_to_fit();
+ }
+
+ void reserve(std::size_t n) {elements_.reserve(n);}
+
+ void resize(std::size_t n) {elements_.resize(n);}
+
+ void resize(std::size_t n, const Json& val) {elements_.resize(n,val);}
+
+ #if !defined(JSONCONS_NO_DEPRECATED)
+ JSONCONS_DEPRECATED_MSG("Instead, use erase(const_iterator, const_iterator)")
+ void remove_range(std::size_t from_index, std::size_t to_index)
+ {
+ JSONCONS_ASSERT(from_index <= to_index);
+ JSONCONS_ASSERT(to_index <= elements_.size());
+ elements_.erase(elements_.cbegin()+from_index,elements_.cbegin()+to_index);
+ }
+ #endif
+
+ iterator erase(const_iterator pos)
+ {
+ #if defined(JSONCONS_NO_VECTOR_ERASE_TAKES_CONST_ITERATOR)
+ iterator it = elements_.begin() + (pos - elements_.begin());
+ return elements_.erase(it);
+ #else
+ return elements_.erase(pos);
+ #endif
+ }
+
+ iterator erase(const_iterator first, const_iterator last)
+ {
+ #if defined(JSONCONS_NO_VECTOR_ERASE_TAKES_CONST_ITERATOR)
+ iterator it1 = elements_.begin() + (first - elements_.begin());
+ iterator it2 = elements_.begin() + (last - elements_.begin());
+ return elements_.erase(it1,it2);
+ #else
+ return elements_.erase(first,last);
+ #endif
+ }
+
+ Json& operator[](std::size_t i) {return elements_[i];}
+
+ const Json& operator[](std::size_t i) const {return elements_[i];}
+
+ // push_back
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<type_traits::is_stateless<A>::value,void>::type
+ push_back(T&& value)
+ {
+ elements_.emplace_back(std::forward<T>(value));
+ }
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<!type_traits::is_stateless<A>::value,void>::type
+ push_back(T&& value)
+ {
+ elements_.emplace_back(std::forward<T>(value),get_allocator());
+ }
+
+ template <class T, class A=allocator_type>
+ typename std::enable_if<type_traits::is_stateless<A>::value,iterator>::type
+ insert(const_iterator pos, T&& value)
+ {
+ #if defined(JSONCONS_NO_VECTOR_ERASE_TAKES_CONST_ITERATOR)
+ iterator it = elements_.begin() + (pos - elements_.begin());
+ return elements_.emplace(it, std::forward<T>(value));
+ #else
+ return elements_.emplace(pos, std::forward<T>(value));
+ #endif
+ }
+ template <class T, class A=allocator_type>
+ typename std::enable_if<!type_traits::is_stateless<A>::value,iterator>::type
+ insert(const_iterator pos, T&& value)
+ {
+ #if defined(JSONCONS_NO_VECTOR_ERASE_TAKES_CONST_ITERATOR)
+ iterator it = elements_.begin() + (pos - elements_.begin());
+ return elements_.emplace(it, std::forward<T>(value), get_allocator());
+ #else
+ return elements_.emplace(pos, std::forward<T>(value), get_allocator());
+ #endif
+ }
+
+ template <class InputIt>
+ iterator insert(const_iterator pos, InputIt first, InputIt last)
+ {
+ #if defined(JSONCONS_NO_VECTOR_ERASE_TAKES_CONST_ITERATOR)
+ iterator it = elements_.begin() + (pos - elements_.begin());
+ elements_.insert(it, first, last);
+ return first == last ? it : it + 1;
+ #else
+ return elements_.insert(pos, first, last);
+ #endif
+ }
+
+ template <class A=allocator_type, class... Args>
+ typename std::enable_if<type_traits::is_stateless<A>::value,iterator>::type
+ emplace(const_iterator pos, Args&&... args)
+ {
+ #if defined(JSONCONS_NO_VECTOR_ERASE_TAKES_CONST_ITERATOR)
+ iterator it = elements_.begin() + (pos - elements_.begin());
+ return elements_.emplace(it, std::forward<Args>(args)...);
+ #else
+ return elements_.emplace(pos, std::forward<Args>(args)...);
+ #endif
+ }
+
+ template <class... Args>
+ Json& emplace_back(Args&&... args)
+ {
+ elements_.emplace_back(std::forward<Args>(args)...);
+ return elements_.back();
+ }
+
+ iterator begin() {return elements_.begin();}
+
+ iterator end() {return elements_.end();}
+
+ const_iterator begin() const {return elements_.begin();}
+
+ const_iterator end() const {return elements_.end();}
+
+ bool operator==(const json_array<Json>& rhs) const noexcept
+ {
+ return elements_ == rhs.elements_;
+ }
+
+ bool operator<(const json_array<Json>& rhs) const noexcept
+ {
+ return elements_ < rhs.elements_;
+ }
+ private:
+
+ json_array& operator=(const json_array<Json>&) = delete;
+
+ void flatten_and_destroy() noexcept
+ {
+ while (!elements_.empty())
+ {
+ value_type current = std::move(elements_.back());
+ elements_.pop_back();
+ switch (current.storage_kind())
+ {
+ case json_storage_kind::array_value:
+ {
+ for (auto&& item : current.array_range())
+ {
+ if (item.size() > 0) // non-empty object or array
+ {
+ elements_.push_back(std::move(item));
+ }
+ }
+ current.clear();
+ break;
+ }
+ case json_storage_kind::object_value:
+ {
+ for (auto&& kv : current.object_range())
+ {
+ if (kv.value().size() > 0) // non-empty object or array
+ {
+ elements_.push_back(std::move(kv.value()));
+ }
+ }
+ current.clear();
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ };
+
+} // namespace jsoncons
+
+#endif