@@ -18,57 +18,66 @@ namespace rdf4cpp::datatypes::registry::util {
1818 */
1919template <size_t N>
2020struct ConstexprString {
21- std::array<char , N> value;
21+ std::array<char , N> value{} ;
2222
23- constexpr ConstexprString (const char (&str)[N]) noexcept {
23+ constexpr ConstexprString () noexcept = default;
24+
25+ /* *
26+ * @param str null-terminated char array/string literal
27+ */
28+ constexpr ConstexprString (char const (&str)[N]) noexcept {
2429 std::copy_n (str, N, value.data ());
2530 }
31+
2632 constexpr ConstexprString (std::string_view v) {
27- if (v.size ()+1 != N)
28- throw std::invalid_argument{" size missmatch" };
29- std::copy_n (v.data (), N-1 , value.data ());
30- value[N-1 ] = 0 ;
33+ if (v.size () != N - 1 ) {
34+ throw std::invalid_argument{" size mismatch" };
35+ }
36+
37+ std::copy_n (v.data (), N - 1 , value.data ());
38+ // implicitly null terminated by default init of array
3139 }
32- constexpr ConstexprString () = default;
3340
34- constexpr operator std::string_view () const noexcept {
35- return std::string_view{ value.data (), value. size () - 1 } ;
41+ [[nodiscard]] constexpr char const * data () const noexcept {
42+ return value.data ();
3643 }
3744
38- [[nodiscard]] constexpr char const * c_str () const noexcept {
45+ [[nodiscard]] constexpr char * data () noexcept {
3946 return value.data ();
4047 }
4148
49+ [[nodiscard]] static constexpr size_t size () noexcept {
50+ return N - 1 ; // exclude null terminator
51+ }
52+
53+ [[nodiscard]] constexpr std::string_view view () const noexcept {
54+ return std::string_view{data (), size ()};
55+ }
56+
57+ constexpr operator std::string_view () const noexcept {
58+ return view ();
59+ }
60+
4261 template <size_t M>
4362 constexpr std::strong_ordering operator <=>(ConstexprString<M> const &other) const noexcept {
44- auto min = std::min (M, N);
45- for (size_t i = 0 ; i < min; ++i) {
46- std::strong_ordering cmp = this ->value [i] <=> other.value [i];
47- if (cmp != std::strong_ordering::equal)
48- return cmp;
49- }
50- std::strong_ordering cmp = N <=> M;
51- return cmp;
63+ return view () <=> other.view ();
5264 }
5365
5466 template <size_t M>
5567 constexpr bool operator ==(ConstexprString<M> const &other) const noexcept {
56- if (M == N) {
57- return (* this <=> other == std::strong_ordering::equal) ;
68+ if constexpr (M == N) {
69+ return value == other. value ;
5870 } else {
5971 return false ;
6072 }
6173 }
6274
63- [[nodiscard]] constexpr size_t size () const noexcept {
64- return N;
65- }
66-
6775 template <size_t M>
68- constexpr ConstexprString<M+N-1 > operator +(const ConstexprString<M>& other) const noexcept {
69- ConstexprString<M+N-1 > r{};
70- std::copy_n (this ->value .data (), N-1 , r.value .data ());
71- std::copy_n (other.value .data (), M-1 , r.value .data () + (N-1 ));
76+ constexpr ConstexprString<M+N-1 > operator +(ConstexprString<M> const &other) const noexcept {
77+ ConstexprString<M+N-1 > r{}; // only include a single null terminator N+M would include 2
78+ std::copy_n (data (), size (), r.data ());
79+ std::copy_n (other.data (), other.size (), r.data () + size ());
80+ // implicitly null terminated by default init of array
7281 return r;
7382 }
7483};
@@ -83,7 +92,7 @@ struct ConstexprStringHolder {
8392template <size_t N>
8493struct std ::formatter<rdf4cpp::datatypes::registry::util::ConstexprString<N>> : std::formatter<std::string_view> {
8594 auto format (rdf4cpp::datatypes::registry::util::ConstexprString<N> const &s, format_context& ctx) const {
86- return formatter<string_view>::format (static_cast <std::string_view>(s ), ctx);
95+ return formatter<string_view>::format (s. view ( ), ctx);
8796 }
8897};
8998
0 commit comments