nngn
Loading...
Searching...
No Matches
ranges.h
Go to the documentation of this file.
1#ifndef NNGN_UTILS_RANGES_H
2#define NNGN_UTILS_RANGES_H
3
4#include <algorithm>
5#include <cassert>
6#include <cstring>
7#include <iterator>
8#include <numeric>
9#include <ranges>
10#include <span>
11#include <utility>
12
13#include "utils.h"
14
15namespace nngn {
16
17template<typename T>
18using const_iterator = decltype(std::ranges::cbegin(std::declval<T&>()));
19
20template<typename T>
21class owning_view {
22public:
23 constexpr owning_view(const T&) = delete;
24 constexpr explicit owning_view(T &r);
25 constexpr explicit owning_view(T &&r) : owning_view{r} {}
26 constexpr auto begin(void) const { return this->b; }
27 constexpr auto begin(void) { return this->b; }
28 constexpr auto end(void) const { return this->e; }
29 constexpr auto end(void) { return this->e; }
30private:
31 std::ranges::iterator_t<T> b, e;
32};
33
34template<typename T>
35inline constexpr owning_view<T>::owning_view(T &r) :
36 b{std::move(std::ranges::begin(r))},
37 e{std::move(std::ranges::end(r))}
38{}
39
40template<typename T>
41struct range_to {
42 template<std::ranges::range R>
43 friend auto operator|(R &&r, range_to) {
44 T ret = {};
45 if constexpr(std::ranges::sized_range<R>)
46 ret.reserve(std::ranges::size(FWD(r)));
47 for(auto &&x : FWD(r))
48 ret.push_back(x);
49 return ret;
50 }
51};
52
53constexpr auto *data_end(std::ranges::contiguous_range auto &&r) {
54 return std::data(r) + std::size(r);
55}
56
57/* TODO libc++
58constexpr auto enumerate(std::ranges::range auto &&r, auto i = std::size_t{}) {
59 return std::views::transform(
60 FWD(r), [i](auto &&x) mutable { return std::pair{i++, FWD(x)}; });
61} */
62
63template<typename T>
64void resize_and_init(T *p, std::size_t n, auto &&f) {
65 auto &v = *p;
66 const auto prev = v.size();
67 v.resize(n);
68 for(std::size_t i = prev; i < n; ++i)
69 FWD(f)(&v[i]);
70}
71
72template<typename V>
73void set_capacity(V *v, size_t n) {
74 if(n < v->capacity())
75 V{}.swap(*v);
76 return v->reserve(n);
77}
78
79template<std::size_t N>
80consteval auto to_array(const char *s) {
81 return [&s]<auto ...I>(std::index_sequence<I...>) {
82 return std::array{s[I]...};
83 }(std::make_index_sequence<N>{});
84}
85
86template<std::size_t N>
87consteval auto to_array(const char (&s)[N]) {
88 return to_array<N - 1>(static_cast<const char*>(s));
89}
90
91template<std::size_t N>
92consteval auto to_array(const std::ranges::contiguous_range auto &r) {
93 return to_array<N>(std::data(r));
94}
95
96template<std::size_t N, std::ranges::view V>
97consteval auto to_array(V &&v) {
98 using T = std::ranges::range_value_t<V>;
99 std::array<T, N> ret = {};
100 std::copy_n(std::ranges::begin(v), N, begin(ret));
101 return ret;
102}
103
104constexpr bool contains(
105 const std::ranges::contiguous_range auto &r, const auto &x)
106{
107 return std::ranges::less_equal{}(&*std::ranges::cbegin(r), &x)
108 && std::ranges::less{}(&x, &*std::ranges::cend(r));
109}
110
111constexpr bool in_range(
112 const std::ranges::contiguous_range auto &r, const auto &x)
113{
114 return std::ranges::less_equal{}(&*std::ranges::cbegin(r), &x)
115 && std::ranges::less_equal{}(&x, &*std::ranges::cend(r));
116}
117
118template<std::ranges::forward_range R, typename Proj = std::identity>
119constexpr bool is_sequence(R &&r, Proj proj = {}) {
120 return std::adjacent_find(
121 std::ranges::begin(FWD(r)), std::ranges::end(FWD(r)),
122 [proj]<typename T>(const T &lhs, const T &rhs) {
123 return proj(lhs) + proj(T{1}) != proj(rhs);
124 }
125 ) == end(FWD(r));
126}
127
128template<std::ranges::range R>
129constexpr void iota(R &&r, std::ranges::range_value_t<R> &&x = {}) {
130 std::iota(std::ranges::begin(r), std::ranges::end(r), FWD(x));
131}
132
133constexpr auto reduce(std::ranges::range auto &&r) {
134 return std::reduce(std::ranges::begin(r), std::ranges::end(r));
135}
136
137constexpr auto reduce(
138 std::ranges::range auto &&r, auto &&init = {}, auto &&op = std::plus<>{})
139{
140 return std::reduce(
141 std::ranges::begin(r), std::ranges::end(r),
142 FWD(init), FWD(op));
143}
144
145void const_time_erase(auto *v, auto *p) {
146 assert(contains(*v, *p));
147 auto last = v->end() - 1;
148 *p = std::move(*last);
149 v->erase(last);
150}
151
152template<
153 std::input_iterator I,
154 std::output_iterator<std::iter_value_t<I>> O>
155constexpr void fill_with_pattern(I f, I l, O df, O dl) {
156 std::generate(df, dl, [i = f, f, l](void) mutable {
157 if(i == l)
158 i = f;
159 return *i++;
160 });
161}
162
163constexpr void fill_with_pattern(
164 std::ranges::range auto &&p, std::ranges::range auto &&r)
165{
166 return fill_with_pattern(
167 std::ranges::begin(FWD(p)), std::ranges::end(FWD(p)),
168 std::ranges::begin(FWD(r)), std::ranges::end(FWD(r)));
169}
170
171template<typename T>
172constexpr T *memcpy(T *dst, std::ranges::contiguous_range auto &&r) {
173 const auto n = std::span{FWD(r)}.size_bytes();
174 std::memcpy(dst, std::data(FWD(r)), n);
175 return cast<char*>(dst) + n;
176}
177
178template<typename T>
179constexpr T *memmove(T *dst, std::ranges::contiguous_range auto &&r) {
180 const auto n = std::span{r}.size_bytes();
181 std::memmove(dst, std::data(FWD(r)), n);
182 return cast<char*>(dst) + n;
183}
184
185}
186
187namespace std::ranges {
188
189#ifdef DOXYGEN
190template<typename T> inline constexpr bool enable_view;
191template<typename T> inline constexpr bool enable_borrowed_range;
192#endif
193
195template<typename T>
196inline constexpr bool enable_view<nngn::owning_view<T>> = true;
197
199template<typename T>
200inline constexpr bool enable_borrowed_range<nngn::owning_view<T>> = true;
201
202}
203
204#endif
Definition: ranges.h:21
constexpr auto end(void) const
Definition: ranges.h:28
constexpr auto begin(void)
Definition: ranges.h:27
constexpr auto end(void)
Definition: ranges.h:29
std::ranges::iterator_t< T > b
Definition: ranges.h:31
constexpr auto begin(void) const
Definition: ranges.h:26
constexpr owning_view(const T &)=delete
constexpr owning_view(T &&r)
Definition: ranges.h:25
constexpr owning_view(T &r)
std::ranges::iterator_t< T > e
Definition: ranges.h:31
init
Definition: img_common.lua:34
function DEMO text end
Definition: demo0.lua:6
for i
Definition: font.lua:5
r
Definition: gamma.lua:7
N
Definition: gamma.lua:5
l
Definition: light.lua:23
assert
Definition: debug.lua:3
n
Definition: dump_lights.lua:5
move
Definition: camera.lua:48
p
Definition: input.lua:29
function f()) end
v[1]
Definition: math.lua:19
std::chrono::seconds s
Definition: timing.cpp:6
#define FWD(...)
Definition: utils.h:18
#define T(f0, f1, f2)
e
Definition: math.lua:4
Definition: audio.cpp:7
void const_time_erase(auto *v, auto *p)
Definition: ranges.h:145
constexpr const R * begin(const T< R > &v)
Definition: vec.h:207
constexpr auto * data_end(std::ranges::contiguous_range auto &&r)
Definition: ranges.h:53
constexpr auto reduce(std::ranges::range auto &&r)
Definition: ranges.h:133
consteval auto to_array(const char *s)
Definition: ranges.h:80
constexpr void fill_with_pattern(I f, I l, O df, O dl)
Definition: ranges.h:155
void set_capacity(V *v, size_t n)
Definition: ranges.h:73
constexpr bool in_range(const std::ranges::contiguous_range auto &r, const auto &x)
Definition: ranges.h:111
constexpr bool is_sequence(R &&r, Proj proj={})
Definition: ranges.h:119
constexpr void iota(R &&r, std::ranges::range_value_t< R > &&x={})
Definition: ranges.h:129
constexpr T * memcpy(T *dst, std::ranges::contiguous_range auto &&r)
Definition: ranges.h:172
typedef const_iterator
Definition: ranges.h:18
constexpr bool contains(const std::ranges::contiguous_range auto &r, const auto &x)
Definition: ranges.h:104
constexpr T * memmove(T *dst, std::ranges::contiguous_range auto &&r)
Definition: ranges.h:179
void resize_and_init(T *p, std::size_t n, auto &&f)
Definition: ranges.h:64
Definition: ranges.h:187
Definition: debug.h:13
Definition: ranges.h:41
friend auto operator|(R &&r, range_to)
Definition: ranges.h:43