// // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/fixed_string // #ifndef BOOST_FIXED_STRING_IMPL_FIXED_STRING_HPP #define BOOST_FIXED_STRING_IMPL_FIXED_STRING_HPP #include #include #include #include namespace boost { namespace fixed_string { //------------------------------------------------------------------------------ // // Construction // //------------------------------------------------------------------------------ template fixed_string:: fixed_string() { n_ = 0; term(); } template fixed_string:: fixed_string(size_type count, CharT ch) { assign(count, ch); } template template fixed_string:: fixed_string(fixed_string const& other, size_type pos) { assign(other, pos); } template template fixed_string:: fixed_string( fixed_string const& other, size_type pos, size_type count) { assign(other, pos, count); } template fixed_string:: fixed_string(CharT const* s, size_type count) { assign(s, count); } template fixed_string:: fixed_string(CharT const* s) { auto const count = Traits::length(s); if(count > max_size()) BOOST_THROW_EXCEPTION(std::length_error{ "count > max_size()"}); n_ = count; Traits::copy(&s_[0], s, n_ + 1); } template template fixed_string:: fixed_string( InputIt first, InputIt last, typename std::enable_if< detail::is_input_iterator::value, iterator>::type*) { assign(first, last); } template fixed_string:: fixed_string( fixed_string const& s) { assign(s); } template template fixed_string:: fixed_string( fixed_string const& s) { assign(s); } template fixed_string:: fixed_string(std::initializer_list init) { assign(init.begin(), init.end()); } template fixed_string:: fixed_string(string_view_type sv) { assign(sv); } template template fixed_string:: fixed_string(T const& t, size_type pos, size_type n) { assign(t, pos, n); } //------------------------------------------------------------------------------ // // Assignment // //------------------------------------------------------------------------------ template auto fixed_string:: assign( size_type count, CharT ch) -> fixed_string& { if(count > max_size()) BOOST_THROW_EXCEPTION(std::length_error{ "count > max_size()"}); n_ = count; Traits::assign(&s_[0], n_, ch); term(); return *this; } template auto fixed_string:: assign( fixed_string const& s) noexcept -> fixed_string& { if(this == &s) return *this; n_ = s.n_; auto const n = n_ + 1; // VFALCO This informs the static analyzer //BOOST_BEAST_ASSUME(n != 0); Traits::copy(&s_[0], &s.s_[0], n); return *this; } template template auto fixed_string:: assign( fixed_string const& s, size_type pos, size_type count) -> fixed_string& { auto const ss = s.substr(pos, count); return assign(ss.data(), ss.size()); } template auto fixed_string:: assign( CharT const* s, size_type count) -> fixed_string& { if(count > max_size()) BOOST_THROW_EXCEPTION(std::length_error{ "count > max_size()"}); n_ = count; Traits::copy(&s_[0], s, n_); term(); return *this; } template template auto fixed_string:: assign( InputIt first, InputIt last) -> typename std::enable_if< detail::is_input_iterator::value, fixed_string&>::type { std::size_t const n = std::distance(first, last); if(n > max_size()) BOOST_THROW_EXCEPTION(std::length_error{ "n > max_size()"}); n_ = n; for(auto it = &s_[0]; first != last; ++it, ++first) Traits::assign(*it, *first); term(); return *this; } //------------------------------------------------------------------------------ // // Element access // //------------------------------------------------------------------------------ template auto fixed_string:: at(size_type pos) -> reference { if(pos >= size()) BOOST_THROW_EXCEPTION(std::out_of_range{ "pos >= size()"}); return s_[pos]; } template auto fixed_string:: at(size_type pos) const -> const_reference { if(pos >= size()) BOOST_THROW_EXCEPTION(std::out_of_range{ "pos >= size()"}); return s_[pos]; } //------------------------------------------------------------------------------ // // Capacity // //------------------------------------------------------------------------------ template void fixed_string:: reserve(std::size_t n) { if(n > max_size()) BOOST_THROW_EXCEPTION(std::length_error{ "n > max_size()"}); } //------------------------------------------------------------------------------ // // Operations // //------------------------------------------------------------------------------ template void fixed_string:: clear() { n_ = 0; term(); } //------------------------------------------------------------------------------ template auto fixed_string:: insert( size_type index, size_type count, CharT ch) -> fixed_string& { if(index > size()) BOOST_THROW_EXCEPTION(std::out_of_range{ "index > size()"}); insert(begin() + index, count, ch); return *this; } template auto fixed_string:: insert( size_type index, CharT const* s, size_type count) -> fixed_string& { if(index > size()) BOOST_THROW_EXCEPTION(std::out_of_range{ "index > size()"}); if(size() + count > max_size()) BOOST_THROW_EXCEPTION(std::length_error{ "size() + count > max_size()"}); Traits::move( &s_[index + count], &s_[index], size() - index); n_ += count; Traits::copy(&s_[index], s, count); term(); return *this; } template auto fixed_string:: insert( const_iterator pos, size_type count, CharT ch) -> iterator { if(size() + count > max_size()) BOOST_THROW_EXCEPTION(std::length_error{ "size() + count() > max_size()"}); auto const index = pos - &s_[0]; Traits::move( &s_[index + count], &s_[index], size() - index); n_ += count; Traits::assign(&s_[index], count, ch); term(); return &s_[index]; } template template auto fixed_string:: insert( const_iterator pos, InputIt first, InputIt last) -> typename std::enable_if< detail::is_input_iterator< InputIt>::value, iterator>::type { std::size_t const count = std::distance(first, last); if(size() + count > max_size()) BOOST_THROW_EXCEPTION(std::length_error{ "size() + count > max_size()"}); std::size_t const index = pos - begin(); Traits::move( &s_[index + count], &s_[index], size() - index); n_ += count; for(auto it = begin() + index; first != last; ++it, ++first) Traits::assign(*it, *first); term(); return begin() + index; } template template auto fixed_string:: insert( size_type index, T const & t) -> typename std::enable_if< std::is_convertible< T const&, string_view_type>::value && ! std::is_convertible< T const&, CharT const*>::value, fixed_string& >::type { return insert(index, t, 0, npos); } template template auto fixed_string:: insert( size_type index, T const & t, size_type index_str, size_type count) -> typename std::enable_if< std::is_convertible< T const&, string_view_type>::value && ! std::is_convertible< T const&, CharT const*>::value, fixed_string& >::type { auto const s = string_view_type(t).substr(index_str, count); return insert(index, s.data(), s.size()); } //------------------------------------------------------------------------------ template auto fixed_string:: erase( size_type index, size_type count) -> fixed_string& { if(index > size()) BOOST_THROW_EXCEPTION(std::out_of_range{ "index > size()"}); auto const n = (std::min)(count, size() - index); Traits::move( &s_[index], &s_[index + n], size() - (index + n) + 1); n_ -= n; return *this; } template auto fixed_string:: erase( const_iterator pos) -> iterator { erase(pos - begin(), 1); return begin() + (pos - begin()); } template auto fixed_string:: erase( const_iterator first, const_iterator last) -> iterator { erase(first - begin(), std::distance(first, last)); return begin() + (first - begin()); } template void fixed_string:: push_back( CharT ch) { if(size() >= max_size()) BOOST_THROW_EXCEPTION(std::length_error{ "size() >= max_size()"}); Traits::assign(s_[n_++], ch); term(); } template auto fixed_string:: append( CharT const* s, size_type count) -> fixed_string& { if(size() + count > max_size()) BOOST_THROW_EXCEPTION(std::length_error{ "size() + count > max_size()"}); Traits::move( &s_[n_ + count], &s_[n_], size() - n_); Traits::copy(&s_[n_], s, count); n_ += count; term(); return *this; } template auto fixed_string:: substr(size_type pos, size_type count) const -> string_view_type { if(pos > size()) BOOST_THROW_EXCEPTION(std::out_of_range{ "pos > size()"}); return{&s_[pos], (std::min)(count, size() - pos)}; } template auto fixed_string:: copy(CharT* dest, size_type count, size_type pos) const -> size_type { auto const s = substr(pos, count); Traits::copy(dest, s.data(), s.size()); return s.size(); } template void fixed_string:: resize(std::size_t n) { if(n > max_size()) BOOST_THROW_EXCEPTION(std::length_error{ "n > max_size()"}); if(n > n_) Traits::assign(&s_[n_], n - n_, CharT{}); n_ = n; term(); } template void fixed_string:: resize(std::size_t n, CharT c) { if(n > max_size()) BOOST_THROW_EXCEPTION(std::length_error{ "n > max_size()"}); if(n > n_) Traits::assign(&s_[n_], n - n_, c); n_ = n; term(); } template void fixed_string:: swap(fixed_string& s) { fixed_string tmp(s); s.n_ = n_; Traits::copy(&s.s_[0], &s_[0], n_ + 1); n_ = tmp.n_; Traits::copy(&s_[0], &tmp.s_[0], n_ + 1); } template template void fixed_string:: swap(fixed_string& s) { if(size() > s.max_size()) BOOST_THROW_EXCEPTION(std::length_error{ "size() > s.max_size()"}); if(s.size() > max_size()) BOOST_THROW_EXCEPTION(std::length_error{ "s.size() > max_size()"}); fixed_string tmp(s); s.n_ = n_; Traits::copy(&s.s_[0], &s_[0], n_ + 1); n_ = tmp.n_; Traits::copy(&s_[0], &tmp.s_[0], n_ + 1); } template auto fixed_string:: replace( size_type pos, size_type n1, const CharT* s, size_type n2) -> fixed_string& { if (pos > size()) BOOST_THROW_EXCEPTION(std::out_of_range{ "pos > size()"}); if ((size() - n1 + n2) > max_size()) BOOST_THROW_EXCEPTION(std::length_error{ "replaced string exceeds max_size()"}); Traits::move(&s_[pos + n2], &s_[pos + n1], size() - pos - n1 + 1); Traits::copy(&s_[pos], s, n2); n_ += (n2 - n1); return *this; } template auto fixed_string:: replace( size_type pos, size_type n1, size_type n2, CharT c) -> fixed_string & { if (pos > size()) BOOST_THROW_EXCEPTION(std::out_of_range{ "pos > size()"}); if ((size() - n1 + n2) > max_size()) BOOST_THROW_EXCEPTION(std::length_error{ "replaced string exceeds max_size()"}); Traits::move(&s_[pos + n2], &s_[pos + n1], size() - pos - n1 + 1); Traits::assign(&s_[pos], n2, c); n_ += (n2 - n1); return *this; } template auto fixed_string:: assign_char(CharT ch, std::true_type) -> fixed_string& { n_ = 1; Traits::assign(s_[0], ch); term(); return *this; } template auto fixed_string:: assign_char(CharT, std::false_type) -> fixed_string& { BOOST_THROW_EXCEPTION(std::length_error{ "max_size() == 0"}); } template fixed_string to_fixed_string(Integer x) { using CharT = char; using Traits = std::char_traits; BOOST_STATIC_ASSERT(std::is_integral::value); char buf[detail::max_digits(sizeof(Integer))]; auto last = buf + sizeof(buf); auto it = detail::raw_to_string< CharT, Integer, Traits>(last, sizeof(buf), x); fixed_string s; s.resize(static_cast(last - it)); auto p = s.data(); while(it < last) Traits::assign(*p++, *it++); return s; } } // fixed_string } // boost #endif