📄 flex_string.hpp
字号:
/*=============================================================================
Boost.Wave: A Standard compliant C++ preprocessor library
http://www.boost.org/
Copyright (c) 2001 by Andrei Alexandrescu. 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)
=============================================================================*/
// This code is taken from:
// Andrei Alexandrescu, Generic<Programming>: A Policy-Based basic_string
// Implementation. http://www.cuj.com/documents/s=7994/cujcexp1906alexandr/
//
// #HK030306:
// - Moved into the namespace boost::wave::util
// - Added a bunch of missing typename(s)
// - Integrated with boost config
// - Added a missing header include
// - Added special constructors and operator= to allow CowString to be
// a real COW-string (removed unnecessary data copying)
// - Fixed a string terminating bug in append
//
// #HK040109:
// - Incorporated the changes from Andrei's latest version of this class
#ifndef FLEX_STRING_INC_
#define FLEX_STRING_INC_
/*
////////////////////////////////////////////////////////////////////////////////
template <typename E, class A = @>
class StoragePolicy
{
typedef E value_type;
typedef @ iterator;
typedef @ const_iterator;
typedef A allocator_type;
typedef @ size_type;
StoragePolicy(const StoragePolicy& s);
StoragePolicy(const A&);
StoragePolicy(const E* s, size_type len, const A&);
StoragePolicy(size_type len, E c, const A&);
~StoragePolicy();
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
size_type size() const;
size_type max_size() const;
size_type capacity() const;
void reserve(size_type res_arg);
void append(const E* s, size_type sz);
template <class InputIterator>
void append(InputIterator b, InputIterator e);
void resize(size_type newSize, E fill);
void swap(StoragePolicy& rhs);
const E* c_str() const;
const E* data() const;
A get_allocator() const;
};
////////////////////////////////////////////////////////////////////////////////
*/
#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/iterator/reverse_iterator.hpp>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <limits>
#include <stdexcept>
#include <cstddef>
///////////////////////////////////////////////////////////////////////////////
namespace boost {
namespace wave {
namespace util {
namespace flex_string_details
{
template <class Pod, class T>
inline void pod_fill(Pod* b, Pod* e, T c)
{
switch ((e - b) & 7)
{
case 0:
while (b != e)
{
*b = c; ++b;
case 7: *b = c; ++b;
case 6: *b = c; ++b;
case 5: *b = c; ++b;
case 4: *b = c; ++b;
case 3: *b = c; ++b;
case 2: *b = c; ++b;
case 1: *b = c; ++b;
}
}
}
template <class Pod>
inline void pod_move(const Pod* b, const Pod* e, Pod* d)
{
using namespace std;
memmove(d, b, (e - b) * sizeof(*b));
}
template <class Pod>
inline Pod* pod_copy(const Pod* b, const Pod* e, Pod* d)
{
const std::size_t s = e - b;
using namespace std;
memcpy(d, b, s * sizeof(*b));
return d + s;
}
template <typename T> struct get_unsigned
{
typedef T result;
};
template <> struct get_unsigned<char>
{
typedef unsigned char result;
};
template <> struct get_unsigned<signed char>
{
typedef unsigned char result;
};
template <> struct get_unsigned<short int>
{
typedef unsigned short int result;
};
template <> struct get_unsigned<int>
{
typedef unsigned int result;
};
template <> struct get_unsigned<long int>
{
typedef unsigned long int result;
};
enum Shallow {};
}
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
return NULL;
}
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
return NULL;
}
////////////////////////////////////////////////////////////////////////////////
// class template SimpleStringStorage
// Allocates memory with malloc
////////////////////////////////////////////////////////////////////////////////
template <typename E, class A = std::allocator<E> >
class SimpleStringStorage
{
// The "public" below exists because MSVC can't do template typedefs
public:
struct Data
{
Data() : pEnd_(buffer_), pEndOfMem_(buffer_) { buffer_[0] = E(0); }
E* pEnd_;
E* pEndOfMem_;
E buffer_[1];
};
static const Data emptyString_;
typedef typename A::size_type size_type;
private:
Data* pData_;
void Init(size_type size, size_type capacity)
{
BOOST_ASSERT(size <= capacity);
if (capacity == 0)
{
pData_ = const_cast<Data*>(&emptyString_);
}
else
{
// 11-17-2000: comment added:
// No need to allocate (capacity + 1) to
// accomodate the terminating 0, because Data already
// has one one character in there
pData_ = static_cast<Data*>(
malloc(sizeof(Data) + capacity * sizeof(E)));
if (!pData_) throw std::bad_alloc();
pData_->pEnd_ = pData_->buffer_ + size;
pData_->pEndOfMem_ = pData_->buffer_ + capacity;
}
}
private:
// Warning - this doesn't initialize pData_. Used in reserve()
SimpleStringStorage()
{ }
public:
typedef E value_type;
typedef E* iterator;
typedef const E* const_iterator;
typedef A allocator_type;
SimpleStringStorage(const SimpleStringStorage& rhs)
{
const size_type sz = rhs.size();
Init(sz, sz);
if (sz) flex_string_details::pod_copy(rhs.begin(), rhs.end(), begin());
}
SimpleStringStorage(const SimpleStringStorage& s,
flex_string_details::Shallow)
: pData_(s.pData_)
{
}
SimpleStringStorage(const A&)
{ pData_ = const_cast<Data*>(&emptyString_); }
SimpleStringStorage(const E* s, size_type len, const A&)
{
Init(len, len);
flex_string_details::pod_copy(s, s + len, begin());
}
SimpleStringStorage(size_type len, E c, const A&)
{
Init(len, len);
flex_string_details::pod_fill(begin(), end(), c);
}
SimpleStringStorage& operator=(const SimpleStringStorage& rhs)
{
const size_type sz = rhs.size();
reserve(sz);
flex_string_details::pod_copy(&*rhs.begin(), &*rhs.end(), begin());
pData_->pEnd_ = &*begin() + sz;
return *this;
}
~SimpleStringStorage()
{
BOOST_ASSERT(begin() <= end());
if (pData_ != &emptyString_) free(pData_);
}
iterator begin()
{ return pData_->buffer_; }
const_iterator begin() const
{ return pData_->buffer_; }
iterator end()
{ return pData_->pEnd_; }
const_iterator end() const
{ return pData_->pEnd_; }
size_type size() const
{ return pData_->pEnd_ - pData_->buffer_; }
size_type max_size() const
{ return std::size_t(-1) / sizeof(E) - sizeof(Data) - 1; }
size_type capacity() const
{ return pData_->pEndOfMem_ - pData_->buffer_; }
void reserve(size_type res_arg)
{
if (res_arg <= capacity())
{
// @@@ insert shrinkage here if you wish
return;
}
if (pData_ == &emptyString_)
{
Init(0, res_arg);
}
else
{
const size_type sz = size();
void* p = realloc(pData_,
sizeof(Data) + res_arg * sizeof(E));
if (!p) throw std::bad_alloc();
if (p != pData_)
{
pData_ = static_cast<Data*>(p);
pData_->pEnd_ = pData_->buffer_ + sz;
}
pData_->pEndOfMem_ = pData_->buffer_ + res_arg;
}
}
void append(const E* s, size_type sz)
{
const size_type neededCapacity = size() + sz;
if (capacity() < neededCapacity)
{
const iterator b = begin();
static std::less_equal<const E*> le;
if (le(b, s) && le(s, end()))
{
// aliased
const size_type offset = s - b;
reserve(neededCapacity);
s = begin() + offset;
}
else
{
reserve(neededCapacity);
}
}
flex_string_details::pod_copy(s, s + sz, end());
pData_->pEnd_ += sz;
}
template <class InputIterator>
void append(InputIterator b, InputIterator e)
{
// @@@ todo: optimize this depending on iterator type
for (; b != e; ++b)
{
*this += *b;
}
}
void resize(size_type newSize, E fill)
{
const int delta = int(newSize - size());
if (delta == 0) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -