native 0.0.1
Vectors, masks and wide register packs for C++26
Loading...
Searching...
No Matches
native.static_string.ccm
Go to the documentation of this file.
1module;
2#include <native/attributes.h>
3#include <concepts>
4#include <cstddef>
5#include <functional>
6#include <iterator>
7#include <ostream>
8#include <ranges>
9#include <string>
10#include <string_view>
11#include <type_traits>
12#include <utility>
13
21
22export module native.static_string;
23
24export namespace native {
25
26namespace detail {
27 template<class T>
28 concept static_character = std::same_as<T, char> || std::same_as<T, wchar_t> ||
29 std::same_as<T, char8_t> || std::same_as<T, char16_t> || std::same_as<T, char32_t>;
30
31 template<class CharT, std::size_t N>
32 struct static_string_literal {
33 using char_type = CharT;
34 static constexpr std::size_t size = N;
35 CharT value[N];
36 consteval static_string_literal(CharT const (&text)[N]) noexcept {
37 for (std::size_t i = 0; i != N; ++i) value[i] = text[i];
38 }
39 };
40}
41
42
44template <typename T, T...xs>
45struct reify {
46 static constexpr const T value[sizeof...(xs)+1] = {xs..., T() };
47};
48
49// forward declaration
50class static_c_string;
51
69template <
70 typename CharT,
71 typename Traits = std::char_traits<CharT>
72>
74 std::basic_string_view<CharT,Traits> view{reify<CharT>::value, 0};
75
76public:
80 native_inline constexpr
81 basic_static_string(std::basic_string_view<CharT,Traits> value) noexcept
82 : view(value) {}
83
85 friend class static_c_string;
86 using traits_type = Traits;
87 using value_type = CharT;
88 using pointer = CharT *;
89 using const_pointer = CharT const *;
90 using reference = CharT &;
91 using const_reference = CharT const &;
92 using const_iterator = CharT const *;
93 using iterator = const_iterator;
94 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
95 using reverse_iterator = const_reverse_iterator;
96 using size_type = std::size_t;
97 using difference_type = std::ptrdiff_t;
98
101
103 template <CharT...xs>
104 consteval explicit basic_static_string(std::integer_sequence<CharT,xs...>) noexcept
105 : view(reify<CharT,xs...>::value,sizeof...(xs)) {}
106
108 native_inline constexpr
109 basic_static_string() noexcept = default;
110
112 native_inline constexpr
113 basic_static_string(basic_static_string const &) noexcept = default;
114
116 native_inline constexpr
118
122
125 basic_static_string & operator = (basic_static_string const & that) noexcept = default;
126
129 basic_static_string & operator = (basic_static_string && that) noexcept = default;
130
131
135
138 operator CharT const * () const noexcept {
139 return view.data(); // an extra invariant that its null terminated is maintained
140 }
141
144 operator std::basic_string_view<CharT,Traits>() const noexcept {
145 return view;
146 }
147
150 operator std::basic_string<CharT,Traits>() const {
151 return std::basic_string<CharT,Traits>(view);
152 }
153
157
160 CharT const & operator [](size_type i) const noexcept { return view[i]; }
161
164 CharT const & at(size_type i) const { return view.at(i); }
165
168 const_reference front() const noexcept { return view.front(); }
169
173 const_reference back() const noexcept { return view.back(); }
174
177 const_pointer data() const noexcept { return view.data(); }
178
182
185 size_type size() const noexcept { return view.size(); }
186
189 size_type length() const noexcept { return view.length(); }
190
193 size_type max_size() const noexcept { return view.max_size(); }
194
197 bool empty() const noexcept { return view.empty(); }
198
201 explicit constexpr operator bool () const noexcept { return !view.empty(); }
202
206
211 if constexpr (std::is_same_v<Traits,std::char_traits<CharT>> && detail::static_character<CharT>) {
212 return self.view.data() == that.view.data();
213 } else {
214 return (self.view.data() == that.view.data()) || (self.view == that.view); // fallback required
215 }
216 }
217
222 if constexpr (std::is_same_v<Traits,std::char_traits<CharT>> && detail::static_character<CharT>) {
223 return self.view.data() != that.view.data();
224 } else {
225 return (self.view.data() != that.view.data()) && (self.view != that.view);
226 }
227 }
228
232
235 friend constexpr
236 std::basic_ostream<CharT, Traits> & operator<<(std::basic_ostream<CharT, Traits>& os, basic_static_string<CharT, Traits> v) {
237 return os << v.view;
238 }
239
240
244
247 auto begin() const noexcept { return view.data(); }
248
251 auto end() const noexcept { return view.data() + view.size(); }
252
255 auto cbegin() const noexcept { return begin(); }
256
259 auto cend() const noexcept { return end(); }
260
263 auto rbegin() const noexcept { return const_reverse_iterator(end()); }
264
267 auto rend() const noexcept { return const_reverse_iterator(begin()); }
268
271 auto crbegin() const noexcept { return rbegin(); }
272
275 auto crend() const noexcept { return rend(); }
276
278
280 native_inline constexpr friend
282 using std::swap;
283 swap(x.view,y.view);
284 }
285
286 static constexpr size_type npos = std::basic_string_view<CharT,Traits>::npos;
287};
288
290template <typename CharT, CharT...xs>
291basic_static_string(std::integer_sequence<CharT,xs...>) -> basic_static_string<CharT,std::char_traits<CharT>>;
293
294using static_string = basic_static_string<char>;
295using static_wstring = basic_static_string<wchar_t>;
296using static_u8string = basic_static_string<char8_t>;
297using static_u16string = basic_static_string<char16_t>;
298using static_u32string = basic_static_string<char32_t>;
299
307 char const * p = reify<char>::value;
308public:
309
310 using traits_type = std::char_traits<char>;
311 using value_type = char;
312 using pointer = char *;
313 using const_pointer = char const *;
314 using reference = char &;
315 using const_reference = char const &;
316 using const_iterator = char const *;
317 using iterator = const_iterator;
318 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
319 using reverse_iterator = const_reverse_iterator;
320 using size_type = std::size_t;
321 using difference_type = std::ptrdiff_t;
322
325
327 native_inline constexpr
328 static_c_string() noexcept = default;
329
331 native_inline constexpr
332 static_c_string(static_c_string const &) noexcept = default;
333
335 native_inline constexpr
336 static_c_string(static_c_string &&) noexcept = default;
337
340 native_inline constexpr
341 static_c_string(static_string x) noexcept : p(x.data()) {}
342
346
349 static_c_string & operator = (static_c_string const &) noexcept = default;
350
354
358
361 operator const char * () const noexcept { return p; }
362
365 operator static_string () const noexcept { return static_string(std::string_view(p)); }
366
369 const char * data() const noexcept { return p; }
370
374
377 bool operator == (static_c_string x, static_c_string y) noexcept { return x.p == y.p; }
378
381 bool operator != (static_c_string x, static_c_string y) noexcept { return x.p != y.p; }
382
386
390 auto begin() const noexcept { return p; }
391
394 auto end() const noexcept { return p + std::char_traits<char>::length(p); }
395
399 auto cbegin() const noexcept { return p; }
400
404 auto cend() const noexcept { return p + std::char_traits<char>::length(p); }
405
409 auto rbegin() const noexcept { return std::reverse_iterator<const char *>(end()); }
410
414 auto rend() const noexcept { return std::reverse_iterator<const char *>(begin()); }
415
419 auto crbegin() const noexcept { return std::reverse_iterator<const char *>(end()); }
420
424 auto crend() const noexcept { return std::reverse_iterator<const char *>(begin()); }
425
427
429 native_inline friend
430 void swap(static_c_string & x, static_c_string & y) noexcept {
431 using std::swap;
432 swap(x.p,y.p);
433 }
434};
435
439// Structural string-literal NTTPs are standard C++; no GNU pack extension.
440template <detail::static_string_literal Text>
441consteval auto operator""_ss() noexcept {
442 using CharT = typename decltype(Text)::char_type;
443 return []<std::size_t... I>(std::index_sequence<I...>) {
444 return basic_static_string<CharT>(std::integer_sequence<CharT, Text.value[I]...>{});
445 }(std::make_index_sequence<Text.size - 1>{});
446}
447
451template <detail::static_string_literal Text>
452 requires std::same_as<typename decltype(Text)::char_type, char>
453consteval static_c_string operator""_scs() noexcept {
454 return static_c_string(operator""_ss<Text>());
455}
456
457} // namespace native
458
459export namespace std {
460 using ::std::hash;
461 template <typename CharT, typename Traits>
462 struct hash<::native::basic_static_string<CharT,Traits>> {
464 size_t operator()(::native::basic_static_string<CharT,Traits> const & s) const noexcept {
465 return reinterpret_cast<size_t>(s.data());
466 }
467 };
468 template <>
469 struct hash<::native::static_c_string> {
471 size_t operator()(::native::static_c_string s) const noexcept {
472 return reinterpret_cast<size_t>(s.data());
473 }
474 };
475 namespace ranges {
476
478 template< class CharT, class Traits >
479 inline constexpr bool enable_borrowed_range<::native::basic_static_string<CharT, Traits>> = true;
480
481 template< class CharT, class Traits >
482 inline constexpr bool enable_view<::native::basic_static_string<CharT, Traits>> = true;
483
484 template <>
485 inline constexpr bool enable_borrowed_range<::native::static_c_string> = true;
486
487 template <>
488 inline constexpr bool enable_view<::native::static_c_string> = true;
490 }
491} // namespace std
Compiler attributes for host code, with shader-safe shared modifiers.
A view of one complete interned string, with its length retained. The five standard character widths ...
constexpr friend void swap(basic_static_string &x, basic_static_string &y) noexcept
Exchange views without moving characters.
constexpr auto cbegin() const noexcept
Return the first const character iterator.
constexpr auto rend() const noexcept
Return the reverse end iterator.
constexpr auto cend() const noexcept
Return the const end iterator; C-string form scans to its NUL.
constexpr auto rbegin() const noexcept
Return the first reverse iterator; C-string form first finds its end.
friend constexpr bool operator==(basic_static_string self, basic_static_string that) noexcept
constexpr auto crbegin() const noexcept
Return the first const reverse iterator.
constexpr const_reference back() const noexcept
constexpr size_type max_size() const noexcept
Return the underlying string_view capacity bound, not the current length.
constexpr bool empty() const noexcept
Return whether the stored length is zero.
consteval basic_static_string(std::integer_sequence< CharT, xs... >) noexcept
Intern a compile-time character sequence; append one terminator outside its length.
friend constexpr std::basic_ostream< char, std::char_traits< char > > & operator<<(std::basic_ostream< char, std::char_traits< char > > &os, basic_static_string< char, std::char_traits< char > > v)
constexpr const_pointer data() const noexcept
Borrow the canonical storage; the terminator is at data()[size()].
constexpr const_reference front() const noexcept
Returns the first character. Requires !empty().
constexpr CharT const & at(size_type i) const
access the specified character with bounds checking
constexpr CharT const & operator[](size_type i) const noexcept
Access character i. Requires i < size().
constexpr auto end() const noexcept
Return the one-past-last character iterator; C-string form scans to its NUL.
constexpr auto crend() const noexcept
Return the const reverse end iterator.
constexpr auto begin() const noexcept
Return the first character iterator.
constexpr size_type size() const noexcept
Return the stored number of characters, excluding the final terminator.
constexpr size_type length() const noexcept
Synonym for size().
constexpr basic_static_string(std::basic_string_view< CharT, Traits > value) noexcept
constexpr basic_static_string() noexcept=default
Select the canonical empty interned string.
friend constexpr bool operator!=(basic_static_string self, basic_static_string that) noexcept
A pointer-sized view of a complete interned char string. Length is recovered from the first NUL....
constexpr auto rend() const noexcept
constexpr friend bool operator!=(static_c_string x, static_c_string y) noexcept
Return whether the interned addresses differ.
friend void swap(static_c_string &x, static_c_string &y) noexcept
Exchange the interned pointers without touching characters.
constexpr auto cbegin() const noexcept
constexpr auto rbegin() const noexcept
constexpr auto begin() const noexcept
constexpr auto crbegin() const noexcept
constexpr static_c_string & operator=(static_c_string const &) noexcept=default
Replace this view with the source view without allocation; the source is unchanged.
constexpr friend bool operator==(static_c_string x, static_c_string y) noexcept
Return whether both views refer to the same interned address.
constexpr static_c_string() noexcept=default
Select the canonical empty C string.
constexpr auto cend() const noexcept
constexpr auto crend() const noexcept
constexpr const char * data() const noexcept
Return the borrowed interned pointer.
constexpr auto end() const noexcept
Return the one-past-last character iterator; C-string form scans to its NUL.
#define native_reinitializes
[[clang::reinitializes]]
Definition attributes.h:443
#define native_artificial
[[artificial]].
Definition attributes.h:245
#define native_inline
inline [[always_inline]]
Definition attributes.h:212
#define native_nodiscard
C++17 [[nodiscard]].
Definition attributes.h:189
#define native_pure
[[pure]]
Definition attributes.h:126
Architecture-tagged vectors, register packs and supporting value types. Native arithmetic follows its...
Standard-library adaptations documented here for SIMD value types.
Store a compile-time sequence followed by one value-initialized terminator.