📄 flex_string.hpp
字号:
template <typename E,
class T = std::char_traits<E>,
class A = std::allocator<E>,
class Storage = AllocatorStringStorage<E, A> >
class flex_string : private Storage
{
#if defined(THROW_ON_ENFORCE)
template <typename Exception>
static void Enforce(bool condition, Exception*, const char* msg)
{ if (!condition) throw Exception(msg); }
#else
template <typename Exception>
static inline void Enforce(bool condition, Exception*, const char* msg)
{ BOOST_ASSERT(condition && msg); }
#endif // defined(THROW_ON_ENFORCE)
bool Sane() const
{
return
begin() <= end() &&
empty() == (size() == 0) &&
empty() == (begin() == end()) &&
size() <= max_size() &&
capacity() <= max_size() &&
size() <= capacity();
}
struct Invariant;
friend struct Invariant;
struct Invariant
{
Invariant(const flex_string& s) : s_(s)
{
BOOST_ASSERT(s_.Sane());
}
~Invariant()
{
BOOST_ASSERT(s_.Sane());
}
private:
const flex_string& s_;
};
public:
// types
typedef T traits_type;
typedef typename traits_type::char_type value_type;
typedef A allocator_type;
typedef typename A::size_type size_type;
typedef typename A::difference_type difference_type;
typedef typename A::reference reference;
typedef typename A::const_reference const_reference;
typedef typename A::pointer pointer;
typedef typename A::const_pointer const_pointer;
typedef typename Storage::iterator iterator;
typedef typename Storage::const_iterator const_iterator;
typedef boost::reverse_iterator<iterator> reverse_iterator;
typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
static const size_type npos; // = size_type(-1)
private:
static size_type Min(size_type lhs, size_type rhs)
{ return lhs < rhs ? lhs : rhs; }
public:
// 21.3.1 construct/copy/destroy
explicit flex_string(const A& a = A())
: Storage(a)
{}
flex_string(const flex_string& str)
: Storage(str)
{
}
flex_string(const flex_string& str, size_type pos,
size_type n = npos, const A& a = A())
: Storage(a)
{
Enforce(pos <= str.size(), (std::out_of_range*)0, "");
assign(str, pos, n);
}
flex_string(const value_type* s, const A& a = A())
: Storage(s, traits_type::length(s), a)
{}
flex_string(const value_type* s, size_type n, const A& a = A())
: Storage(s, n, a)
{}
flex_string(size_type n, value_type c, const A& a = A())
: Storage(n, c, a)
{}
template <class InputIterator>
flex_string(InputIterator begin, InputIterator end, const A& a = A())
: Storage(a)
{
assign(begin, end);
}
~flex_string()
{}
flex_string& operator=(const flex_string& str)
{
if (this != &str) {
Storage& s = *this;
s = str;
}
return *this;
}
flex_string& operator=(const value_type* s)
{
assign(s);
return *this;
}
flex_string& operator=(value_type c)
{
assign(1, c);
return *this;
}
// 21.3.2 iterators:
iterator begin()
{ return Storage::begin(); }
const_iterator begin() const
{ return Storage::begin(); }
iterator end()
{ return Storage::end(); }
const_iterator end() const
{ return Storage::end(); }
reverse_iterator rbegin()
{ return reverse_iterator(end()); }
const_reverse_iterator rbegin() const
{ return const_reverse_iterator(end()); }
reverse_iterator rend()
{ return reverse_iterator(begin()); }
const_reverse_iterator rend() const
{ return const_reverse_iterator(begin()); }
// 21.3.3 capacity:
size_type size() const
{ return Storage::size(); }
size_type length() const
{ return size(); }
size_type max_size() const
{ return Storage::max_size(); }
void resize(size_type n, value_type c)
{ Storage::resize(n, c); }
void resize(size_type n)
{ resize(n, value_type()); }
size_type capacity() const
{ return Storage::capacity(); }
void reserve(size_type res_arg = 0)
{
Enforce(res_arg <= max_size(), (std::length_error*)0, "");
Storage::reserve(res_arg);
}
void clear()
{ resize(0); }
bool empty() const
{ return size() == 0; }
// 21.3.4 element access:
const_reference operator[](size_type pos) const
{ return *(begin() + pos); }
reference operator[](size_type pos)
{ return *(begin() + pos); }
const_reference at(size_type n) const
{
Enforce(n < size(), (std::out_of_range*)0, "");
return (*this)[n];
}
reference at(size_type n)
{
Enforce(n < size(), (std::out_of_range*)0, "");
return (*this)[n];
}
// 21.3.5 modifiers:
flex_string& operator+=(const flex_string& str)
{ return append(str); }
flex_string& operator+=(const value_type* s)
{ return append(s); }
flex_string& operator+=(value_type c)
{
const size_type cap = capacity();
if (size() == cap)
{
reserve(cap << 1u);
}
resize(size() + 1, c);
return *this;
}
flex_string& append(const flex_string& str)
{ return append(str, 0, npos); }
flex_string& append(const flex_string& str, size_type pos,
size_type n)
{
const size_type sz = str.size();
Enforce(pos <= sz, (std::out_of_range*)0, "");
return append(str.c_str() + pos, Min(n, sz - pos));
}
flex_string& append(const value_type* s, size_type n)
{
Storage::append(s, n);
return *this;
}
flex_string& append(const value_type* s)
{ return append(s, traits_type::length(s)); }
flex_string& append(size_type n, value_type c)
{
resize(size() + n, c);
return *this;
}
/*
template<class InputIterator>
flex_string& append(InputIterator first, InputIterator last)
{
for (; first != last; ++first) *this += E(*first);
return *this;
}
*/
void push_back(value_type c)
{
*this += c;
}
flex_string& assign(const flex_string& str)
{
if (&str == this) return *this;
replace(0, size(), &*str.begin(), str.size());
return *this;
}
flex_string& assign(const flex_string& str, size_type pos,
size_type n)
{
Enforce(pos <= str.size(), (std::out_of_range*)0, "");
return assign(str.data() + pos, Min(n, str.size() - pos));
}
flex_string& assign(const value_type* s, size_type n)
{
if (size() >= n)
{
flex_string_details::pod_move(s, s + n, &*begin());
resize(n, value_type());
}
else
{
flex_string_details::pod_move(s, s + size(), &*begin());
Storage::append(s + size(), n - size());
}
return *this;
}
flex_string& assign(const value_type* s)
{ return assign(s, traits_type::length(s)); }
flex_string& assign(size_type n, value_type c)
{ return replace(begin(), end(), n, c); }
template<class InputIterator>
flex_string& assign(InputIterator first, InputIterator last)
{ return replace(begin(), end(), first, last); }
flex_string& insert(size_type pos1, const flex_string& str)
{ return insert(pos1, str, 0, npos); }
flex_string& insert(size_type pos1, const flex_string& str,
size_type pos2, size_type n)
{ return replace(pos1, 0, str, pos2, n); }
flex_string& insert(size_type pos, const value_type* s, size_type n)
{ return replace(pos, 0, s, n); }
flex_string& insert(size_type pos, const value_type* s)
{ return insert(pos, s, traits_type::length(s)); }
flex_string& insert(size_type pos, size_type n, value_type c)
{ return replace(pos, 0, n, c); }
iterator insert(iterator p, value_type c = value_type())
{
const size_type pos = p - begin();
insert(pos, &c, 1);
return begin() + pos;
}
void insert(iterator p, size_type n, value_type c)
{ insert(p - begin(), n, c); }
template<class InputIterator>
void insert(iterator p, InputIterator first, InputIterator last)
{ replace(p, p, first, last); }
flex_string& erase(size_type pos = 0, size_type n = npos)
{
return replace(pos, Min(n, size() - pos), 0, value_type());
}
iterator erase(iterator position)
{
const size_type pos(position - begin());
erase(pos, 1);
return begin() + pos;
}
iterator erase(iterator first, iterator last)
{
const size_type pos(first - begin());
erase(pos, last - first);
return begin() + pos;
}
// @@@ replace
flex_string& replace(size_type pos1, size_type n1, const flex_string& str)
{ return replace(pos1, n1, str, 0, npos); }
flex_string& replace(size_type pos1, size_type n1, const flex_string& str,
size_type pos2, size_type n2)
{
Enforce(pos1 <= length() && pos2 <= str.length(),
(std::out_of_range*)0, "");
return replace(pos1, n1, &*str.begin() + pos2,
Min(n2, str.length() - pos2));
}
flex_string& replace(const size_type d, size_type n1, const value_type* s1,
const size_type n2)
{
using namespace flex_string_details;
Enforce(d <= size(), (std::out_of_range*)0, "");
if (d + n1 > size()) n1 = size() - d;
const int delta = int(n2 - n1);
static const std::less_equal<const value_type*> le =
std::less_equal<const value_type*>();
const bool aliased = le(&*begin(), s1) && le(s1, &*end());
if (delta > 0)
{
if (capacity() < size() + delta)
{
// realloc the string
if (aliased)
{
const size_type offset = s1 - &*begin();
reserve(size() + delta);
s1 = &*begin() + offset;
}
else
{
reserve(size() + delta);
}
}
const value_type* s2 = s1 + n2;
value_type* d1 = &*begin() + d;
value_type* d2 = d1 + n1;
const int tailLen = int(&*end() - d2);
if (delta <= tailLen)
{
value_type* oldEnd = &*end();
// simple case
Storage::append(oldEnd - delta, delta);
pod_move(d2, d2 + (tailLen - delta), d2 + delta);
if (le(d2, s1))
{
if (aliased)
{
pod_copy(s1 + delta, s2 + delta, d1);
}
else
{
pod_copy(s1, s2, d1);
}
}
else
{
// d2 > s1
if (le(d2, s2))
{
BOOST_ASSERT(aliased);
pod_move(s1, d2, d1);
pod_move(d2 + delta, s2 + delta, d1 + (d2 - s1));
}
else
{
pod_move(s1, s2, d1);
}
}
}
else
{
const size_type sz = delta - tailLen;
Storage::append(s2 - sz, sz);
Storage::append(d2, tailLen);
pod_move(s1, s2 - (delta - tailLen), d1);
}
}
else
{
pod_move(s1, s1 + n2, &*begin() + d);
pod_move(&*begin() + d + n1, &*end(), &*begin() + d + n1 + delta);
resize(size() + delta);
}
return *this;
}
flex_string& replace(size_type pos, size_type n1, const value_type* s)
{ return replace(pos, n1, s, traits_type::length(s)); }
flex_string& replace(size_type pos, size_type n1, size_type n2,
value_type c)
{
if (pos + n1 > size()) n1 = size() - pos;
const size_type oldSize = size();
if (pos + n2 > oldSize)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -