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