]> git.cworth.org Git - vogl/blob - src/extlib/loki/include/loki/flex/simplestringstorage.h
Initial vogl checkin
[vogl] / src / extlib / loki / include / loki / flex / simplestringstorage.h
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 SIMPLE_STRING_STORAGE_INC_
14 #define SIMPLE_STRING_STORAGE_INC_
15
16 // $Id: simplestringstorage.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     template <class ForwardIterator>
48     void append(ForwardIterator b, ForwardIterator e);
49
50     void resize(size_type newSize, E fill);
51
52     void swap(StoragePolicy& rhs);
53
54     const E* c_str() const;
55     const E* data() const;
56
57     A get_allocator() const;
58 };
59 ////////////////////////////////////////////////////////////////////////////////
60 */
61
62 #include <memory>
63 #include <algorithm>
64 #include <functional>
65 #include <cassert>
66 #include <limits>
67 #include <stdexcept>
68
69
70 ////////////////////////////////////////////////////////////////////////////////
71 // class template SimpleStringStorage
72 // Allocates memory with malloc
73 ////////////////////////////////////////////////////////////////////////////////
74
75 template <typename E, class A = std::allocator<E> >
76 class SimpleStringStorage
77 {
78         // The "public" below exists because MSVC can't do template typedefs
79 public:
80         struct Data
81         {
82                 Data() : pEnd_(buffer_), pEndOfMem_(buffer_)
83                 {
84                         buffer_[0] = E(0);
85                 }
86
87                 E *pEnd_;
88                 E *pEndOfMem_;
89                 E buffer_[1];
90         };
91         static const Data emptyString_;
92
93         typedef typename A::size_type size_type;
94
95 private:
96         Data *pData_;
97
98         void Init(size_type size, size_type capacity)
99         {
100                 assert(size <= capacity);
101                 if (capacity == 0)
102                 {
103                         pData_ = const_cast<Data *>(&emptyString_);
104                 }
105                 else
106                 {
107                         // 11-17-2000: comment added:
108                         //     No need to allocate (capacity + 1) to
109                         //     accomodate the terminating 0, because Data already
110                         //     has one one character in there
111                         pData_ = static_cast<Data *>(
112                                      malloc(sizeof(Data) + capacity * sizeof(E)));
113                         if (!pData_) throw std::bad_alloc();
114                         pData_->pEnd_ = pData_->buffer_ + size;
115                         pData_->pEndOfMem_ = pData_->buffer_ + capacity;
116                 }
117         }
118
119 private:
120         // Warning - this doesn't initialize pData_. Used in reserve()
121         SimpleStringStorage()
122         { }
123
124 public:
125         typedef E value_type;
126         typedef E *iterator;
127         typedef const E *const_iterator;
128         typedef A allocator_type;
129         typedef typename A::reference reference;
130
131
132         SimpleStringStorage(const SimpleStringStorage &rhs)
133         {
134                 const size_type sz = rhs.size();
135                 Init(sz, sz);
136                 if (sz) flex_string_details::pod_copy(rhs.begin(), rhs.end(), begin());
137         }
138
139         SimpleStringStorage(const SimpleStringStorage &s,
140                             flex_string_details::Shallow)
141                 : pData_(s.pData_)
142         {
143         }
144
145         SimpleStringStorage(const A &)
146         {
147                 pData_ = const_cast<Data *>(&emptyString_);
148         }
149
150         SimpleStringStorage(const E *s, size_type len, const A &)
151         {
152                 Init(len, len);
153                 flex_string_details::pod_copy(s, s + len, begin());
154         }
155
156         SimpleStringStorage(size_type len, E c, const A &)
157         {
158                 Init(len, len);
159                 flex_string_details::pod_fill(begin(), end(), c);
160         }
161
162         SimpleStringStorage &operator=(const SimpleStringStorage &rhs)
163         {
164                 const size_type sz = rhs.size();
165                 reserve(sz);
166                 flex_string_details::pod_copy(&*rhs.begin(), &*rhs.end(), begin());
167                 pData_->pEnd_ = &*begin() + sz;
168                 return *this;
169         }
170
171         ~SimpleStringStorage()
172         {
173                 assert(begin() <= end());
174                 if (pData_ != &emptyString_) free(pData_);
175         }
176
177         iterator begin()
178         {
179                 return pData_->buffer_;
180         }
181
182         const_iterator begin() const
183         {
184                 return pData_->buffer_;
185         }
186
187         iterator end()
188         {
189                 return pData_->pEnd_;
190         }
191
192         const_iterator end() const
193         {
194                 return pData_->pEnd_;
195         }
196
197         size_type size() const
198         {
199                 return pData_->pEnd_ - pData_->buffer_;
200         }
201
202         size_type max_size() const
203         {
204                 return size_t(-1) / sizeof(E) - sizeof(Data) - 1;
205         }
206
207         size_type capacity() const
208         {
209                 return pData_->pEndOfMem_ - pData_->buffer_;
210         }
211
212         void reserve(size_type res_arg)
213         {
214                 if (res_arg <= capacity())
215                 {
216                         // @@@ insert shrinkage here if you wish
217                         return;
218                 }
219
220                 if (pData_ == &emptyString_)
221                 {
222                         Init(0, res_arg);
223                 }
224                 else
225                 {
226                         const size_type sz = size();
227
228                         void *p = realloc(pData_,
229                                           sizeof(Data) + res_arg * sizeof(E));
230                         if (!p) throw std::bad_alloc();
231
232                         if (p != pData_)
233                         {
234                                 pData_ = static_cast<Data *>(p);
235                                 pData_->pEnd_ = pData_->buffer_ + sz;
236                         }
237                         pData_->pEndOfMem_ = pData_->buffer_ + res_arg;
238                 }
239         }
240
241         template <class InputIterator>
242         void append(InputIterator b, InputIterator e)
243         {
244                 const size_type
245                 sz = std::distance(b, e),
246                 neededCapacity = size() + sz;
247                 if (capacity() < neededCapacity)
248                 {
249                         static std::less_equal<const E *> le;
250                         (void) le;
251                         assert(!(le(begin(), &*b) && le(&*b, end()))); // no aliasing
252                         reserve(neededCapacity);
253                 }
254                 std::copy(b, e, end());
255                 pData_->pEnd_ += sz;
256         }
257
258         void resize(size_type newSize, E fill)
259         {
260                 const int delta = int(newSize - size());
261                 if (delta == 0) return;
262
263                 if (delta > 0)
264                 {
265                         if (newSize > capacity())
266                         {
267                                 reserve(newSize);
268                         }
269                         E *e = &*end();
270                         flex_string_details::pod_fill(e, e + delta, fill);
271                 }
272                 pData_->pEnd_ = pData_->buffer_ + newSize;
273         }
274
275         void swap(SimpleStringStorage &rhs)
276         {
277                 std::swap(pData_, rhs.pData_);
278         }
279
280         const E *c_str() const
281         {
282                 if (pData_ != &emptyString_) *pData_->pEnd_ = E();
283                 return pData_->buffer_;
284         }
285
286         const E *data() const
287         {
288                 return pData_->buffer_;
289         }
290
291         A get_allocator() const
292         {
293                 return A();
294         }
295 };
296
297 template <typename E, class A>
298 const typename SimpleStringStorage<E, A>::Data
299 SimpleStringStorage<E, A>::emptyString_;
300 //{
301 //    const_cast<E*>(SimpleStringStorage<E, A>::emptyString_.buffer_),
302 //    const_cast<E*>(SimpleStringStorage<E, A>::emptyString_.buffer_),
303 //    { E() }
304 //};
305
306
307
308 #endif // SIMPLE_STRING_STORAGE_INC_