C++ Essence Library 0.1.0
A Utility Library for Modern C++ Programming
Loading...
Searching...
No Matches
range.hpp
1/*
2 * Copyright (c) 2024 The RefValue Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#pragma once
24
25#include "char.hpp"
26
27#include <array>
28#include <concepts>
29#include <ranges>
30#include <span>
31#include <type_traits>
32
33namespace essence::detail {
40 template <std::ranges::range Range>
41 consteval auto get_range_value_t_or_self() noexcept {
42 return std::type_identity<std::ranges::range_value_t<Range>>{};
43 }
44
51 template <typename T>
52 consteval auto get_range_value_t_or_self() noexcept {
53 return std::type_identity<T>{};
54 }
55} // namespace essence::detail
56
57namespace essence {
58 template <typename T>
59 concept byte_like_contiguous_range = std::ranges::contiguous_range<T> && byte_like<std::ranges::range_value_t<T>>;
60
61 template <typename T>
62 concept extendable_contiguous_range = requires(T obj, std::size_t size, typename T::value_type value) {
63 requires std::ranges::contiguous_range<T>;
64 obj.clear();
65 obj.resize(size);
66 obj.shrink_to_fit();
67 obj.push_back(value);
68 };
69
74 template <typename T>
76 using type = typename decltype(detail::get_range_value_t_or_self<T>())::type;
77 };
78
83 template <typename T>
84 using range_value_t_or_self_t = typename range_value_t_or_self<T>::type;
85
86 template <byte_like_contiguous_range Range>
87 constexpr auto as_const_byte_span(Range&& range) noexcept {
88 // Deals with a narrow/UTF-8 string literal correctly (excluding the trailing null-terminating character).
89 if constexpr (std::convertible_to<Range, std::string_view>) {
90 const std::string_view view{range};
91
92 return std::span{reinterpret_cast<const std::byte*>(view.data()), view.size()};
93
94 } else if constexpr (std::convertible_to<Range, std::u8string_view>) {
95 const std::u8string_view view{range};
96
97 return std::span{reinterpret_cast<const std::byte*>(view.data()), view.size()};
98 } else {
99 return std::span{reinterpret_cast<const std::byte*>(std::ranges::cdata(range)),
100 std::ranges::size(range) * sizeof(std::ranges::range_value_t<Range>)};
101 }
102 }
103
112 template <std::ranges::forward_range Range, std::ranges::forward_range Delimiter>
113 requires(std::ranges::contiguous_range<std::ranges::range_value_t<Range>>
114 && std::ranges::contiguous_range<Delimiter>)
115 constexpr auto join_with(Range&& range, Delimiter&& delimiter) {
116 using cache_type =
117 std::array<std::span<const std::ranges::range_value_t<std::ranges::range_value_t<Range>>>, 2>;
118
119 cache_type cache;
120
121 cache.back() = std::span{std::ranges::data(delimiter), std::ranges::size(delimiter)};
122
123 auto adapter = range | std::views::transform([cache](const auto& inner) mutable {
124 cache.front() = std::span{std::ranges::data(inner), std::ranges::size(inner)};
125
126 return cache | std::views::join;
127 }) | std::views::join;
128
129 auto size = std::ranges::distance(adapter);
130
131 return adapter | std::views::take(size == 0 ? 0 : size - 1) | std::views::common;
132 }
133} // namespace essence
Definition char.hpp:36
Gets the type of range value, or the type itself if the type is non-ranged.
Definition range.hpp:75