flex_string.hpp
字号:
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; if (delta > 0) { if (newSize > capacity()) { reserve(newSize); } E* e = &*end(); flex_string_details::pod_fill(e, e + delta, fill); } pData_->pEnd_ = pData_->buffer_ + newSize; } void swap(SimpleStringStorage& rhs) { std::swap(pData_, rhs.pData_); } const E* c_str() const { if (pData_ != &emptyString_) *pData_->pEnd_ = E(); return pData_->buffer_; } const E* data() const { return pData_->buffer_; } A get_allocator() const { return A(); }};template <typename E, class A>const typename SimpleStringStorage<E, A>::DataSimpleStringStorage<E, A>::emptyString_ = typename SimpleStringStorage<E, A>::Data();//{ // const_cast<E*>(SimpleStringStorage<E, A>::emptyString_.buffer_), // const_cast<E*>(SimpleStringStorage<E, A>::emptyString_.buffer_), // { E() }//};////////////////////////////////////////////////////////////////////////////////// class template AllocatorStringStorage// Allocates with your allocator// Takes advantage of the Empty Base Optimization if available////////////////////////////////////////////////////////////////////////////////template <typename E, class A = std::allocator<E> >class AllocatorStringStorage : public A{ typedef typename A::size_type size_type; typedef typename SimpleStringStorage<E, A>::Data Data; void* Alloc(size_type sz, const void* p = 0) { return A::allocate(1 + (sz - 1) / sizeof(E), static_cast<const char*>(p)); } void* Realloc(void* p, size_type oldSz, size_type newSz) { void* r = Alloc(newSz); flex_string_details::pod_copy(p, p + Min(oldSz, newSz), r); Free(p, oldSz); return r; } void Free(void* p, size_type sz) { A::deallocate(static_cast<E*>(p), sz); } Data* pData_; void Init(size_type size, size_type cap) { BOOST_ASSERT(size <= cap); if (cap == 0) { pData_ = const_cast<Data*>( &SimpleStringStorage<E, A>::emptyString_); } else { pData_ = static_cast<Data*>(Alloc( cap * sizeof(E) + sizeof(Data))); pData_->pEnd_ = pData_->buffer_ + size; pData_->pEndOfMem_ = pData_->buffer_ + cap; } } public: typedef E value_type; typedef A allocator_type; typedef typename A::pointer iterator; typedef typename A::const_pointer const_iterator; AllocatorStringStorage() : A(), pData_(0) { } AllocatorStringStorage(const AllocatorStringStorage& rhs) : A(rhs.get_allocator()) { const size_type sz = rhs.size(); Init(sz, sz); if (sz) flex_string_details::pod_copy(rhs.begin(), rhs.end(), begin()); } AllocatorStringStorage(const AllocatorStringStorage& s, flex_string_details::Shallow) : A(s.get_allocator()) { pData_ = s.pData_; } AllocatorStringStorage(const A& a) : A(a) { pData_ = const_cast<Data*>( &SimpleStringStorage<E, A>::emptyString_); } AllocatorStringStorage(const E* s, size_type len, const A& a) : A(a) { Init(len, len); flex_string_details::pod_copy(s, s + len, begin()); } AllocatorStringStorage(size_type len, E c, const A& a) : A(a) { Init(len, len); flex_string_details::pod_fill(&*begin(), &*end(), c); } AllocatorStringStorage& operator=(const AllocatorStringStorage& rhs) { const size_type sz = rhs.size(); reserve(sz); flex_string_details::pod_copy(&*rhs.begin(), &*rhs.end(), begin()); pData_->pEnd_ = &*begin() + rhs.size(); return *this; } ~AllocatorStringStorage() { if (capacity()) { Free(pData_, sizeof(Data) + capacity() * sizeof(E)); } } 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 size_type(end() - begin()); } size_type max_size() const { return A::max_size(); } size_type capacity() const { return size_type(pData_->pEndOfMem_ - pData_->buffer_); } void resize(size_type n, E c) { reserve(n); iterator newEnd = begin() + n; iterator oldEnd = end(); if (newEnd > oldEnd) { // Copy the characters flex_string_details::pod_fill(oldEnd, newEnd, c); } if (capacity()) pData_->pEnd_ = newEnd; } void reserve(size_type res_arg) { if (res_arg <= capacity()) { // @@@ shrink to fit here return; } A& myAlloc = *this; AllocatorStringStorage newStr(myAlloc); newStr.Init(size(), res_arg); flex_string_details::pod_copy(begin(), end(), newStr.begin()); swap(newStr); } template <class ForwardIterator> void append(ForwardIterator b, ForwardIterator e) { const size_type sz = std::distance(b, e), neededCapacity = size() + sz; if (capacity() < neededCapacity) {// typedef std::less_equal<const E*> le_type;// BOOST_ASSERT(!(le_type()(begin(), &*b) && le_type()(&*b, end()))); reserve(neededCapacity); } std::copy(b, e, end()); pData_->pEnd_ += sz; } void swap(AllocatorStringStorage& rhs) { // @@@ The following line is commented due to a bug in MSVC //std::swap(lhsAlloc, rhsAlloc); std::swap(pData_, rhs.pData_); } const E* c_str() const { if (pData_ != &SimpleStringStorage<E, A>::emptyString_) { *pData_->pEnd_ = E(); } return &*begin(); } const E* data() const { return &*begin(); } A get_allocator() const { return *this; }};////////////////////////////////////////////////////////////////////////////////// class template VectorStringStorage// Uses std::vector// Takes advantage of the Empty Base Optimization if available////////////////////////////////////////////////////////////////////////////////template <typename E, class A = std::allocator<E> >class VectorStringStorage : protected std::vector<E, A>{ typedef std::vector<E, A> base;public: // protected: typedef E value_type; typedef typename base::iterator iterator; typedef typename base::const_iterator const_iterator; typedef A allocator_type; typedef typename A::size_type size_type; VectorStringStorage(const VectorStringStorage& s) : base(s) { } VectorStringStorage(const A& a) : base(1, E(), a) { } VectorStringStorage(const E* s, size_type len, const A& a) : base(a) { base::reserve(len + 1); base::insert(base::end(), s, s + len); // Terminating zero base::insert(base::end(), E()); } VectorStringStorage(size_type len, E c, const A& a) : base(len + 1, c, a) { // Terminating zero base::back() = E(); } VectorStringStorage& operator=(const VectorStringStorage& rhs) { base& v = *this; v = rhs; return *this; } iterator begin() { return base::begin(); } const_iterator begin() const { return base::begin(); } iterator end() { return base::end() - 1; } const_iterator end() const { return base::end() - 1; } size_type size() const { return base::size() - 1; } size_type max_size() const { return base::max_size() - 1; } size_type capacity() const { return base::capacity() - 1; } void reserve(size_type res_arg) { BOOST_ASSERT(res_arg < max_size()); base::reserve(res_arg + 1); } void append(const E* s, size_type sz) { // Check for aliasing because std::vector doesn't do it. static std::less_equal<const E*> le; if (!base::empty()) { const E* start = &base::front(); if (le(start, s) && le(s, start + size())) { // aliased const size_type offset = s - start; reserve(size() + sz); s = &base::front() + offset; } } base::insert(end(), s, s + sz); } template <class InputIterator> void append(InputIterator b, InputIterator e) { base::insert(end(), b, e); } void resize(size_type n, E c) { base::reserve(n + 1); base::back() = c; base::resize(n + 1, c); base::back() = E(); } void swap(VectorStringStorage& rhs) { base::swap(rhs); } const E* c_str() const { return &*begin(); } const E* data() const { return &*begin(); } A get_allocator() const { return base::get_allocator(); }};////////////////////////////////////////////////////////////////////////////////// class template SmallStringOpt// Builds the small string optimization over any other storage////////////////////////////////////////////////////////////////////////////////template <class Storage, unsigned int threshold, typename Align = typename Storage::value_type*>class SmallStringOpt{public: typedef typename Storage::value_type value_type; typedef value_type* iterator; typedef const value_type* const_iterator; typedef typename Storage::allocator_type allocator_type; typedef typename allocator_type::size_type size_type; private: enum { temp1 = threshold * sizeof(value_type) > sizeof(Storage) ? threshold * sizeof(value_type) : sizeof(Storage) }; enum { temp2 = temp1 > sizeof(Align) ? temp1 : sizeof(Align) };public: enum { maxSmallString = (temp2 + sizeof(value_type) - 1) / sizeof(value_type) }; private: enum { magic = maxSmallString + 1 }; union { mutable value_type buf_[maxSmallString + 1]; Align align_; }; Storage& GetStorage() { BOOST_ASSERT(buf_[maxSmallString] == magic); Storage* p = reinterpret_cast<Storage*>(&buf_[0]); return *p; } const Storage& GetStorage() const { BOOST_ASSERT(buf_[maxSmallString] == magic); const Storage *p = reinterpret_cast<const Storage*>(&buf_[0]); return *p; } bool Small() const { return buf_[maxSmallString] != magic; } public: SmallStringOpt(const SmallStringOpt& s) { if (s.Small()) { flex_string_details::pod_copy( s.buf_, s.buf_ + s.size(), buf_); } else { new(buf_) Storage(s.GetStorage()); } buf_[maxSmallString] = s.buf_[maxSmallString]; } SmallStringOpt(const allocator_type&) { buf_[maxSmallString] = maxSmallString; } SmallStringOpt(const value_type* s, size_type len, const allocator_type& a) { if (len <= maxSmallString) { flex_string_details::pod_copy(s, s + len, buf_); buf_[maxSmallString] = value_type(maxSmallString - len); } else { new(buf_) Storage(s, len, a); buf_[maxSmallString] = magic; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -