1 ////////////////////////////////////////////////////////////////////////////////
2 // flex_string
3 // Copyright (c) 2001 by Andrei Alexandrescu
4 // Permission to use, copy, modify, distribute and sell this software for any
5 //     purpose is hereby granted without fee, provided that the above copyright
6 //     notice appear in all copies and that both that copyright notice and this
7 //     permission notice appear in supporting documentation.
8 // The author makes no representations about the
9 //     suitability of this software for any purpose. It is provided "as is"
10 //     without express or implied warranty.
11 ////////////////////////////////////////////////////////////////////////////////
12 
13 #ifndef VECTOR_STRING_STORAGE_INC_
14 #define VECTOR_STRING_STORAGE_INC_
15 
16 // $Id: vectorstringstorage.h 754 2006-10-17 19:59:11Z syntheticpp $
17 
18 
19 /* This is the template for a storage policy
20 ////////////////////////////////////////////////////////////////////////////////
21 template <typename E, class A = @>
22 class StoragePolicy
23 {
24     typedef E value_type;
25     typedef @ iterator;
26     typedef @ const_iterator;
27     typedef A allocator_type;
28     typedef @ size_type;
29 
30     StoragePolicy(const StoragePolicy& s);
31     StoragePolicy(const A&);
32     StoragePolicy(const E* s, size_type len, const A&);
33     StoragePolicy(size_type len, E c, const A&);
34     ~StoragePolicy();
35 
36     iterator begin();
37     const_iterator begin() const;
38     iterator end();
39     const_iterator end() const;
40 
41     size_type size() const;
42     size_type max_size() const;
43     size_type capacity() const;
44 
45     void reserve(size_type res_arg);
46 
47     void append(const E* s, size_type sz);
48 
49     template <class InputIterator>
50     void append(InputIterator b, InputIterator e);
51 
52     void resize(size_type newSize, E fill);
53 
54     void swap(StoragePolicy& rhs);
55 
56     const E* c_str() const;
57     const E* data() const;
58 
59     A get_allocator() const;
60 };
61 ////////////////////////////////////////////////////////////////////////////////
62 */
63 
64 #include <memory>
65 #include <vector>
66 #include <algorithm>
67 #include <functional>
68 #include <cassert>
69 #include <limits>
70 #include <stdexcept>
71 
72 ////////////////////////////////////////////////////////////////////////////////
73 // class template VectorStringStorage
74 // Uses std::vector
75 // Takes advantage of the Empty Base Optimization if available
76 ////////////////////////////////////////////////////////////////////////////////
77 
78 template <typename E, class A = std::allocator<E> >
79 class VectorStringStorage : protected std::vector<E, A>
80 {
81     typedef std::vector<E, A> base;
82 
83 public: // protected:
84     typedef E value_type;
85     typedef typename base::iterator iterator;
86     typedef typename base::const_iterator const_iterator;
87     typedef A allocator_type;
88     typedef typename A::size_type size_type;
89     typedef typename A::reference reference;
90 
VectorStringStorage(const VectorStringStorage & s)91     VectorStringStorage(const VectorStringStorage& s) : base(s)
92     { }
93 
VectorStringStorage(const A & a)94     VectorStringStorage(const A& a) : base(1, value_type(), a)
95     { }
96 
VectorStringStorage(const value_type * s,size_type len,const A & a)97     VectorStringStorage(const value_type* s, size_type len, const A& a)
98     : base(a)
99     {
100         base::reserve(len + 1);
101         base::insert(base::end(), s, s + len);
102         // Terminating zero
103         base::push_back(value_type());
104     }
105 
VectorStringStorage(size_type len,E c,const A & a)106     VectorStringStorage(size_type len, E c, const A& a)
107     : base(len + 1, c, a)
108     {
109         // Terminating zero
110         base::back() = value_type();
111     }
112 
113     VectorStringStorage& operator=(const VectorStringStorage& rhs)
114     {
115         base& v = *this;
116         v = rhs;
117         return *this;
118     }
119 
begin()120     iterator begin()
121     { return base::begin(); }
122 
begin()123     const_iterator begin() const
124     { return base::begin(); }
125 
end()126     iterator end()
127     { return base::end() - 1; }
128 
end()129     const_iterator end() const
130     { return base::end() - 1; }
131 
size()132     size_type size() const
133     { return base::size() - 1; }
134 
max_size()135     size_type max_size() const
136     { return base::max_size() - 1; }
137 
capacity()138     size_type capacity() const
139     { return base::capacity() - 1; }
140 
reserve(size_type res_arg)141     void reserve(size_type res_arg)
142     {
143         assert(res_arg < max_size());
144         base::reserve(res_arg + 1);
145     }
146 
147     template <class ForwardIterator>
append(ForwardIterator b,ForwardIterator e)148     void append(ForwardIterator b, ForwardIterator e)
149     {
150         const typename std::iterator_traits<ForwardIterator>::difference_type
151             sz = std::distance(b, e);
152         assert(sz >= 0);
153         if (sz == 0) return;
154         base::reserve(base::size() + sz);
155         const value_type & v = *b;
156         struct OnBlockExit
157         {
158             VectorStringStorage * that;
159             ~OnBlockExit()
160             {
161                 that->base::push_back(value_type());
162             }
163         } onBlockExit = { this };
164         (void) onBlockExit;
165         assert(!base::empty());
166         assert(base::back() == value_type());
167         base::back() = v;
168         base::insert(base::end(), ++b, e);
169     }
170 
resize(size_type n,E c)171     void resize(size_type n, E c)
172     {
173         base::reserve(n + 1);
174         base::back() = c;
175         base::resize(n + 1, c);
176         base::back() = E();
177     }
178 
swap(VectorStringStorage & rhs)179     void swap(VectorStringStorage& rhs)
180     { base::swap(rhs); }
181 
c_str()182     const E* c_str() const
183     { return &*begin(); }
184 
data()185     const E* data() const
186     { return &*begin(); }
187 
get_allocator()188     A get_allocator() const
189     { return base::get_allocator(); }
190 };
191 
192 
193 #endif // VECTOR_STRING_STORAGE_INC_
194