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() ? _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