1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
/* 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 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
|