11#pragma once
22#include < algorithm>
33#include < array>
4- #include < cstdint>
54#include < compare>
5+ #include < cstdint>
66#include < string_view>
77#include < type_traits>
88
@@ -84,6 +84,38 @@ namespace strtype
8484 return fixed_string<SIZE>(copy.data ());
8585 }
8686
87+ template <unsigned M>
88+ consteval auto prefix (char const (&value)[M]) const noexcept
89+ {
90+ return prefix (fixed_string<M - 1 > {value});
91+ }
92+
93+ template <size_t M>
94+ consteval auto prefix (fixed_string<M> value) const noexcept -> fixed_string<N + M>
95+ {
96+ std::array<char , N + M> result {};
97+ for (size_t i = 0 ; i < M; ++i) result[i] = value[i];
98+ for (size_t i = 0 ; i < N; ++i) result[M + i] = buf[i];
99+
100+ return fixed_string<N + M>(result.data ());
101+ }
102+
103+ template <unsigned M>
104+ consteval auto postfix (char const (&value)[M]) const noexcept
105+ {
106+ return postfix (fixed_string<M - 1 > {value});
107+ }
108+
109+ template <size_t M>
110+ consteval auto postfix (fixed_string<M> value) const noexcept -> fixed_string<N + M>
111+ {
112+ std::array<char , N + M> result {};
113+ for (size_t i = 0 ; i < N; ++i) result[i] = buf[i];
114+ for (size_t i = 0 ; i < M; ++i) result[N + i] = value[i];
115+
116+ return fixed_string<N + M>(result.data ());
117+ }
118+
87119 constexpr auto begin () const noexcept { return buf; }
88120 constexpr auto cbegin () const noexcept { return buf; }
89121 constexpr auto end () const noexcept { return &buf[N]; }
@@ -178,9 +210,9 @@ namespace strtype
178210 // figure out if the Value is either an enum value of the given enum type, or equivalent to the underlying
179211 // value;
180212 template <typename T, auto Value>
181- concept IsEnumValueOrUnderlying = IsValidStringifyableEnum<T> &&
182- (std::is_same_v< decltype (Value), T> ||
183- std::is_same_v<decltype (Value), std::underlying_type_t <T>>);
213+ concept IsEnumValueOrUnderlying =
214+ IsValidStringifyableEnum< T> &&
215+ (std::is_same_v< decltype (Value), T> || std::is_same_v<decltype(Value), std::underlying_type_t<T>>);
184216
185217 template <typename T, auto Value, bool ApplyOffset = false >
186218 requires (IsEnumValueOrUnderlying<T, Value>)
@@ -638,9 +670,9 @@ namespace strtype
638670 T* value_buffer = nullptr ) constexpr {
639671 size_t count = 0 ;
640672
641- constexpr auto get_and_fill_valid_enum_value =
642- []< auto Index>( auto & count, std::string_view* str_buffer, T* value_buffer) constexpr
643- {
673+ constexpr auto get_and_fill_valid_enum_value = []< auto Index>( auto & count,
674+ std::string_view* str_buffer,
675+ T* value_buffer) constexpr {
644676 constexpr auto get_enum_name = []<T value>() constexpr {
645677 return details::stringify_value_impl<value,
646678 details::get_known_offset<T {enum_information<T>::BEGIN}>()>();
@@ -693,34 +725,34 @@ namespace strtype
693725 constexpr underlying_t remainder = (End - Begin) % PACK_SIZE;
694726 constexpr underlying_t iterations = (End - Begin - remainder) / PACK_SIZE;
695727
696- constexpr auto split_into_iteration_packs_and_invoke = []<std:: underlying_type_t <T>... Indices>(
697- std::integer_sequence <std::underlying_type_t <T>, Indices ...>) constexpr
698- {
699- constexpr auto merge_results = []<typename ... Ts>(Ts&&... arrays) constexpr {
700- constexpr auto total_size = details::get_array_pack_size<Ts...>::value;
701- std::array<std::string_view, total_size> res_string {};
702- std::array<T, total_size> res_values {};
703- size_t offset {0 };
704- constexpr auto fill =
705- [](auto & dst_str, auto & dst_values, const auto & src, size_t & offset) constexpr {
706- for (size_t i = 0 ; i < src.first .size (); ++offset, ++i)
707- {
708- dst_str[offset] = src.first [i];
709- dst_values[offset] = src.second [i];
710- }
711- };
712- (fill (res_string, res_values, arrays, offset), ...);
713- return std::pair {res_string, res_values};
714- };
715-
716- // returns all valid enum values for the given range [Offset, Offset + Count) as a
717- return merge_results (stringify<T>(details::make_offset_sequence<Begin + (Indices * PACK_SIZE),
718- PACK_SIZE,
719- std::underlying_type_t <T>>())...,
720- stringify<T>(details::make_offset_sequence<Begin + (iterations * PACK_SIZE),
721- remainder,
722- std::underlying_type_t <T>>()));
723- };
728+ constexpr auto split_into_iteration_packs_and_invoke =
729+ [] <std::underlying_type_t <T>... Indices>(
730+ std::integer_sequence<std:: underlying_type_t <T>, Indices...>) constexpr {
731+ constexpr auto merge_results = []<typename ... Ts>(Ts&&... arrays) constexpr {
732+ constexpr auto total_size = details::get_array_pack_size<Ts...>::value;
733+ std::array<std::string_view, total_size> res_string {};
734+ std::array<T, total_size> res_values {};
735+ size_t offset {0 };
736+ constexpr auto fill =
737+ [](auto & dst_str, auto & dst_values, const auto & src, size_t & offset) constexpr {
738+ for (size_t i = 0 ; i < src.first .size (); ++offset, ++i)
739+ {
740+ dst_str[offset] = src.first [i];
741+ dst_values[offset] = src.second [i];
742+ }
743+ };
744+ (fill (res_string, res_values, arrays, offset), ...);
745+ return std::pair {res_string, res_values};
746+ };
747+
748+ // returns all valid enum values for the given range [Offset, Offset + Count) as a
749+ return merge_results (stringify<T>(details::make_offset_sequence<Begin + (Indices * PACK_SIZE),
750+ PACK_SIZE,
751+ std::underlying_type_t <T>>())...,
752+ stringify<T>(details::make_offset_sequence<Begin + (iterations * PACK_SIZE),
753+ remainder,
754+ std::underlying_type_t <T>>()));
755+ };
724756 return split_into_iteration_packs_and_invoke (
725757 std::make_integer_sequence<std::underlying_type_t <T>, iterations>());
726758 }
@@ -745,11 +777,9 @@ namespace strtype
745777
746778 // prepares an std::index_sequence<> where the indices are every bit value with added 0. I.e. it's a range
747779 // that looks like: { 0, 1, 2, 4, 8, 16, 32, ..., 1 << (sizeof(underlying_t) * 8) }
748- constexpr auto bit_shift_indices = []<size_t ... Indices>(std::index_sequence<Indices...>) constexpr
749- {
780+ constexpr auto bit_shift_indices = []<size_t ... Indices>(std::index_sequence<Indices...>) constexpr {
750781 return std::index_sequence<0 , size_t {1 } << Indices...> {};
751- }
752- (std::make_index_sequence<BITS>());
782+ }(std::make_index_sequence<BITS>());
753783
754784 return stringify<T>(bit_shift_indices);
755785 }
@@ -857,14 +887,14 @@ namespace strtype
857887 constexpr auto value = stringify_typename<T>();
858888 constexpr auto end = [](std::string_view value) {
859889 auto offset = value.find (' <' );
860- auto end = value.rfind (' :' , offset);
861- return (end != std::string_view::npos && end > 0 && value[end - 1 ] == ' :' ) ? end -1 : 0 ;
890+ auto end = value.rfind (' :' , offset);
891+ return (end != std::string_view::npos && end > 0 && value[end - 1 ] == ' :' ) ? end - 1 : 0 ;
862892 }(value);
863893
864894 return value.template substr <0 , end>();
865895 }
866896
867- template <typename T>
897+ template <typename T>
868898 consteval auto is_templated_type () noexcept -> bool
869899 {
870900 constexpr auto value = stringify_typename<T>();
0 commit comments