blob: 355e51b4fc567c5b7f07b70f357c0c1bfc5ea878 [file] [log] [blame]
// -*- C++ -*-
/***************************************************************************
*
* <string> - definition of the C++ Standard Library basic_string template
*
* $Id$
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 1994-2008 Rogue Wave Software, Inc.
*
**************************************************************************/
#ifndef _RWSTD_STRING_INCLUDED
#define _RWSTD_STRING_INCLUDED
#if __GNUG__ >= 3
# pragma GCC system_header
#endif // gcc >= 3
#include <rw/_iosfwd.h>
#include <rw/_iterator.h>
#include <rw/_error.h>
#include <rw/_select.h>
#include <rw/_strref.h>
#include <rw/_defs.h>
_RWSTD_NAMESPACE (std) {
#if defined _RWSTD_NO_EXTERN_MEMBER_TEMPLATE
# define _RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES
#endif // _RWSTD_NO_STRING_MEMBER_TEMPLATES
#ifdef _RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES
_EXPORT
template <class _CharT, class _Traits, class _Alloc,
class _StringIter, class _InputIter>
std::basic_string<_CharT, _Traits, _Alloc>&
__rw_replace (std::basic_string<_CharT, _Traits, _Alloc>&,
_StringIter, _StringIter, _InputIter, _InputIter);
_EXPORT
template <class _CharT, class _Traits, class _Alloc,
class _StringIter, class _InputIter>
std::basic_string<_CharT, _Traits, _Alloc>&
__rw_replace_aux (std::basic_string<_CharT, _Traits, _Alloc>&,
_StringIter, _StringIter, _InputIter, _InputIter);
#endif // _RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES
_EXPORT
template <class _CharT, class _Traits, class _Allocator>
class basic_string: private _Allocator
{
public:
typedef _Traits traits_type;
typedef typename traits_type::char_type value_type;
typedef _Allocator allocator_type;
typedef _RW::__string_ref<value_type, traits_type, allocator_type>
_C_string_ref_type;
typedef _RWSTD_ALLOC_TYPE(allocator_type, value_type)
_C_value_alloc_type;
typedef _RWSTD_REBIND(allocator_type, _C_string_ref_type)
_C_ref_alloc_type;
typedef typename allocator_type::size_type size_type;
typedef typename allocator_type::difference_type difference_type;
typedef typename allocator_type::reference reference;
typedef typename allocator_type::const_reference const_reference;
typedef typename allocator_type::pointer pointer;
typedef typename allocator_type::const_pointer const_pointer;
#ifndef _RWSTD_NO_DEBUG_ITER
typedef _RW::__rw_debug_iter <basic_string, pointer, pointer>
iterator;
typedef _RW::__rw_debug_iter <basic_string, const_pointer, pointer>
const_iterator;
iterator _C_make_iter (const pointer& __ptr) {
return iterator (*this, __ptr);
}
const_iterator _C_make_iter (const const_pointer& __ptr) const {
return const_iterator (*this, __ptr);
}
#else // if defined (_RWSTD_NO_DEBUG_ITER)
typedef pointer iterator;
typedef const_pointer const_iterator;
iterator _C_make_iter (pointer __ptr) {
return __ptr;
}
const_iterator _C_make_iter (const_pointer __ptr) const {
return __ptr;
}
#endif // _RWSTD_NO_DEBUG_ITER
#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC
typedef _STD::reverse_iterator<const_iterator> const_reverse_iterator;
typedef _STD::reverse_iterator<iterator> reverse_iterator;
#else // if defined (_RWSTD_NO_CLASS_PARTIAL_SPEC)
typedef _STD::reverse_iterator<const_iterator,
random_access_iterator_tag, value_type,
const_reference, const_pointer, difference_type>
const_reverse_iterator;
typedef _STD::reverse_iterator<iterator,
random_access_iterator_tag, value_type,
reference, pointer, difference_type>
reverse_iterator;
#endif // _RWSTD_NO_CLASS_PARTIAL_SPEC
#ifndef _RWSTD_NO_STRING_NPOS_TYPE
_RWSTD_STATIC_CONST (size_type, npos = size_type (_RWSTD_SIZE_MAX));
#else // if defined (_RWSTD_NO_STRING_NPOS_TYPE)
// working around an MSVC 7.0 bug (PR #26549)
// and an HP aCC extern template bug #333
_RWSTD_STATIC_CONST (_RWSTD_SIZE_T, npos = _RWSTD_SIZE_MAX);
#endif
// 21.3.1, p2
explicit basic_string (const allocator_type &__alloc = allocator_type ())
: allocator_type (__alloc), _C_data (_C_nullref ()->data ()) { }
// lwg issue #42
basic_string (const basic_string&);
// 21.3.1, p3
basic_string (const basic_string&, size_type, size_type = npos,
const allocator_type& = allocator_type ());
// 21.3.1, p6
basic_string (const_pointer, size_type,
const allocator_type& = allocator_type ());
// 21.3.1, p9
basic_string (const_pointer, const allocator_type& = allocator_type ());
// 21.3.1, p12
basic_string (size_type, value_type,
const allocator_type& = allocator_type ());
// 21.3.1, p15
template <class _InputIter>
basic_string (_InputIter __first, _InputIter __last,
const allocator_type &__alloc = allocator_type ())
: allocator_type (__alloc), _C_data (_C_nullref ()->data ()) {
replace (_C_make_iter (_C_data), _C_make_iter (_C_data),
__first, __last);
}
basic_string (const_pointer, const_pointer, const allocator_type&
_RWSTD_REDECLARED_DEFAULT (allocator_type ()));
~basic_string () {
_C_unlink (0);
}
// 21.3.1, p16
basic_string& operator= (const basic_string&);
// 21.3.1, p18
basic_string& operator= (const_pointer __s) {
return replace (size_type (), size (), __s, traits_type::length (__s));
}
// 21.3.1, p20
basic_string& operator= (value_type __c) {
return replace (size_type (), size (), &__c, size_type (1));
}
// disables reference counting
iterator begin ();
const_iterator begin () const {
return _C_make_iter (_C_data);
}
iterator end () {
// disable reference counting
return begin () + size ();
}
const_iterator end () const {
return _C_make_iter (_C_data + size ());
}
reverse_iterator rbegin () {
return reverse_iterator (end ());
}
const_reverse_iterator rbegin () const {
return const_reverse_iterator (end ());
}
reverse_iterator rend () {
return reverse_iterator (begin ());
}
const_reverse_iterator rend () const {
return const_reverse_iterator (begin ());
}
size_type size () const {
return _C_pref ()->size ();
}
size_type length () const {
return size ();
}
size_type max_size () const;
void resize (size_type, value_type);
void resize (size_type __n) {
resize (__n, value_type ());
}
size_type capacity () const {
return _C_pref ()->capacity ();
}
void reserve (size_type = 0);
void clear () {
if (size_type (1) < size_type (_C_pref ()->_C_get_ref ()))
_C_unlink (_C_nullref ()->data ());
else {
traits_type::assign (_C_data [0], value_type ());
_C_pref ()->_C_size._C_size = 0;
}
}
bool empty () const {
return size () == 0;
}
const_reference operator[] (size_type) const;
reference operator[] (size_type);
const_reference at (size_type) const;
reference at (size_type);
basic_string& operator+= (const basic_string &__s) {
return append (__s);
}
basic_string& operator+= (const_pointer __s) {
return append (__s);
}
basic_string& operator+= (value_type __c) {
return push_back (__c), *this;
}
basic_string& append (const basic_string&, size_type, size_type);
basic_string& append (const basic_string &__str) {
return append (__str.data (), __str.size ());
}
basic_string& append (const_pointer, size_type);
basic_string& append (const_pointer __s) {
return append (__s, traits_type::length (__s));
}
template<class _InputIter>
basic_string& append (_InputIter __first, _InputIter __last) {
// resolves to append (size_type, value_type) if _InputIter
// is any integral type (even not an exact match, such as char)
// the cast to int is necessary to prevent an exact match
return append (__first, __last, _RWSTD_DISPATCH (_InputIter));
}
template<class _InputIter>
basic_string& append (_InputIter __first, _InputIter __last, void*) {
return replace (_C_make_iter (_C_data + size ()),
_C_make_iter (_C_data + size ()),
__first, __last), *this;
}
basic_string& append (size_type __n, value_type __c, int) {
// unnamed arg is used for overload resolution
return append (__n, __c);
}
basic_string& append (size_type, value_type);
// lwg issue 7
void push_back (value_type);
basic_string& assign (const basic_string &__str) {
return *this = __str;
}
basic_string& assign (const basic_string&, size_type, size_type);
basic_string& assign (const_pointer __s, size_type __n) {
return replace (size_type (), size (), __s, __n);
}
basic_string& assign (const_pointer __s) {
return replace (size_type (), size (), __s, traits_type::length (__s));
}
template<class _InputIter>
basic_string& assign (_InputIter __first, _InputIter __last) {
// resolves to assign (size_type, value_type) if _InputIter
// is any integral type (even not an exact match, such as char)
// the cast to int is necessary to prevent an exact match
return assign (__first, __last, _RWSTD_DISPATCH (_InputIter));
}
template<class _InputIter>
basic_string& assign (_InputIter __first, _InputIter __last, void*) {
// unnamed arg is used for overload resolution
// _RWSTD_COMPILE_ASSERT (sizeof (*__first));
return replace (_C_make_iter (_C_data),
_C_make_iter (_C_data + size ()), __first, __last);
}
basic_string& assign (size_type __n, value_type __c, int) {
// unnamed arg is used for overload resolution
return replace (size_type (), size (), __n, __c);
}
basic_string& assign (size_type __n, value_type __c) {
return replace (size_type (), size (), __n, __c);
}
basic_string& insert (size_type, const basic_string&);
basic_string& insert (size_type, const basic_string&,
size_type, size_type);
basic_string& insert (size_type __pos, const_pointer __s, size_type __n) {
replace (__pos, size_type (), __s, __n);
return *this;
}
basic_string& insert (size_type __pos, const_pointer __s) {
return insert (__pos, __s, traits_type::length (__s));
}
// 21.3.5.4, p10
iterator insert (iterator __pos, value_type __c) {
const size_type __inx = _C_off (__pos);
return insert (__inx, &__c, 1), begin () + __inx;
}
template<class _InputIter>
void insert (iterator __p, _InputIter __first, _InputIter __last) {
insert (__p, __first, __last, _RWSTD_DISPATCH (_InputIter));
}
template <class _InputIter>
void insert (iterator __p, _InputIter __first, _InputIter __last, void*) {
// unnamed arg is used for overload resolution
// _RWSTD_COMPILE_ASSERT (sizeof (*__first));
replace (__p, __p, __first, __last);
}
void insert (iterator __p, size_type __n, value_type __c, int) {
// unnamed arg is used for overload resolution
replace (_C_off (__p), size_type (), __n, __c);
}
void insert (iterator __p,
const_pointer __first, const_pointer __last, void*) {
if (__first >= _C_data && __first <= _C_data + size ())
insert (_C_off (__p), basic_string (__first, __last));
else
replace (__p, __p, __first, __last);
}
# ifndef _RWSTD_NO_DEBUG_ITER
void insert (iterator __p,
const_iterator __first, const_iterator __last, void*) {
// unnamed arg is used for overload resolution
if (!(__first == __last)) {
const const_pointer __pf = &*__first;
insert (__p, __pf, __pf + _C_off (__first, __last));
}
}
void insert (iterator __p, iterator __first, iterator __last, void*) {
// unnamed arg is used for overload resolution
insert (__p, const_iterator (__first), const_iterator (__last),
(void*)0);
}
# endif // _RWSTD_NO_DEBUG_ITER
void insert (iterator __it, size_type __n, value_type __c) {
replace (_C_off (__it), size_type (), __n, __c);
}
basic_string& insert (size_type __pos, size_type __n, value_type __c) {
return replace (__pos, size_type (), __n, __c);
}
basic_string& erase (size_type = 0, size_type = npos);
iterator erase (iterator __it) {
_RWSTD_ASSERT (__it != end ()); // verify precondition (Table 67)
return erase (__it, __it + 1);
}
iterator erase (iterator __first, iterator __last) {
const size_type __pos = _C_off (__first);
replace (__pos, _C_off (__first, __last), const_pointer(), size_type());
return _C_make_iter (_C_data + __pos);
}
private:
static size_type _C_min (size_type __x, size_type __y) {
return __x < __y ? __x : __y;
}
iterator __replace_aux (size_type __pos1, size_type __n1,
const basic_string &__str,
size_type __pos2 = 0,
size_type __n2 = npos) {
replace (__pos1, __n1, __str.c_str() + __pos2, __n2);
return _C_make_iter (_C_data + __pos1);
}
public:
#ifndef _RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES
template <class _InputIter>
basic_string& __replace_aux (iterator, iterator, _InputIter, _InputIter);
#else
template <class _InputIter>
basic_string& __replace_aux (iterator __first1, iterator __last1,
_InputIter __first2, _InputIter __last2) {
return __rw_replace_aux (*this, __first1, __last1, __first2, __last2);
}
#endif // _RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES
size_type _C_grow (size_type, size_type) const;
public:
// 21.3.5.6, p1
basic_string&
replace (size_type __pos, size_type __n, const basic_string &__s) {
return replace (__pos, __n, __s, size_type (), __s.size ());
}
// 21.3.5.6, p2
basic_string&
replace (size_type, size_type, const basic_string&, size_type, size_type);
// 21.3.5.6, p7
basic_string&
replace (size_type, size_type, const_pointer, size_type);
// 21.3.5.6, p8
basic_string&
replace (size_type __pos, size_type __n, const_pointer __s) {
return replace (__pos, __n, __s, traits_type::length (__s));
}
// 21.3.5.6, p10
basic_string&
replace (size_type, size_type, size_type, value_type);
// 21.3.5.6, p11
basic_string&
replace (iterator __first, iterator __last, const basic_string &__str) {
return replace (_C_off (__first), _C_off (__first, __last), __str);
}
// 21.3.5.6, p15
basic_string&
replace (iterator __first, iterator __last,
const_pointer __s, size_type __n) {
replace (_C_off (__first), _C_off (__first, __last), __s, __n);
return *this;
}
// 21.3.5.6, p17
basic_string&
replace (iterator __first, iterator __last, const_pointer __s) {
return replace (__first, __last, __s, traits_type::length (__s));
}
// 21.3.5.6, p19
basic_string&
replace (iterator __first, iterator __last, size_type __n, value_type __c) {
return replace (_C_off (__first), _C_off (__first, __last), __n, __c);
}
#ifndef _RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES
template<class _InputIter>
basic_string&
replace (iterator __first1, iterator __last1,
_InputIter __first2, _InputIter __last2, void*);
#else // if defined (_RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES)
template<class _InputIter>
basic_string&
replace (iterator __first1, iterator __last1,
_InputIter __first2, _InputIter __last2, void*) {
return __rw_replace (*this, __first1, __last1, __first2, __last2);
}
#endif // _RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES
basic_string&
replace (iterator __first, iterator __last,
size_type __n, value_type __c, int) {
return replace (_C_off (__first), _C_off (__first, __last), __n, __c);
}
// 21.3.5.6, p21
template<class _InputIter>
basic_string&
replace (iterator __first1, iterator __last1,
_InputIter __first2, _InputIter __last2) {
return replace (__first1, __last1, __first2, __last2,
_RWSTD_DISPATCH (_InputIter));
}
// 21.3.5.7, p1
size_type copy (pointer, size_type, size_type = 0) const;
#ifndef _RWSTD_NO_EXT_DEEP_STRING_COPY
basic_string copy () const {
return basic_string (data (), size ());
}
#endif //_RWSTD_NO_EXT_DEEP_STRING_COPY
void swap (basic_string &__s) {
if (get_allocator () == __s.get_allocator ()) {
pointer __temp = _C_data;
_C_data = __s._C_data;
__s._C_data = __temp;
}
else {
basic_string __tmp = *this;
*this = __s;
__s = __tmp;
}
}
//
// string operations
//
const_pointer c_str () const {
return _C_data;
}
const_pointer data () const {
return _C_data;
}
allocator_type get_allocator() const {
return *this;
}
// 21.3.6.1, p1
size_type find (const basic_string &__str, size_type __pos = 0) const {
return find (__str.c_str (), __pos, __str.size ());
}
// 21.3.6.1, p4
size_type find (const_pointer, size_type, size_type) const;
// 21.3.6.1, p5
size_type find (const_pointer __s, size_type __pos = 0) const {
return find (__s, __pos, traits_type::length (__s));
}
// 21.3.6.1, p7
size_type find (value_type, size_type = 0) const;
// 21.3.6.2, p1
size_type rfind (const basic_string &__str, size_type __pos = npos) const {
return rfind (__str.c_str (), __pos, __str.size ());
}
// 21.3.6.2, p4
size_type rfind (const_pointer, size_type, size_type) const;
// 21.3.6.2, p5
size_type rfind (const_pointer __s, size_type __pos = npos) const {
return rfind (__s, __pos, traits_type::length (__s));
}
// 21.3.6.2, p7
size_type rfind (value_type __c, size_type __pos = npos) const {
return rfind (&__c, __pos, 1);
}
// 21.3.6.3, p1
size_type find_first_of (const basic_string &__str,
size_type __pos = 0) const {
return find_first_of (__str.c_str (), __pos, __str.size ());
}
// 21.3.6.3, p4
size_type find_first_of (const_pointer, size_type, size_type) const;
// 21.3.6.3, p5
size_type find_first_of (const_pointer __s, size_type __pos = 0) const {
return find_first_of (__s, __pos, traits_type::length (__s));
}
// 21.3.6.3, p6
size_type find_first_of (value_type __c, size_type __pos = 0) const {
return find (__c, __pos);
}
// 21.3.6.4, p1
size_type find_last_of (const basic_string &__str,
size_type __pos = npos) const {
return find_last_of (__str.c_str (), __pos, __str.size ());
}
// 21.3.6.4, p4
size_type find_last_of (const_pointer, size_type, size_type) const;
// 21.3.6.4, p5
size_type find_last_of (const_pointer __s, size_type __pos = npos) const {
return find_last_of (__s, __pos, traits_type::length (__s));
}
// 21.3.6.4, p7
size_type find_last_of (value_type __c, size_type __pos = npos) const {
return rfind (__c, __pos);
}
// 21.3.6.5, p1
size_type find_first_not_of (const basic_string &__str,
size_type __pos = 0) const {
return find_first_not_of (__str.c_str (), __pos, __str.size ());
}
// 21.3.6.5, p4
size_type find_first_not_of (const_pointer, size_type, size_type) const;
// 21.3.6.5, p5
size_type find_first_not_of (const_pointer __s,
size_type __pos = 0) const {
return find_first_not_of (__s, __pos, traits_type::length(__s));
}
// 21.3.6.5, p7
size_type find_first_not_of (value_type __c, size_type __pos = 0) const {
return find_first_not_of (&__c, __pos, size_type (1));
}
// 21.3.6.6, p1
size_type find_last_not_of (const basic_string &__str,
size_type __pos = npos) const {
return find_last_not_of (__str.c_str (), __pos, __str.size ());
}
// 21.3.6.6, p4
size_type find_last_not_of (const_pointer, size_type, size_type) const;
// 21.3.6.6, p6
size_type find_last_not_of (const_pointer __s,
size_type __pos = npos) const {
return find_last_not_of (__s, __pos, traits_type::length (__s));
}
// 21.3.6.6, p7
size_type find_last_not_of (value_type __c, size_type __pos = npos) const {
return find_last_not_of (&__c, __pos, size_type (1));
}
// 21.3.6.7
basic_string substr (size_type = 0, size_type = npos) const;
// 21.3.6.8, p1
int compare (const basic_string &__str) const;
// 21.3.6.8, p3
int compare (size_type __pos, size_type __n,
const basic_string &__str) const {
return compare (__pos, __n, __str.c_str(), __str.size());
}
// 21.3.6.8, p4
int compare (size_type, size_type, const basic_string&,
size_type, size_type) const;
// 21.3.6.8, p5
int compare (const_pointer __s) const {
return compare (size_type (), size (), __s, traits_type::length(__s));
}
// 21.3.6.8, p6, see also lwg Issue 5
int compare (size_type __pos, size_type __n, const_pointer __s) const {
return compare(__pos, __n, __s, traits_type::length (__s));
}
// lwg Issue 5
int compare (size_type, size_type, const_pointer, size_type) const;
#if defined (_RWSTD_NO_PART_SPEC_OVERLOAD)
friend void swap (basic_string& __lhs, basic_string& __rhs) {
__lhs.swap (__rhs);
}
#endif
#ifndef _RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES
private:
#else // if defined (_RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATSE)
public:
#endif // _RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES
static size_type
_C_off (const_iterator __first, const_iterator __last) {
_RWSTD_ASSERT_RANGE (__first, __last);
return size_type (__last - __first);
}
size_type
_C_off (const_iterator __it) const {
_RWSTD_ASSERT_RANGE (__it, _C_make_iter (_C_data));
return _C_off (_C_make_iter (_C_data), __it);
}
void _C_clone (size_type);
_C_string_ref_type* _C_pref () const {
// use two static_casts in favor of reinterpret_cast
// to prevent "increased alignment" warnings
return _RWSTD_STATIC_CAST (_C_string_ref_type*,
_RWSTD_STATIC_CAST (void*, _C_data)) - 1;
}
void _C_unlink (pointer);
friend struct _RW::__string_ref<value_type, traits_type, allocator_type>;
#ifndef _RWSTD_NO_COLLAPSE_TEMPLATE_STATICS
static _RW::__null_ref<_CharT, _Traits, _Allocator> _C_null_ref;
static _RW::__null_ref<_CharT, _Traits, _Allocator>* _C_nullref () {
return &_C_null_ref;
}
#else // if defined (_RWSTD_NO_COLLAPSE_TEMPLATE_STATICS)
static _RW::__null_ref<_CharT, _Traits, _Allocator>* _C_nullref () {
typedef _RW::__null_ref<_CharT, _Traits, _Allocator> _NullRef;
return _RWSTD_REINTERPRET_CAST (_NullRef*, _RW::__nullref);
}
#endif // _RWSTD_NO_COLLAPSE_TEMPLATE_STATICS
_C_string_ref_type * _C_get_rep (size_type, size_type);
pointer _C_data;
};
typedef basic_string<char, char_traits<char>, allocator<char> > string;
#ifndef _RWSTD_NO_WCHAR_T
typedef basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> >
wstring;
#endif // _RWSTD_NO_WCHAR_T
template <class _CharT, class _Traits , class _Allocator>
#if !defined (__GNUG__) \
|| __GNUG__ > 3 || __GNUC_MINOR__ > 3 \
|| !defined (__ia64__)
// working around a gcc 3.2.3 inliner bug on IA64 (PR #29766)
inline
#endif // !gcc || gcc > 3.3 || !IA64
void basic_string<_CharT, _Traits, _Allocator>::
_C_unlink (pointer __ptr)
{
_RWSTD_ASSERT (0 != _C_data);
if (0 >= _C_pref ()->_C_dec_ref ()) {
// positive result of the decrement means the string body
// is shared by two or more basic_string objects (handles)
// result of 0 means that this object (handle) is the only
// owner of the string body
// negative result means that this object is the only owner
// of the string body which has reference counting disabled
// must pass same size to deallocate as allocate (see string.cc)
// note that we cannot call capacity() after the destroy() call
const size_type __size =
capacity () + sizeof (_C_string_ref_type) / sizeof (value_type) + 2;
_C_pref ()->_C_destroy ();
_C_ref_alloc_type (*this).destroy (_C_pref ());
_RWSTD_VALUE_ALLOC (_C_value_alloc_type, *this,
deallocate (_RWSTD_REINTERPRET_CAST (pointer,
_C_pref ()),
__size));
}
_C_data = __ptr;
}
template <class _CharT, class _Traits, class _Alloc>
inline typename basic_string<_CharT, _Traits, _Alloc>::size_type
basic_string<_CharT, _Traits, _Alloc>::
_C_grow (size_type __from, size_type __to) const
{
const size_type __cap = _RWSTD_NEW_CAPACITY (basic_string, this, __from);
return __cap < __to ? __to : __cap;
}
template <class _CharT, class _Traits , class _Allocator>
inline basic_string<_CharT, _Traits, _Allocator>::
basic_string (const basic_string<_CharT, _Traits, _Allocator> &__s)
: allocator_type (__s.get_allocator ())
{
if (size_type (0) < size_type (__s._C_pref ()->_C_get_ref ())) {
_C_data = __s._C_data;
_C_pref ()->_C_inc_ref ();
}
else {
const size_type __n = __s.size ();
_C_data = _C_get_rep (__n, __n)->data ();
traits_type::copy (_C_data, __s.data (), __n);
}
_RWSTD_ASSERT (0 != _C_data);
}
template <class _CharT, class _Traits , class _Allocator>
inline typename basic_string<_CharT, _Traits, _Allocator>::iterator
basic_string<_CharT, _Traits, _Allocator>::
begin ()
{
if (size_type (1) < size_type (_C_pref ()->_C_get_ref ()))
_C_clone (size ());
// not thread safe: there is exactly one body pointed to by
// this->_C_pref() at this point and the caller is responsible
// for synchronizing accesses to the same object from multiple
// threads
_C_pref ()->_C_unref ();
return _C_make_iter (_C_data);
}
template <class _CharT, class _Traits , class _Allocator>
inline typename basic_string<_CharT, _Traits, _Allocator>::size_type
basic_string<_CharT, _Traits, _Allocator>::
max_size () const
{
const size_type __max_chars = allocator_type::max_size ();
const size_type __ref_size =
1U + sizeof (_C_string_ref_type) / sizeof (_CharT);
return __max_chars < __ref_size ? 0 : __max_chars - __ref_size;
}
template <class _CharT, class _Traits , class _Allocator>
inline basic_string<_CharT, _Traits, _Allocator>&
basic_string<_CharT, _Traits, _Allocator>::
erase (size_type __pos, size_type __n)
{
_RWSTD_REQUIRES (__pos <= size (),
(_RWSTD_ERROR_OUT_OF_RANGE,
_RWSTD_FUNC ("basic_string::erase(size_type, size_type)"),
__pos, size ()));
const value_type __tmp = value_type () ;
size_type __len = size () - __pos;
return replace (__pos, __n < __len ? __n : __len, &__tmp, size_type ());
}
template <class _CharT, class _Traits , class _Allocator>
inline typename basic_string<_CharT, _Traits, _Allocator>::const_reference
basic_string<_CharT, _Traits, _Allocator>::
operator[] (size_type __pos) const
{
#ifdef _RWSTD_BOUNDS_CHECKING
_RWSTD_REQUIRES (__pos <= size (),
(_RWSTD_ERROR_OUT_OF_RANGE,
_RWSTD_FUNC ("basic_string::operator[](size_type) const"),
__pos, size ()));
#endif // _RWSTD_BOUNDS_CHECKING
// reference counting still enabled
return _C_data [__pos];
}
template <class _CharT, class _Traits , class _Allocator>
inline typename basic_string<_CharT, _Traits, _Allocator>::reference
basic_string<_CharT, _Traits, _Allocator>::
operator[] (size_type __pos)
{
#ifdef _RWSTD_BOUNDS_CHECKING
// 21.3.4, p1 - behavior is undefined if __pos == size ()
_RWSTD_REQUIRES (__pos < size (),
(_RWSTD_ERROR_OUT_OF_RANGE,
_RWSTD_FUNC ("basic_string::operator[](size_type)"),
__pos, size ()));
#endif // _RWSTD_BOUNDS_CHECKING
// prevent reference counting
return begin ()[__pos];
}
template <class _CharT, class _Traits , class _Allocator>
inline typename basic_string<_CharT, _Traits, _Allocator>::const_reference
basic_string<_CharT, _Traits, _Allocator>::
at (size_type __pos) const
{
_RWSTD_REQUIRES (__pos < size (),
(_RWSTD_ERROR_OUT_OF_RANGE,
_RWSTD_FUNC ("basic_string::at (size_type) const"),
__pos, size ()));
// reference counting still enabled
return _C_data [__pos];
}
template <class _CharT, class _Traits , class _Allocator>
inline typename basic_string<_CharT, _Traits, _Allocator>::reference
basic_string<_CharT, _Traits, _Allocator>::
at (size_type __pos)
{
_RWSTD_REQUIRES (__pos < size (),
(_RWSTD_ERROR_OUT_OF_RANGE,
_RWSTD_FUNC ("basic_string::at (size_type)"),
__pos, size ()));
// prevent reference counting
return begin ()[__pos];
}
template <class _CharT, class _Traits , class _Allocator>
inline void
basic_string<_CharT, _Traits, _Allocator>::
resize (size_type __n, value_type __c)
{
_RWSTD_REQUIRES (__n <= max_size (),
(_RWSTD_ERROR_LENGTH_ERROR,
_RWSTD_FUNC ("basic_string::resize(size_type, "
"value_type)"), __n, max_size ()));
if (__n < size())
erase (__n, size () - __n);
else
replace (size (), size_type (), __n - size (), __c);
}
template <class _CharT, class _Traits , class _Allocator>
inline void
basic_string<_CharT, _Traits, _Allocator>::
push_back (value_type __c)
{
const size_type __size0 = size ();
const _RWSTD_SIZE_T __size1 = __size0 + 1;
if ( capacity () < __size1
|| size_type (1) < size_type (_C_pref ()->_C_get_ref ())) {
replace (size (), size_type (), 1, __c);
}
else {
traits_type::assign (_C_data [__size0], __c);
traits_type::assign (_C_data [__size1], value_type ());
_C_pref ()->_C_size._C_size = __size1;
}
}
template <class _CharT, class _Traits , class _Allocator>
inline void basic_string<_CharT, _Traits, _Allocator>::
reserve (size_type __cap)
{
_RWSTD_REQUIRES (__cap <= max_size (),
(_RWSTD_ERROR_LENGTH_ERROR,
_RWSTD_FUNC ("basic_string::reserve(size_type)"),
__cap, max_size ()));
if (__cap > capacity ())
_C_clone (__cap);
}
template <class _CharT, class _Traits , class _Allocator>
inline basic_string<_CharT, _Traits, _Allocator>&
basic_string<_CharT, _Traits, _Allocator>::
replace (size_type __pos1, size_type __n1, const basic_string &__str,
size_type __pos2, size_type __n2)
{
_RWSTD_REQUIRES (__pos1 <= size (),
(_RWSTD_ERROR_OUT_OF_RANGE,
_RWSTD_FUNC ("basic_string::replace(size_type, "
"size_type, const basic_string&, "
"size_type, size_type)"),
__pos1, size ()));
_RWSTD_REQUIRES (__pos2 <= __str.size (),
(_RWSTD_ERROR_OUT_OF_RANGE,
_RWSTD_FUNC ("basic_string::replace(size_type, "
"size_type, const basic_string&, "
"size_type, size_type)"),
__pos2, __str.size ()));
const size_type __rem = __str.size () - __pos2;
replace (__pos1, __n1, __str.data () + __pos2, __n2 < __rem ? __n2 : __rem);
return *this;
}
template <class _CharT, class _Traits , class _Allocator>
inline typename basic_string<_CharT, _Traits, _Allocator>::size_type
basic_string<_CharT, _Traits, _Allocator>::
find (value_type __c, size_type __pos) const
{
if (__pos > size ())
return npos;
const const_pointer __where =
traits_type::find (_C_data + __pos, size () - __pos, __c);
return __where ? __where - _C_data : npos;
}
template <class _CharT, class _Traits, class _Allocator>
inline void
basic_string<_CharT, _Traits, _Allocator>::
_C_clone (size_type __cap)
{
const size_type __size = size ();
_C_string_ref_type* const __temp =
_C_get_rep (__cap, __size > __cap ? __cap : __size);
traits_type::copy (__temp->data (), _C_data, __size);
_C_unlink (__temp->data ());
}
template <class _CharT, class _Traits, class _Allocator>
inline int
basic_string<_CharT, _Traits, _Allocator>::
compare (const basic_string &__str) const
{
const size_type __n1 = size ();
const size_type __n2 = __str.size ();
const bool __first = __n1 < __n2;
const int __res =
traits_type::compare (data (), __str.data (), __first ? __n1 : __n2);
return __res ? __res : __first ? -1 : int (__n1 != __n2);
}
template <class _CharT, class _Traits, class _Allocator>
inline basic_string<_CharT, _Traits, _Allocator>&
basic_string<_CharT, _Traits, _Allocator>::
append (const basic_string &__str, size_type __pos, size_type __n)
{
_RWSTD_REQUIRES (__pos <= __str.size (),
(_RWSTD_ERROR_OUT_OF_RANGE,
_RWSTD_FUNC ("basic_string::append(const basic_string&,"
" size_type, size_type)"),
__pos, __str.size ()));
const size_type __rlen = _C_min (__str.size() - __pos, __n);
return append (__str.data () + __pos, __rlen);
}
template <class _CharT, class _Traits, class _Allocator>
inline basic_string<_CharT, _Traits, _Allocator>&
basic_string<_CharT, _Traits, _Allocator>::
append (const_pointer __s, size_type __n)
{
const size_type __size0 = size ();
const _RWSTD_SIZE_T __size1 = __size0 + __n;
if ( capacity () <= __size1
|| size_type (1) < size_type (_C_pref ()->_C_get_ref ()))
return replace (size (), size_type (), __s, __n);
traits_type::copy (_C_data + __size0, __s, __n);
traits_type::assign (_C_data [__size1], value_type ());
_C_pref ()->_C_size._C_size = __size1;
return *this;
}
template <class _CharT, class _Traits, class _Allocator>
inline basic_string<_CharT, _Traits, _Allocator>&
basic_string<_CharT, _Traits, _Allocator>::
append (size_type __n, value_type __c)
{
const size_type __size0 = size ();
const _RWSTD_SIZE_T __size1 = __size0 + __n;
if ( capacity () < __size1
|| size_type (1) < size_type (_C_pref ()->_C_get_ref ()))
return replace (size (), size_type (), __n, __c);
traits_type::assign (_C_data + __size0, __n, __c);
traits_type::assign (_C_data [__size1], value_type ());
_C_pref ()->_C_size._C_size = __size1;
return *this;
}
// 21.3.7.1, p1
template <class _CharT, class _Traits , class _Allocator>
inline basic_string<_CharT, _Traits, _Allocator>
operator+ (const basic_string<_CharT, _Traits, _Allocator> &__lhs,
const basic_string<_CharT, _Traits, _Allocator> &__rhs)
{
typedef basic_string<_CharT, _Traits, _Allocator> string_type;
// prevent reference counting while creating a copy of lhs
return string_type (__lhs.data (), __lhs.size ()) += __rhs;
}
// 21.3.7.1, p2
template <class _CharT, class _Traits , class _Allocator>
inline basic_string<_CharT, _Traits, _Allocator>
operator+ (const _CharT* __lhs,
const basic_string<_CharT, _Traits, _Allocator>& __rhs)
{
return basic_string<_CharT, _Traits, _Allocator>(__lhs) += __rhs;
}
// 21.3.7.1, p4
template <class _CharT, class _Traits , class _Allocator>
inline basic_string<_CharT, _Traits, _Allocator>
operator+ (_CharT __lhs,
const basic_string<_CharT, _Traits, _Allocator>& __rhs)
{
return basic_string<_CharT, _Traits, _Allocator>(1, __lhs) += __rhs;
}
// 21.3.7.1, p5
template <class _CharT, class _Traits , class _Allocator>
inline basic_string<_CharT, _Traits, _Allocator>
operator+ (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
const _CharT* __rhs)
{
typedef basic_string<_CharT, _Traits, _Allocator> string_type;
// prevent reference counting while creating a copy of lhs
return string_type (__lhs.data (), __lhs.size ()) += __rhs;
}
// 21.3.7.1, p7
template <class _CharT, class _Traits , class _Allocator>
inline basic_string<_CharT, _Traits, _Allocator>
operator+ (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
_CharT __rhs)
{
typedef basic_string<_CharT, _Traits, _Allocator> string_type;
// prevent reference counting while creating a copy of lhs
return string_type (__lhs.data (), __lhs.size ()) += __rhs;
}
// 21.3.7.2, p1
template <class _CharT, class _Traits , class _Allocator>
inline bool
operator== (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
const basic_string<_CharT, _Traits, _Allocator>& __rhs)
{
// avoid using basic_string<>::compare() for efficiency
return __lhs.size () == __rhs.size ()
&& !_Traits::compare (__lhs.data (), __rhs.data (), __lhs.size ());
}
// 21.3.7.2, p2
template <class _CharT, class _Traits , class _Allocator>
inline bool
operator== (const _CharT* __lhs,
const basic_string<_CharT, _Traits, _Allocator>& __rhs)
{
const typename basic_string<_CharT, _Traits, _Allocator>::size_type
__n = _Traits::length (__lhs);
// avoid using basic_string<>::compare() for efficiency
return __rhs.size () == __n
&& !_Traits::compare (__lhs, __rhs.data (), __n);
}
// 21.3.7.2, p3
template <class _CharT, class _Traits , class _Allocator>
inline bool
operator== (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
const _CharT* __rhs)
{
return __rhs == __lhs;
}
// 21.3.7.4, p1
template <class _CharT, class _Traits , class _Allocator>
inline bool
operator< (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
const basic_string<_CharT, _Traits, _Allocator>& __rhs)
{
return 0 > __lhs.compare (__rhs);
}
// 21.3.7.4, p2
template <class _CharT, class _Traits , class _Allocator>
inline bool
operator< (const _CharT* __lhs,
const basic_string<_CharT, _Traits, _Allocator>& __rhs)
{
return 0 < __rhs.compare (__lhs);
}
// 21.3.7.4, p3
template <class _CharT, class _Traits , class _Allocator>
inline bool
operator< (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
const _CharT* __rhs)
{
return 0 > __lhs.compare (__rhs);
}
// 21.3.7.3, p1
template <class _CharT, class _Traits , class _Allocator>
inline bool
operator!= (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
const basic_string<_CharT, _Traits, _Allocator>& __rhs)
{
return !(__lhs == __rhs);
}
// 21.3.7.5, p1
template <class _CharT, class _Traits , class _Allocator>
inline bool
operator> (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
const basic_string<_CharT, _Traits, _Allocator>& __rhs)
{
return __rhs < __lhs;
}
// 21.3.7.6, p1
template <class _CharT, class _Traits , class _Allocator>
inline bool
operator<= (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
const basic_string<_CharT, _Traits, _Allocator>& __rhs)
{
return !(__rhs < __lhs);
}
// 21.3.7.7, p1
template <class _CharT, class _Traits , class _Allocator>
inline bool
operator>= (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
const basic_string<_CharT, _Traits, _Allocator>& __rhs)
{
return !(__lhs < __rhs);
}
// 21.3.7.8, p1
#ifndef _RWSTD_NO_PART_SPEC_OVERLOAD
template <class _CharT, class _Traits, class _Allocator>
inline void swap (basic_string<_CharT, _Traits, _Allocator>& __a,
basic_string<_CharT, _Traits, _Allocator>& __b)
{
__a.swap (__b);
}
#endif // _RWSTD_NO_PART_SPEC_OVERLOAD
// 21.3.7.3, p2
template <class _CharT, class _Traits , class _Allocator>
inline bool
operator!= (const _CharT* __lhs,
const basic_string<_CharT, _Traits, _Allocator>& __rhs)
{
return !(__lhs == __rhs);
}
// 21.3.7.3, p3
template <class _CharT, class _Traits , class _Allocator>
inline bool
operator!= (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
const _CharT* __rhs)
{
return !(__lhs == __rhs);
}
// 21.3.7.5, p2
template <class _CharT, class _Traits , class _Allocator>
inline bool
operator> (const _CharT* __lhs,
const basic_string<_CharT, _Traits, _Allocator>& __rhs)
{
return __rhs < __lhs;
}
// 21.3.7.5, p3
template <class _CharT, class _Traits , class _Allocator>
inline bool
operator> (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
const _CharT* __rhs)
{
return __rhs < __lhs;
}
// 21.3.7.6, p2
template <class _CharT, class _Traits , class _Allocator>
inline bool
operator<= (const _CharT* __lhs,
const basic_string<_CharT, _Traits, _Allocator>& __rhs)
{
return !(__rhs < __lhs);
}
// 21.3.7.6, p3
template <class _CharT, class _Traits , class _Allocator>
inline bool
operator<= (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
const _CharT* __rhs)
{
return !(__rhs < __lhs);
}
// 21.3.7.7, p2
template <class _CharT, class _Traits , class _Allocator>
inline bool
operator>= (const _CharT* __lhs,
const basic_string<_CharT, _Traits, _Allocator>& __rhs)
{
return !(__lhs < __rhs);
}
// 21.3.7.7, p3
template <class _CharT, class _Traits , class _Allocator>
inline bool
operator>= (const basic_string<_CharT, _Traits, _Allocator>& __lhs,
const _CharT* __rhs)
{
return !(__lhs < __rhs);
}
} // namespace std
#ifndef _RWSTD_RW_STRINGIO_H_INCLUDED
# include <rw/_stringio.h>
#endif // _RWSTD_RW_STRINGIO_H_INCLUDED
_RWSTD_NAMESPACE (__rw) {
#ifndef _RWSTD_NO_FUNC_PARTIAL_SPEC
# ifndef _RWSTD_NO_NONDEDUCED_CONTEXT
# define _RWSTD_STRING_SIZE_TYPE \
typename _STD::basic_string<_CharT, _Traits, _Allocator>::size_type
# else
# define _RWSTD_STRING_SIZE_TYPE _RWSTD_SIZE_T
# endif // _RWSTD_NO_NONDEDUCED_CONTEXT
// more specialized version for basic_string<>; may be further specialized
// in user code for example on a user-defined allocator
template <class _CharT, class _Traits, class _Allocator>
inline _RWSTD_STRING_SIZE_TYPE
__rw_new_capacity (_RWSTD_STRING_SIZE_TYPE __size,
const _STD::basic_string<_CharT, _Traits, _Allocator>*)
{
typedef _RWSTD_STRING_SIZE_TYPE _RWSizeT;
const _RWSizeT __ratio = _RWSizeT ( (_RWSTD_STRING_CAPACITY_RATIO << 10)
/ _RWSTD_RATIO_DIVIDER);
const _RWSizeT __cap = (__size >> 10) * __ratio
+ (((__size & 0x3ff) * __ratio) >> 10);
return (__size += _RWSTD_MINIMUM_STRING_CAPACITY) > __cap ? __size : __cap;
}
#else // if defined (_RWSTD_NO_FUNC_PARTIAL_SPEC)
# ifndef _RWSTD_NO_NONDEDUCED_CONTEXT
# define _RWSTD_STRING_SIZE_TYPE(type) type::size_type
# else
# define _RWSTD_STRING_SIZE_TYPE(ignore) _RWSTD_SIZE_T
# endif // _RWSTD_NO_NONDEDUCED_CONTEXT
// the following specializations of the __rw_new_capacity<> function template
// are provided for char and wchar_t; the general case is given in <memory>
_RWSTD_SPECIALIZED_FUNCTION
inline _RWSTD_STRING_SIZE_TYPE (_STD::string)
__rw_new_capacity (_RWSTD_STRING_SIZE_TYPE (_STD::string) __size,
const _STD::string*)
{
typedef _RWSTD_STRING_SIZE_TYPE (_STD::string) _RWSizeT;
const _RWSizeT __ratio = _RWSizeT ( (_RWSTD_STRING_CAPACITY_RATIO << 10)
/ _RWSTD_RATIO_DIVIDER);
const _RWSizeT __cap = (__size >> 10) * __ratio
+ (((__size & 0x3ff) * __ratio) >> 10);
return (__size += _RWSTD_MINIMUM_STRING_CAPACITY) > __cap ? __size : __cap;
}
_RWSTD_SPECIALIZED_FUNCTION
inline _RWSTD_STRING_SIZE_TYPE (_STD::wstring)
__rw_new_capacity (_RWSTD_STRING_SIZE_TYPE (_STD::wstring) __size,
const _STD::wstring*)
{
typedef _RWSTD_STRING_SIZE_TYPE (_STD::wstring) _RWSizeT;
const _RWSizeT __ratio = _RWSizeT ( (_RWSTD_STRING_CAPACITY_RATIO << 10)
/ _RWSTD_RATIO_DIVIDER);
const _RWSizeT __cap = (__size >> 10) * __ratio
+ (((__size & 0x3ff) * __ratio) >> 10);
return (__size += _RWSTD_MINIMUM_STRING_CAPACITY) > __cap ? __size : __cap;
}
#endif // _RWSTD_NO_FUNC_PARTIAL_SPEC
// clean up
#undef _RWSTD_STRING_SIZE_TYPE
} // namespace __rw
#if _RWSTD_DEFINE_TEMPLATE_FIRST (_BASIC_STRING)
# include <string.cc>
#endif // _RWSTD_DEFINE_TEMPLATE_FIRST (_BASIC_STRING)
#ifdef _RWSTD_MSVC
# pragma warning (push)
# pragma warning (disable: 4231)
#endif // _RWSTD_MSVC
_RWSTD_NAMESPACE (std) {
#if _RWSTD_INSTANTIATE (_BASIC_STRING, _CHAR)
_RWSTD_INSTANTIATE_3 (class _RWSTD_TI_EXPORT
basic_string<char, char_traits<char>,
allocator<char> >);
#endif // _RWSTD_INSTANTIATE (_BASIC_STRING, _CHAR)
#if _RWSTD_INSTANTIATE (_BASIC_STRING, _WCHAR_T)
_RWSTD_INSTANTIATE_3 (class _RWSTD_TI_EXPORT
basic_string<wchar_t, char_traits<wchar_t>,
allocator<wchar_t> >);
#endif // _RWSTD_INSTANTIATE (_BASIC_STRING, _WCHAR_T)
} // namespace std
#ifdef _RWSTD_MSVC
# pragma warning (pop)
#endif // _RWSTD_MSVC
#if _RWSTD_DEFINE_TEMPLATE_LAST (_BASIC_STRING)
# include <string.cc>
#endif // _RWSTD_DEFINE_TEMPLATE_LAST (_BASIC_STRING)
#endif // _RWSTD_STRING_INCLUDED