summaryrefslogtreecommitdiffstats
path: root/src/third-party/scnlib/include/scn/util/span.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/third-party/scnlib/include/scn/util/span.h')
-rw-r--r--src/third-party/scnlib/include/scn/util/span.h240
1 files changed, 240 insertions, 0 deletions
diff --git a/src/third-party/scnlib/include/scn/util/span.h b/src/third-party/scnlib/include/scn/util/span.h
new file mode 100644
index 0000000..1abdd6c
--- /dev/null
+++ b/src/third-party/scnlib/include/scn/util/span.h
@@ -0,0 +1,240 @@
+// Copyright 2017 Elias Kosunen
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// This file is a part of scnlib:
+// https://github.com/eliaskosunen/scnlib
+
+#ifndef SCN_UTIL_SPAN_H
+#define SCN_UTIL_SPAN_H
+
+#include "memory.h"
+
+SCN_GCC_PUSH
+SCN_GCC_IGNORE("-Wnoexcept")
+#include <iterator>
+SCN_GCC_POP
+
+namespace scn {
+ SCN_BEGIN_NAMESPACE
+
+ namespace custom_ranges {
+ // iterator_category
+ using std::bidirectional_iterator_tag;
+ using std::forward_iterator_tag;
+ using std::input_iterator_tag;
+ using std::output_iterator_tag;
+ using std::random_access_iterator_tag;
+ struct contiguous_iterator_tag : random_access_iterator_tag {
+ };
+ } // namespace custom_ranges
+
+ /**
+ * A view over a contiguous range.
+ * Stripped-down version of `std::span`.
+ */
+ template <typename T>
+ class span {
+ public:
+ using element_type = T;
+ using value_type = typename std::remove_cv<T>::type;
+ using index_type = std::size_t;
+ using ssize_type = std::ptrdiff_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>;
+
+ constexpr span() noexcept = default;
+
+ template <typename I,
+ typename = decltype(detail::to_address(SCN_DECLVAL(I)))>
+ SCN_CONSTEXPR14 span(I begin, index_type count) noexcept
+ : m_ptr(detail::to_address(begin)),
+ m_end(detail::to_address(begin) + count)
+ {
+ }
+
+ template <typename I,
+ typename S,
+ typename = decltype(detail::to_address(SCN_DECLVAL(I)),
+ detail::to_address(SCN_DECLVAL(S)))>
+ SCN_CONSTEXPR14 span(I first, S last) noexcept
+ : m_ptr(detail::to_address(first)),
+ m_end(detail::to_address_safe(last, first, last))
+ {
+ }
+
+ template <typename U = typename std::add_const<T>::type,
+ typename E = element_type,
+ typename = typename std::enable_if<
+ std::is_same<E, value_type>::value>::type>
+ constexpr span(span<U> other) : m_ptr(other.m_ptr), m_end(other.m_end)
+ {
+ }
+
+ template <size_t N>
+ constexpr span(element_type (&arr)[N]) noexcept
+ : m_ptr(&arr), m_end(&arr + N)
+ {
+ }
+
+ SCN_CONSTEXPR14 iterator begin() noexcept
+ {
+ return m_ptr;
+ }
+ SCN_CONSTEXPR14 iterator end() noexcept
+ {
+ return m_end;
+ }
+ SCN_CONSTEXPR14 reverse_iterator rbegin() noexcept
+ {
+ return reverse_iterator{end()};
+ }
+ SCN_CONSTEXPR14 reverse_iterator rend() noexcept
+ {
+ return reverse_iterator{begin()};
+ }
+
+ constexpr const_iterator begin() const noexcept
+ {
+ return m_ptr;
+ }
+ constexpr const_iterator end() const noexcept
+ {
+ return m_end;
+ }
+ constexpr const_reverse_iterator rbegin() const noexcept
+ {
+ return reverse_iterator{end()};
+ }
+ constexpr const_reverse_iterator rend() const noexcept
+ {
+ return reverse_iterator{begin()};
+ }
+
+ constexpr const_iterator cbegin() const noexcept
+ {
+ return m_ptr;
+ }
+ constexpr const_iterator cend() const noexcept
+ {
+ return m_end;
+ }
+ constexpr const_reverse_iterator crbegin() const noexcept
+ {
+ return reverse_iterator{cend()};
+ }
+ constexpr const_reverse_iterator crend() const noexcept
+ {
+ return reverse_iterator{cbegin()};
+ }
+
+ SCN_CONSTEXPR14 reference operator[](index_type i) const noexcept
+ {
+ SCN_EXPECT(size() > i);
+ return *(m_ptr + i);
+ }
+
+ constexpr pointer data() const noexcept
+ {
+ return m_ptr;
+ }
+ SCN_NODISCARD constexpr index_type size() const noexcept
+ {
+ return static_cast<index_type>(m_end - m_ptr);
+ }
+ SCN_NODISCARD constexpr ssize_type ssize() const noexcept
+ {
+ return m_end - m_ptr;
+ }
+
+ SCN_CONSTEXPR14 span<T> first(index_type n) const
+ {
+ SCN_EXPECT(size() >= n);
+ return span<T>(data(), data() + n);
+ }
+ SCN_CONSTEXPR14 span<T> last(index_type n) const
+ {
+ SCN_EXPECT(size() >= n);
+ return span<T>(data() + size() - n, data() + size());
+ }
+ SCN_CONSTEXPR14 span<T> subspan(index_type off) const
+ {
+ SCN_EXPECT(size() >= off);
+ return span<T>(data() + off, size() - off);
+ }
+ SCN_CONSTEXPR14 span<T> subspan(index_type off,
+ difference_type count) const
+ {
+ SCN_EXPECT(size() > off + count);
+ SCN_EXPECT(count > 0);
+ return span<T>(data() + off, count);
+ }
+
+ constexpr operator span<typename std::add_const<T>::type>() const
+ {
+ return {m_ptr, m_end};
+ }
+ constexpr span<typename std::add_const<T>::type> as_const() const
+ {
+ return {m_ptr, m_end};
+ }
+
+ private:
+ pointer m_ptr{nullptr};
+ pointer m_end{nullptr};
+ };
+
+ template <typename I,
+ typename S,
+ typename Ptr = decltype(detail::to_address(SCN_DECLVAL(I))),
+ typename SPtr = decltype(detail::to_address(SCN_DECLVAL(S))),
+ typename ValueT = typename detail::remove_reference<
+ typename std::remove_pointer<Ptr>::type>::type>
+ SCN_CONSTEXPR14 auto make_span(I first, S last) noexcept -> span<ValueT>
+ {
+ return {first, last};
+ }
+ template <typename I,
+ typename Ptr = decltype(detail::to_address(SCN_DECLVAL(I))),
+ typename ValueT = typename detail::remove_reference<
+ typename std::remove_pointer<Ptr>::type>::type>
+ SCN_CONSTEXPR14 auto make_span(I first, std::size_t len) noexcept
+ -> span<ValueT>
+ {
+ return {first, len};
+ }
+
+ template <typename T>
+ SCN_CONSTEXPR14 span<typename T::value_type> make_span(
+ T& container) noexcept
+ {
+ using std::begin;
+ using std::end;
+ return span<typename T::value_type>(
+ detail::to_address(begin(container)),
+ detail::to_address_safe(end(container), begin(container),
+ end(container)));
+ }
+
+ SCN_END_NAMESPACE
+} // namespace scn
+
+#endif // SCN_SPAN_H