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
40template <class _Tp, class _Alloc>
41class _String_base {
42    typedef _String_base<_Tp, _Alloc> _Self;
43protected:
44  _STLP_FORCE_ALLOCATORS(_Tp, _Alloc)
45public:
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;
52private:
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 */
61protected:
62#if defined (_STLP_USE_SHORT_STRING_OPTIM)
63  bool _M_using_static_buf() const
64  { return (_M_start_of_storage._M_data == _M_buffers._M_static_buf); }
65  _Tp const* _M_Start() const { return _M_start_of_storage._M_data; }
66  _Tp* _M_Start() { return _M_start_of_storage._M_data; }
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; }
69  _Tp* _M_End()
70  { return _M_using_static_buf() ? _M_buffers._M_static_buf + _DEFAULT_SIZE : _M_buffers._M_end_of_storage; }
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; }
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
89  _Tp const* _M_Finish() const {return _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);
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
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
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
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