1 ////////////////////////////////////////////////////////////////////////////////
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 ////////////////////////////////////////////////////////////////////////////////
13 #ifndef COW_STRING_OPT_INC_
14 #define COW_STRING_OPT_INC_
16 // $Id: cowstringopt.h 836 2007-09-20 15:51:37Z aandrei $
19 ////////////////////////////////////////////////////////////////////////////////
20 // class template CowStringOpt
21 // Implements Copy on Write over any storage
22 ////////////////////////////////////////////////////////////////////////////////
25 /* This is the template for a storage policy
26 ////////////////////////////////////////////////////////////////////////////////
27 template <typename E, class A = @>
32 typedef @ const_iterator;
33 typedef A allocator_type;
36 StoragePolicy(const StoragePolicy& s);
37 StoragePolicy(const A&);
38 StoragePolicy(const E* s, size_type len, const A&);
39 StoragePolicy(size_type len, E c, const A&);
43 const_iterator begin() const;
45 const_iterator end() const;
47 size_type size() const;
48 size_type max_size() const;
49 size_type capacity() const;
51 void reserve(size_type res_arg);
53 void append(const E* s, size_type sz);
55 template <class InputIterator>
56 void append(InputIterator b, InputIterator e);
58 void resize(size_type newSize, E fill);
60 void swap(StoragePolicy& rhs);
62 const E* c_str() const;
63 const E* data() const;
65 A get_allocator() const;
67 ////////////////////////////////////////////////////////////////////////////////
76 #include "flex_string_details.h"
79 ////////////////////////////////////////////////////////////////////////////////
80 // class template CowStringOpt
81 // Implements Copy on Write over any storage
82 ////////////////////////////////////////////////////////////////////////////////
84 template <class Storage, typename Align = typename Storage::value_type *>
87 typedef typename Storage::value_type E;
88 typedef typename flex_string_details::get_unsigned<E>::result RefCountType;
92 typedef typename Storage::iterator iterator;
93 typedef typename Storage::const_iterator const_iterator;
94 typedef typename Storage::allocator_type allocator_type;
95 typedef typename allocator_type::size_type size_type;
96 typedef typename Storage::reference reference;
101 mutable char buf_[sizeof(Storage)];
105 Storage &Data() const
107 return *reinterpret_cast<Storage *>(buf_);
110 RefCountType GetRefs() const
112 const Storage &d = Data();
113 assert(d.size() > 0);
114 assert(*d.begin() > 0);
121 assert(d.size() > 0);
122 return reinterpret_cast<RefCountType &>(*d.begin());
125 void MakeUnique() const
127 assert(GetRefs() >= 1);
128 if (GetRefs() == 1) return;
132 char buf_[sizeof(Storage)];
136 --(*Data().begin()); // Harmut Kaiser fix:
137 // decrement the use count of the remaining object
139 *new(temp.buf_) Storage(Data()),
140 flex_string_details::Shallow());
145 CowStringOpt(const CowStringOpt &s)
147 if (s.GetRefs() == std::numeric_limits<RefCountType>::max())
149 // must make a brand new copy
150 new(buf_) Storage(s.Data()); // non shallow
155 new(buf_) Storage(s.Data(), flex_string_details::Shallow());
158 assert(Data().size() > 0);
161 CowStringOpt(const allocator_type &a)
163 new(buf_) Storage(1, 1, a);
166 CowStringOpt(const E *s, size_type len, const allocator_type &a)
168 // Warning - MSVC's debugger has trouble tracing through the code below.
169 // It seems to be a const-correctness issue
171 new(buf_) Storage(a);
172 Data().reserve(len + 1);
174 Data().append(s, s + len);
177 CowStringOpt(size_type len, E c, const allocator_type &a)
179 new(buf_) Storage(len + 1, c, a);
183 CowStringOpt &operator=(const CowStringOpt &rhs)
185 CowStringOpt(rhs).swap(*this);
191 assert(Data().size() > 0);
192 if (--Refs() == 0) Data().~Storage();
197 assert(Data().size() > 0);
199 return Data().begin() + 1;
202 const_iterator begin() const
204 assert(Data().size() > 0);
205 return Data().begin() + 1;
214 const_iterator end() const
219 size_type size() const
221 assert(Data().size() > 0);
222 return Data().size() - 1;
225 size_type max_size() const
227 assert(Data().max_size() > 0);
228 return Data().max_size() - 1;
231 size_type capacity() const
233 assert(Data().capacity() > 0);
234 return Data().capacity() - 1;
237 void resize(size_type n, E c)
239 assert(Data().size() > 0);
241 Data().resize(n + 1, c);
244 template <class FwdIterator>
245 void append(FwdIterator b, FwdIterator e)
251 void reserve(size_type res_arg)
253 if (capacity() > res_arg) return;
255 Data().reserve(res_arg + 1);
258 void swap(CowStringOpt &rhs)
260 Data().swap(rhs.Data());
263 const E *c_str() const
265 assert(Data().size() > 0);
266 return Data().c_str() + 1;
269 const E *data() const
271 assert(Data().size() > 0);
272 return Data().data() + 1;
275 allocator_type get_allocator() const
277 return Data().get_allocator();
282 #endif // COW_STRING_OPT_INC_