21 template<
unsigned int BuffN,
class charT,
class traits>
23 basic_stack_string<BuffN, charT, traits>::buffer_type::copy(native_databus_type
const *src)
noexcept(
true) {
24 assert(std::strlen(
reinterpret_cast<value_type
const *>(src))<small_string_max_size);
27 unrolled_op_t::result([src,
this](
std::size_t i) {fast_copy_values[i]=src[i];});
32 template<
std::size_t SrcSz>
34 basic_stack_string<BuffN, charT, traits>::buffer_type::copy(
value_type const (& src)[SrcSz])
noexcept(
true) {
37 memcpy_opt(src, small_basic_stack_string);
41 template<
unsigned int BuffN,
class charT,
class traits>
43 basic_stack_string<BuffN, charT, traits>::buffer_type::copy(ensure_char_ptr_argument_aligned src)
noexcept(
true) {
44 assert(std::strlen(src)<small_string_max_size);
45 native_databus_type
const *punned_src=
reinterpret_cast<native_databus_type
const *>(src);
49 template<
unsigned int BuffN,
class charT,
class traits>
54 std::memcpy(small_basic_stack_string+offset, b, std::distance(b, e));
56 std::memcpy(heap+offset, b, std::distance(b, e));
60 template<
unsigned int BuffN,
class charT,
class traits>
65 memset(small_basic_stack_string+offset, i, n);
67 memset(heap+offset, i, n);
71 template<
unsigned int BuffN,
class charT,
class traits>
73 basic_stack_string<BuffN, charT, traits>::buffer_type::ctor(
size_type cap, ensure_char_ptr_argument_aligned src)
noexcept(
false) {
75 std::memcpy(small_basic_stack_string, src, cap);
79 assert(
static_cast<size_type>(ptr.second)>=cap);
81 std::memcpy(heap, src, cap);
83 throw std::bad_alloc();
89 template<
std::size_t SrcSz>
91 basic_stack_string<BuffN, charT, traits>::buffer_type::ctor(
value_type const (& src)[SrcSz])
noexcept(SrcSz<=small_string_max_size) {
98 assert(
static_cast<size_type>(ptr.second)>=SrcSz);
101 memcpy_opt(src,
reinterpret_cast<dest_type &>(*heap));
104 throw std::bad_alloc();
109 template<
unsigned int BuffN,
class charT,
class traits>
111 basic_stack_string<BuffN, charT, traits>::buffer_type::cctor(
size_type cap, buffer_type
const &b)
noexcept(
false) {
113 unrolled_op_t::result([&b,
this](
std::size_t i) {fast_copy_values[i]=b.fast_copy_values[i];});
117 assert(
static_cast<size_type>(ptr.second)<=cap);
119 std::memcpy(heap, b.heap, cap);
121 throw std::bad_alloc();
126 template<
unsigned int BuffN,
class charT,
class traits>
128 basic_stack_string<BuffN, charT, traits>::buffer_type::swap(buffer_type &buff)
noexcept(
true) {
130 unrolled_op_t::result([
this, &buff](
std::size_t i) {
std::swap(fast_copy_values[i], buff.fast_copy_values[i]);});
133 template<
unsigned int BuffN,
class charT,
class traits>
135 basic_stack_string<BuffN, charT, traits>::buffer_type::move(
size_type cap,
typename iterator_traits::difference_type f,
typename iterator_traits::difference_type l,
size_type n)
noexcept(
true) {
138 memmove(small_basic_stack_string+f, small_basic_stack_string+l, n);
140 memmove(heap+f, heap+l, n);
144 template<
unsigned int BuffN,
class charT,
class traits>
147 : size_(), capacity_(), buffer() {
150 template<
unsigned int BuffN,
class charT,
class traits>
152 basic_stack_string<BuffN, charT, traits>::
basic_stack_string(ensure_char_ptr_argument_aligned src,
std::size_t sz)
noexcept(
false) {
153 if (
LIKELY(src!=
nullptr)) {
156 buffer.ctor(capacity_, src);
160 assert(size_<capacity_);
164 template<
std::size_t SrcSz>
167 : size_(SrcSz-1), capacity_(size_+1) {
168 buffer.
template ctor<SrcSz>(src);
169 assert(size_<capacity_);
172 template<
unsigned int BuffN,
class charT,
class traits>
174 basic_stack_string<BuffN, charT, traits>::
basic_stack_string(basic_stack_string
const &str)
noexcept(
false)
175 : size_(str.size_), capacity_() {
178 buffer.cctor(capacity_, str.buffer);
179 assert(size_<capacity_);
183 template<
unsigned int BuffN,
class charT,
class traits>
185 basic_stack_string<BuffN, charT, traits>::
basic_stack_string(basic_stack_string &&str)
noexcept(
true)
186 : size_(str.size_), capacity_(str.capacity_), buffer(str.buffer) {
189 str.buffer.heap=
nullptr;
192 template<
unsigned int BuffN,
class charT,
class traits>
200 std::return_temporary_buffer(buffer.heap);
204 template<
unsigned int BuffN,
class charT,
class traits>
206 basic_stack_string<BuffN, charT, traits>::
swap(basic_stack_string &str)
noexcept(
true) {
207 std::swap(size_, str.size_);
208 std::swap(capacity_, str.capacity_);
209 buffer.swap(str.buffer);
212 template<
unsigned int BuffN,
class charT,
class traits>
213 inline basic_stack_string<BuffN, charT, traits> &
214 basic_stack_string<BuffN, charT, traits>::
operator=(basic_stack_string
const &str)
noexcept(
false) {
215 basic_stack_string tmp(str);
220 template<
unsigned int BuffN,
class charT,
class traits>
221 inline basic_stack_string<BuffN, charT, traits> &
222 basic_stack_string<BuffN, charT, traits>::
operator=(basic_stack_string &&str)
noexcept(
true) {
227 template<
unsigned int BuffN,
class charT,
class traits>
228 inline typename basic_stack_string<BuffN, charT, traits>::
iterator
229 basic_stack_string<BuffN, charT, traits>::
begin()
noexcept(
true) {
233 template<
unsigned int BuffN,
class charT,
class traits>
234 inline typename basic_stack_string<BuffN, charT, traits>::
const_iterator
235 basic_stack_string<BuffN, charT, traits>::
begin()
const noexcept(
true) {
239 template<
unsigned int BuffN,
class charT,
class traits>
240 inline typename basic_stack_string<BuffN, charT, traits>::
iterator
241 basic_stack_string<BuffN, charT, traits>::
end()
noexcept(
true) {
245 template<
unsigned int BuffN,
class charT,
class traits>
246 inline typename basic_stack_string<BuffN, charT, traits>::
const_iterator
247 basic_stack_string<BuffN, charT, traits>::
end()
const noexcept(
true) {
251 template<
unsigned int BuffN,
class charT,
class traits>
252 inline constexpr bool
253 basic_stack_string<BuffN, charT, traits>::
operator==(basic_stack_string
const &s)
const noexcept(
true) {
254 return size()==s.size() && memcmp(begin(), s.begin(),
size());
257 template<
unsigned int BuffN,
class charT,
class traits>
258 inline constexpr bool
259 basic_stack_string<BuffN, charT, traits>::
operator!=(basic_stack_string
const &s)
const noexcept(
true) {
263 template<
unsigned int BuffN,
class charT,
class traits>
264 inline constexpr typename basic_stack_string<BuffN, charT, traits>::
size_type
265 basic_stack_string<BuffN, charT, traits>::
size()
const noexcept(
true) {
269 template<
unsigned int BuffN,
class charT,
class traits>
284 tmp.copy(buffer.fast_copy_values);
287 assert(
static_cast<size_type>(ptr.second)<=s);
288 buffer.heap=ptr.first;
290 throw std::bad_alloc();
292 std::memcpy(buffer.heap, tmp.small_basic_stack_string, size_+1);
298 assert(
static_cast<size_type>(ptr.second)<=s);
300 throw std::bad_alloc();
302 std::memcpy(ptr.first, buffer.heap, size_+1);
303 std::swap(buffer.heap, ptr.first);
304 std::return_temporary_buffer(ptr.first);
308 assert(size_<capacity_);
312 template<
unsigned int BuffN,
class charT,
class traits>
318 assert(size_<capacity_);
321 template<
unsigned int BuffN,
class charT,
class traits>
326 assert(s<=capacity_);
327 buffer.fill_n(capacity_, size_, s-size_, i);
331 assert(size_<capacity_);
334 template<
unsigned int BuffN,
class charT,
class traits>
336 basic_stack_string<BuffN, charT, traits>::
clear()
noexcept(
true) {
341 template<
unsigned int BuffN,
class charT,
class traits>
342 inline constexpr bool
343 basic_stack_string<BuffN, charT, traits>::
empty()
const noexcept(
true) {
347 template<
unsigned int BuffN,
class charT,
class traits>
348 inline typename basic_stack_string<BuffN, charT, traits>::
reference
350 return *
std::next(begin(), p);
353 template<
unsigned int BuffN,
class charT,
class traits>
354 inline typename basic_stack_string<BuffN, charT, traits>::
const_reference
356 return *
std::next(begin(), p);
359 template<
unsigned int BuffN,
class charT,
class traits>
365 template<
unsigned int BuffN,
class charT,
class traits>
366 inline typename basic_stack_string<BuffN, charT, traits>::
iterator
369 assert(
static_cast<size_type>(std::distance(begin(), p))<=size_);
370 assert(
static_cast<size_type>(std::distance(p, end()))<=size_);
372 const typename iterator_traits::difference_type size_str_ins=
std::distance(b, e);
373 const typename iterator_traits::difference_type dist_in_str=
std::distance(begin(), p);
377 memmove(buffer.small_basic_stack_string+dist_in_str+size_str_ins, buffer.small_basic_stack_string+dist_in_str, size_-dist_in_str);
378 std::memcpy(buffer.small_basic_stack_string+dist_in_str, b, size_str_ins);
381 assert(size_<=capacity_);
384 memmove(buffer.heap+dist_in_str+size_str_ins, buffer.heap+dist_in_str, size_-dist_in_str);
385 std::memcpy(buffer.heap+dist_in_str, b, size_str_ins);
388 assert(size_<=capacity_);
389 return std::next(begin()+dist_in_str-1);
396 template<
unsigned int BuffN,
class charT,
class traits>
397 inline typename basic_stack_string<BuffN, charT, traits>::
iterator
400 assert(
static_cast<size_type>(std::distance(const_iterator(begin()), b))<=size_);
401 assert(
static_cast<size_type>(std::distance(b, const_iterator(end())))<=size_);
402 assert(
static_cast<size_type>(std::distance(const_iterator(begin()), e))<=size_);
403 assert(
static_cast<size_type>(std::distance(e, const_iterator(end())))<=size_);
405 const typename iterator_traits::difference_type first=
std::distance(
const_iterator(begin()), b);
406 const typename iterator_traits::difference_type last=
std::distance(
const_iterator(begin()), e);
407 buffer.move(capacity_, first, last, size_-last);
410 assert(size_<=capacity_);
411 return begin()+first;
417 template<
unsigned int BuffN,
class charT,
class traits>
418 inline basic_stack_string<BuffN, charT, traits> &
421 if (
LIKELY(src_b!=src_e)) {
426 assert(
static_cast<size_type>(std::distance(begin(), b))<=size_);
427 assert(
static_cast<size_type>(std::distance(b, end()))<=size_);
428 assert(
static_cast<size_type>(std::distance(begin(), e))<=size_);
429 assert(
static_cast<size_type>(std::distance(e, end()))<=size_);
431 const typename iterator_traits::difference_type first=
std::distance(begin(), b);
432 const typename iterator_traits::difference_type last=
std::distance(begin(), e);
433 const typename iterator_traits::difference_type replace_str_sz=
std::distance(src_b, src_e);
434 if (
LIKELY((last-first)>=replace_str_sz)) {
438 std::memcpy(buffer.small_basic_stack_string+first, src_b, replace_str_sz);
439 memmove(buffer.small_basic_stack_string+first+replace_str_sz, buffer.small_basic_stack_string+last, size_-last);
441 std::memcpy(buffer.heap+first, src_b, replace_str_sz);
442 memmove(buffer.heap+first+replace_str_sz, buffer.heap+last, size_-last);
444 size_-=(last-first)-replace_str_sz;
446 reserve(size_+(replace_str_sz-(last-first))+1
);
449 std::copy_backward(buffer.small_basic_stack_string+last, buffer.small_basic_stack_string+size_, buffer.small_basic_stack_string+first+replace_str_sz+size_-last);
450 std::memcpy(buffer.small_basic_stack_string+first, src_b, replace_str_sz);
452 std::copy_backward(buffer.heap+last, buffer.heap+size_, buffer.heap+first+replace_str_sz+size_-last);
453 std::memcpy(buffer.heap+first, src_b, replace_str_sz);
455 size_+=replace_str_sz-(last-first);
463 assert(size_<=capacity_);
467 template<
unsigned int BuffN,
class charT,
class traits>
inline std::basic_ostream<charT, traits> &
468 operator<<(
std::basic_ostream<charT, traits> &os, basic_stack_string<BuffN, charT, traits>
const &s)
noexcept(
false) {
469 os.write(s.begin(), s.size());
473 template<
unsigned int BuffN,
class charT,
class traits>
inline std::basic_istream<charT, traits> &
474 operator>>(
std::basic_istream<charT, traits> &is, basic_stack_string<BuffN, charT, traits> &s)
noexcept(
false) {
475 typename std::basic_istream<charT, traits>::int_type ret;
476 while ((ret=is.get())!=traits::eof()) {
477 s.push_back(
static_cast<
typename basic_stack_string<BuffN, charT, traits>::value_type>(ret));