mirror of
https://github.com/reactos/reactos.git
synced 2024-09-21 02:01:15 +00:00
232 lines
8.4 KiB
C
232 lines
8.4 KiB
C
|
/*
|
||
|
* 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:
|
||
|
*/
|