PSP2SDK
dirty-f9e4f2d
The free SDK for PSP2
|
00001 // Short-string-optimized versatile string base -*- C++ -*- 00002 00003 // Copyright (C) 2015 PSP2SDK Project 00004 // This file is modified by PSP2SDK Team 00005 00006 // Copyright (C) 2005-2014 Free Software Foundation, Inc. 00007 // 00008 // This file is part of the GNU ISO C++ Library. This library is free 00009 // software; you can redistribute it and/or modify it under the 00010 // terms of the GNU General Public License as published by the 00011 // Free Software Foundation; either version 3, or (at your option) 00012 // any later version. 00013 00014 // This library is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 // GNU General Public License for more details. 00018 00019 // Under Section 7 of GPL version 3, you are granted additional 00020 // permissions described in the GCC Runtime Library Exception, version 00021 // 3.1, as published by the Free Software Foundation. 00022 00023 // You should have received a copy of the GNU General Public License and 00024 // a copy of the GCC Runtime Library Exception along with this program; 00025 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00026 // <http://www.gnu.org/licenses/>. 00027 00033 #ifndef _SSO_STRING_BASE_H 00034 #define _SSO_STRING_BASE_H 1 00035 #include <stdexcept> 00036 00037 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) 00038 { 00039 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00040 00041 template<typename _CharT, typename _Traits, typename _Alloc> 00042 class __sso_string_base 00043 : protected __vstring_utility<_CharT, _Traits, _Alloc> 00044 { 00045 public: 00046 typedef _Traits traits_type; 00047 typedef typename _Traits::char_type value_type; 00048 00049 typedef __vstring_utility<_CharT, _Traits, _Alloc> _Util_Base; 00050 typedef typename _Util_Base::_CharT_alloc_type _CharT_alloc_type; 00051 typedef typename _CharT_alloc_type::size_type size_type; 00052 00053 private: 00054 // Data Members: 00055 typename _Util_Base::template _Alloc_hider<_CharT_alloc_type> 00056 _M_dataplus; 00057 size_type _M_string_length; 00058 00059 enum { _S_local_capacity = 15 }; 00060 00061 union 00062 { 00063 _CharT _M_local_data[_S_local_capacity + 1]; 00064 size_type _M_allocated_capacity; 00065 }; 00066 00067 void 00068 _M_data(_CharT* __p) 00069 { _M_dataplus._M_p = __p; } 00070 00071 void 00072 _M_length(size_type __length) 00073 { _M_string_length = __length; } 00074 00075 void 00076 _M_capacity(size_type __capacity) 00077 { _M_allocated_capacity = __capacity; } 00078 00079 bool 00080 _M_is_local() const 00081 { return _M_data() == _M_local_data; } 00082 00083 // Create & Destroy 00084 _CharT* 00085 _M_create(size_type&, size_type); 00086 00087 void 00088 _M_dispose() 00089 { 00090 if (!_M_is_local()) 00091 _M_destroy(_M_allocated_capacity); 00092 } 00093 00094 void 00095 _M_destroy(size_type __size) throw() 00096 { _M_get_allocator().deallocate(_M_data(), __size + 1); } 00097 00098 // _M_construct_aux is used to implement the 21.3.1 para 15 which 00099 // requires special behaviour if _InIterator is an integral type 00100 template<typename _InIterator> 00101 void 00102 _M_construct_aux(_InIterator __beg, _InIterator __end, 00103 std::__false_type) 00104 { 00105 typedef typename iterator_traits<_InIterator>::iterator_category _Tag; 00106 _M_construct(__beg, __end, _Tag()); 00107 } 00108 00109 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00110 // 438. Ambiguity in the "do the right thing" clause 00111 template<typename _Integer> 00112 void 00113 _M_construct_aux(_Integer __beg, _Integer __end, std::__true_type) 00114 { _M_construct_aux_2(static_cast<size_type>(__beg), __end); } 00115 00116 void 00117 _M_construct_aux_2(size_type __req, _CharT __c) 00118 { _M_construct(__req, __c); } 00119 00120 template<typename _InIterator> 00121 void 00122 _M_construct(_InIterator __beg, _InIterator __end) 00123 { 00124 typedef typename std::__is_integer<_InIterator>::__type _Integral; 00125 _M_construct_aux(__beg, __end, _Integral()); 00126 } 00127 00128 // For Input Iterators, used in istreambuf_iterators, etc. 00129 template<typename _InIterator> 00130 void 00131 _M_construct(_InIterator __beg, _InIterator __end, 00132 std::input_iterator_tag); 00133 00134 // For forward_iterators up to random_access_iterators, used for 00135 // string::iterator, _CharT*, etc. 00136 template<typename _FwdIterator> 00137 void 00138 _M_construct(_FwdIterator __beg, _FwdIterator __end, 00139 std::forward_iterator_tag); 00140 00141 void 00142 _M_construct(size_type __req, _CharT __c); 00143 00144 public: 00145 size_type 00146 _M_max_size() const 00147 { return (_M_get_allocator().max_size() - 1) / 2; } 00148 00149 _CharT* 00150 _M_data() const 00151 { return _M_dataplus._M_p; } 00152 00153 size_type 00154 _M_length() const 00155 { return _M_string_length; } 00156 00157 size_type 00158 _M_capacity() const 00159 { 00160 return _M_is_local() ? size_type(_S_local_capacity) 00161 : _M_allocated_capacity; 00162 } 00163 00164 bool 00165 _M_is_shared() const 00166 { return false; } 00167 00168 void 00169 _M_set_leaked() { } 00170 00171 void 00172 _M_leak() { } 00173 00174 void 00175 _M_set_length(size_type __n) 00176 { 00177 _M_length(__n); 00178 traits_type::assign(_M_data()[__n], _CharT()); 00179 } 00180 00181 __sso_string_base() 00182 : _M_dataplus(_M_local_data) 00183 { _M_set_length(0); } 00184 00185 __sso_string_base(const _Alloc& __a); 00186 00187 __sso_string_base(const __sso_string_base& __rcs); 00188 00189 #if __cplusplus >= 201103L 00190 __sso_string_base(__sso_string_base&& __rcs); 00191 #endif 00192 00193 __sso_string_base(size_type __n, _CharT __c, const _Alloc& __a); 00194 00195 template<typename _InputIterator> 00196 __sso_string_base(_InputIterator __beg, _InputIterator __end, 00197 const _Alloc& __a); 00198 00199 ~__sso_string_base() 00200 { _M_dispose(); } 00201 00202 _CharT_alloc_type& 00203 _M_get_allocator() 00204 { return _M_dataplus; } 00205 00206 const _CharT_alloc_type& 00207 _M_get_allocator() const 00208 { return _M_dataplus; } 00209 00210 void 00211 _M_swap(__sso_string_base& __rcs); 00212 00213 void 00214 _M_assign(const __sso_string_base& __rcs); 00215 00216 void 00217 _M_reserve(size_type __res); 00218 00219 void 00220 _M_mutate(size_type __pos, size_type __len1, const _CharT* __s, 00221 size_type __len2); 00222 00223 void 00224 _M_erase(size_type __pos, size_type __n); 00225 00226 void 00227 _M_clear() 00228 { _M_set_length(0); } 00229 00230 bool 00231 _M_compare(const __sso_string_base&) const 00232 { return false; } 00233 }; 00234 00235 template<typename _CharT, typename _Traits, typename _Alloc> 00236 void 00237 __sso_string_base<_CharT, _Traits, _Alloc>:: 00238 _M_swap(__sso_string_base& __rcs) 00239 { 00240 if (this == &__rcs) 00241 return; 00242 00243 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00244 // 431. Swapping containers with unequal allocators. 00245 std::__alloc_swap<_CharT_alloc_type>::_S_do_it(_M_get_allocator(), 00246 __rcs._M_get_allocator()); 00247 00248 if (_M_is_local()) 00249 if (__rcs._M_is_local()) 00250 { 00251 if (_M_length() && __rcs._M_length()) 00252 { 00253 _CharT __tmp_data[_S_local_capacity + 1]; 00254 traits_type::copy(__tmp_data, __rcs._M_local_data, 00255 _S_local_capacity + 1); 00256 traits_type::copy(__rcs._M_local_data, _M_local_data, 00257 _S_local_capacity + 1); 00258 traits_type::copy(_M_local_data, __tmp_data, 00259 _S_local_capacity + 1); 00260 } 00261 else if (__rcs._M_length()) 00262 { 00263 traits_type::copy(_M_local_data, __rcs._M_local_data, 00264 _S_local_capacity + 1); 00265 _M_length(__rcs._M_length()); 00266 __rcs._M_set_length(0); 00267 return; 00268 } 00269 else if (_M_length()) 00270 { 00271 traits_type::copy(__rcs._M_local_data, _M_local_data, 00272 _S_local_capacity + 1); 00273 __rcs._M_length(_M_length()); 00274 _M_set_length(0); 00275 return; 00276 } 00277 } 00278 else 00279 { 00280 const size_type __tmp_capacity = __rcs._M_allocated_capacity; 00281 traits_type::copy(__rcs._M_local_data, _M_local_data, 00282 _S_local_capacity + 1); 00283 _M_data(__rcs._M_data()); 00284 __rcs._M_data(__rcs._M_local_data); 00285 _M_capacity(__tmp_capacity); 00286 } 00287 else 00288 { 00289 const size_type __tmp_capacity = _M_allocated_capacity; 00290 if (__rcs._M_is_local()) 00291 { 00292 traits_type::copy(_M_local_data, __rcs._M_local_data, 00293 _S_local_capacity + 1); 00294 __rcs._M_data(_M_data()); 00295 _M_data(_M_local_data); 00296 } 00297 else 00298 { 00299 _CharT* __tmp_ptr = _M_data(); 00300 _M_data(__rcs._M_data()); 00301 __rcs._M_data(__tmp_ptr); 00302 _M_capacity(__rcs._M_allocated_capacity); 00303 } 00304 __rcs._M_capacity(__tmp_capacity); 00305 } 00306 00307 const size_type __tmp_length = _M_length(); 00308 _M_length(__rcs._M_length()); 00309 __rcs._M_length(__tmp_length); 00310 } 00311 00312 template<typename _CharT, typename _Traits, typename _Alloc> 00313 _CharT* 00314 __sso_string_base<_CharT, _Traits, _Alloc>:: 00315 _M_create(size_type& __capacity, size_type __old_capacity) 00316 { 00317 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00318 // 83. String::npos vs. string::max_size() 00319 if (__capacity > _M_max_size()) 00320 std::__throw_length_error(__N("__sso_string_base::_M_create")); 00321 00322 // The below implements an exponential growth policy, necessary to 00323 // meet amortized linear time requirements of the library: see 00324 // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html. 00325 if (__capacity > __old_capacity && __capacity < 2 * __old_capacity) 00326 { 00327 __capacity = 2 * __old_capacity; 00328 // Never allocate a string bigger than max_size. 00329 if (__capacity > _M_max_size()) 00330 __capacity = _M_max_size(); 00331 } 00332 00333 // NB: Need an array of char_type[__capacity], plus a terminating 00334 // null char_type() element. 00335 return _M_get_allocator().allocate(__capacity + 1); 00336 } 00337 00338 template<typename _CharT, typename _Traits, typename _Alloc> 00339 __sso_string_base<_CharT, _Traits, _Alloc>:: 00340 __sso_string_base(const _Alloc& __a) 00341 : _M_dataplus(__a, _M_local_data) 00342 { _M_set_length(0); } 00343 00344 template<typename _CharT, typename _Traits, typename _Alloc> 00345 __sso_string_base<_CharT, _Traits, _Alloc>:: 00346 __sso_string_base(const __sso_string_base& __rcs) 00347 : _M_dataplus(__rcs._M_get_allocator(), _M_local_data) 00348 { _M_construct(__rcs._M_data(), __rcs._M_data() + __rcs._M_length()); } 00349 00350 #if __cplusplus >= 201103L 00351 template<typename _CharT, typename _Traits, typename _Alloc> 00352 __sso_string_base<_CharT, _Traits, _Alloc>:: 00353 __sso_string_base(__sso_string_base&& __rcs) 00354 : _M_dataplus(__rcs._M_get_allocator(), _M_local_data) 00355 { 00356 if (__rcs._M_is_local()) 00357 { 00358 if (__rcs._M_length()) 00359 traits_type::copy(_M_local_data, __rcs._M_local_data, 00360 _S_local_capacity + 1); 00361 } 00362 else 00363 { 00364 _M_data(__rcs._M_data()); 00365 _M_capacity(__rcs._M_allocated_capacity); 00366 } 00367 00368 _M_set_length(__rcs._M_length()); 00369 __rcs._M_data(__rcs._M_local_data); 00370 __rcs._M_set_length(0); 00371 } 00372 #endif 00373 00374 template<typename _CharT, typename _Traits, typename _Alloc> 00375 __sso_string_base<_CharT, _Traits, _Alloc>:: 00376 __sso_string_base(size_type __n, _CharT __c, const _Alloc& __a) 00377 : _M_dataplus(__a, _M_local_data) 00378 { _M_construct(__n, __c); } 00379 00380 template<typename _CharT, typename _Traits, typename _Alloc> 00381 template<typename _InputIterator> 00382 __sso_string_base<_CharT, _Traits, _Alloc>:: 00383 __sso_string_base(_InputIterator __beg, _InputIterator __end, 00384 const _Alloc& __a) 00385 : _M_dataplus(__a, _M_local_data) 00386 { _M_construct(__beg, __end); } 00387 00388 // NB: This is the special case for Input Iterators, used in 00389 // istreambuf_iterators, etc. 00390 // Input Iterators have a cost structure very different from 00391 // pointers, calling for a different coding style. 00392 template<typename _CharT, typename _Traits, typename _Alloc> 00393 template<typename _InIterator> 00394 void 00395 __sso_string_base<_CharT, _Traits, _Alloc>:: 00396 _M_construct(_InIterator __beg, _InIterator __end, 00397 std::input_iterator_tag) 00398 { 00399 size_type __len = 0; 00400 size_type __capacity = size_type(_S_local_capacity); 00401 00402 while (__beg != __end && __len < __capacity) 00403 { 00404 _M_data()[__len++] = *__beg; 00405 ++__beg; 00406 } 00407 00408 __try 00409 { 00410 while (__beg != __end) 00411 { 00412 if (__len == __capacity) 00413 { 00414 // Allocate more space. 00415 __capacity = __len + 1; 00416 _CharT* __another = _M_create(__capacity, __len); 00417 this->_S_copy(__another, _M_data(), __len); 00418 _M_dispose(); 00419 _M_data(__another); 00420 _M_capacity(__capacity); 00421 } 00422 _M_data()[__len++] = *__beg; 00423 ++__beg; 00424 } 00425 } 00426 __catch(...) 00427 { 00428 _M_dispose(); 00429 __throw_exception_again; 00430 } 00431 00432 _M_set_length(__len); 00433 } 00434 00435 template<typename _CharT, typename _Traits, typename _Alloc> 00436 template<typename _InIterator> 00437 void 00438 __sso_string_base<_CharT, _Traits, _Alloc>:: 00439 _M_construct(_InIterator __beg, _InIterator __end, 00440 std::forward_iterator_tag) 00441 { 00442 // NB: Not required, but considered best practice. 00443 if (__is_null_pointer(__beg) && __beg != __end) 00444 throw logic_error(__N("__sso_string_base::" 00445 "_M_construct null not valid")); 00446 00447 size_type __dnew = static_cast<size_type>(std::distance(__beg, __end)); 00448 00449 if (__dnew > size_type(_S_local_capacity)) 00450 { 00451 _M_data(_M_create(__dnew, size_type(0))); 00452 _M_capacity(__dnew); 00453 } 00454 00455 // Check for out_of_range and length_error exceptions. 00456 __try 00457 { this->_S_copy_chars(_M_data(), __beg, __end); } 00458 __catch(...) 00459 { 00460 _M_dispose(); 00461 __throw_exception_again; 00462 } 00463 00464 _M_set_length(__dnew); 00465 } 00466 00467 template<typename _CharT, typename _Traits, typename _Alloc> 00468 void 00469 __sso_string_base<_CharT, _Traits, _Alloc>:: 00470 _M_construct(size_type __n, _CharT __c) 00471 { 00472 if (__n > size_type(_S_local_capacity)) 00473 { 00474 _M_data(_M_create(__n, size_type(0))); 00475 _M_capacity(__n); 00476 } 00477 00478 if (__n) 00479 this->_S_assign(_M_data(), __n, __c); 00480 00481 _M_set_length(__n); 00482 } 00483 00484 template<typename _CharT, typename _Traits, typename _Alloc> 00485 void 00486 __sso_string_base<_CharT, _Traits, _Alloc>:: 00487 _M_assign(const __sso_string_base& __rcs) 00488 { 00489 if (this != &__rcs) 00490 { 00491 const size_type __rsize = __rcs._M_length(); 00492 const size_type __capacity = _M_capacity(); 00493 00494 if (__rsize > __capacity) 00495 { 00496 size_type __new_capacity = __rsize; 00497 _CharT* __tmp = _M_create(__new_capacity, __capacity); 00498 _M_dispose(); 00499 _M_data(__tmp); 00500 _M_capacity(__new_capacity); 00501 } 00502 00503 if (__rsize) 00504 this->_S_copy(_M_data(), __rcs._M_data(), __rsize); 00505 00506 _M_set_length(__rsize); 00507 } 00508 } 00509 00510 template<typename _CharT, typename _Traits, typename _Alloc> 00511 void 00512 __sso_string_base<_CharT, _Traits, _Alloc>:: 00513 _M_reserve(size_type __res) 00514 { 00515 // Make sure we don't shrink below the current size. 00516 if (__res < _M_length()) 00517 __res = _M_length(); 00518 00519 const size_type __capacity = _M_capacity(); 00520 if (__res != __capacity) 00521 { 00522 if (__res > __capacity 00523 || __res > size_type(_S_local_capacity)) 00524 { 00525 _CharT* __tmp = _M_create(__res, __capacity); 00526 this->_S_copy(__tmp, _M_data(), _M_length() + 1); 00527 _M_dispose(); 00528 _M_data(__tmp); 00529 _M_capacity(__res); 00530 } 00531 else if (!_M_is_local()) 00532 { 00533 this->_S_copy(_M_local_data, _M_data(), _M_length() + 1); 00534 _M_destroy(__capacity); 00535 _M_data(_M_local_data); 00536 } 00537 } 00538 } 00539 00540 template<typename _CharT, typename _Traits, typename _Alloc> 00541 void 00542 __sso_string_base<_CharT, _Traits, _Alloc>:: 00543 _M_mutate(size_type __pos, size_type __len1, const _CharT* __s, 00544 size_type __len2) 00545 { 00546 const size_type __how_much = _M_length() - __pos - __len1; 00547 00548 size_type __new_capacity = _M_length() + __len2 - __len1; 00549 _CharT* __r = _M_create(__new_capacity, _M_capacity()); 00550 00551 if (__pos) 00552 this->_S_copy(__r, _M_data(), __pos); 00553 if (__s && __len2) 00554 this->_S_copy(__r + __pos, __s, __len2); 00555 if (__how_much) 00556 this->_S_copy(__r + __pos + __len2, 00557 _M_data() + __pos + __len1, __how_much); 00558 00559 _M_dispose(); 00560 _M_data(__r); 00561 _M_capacity(__new_capacity); 00562 } 00563 00564 template<typename _CharT, typename _Traits, typename _Alloc> 00565 void 00566 __sso_string_base<_CharT, _Traits, _Alloc>:: 00567 _M_erase(size_type __pos, size_type __n) 00568 { 00569 const size_type __how_much = _M_length() - __pos - __n; 00570 00571 if (__how_much && __n) 00572 this->_S_move(_M_data() + __pos, _M_data() + __pos + __n, __how_much); 00573 00574 _M_set_length(_M_length() - __n); 00575 } 00576 00577 _GLIBCXX_END_NAMESPACE_VERSION 00578 } // namespace 00579 00580 #endif /* _SSO_STRING_BASE_H */