| /* Copyright (c) 2015-2025 The Khronos Group Inc. |
| * Copyright (c) 2015-2025 Valve Corporation |
| * Copyright (c) 2015-2025 LunarG, Inc. |
| * |
| * 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. |
| |
| */ |
| |
| #pragma once |
| #include <cstddef> |
| #include <type_traits> |
| #include <utility> |
| |
| namespace vvl { |
| // Partial implementation of std::span for C++11 |
| template <typename T, typename Iterator> |
| class enumeration { |
| public: |
| using pointer = T *; |
| using const_pointer = T const *; |
| using iterator = Iterator; |
| using const_iterator = const Iterator; |
| |
| enumeration() = default; |
| enumeration(pointer start, size_t n) : data_(start), count_(n) {} |
| template <typename Position> |
| enumeration(Position start, Position end) : data_(&(*start)), count_(end - start) {} |
| template <typename Container> |
| enumeration(Container &c) : data_(c.data()), count_(c.size()) {} |
| |
| iterator begin() { return data_; } |
| const_iterator begin() const { return data_; } |
| |
| iterator end() { return data_ + count_; } |
| const_iterator end() const { return data_ + count_; } |
| |
| T &operator[](size_t i) { return data_[i]; } |
| const T &operator[](size_t i) const { return data_[i]; } |
| |
| T &front() { return *data_; } |
| const T &front() const { return *data_; } |
| |
| T &back() { return *(data_ + (count_ - 1)); } |
| const T &back() const { return *(data_ + (count_ - 1)); } |
| |
| size_t size() const { return count_; } |
| bool empty() const { return count_ == 0; } |
| |
| pointer data() const { return data_; } |
| |
| private: |
| pointer data_ = {}; |
| size_t count_ = 0; |
| }; |
| |
| template <typename T, typename IndexType = size_t> |
| class IndexedIterator { |
| public: |
| IndexedIterator(T *data, IndexType index = 0) : index_(index), data_(data) {} |
| |
| std::pair<IndexType, T &> operator*() { return std::pair<IndexType, T &>(index_, *data_); } |
| std::pair<IndexType, T> operator*() const { return std::make_pair(index_, *data_); } |
| |
| // prefix increment |
| IndexedIterator<T, IndexType> &operator++() { |
| ++data_; |
| ++index_; |
| return *this; |
| } |
| |
| // postfix increment |
| IndexedIterator<T, IndexType> operator++(int) { |
| IndexedIterator<T, IndexType> old = *this; |
| operator++(); |
| return old; |
| } |
| |
| bool operator==(const IndexedIterator<T, IndexType> &rhs) const { |
| // No need to compare indices, just compare pointers |
| // And given the implementation of enumeration::end(), |
| // where no index is given when constructing an iterator, |
| // index_ will default to 0 for end(), which is wrong, but we can live with it for now |
| return data_ == rhs.data_; |
| } |
| bool operator!=(const IndexedIterator<T, IndexType> &rhs) const { return data_ != rhs.data_; } |
| |
| public: |
| IndexType index_ = 0; |
| T *data_; |
| }; |
| |
| template <typename T> |
| using span = enumeration<T, T *>; |
| |
| // |
| // Allow type inference that using the constructor doesn't allow in C++11 |
| template <typename T> |
| span<T> make_span(T *begin, size_t count) { |
| return span<T>(begin, count); |
| } |
| template <typename T> |
| span<T> make_span(T *begin, T *end) { |
| return make_span<T>(begin, end); |
| } |
| |
| template <typename Container> |
| auto make_span(Container &container) { |
| return span<typename Container::value_type>(container.data(), container.size()); |
| } |
| |
| template <typename Container> |
| auto make_span(const Container &container) { |
| return span<std::add_const_t<typename Container::value_type>>(container.data(), container.size()); |
| } |
| |
| template <typename T, typename IndexType> |
| auto enumerate(T *begin, IndexType count) { |
| return enumeration<T, IndexedIterator<T, IndexType>>(begin, count); |
| } |
| template <typename T> |
| auto enumerate(T *begin, T *end) { |
| return enumeration<T, IndexedIterator<T>>(begin, end); |
| } |
| |
| template <typename Container> |
| auto enumerate(Container &container) { |
| return enumeration<typename Container::value_type, |
| IndexedIterator<typename Container::value_type, typename Container::size_type>>(container.data(), |
| container.size()); |
| } |
| |
| template <typename Container> |
| auto enumerate(const Container &container) { |
| return enumeration<std::add_const_t<typename Container::value_type>, |
| IndexedIterator<std::add_const_t<typename Container::value_type>, typename Container::size_type>>( |
| container.data(), container.size()); |
| } |
| } // namespace vvl |