summaryrefslogtreecommitdiffstats
path: root/stlport/stlport/stl/_string_base.h
blob: 7c6d7fe694a1aa07cb34b815216993824bf4b732 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/*
 * Copyright (c) 1997-1999
 * Silicon Graphics Computer Systems, Inc.
 *
 * Copyright (c) 1999
 * Boris Fomitchev
 *
 * Copyright (c) 2003
 * Francois Dumont
 *
 * This material is provided "as is", with absolutely no warranty expressed
 * or implied. Any use is at your own risk.
 *
 * Permission to use or copy this software for any purpose is hereby granted
 * without fee, provided the above notices are retained on all copies.
 * Permission to modify the code and to distribute modified code is granted,
 * provided the above notices are retained, and a notice that the code was
 * modified is included with the above copyright notice.
 *
 */

#ifndef _STLP_STRING_BASE_H
#define _STLP_STRING_BASE_H

// ------------------------------------------------------------
// Class _String_base.

// _String_base is a helper class that makes it it easier to write an
// exception-safe version of basic_string.  The constructor allocates,
// but does not initialize, a block of memory.  The destructor
// deallocates, but does not destroy elements within, a block of
// memory.  The destructor assumes that _M_start either is null, or else
// points to a block of memory that was allocated using _String_base's
// allocator and whose size is _M_end_of_storage - _M_start_of_storage._M_data.

_STLP_BEGIN_NAMESPACE

_STLP_MOVE_TO_PRIV_NAMESPACE

template <class _Tp, class _Alloc>
class _String_base {
    typedef _String_base<_Tp, _Alloc> _Self;
protected:
  _STLP_FORCE_ALLOCATORS(_Tp, _Alloc)
public:
  //dums: Some compiler(MSVC6) require it to be public not simply protected!
  enum {_DEFAULT_SIZE = 4 * sizeof( void * )};
  //This is needed by the full move framework
  typedef _Alloc allocator_type;
  typedef _STLP_alloc_proxy<_Tp*, _Tp, allocator_type> _AllocProxy;
  typedef size_t size_type;
private:
#if defined (_STLP_USE_SHORT_STRING_OPTIM)
  union _Buffers {
    _Tp*  _M_end_of_storage;
    _Tp   _M_static_buf[_DEFAULT_SIZE];
  } _M_buffers;
#else
  _Tp*    _M_end_of_storage;
#endif /* _STLP_USE_SHORT_STRING_OPTIM */
protected:
#if defined (_STLP_USE_SHORT_STRING_OPTIM)
  bool _M_using_static_buf() const
  { return (_M_start_of_storage._M_data == _M_buffers._M_static_buf); }
  _Tp const* _M_Start() const { return _M_start_of_storage._M_data; }
  _Tp* _M_Start() { return _M_start_of_storage._M_data; }
  _Tp const* _M_End() const
  { return _M_using_static_buf() ? _M_buffers._M_static_buf + _DEFAULT_SIZE : _M_buffers._M_end_of_storage; }
  _Tp* _M_End()
  { return _M_using_static_buf() ? _M_buffers._M_static_buf + _DEFAULT_SIZE : _M_buffers._M_end_of_storage; }
  size_type _M_capacity() const
  { return _M_using_static_buf() ? _DEFAULT_SIZE : _M_buffers._M_end_of_storage - _M_start_of_storage._M_data; }
  size_type _M_rest() const
  { return  _M_using_static_buf() ? _DEFAULT_SIZE - (_M_finish - _M_buffers._M_static_buf) : _M_buffers._M_end_of_storage - _M_finish; }
#else
  _Tp const* _M_Start() const { return _M_start_of_storage._M_data; }
  _Tp* _M_Start() { return _M_start_of_storage._M_data; }
  _Tp const* _M_End() const { return _M_end_of_storage; }
  _Tp* _M_End() { return _M_end_of_storage; }
  size_type _M_capacity() const
  { return _M_end_of_storage - _M_start_of_storage._M_data; }
  size_type _M_rest() const
  { return _M_end_of_storage - _M_finish; }
#endif /* _STLP_USE_SHORT_STRING_OPTIM */

  _Tp*    _M_finish;
  _AllocProxy _M_start_of_storage;

  _Tp const* _M_Finish() const {return _M_finish;}
  _Tp* _M_Finish() {return _M_finish;}

  // Precondition: 0 < __n <= max_size().
  void _M_allocate_block(size_t __n = _DEFAULT_SIZE);
  void _M_deallocate_block() {
#if defined (_STLP_USE_SHORT_STRING_OPTIM)
    if (!_M_using_static_buf() && (_M_start_of_storage._M_data != 0))
      _M_start_of_storage.deallocate(_M_start_of_storage._M_data, _M_buffers._M_end_of_storage - _M_start_of_storage._M_data);
#else
    if (_M_start_of_storage._M_data != 0)
      _M_start_of_storage.deallocate(_M_start_of_storage._M_data, _M_end_of_storage - _M_start_of_storage._M_data);
#endif /* _STLP_USE_SHORT_STRING_OPTIM */
  }

  size_t max_size() const {
    const size_type __string_max_size = size_type(-1) / sizeof(_Tp);
    typename allocator_type::size_type __alloc_max_size = _M_start_of_storage.max_size();
    return (min)(__alloc_max_size, __string_max_size) - 1;
  }

  _String_base(const allocator_type& __a)
#if defined (_STLP_USE_SHORT_STRING_OPTIM)
    : _M_finish(_M_buffers._M_static_buf), _M_start_of_storage(__a, _M_buffers._M_static_buf)
#else
    : _M_end_of_storage(0), _M_finish(0), _M_start_of_storage(__a, (_Tp*)0)
#endif
    {}

  _String_base(const allocator_type& __a, size_t __n)
#if defined (_STLP_USE_SHORT_STRING_OPTIM)
    : _M_finish(_M_buffers._M_static_buf), _M_start_of_storage(__a, _M_buffers._M_static_buf) {
#else
    : _M_end_of_storage(0), _M_finish(0), _M_start_of_storage(__a, (_Tp*)0) {
#endif
      _M_allocate_block(__n);
    }

#if defined (_STLP_USE_SHORT_STRING_OPTIM)
  void _M_move_src (_Self &src) {
    if (src._M_using_static_buf()) {
      _M_buffers = src._M_buffers;
      _M_finish = _M_buffers._M_static_buf + (src._M_finish - src._M_start_of_storage._M_data);
      _M_start_of_storage._M_data = _M_buffers._M_static_buf;
    }
    else {
      _M_start_of_storage._M_data = src._M_start_of_storage._M_data;
      _M_finish = src._M_finish;
      _M_buffers._M_end_of_storage = src._M_buffers._M_end_of_storage;
      src._M_start_of_storage._M_data = 0;
    }
  }
#endif

#if !defined (_STLP_NO_MOVE_SEMANTIC)
  _String_base(__move_source<_Self> src)
#  if defined (_STLP_USE_SHORT_STRING_OPTIM)
    : _M_start_of_storage(__move_source<_AllocProxy>(src.get()._M_start_of_storage)) {
      _M_move_src(src.get());
#  else
    : _M_end_of_storage(src.get()._M_end_of_storage), _M_finish(src.get()._M_finish),
      _M_start_of_storage(__move_source<_AllocProxy>(src.get()._M_start_of_storage)) {
      src.get()._M_start_of_storage._M_data = 0;
#  endif
    }
#endif

  ~_String_base() { _M_deallocate_block(); }

  void _M_reset(_Tp *__start, _Tp *__finish, _Tp *__end_of_storage) {
#if defined (_STLP_USE_SHORT_STRING_OPTIM)
    _M_buffers._M_end_of_storage = __end_of_storage;
#else
    _M_end_of_storage = __end_of_storage;
#endif
    _M_finish = __finish;
    _M_start_of_storage._M_data = __start;
  }

  void _M_swap(_Self &__s) {
#if defined (_STLP_USE_SHORT_STRING_OPTIM)
    if (_M_using_static_buf()) {
      if (__s._M_using_static_buf()) {
        _STLP_STD::swap(_M_buffers, __s._M_buffers);
        _Tp *__tmp = _M_finish;
        _M_finish = _M_start_of_storage._M_data + (__s._M_finish - __s._M_start_of_storage._M_data);
        __s._M_finish = __s._M_buffers._M_static_buf + (__tmp - _M_start_of_storage._M_data);
        //We need to swap _M_start_of_storage for allocators with state:
        _M_start_of_storage.swap(__s._M_start_of_storage);
        _M_start_of_storage._M_data = _M_buffers._M_static_buf;
        __s._M_start_of_storage._M_data = __s._M_buffers._M_static_buf;
      } else {
        __s._M_swap(*this);
        return;
      }
    }
    else if (__s._M_using_static_buf()) {
      _Tp *__tmp = _M_start_of_storage._M_data;
      _Tp *__tmp_finish = _M_finish;
      _Tp *__tmp_end_data = _M_buffers._M_end_of_storage;
      _M_buffers = __s._M_buffers;
      //We need to swap _M_start_of_storage for allocators with state:
      _M_start_of_storage.swap(__s._M_start_of_storage);
      _M_start_of_storage._M_data = _M_buffers._M_static_buf;
      _M_finish = _M_buffers._M_static_buf + (__s._M_finish - __s._M_buffers._M_static_buf);
      __s._M_buffers._M_end_of_storage = __tmp_end_data;
      __s._M_start_of_storage._M_data = __tmp;
      __s._M_finish = __tmp_finish;
    }
    else {
      _STLP_STD::swap(_M_buffers._M_end_of_storage, __s._M_buffers._M_end_of_storage);
      _M_start_of_storage.swap(__s._M_start_of_storage);
      _STLP_STD::swap(_M_finish, __s._M_finish);
    }
#else
    _STLP_STD::swap(_M_end_of_storage, __s._M_end_of_storage);
    _M_start_of_storage.swap(__s._M_start_of_storage);
    _STLP_STD::swap(_M_finish, __s._M_finish);
#endif
  }

  void _STLP_FUNCTION_THROWS _M_throw_length_error() const;
  void _STLP_FUNCTION_THROWS _M_throw_out_of_range() const;
};

#if defined (_STLP_USE_TEMPLATE_EXPORT)
_STLP_EXPORT_TEMPLATE_CLASS _String_base<char, allocator<char> >;
#  if defined (_STLP_HAS_WCHAR_T)
_STLP_EXPORT_TEMPLATE_CLASS _String_base<wchar_t, allocator<wchar_t> >;
#  endif
#endif /* _STLP_USE_TEMPLATE_EXPORT */

_STLP_MOVE_TO_STD_NAMESPACE

_STLP_END_NAMESPACE

#endif /* _STLP_STRING_BASE_H */

/*
 * Local Variables:
 * mode:C++
 * End:
 */