⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flex_string.hpp

📁 C++的一个好库。。。现在很流行
💻 HPP
📖 第 1 页 / 共 5 页
字号:
        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>::Data
SimpleStringStorage<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(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);
    }

    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;
    }
    
    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;
        }
    }

    SmallStringOpt(size_type len, value_type c, const allocator_type& a)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -