_string_base.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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. #ifndef _STLP_STRING_BASE_H
  22. #define _STLP_STRING_BASE_H
  23. // ------------------------------------------------------------
  24. // Class _String_base.
  25. // _String_base is a helper class that makes it it easier to write an
  26. // exception-safe version of basic_string. The constructor allocates,
  27. // but does not initialize, a block of memory. The destructor
  28. // deallocates, but does not destroy elements within, a block of
  29. // memory. The destructor assumes that _M_start either is null, or else
  30. // points to a block of memory that was allocated using _String_base's
  31. // allocator and whose size is _M_end_of_storage - _M_start_of_storage._M_data.
  32. _STLP_BEGIN_NAMESPACE
  33. _STLP_MOVE_TO_PRIV_NAMESPACE
  34. template <class _Tp, class _Alloc>
  35. class _String_base {
  36. typedef _String_base<_Tp, _Alloc> _Self;
  37. protected:
  38. _STLP_FORCE_ALLOCATORS(_Tp, _Alloc)
  39. public:
  40. //dums: Some compiler(MSVC6) require it to be public not simply protected!
  41. enum {_DEFAULT_SIZE = 4 * sizeof( void * )};
  42. //This is needed by the full move framework
  43. typedef _Alloc allocator_type;
  44. typedef _STLP_alloc_proxy<_Tp*, _Tp, allocator_type> _AllocProxy;
  45. typedef size_t size_type;
  46. private:
  47. #if defined (_STLP_USE_SHORT_STRING_OPTIM)
  48. union _Buffers {
  49. _Tp* _M_end_of_storage;
  50. _Tp _M_static_buf[_DEFAULT_SIZE];
  51. } _M_buffers;
  52. #else
  53. _Tp* _M_end_of_storage;
  54. #endif /* _STLP_USE_SHORT_STRING_OPTIM */
  55. protected:
  56. #if defined (_STLP_USE_SHORT_STRING_OPTIM)
  57. bool _M_using_static_buf() const
  58. { return (_M_start_of_storage._M_data == _M_buffers._M_static_buf); }
  59. _Tp const* _M_Start() const { return _M_start_of_storage._M_data; }
  60. _Tp* _M_Start() { return _M_start_of_storage._M_data; }
  61. _Tp const* _M_End() const
  62. { return _M_using_static_buf() ? _M_buffers._M_static_buf + _DEFAULT_SIZE : _M_buffers._M_end_of_storage; }
  63. _Tp* _M_End()
  64. { return _M_using_static_buf() ? _M_buffers._M_static_buf + _DEFAULT_SIZE : _M_buffers._M_end_of_storage; }
  65. size_type _M_capacity() const
  66. { return _M_using_static_buf() ? _DEFAULT_SIZE : _M_buffers._M_end_of_storage - _M_start_of_storage._M_data; }
  67. size_type _M_rest() const
  68. { return _M_using_static_buf() ? _DEFAULT_SIZE - (_M_finish - _M_buffers._M_static_buf) : _M_buffers._M_end_of_storage - _M_finish; }
  69. #else
  70. _Tp const* _M_Start() const { return _M_start_of_storage._M_data; }
  71. _Tp* _M_Start() { return _M_start_of_storage._M_data; }
  72. _Tp const* _M_End() const { return _M_end_of_storage; }
  73. _Tp* _M_End() { return _M_end_of_storage; }
  74. size_type _M_capacity() const
  75. { return _M_end_of_storage - _M_start_of_storage._M_data; }
  76. size_type _M_rest() const
  77. { return _M_end_of_storage - _M_finish; }
  78. #endif /* _STLP_USE_SHORT_STRING_OPTIM */
  79. _Tp* _M_finish;
  80. _AllocProxy _M_start_of_storage;
  81. _Tp const* _M_Finish() const {return _M_finish;}
  82. _Tp* _M_Finish() {return _M_finish;}
  83. // Precondition: 0 < __n <= max_size().
  84. void _M_allocate_block(size_t __n = _DEFAULT_SIZE);
  85. void _M_deallocate_block() {
  86. #if defined (_STLP_USE_SHORT_STRING_OPTIM)
  87. if (!_M_using_static_buf() && (_M_start_of_storage._M_data != 0))
  88. _M_start_of_storage.deallocate(_M_start_of_storage._M_data, _M_buffers._M_end_of_storage - _M_start_of_storage._M_data);
  89. #else
  90. if (_M_start_of_storage._M_data != 0)
  91. _M_start_of_storage.deallocate(_M_start_of_storage._M_data, _M_end_of_storage - _M_start_of_storage._M_data);
  92. #endif /* _STLP_USE_SHORT_STRING_OPTIM */
  93. }
  94. size_t max_size() const {
  95. const size_type __string_max_size = size_type(-1) / sizeof(_Tp);
  96. typename allocator_type::size_type __alloc_max_size = _M_start_of_storage.max_size();
  97. return (min)(__alloc_max_size, __string_max_size) - 1;
  98. }
  99. _String_base(const allocator_type& __a)
  100. #if defined (_STLP_USE_SHORT_STRING_OPTIM)
  101. : _M_finish(_M_buffers._M_static_buf), _M_start_of_storage(__a, _M_buffers._M_static_buf)
  102. #else
  103. : _M_end_of_storage(0), _M_finish(0), _M_start_of_storage(__a, (_Tp*)0)
  104. #endif
  105. {}
  106. _String_base(const allocator_type& __a, size_t __n)
  107. #if defined (_STLP_USE_SHORT_STRING_OPTIM)
  108. : _M_finish(_M_buffers._M_static_buf), _M_start_of_storage(__a, _M_buffers._M_static_buf) {
  109. #else
  110. : _M_end_of_storage(0), _M_finish(0), _M_start_of_storage(__a, (_Tp*)0) {
  111. #endif
  112. _M_allocate_block(__n);
  113. }
  114. #if defined (_STLP_USE_SHORT_STRING_OPTIM)
  115. void _M_move_src (_Self &src) {
  116. if (src._M_using_static_buf()) {
  117. _M_buffers = src._M_buffers;
  118. _M_finish = _M_buffers._M_static_buf + (src._M_finish - src._M_start_of_storage._M_data);
  119. _M_start_of_storage._M_data = _M_buffers._M_static_buf;
  120. }
  121. else {
  122. _M_start_of_storage._M_data = src._M_start_of_storage._M_data;
  123. _M_finish = src._M_finish;
  124. _M_buffers._M_end_of_storage = src._M_buffers._M_end_of_storage;
  125. src._M_start_of_storage._M_data = 0;
  126. }
  127. }
  128. #endif
  129. #if !defined (_STLP_NO_MOVE_SEMANTIC)
  130. _String_base(__move_source<_Self> src)
  131. # if defined (_STLP_USE_SHORT_STRING_OPTIM)
  132. : _M_start_of_storage(__move_source<_AllocProxy>(src.get()._M_start_of_storage)) {
  133. _M_move_src(src.get());
  134. # else
  135. : _M_end_of_storage(src.get()._M_end_of_storage), _M_finish(src.get()._M_finish),
  136. _M_start_of_storage(__move_source<_AllocProxy>(src.get()._M_start_of_storage)) {
  137. src.get()._M_start_of_storage._M_data = 0;
  138. # endif
  139. }
  140. #endif
  141. ~_String_base() { _M_deallocate_block(); }
  142. void _M_reset(_Tp *__start, _Tp *__finish, _Tp *__end_of_storage) {
  143. #if defined (_STLP_USE_SHORT_STRING_OPTIM)
  144. _M_buffers._M_end_of_storage = __end_of_storage;
  145. #else
  146. _M_end_of_storage = __end_of_storage;
  147. #endif
  148. _M_finish = __finish;
  149. _M_start_of_storage._M_data = __start;
  150. }
  151. void _M_swap(_Self &__s) {
  152. #if defined (_STLP_USE_SHORT_STRING_OPTIM)
  153. if (_M_using_static_buf()) {
  154. if (__s._M_using_static_buf()) {
  155. _STLP_STD::swap(_M_buffers, __s._M_buffers);
  156. _Tp *__tmp = _M_finish;
  157. _M_finish = _M_start_of_storage._M_data + (__s._M_finish - __s._M_start_of_storage._M_data);
  158. __s._M_finish = __s._M_buffers._M_static_buf + (__tmp - _M_start_of_storage._M_data);
  159. //We need to swap _M_start_of_storage for allocators with state:
  160. _M_start_of_storage.swap(__s._M_start_of_storage);
  161. _M_start_of_storage._M_data = _M_buffers._M_static_buf;
  162. __s._M_start_of_storage._M_data = __s._M_buffers._M_static_buf;
  163. } else {
  164. __s._M_swap(*this);
  165. return;
  166. }
  167. }
  168. else if (__s._M_using_static_buf()) {
  169. _Tp *__tmp = _M_start_of_storage._M_data;
  170. _Tp *__tmp_finish = _M_finish;
  171. _Tp *__tmp_end_data = _M_buffers._M_end_of_storage;
  172. _M_buffers = __s._M_buffers;
  173. //We need to swap _M_start_of_storage for allocators with state:
  174. _M_start_of_storage.swap(__s._M_start_of_storage);
  175. _M_start_of_storage._M_data = _M_buffers._M_static_buf;
  176. _M_finish = _M_buffers._M_static_buf + (__s._M_finish - __s._M_buffers._M_static_buf);
  177. __s._M_buffers._M_end_of_storage = __tmp_end_data;
  178. __s._M_start_of_storage._M_data = __tmp;
  179. __s._M_finish = __tmp_finish;
  180. }
  181. else {
  182. _STLP_STD::swap(_M_buffers._M_end_of_storage, __s._M_buffers._M_end_of_storage);
  183. _M_start_of_storage.swap(__s._M_start_of_storage);
  184. _STLP_STD::swap(_M_finish, __s._M_finish);
  185. }
  186. #else
  187. _STLP_STD::swap(_M_end_of_storage, __s._M_end_of_storage);
  188. _M_start_of_storage.swap(__s._M_start_of_storage);
  189. _STLP_STD::swap(_M_finish, __s._M_finish);
  190. #endif
  191. }
  192. void _STLP_FUNCTION_THROWS _M_throw_length_error() const;
  193. void _STLP_FUNCTION_THROWS _M_throw_out_of_range() const;
  194. };
  195. #if defined (_STLP_USE_TEMPLATE_EXPORT)
  196. _STLP_EXPORT_TEMPLATE_CLASS _String_base<char, allocator<char> >;
  197. # if defined (_STLP_HAS_WCHAR_T)
  198. _STLP_EXPORT_TEMPLATE_CLASS _String_base<wchar_t, allocator<wchar_t> >;
  199. # endif
  200. #endif /* _STLP_USE_TEMPLATE_EXPORT */
  201. _STLP_MOVE_TO_STD_NAMESPACE
  202. _STLP_END_NAMESPACE
  203. #endif /* _STLP_STRING_BASE_H */
  204. /*
  205. * Local Variables:
  206. * mode:C++
  207. * End:
  208. */