MT Core (C++)
Core library for replacing C++ standard in project usage
Loading...
Searching...
No Matches
colls/slice.hpp
Go to the documentation of this file.
1/*
2
3Copyright 2025 Matthew Tolman
4
5Licensed under the Apache License, Version 2.0 (the "License");
6you may not use this file except in compliance with the License.
7You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11Unless required by applicable law or agreed to in writing, software
12distributed under the License is distributed on an "AS IS" BASIS,
13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14See the License for the specific language governing permissions and
15limitations under the License.
16
17*/
18
19#pragma once
20
21#ifndef MTCORE_SLICE_HPP
22#define MTCORE_SLICE_HPP
23
24#include "../core.hpp"
25#include "../traits.hpp"
26#include "iter.hpp"
27#include "optional.hpp"
28#include <string>
29#include <vector>
30
31namespace mtcore {
45 template<class T>
46 struct Slice {
47 using Elem = T;
48
49 T *head = nullptr;
50 size_t len = 0;
51
52 [[nodiscard]] decltype(auto) ptr_iter() noexcept { return iter::ptr(*this); }
53 [[nodiscard]] decltype(auto) ptr_iter() const noexcept { return iter::const_ptr(*this); }
54 [[nodiscard]] decltype(auto) iter() const noexcept { return iter::val(*this); }
55
57 [[nodiscard]] constexpr Slice<std::add_const_t<T>> to_const() const noexcept {
58 return {static_cast<std::add_pointer_t<std::add_const_t<T>>>(head), len};
59 }
60
69 constexpr void init(T *head, size_t len) {
70 this->head = head;
71 this->len = len;
72 }
73
79 [[nodiscard]] constexpr const T &operator[](size_t i) const noexcept {
80 ensure(i < len, "SLICE ACCESS OUT OF BOUNDS");
81 ensure(head, "NULL POINTER DEREFERENCE");
82 return head[i];
83 }
84
90 T &operator[](size_t i) noexcept {
91 ensure(i < len, "SLICE ACCESS OUT OF BOUNDS");
92 ensure(head, "NULL POINTER DEREFERENCE");
93 return head[i];
94 }
95
101 [[nodiscard]] T &at(size_t i) noexcept { return (*this)[i]; }
102
108 [[nodiscard]] constexpr const T &at(size_t i) const noexcept { return (*this)[i]; }
109
113 [[nodiscard]] constexpr size_t size() const noexcept { return head != nullptr ? len : 0; }
114
118 [[nodiscard]] constexpr bool empty() const noexcept { return head == nullptr || len == 0; }
119
125 [[nodiscard]] constexpr Slice sub_rng(size_t start, size_t end) const noexcept {
126 if (start >= end || start >= len) {
127 Slice res;
128 res.init(nullptr, 0);
129 return res;
130 }
131 return sub(start, end - start);
132 }
133
138 [[nodiscard]] constexpr Slice sub(size_t start) const noexcept {
139 Slice res;
140 if (start >= len) {
141 res.init(nullptr, 0);
142 return res;
143 }
144
145 res.init(head + start, len - start);
146 ensure(res.len + start == len, "BAD LENGTH MATH");
147 ensure(head + len == res.head + res.len, "BAD END POINTER");
148 return res;
149 }
150
156 [[nodiscard]] constexpr Slice sub(size_t start, size_t len) const noexcept {
157 auto res = sub(start);
158 res.len = res.len > len ? len : res.len;
159 ensure(res.len <= len, "BAD LENGTH");
160 return res;
161 }
162
168 std::strong_ordering operator<=>(const Slice<std::remove_const_t<T>> &other) const noexcept {
169 return *this <=> other.to_const();
170 }
171
177 std::strong_ordering operator<=>(const Slice<std::add_const_t<T>> &other) const noexcept {
178 if (empty() && other.empty()) {
179 return std::strong_ordering::equal;
180 }
181
182 if (empty()) {
183 return std::strong_ordering::less;
184 }
185
186 if (other.empty()) {
187 return std::strong_ordering::greater;
188 }
189
190 for (size_t i = 0; i < len && i < other.len; ++i) {
191 if (head[i] > other.head[i]) {
192 return std::strong_ordering::greater;
193 }
194 if (head[i] < other.head[i]) {
195 return std::strong_ordering::less;
196 }
197 }
198
199 if (len == other.len) {
200 return std::strong_ordering::equal;
201 }
202 else if (len < other.len) {
203 return std::strong_ordering::less;
204 }
205 else {
206 return std::strong_ordering::greater;
207 }
208 }
209
210 bool operator==(const Slice<std::remove_const_t<T>> &o) const noexcept {
211 return (*this <=> o) == std::strong_ordering::equal;
212 }
213
214 bool operator!=(const Slice<std::remove_const_t<T>> &o) const noexcept {
215 return (*this <=> o) != std::strong_ordering::equal;
216 }
217
218 bool operator<(const Slice<std::remove_const_t<T>> &o) const noexcept {
219 return (*this <=> o) == std::strong_ordering::less;
220 }
221
222 bool operator>(const Slice<std::remove_const_t<T>> &o) const noexcept {
223 return (*this <=> o) == std::strong_ordering::greater;
224 }
225
226 bool operator<=(const Slice<std::remove_const_t<T>> &o) const noexcept {
227 const auto cmp = *this <=> o;
228 return (cmp == std::strong_ordering::less || cmp == std::strong_ordering::equal);
229 }
230
231 bool operator>=(const Slice<std::remove_const_t<T>> &o) const noexcept {
232 const auto cmp = *this <=> o;
233 return (cmp == std::strong_ordering::greater || cmp == std::strong_ordering::equal);
234 }
235
236 bool operator==(const Slice<std::add_const_t<T>> &o) const noexcept {
237 return (*this <=> o) == std::strong_ordering::equal;
238 }
239
240 bool operator!=(const Slice<std::add_const_t<T>> &o) const noexcept {
241 return (*this <=> o) != std::strong_ordering::equal;
242 }
243
244 bool operator<(const Slice<std::add_const_t<T>> &o) const noexcept {
245 return (*this <=> o) == std::strong_ordering::less;
246 }
247
248 bool operator>(const Slice<std::add_const_t<T>> &o) const noexcept {
249 return (*this <=> o) == std::strong_ordering::greater;
250 }
251
252 bool operator<=(const Slice<std::add_const_t<T>> &o) const noexcept {
253 const auto cmp = *this <=> o;
254 return (cmp == std::strong_ordering::less || cmp == std::strong_ordering::equal);
255 }
256
257 bool operator>=(const Slice<std::add_const_t<T>> &o) const noexcept {
258 const auto cmp = *this <=> o;
259 return (cmp == std::strong_ordering::greater || cmp == std::strong_ordering::equal);
260 }
261 };
262
268 [[nodiscard]] constexpr Slice<char32_t> mut_slice_from(char32_t *cstr, size_t len) {
269 return Slice<char32_t>{(cstr), len};
270 }
271
277 [[nodiscard]] constexpr Slice<char32_t> mut_slice_from(char32_t *cstr) {
278 if (!cstr) {
279 return Slice<char32_t>{(cstr), 0};
280 }
281 size_t len = 0;
282 for (; cstr[len]; ++len) {}
283 return Slice<char32_t>{(cstr), len};
284 }
285
291 [[nodiscard]] constexpr Slice<const char32_t> slice_from(char32_t *cstr) {
292 if (!cstr) {
293 return Slice<const char32_t>{static_cast<const char32_t *>(cstr), 0};
294 }
295 size_t len = 0;
296 for (; cstr[len]; ++len) {}
297 return Slice<const char32_t>{static_cast<const char32_t *>(cstr), len};
298 }
299
305 [[nodiscard]] constexpr Slice<const char32_t> slice_from(char32_t *cstr, size_t len) {
306 return Slice<const char32_t>{static_cast<const char32_t *>(cstr), len};
307 }
308
314 [[nodiscard]] constexpr Slice<const char32_t> slice_from(const char32_t *cstr, size_t len) {
315 return Slice<const char32_t>{cstr, len};
316 }
317
323 [[nodiscard]] constexpr Slice<const char32_t> slice_from(const char32_t *cstr) {
324 if (!cstr) {
325 return Slice<const char32_t>{cstr, 0};
326 }
327 size_t len = 0;
328 for (; cstr[len]; ++len) {}
329 return Slice<const char32_t>{cstr, len};
330 }
331
337 [[nodiscard]] constexpr Slice<char16_t> mut_slice_from(char16_t *cstr, size_t len) {
338 return Slice<char16_t>{cstr, len};
339 }
340
346 [[nodiscard]] constexpr Slice<const char16_t> slice_from(char16_t *cstr, size_t len) {
347 return Slice<const char16_t>{static_cast<const char16_t *>(cstr), len};
348 }
349
355 [[nodiscard]] constexpr Slice<const char16_t> slice_from(const char16_t *cstr, size_t len) {
356 return Slice<const char16_t>{cstr, len};
357 }
358
364 [[nodiscard]] constexpr Slice<char8_t> mut_slice_from(char8_t *cstr, size_t len) { return Slice<char8_t>{cstr, len}; }
365
371 [[nodiscard]] constexpr Slice<const char8_t> slice_from(char8_t *cstr, size_t len) {
372 return Slice<const char8_t>{static_cast<const char8_t *>(cstr), len};
373 }
374
380 [[nodiscard]] constexpr Slice<const char8_t> slice_from(const char8_t *cstr, size_t len) {
381 return Slice<const char8_t>{cstr, len};
382 }
383
389 [[nodiscard]] constexpr Slice<char16_t> mut_slice_from(char16_t *cstr) {
390 if (!cstr) {
391 return Slice<char16_t>{(cstr), 0};
392 }
393 size_t len = 0;
394 for (; cstr[len]; ++len) {}
395 return Slice<char16_t>{(cstr), len};
396 }
397
403 [[nodiscard]] constexpr Slice<const char16_t> slice_from(char16_t *cstr) {
404 if (!cstr) {
405 return Slice<const char16_t>{static_cast<const char16_t *>(cstr), 0};
406 }
407 size_t len = 0;
408 for (; cstr[len]; ++len) {}
409 return Slice<const char16_t>{static_cast<const char16_t *>(cstr), len};
410 }
411
417 [[nodiscard]] constexpr Slice<const char16_t> slice_from(const char16_t *cstr) {
418 if (!cstr) {
419 return Slice<const char16_t>{cstr, 0};
420 }
421 size_t len = 0;
422 for (; cstr[len]; ++len) {}
423 return Slice<const char16_t>{cstr, len};
424 }
425
431 [[nodiscard]] constexpr Slice<char8_t> mut_slice_from(char8_t *cstr) {
432 if (!cstr) {
433 return Slice<char8_t>{(cstr), 0};
434 }
435 size_t len = 0;
436 for (; cstr[len]; ++len) {}
437 return Slice<char8_t>{(cstr), len};
438 }
439
445 [[nodiscard]] constexpr Slice<const char8_t> slice_from(char8_t *cstr) {
446 if (!cstr) {
447 return Slice<const char8_t>{static_cast<const char8_t *>(cstr), 0};
448 }
449 size_t len = 0;
450 for (; cstr[len]; ++len) {}
451 return Slice<const char8_t>{static_cast<const char8_t *>(cstr), len};
452 }
453
459 [[nodiscard]] constexpr Slice<const char8_t> slice_from(const char8_t *cstr) {
460 if (!cstr) {
461 return Slice<const char8_t>{cstr, 0};
462 }
463 size_t len = 0;
464 for (; cstr[len]; ++len) {}
465 return Slice<const char8_t>{cstr, len};
466 }
467
473 [[nodiscard]] constexpr Slice<const char> slice_from(char *cstr) {
474 if (!cstr) {
475 return Slice<const char>{static_cast<const char *>(cstr), 0};
476 }
477 size_t len = 0;
478 for (; cstr[len]; ++len) {}
479 return Slice<const char>{static_cast<const char *>(cstr), len};
480 }
481
487 [[nodiscard]] constexpr Slice<const char> slice_from(const char *cstr) {
488 if (!cstr) {
489 return Slice<const char>{cstr, 0};
490 }
491 size_t len = 0;
492 for (; cstr[len]; ++len) {}
493 return Slice<const char>{cstr, len};
494 }
495
501 [[nodiscard]] constexpr Slice<const char> slice_from(char *cstr, const size_t len) {
502 return Slice<const char>{static_cast<const char *>(cstr), len};
503 }
504
510 [[nodiscard]] constexpr Slice<char> mut_slice_from(char *cstr, const size_t len) { return Slice<char>{cstr, len}; }
511
517 [[nodiscard]] constexpr Slice<const char> slice_from(const char *cstr, const size_t len) {
518 return Slice<const char>{cstr, len};
519 }
520
526 [[nodiscard]] inline Slice<const char> slice_from(const std::string &str) {
527 return Slice<const char>{str.c_str(), str.size()};
528 }
529
535 [[nodiscard]] constexpr Slice<const char> slice_from(const std::string_view &sv) {
536 return Slice<const char>{&sv[0], sv.size()};
537 }
538
544 template<typename T>
545 [[nodiscard]] Slice<std::add_const_t<T>> slice_from(const std::vector<T> &arr) {
546 return Slice<std::add_const<T>>{static_cast<std::add_pointer_t<std::add_const_t<T>>>(arr.data()), arr.size()};
547 }
548
554 template<typename T>
555 [[nodiscard]] Slice<T> mut_slice_from(std::vector<T> &arr) {
556 return Slice<T>{arr.data(), arr.size()};
557 }
558
564 template<typename T, size_t N>
565 [[nodiscard]] constexpr Slice<std::add_const_t<T>> slice_from(const std::array<T, N> &arr) {
566 return Slice<std::add_const_t<T>>{static_cast<std::add_pointer_t<std::add_const_t<T>>>(arr.data()), arr.size()};
567 }
568
574 template<typename T, size_t N>
575 [[nodiscard]] constexpr Slice<T> mut_slice_from(std::array<T, N> &arr) {
576 return Slice<T>{arr.data(), arr.size()};
577 }
578
584 [[nodiscard]] inline Slice<char> mut_slice_from(char *cstr) {
585 if (!cstr) {
586 return Slice<char>{cstr, 0};
587 }
588 size_t len = 0;
589 for (; cstr[len]; ++len) {}
590 return Slice<char>{cstr, len};
591 }
592
598 [[nodiscard]] inline Slice<char> mut_slice_from(std::string &str) { return Slice<char>{str.data(), str.size()}; }
599
609 template<typename Left, typename Right>
610 std::strong_ordering str_compare(const Left &left, const Right &right) {
611 using L = std::decay_t<std::remove_cv_t<Left>>;
612 using R = std::decay_t<std::remove_cv_t<Right>>;
613 static_assert(std::same_as<Slice<char>, L> || std::same_as<Slice<const char>, L> || std::same_as<std::string, L> ||
614 std::same_as<std::string_view, L> || std::same_as<char *, L> || std::same_as<const char *, L>);
615 static_assert(std::same_as<Slice<char>, R> || std::same_as<Slice<const char>, R> || std::same_as<std::string, R> ||
616 std::same_as<std::string_view, R> || std::same_as<char *, R> || std::same_as<const char *, R>);
617
618 Slice<const char> leftSlice;
619 if constexpr (std::is_same_v<Slice<const char>, L>) {
620 leftSlice = left;
621 }
622 else if constexpr (std::is_same_v<Slice<char>, L>) {
623 leftSlice = left.to_const();
624 }
625 else {
626 leftSlice = slice_from(left);
627 }
628
629 Slice<const char> rightSlice;
630 if constexpr (std::is_same_v<Slice<const char>, R>) {
631 rightSlice = right;
632 }
633 else if constexpr (std::is_same_v<Slice<char>, R>) {
634 rightSlice = right.to_const();
635 }
636 else {
637 rightSlice = slice_from(right);
638 }
639
640 return leftSlice <=> rightSlice;
641 }
642
652 template<typename L, typename R>
653 bool str_equal(const L &left, const R &right) {
654 return str_compare(left, right) == std::strong_ordering::equal;
655 }
656} // namespace mtcore
657
658#endif // MTCORE_SLICE_HPP
constexpr Slice< char32_t > mut_slice_from(char32_t *cstr, size_t len)
Creates a mutable slice from a utf32 string and length.
ValIter< T > val(const T &r)
Generic value iterator that uses the operator[] and incrementing indexes to iterate over a collection...
Definition iter.hpp:114
ConstPtrIter< T > const_ptr(const T &r)
Generic constant pointer iterator that uses the operator[] and incrementing indexes to iterate over a...
Definition iter.hpp:128
PtrIter< T > ptr(T &r)
Generic pointer iterator that uses the operator[] and incrementing indexes to iterate over a collecti...
Definition iter.hpp:101
constexpr Slice< const char32_t > slice_from(char32_t *cstr)
Creates a slice from a utf32 string in the form of a c string.
#define ensure(check,...)
Ensures that a check holds true, aborts the program if not true Will print error if the condition is ...
Core library for C++ with Zig-related functionality.
std::strong_ordering str_compare(const Left &left, const Right &right)
Compares two string strings for ordering.
bool str_equal(const L &left, const R &right)
Compares two string strings for ordering.
A Slice which is just a pointer + length Accessing elements through the array operator will do bounds...
T & operator[](size_t i) noexcept
Access element at a specific index Non-const operator, returns a mutable reference.
constexpr void init(T *head, size_t len)
Initializes a Slice Using init instead of a constructor so that slices allocated with malloc or an ar...
decltype(auto) ptr_iter() const noexcept
constexpr Slice sub_rng(size_t start, size_t end) const noexcept
Gets a sub slice from start to end index.
constexpr Slice sub(size_t start) const noexcept
Gets a sub Slice from start.
bool operator>=(const Slice< std::remove_const_t< T > > &o) const noexcept
constexpr size_t size() const noexcept
Gets the size of a Slice.
decltype(auto) ptr_iter() noexcept
bool operator!=(const Slice< std::remove_const_t< T > > &o) const noexcept
constexpr bool empty() const noexcept
Checks if a Slice is empty.
constexpr const T & operator[](size_t i) const noexcept
Access element at a specific index Const operator, returns a const reference.
std::strong_ordering operator<=>(const Slice< std::remove_const_t< T > > &other) const noexcept
Compares against another Slice.
std::remove_const_t< ReadElem > * head
bool operator!=(const Slice< std::add_const_t< T > > &o) const noexcept
bool operator==(const Slice< std::add_const_t< T > > &o) const noexcept
bool operator<(const Slice< std::remove_const_t< T > > &o) const noexcept
bool operator<(const Slice< std::add_const_t< T > > &o) const noexcept
bool operator<=(const Slice< std::remove_const_t< T > > &o) const noexcept
constexpr const T & at(size_t i) const noexcept
Access element at a specific index Const operator, returns a const reference.
bool operator<=(const Slice< std::add_const_t< T > > &o) const noexcept
std::strong_ordering operator<=>(const Slice< std::add_const_t< T > > &other) const noexcept
Compares against another Slice.
constexpr Slice sub(size_t start, size_t len) const noexcept
Gets a sub Slice from start up to a length.
bool operator>=(const Slice< std::add_const_t< T > > &o) const noexcept
bool operator==(const Slice< std::remove_const_t< T > > &o) const noexcept
bool operator>(const Slice< std::add_const_t< T > > &o) const noexcept
bool operator>(const Slice< std::remove_const_t< T > > &o) const noexcept
constexpr Slice< std::add_const_t< T > > to_const() const noexcept
Converts to a const Slice.
decltype(auto) iter() const noexcept
T & at(size_t i) noexcept
Access element at a specific index Non-const operator, returns a mutable reference.