williamr@4: /* williamr@4: * Copyright (c) 1997-1999 williamr@4: * Silicon Graphics Computer Systems, Inc. williamr@4: * williamr@4: * Copyright (c) 1999 williamr@4: * Boris Fomitchev williamr@4: * williamr@4: * Copyright (c) 2003 williamr@4: * Francois Dumont williamr@4: * williamr@4: * This material is provided "as is", with absolutely no warranty expressed williamr@4: * or implied. Any use is at your own risk. williamr@4: * williamr@4: * Permission to use or copy this software for any purpose is hereby granted williamr@4: * without fee, provided the above notices are retained on all copies. williamr@4: * Permission to modify the code and to distribute modified code is granted, williamr@4: * provided the above notices are retained, and a notice that the code was williamr@4: * modified is included with the above copyright notice. williamr@4: * williamr@4: */ williamr@4: williamr@4: #ifndef _STLP_STRING_BASE_H williamr@4: #define _STLP_STRING_BASE_H williamr@4: williamr@4: // ------------------------------------------------------------ williamr@4: // Class _String_base. williamr@4: williamr@4: // _String_base is a helper class that makes it it easier to write an williamr@4: // exception-safe version of basic_string. The constructor allocates, williamr@4: // but does not initialize, a block of memory. The destructor williamr@4: // deallocates, but does not destroy elements within, a block of williamr@4: // memory. The destructor assumes that _M_start either is null, or else williamr@4: // points to a block of memory that was allocated using _String_base's williamr@4: // allocator and whose size is _M_end_of_storage._M_data - _M_start. williamr@4: williamr@4: _STLP_BEGIN_NAMESPACE williamr@4: williamr@4: _STLP_MOVE_TO_PRIV_NAMESPACE williamr@4: williamr@4: #ifndef _STLP_SHORT_STRING_SZ williamr@4: # define _STLP_SHORT_STRING_SZ 16 williamr@4: #endif williamr@4: williamr@4: template williamr@4: class _String_base { williamr@4: typedef _String_base<_Tp, _Alloc> _Self; williamr@4: protected: williamr@4: _STLP_FORCE_ALLOCATORS(_Tp, _Alloc) williamr@4: public: williamr@4: //dums: Some compiler(MSVC6) require it to be public not simply protected! williamr@4: enum {_DEFAULT_SIZE = _STLP_SHORT_STRING_SZ}; williamr@4: //This is needed by the full move framework williamr@4: typedef typename _Alloc_traits<_Tp, _Alloc>::allocator_type allocator_type; williamr@4: typedef _STLP_alloc_proxy<_Tp*, _Tp, allocator_type> _AllocProxy; williamr@4: typedef size_t size_type; williamr@4: private: williamr@4: #if defined (_STLP_USE_SHORT_STRING_OPTIM) williamr@4: union _Buffers { williamr@4: _Tp* _M_dynamic_buf; williamr@4: _Tp _M_static_buf[_DEFAULT_SIZE]; williamr@4: } _M_buffers; williamr@4: #else williamr@4: _Tp* _M_start; williamr@4: #endif /* _STLP_USE_SHORT_STRING_OPTIM */ williamr@4: protected: williamr@4: #if defined (_STLP_USE_SHORT_STRING_OPTIM) williamr@4: bool _M_using_static_buf() const { williamr@4: return (_M_end_of_storage._M_data == _M_buffers._M_static_buf + _DEFAULT_SIZE); williamr@4: } williamr@4: _Tp const* _M_Start() const { williamr@4: return _M_using_static_buf()?_M_buffers._M_static_buf:_M_buffers._M_dynamic_buf; williamr@4: } williamr@4: _Tp* _M_Start() { williamr@4: return _M_using_static_buf()?_M_buffers._M_static_buf:_M_buffers._M_dynamic_buf; williamr@4: } williamr@4: #else williamr@4: _Tp const* _M_Start() const {return _M_start;} williamr@4: _Tp* _M_Start() {return _M_start;} williamr@4: #endif /* _STLP_USE_SHORT_STRING_OPTIM */ williamr@4: williamr@4: _Tp* _M_finish; williamr@4: _AllocProxy _M_end_of_storage; williamr@4: williamr@4: _Tp const* _M_Finish() const {return _M_finish;} williamr@4: _Tp* _M_Finish() {return _M_finish;} williamr@4: williamr@4: // Precondition: 0 < __n <= max_size(). williamr@4: void _M_allocate_block(size_t __n = _DEFAULT_SIZE); williamr@4: void _M_deallocate_block() { williamr@4: #if defined (_STLP_USE_SHORT_STRING_OPTIM) williamr@4: if (!_M_using_static_buf() && (_M_buffers._M_dynamic_buf != 0)) williamr@4: _M_end_of_storage.deallocate(_M_buffers._M_dynamic_buf, _M_end_of_storage._M_data - _M_buffers._M_dynamic_buf); williamr@4: #else williamr@4: if (_M_start != 0) williamr@4: _M_end_of_storage.deallocate(_M_start, _M_end_of_storage._M_data - _M_start); williamr@4: #endif /* _STLP_USE_SHORT_STRING_OPTIM */ williamr@4: } williamr@4: williamr@4: size_t max_size() const { williamr@4: const size_type __string_max_size = size_type(-1) / sizeof(_Tp); williamr@4: typename allocator_type::size_type __alloc_max_size = _M_end_of_storage.max_size(); williamr@4: return (min)(__alloc_max_size, __string_max_size) - 1; williamr@4: } williamr@4: williamr@4: _String_base(const allocator_type& __a) williamr@4: #if defined (_STLP_USE_SHORT_STRING_OPTIM) williamr@4: : _M_finish(_M_buffers._M_static_buf), _M_end_of_storage(__a, _M_buffers._M_static_buf + _DEFAULT_SIZE) williamr@4: #else williamr@4: : _M_start(0), _M_finish(0), _M_end_of_storage(__a, (_Tp*)0) williamr@4: #endif williamr@4: {} williamr@4: williamr@4: _String_base(const allocator_type& __a, size_t __n) williamr@4: #if defined (_STLP_USE_SHORT_STRING_OPTIM) williamr@4: : _M_finish(_M_buffers._M_static_buf), _M_end_of_storage(__a, _M_buffers._M_static_buf + _DEFAULT_SIZE) { williamr@4: #else williamr@4: : _M_start(0), _M_finish(0), _M_end_of_storage(__a, (_Tp*)0) { williamr@4: #endif williamr@4: _M_allocate_block(__n); williamr@4: } williamr@4: williamr@4: #if defined (_STLP_USE_SHORT_STRING_OPTIM) williamr@4: void _M_move_src (_Self &src) { williamr@4: if (src._M_using_static_buf()) { williamr@4: _M_buffers = src._M_buffers; williamr@4: _M_finish = _M_buffers._M_static_buf + (src._M_finish - src._M_buffers._M_static_buf); williamr@4: _M_end_of_storage._M_data = _M_buffers._M_static_buf + _DEFAULT_SIZE; williamr@4: } williamr@4: else { williamr@4: _M_buffers._M_dynamic_buf = src._M_buffers._M_dynamic_buf; williamr@4: _M_finish = src._M_finish; williamr@4: _M_end_of_storage._M_data = src._M_end_of_storage._M_data; williamr@4: src._M_buffers._M_dynamic_buf = 0; williamr@4: } williamr@4: } williamr@4: #endif williamr@4: williamr@4: _String_base(__move_source<_Self> src) williamr@4: #if defined (_STLP_USE_SHORT_STRING_OPTIM) williamr@4: : _M_end_of_storage(__move_source<_AllocProxy>(src.get()._M_end_of_storage)) { williamr@4: _M_move_src(src.get()); williamr@4: #else williamr@4: : _M_start(src.get()._M_start), _M_finish(src.get()._M_finish), williamr@4: _M_end_of_storage(__move_source<_AllocProxy>(src.get()._M_end_of_storage)) { williamr@4: src.get()._M_start = 0; williamr@4: #endif williamr@4: } williamr@4: williamr@4: ~_String_base() { _M_deallocate_block(); } williamr@4: williamr@4: void _M_reset(_Tp *__start, _Tp *__finish, _Tp *__end_of_storage) { williamr@4: #if defined (_STLP_USE_SHORT_STRING_OPTIM) williamr@4: _M_buffers._M_dynamic_buf = __start; williamr@4: #else williamr@4: _M_start = __start; williamr@4: #endif williamr@4: _M_finish = __finish; williamr@4: _M_end_of_storage._M_data = __end_of_storage; williamr@4: } williamr@4: williamr@4: void _M_destroy_back () { williamr@4: #if defined (_STLP_USE_SHORT_STRING_OPTIM) williamr@4: if (!_M_using_static_buf()) williamr@4: #endif /* _STLP_USE_SHORT_STRING_OPTIM */ williamr@4: _STLP_STD::_Destroy(_M_finish); williamr@4: } williamr@4: williamr@4: void _M_destroy_range(size_t __from_off = 0, size_t __to_off = 1) { williamr@4: #if defined (_STLP_USE_SHORT_STRING_OPTIM) williamr@4: if (!_M_using_static_buf()) williamr@4: _STLP_STD::_Destroy_Range(_M_buffers._M_dynamic_buf + __from_off, _M_finish + __to_off); williamr@4: #else williamr@4: _STLP_STD::_Destroy_Range(_M_start + __from_off, _M_finish + __to_off); williamr@4: #endif /* _STLP_USE_SHORT_STRING_OPTIM */ williamr@4: } williamr@4: williamr@4: void _M_destroy_ptr_range(_Tp *__f, _Tp *__l) { williamr@4: #if defined (_STLP_USE_SHORT_STRING_OPTIM) williamr@4: if (!_M_using_static_buf()) williamr@4: #endif /* _STLP_USE_SHORT_STRING_OPTIM */ williamr@4: _STLP_STD::_Destroy_Range(__f, __l); williamr@4: } williamr@4: williamr@4: void _M_Swap(_Self &__s) { williamr@4: #if defined (_STLP_USE_SHORT_STRING_OPTIM) williamr@4: if (_M_using_static_buf()) { williamr@4: if (__s._M_using_static_buf()) { williamr@4: _STLP_STD::swap(_M_buffers, __s._M_buffers); williamr@4: _Tp *__tmp = _M_finish; williamr@4: _M_finish = _M_buffers._M_static_buf + (__s._M_finish - __s._M_buffers._M_static_buf); williamr@4: __s._M_finish = __s._M_buffers._M_static_buf + (__tmp - _M_buffers._M_static_buf); williamr@4: //We need to swap _M_end_of_storage for allocators with state: williamr@4: _M_end_of_storage.swap(__s._M_end_of_storage); williamr@4: _M_end_of_storage._M_data = _M_buffers._M_static_buf + _DEFAULT_SIZE; williamr@4: __s._M_end_of_storage._M_data = __s._M_buffers._M_static_buf + _DEFAULT_SIZE; williamr@4: } else { williamr@4: __s._M_Swap(*this); williamr@4: return; williamr@4: } williamr@4: } williamr@4: else if (__s._M_using_static_buf()) { williamr@4: _Tp *__tmp = _M_buffers._M_dynamic_buf; williamr@4: _Tp *__tmp_finish = _M_finish; williamr@4: _Tp *__tmp_end_data = _M_end_of_storage._M_data; williamr@4: _M_buffers = __s._M_buffers; williamr@4: //We need to swap _M_end_of_storage for allocators with state: williamr@4: _M_end_of_storage.swap(__s._M_end_of_storage); williamr@4: _M_end_of_storage._M_data = _M_buffers._M_static_buf + _DEFAULT_SIZE; williamr@4: _M_finish = _M_buffers._M_static_buf + (__s._M_finish - __s._M_buffers._M_static_buf); williamr@4: __s._M_buffers._M_dynamic_buf = __tmp; williamr@4: __s._M_end_of_storage._M_data = __tmp_end_data; williamr@4: __s._M_finish = __tmp_finish; williamr@4: } williamr@4: else { williamr@4: _STLP_STD::swap(_M_buffers._M_dynamic_buf, __s._M_buffers._M_dynamic_buf); williamr@4: _M_end_of_storage.swap(__s._M_end_of_storage); williamr@4: _STLP_STD::swap(_M_finish, __s._M_finish); williamr@4: } williamr@4: #else williamr@4: _STLP_STD::swap(_M_start, __s._M_start); williamr@4: _M_end_of_storage.swap(__s._M_end_of_storage); williamr@4: _STLP_STD::swap(_M_finish, __s._M_finish); williamr@4: #endif /* _STLP_USE_SHORT_STRING_OPTIM */ williamr@4: } williamr@4: williamr@4: void _STLP_FUNCTION_THROWS _M_throw_length_error() const; williamr@4: void _STLP_FUNCTION_THROWS _M_throw_out_of_range() const; williamr@4: }; williamr@4: williamr@4: #undef _STLP_SHORT_STRING_SZ williamr@4: williamr@4: #if defined (_STLP_USE_TEMPLATE_EXPORT) williamr@4: _STLP_EXPORT_TEMPLATE_CLASS _String_base >; williamr@4: # if defined (_STLP_HAS_WCHAR_T) williamr@4: _STLP_EXPORT_TEMPLATE_CLASS _String_base >; williamr@4: # endif williamr@4: #endif /* _STLP_USE_TEMPLATE_EXPORT */ williamr@4: williamr@4: _STLP_MOVE_TO_STD_NAMESPACE williamr@4: williamr@4: _STLP_END_NAMESPACE williamr@4: williamr@4: #endif /* _STLP_STRING_BASE_H */ williamr@4: williamr@4: /* williamr@4: * Local Variables: williamr@4: * mode:C++ williamr@4: * End: williamr@4: */