siplasplas
string.hpp
1 #ifndef SIPLASPLAS_CONSTEXPR_STRING_HPP
2 #define SIPLASPLAS_CONSTEXPR_STRING_HPP
3 
4 #include "stringview.hpp"
5 #include "algorithm.hpp"
6 #include <siplasplas/utility/meta.hpp>
7 #include <siplasplas/utility/cast.hpp>
8 #include <array>
9 
10 namespace cpp
11 {
12 
13 namespace constexp
14 {
15 
16 template<std::size_t Size>
17 class String
18 {
19 public:
20  template<typename Begin, typename End>
21  constexpr String(Begin begin, End end);
22 
23  constexpr String(const std::initializer_list<char>& initList);
24 
25  template<std::size_t StringSize>
26  constexpr String(const char(&string)[StringSize]);
27 
28  constexpr char operator[](std::size_t i) const;
29  constexpr std::size_t size() const;
30 
31  constexpr const char* begin() const;
32  constexpr const char* end() const;
33  constexpr ConstStringView view() const;
34  constexpr ConstStringView operator()(std::size_t i, std::size_t j) const;
35 
36  std::string str() const;
37  constexpr const char* c_str() const;
38 
39 private:
40  std::array<char, Size> _storage;
41 };
42 
43 namespace detail
44 {
45 
46 template<typename Begin, typename End, std::size_t... Is>
47 constexpr std::array<char, sizeof...(Is)> makeArray(Begin begin, End end, cpp::meta::index_sequence<Is...>)
48 {
49  return {{
50  (*(begin + Is))...
51  }};
52 }
53 
54 }
55 
56 template<std::size_t Size>
57 template<typename Begin, typename End>
58 constexpr String<Size>::String(Begin begin, End end) :
59  _storage{detail::makeArray(begin, end, cpp::meta::make_index_sequence<Size>())}
60 {}
61 
62 template<std::size_t Size>
63 constexpr String<Size>::String(const std::initializer_list<char>& initList) :
64  String{initList.begin(), initList.end()}
65 {}
66 
67 template<std::size_t Size>
68 template<std::size_t StringSize>
69 constexpr String<Size>::String(const char (&string)[StringSize]) :
71 {
72  static_assert(Size >= StringSize, "Not enough storage for the given string literal");
73 }
74 
75 template<std::size_t Size>
76 constexpr char String<Size>::operator[](std::size_t i) const
77 {
78  return _storage[i];
79 }
80 
81 template<std::size_t Size>
82 constexpr std::size_t String<Size>::size() const
83 {
84  return Size;
85 }
86 
87 template<std::size_t Size>
88 constexpr const char* String<Size>::begin() const
89 {
90  return &_storage[0];
91 }
92 
93 template<std::size_t Size>
94 constexpr const char* String<Size>::end() const
95 {
96  return &_storage[Size];
97 }
98 
99 template<std::size_t Size>
100 constexpr ConstStringView String<Size>::view() const
101 {
102  return { begin(), end() };
103 }
104 
105 template<std::size_t Size>
106 constexpr ConstStringView String<Size>::operator()(std::size_t i, std::size_t j) const
107 {
108  return view()(i, j);
109 }
110 
111 template<std::size_t Size>
112 std::string String<Size>::str() const
113 {
114  return view().str();
115 }
116 
117 template<std::size_t Size>
118 constexpr const char* String<Size>::c_str() const
119 {
120  return view().c_str();
121 }
122 
123 namespace detail
124 {
125 
126 template<std::size_t LhsSize, std::size_t RhsSize, std::size_t... Is, std::size_t... Js>
127 constexpr String<LhsSize + RhsSize - 1> cat(const String<LhsSize>& lhs, const String<RhsSize>& rhs,
130 {
131  return {{
132  lhs[Is]...,
133  rhs[Js]...
134  }};
135 }
136 
137 }
138 
139 template<std::size_t LhsSize, std::size_t RhsSize>
140 constexpr String<LhsSize + RhsSize - 1> operator+(const String<LhsSize>& lhs, const String<RhsSize>& rhs)
141 {
142  return detail::cat(
143  lhs,
144  rhs,
145  cpp::meta::make_index_sequence<LhsSize - 1>(), // Remove the middle null terminator
146  cpp::meta::make_index_sequence<RhsSize>()
147  );
148 }
149 
150 template<std::size_t LhsSize, std::size_t RhsSize>
151 constexpr bool operator==(const String<LhsSize>& lhs, const String<RhsSize>& rhs)
152 {
153  return cpp::constexp::equal(
154  lhs,
155  rhs
156  );
157 }
158 
159 template<std::size_t LhsSize, std::size_t RhsSize>
160 constexpr bool operator!=(const String<LhsSize>& lhs, const String<RhsSize>& rhs)
161 {
162  return !(lhs == rhs);
163 }
164 
165 template<std::size_t Size>
166 std::ostream& operator<<(std::ostream& os, const String<Size>& string)
167 {
168  return os << string.view();
169 }
170 
171 template<std::size_t N>
172 constexpr String<N> stringLiteral(const char (&stringLiteral)[N])
173 {
174  return {stringLiteral};
175 }
176 
177 }
178 
179 }
180 
181 #endif // SIPLASPLAS_CONSTEXPR_STRING_HPP
Definition: messaging.hpp:8
constexpr bool equal(Begin1 begin1, End1 end1, Begin2 begin2, End2 end2, Compare compare)
Compares if two sequences are equal.
Definition: algorithm.hpp:137
Definition: meta.hpp:225
Definition: string.hpp:17
constexpr auto end(const Sequence &sequence)
Returns an iterator pointing to the end of a sequence.
Definition: algorithm.hpp:86
constexpr auto begin(const Sequence &sequence)
Returns an iterator pointing to the beginning of a sequence.
Definition: algorithm.hpp:62
Definition: test_util.hpp:13
Definition: stringview.hpp:63