]> git.cworth.org Git - vogl/blob - src/extlib/loki/include/loki/flex/allocatorstringstorage.h
Initial vogl checkin
[vogl] / src / extlib / loki / include / loki / flex / allocatorstringstorage.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 ALLOCATOR_STRING_STORAGE_INC_
14 #define ALLOCATOR_STRING_STORAGE_INC_
15
16 // $Id: allocatorstringstorage.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 #include "flex_string_details.h"
69 #include "simplestringstorage.h"
70
71 ////////////////////////////////////////////////////////////////////////////////
72 // class template AllocatorStringStorage
73 // Allocates with your allocator
74 // Takes advantage of the Empty Base Optimization if available
75 ////////////////////////////////////////////////////////////////////////////////
76
77 template <typename E, class A = std::allocator<E> >
78 class AllocatorStringStorage : public A
79 {
80         typedef typename A::size_type size_type;
81         typedef typename SimpleStringStorage<E, A>::Data Data;
82
83         void *Alloc(size_type sz, const void *p = 0)
84         {
85                 return A::allocate(1 + (sz - 1) / sizeof(E),
86                                    static_cast<const char *>(p));
87         }
88
89         void *Realloc(void *p, size_type oldSz, size_type newSz)
90         {
91                 void *r = Alloc(newSz);
92                 flex_string_details::pod_copy(p, p + Min(oldSz, newSz), r);
93                 Free(p, oldSz);
94                 return r;
95         }
96
97         void Free(void *p, size_type sz)
98         {
99                 A::deallocate(static_cast<E *>(p), sz);
100         }
101
102         Data *pData_;
103
104         void Init(size_type size, size_type cap)
105         {
106                 assert(size <= cap);
107
108                 if (cap == 0)
109                 {
110                         pData_ = const_cast<Data *>(
111                                      &SimpleStringStorage<E, A>::emptyString_);
112                 }
113                 else
114                 {
115                         pData_ = static_cast<Data *>(Alloc(
116                                                          cap * sizeof(E) + sizeof(Data)));
117                         pData_->pEnd_ = pData_->buffer_ + size;
118                         pData_->pEndOfMem_ = pData_->buffer_ + cap;
119                 }
120         }
121
122 public:
123         typedef E value_type;
124         typedef A allocator_type;
125         typedef typename A::pointer iterator;
126         typedef typename A::const_pointer const_iterator;
127
128         AllocatorStringStorage()
129                 : A(), pData_(0)
130         {
131         }
132
133         AllocatorStringStorage(const AllocatorStringStorage &rhs)
134                 : A(rhs.get_allocator())
135         {
136                 const size_type sz = rhs.size();
137                 Init(sz, sz);
138                 if (sz) flex_string_details::pod_copy(rhs.begin(), rhs.end(), begin());
139         }
140
141         AllocatorStringStorage(const AllocatorStringStorage &s,
142                                flex_string_details::Shallow)
143                 : A(s.get_allocator())
144         {
145                 pData_ = s.pData_;
146         }
147
148         AllocatorStringStorage(const A &a) : A(a)
149         {
150                 pData_ = const_cast<Data *>(
151                              &SimpleStringStorage<E, A>::emptyString_);
152         }
153
154         AllocatorStringStorage(const E *s, size_type len, const A &a)
155                 : A(a)
156         {
157                 Init(len, len);
158                 flex_string_details::pod_copy(s, s + len, begin());
159         }
160
161         AllocatorStringStorage(size_type len, E c, const A &a)
162                 : A(a)
163         {
164                 Init(len, len);
165                 flex_string_details::pod_fill(&*begin(), &*end(), c);
166         }
167
168         AllocatorStringStorage &operator=(const AllocatorStringStorage &rhs)
169         {
170                 const size_type sz = rhs.size();
171                 reserve(sz);
172                 flex_string_details::pod_copy(&*rhs.begin(), &*rhs.end(), begin());
173                 pData_->pEnd_ = &*begin() + rhs.size();
174                 return *this;
175         }
176
177         ~AllocatorStringStorage()
178         {
179                 if (capacity())
180                 {
181                         Free(pData_,
182                              sizeof(Data) + capacity() * sizeof(E));
183                 }
184         }
185
186         iterator begin()
187         {
188                 return pData_->buffer_;
189         }
190
191         const_iterator begin() const
192         {
193                 return pData_->buffer_;
194         }
195
196         iterator end()
197         {
198                 return pData_->pEnd_;
199         }
200
201         const_iterator end() const
202         {
203                 return pData_->pEnd_;
204         }
205
206         size_type size() const
207         {
208                 return size_type(end() - begin());
209         }
210
211         size_type max_size() const
212         {
213                 return A::max_size();
214         }
215
216         size_type capacity() const
217         {
218                 return size_type(pData_->pEndOfMem_ - pData_->buffer_);
219         }
220
221         void resize(size_type n, E c)
222         {
223                 reserve(n);
224                 iterator newEnd = begin() + n;
225                 iterator oldEnd = end();
226                 if (newEnd > oldEnd)
227                 {
228                         // Copy the characters
229                         flex_string_details::pod_fill(oldEnd, newEnd, c);
230                 }
231                 if (capacity()) pData_->pEnd_ = newEnd;
232         }
233
234         void reserve(size_type res_arg)
235         {
236                 if (res_arg <= capacity())
237                 {
238                         // @@@ shrink to fit here
239                         return;
240                 }
241
242                 A &myAlloc = *this;
243                 AllocatorStringStorage newStr(myAlloc);
244                 newStr.Init(size(), res_arg);
245
246                 flex_string_details::pod_copy(begin(), end(), newStr.begin());
247
248                 swap(newStr);
249         }
250
251         template <class ForwardIterator>
252         void append(ForwardIterator b, ForwardIterator e)
253         {
254                 const size_type
255                 sz = std::distance(b, e),
256                 neededCapacity = size() + sz;
257
258                 if (capacity() < neededCapacity)
259                 {
260                         static std::less_equal<const E *> le;
261                         (void) le;
262                         assert(!(le(begin(), &*b) && le(&*b, end())));
263                         reserve(neededCapacity);
264                 }
265                 std::copy(b, e, end());
266                 pData_->pEnd_ += sz;
267         }
268
269         void swap(AllocatorStringStorage &rhs)
270         {
271                 // @@@ The following line is commented due to a bug in MSVC
272                 //std::swap(lhsAlloc, rhsAlloc);
273                 std::swap(pData_, rhs.pData_);
274         }
275
276         const E *c_str() const
277         {
278                 if (pData_ != &SimpleStringStorage<E, A>::emptyString_)
279                 {
280                         *pData_->pEnd_ = E();
281                 }
282                 return &*begin();
283         }
284
285         const E *data() const
286         {
287                 return &*begin();
288         }
289
290         A get_allocator() const
291         {
292                 return *this;
293         }
294 };
295
296 #endif // ALLOCATOR_STRING_STORAGE_INC_