23
23
#include < utils/ostream.h>
24
24
25
25
#include < string_view>
26
+ #include < utility>
26
27
27
28
#include < assert.h>
28
29
#include < stddef.h>
@@ -97,11 +98,7 @@ class UTILS_PUBLIC CString {
97
98
return *this ;
98
99
}
99
100
100
- ~CString () noexcept {
101
- if (mData ) {
102
- free (mData - 1 );
103
- }
104
- }
101
+ ~CString () noexcept ;
105
102
106
103
void swap (CString& other) noexcept {
107
104
// don't use std::swap(), we don't want an STL dependency in this file
@@ -110,42 +107,98 @@ class UTILS_PUBLIC CString {
110
107
other.mCStr = temp;
111
108
}
112
109
113
- const_pointer c_str () const noexcept { return mCStr ; }
114
110
pointer c_str () noexcept { return mCStr ; }
111
+ const_pointer c_str () const noexcept { return const_cast <CString*>(this )->c_str (); }
115
112
const_pointer c_str_safe () const noexcept { return mData ? c_str () : " " ; }
116
113
const_pointer data () const noexcept { return c_str (); }
117
114
pointer data () noexcept { return c_str (); }
118
115
size_type size () const noexcept { return mData ? mData [-1 ].length : 0 ; }
119
116
size_type length () const noexcept { return size (); }
120
117
bool empty () const noexcept { return size () == 0 ; }
121
118
122
- iterator begin () noexcept { return mCStr ; }
119
+ iterator begin () noexcept { return c_str () ; }
123
120
iterator end () noexcept { return begin () + length (); }
124
121
const_iterator begin () const noexcept { return data (); }
125
122
const_iterator end () const noexcept { return begin () + length (); }
126
123
const_iterator cbegin () const noexcept { return begin (); }
127
124
const_iterator cend () const noexcept { return end (); }
128
125
129
- CString& replace (size_type pos, size_type len, const CString& str) noexcept ;
130
- CString& insert (size_type pos, const CString& str) noexcept { return replace (pos, 0 , str); }
131
- CString& append (const CString& str) noexcept { return insert (length (), str); }
126
+ // replace
127
+ template <size_t N>
128
+ CString& replace (size_type const pos,
129
+ size_type const len, const StringLiteral<N>& str) & noexcept {
130
+ return replace (pos, len, str, N - 1 );
131
+ }
132
+
133
+ CString& replace (size_type const pos, size_type const len, const CString& str) & noexcept {
134
+ return replace (pos, len, str.c_str_safe (), str.size ());
135
+ }
136
+
137
+ template <size_t N>
138
+ CString&& replace(size_type const pos,
139
+ size_type const len, const StringLiteral<N>& str) && noexcept {
140
+ return std::move (replace (pos, len, str));
141
+ }
132
142
133
- const_reference operator [](size_type pos) const noexcept {
143
+ CString&& replace(size_type const pos, size_type const len, const CString& str) && noexcept {
144
+ return std::move (replace (pos, len, str));
145
+ }
146
+
147
+ // insert
148
+ template <size_t N>
149
+ CString& insert (size_type const pos, const StringLiteral<N>& str) & noexcept {
150
+ return replace (pos, 0 , str);
151
+ }
152
+
153
+ CString& insert (size_type const pos, const CString& str) & noexcept {
154
+ return replace (pos, 0 , str);
155
+ }
156
+
157
+ template <size_t N>
158
+ CString&& insert(size_type const pos, const StringLiteral<N>& str) && noexcept {
159
+ return std::move (*this ).replace (pos, 0 , str);
160
+ }
161
+
162
+ CString&& insert(size_type const pos, const CString& str) && noexcept {
163
+ return std::move (*this ).replace (pos, 0 , str);
164
+ }
165
+
166
+ // append
167
+ template <size_t N>
168
+ CString& append (const StringLiteral<N>& str) & noexcept {
169
+ return insert (length (), str);
170
+ }
171
+
172
+ CString& append (const CString& str) & noexcept {
173
+ return insert (length (), str);
174
+ }
175
+
176
+ template <size_t N>
177
+ CString&& append(const StringLiteral<N>& str) && noexcept {
178
+ return std::move (*this ).insert (length (), str);
179
+ }
180
+
181
+ CString&& append(const CString& str) && noexcept {
182
+ return std::move (*this ).insert (length (), str);
183
+ }
184
+
185
+
186
+ const_reference operator [](size_type const pos) const noexcept {
134
187
assert (pos < size ());
135
188
return begin ()[pos];
136
189
}
137
190
138
- reference operator [](size_type pos) noexcept {
191
+ reference operator [](size_type const pos) noexcept {
139
192
assert (pos < size ());
140
193
return begin ()[pos];
141
194
}
142
195
143
- const_reference at (size_type pos) const noexcept {
196
+ const_reference at (size_type const pos) const noexcept {
144
197
assert (pos < size ());
145
198
return begin ()[pos];
146
199
}
147
200
148
- reference at (size_type pos) noexcept {
201
+ reference at (size_type const pos) noexcept {
149
202
assert (pos < size ());
150
203
return begin ()[pos];
151
204
}
@@ -171,7 +224,7 @@ class UTILS_PUBLIC CString {
171
224
}
172
225
173
226
// placement new declared as "throw" to avoid the compiler's null-check
174
- inline void * operator new (size_t , void * ptr) {
227
+ void * operator new (size_t , void * ptr) {
175
228
assert (ptr);
176
229
return ptr;
177
230
}
@@ -185,6 +238,8 @@ class UTILS_PUBLIC CString {
185
238
};
186
239
187
240
private:
241
+ CString& replace (size_type pos, size_type len, char const * str, size_t l) & noexcept ;
242
+
188
243
#if !defined(NDEBUG)
189
244
friend io::ostream& operator <<(io::ostream& out, const CString& rhs);
190
245
#endif
@@ -225,7 +280,7 @@ class UTILS_PUBLIC CString {
225
280
}
226
281
};
227
282
228
- // implement this for your type for automatic conversion to CString. Failing to do so leads
283
+ // Implement this for your type for automatic conversion to CString. Failing to do so leads
229
284
// to a compile-time failure.
230
285
template <typename T>
231
286
CString to_string (T value) noexcept ;
@@ -249,7 +304,7 @@ class UTILS_PUBLIC FixedSizeString {
249
304
pointer c_str () noexcept { return mData ; }
250
305
251
306
private:
252
- value_type mData [N] = {0 };
307
+ value_type mData [N] = {};
253
308
};
254
309
255
310
} // namespace utils
0 commit comments