/* * 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 * * http://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. * * Copyright 2015-2017 Danny Robson */ #ifndef CRUFT_UTIL_VIEW_HPP #define CRUFT_UTIL_VIEW_HPP #include "./debug.hpp" #include "./types/traits.hpp" #include #include #include #include #include namespace util { template struct view { public: using value_type = typename std::iterator_traits>::value_type; constexpr view (T first, T last) noexcept: m_begin (first), m_end (last) { ; } constexpr view (const view &rhs) noexcept: m_begin (rhs.m_begin), m_end (rhs.m_end) { ; } // technically we could get away without explicitly defining a move // constructor here, but by nulling rhs we can more easily use this // class as a base for unique owning pointers without exposing // begin/end to them directly. constexpr view (view &&rhs) noexcept: view (T{}, T{}) { std::swap (m_begin, rhs.m_begin); std::swap (m_end, rhs.m_end); } template constexpr explicit view (K &klass): m_begin (std::begin (klass)), m_end (std::end (klass)) { ; } template constexpr explicit view (const K &klass): m_begin (std::begin (klass)), m_end (std::end (klass)) { ; } view& operator= (const view &rhs) noexcept { m_begin = rhs.m_begin; m_end = rhs.m_end; return *this; } view& operator= (view &&rhs) noexcept { m_begin = rhs.m_begin; m_end = rhs.m_end; m_begin = T{}; m_end = T{}; return *this; }; constexpr T begin (void) noexcept { return m_begin; } constexpr T end (void) noexcept { return m_end; } constexpr const T begin (void) const noexcept { return cbegin (); } constexpr const T end (void) const noexcept { return cend (); } constexpr const T cbegin (void) const noexcept { return m_begin; } constexpr const T cend (void) const noexcept { return m_end; } auto data (void) { return begin (); } auto data (void) const { return begin (); } constexpr bool empty (void) const noexcept { return m_begin == m_end; } constexpr auto size (void) const noexcept { return std::distance (m_begin, m_end); } constexpr auto redim (int count) const { CHECK_GT (count, 0); if (count > size ()) throw std::invalid_argument ("redim to higher size not allowed"); return view { m_begin, m_begin + count }; }; constexpr value_type& operator[] (size_t idx) noexcept { auto it = begin (); std::advance (it, idx); return *it; } constexpr const value_type& operator[] (size_t idx) const noexcept { auto it = begin (); std::advance (it, idx); return *it; } bool operator== (const view &rhs) const noexcept { return rhs.m_begin == m_begin && rhs.m_end == m_end; } private: T m_begin; T m_end; }; template auto make_view (const T (&arr)[N]) { return util::view (arr + 0, arr + N); } template auto make_view (T &t) { return util::view { std::begin (t), std::end (t) }; } template auto make_view (const T &t) { return util::view { std::cbegin (t), std::cend (t) }; } template auto make_view (T&&) = delete; template auto make_cview (const T &t) { return util::view { std::cbegin (t), std::cend (t) }; } template auto make_view (T first, T last) { return view {first, last}; } template auto make_cview (T *first, T *last) { return view {first, last}; } // string conversions inline view make_view (const char *str) { return { str, str + strlen (str) }; } inline view make_view (char *str) { return { str, str + strlen (str) }; } template view make_view (const std::basic_string &str) { return { std::data (str), std::data (str) + std::size (str) }; } template view make_view (std::basic_string &str) { return { std::data (str), std::data (str) + std::size (str) }; } template view make_view (const std::basic_string&&) = delete; template view make_view (std::basic_string&&) = delete; // boolean operationrs template bool operator!= (view, view); bool operator== (const std::string&, view); bool operator== (const std::string&, view); bool operator== (const std::string&, view); bool operator== (const std::string&, view); bool operator== (view, const std::string&); bool operator== (view, const std::string&); bool operator== (view, const std::string&); bool operator== (view, const std::string&); template std::ostream& operator<< (std::ostream&, view); } #endif