📄 flex_string_shell.h
字号:
////////////////////////////////////////////////////////////////////////////////
// flex_string
// Copyright (c) 2001 by Andrei Alexandrescu
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author makes no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
#ifndef FLEX_STRING_SHELL_INC_
#define FLEX_STRING_SHELL_INC_
///////////////////////////////////////////////////////////////////////////////
// class template flex_string
// This file does not include any storage policy headers
///////////////////////////////////////////////////////////////////////////////
#include <memory>
#include <algorithm>
#include <functional>
#include <cassert>
#include <limits>
#include <stdexcept>
#include "flex_string_details.h"
#include <string>
// Forward declaration for default storage policy
template <typename E, class A> class AllocatorStringStorage;
template <class T> class mallocator
{
public:
typedef T value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef std::size_t size_type;
//typedef unsigned int size_type;
//typedef std::ptrdiff_t difference_type;
typedef int difference_type;
template <class U>
struct rebind { typedef mallocator<U> other; };
mallocator() {}
mallocator(const mallocator&) {}
//template <class U>
//mallocator(const mallocator<U>&) {}
~mallocator() {}
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const
{
return x;
}
pointer allocate(size_type n, const_pointer = 0)
{
using namespace std;
void* p = malloc(n * sizeof(T));
if (!p) throw bad_alloc();
return static_cast<pointer>(p);
}
void deallocate(pointer p, size_type)
{
using namespace std;
free(p);
}
size_type max_size() const
{
return static_cast<size_type>(-1) / sizeof(T);
}
void construct(pointer p, const value_type& x)
{
new(p) value_type(x);
}
void destroy(pointer p)
{
p->~value_type();
}
private:
void operator=(const mallocator&);
};
template<> class mallocator<void>
{
typedef void value_type;
typedef void* pointer;
typedef const void* const_pointer;
template <class U>
struct rebind { typedef mallocator<U> other; };
};
template <class T>
inline bool operator==(const mallocator<T>&,
const mallocator<T>&) {
return true;
}
template <class T>
inline bool operator!=(const mallocator<T>&,
const mallocator<T>&) {
return false;
}
template <class Allocator>
typename Allocator::pointer Reallocate(
Allocator& alloc,
typename Allocator::pointer p,
typename Allocator::size_type oldObjCount,
typename Allocator::size_type newObjCount,
void*)
{
// @@@ not implemented
}
template <class Allocator>
typename Allocator::pointer Reallocate(
Allocator& alloc,
typename Allocator::pointer p,
typename Allocator::size_type oldObjCount,
typename Allocator::size_type newObjCount,
mallocator<void>*)
{
// @@@ not implemented
}
////////////////////////////////////////////////////////////////////////////////
// class template flex_string
// a std::basic_string compatible implementation
// Uses a Storage policy
////////////////////////////////////////////////////////////////////////////////
template <typename E,
class T = std::char_traits<E>,
class A = std::allocator<E>,
class Storage = AllocatorStringStorage<E, A> >
class flex_string : private Storage
{
template <typename Exception>
static void Enforce(bool condition, Exception*, const char* msg)
{ if (!condition) throw Exception(msg); }
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
{
#ifndef NDEBUG
Invariant(const flex_string& s) : s_(s)
{
assert(s_.Sane());
}
~Invariant()
{
assert(s_.Sane());
}
private:
const flex_string& s_;
#else
Invariant(const flex_string&) {}
#endif
Invariant& operator=(const Invariant&);
};
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 Storage::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 std::reverse_iterator<iterator
#ifdef NO_ITERATOR_TRAITS
, value_type
#endif
> reverse_iterator;
typedef std::reverse_iterator<const_iterator
#ifdef NO_ITERATOR_TRAITS
, const value_type
#endif
> 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; }
static void Procust(size_type& n, size_type nmax)
{ if (n > nmax) n = nmax; }
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)
{
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)
{
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(), static_cast<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 *(c_str() + pos); }
reference operator[](size_type pos)
{ return *(begin() + pos); }
const_reference at(size_type n) const
{
Enforce(n <= size(), static_cast<std::out_of_range*>(0), "");
return (*this)[n];
}
reference at(size_type n)
{
Enforce(n < size(), static_cast<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+=(const value_type c)
{
push_back(c);
return *this;
}
flex_string& append(const flex_string& str)
{ return append(str.data(), str.length()); }
flex_string& append(const flex_string& str, const size_type pos,
size_type n)
{
const size_type sz = str.size();
Enforce(pos <= sz, static_cast<std::out_of_range*>(0), "");
Procust(n, sz - pos);
return append(str.data() + pos, n);
}
flex_string& append(const value_type* s, const size_type n)
{
Invariant checker(*this);
(void) checker;
static std::less_equal<const value_type*> le;
if (le(&*begin(), s) && le(s, &*end())) // aliasing
{
const size_type offset = s - &*begin();
Storage::reserve(size() + n);
s = &*begin() + offset;
}
Storage::append(s, 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)
{
insert(end(), first, last);
return *this;
}
void push_back(const value_type c) // primitive
{
const size_type cap = capacity();
if (size() == cap)
{
reserve(cap << 1u);
}
Storage::append(&c, &c + 1);
}
flex_string& assign(const flex_string& str)
{
if (&str == this) return *this;
return assign(str.data(), str.size());
}
flex_string& assign(const flex_string& str, const size_type pos,
size_type n)
{
const size_type sz = str.size();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -