AsmGrader 0.0.0
Loading...
Searching...
No Matches
static_string.hpp
Go to the documentation of this file.
1// Inspired by, but heavily modified from, https://blog.ganets.ky/StaticString/
2// In accordance with above mentioned site's licensing:
3//
4// The MIT License (MIT)
5// Copyright (c) 2013-2018 Blackrock Digital LLC
6//
7// Permission is hereby granted, free of charge, to any person obtaining a copy
8// of this software and associated documentation files (the "Software"), to deal
9// in the Software without restriction, including without limitation the rights
10// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11// copies of the Software, and to permit persons to whom the Software is
12// furnished to do so, subject to the following conditions:
13//
14// The above copyright notice and this permission notice shall be included in
15// all copies or substantial portions of the Software.
16//
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23// THE SOFTWARE.
24
25#pragma once
26
28
29#include <fmt/base.h>
30#include <fmt/compile.h>
31#include <fmt/format.h>
32#include <fmt/ranges.h>
33#include <libassert/assert.hpp>
34#include <range/v3/algorithm/copy.hpp>
35#include <range/v3/algorithm/copy_if.hpp>
36#include <range/v3/algorithm/copy_n.hpp>
37#include <range/v3/algorithm/find.hpp>
38#include <range/v3/range/access.hpp>
39#include <range/v3/range/concepts.hpp>
40#include <range/v3/view/subrange.hpp>
41
42#include <algorithm>
43#include <array>
44#include <concepts>
45#include <cstddef>
46#include <iterator>
47#include <limits>
48#include <string>
49#include <string_view>
50#include <type_traits>
51#include <utility>
52
53namespace asmgrader {
54
57template <std::size_t Size>
59{
60public:
61 constexpr StaticString() = default;
62
63 // NOLINTNEXTLINE(google-explicit-constructor,*-avoid-c-arrays)
64 constexpr /*implicit*/ StaticString(const char (&input)[Size + 1]) {
65 if (input[Size] != '\0') {
66 throw;
67 }
68 ranges::copy_n(std::data(input), Size + 1, data.begin());
69 }
70
72 // NOLINTNEXTLINE(google-explicit-constructor)
73 constexpr /*implicit*/ StaticString(const ranges::forward_range auto& rng) {
74 ranges::copy_n(ranges::begin(rng), Size, data.begin());
75
76 data.back() = '\0';
77 }
78
79 std::array<char, Size + 1> data{};
80
81 template <std::size_t Pos, std::size_t Len = std::numeric_limits<std::size_t>::max()>
82 requires(Pos <= Size)
83 constexpr auto substr() const {
84 // exclude '\0' from ctor call
85 constexpr auto end = std::min(Size, Pos + Len);
86 constexpr auto substr_size = std::min(Size - Pos, Len);
87
88 return StaticString<substr_size>{ranges::subrange{data.begin() + Pos, data.begin() + end}};
89 }
90
91 template <std::size_t N>
92 requires(N <= Size)
94 // exclude '\0' from ctor call
95 return {ranges::subrange{data.begin() + N, data.end() - 1}};
96 }
97
98 template <std::size_t N>
99 requires(N <= Size)
101 // exclude '\0' from ctor call
102 return {ranges::subrange{data.begin(), data.end() - 1 - N}};
103 }
104
105 template <typename Range>
106 constexpr auto operator+(const Range& rhs) const {
107 constexpr auto n = [] {
108 constexpr auto rng_sz = get_static_size<Range>();
109 using std::get;
110 if constexpr (std::is_array_v<std::remove_cvref_t<Range>>) {
111 return rng_sz - 1;
112 }
113 return rng_sz;
114 }();
115
117
118 ranges::copy_n(data.begin(), Size, result.data.begin());
119
120 if constexpr (std::same_as<Range, StaticString<n>>) {
121 ranges::copy_n(rhs.data.begin(), n, result.data.begin() + Size);
122 } else {
123 ranges::copy_n(ranges::begin(rhs), n, result.data.begin() + Size);
124 }
125
126 return result;
127 }
128
129 constexpr std::size_t size() const { return Size; }
130
131 constexpr auto begin() { return data.begin(); }
132
133 constexpr auto begin() const { return data.cbegin(); }
134
135 constexpr auto cbegin() const { return data.cbegin(); }
136
137 constexpr auto end() { return data.end() - 1; }
138
139 constexpr auto end() const { return data.cend() - 1; }
140
141 constexpr auto cend() const { return data.cend() - 1; }
142
143 // NOLINTNEXTLINE(google-explicit-constructor)
144 constexpr /*implicit*/ operator std::string_view() const { return data.data(); }
145
146 std::string str() const { return data.data(); }
147
148 constexpr char operator[](std::size_t i) const {
149 ASSERT(i < Size);
150 return data[i];
151 }
152
153 constexpr char& operator[](std::size_t i) {
154 ASSERT(i < Size);
155 return data[i];
156 }
157
158 constexpr char at(std::size_t i) const { return data.at(i); }
159
160 constexpr char& at(std::size_t i) { return data.at(i); }
161
162 template <std::size_t OtherSize>
163 constexpr auto operator<=>(const StaticString<OtherSize>& rhs) const {
164 return std::string_view{*this} <=> std::string_view{rhs};
165 }
166
167 // Support comparison with string_view-convertable objects
168 constexpr auto operator<=>(std::string_view rhs) const { return std::string_view{*this} <=> rhs; }
169
170 template <std::size_t OtherSize>
171 constexpr bool operator==(const StaticString<OtherSize>& rhs) const {
172 return std::string_view{*this} == std::string_view{rhs};
173 }
174
175 // Support comparison with string_view-convertable objects
176 constexpr bool operator==(std::string_view rhs) const { return std::string_view{*this} == rhs; }
177};
178
179// Deduction guide
180template <std::size_t N>
181// NOLINTNEXTLINE(*-avoid-c-arrays)
182StaticString(const char (&input)[N]) -> StaticString<N - 1>;
183
184template <StaticString Fmt, std::size_t MaxSz = 10 * 1'024, fmt::formattable... Args>
185constexpr auto static_format(Args&&... args) {
186 constexpr auto compiled_fmt = FMT_COMPILE(Fmt.data.begin());
187
188 StaticString<MaxSz> result;
189
190 fmt::format_to(result.data.begin(), compiled_fmt, std::forward<Args>(args)...);
191
192 return result;
193}
194
195template <std::size_t N>
196constexpr std::string_view format_as(const StaticString<N>& str) {
197 return str;
198}
199
200namespace literals {
201
202template <StaticString String>
203consteval auto operator""_static() {
204 return String;
205}
206
207} // namespace literals
208
209} // namespace asmgrader
210
211namespace std {
212
214template <std::size_t Size>
215// See: https://en.cppreference.com/w/cpp/utility/tuple_size.html
216// NOLINTNEXTLINE(cert-dcl58-cpp) - this is well defined and probably a clang-tidy bug
217struct tuple_size<::asmgrader::StaticString<Size>> : public std::integral_constant<std::size_t, Size>
218{
219};
220
222template <std::size_t I, std::size_t Size>
223 requires(I < Size)
224// See: https://en.cppreference.com/w/cpp/container/array/tuple_element.html
225// NOLINTNEXTLINE(cert-dcl58-cpp) - this is well defined and probably a clang-tidy bug
226struct tuple_element<I, ::asmgrader::StaticString<Size>>
227{
228 using type = char;
229};
230
231} // namespace std
232
233namespace asmgrader {
234
236template <std::size_t I, std::size_t Size>
237 requires(I < Size)
238constexpr char get(const ::asmgrader::StaticString<Size>& str) {
239 return str.at(I);
240}
241
242} // namespace asmgrader
243
244// Testbed for {fmt} stuff as it's been really annoying to fix this:
245// https://godbolt.org/z/6158EMoz3
246
247// Disable range formatting for StaticString to prevent ambiguity
248template <std::size_t N, typename CharType>
249struct fmt::is_range<asmgrader::StaticString<N>, CharType> : std::false_type
250{
251};
252
253// Disable tuple formatting for StaticString to prevent ambiguity
254template <std::size_t N>
255struct fmt::is_tuple_like<asmgrader::StaticString<N>> : std::false_type
256{
257};
A fully compile-time capable string type Guaranteed to be null-terminated.
Definition static_string.hpp:59
constexpr auto substr() const
Definition static_string.hpp:83
constexpr auto end() const
Definition static_string.hpp:139
constexpr char & at(std::size_t i)
Definition static_string.hpp:160
constexpr bool operator==(std::string_view rhs) const
Definition static_string.hpp:176
std::string str() const
Definition static_string.hpp:146
constexpr auto begin() const
Definition static_string.hpp:133
constexpr char & operator[](std::size_t i)
Definition static_string.hpp:153
constexpr auto begin()
Definition static_string.hpp:131
constexpr StaticString< Size - N > remove_prefix() const
Definition static_string.hpp:93
constexpr auto operator+(const Range &rhs) const
Definition static_string.hpp:106
constexpr StaticString< Size - N > remove_suffix() const
Definition static_string.hpp:100
std::array< char, Size+1 > data
Definition static_string.hpp:79
constexpr auto cend() const
Definition static_string.hpp:141
constexpr char operator[](std::size_t i) const
Definition static_string.hpp:148
constexpr auto cbegin() const
Definition static_string.hpp:135
constexpr StaticString(const ranges::forward_range auto &rng)
Do not include '\0'.
Definition static_string.hpp:73
constexpr bool operator==(const StaticString< OtherSize > &rhs) const
Definition static_string.hpp:171
constexpr std::size_t size() const
Definition static_string.hpp:129
constexpr auto operator<=>(std::string_view rhs) const
Definition static_string.hpp:168
constexpr auto end()
Definition static_string.hpp:137
constexpr auto operator<=>(const StaticString< OtherSize > &rhs) const
Definition static_string.hpp:163
constexpr StaticString()=default
constexpr StaticString(const char(&input)[Size+1])
Definition static_string.hpp:64
constexpr char at(std::size_t i) const
Definition static_string.hpp:158
Definition asm_buffer.hpp:20
consteval std::size_t get_static_size()
Definition static_size.hpp:19
constexpr char get(const ::asmgrader::StaticString< Size > &str)
Specialization of get to play nice with algorithms that work on tuple-like types.
Definition static_string.hpp:238
constexpr std::string_view format_as(const StaticString< N > &str)
Definition static_string.hpp:196
constexpr auto static_format(Args &&... args)
Definition static_string.hpp:185
StaticString(const char(&input)[N]) -> StaticString< N - 1 >
Definition byte_array.hpp:94
#define N
Definition test_macros.hpp:147