aboutsummaryrefslogtreecommitdiff
path: root/include/jsoncons/detail/span.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/jsoncons/detail/span.hpp')
-rw-r--r--include/jsoncons/detail/span.hpp188
1 files changed, 188 insertions, 0 deletions
diff --git a/include/jsoncons/detail/span.hpp b/include/jsoncons/detail/span.hpp
new file mode 100644
index 0000000..02c24ee
--- /dev/null
+++ b/include/jsoncons/detail/span.hpp
@@ -0,0 +1,188 @@
+#ifndef JSONCONS_DETAIL_SPAN_HPP
+#define JSONCONS_DETAIL_SPAN_HPP
+
+#include <utility> // std::swap
+#include <memory> // std::addressof
+#include <type_traits> // std::enable_if, std::true_type, std::false_type
+#include <jsoncons/config/compiler_support.hpp>
+#include <jsoncons/more_type_traits.hpp>
+#include <iterator>
+#include <limits>
+
+namespace jsoncons
+{
+namespace detail
+{
+ constexpr std::size_t dynamic_extent = (std::numeric_limits<std::size_t>::max)();
+
+ template< class T, std::size_t Extent = dynamic_extent>
+ class span;
+
+ template<class T>
+ struct is_span : std::false_type{};
+
+ template< class T>
+ struct is_span<span<T>> : std::true_type{};
+
+ template<
+ class T,
+ std::size_t Extent
+ > class span
+ {
+ public:
+ using element_type = T;
+ using value_type = typename std::remove_volatile<typename std::remove_const<T>::type>::type;
+ using size_type = std::size_t;
+ using difference_type = std::ptrdiff_t;
+ using pointer = T*;
+ using const_pointer = const T*;
+ using reference = T&;
+ using const_reference = const T&;
+ using iterator = pointer;
+ using const_iterator = const_pointer;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ private:
+ pointer data_;
+ size_type size_;
+ public:
+ static constexpr std::size_t extent = Extent;
+
+ constexpr span() noexcept
+ : data_(nullptr), size_(0)
+ {
+ }
+ constexpr span(pointer data, size_type size)
+ : data_(data), size_(size)
+ {
+ }
+
+ template <typename C>
+ constexpr span(C& c,
+ typename std::enable_if<!is_span<C>::value && !type_traits::is_std_array<C>::value && type_traits::is_compatible_element<C,element_type>::value && type_traits::has_data_and_size<C>::value>::type* = 0)
+ : data_(c.data()), size_(c.size())
+ {
+ }
+
+ template <std::size_t N>
+ span(element_type (&arr)[N]) noexcept
+ : data_(std::addressof(arr[0])), size_(N)
+ {
+ }
+
+ template <std::size_t N>
+ span(std::array<value_type, N>& arr,
+ typename std::enable_if<(extent == dynamic_extent || extent == N)>::type* = 0) noexcept
+ : data_(arr.data()), size_(arr.size())
+ {
+ }
+
+ template <std::size_t N>
+ span(const std::array<value_type, N>& arr,
+ typename std::enable_if<(extent == dynamic_extent || extent == N)>::type* = 0) noexcept
+ : data_(arr.data()), size_(arr.size())
+ {
+ }
+
+ template <typename C>
+ constexpr span(const C& c,
+ typename std::enable_if<!is_span<C>::value && !type_traits::is_std_array<C>::value && type_traits::is_compatible_element<C,element_type>::value && type_traits::has_data_and_size<C>::value>::type* = 0)
+ : data_(c.data()), size_(c.size())
+ {
+ }
+
+ template <class U, std::size_t N>
+ constexpr span(const span<U, N>& s,
+ typename std::enable_if<(N == dynamic_extent || N == extent) && std::is_convertible<U(*)[], element_type(*)[]>::value>::type* = 0) noexcept
+ : data_(s.data()), size_(s.size())
+ {
+ }
+
+ constexpr span(const span& other) noexcept = default;
+
+ span& operator=( const span& other ) noexcept = default;
+
+ constexpr pointer data() const noexcept
+ {
+ return data_;
+ }
+
+ constexpr size_type size() const noexcept
+ {
+ return size_;
+ }
+
+ constexpr bool empty() const noexcept
+ {
+ return size_ == 0;
+ }
+
+ constexpr reference operator[](size_type index) const
+ {
+ return data_[index];
+ }
+
+ // iterator support
+ const_iterator begin() const noexcept
+ {
+ return data_;
+ }
+ const_iterator end() const noexcept
+ {
+ return data_ + size_;
+ }
+ const_iterator cbegin() const noexcept
+ {
+ return data_;
+ }
+ const_iterator cend() const noexcept
+ {
+ return data_ + size_;
+ }
+ const_reverse_iterator rbegin() const noexcept
+ {
+ return const_reverse_iterator(end());
+ }
+ const_reverse_iterator rend() const noexcept
+ {
+ return const_reverse_iterator(begin());
+ }
+ const_reverse_iterator crbegin() const noexcept
+ {
+ return const_reverse_iterator(end());
+ }
+ const_reverse_iterator crend() const noexcept
+ {
+ return const_reverse_iterator(begin());
+ }
+
+ span<element_type, dynamic_extent>
+ first(std::size_t count) const
+ {
+ JSONCONS_ASSERT(count <= size());
+
+ return span< element_type, dynamic_extent >( data(), count );
+ }
+
+ span<element_type, dynamic_extent>
+ last(std::size_t count) const
+ {
+ JSONCONS_ASSERT(count <= size());
+
+ return span<element_type, dynamic_extent>(data() + ( size() - count ), count);
+ }
+
+ span<element_type, dynamic_extent>
+ subspan(std::size_t offset, std::size_t count = dynamic_extent) const
+ {
+ //JSONCONS_ASSERT((offset <= size() && (count == dynamic_extent || (offset + count <= size()))));
+
+ return span<element_type, dynamic_extent>(
+ data() + offset, count == dynamic_extent ? size() - offset : count );
+ }
+ };
+
+} // namespace detail
+} // namespace jsoncons
+
+#endif