WPILibC++ 2027.0.0-alpha-2
Loading...
Searching...
No Matches
slice.hpp
Go to the documentation of this file.
1// Copyright (c) Sleipnir contributors
2
3#pragma once
4
5#include <concepts>
6#include <limits>
7#include <utility>
8
11
12namespace slp {
13
14namespace slicing {
15
16/**
17 * Type tag used to designate an omitted argument of the slice.
18 */
19struct none_t {};
20
21/**
22 * Designates an omitted argument of the slice.
23 */
24static inline constexpr none_t _;
25
26} // namespace slicing
27
28/**
29 * Represents a sequence of elements in an iterable object.
30 */
32 public:
33 /// Start index (inclusive).
34 int start = 0;
35
36 /// Stop index (exclusive).
37 int stop = 0;
38
39 /// Step.
40 int step = 1;
41
42 /**
43 * Constructs a Slice.
44 */
45 constexpr Slice() = default;
46
47 /**
48 * Constructs a slice.
49 */
50 constexpr Slice(slicing::none_t) // NOLINT
51 : Slice(0, std::numeric_limits<int>::max(), 1) {}
52
53 /**
54 * Constructs a slice.
55 *
56 * @param start Slice start index (inclusive).
57 */
58 constexpr Slice(int start) { // NOLINT
59 this->start = start;
60 this->stop = (start == -1) ? std::numeric_limits<int>::max() : start + 1;
61 this->step = 1;
62 }
63
64 /**
65 * Constructs a slice.
66 *
67 * @param start Slice start index (inclusive).
68 * @param stop Slice stop index (exclusive).
69 */
70 template <typename Start, typename Stop>
71 requires(std::same_as<Start, slicing::none_t> ||
72 std::convertible_to<Start, int>) &&
73 (std::same_as<Stop, slicing::none_t> ||
74 std::convertible_to<Stop, int>)
75 constexpr Slice(Start start, Stop stop)
76 : Slice(std::move(start), std::move(stop), 1) {}
77
78 /**
79 * Constructs a slice.
80 *
81 * @param start Slice start index (inclusive).
82 * @param stop Slice stop index (exclusive).
83 * @param step Slice step.
84 */
85 template <typename Start, typename Stop, typename Step>
86 requires(std::same_as<Start, slicing::none_t> ||
87 std::convertible_to<Start, int>) &&
88 (std::same_as<Stop, slicing::none_t> ||
89 std::convertible_to<Stop, int>) &&
90 (std::same_as<Step, slicing::none_t> ||
91 std::convertible_to<Step, int>)
92 constexpr Slice(Start start, Stop stop, Step step) {
93 if constexpr (std::same_as<Step, slicing::none_t>) {
94 this->step = 1;
95 } else {
96 slp_assert(step != 0);
97
98 this->step = step;
99 }
100
101 // Avoid UB for step = -step if step is INT_MIN
102 if (this->step == std::numeric_limits<int>::min()) {
103 this->step = -std::numeric_limits<int>::max();
104 }
105
106 if constexpr (std::same_as<Start, slicing::none_t>) {
107 if (this->step < 0) {
108 this->start = std::numeric_limits<int>::max();
109 } else {
110 this->start = 0;
111 }
112 } else {
113 this->start = start;
114 }
115
116 if constexpr (std::same_as<Stop, slicing::none_t>) {
117 if (this->step < 0) {
118 this->stop = std::numeric_limits<int>::min();
119 } else {
120 this->stop = std::numeric_limits<int>::max();
121 }
122 } else {
123 this->stop = stop;
124 }
125 }
126
127 /**
128 * Adjusts start and end slice indices assuming a sequence of the specified
129 * length.
130 *
131 * @param length The sequence length.
132 * @return The slice length.
133 */
134 constexpr int adjust(int length) {
135 slp_assert(step != 0);
136 slp_assert(step >= -std::numeric_limits<int>::max());
137
138 if (start < 0) {
139 start += length;
140
141 if (start < 0) {
142 start = (step < 0) ? -1 : 0;
143 }
144 } else if (start >= length) {
145 start = (step < 0) ? length - 1 : length;
146 }
147
148 if (stop < 0) {
149 stop += length;
150
151 if (stop < 0) {
152 stop = (step < 0) ? -1 : 0;
153 }
154 } else if (stop >= length) {
155 stop = (step < 0) ? length - 1 : length;
156 }
157
158 if (step < 0) {
159 if (stop < start) {
160 return (start - stop - 1) / -step + 1;
161 } else {
162 return 0;
163 }
164 } else {
165 if (start < stop) {
166 return (stop - start - 1) / step + 1;
167 } else {
168 return 0;
169 }
170 }
171 }
172};
173
174} // namespace slp
#define slp_assert(condition)
Abort in C++.
Definition assert.hpp:26
Represents a sequence of elements in an iterable object.
Definition slice.hpp:31
constexpr Slice()=default
Constructs a Slice.
constexpr Slice(Start start, Stop stop)
Constructs a slice.
Definition slice.hpp:75
constexpr Slice(slicing::none_t)
Constructs a slice.
Definition slice.hpp:50
constexpr int adjust(int length)
Adjusts start and end slice indices assuming a sequence of the specified length.
Definition slice.hpp:134
constexpr Slice(Start start, Stop stop, Step step)
Constructs a slice.
Definition slice.hpp:92
constexpr Slice(int start)
Constructs a slice.
Definition slice.hpp:58
static constexpr none_t _
Designates an omitted argument of the slice.
Definition slice.hpp:24
Definition expression_graph.hpp:11
Definition PointerIntPair.h:280
Type tag used to designate an omitted argument of the slice.
Definition slice.hpp:19
#define SLEIPNIR_DLLEXPORT
Definition symbol_exports.hpp:34