1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9
10 #ifndef BOOST_BEAST_IMPL_STATIC_STRING_HPP
11 #define BOOST_BEAST_IMPL_STATIC_STRING_HPP
12
13 #include <boost/beast/core/detail/static_string.hpp>
14 #include <boost/throw_exception.hpp>
15
16 namespace boost {
17 namespace beast {
18
19 //
20 // (constructor)
21 //
22
23 template<std::size_t N, class CharT, class Traits>
24 static_string<N, CharT, Traits>::
static_string()25 static_string()
26 {
27 n_ = 0;
28 term();
29 }
30
31 template<std::size_t N, class CharT, class Traits>
32 static_string<N, CharT, Traits>::
static_string(size_type count,CharT ch)33 static_string(size_type count, CharT ch)
34 {
35 assign(count, ch);
36 }
37
38 template<std::size_t N, class CharT, class Traits>
39 template<std::size_t M>
40 static_string<N, CharT, Traits>::
static_string(static_string<M,CharT,Traits> const & other,size_type pos)41 static_string(static_string<M, CharT, Traits> const& other,
42 size_type pos)
43 {
44 assign(other, pos);
45 }
46
47 template<std::size_t N, class CharT, class Traits>
48 template<std::size_t M>
49 static_string<N, CharT, Traits>::
static_string(static_string<M,CharT,Traits> const & other,size_type pos,size_type count)50 static_string(static_string<M, CharT, Traits> const& other,
51 size_type pos, size_type count)
52 {
53 assign(other, pos, count);
54 }
55
56 template<std::size_t N, class CharT, class Traits>
57 static_string<N, CharT, Traits>::
static_string(CharT const * s,size_type count)58 static_string(CharT const* s, size_type count)
59 {
60 assign(s, count);
61 }
62
63 template<std::size_t N, class CharT, class Traits>
64 static_string<N, CharT, Traits>::
static_string(CharT const * s)65 static_string(CharT const* s)
66 {
67 auto const count = Traits::length(s);
68 if(count > max_size())
69 BOOST_THROW_EXCEPTION(std::length_error{
70 "count > max_size()"});
71 n_ = count;
72 Traits::copy(&s_[0], s, n_ + 1);
73 }
74
75 template<std::size_t N, class CharT, class Traits>
76 template<class InputIt>
77 static_string<N, CharT, Traits>::
static_string(InputIt first,InputIt last)78 static_string(InputIt first, InputIt last)
79 {
80 assign(first, last);
81 }
82
83 template<std::size_t N, class CharT, class Traits>
84 static_string<N, CharT, Traits>::
static_string(static_string const & s)85 static_string(static_string const& s)
86 {
87 assign(s);
88 }
89
90 template<std::size_t N, class CharT, class Traits>
91 template<std::size_t M>
92 static_string<N, CharT, Traits>::
static_string(static_string<M,CharT,Traits> const & s)93 static_string(static_string<M, CharT, Traits> const& s)
94 {
95 assign(s);
96 }
97
98 template<std::size_t N, class CharT, class Traits>
99 static_string<N, CharT, Traits>::
static_string(std::initializer_list<CharT> init)100 static_string(std::initializer_list<CharT> init)
101 {
102 assign(init.begin(), init.end());
103 }
104
105 template<std::size_t N, class CharT, class Traits>
106 static_string<N, CharT, Traits>::
static_string(string_view_type sv)107 static_string(string_view_type sv)
108 {
109 assign(sv);
110 }
111
112 template<std::size_t N, class CharT, class Traits>
113 template<class T, class>
114 static_string<N, CharT, Traits>::
static_string(T const & t,size_type pos,size_type n)115 static_string(T const& t, size_type pos, size_type n)
116 {
117 assign(t, pos, n);
118 }
119
120 //
121 // (assignment)
122 //
123
124 template<std::size_t N, class CharT, class Traits>
125 auto
126 static_string<N, CharT, Traits>::
operator =(CharT const * s)127 operator=(CharT const* s) ->
128 static_string&
129 {
130 auto const count = Traits::length(s);
131 if(count > max_size())
132 BOOST_THROW_EXCEPTION(std::length_error{
133 "count > max_size()"});
134 n_ = count;
135 Traits::copy(&s_[0], s, n_ + 1);
136 return *this;
137 }
138
139 template<std::size_t N, class CharT, class Traits>
140 auto
141 static_string<N, CharT, Traits>::
assign(size_type count,CharT ch)142 assign(size_type count, CharT ch) ->
143 static_string&
144 {
145 if(count > max_size())
146 BOOST_THROW_EXCEPTION(std::length_error{
147 "count > max_size()"});
148 n_ = count;
149 Traits::assign(&s_[0], n_, ch);
150 term();
151 return *this;
152 }
153
154 template<std::size_t N, class CharT, class Traits>
155 auto
156 static_string<N, CharT, Traits>::
assign(static_string const & str)157 assign(static_string const& str) ->
158 static_string&
159 {
160 n_ = str.n_;
161 auto const n = n_ + 1;
162 BOOST_BEAST_ASSUME(n != 0);
163 Traits::copy(&s_[0], &str.s_[0], n);
164 return *this;
165 }
166
167 template<std::size_t N, class CharT, class Traits>
168 template<std::size_t M>
169 auto
170 static_string<N, CharT, Traits>::
assign(static_string<M,CharT,Traits> const & str,size_type pos,size_type count)171 assign(static_string<M, CharT, Traits> const& str,
172 size_type pos, size_type count) ->
173 static_string&
174 {
175 auto const ss = str.substr(pos, count);
176 return assign(ss.data(), ss.size());
177 }
178
179 template<std::size_t N, class CharT, class Traits>
180 auto
181 static_string<N, CharT, Traits>::
assign(CharT const * s,size_type count)182 assign(CharT const* s, size_type count) ->
183 static_string&
184 {
185 if(count > max_size())
186 BOOST_THROW_EXCEPTION(std::length_error{
187 "count > max_size()"});
188 n_ = count;
189 Traits::copy(&s_[0], s, n_);
190 term();
191 return *this;
192 }
193
194 template<std::size_t N, class CharT, class Traits>
195 template<class InputIt>
196 auto
197 static_string<N, CharT, Traits>::
assign(InputIt first,InputIt last)198 assign(InputIt first, InputIt last) ->
199 static_string&
200 {
201 std::size_t const n = std::distance(first, last);
202 if(n > max_size())
203 BOOST_THROW_EXCEPTION(std::length_error{
204 "n > max_size()"});
205 n_ = n;
206 for(auto it = &s_[0]; first != last; ++it, ++first)
207 Traits::assign(*it, *first);
208 term();
209 return *this;
210 }
211
212 template<std::size_t N, class CharT, class Traits>
213 template<class T>
214 auto
215 static_string<N, CharT, Traits>::
assign(T const & t,size_type pos,size_type count)216 assign(T const& t, size_type pos, size_type count) ->
217 typename std::enable_if<std::is_convertible<T,
218 string_view_type>::value, static_string&>::type
219 {
220 auto const sv = string_view_type(t).substr(pos, count);
221 if(sv.size() > max_size())
222 BOOST_THROW_EXCEPTION(std::length_error{
223 "sv.size() > max_size()"});
224 n_ = sv.size();
225 Traits::copy(&s_[0], &sv[0], n_);
226 term();
227 return *this;
228 }
229
230 //
231 // Element access
232 //
233
234 template<std::size_t N, class CharT, class Traits>
235 auto
236 static_string<N, CharT, Traits>::
at(size_type pos)237 at(size_type pos) ->
238 reference
239 {
240 if(pos >= size())
241 BOOST_THROW_EXCEPTION(std::out_of_range{
242 "pos >= size()"});
243 return s_[pos];
244 }
245
246 template<std::size_t N, class CharT, class Traits>
247 auto
248 static_string<N, CharT, Traits>::
at(size_type pos) const249 at(size_type pos) const ->
250 const_reference
251 {
252 if(pos >= size())
253 BOOST_THROW_EXCEPTION(std::out_of_range{
254 "pos >= size()"});
255 return s_[pos];
256 }
257
258 //
259 // Capacity
260 //
261
262 template<std::size_t N, class CharT, class Traits>
263 void
264 static_string<N, CharT, Traits>::
reserve(std::size_t n)265 reserve(std::size_t n)
266 {
267 if(n > max_size())
268 BOOST_THROW_EXCEPTION(std::length_error{
269 "n > max_size()"});
270 }
271
272 //
273 // Operations
274 //
275
276 template<std::size_t N, class CharT, class Traits>
277 void
278 static_string<N, CharT, Traits>::
clear()279 clear()
280 {
281 n_ = 0;
282 term();
283 }
284
285 template<std::size_t N, class CharT, class Traits>
286 auto
287 static_string<N, CharT, Traits>::
insert(size_type index,size_type count,CharT ch)288 insert(size_type index, size_type count, CharT ch) ->
289 static_string&
290 {
291 if(index > size())
292 BOOST_THROW_EXCEPTION(std::out_of_range{
293 "index > size()"});
294 insert(begin() + index, count, ch);
295 return *this;
296 }
297
298 template<std::size_t N, class CharT, class Traits>
299 auto
300 static_string<N, CharT, Traits>::
insert(size_type index,CharT const * s,size_type count)301 insert(size_type index, CharT const* s, size_type count) ->
302 static_string&
303 {
304 if(index > size())
305 BOOST_THROW_EXCEPTION(std::out_of_range{
306 "index > size()"});
307 if(size() + count > max_size())
308 BOOST_THROW_EXCEPTION(std::length_error{
309 "size() + count > max_size()"});
310 Traits::move(
311 &s_[index + count], &s_[index], size() - index);
312 n_ += count;
313 Traits::copy(&s_[index], s, count);
314 term();
315 return *this;
316 }
317
318 template<std::size_t N, class CharT, class Traits>
319 template<std::size_t M>
320 auto
321 static_string<N, CharT, Traits>::
insert(size_type index,static_string<M,CharT,Traits> const & str,size_type index_str,size_type count)322 insert(size_type index,
323 static_string<M, CharT, Traits> const& str,
324 size_type index_str, size_type count) ->
325 static_string&
326 {
327 auto const ss = str.substr(index_str, count);
328 return insert(index, ss.data(), ss.size());
329 }
330
331 template<std::size_t N, class CharT, class Traits>
332 auto
333 static_string<N, CharT, Traits>::
insert(const_iterator pos,size_type count,CharT ch)334 insert(const_iterator pos, size_type count, CharT ch) ->
335 iterator
336 {
337 if(size() + count > max_size())
338 BOOST_THROW_EXCEPTION(std::length_error{
339 "size() + count() > max_size()"});
340 auto const index = pos - &s_[0];
341 Traits::move(
342 &s_[index + count], &s_[index], size() - index);
343 n_ += count;
344 Traits::assign(&s_[index], count, ch);
345 term();
346 return &s_[index];
347 }
348
349 template<std::size_t N, class CharT, class Traits>
350 template<class InputIt>
351 auto
352 static_string<N, CharT, Traits>::
insert(const_iterator pos,InputIt first,InputIt last)353 insert(const_iterator pos, InputIt first, InputIt last) ->
354 typename std::enable_if<
355 detail::is_input_iterator<InputIt>::value,
356 iterator>::type
357 {
358 std::size_t const count = std::distance(first, last);
359 if(size() + count > max_size())
360 BOOST_THROW_EXCEPTION(std::length_error{
361 "size() + count > max_size()"});
362 std::size_t const index = pos - begin();
363 Traits::move(
364 &s_[index + count], &s_[index], size() - index);
365 n_ += count;
366 for(auto it = begin() + index;
367 first != last; ++it, ++first)
368 Traits::assign(*it, *first);
369 term();
370 return begin() + index;
371 }
372
373 template<std::size_t N, class CharT, class Traits>
374 template<class T>
375 auto
376 static_string<N, CharT, Traits>::
insert(size_type index,const T & t,size_type index_str,size_type count)377 insert(size_type index, const T& t,
378 size_type index_str, size_type count) ->
379 typename std::enable_if<std::is_convertible<
380 T const&, string_view_type>::value &&
381 ! std::is_convertible<T const&, CharT const*>::value,
382 static_string&>::type
383 {
384 auto const str =
385 string_view_type(t).substr(index_str, count);
386 return insert(index, str.data(), str.size());
387 }
388
389 template<std::size_t N, class CharT, class Traits>
390 auto
391 static_string<N, CharT, Traits>::
erase(size_type index,size_type count)392 erase(size_type index, size_type count) ->
393 static_string&
394 {
395 if(index > size())
396 BOOST_THROW_EXCEPTION(std::out_of_range{
397 "index > size()"});
398 auto const n = (std::min)(count, size() - index);
399 Traits::move(
400 &s_[index], &s_[index + n], size() - (index + n) + 1);
401 n_ -= n;
402 return *this;
403 }
404
405 template<std::size_t N, class CharT, class Traits>
406 auto
407 static_string<N, CharT, Traits>::
erase(const_iterator pos)408 erase(const_iterator pos) ->
409 iterator
410 {
411 erase(pos - begin(), 1);
412 return begin() + (pos - begin());
413 }
414
415 template<std::size_t N, class CharT, class Traits>
416 auto
417 static_string<N, CharT, Traits>::
erase(const_iterator first,const_iterator last)418 erase(const_iterator first, const_iterator last) ->
419 iterator
420 {
421 erase(first - begin(),
422 std::distance(first, last));
423 return begin() + (first - begin());
424 }
425
426 template<std::size_t N, class CharT, class Traits>
427 void
428 static_string<N, CharT, Traits>::
push_back(CharT ch)429 push_back(CharT ch)
430 {
431 if(size() >= max_size())
432 BOOST_THROW_EXCEPTION(std::length_error{
433 "size() >= max_size()"});
434 Traits::assign(s_[n_++], ch);
435 term();
436 }
437
438 template<std::size_t N, class CharT, class Traits>
439 template<std::size_t M>
440 auto
441 static_string<N, CharT, Traits>::
append(static_string<M,CharT,Traits> const & str,size_type pos,size_type count)442 append(static_string<M, CharT, Traits> const& str,
443 size_type pos, size_type count) ->
444 static_string&
445 {
446 // Valid range is [0, size)
447 if(pos >= str.size())
448 BOOST_THROW_EXCEPTION(std::out_of_range{
449 "pos > str.size()"});
450 string_view_type const ss{&str.s_[pos],
451 (std::min)(count, str.size() - pos)};
452 insert(size(), ss.data(), ss.size());
453 return *this;
454 }
455
456 template<std::size_t N, class CharT, class Traits>
457 auto
458 static_string<N, CharT, Traits>::
substr(size_type pos,size_type count) const459 substr(size_type pos, size_type count) const ->
460 string_view_type
461 {
462 if(pos > size())
463 BOOST_THROW_EXCEPTION(std::out_of_range{
464 "pos > size()"});
465 return{&s_[pos], (std::min)(count, size() - pos)};
466 }
467
468 template<std::size_t N, class CharT, class Traits>
469 auto
470 static_string<N, CharT, Traits>::
copy(CharT * dest,size_type count,size_type pos) const471 copy(CharT* dest, size_type count, size_type pos) const ->
472 size_type
473 {
474 auto const str = substr(pos, count);
475 Traits::copy(dest, str.data(), str.size());
476 return str.size();
477 }
478
479 template<std::size_t N, class CharT, class Traits>
480 void
481 static_string<N, CharT, Traits>::
resize(std::size_t n)482 resize(std::size_t n)
483 {
484 if(n > max_size())
485 BOOST_THROW_EXCEPTION(std::length_error{
486 "n > max_size()"});
487 if(n > n_)
488 Traits::assign(&s_[n_], n - n_, CharT{});
489 n_ = n;
490 term();
491 }
492
493 template<std::size_t N, class CharT, class Traits>
494 void
495 static_string<N, CharT, Traits>::
resize(std::size_t n,CharT c)496 resize(std::size_t n, CharT c)
497 {
498 if(n > max_size())
499 BOOST_THROW_EXCEPTION(std::length_error{
500 "n > max_size()"});
501 if(n > n_)
502 Traits::assign(&s_[n_], n - n_, c);
503 n_ = n;
504 term();
505 }
506
507 template<std::size_t N, class CharT, class Traits>
508 void
509 static_string<N, CharT, Traits>::
swap(static_string & str)510 swap(static_string& str)
511 {
512 static_string tmp(str);
513 str.n_ = n_;
514 Traits::copy(&str.s_[0], &s_[0], n_ + 1);
515 n_ = tmp.n_;
516 Traits::copy(&s_[0], &tmp.s_[0], n_ + 1);
517 }
518
519 template<std::size_t N, class CharT, class Traits>
520 template<std::size_t M>
521 void
522 static_string<N, CharT, Traits>::
swap(static_string<M,CharT,Traits> & str)523 swap(static_string<M, CharT, Traits>& str)
524 {
525 if(size() > str.max_size())
526 BOOST_THROW_EXCEPTION(std::length_error{
527 "size() > str.max_size()"});
528 if(str.size() > max_size())
529 BOOST_THROW_EXCEPTION(std::length_error{
530 "str.size() > max_size()"});
531 static_string tmp(str);
532 str.n_ = n_;
533 Traits::copy(&str.s_[0], &s_[0], n_ + 1);
534 n_ = tmp.n_;
535 Traits::copy(&s_[0], &tmp.s_[0], n_ + 1);
536 }
537
538
539 template<std::size_t N, class CharT, class Traits>
540 auto
541 static_string<N, CharT, Traits>::
assign_char(CharT ch,std::true_type)542 assign_char(CharT ch, std::true_type) ->
543 static_string&
544 {
545 n_ = 1;
546 Traits::assign(s_[0], ch);
547 term();
548 return *this;
549 }
550
551 template<std::size_t N, class CharT, class Traits>
552 auto
553 static_string<N, CharT, Traits>::
assign_char(CharT,std::false_type)554 assign_char(CharT, std::false_type) ->
555 static_string&
556 {
557 BOOST_THROW_EXCEPTION(std::length_error{
558 "max_size() == 0"});
559 }
560
561 template<class Integer, class>
562 static_string<detail::max_digits(sizeof(Integer))>
to_static_string(Integer x)563 to_static_string(Integer x)
564 {
565 using CharT = char;
566 using Traits = std::char_traits<CharT>;
567 BOOST_STATIC_ASSERT(std::is_integral<Integer>::value);
568 char buf[detail::max_digits(sizeof(Integer))];
569 auto last = buf + sizeof(buf);
570 auto it = detail::raw_to_string<
571 CharT, Integer, Traits>(last, sizeof(buf), x);
572 static_string<detail::max_digits(sizeof(Integer))> s;
573 s.resize(static_cast<std::size_t>(last - it));
574 auto p = s.data();
575 while(it < last)
576 Traits::assign(*p++, *it++);
577 return s;
578 }
579
580 } // beast
581 } // boost
582
583 #endif
584