• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 1997-1999
3  * Silicon Graphics Computer Systems, Inc.
4  *
5  * Copyright (c) 1999
6  * Boris Fomitchev
7  *
8  * Copyright (c) 2003
9  * Francois Dumont
10  *
11  * This material is provided "as is", with absolutely no warranty expressed
12  * or implied. Any use is at your own risk.
13  *
14  * Permission to use or copy this software for any purpose is hereby granted
15  * without fee, provided the above notices are retained on all copies.
16  * Permission to modify the code and to distribute modified code is granted,
17  * provided the above notices are retained, and a notice that the code was
18  * modified is included with the above copyright notice.
19  *
20  */
21 
22 #ifndef _STLP_STRING_BASE_H
23 #define _STLP_STRING_BASE_H
24 
25 // ------------------------------------------------------------
26 // Class _String_base.
27 
28 // _String_base is a helper class that makes it it easier to write an
29 // exception-safe version of basic_string.  The constructor allocates,
30 // but does not initialize, a block of memory.  The destructor
31 // deallocates, but does not destroy elements within, a block of
32 // memory.  The destructor assumes that _M_start either is null, or else
33 // points to a block of memory that was allocated using _String_base's
34 // allocator and whose size is _M_end_of_storage - _M_start_of_storage._M_data.
35 
36 _STLP_BEGIN_NAMESPACE
37 
38 _STLP_MOVE_TO_PRIV_NAMESPACE
39 
40 template <class _Tp, class _Alloc>
41 class _String_base {
42     typedef _String_base<_Tp, _Alloc> _Self;
43 protected:
44   _STLP_FORCE_ALLOCATORS(_Tp, _Alloc)
45 public:
46   //dums: Some compiler(MSVC6) require it to be public not simply protected!
47   enum {_DEFAULT_SIZE = 4 * sizeof( void * )};
48   //This is needed by the full move framework
49   typedef _Alloc allocator_type;
50   typedef _STLP_alloc_proxy<_Tp*, _Tp, allocator_type> _AllocProxy;
51   typedef size_t size_type;
52 private:
53 #if defined (_STLP_USE_SHORT_STRING_OPTIM)
54   union _Buffers {
55     _Tp*  _M_end_of_storage;
56     _Tp   _M_static_buf[_DEFAULT_SIZE];
57   } _M_buffers;
58 #else
59   _Tp*    _M_end_of_storage;
60 #endif /* _STLP_USE_SHORT_STRING_OPTIM */
61 protected:
62 #if defined (_STLP_USE_SHORT_STRING_OPTIM)
_M_using_static_buf()63   bool _M_using_static_buf() const
64   { return (_M_start_of_storage._M_data == _M_buffers._M_static_buf); }
_M_Start()65   _Tp const* _M_Start() const { return _M_start_of_storage._M_data; }
_M_Start()66   _Tp* _M_Start() { return _M_start_of_storage._M_data; }
_M_End()67   _Tp const* _M_End() const
68   { return _M_using_static_buf() ? _M_buffers._M_static_buf + _DEFAULT_SIZE : _M_buffers._M_end_of_storage; }
_M_End()69   _Tp* _M_End()
70   { return _M_using_static_buf() ? _M_buffers._M_static_buf + _DEFAULT_SIZE : _M_buffers._M_end_of_storage; }
_M_capacity()71   size_type _M_capacity() const
72   { return _M_using_static_buf() ? static_cast<size_type>(_DEFAULT_SIZE) : _M_buffers._M_end_of_storage - _M_start_of_storage._M_data; }
_M_rest()73   size_type _M_rest() const
74   { return  _M_using_static_buf() ? _DEFAULT_SIZE - (_M_finish - _M_buffers._M_static_buf) : _M_buffers._M_end_of_storage - _M_finish; }
75 #else
76   _Tp const* _M_Start() const { return _M_start_of_storage._M_data; }
77   _Tp* _M_Start() { return _M_start_of_storage._M_data; }
78   _Tp const* _M_End() const { return _M_end_of_storage; }
79   _Tp* _M_End() { return _M_end_of_storage; }
80   size_type _M_capacity() const
81   { return _M_end_of_storage - _M_start_of_storage._M_data; }
82   size_type _M_rest() const
83   { return _M_end_of_storage - _M_finish; }
84 #endif /* _STLP_USE_SHORT_STRING_OPTIM */
85 
86   _Tp*    _M_finish;
87   _AllocProxy _M_start_of_storage;
88 
_M_Finish()89   _Tp const* _M_Finish() const {return _M_finish;}
_M_Finish()90   _Tp* _M_Finish() {return _M_finish;}
91 
92   // Precondition: 0 < __n <= max_size().
93   void _M_allocate_block(size_t __n = _DEFAULT_SIZE);
_M_deallocate_block()94   void _M_deallocate_block() {
95 #if defined (_STLP_USE_SHORT_STRING_OPTIM)
96     if (!_M_using_static_buf() && (_M_start_of_storage._M_data != 0))
97       _M_start_of_storage.deallocate(_M_start_of_storage._M_data, _M_buffers._M_end_of_storage - _M_start_of_storage._M_data);
98 #else
99     if (_M_start_of_storage._M_data != 0)
100       _M_start_of_storage.deallocate(_M_start_of_storage._M_data, _M_end_of_storage - _M_start_of_storage._M_data);
101 #endif /* _STLP_USE_SHORT_STRING_OPTIM */
102   }
103 
max_size()104   size_t max_size() const {
105     const size_type __string_max_size = size_type(-1) / sizeof(_Tp);
106     typename allocator_type::size_type __alloc_max_size = _M_start_of_storage.max_size();
107     return (min)(__alloc_max_size, __string_max_size) - 1;
108   }
109 
_String_base(const allocator_type & __a)110   _String_base(const allocator_type& __a)
111 #if defined (_STLP_USE_SHORT_STRING_OPTIM)
112     : _M_finish(_M_buffers._M_static_buf), _M_start_of_storage(__a, _M_buffers._M_static_buf)
113 #else
114     : _M_end_of_storage(0), _M_finish(0), _M_start_of_storage(__a, (_Tp*)0)
115 #endif
116     {}
117 
_String_base(const allocator_type & __a,size_t __n)118   _String_base(const allocator_type& __a, size_t __n)
119 #if defined (_STLP_USE_SHORT_STRING_OPTIM)
120     : _M_finish(_M_buffers._M_static_buf), _M_start_of_storage(__a, _M_buffers._M_static_buf) {
121 #else
122     : _M_end_of_storage(0), _M_finish(0), _M_start_of_storage(__a, (_Tp*)0) {
123 #endif
124       _M_allocate_block(__n);
125     }
126 
127 #if defined (_STLP_USE_SHORT_STRING_OPTIM)
128   void _M_move_src (_Self &src) {
129     if (src._M_using_static_buf()) {
130       _M_buffers = src._M_buffers;
131       _M_finish = _M_buffers._M_static_buf + (src._M_finish - src._M_start_of_storage._M_data);
132       _M_start_of_storage._M_data = _M_buffers._M_static_buf;
133     }
134     else {
135       _M_start_of_storage._M_data = src._M_start_of_storage._M_data;
136       _M_finish = src._M_finish;
137       _M_buffers._M_end_of_storage = src._M_buffers._M_end_of_storage;
138       src._M_start_of_storage._M_data = 0;
139     }
140   }
141 #endif
142 
143 #if !defined (_STLP_NO_MOVE_SEMANTIC)
144   _String_base(__move_source<_Self> src)
145 #  if defined (_STLP_USE_SHORT_STRING_OPTIM)
146     : _M_start_of_storage(__move_source<_AllocProxy>(src.get()._M_start_of_storage)) {
147       _M_move_src(src.get());
148 #  else
149     : _M_end_of_storage(src.get()._M_end_of_storage), _M_finish(src.get()._M_finish),
150       _M_start_of_storage(__move_source<_AllocProxy>(src.get()._M_start_of_storage)) {
151       src.get()._M_start_of_storage._M_data = 0;
152 #  endif
153     }
154 #endif
155 
156   ~_String_base() { _M_deallocate_block(); }
157 
158   void _M_reset(_Tp *__start, _Tp *__finish, _Tp *__end_of_storage) {
159 #if defined (_STLP_USE_SHORT_STRING_OPTIM)
160     _M_buffers._M_end_of_storage = __end_of_storage;
161 #else
162     _M_end_of_storage = __end_of_storage;
163 #endif
164     _M_finish = __finish;
165     _M_start_of_storage._M_data = __start;
166   }
167 
168   void _M_swap(_Self &__s) {
169 #if defined (_STLP_USE_SHORT_STRING_OPTIM)
170     if (_M_using_static_buf()) {
171       if (__s._M_using_static_buf()) {
172         _STLP_STD::swap(_M_buffers, __s._M_buffers);
173         _Tp *__tmp = _M_finish;
174         _M_finish = _M_start_of_storage._M_data + (__s._M_finish - __s._M_start_of_storage._M_data);
175         __s._M_finish = __s._M_buffers._M_static_buf + (__tmp - _M_start_of_storage._M_data);
176         //We need to swap _M_start_of_storage for allocators with state:
177         _M_start_of_storage.swap(__s._M_start_of_storage);
178         _M_start_of_storage._M_data = _M_buffers._M_static_buf;
179         __s._M_start_of_storage._M_data = __s._M_buffers._M_static_buf;
180       } else {
181         __s._M_swap(*this);
182         return;
183       }
184     }
185     else if (__s._M_using_static_buf()) {
186       _Tp *__tmp = _M_start_of_storage._M_data;
187       _Tp *__tmp_finish = _M_finish;
188       _Tp *__tmp_end_data = _M_buffers._M_end_of_storage;
189       _M_buffers = __s._M_buffers;
190       //We need to swap _M_start_of_storage for allocators with state:
191       _M_start_of_storage.swap(__s._M_start_of_storage);
192       _M_start_of_storage._M_data = _M_buffers._M_static_buf;
193       _M_finish = _M_buffers._M_static_buf + (__s._M_finish - __s._M_buffers._M_static_buf);
194       __s._M_buffers._M_end_of_storage = __tmp_end_data;
195       __s._M_start_of_storage._M_data = __tmp;
196       __s._M_finish = __tmp_finish;
197     }
198     else {
199       _STLP_STD::swap(_M_buffers._M_end_of_storage, __s._M_buffers._M_end_of_storage);
200       _M_start_of_storage.swap(__s._M_start_of_storage);
201       _STLP_STD::swap(_M_finish, __s._M_finish);
202     }
203 #else
204     _STLP_STD::swap(_M_end_of_storage, __s._M_end_of_storage);
205     _M_start_of_storage.swap(__s._M_start_of_storage);
206     _STLP_STD::swap(_M_finish, __s._M_finish);
207 #endif
208   }
209 
210   void _STLP_FUNCTION_THROWS _M_throw_length_error() const;
211   void _STLP_FUNCTION_THROWS _M_throw_out_of_range() const;
212 };
213 
214 #if defined (_STLP_USE_TEMPLATE_EXPORT)
215 _STLP_EXPORT_TEMPLATE_CLASS _String_base<char, allocator<char> >;
216 #  if defined (_STLP_HAS_WCHAR_T)
217 _STLP_EXPORT_TEMPLATE_CLASS _String_base<wchar_t, allocator<wchar_t> >;
218 #  endif
219 #endif /* _STLP_USE_TEMPLATE_EXPORT */
220 
221 _STLP_MOVE_TO_STD_NAMESPACE
222 
223 _STLP_END_NAMESPACE
224 
225 #endif /* _STLP_STRING_BASE_H */
226 
227 /*
228  * Local Variables:
229  * mode:C++
230  * End:
231  */
232