// -*- C++ -*- /*************************************************************************** * * - definition of the C++ Standard Library basic_string template * * $Id: string 172106 2011-11-02 17:04:12Z statham $ * *************************************************************************** * * Copyright (c) 1994-2001 Rogue Wave Software, Inc. All Rights Reserved. * * This computer software is owned by Rogue Wave Software, Inc. and is * protected by U.S. copyright laws and other laws and by international * treaties. This computer software is furnished by Rogue Wave Software, * Inc. pursuant to a written license agreement and may be used, copied, * transmitted, and stored only in accordance with the terms of such * license and with the inclusion of the above copyright notice. This * computer software or any other copies thereof may not be provided or * otherwise made available to any other person. * * U.S. Government Restricted Rights. This computer software is provided * with Restricted Rights. Use, duplication, or disclosure by the * Government is subject to restrictions as set forth in subparagraph (c) * (1) (ii) of The Rights in Technical Data and Computer Software clause * at DFARS 252.227-7013 or subparagraphs (c) (1) and (2) of the * Commercial Computer Software--Restricted Rights at 48 CFR 52.227-19, * as applicable. Manufacturer is Rogue Wave Software, Inc., 5500 * Flatiron Parkway, Boulder, Colorado 80301 USA. * **************************************************************************/ #ifndef _RWSTD_STRING_INCLUDED #define _RWSTD_STRING_INCLUDED #include #include #include #include #include #include #include _RWSTD_NAMESPACE_BEGIN (std) template class basic_string: private _Allocator { public: typedef _Traits traits_type; typedef _TYPENAME traits_type::char_type value_type; typedef _Allocator allocator_type; private: typedef _RW::__string_ref _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; public: 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 iterator; typedef _RW::__rw_debug_iter 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_reverse_iterator; typedef _STD::reverse_iterator reverse_iterator; #else typedef _STD::reverse_iterator const_reverse_iterator; typedef _STD::reverse_iterator reverse_iterator; #endif #if defined(_RWSTD_LLP64_ARCHITECTURE) && defined(_RWSTD_NO_STATIC_CONST_MEMBER_INIT) static const size_type npos; #else _RWSTD_STATIC_CONST (size_type, npos = size_type(-1)); #endif _EXPLICIT basic_string (const allocator_type &__alloc = allocator_type ()) : allocator_type (__alloc), _C_data (_C_null ()) { } // LWG Issue #42. basic_string (const basic_string&); basic_string (const basic_string&, size_type, size_type = npos, const allocator_type& = allocator_type ()); basic_string (const_pointer, size_type, const allocator_type& = allocator_type ()); basic_string (const_pointer, const allocator_type& = allocator_type ()); #ifndef _RWSTD_NO_MEMBER_TEMPLATES // pointers to the incomplete types declared below are used // to disambiguate calls to template member functions // requires: member function and class templates // and partial specialization template basic_string (_InputIterator, _InputIterator, const allocator_type& = allocator_type ()); basic_string (int __n, value_type __c, const allocator_type& __alloc = allocator_type ()) : allocator_type (__alloc) { _C_initn (_RWSTD_STATIC_CAST (size_type, __n), __c); } basic_string (unsigned int __n, value_type __c, const allocator_type& __alloc = allocator_type ()) : allocator_type (__alloc) { _C_initn (_RWSTD_STATIC_CAST (size_type, __n), __c); } basic_string (long __n, value_type __c, const allocator_type& __alloc = allocator_type ()) : allocator_type (__alloc) { _C_initn (_RWSTD_STATIC_CAST (size_type, __n), __c); } basic_string (unsigned long __n, value_type __c, const allocator_type& __alloc = allocator_type ()) : allocator_type (__alloc) { _C_initn (_RWSTD_STATIC_CAST (size_type, __n), __c); } basic_string (short __n, value_type __c, const allocator_type& __alloc = allocator_type ()) : allocator_type (__alloc) { _C_initn (_RWSTD_STATIC_CAST (size_type, __n), __c); } basic_string (unsigned short __n, value_type __c, const allocator_type& __alloc = allocator_type ()) : allocator_type (__alloc) { _C_initn (_RWSTD_STATIC_CAST (size_type, __n), __c); } basic_string (char __n, value_type __c, const allocator_type& __alloc = allocator_type ()) : allocator_type (__alloc) { _C_initn (_RWSTD_STATIC_CAST (size_type, __n), __c); } basic_string (unsigned char __n, value_type __c, const allocator_type& __alloc = allocator_type ()) : allocator_type (__alloc) { _C_initn (_RWSTD_STATIC_CAST (size_type, __n), __c); } #ifndef _RWSTD_NO_NATIVE_WCHAR_T basic_string (wchar_t __n, value_type __c, const allocator_type& __alloc = allocator_type ()) : allocator_type (__alloc) { _C_initn (_RWSTD_STATIC_CAST (size_type, __n), __c); } #endif // _RWSTD_NO_NATIVE_WCHAR_T #ifndef _RWSTD_NO_BOOL basic_string (bool __n, value_type __c, const allocator_type& __alloc = allocator_type ()) : allocator_type (__alloc) { _C_initn (_RWSTD_STATIC_CAST (size_type, __n), __c); } #endif // _RWSTD_NO_BOOL #else // if defined (_RWSTD_NO_MEMBER_TEMPLATES) basic_string (size_type __n, value_type __c, const allocator_type& __alloc = allocator_type ()) : allocator_type (__alloc) { _C_initn (__n, __c); } #endif // _RWSTD_NO_MEMBER_TEMPLATES basic_string (const_pointer, const_pointer, const allocator_type& = allocator_type ()); ~basic_string () { _C_unlink(); } basic_string& operator= (const basic_string&); basic_string& operator= (const_pointer __s); basic_string& operator= (value_type __c) { return replace (0, size(), 1, __c); } iterator begin () { _C_cow (); _C_pref ()->_C_set_ref_count (0); // disable ref counting return _C_make_iter (_C_data); } 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()->_C_size; } size_type length () const { return size (); } size_type max_size () const { return size_type (npos) - sizeof (_C_string_ref_type) - 2U; } 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 () { erase (); } 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 append (size_type (1), __c); } basic_string& append (const basic_string&, size_type, size_type); basic_string& append (const basic_string &__str); basic_string& append (const_pointer __s, size_type __n) { return replace (size (), 0, __s, __n, 0, __n), *this; } basic_string& append (const_pointer __s) { return replace (size (), 0, __s); } #if !defined (_RWSTD_NO_MEMBER_TEMPLATES) \ && !defined (_RWSTD_NO_CLASS_PARTIAL_SPEC) template basic_string& append (_InputIterator __first, _InputIterator __last) { // resolves to append (size_type, value_type) if _InputIterator // 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 (_InputIterator)); } template basic_string& append (_InputIterator __first, _InputIterator __last, _RWSTD_DISPATCH_INT (false)) { 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, _RWSTD_DISPATCH_INT (true)) { // unnamed arg is used for overload resolution return replace (size (), 0, __n, __c); } #else // if defined (_RWSTD_NO_MEMBER_TEMPLATES) basic_string& append (const_pointer __first, const_pointer __last) { replace (size (), 0, __first, __last - __first, 0, __last - __first); return *this; } #endif // _RWSTD_NO_MEMBER_TEMPLATES basic_string& append (size_type __n, value_type __c) { return replace (size (), 0, __n, __c); } void push_back (value_type __c) { append (size_type (1), __c); } 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 (0, size (), __s, __n, 0, __n), *this; } basic_string& assign (const_pointer __s) { return *this = __s; } #if !defined (_RWSTD_NO_MEMBER_TEMPLATES) \ && !defined (_RWSTD_NO_CLASS_PARTIAL_SPEC) template basic_string& assign (_InputIterator __first, _InputIterator __last) { // resolves to assign (size_type, value_type) if _InputIterator // 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 (_InputIterator)); } template basic_string& assign (_InputIterator __first, _InputIterator __last, _RWSTD_DISPATCH_INT (false)) { // 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, _RWSTD_DISPATCH_INT (true)) { // unnamed arg is used for overload resolution return replace (0, size (), __n, __c); } #else // if defined (_RWSTD_NO_MEMBER_TEMPLATES) basic_string& assign (const_pointer __first, const_pointer __last) { replace (size_type (), size (), __first, __last - __first, size_type (), __last - __first); return *this; } #endif // _RWSTD_NO_MEMBER_TEMPLATES basic_string& assign (size_type __n, value_type __c) { return replace (0, 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) { return replace (__pos, 0, __s, __n, 0, __n), *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) { _RWSTD_ASSERT_RANGE (_C_make_iter (_C_data), __pos); size_type __inx = __pos - _C_make_iter (_C_data); return insert (__inx, &__c, 1), begin () + __inx; } #if !defined (_RWSTD_NO_MEMBER_TEMPLATES) \ && !defined (_RWSTD_NO_CLASS_PARTIAL_SPEC) template void insert (iterator __p, _InputIterator __first, _InputIterator __last) { // resolves to insert (iterator, size_type, value_type) // if _InputIterator is any integral type (even not an exact match, // such as char) // the cast to int is necessary to avoid an exact match insert (__p, __first, __last, _RWSTD_DISPATCH (_InputIterator)); } void insert (iterator __p, const_iterator __first, const_iterator __last) { iterator __begin = _C_make_iter (_C_data); iterator __end = _C_make_iter (_C_data + size ()); _RWSTD_ASSERT_RANGE (__begin, __p); if (__first >= __begin && __first <= __end) insert (__p - __begin, basic_string (__first, __last)); else replace (__p, __p, __first, __last); } void insert (iterator __p, iterator __first, iterator __last) { insert (__p, const_iterator (__first), const_iterator (__last)); } template void insert (iterator __p, _InputIterator __first, _InputIterator __last, _RWSTD_DISPATCH_INT (false)) { // 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, _RWSTD_DISPATCH_INT (true)) { // unnamed arg is used for overload resolution replace (__p - _C_make_iter (_C_data), 0, __n, __c); } #else // if defined (_RWSTD_NO_MEMBER_TEMPLATES) void insert (iterator __p, const_pointer __first, const_pointer __last) { replace (__p - _C_make_iter (_C_data), 0, __first, __last - __first, 0, __last - __first); } #endif // _RWSTD_NO_MEMBER_TEMPLATES void insert (iterator __p, size_type __n, value_type __c) { replace (__p - _C_make_iter (_C_data), 0, __n, __c); } basic_string& insert (size_type __pos, size_type __n, value_type __c) { return replace (__pos, 0, __n, __c); } basic_string& erase (size_type = 0, size_type = npos); iterator erase (iterator __it) { return replace (__it - _C_make_iter (_C_data), 1, const_pointer (0), 0, 0, 0); } iterator erase (iterator __first, iterator __last) { return replace (__first - _C_make_iter (_C_data), __last - __first, const_pointer (0), 0, 0, 0); } private: iterator replace (size_type, size_type, const_pointer, size_type, size_type, size_type); iterator __replace_aux (size_type pos1, size_type __n1, const basic_string &__str, size_type pos2 = 0, size_type __n2 = npos) { return replace (pos1, __n1, __str.c_str(), __str.size(), pos2, __n2); } #ifndef _RWSTD_NO_MEMBER_TEMPLATES template basic_string& __replace_aux (iterator first1, iterator last1, _InputIterator first2, _InputIterator last2); #endif // _RWSTD_NO_MEMBER_TEMPLATES public: basic_string& replace (size_type pos1, size_type __n1, const basic_string &__s, size_type pos2, size_type __n2) { replace (pos1, __n1, __s.c_str (), __s.size (), pos2, __n2); return *this; } basic_string& replace (size_type __pos, size_type __n, const basic_string &__s) { return replace (__pos, __n, __s, 0, __s.size ()); } basic_string& replace (size_type __pos, size_type __n1, const_pointer __s, size_type __n2) { return replace (__pos, __n1, __s, __n2, 0, __n2), *this; } basic_string& replace (size_type __pos, size_type __n, const_pointer __s) { return replace (__pos, __n, __s, traits_type::length (__s)); } basic_string& replace (size_type, size_type, size_type, value_type); basic_string& replace (iterator __first, iterator __last, const basic_string &__str) { return replace (__first - _C_make_iter (_C_data), __last - __first, __str); } basic_string& replace (iterator __first, iterator __last, const_pointer __s, size_type __n) { replace (__first - _C_make_iter (_C_data), __last - __first, __s, __n, 0, __n); return *this;; } basic_string& replace (iterator __first, iterator __last, const_pointer __s) { return replace (__first, __last, __s, traits_type::length(__s)); } #if !defined (_RWSTD_NO_MEMBER_TEMPLATES) \ && !defined (_RWSTD_NO_CLASS_PARTIAL_SPEC) template basic_string& replace (iterator, iterator, _InputIterator, _InputIterator, _RWSTD_DISPATCH_INT (false)); basic_string& replace (iterator __first, iterator __last, size_type __n, value_type __c, _RWSTD_DISPATCH_INT (true)) { // unnamed arg is used for overload resolution return replace (__first - _C_make_iter (_C_data), __last - __first, __n, __c); } template basic_string& replace (iterator __first1, iterator __last1, _InputIterator __first2, _InputIterator __last2) { // resolves to replace (iterator, iterator, size_type, value_type) // if _InputIterator is any integral type (even not an exact match, // Such as char) // the cast to int is necessary to prevent an exact match return replace (__first1, __last1, __first2, __last2, _RWSTD_DISPATCH (_InputIterator)); } #else // if defined (_RWSTD_NO_MEMBER_TEMPLATES) basic_string& replace (iterator first1, iterator last1, const_pointer first2, const_pointer last2) { return replace (first1 - _C_make_iter (_C_data), last1 - first1, first2, last2 - first2, 0, last2 - first2), *this; } #endif // _RWSTD_NO_MEMBER_TEMPLATES basic_string& replace (iterator __first, iterator __last, size_type __n, value_type __c) { // unnamed arg is used for overload resolution return replace (__first - _C_make_iter (_C_data), __last - __first, __n, __c); } 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 (), 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, size_type = 0) const; // 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, size_type = npos) const; // 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, size_type = 0) const; // 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, size_type = 0) const; // 21.3.6.5, p7 size_type find_first_not_of (value_type, size_type = 0) const; // 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, size_type = npos) const; // 21.3.6.7 basic_string substr (size_type = 0, size_type = npos) const; int compare (const basic_string &__str) const; int compare (size_type __pos, size_type __n, const basic_string &__str) const { return compare (__pos, __n, __str.c_str(), __str.size()); } int compare (size_type, size_type, const basic_string&, size_type, size_type) const; int compare (const_pointer __s) const { return compare (0, size (), __s, traits_type::length(__s)); } // LWG Issue #5. int compare (size_type __pos, size_type __n, const_pointer __s) const { return compare(__pos, __n, __s, traits_type::length (__s)); } int compare (size_type, size_type, const_pointer, size_type) const; protected: void _C_cow () { // Do copy on write as necessary if (_C_pref ()->_C_ref_count() > 1) _C_clone (); } void _C_cow (size_type __nc) { // Do copy on write w/ new capacity if (_C_pref ()->_C_ref_count () > 1 || capacity () < __nc) _C_clone (__nc); } private: void _C_initn (size_type, value_type); void _C_clone (size_type __nc = npos); _C_string_ref_type* _C_pref () const { return _RWSTD_REINTERPRET_CAST (_C_string_ref_type*, _C_data) - 1; } void _C_unlink (); friend struct _RW::__string_ref; #ifndef _RWSTD_NO_COLLAPSE_TEMPLATE_STATICS static _RW::__null_ref<_CharT, _Traits, _Allocator> __nullref; static pointer _C_null () { return __nullref.data (); } #else // if defined (_RWSTD_NO_COLLAPSE_TEMPLATE_STATICS) static pointer _C_null () { typedef _RW::__null_ref<_CharT, _Traits, _Allocator> _NullRef; return _RWSTD_REINTERPRET_CAST (_NullRef*, &_RW::__nullref)->data (); } #endif // _RWSTD_NO_COLLAPSE_TEMPLATE_STATICS _C_string_ref_type * _C_getRep (size_type, size_type); // for convenience pointer _C_allocate (size_type __cur, size_type __cap, size_type __size) { return _C_getRep (max (size_type (_RW::__rw_new_capacity (__cur, this)), __cap), __size)->data (); } pointer _C_data; }; typedef basic_string, allocator > string; #ifndef _RWSTD_NO_WCHAR_T typedef basic_string, allocator > wstring; #endif // _RWSTD_NO_WCHAR_T template inline void basic_string<_CharT, _Traits, _Allocator>::_C_unlink() { _RWSTD_ASSERT (0 != _C_data); if (data () == _C_null ()) return; if (_C_pref ()->_C_ref_count () == 0 || _C_pref ()->_C_dec_ref () == 0) { // Required to pass same size to deallocate as allocate (see string.cc). // Also note that we cannot call capacity() after the destroy() call. size_type __size = capacity () + sizeof (_C_string_ref_type) / sizeof (value_type) + 2; // explicitly destroy POD _C_pref ()->_C_destroy (); _C_ref_alloc_type (*this).destroy (_C_pref ()); _RWSTD_VALUE_ALLOC (_C_value_alloc_type, deallocate (_RWSTD_REINTERPRET_CAST (pointer, _C_pref()), __size)); } } template inline basic_string<_CharT, _Traits, _Allocator>:: basic_string (const basic_string<_CharT, _Traits, _Allocator> &__s) : allocator_type (__s.get_allocator ()) { if (__s._C_pref()->_C_ref_count () > 0) { _C_data = __s._C_data; _C_pref()->_C_inc_ref (); } else { size_type __n = __s.size(); _C_data = _C_getRep (__n, __n)->data (); traits_type::copy (_C_data, __s.c_str (), __n); } } template 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, 0); } template 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 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 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 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 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 (), 0, __n - size (), __c); } template inline void basic_string<_CharT, _Traits, _Allocator>:: reserve (size_type __n) { _RWSTD_REQUIRES (__n <= max_size (), (_RWSTD_ERROR_LENGTH_ERROR, _RWSTD_FUNC ("basic_string::reserve(size_type)"), __n, max_size ())); if (__n > capacity ()) _C_clone (__n); } template inline _TYPENAME basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>:: find (const_pointer __s, size_type __pos) const { _RWSTD_ASSERT (__s != 0); // 21.3.6.1, p1, bullet 1 if (__pos > size ()) return npos; const_pointer __where = _RW::rw_traits::find (_C_data + __pos, __s); return __where ? __where - _C_data : npos; } template 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_pointer __where = traits_type::find (_C_data + __pos, size() - __pos, __c); return __where ? __where - _C_data : npos; } template inline _TYPENAME basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>:: rfind (value_type __c, size_type __pos) const { if (!size ()) return npos; if (__pos >= size ()) __pos = size () - 1; // start at the last valid position const_pointer __where = _RW::rw_traits::rfind (_C_data, __c, __pos); return __where ? __where - _C_data : npos; } template inline _TYPENAME basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>:: find_first_of (const_pointer __s, size_type __pos) const { _RWSTD_ASSERT (__s != 0); if (__pos > size()) return npos; typedef _RW::rw_traits<_CharT, _Traits> __rw_traits; size_type __i = __rw_traits::find_first_of (_C_data + __pos, __s) + __pos; return __i >= size () ? npos : __i; } template inline _TYPENAME basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>:: find_first_not_of (const_pointer __s, size_type __pos) const { _RWSTD_ASSERT (__s != 0); if (__pos > size()) return npos; typedef _RW::rw_traits<_CharT, _Traits> __rw_traits; size_type __i = __rw_traits::find_first_not_of(_C_data + __pos, __s)+ __pos; return __i >= size () ? npos : __i; } template inline _TYPENAME basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>:: find_first_not_of (value_type __c, size_type __pos) const { return find_first_not_of (&__c, __pos, 1); } template inline _TYPENAME basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>:: find_last_not_of (value_type __c, size_type __pos) const { #if 0 // disabled to work around a bug in several compilers const value_type __tmp [] = { __c, value_type () }; #else value_type __tmp [2]; traits_type::assign (__tmp [0], __c); traits_type::assign (__tmp [1], value_type ()); #endif // 0/1 return find_last_not_of (__tmp, __pos); } template inline void basic_string<_CharT, _Traits, _Allocator>:: _C_clone (size_type __nc /* = npos */) { size_type __len = size(); _C_string_ref_type * __temp = _C_getRep (npos == __nc ? size () : __nc, __len > __nc ? __nc : __len); traits_type::copy (__temp->data(), _C_data, size()); _C_unlink (); _C_data = __temp->data (); } template inline int basic_string<_CharT, _Traits, _Allocator>:: compare (const basic_string &__str) const { int __res = traits_type::compare (data (), __str.data (), _STD::min (size (), __str.size ())); if (0 == __res) __res = size () < __str.size () ? -1 : size () != __str.size (); return __res; } template inline basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append (const basic_string &__str) { size_type __len = size () + __str.size (); if (__len > capacity () || _C_pref ()->_C_ref_count () > 1) return append (__str, 0, __str.size ()); traits_type::copy (_C_data + size (), __str.data (), __str.size () + 1); _C_pref ()->_C_size = __len; return *this; } // 21.3.7.1, p1 template 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.data () + __lhs.size ()) += __rhs; } // 21.3.7.1, p2 template 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 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 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.data () + __lhs.size ()) += __rhs; } // 21.3.7.1, p7 template 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.data () + __lhs.size ()) += __rhs; } // 21.3.7.2, p1 template inline bool operator== (const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) { return __lhs.size () == __rhs.size () && 0 == __lhs.compare (__rhs); } // 21.3.7.2, p2 template inline bool operator== (const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) { return 0 == __rhs.compare (__lhs); } // 21.3.7.2, p3 template inline bool operator== (const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) { return 0 == __lhs.compare (__rhs); } // 21.3.7.4, p1 template 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 inline bool operator< (const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) { return 0 < __rhs.compare (__lhs); } // 21.3.7.4, p3 template inline bool operator< (const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) { return 0 > __lhs.compare (__rhs); } // 21.3.7.3, p1 template 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 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 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 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 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 inline bool operator!= (const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) { return !(__lhs == __rhs); } // 21.3.7.3, p3 template inline bool operator!= (const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) { return !(__lhs == __rhs); } // 21.3.7.5, p2 template inline bool operator> (const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) { return __rhs < __lhs; } // 21.3.7.5, p3 template inline bool operator> (const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) { return __rhs < __lhs; } // 21.3.7.6, p2 template inline bool operator<= (const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) { return !(__rhs < __lhs); } // 21.3.7.6, p3 template inline bool operator<= (const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) { return !(__rhs < __lhs); } // 21.3.7.7, p2 template inline bool operator>= (const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) { return !(__lhs < __rhs); } // 21.3.7.7, p3 template inline bool operator>= (const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) { return !(__lhs < __rhs); } // 21.3.7.9, p3 - declared here, defined inline in template inline basic_ostream<_CharT, _Traits>& operator<< (basic_ostream<_CharT, _Traits>&, const basic_string<_CharT, _Traits, _Allocator>&); _RWSTD_NAMESPACE_END // std _RWSTD_NAMESPACE_BEGIN (__rw) _USING (namespace std); #ifndef _RWSTD_NO_FUNC_PARTIAL_SPEC // more specialized version for basic_string<>; may be further specialized // in user code for example on a user-defined allocator template inline size_t __rw_new_capacity (size_t __size, const basic_string<_CharT, _Traits, _Allocator>*) { size_t __cap = _RWSTD_STATIC_CAST (size_t, _RWSTD_INCREASE_STRING_CAPACITY(__size) /*__size * _RWSTD_STRING_CAPACITY_RATIO*/); return (__size += _RWSTD_MINIMUM_STRING_CAPACITY) > __cap ? __size : __cap; } #else // if defined (_RWSTD_NO_FUNC_PARTIAL_SPEC) // the following specializations of the __rw_new_capacity<> function template // are provided for char and wchar_t; the general case is given in the _RWSTD_SPECIALIZED_FUNCTION inline size_t __rw_new_capacity (size_t __size, const string*) { size_t __cap = _RWSTD_STATIC_CAST (size_t, _RWSTD_INCREASE_STRING_CAPACITY(__size) /*__size * _RWSTD_STRING_CAPACITY_RATIO*/); return (__size += _RWSTD_MINIMUM_STRING_CAPACITY) > __cap ? __size : __cap; } _RWSTD_SPECIALIZED_FUNCTION inline size_t __rw_new_capacity (size_t __size, const wstring*) { size_t __cap = _RWSTD_STATIC_CAST (size_t, _RWSTD_INCREASE_STRING_CAPACITY(__size) /*__size * _RWSTD_STRING_CAPACITY_RATIO*/); return (__size += _RWSTD_MINIMUM_STRING_CAPACITY) > __cap ? __size : __cap; } #endif // _RWSTD_NO_FUNC_PARTIAL_SPEC _RWSTD_NAMESPACE_END // __rw #if _RWSTD_DEFINE_TEMPLATE (BASIC_STRING) # include #endif _RWSTD_NAMESPACE_BEGIN (std) _RWSTD_INSTANTIATE_3 (class _RWSTD_EXPORT basic_string, allocator >); #ifndef _RWSTD_NO_WCHAR_T _RWSTD_INSTANTIATE_3 (class _RWSTD_EXPORT basic_string, allocator >); #endif // _RWSTD_NO_WCHAR_T _RWSTD_NAMESPACE_END // std #endif // _RWSTD_STRING_INCLUDED