• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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