// -*- C++ -*- /*************************************************************************** * * - definition of the C++ Standard Library basic_string template * * $Id$ * *************************************************************************** * * Copyright (c) 1994-2005 Quovadx, Inc., acting through its Rogue Wave * Software division. Licensed 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. * **************************************************************************/ #ifndef _RWSTD_STRING_INCLUDED #define _RWSTD_STRING_INCLUDED #if __GNUG__ >= 3 # pragma GCC system_header #endif // gcc >= 3 #include #include #include #include #include #include _RWSTD_NAMESPACE (std) { #if !defined (_RWSTD_NO_INLINE_MEMBER_TEMPLATES) \ && (!defined (_MSC_VER) || _MSC_VER >= 1300 || defined (__INTEL_COMPILER))\ && defined (_RWSTD_NO_MEMBER_TEMPLATES) template std::basic_string<_CharT, _Traits, _Alloc>& __rw_replace (std::basic_string<_CharT, _Traits, _Alloc>&, _StringIter, _StringIter, _InputIter, _InputIter); template std::basic_string<_CharT, _Traits, _Alloc>& __rw_replace_aux (std::basic_string<_CharT, _Traits, _Alloc>&, _StringIter, _StringIter, _InputIter, _InputIter); #endif // !NO_INLINE_MEMBER_TEMPLATES && NO_MEMBER_TEMPLATES _EXPORT template 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 _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 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 // if defined (_RWSTD_NO_CLASS_PARTIAL_SPEC) typedef _STD::reverse_iterator const_reverse_iterator; typedef _STD::reverse_iterator 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 ()); #if !defined (_RWSTD_NO_INLINE_MEMBER_TEMPLATES) \ && (!defined (_MSC_VER) || _MSC_VER >= 1300 || defined (__INTEL_COMPILER)) // 21.3.1, p15 template 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); } #endif // _RWSTD_NO_INLINE_MEMBER_TEMPLATES basic_string (const_pointer __first, const_pointer __last, const allocator_type &__alloc _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 () { _C_unlink (_C_nullref ()->data ()); } 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&); basic_string& append (const_pointer __s, size_type __n) { return replace (size (), size_type (), __s, __n); } basic_string& append (const_pointer __s) { return replace (size (), size_type (), __s); } #if !defined (_RWSTD_NO_INLINE_MEMBER_TEMPLATES) \ && (!defined (_MSC_VER) || _MSC_VER >= 1300 || defined (__INTEL_COMPILER)) template 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 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 replace (size (), size_type (), __n, __c); } #else // if defined (_RWSTD_NO_INLINE_MEMBER_TEMPLATES) basic_string& append (const_pointer __first, const_pointer __last) { replace (size (), size_type (), __first, __last - __first); return *this; } #endif // _RWSTD_NO_INLINE_MEMBER_TEMPLATES basic_string& append (size_type __n, value_type __c) { return replace (size (), size_type (), __n, __c); } // lwg issue 7 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 (size_type (), size (), __s, __n); } basic_string& assign (const_pointer __s) { return replace (size_type (), size (), __s, traits_type::length (__s)); } #if !defined (_RWSTD_NO_INLINE_MEMBER_TEMPLATES) \ && (!defined (_MSC_VER) || _MSC_VER >= 1300 || defined (__INTEL_COMPILER)) template 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 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); } #else // if defined (_RWSTD_NO_INLINE_MEMBER_TEMPLATES) basic_string& assign (const_pointer __first, const_pointer __last) { replace (size_type (), size (), __first, __last - __first); return *this; } #endif // _RWSTD_NO_INLINE_MEMBER_TEMPLATES 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) { _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_INLINE_MEMBER_TEMPLATE) \ && (!defined (_MSC_VER) || _MSC_VER >= 1300 || defined (__INTEL_COMPILER)) template void insert (iterator __p, _InputIter __first, _InputIter __last) { insert (__p, __first, __last, _RWSTD_DISPATCH (_InputIter)); } template 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 (__p - _C_make_iter (_C_data), size_type (), __n, __c); } void insert (iterator __p, const_pointer __first, const_pointer __last, void*) { // unnamed arg is used for overload resolution const iterator __begin = _C_make_iter (_C_data); _RWSTD_ASSERT_RANGE (__begin, __p); if (__first >= _C_data && __first <= _C_data + size ()) insert (__p - __begin, 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 + (__last - __first)); } } 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 #else // if defined (_RWSTD_NO_INLINE_MEMBER_TEMPLATES) void insert (iterator __p, const_pointer __first, const_pointer __last) { // unnamed arg is used for overload resolution const iterator __begin = _C_make_iter (_C_data); _RWSTD_ASSERT_RANGE (__begin, __p); if (__first >= _C_data && __first <= _C_data + size ()) insert (__p - __begin, basic_string (__first, __last)); else replace (__p, __p, __first, __last); } #endif // _RWSTD_NO_INLINE_MEMBER_TEMPLATES void insert (iterator __it, size_type __n, value_type __c) { _RWSTD_ASSERT_RANGE (_C_make_iter (_C_data), __it); replace (__it - _C_make_iter (_C_data), 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) { _RWSTD_ASSERT_RANGE (_C_make_iter (_C_data), __first); _RWSTD_ASSERT_RANGE (__first, __last); const difference_type __pos = __first - _C_make_iter (_C_data); replace (__pos, __last - __first, 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); } #if !defined (_RWSTD_NO_INLINE_MEMBER_TEMPLATES) \ && (!defined (_MSC_VER) || _MSC_VER >= 1300 || defined (__INTEL_COMPILER)) # ifndef _RWSTD_NO_MEMBER_TEMPLATES template basic_string& __replace_aux (iterator, iterator, _InputIter, _InputIter); # else // if defined (_RWSTD_NO_MEMBER_TEMPLATES) public: template basic_string& __replace_aux (iterator __first1, iterator __last1, _InputIter __first2, _InputIter __last2) { return __rw_replace_aux (*this, __first1, __last1, __first2, __last2); } # endif // _RWSTD_NO_MEMBER_TEMPLATES #endif // _RWSTD_NO_INLINE_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 (__first - _C_make_iter (_C_data), __last - __first, __str); } // 21.3.5.6, p15 basic_string& replace (iterator __first, iterator __last, const_pointer __s, size_type __n) { replace (__first - _C_make_iter (_C_data), __last - __first, __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 (__first - _C_make_iter (_C_data), __last - __first, __n, __c); } #if !defined (_RWSTD_NO_INLINE_MEMBER_TEMPLATES) \ && (!defined (_MSC_VER) || _MSC_VER >= 1300 || defined (__INTEL_COMPILER)) # ifndef _RWSTD_NO_MEMBER_TEMPLATES template basic_string& replace (iterator __first1, iterator __last1, _InputIter __first2, _InputIter __last2, void*); # else // if defined (_RWSTD_NO_MEMBER_TEMPLATES) template basic_string& replace (iterator __first1, iterator __last1, _InputIter __first2, _InputIter __last2, void*) { return __rw_replace (*this, __first1, __last1, __first2, __last2); } # endif // _RWSTD_NO_MEMBER_TEMPLATES basic_string& replace (iterator __first, iterator __last, size_type __n, value_type __c, int) { // unnamed arg is used for overload resolution return replace (__first - _C_make_iter (_C_data), __last - __first, __n, __c); } // 21.3.5.6, p21 template basic_string& replace (iterator __first1, iterator __last1, _InputIter __first2, _InputIter __last2) { return replace (__first1, __last1, __first2, __last2, _RWSTD_DISPATCH (_InputIter)); } #else // if defined (_RWSTD_NO_INLINE_MEMBER_TEMPLATES) basic_string& replace (iterator __first1, iterator __last1, const_pointer __first2, const_pointer __last2) { replace (__first1 - _C_make_iter (_C_data), __last1 - __first1, __first2, __last2 - __first2); return *this; } #endif // _RWSTD_NO_INLINE_MEMBER_TEMPLATES // 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_INLINE_MEMBER_TEMPLATES) \ && (!defined (_MSC_VER) || _MSC_VER >= 1300 || defined (__INTEL_COMPILER)) \ && defined (_RWSTD_NO_MEMBER_TEMPLATES) public: #else private: #endif void _C_clone (size_type); _C_string_ref_type* _C_pref () const { return _RWSTD_REINTERPRET_CAST (_C_string_ref_type*, _C_data) - 1; } void _C_unlink (pointer); friend struct _RW::__string_ref; #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, allocator > string; #ifndef _RWSTD_NO_WCHAR_T typedef basic_string, allocator > wstring; #endif // _RWSTD_NO_WCHAR_T template #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 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 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 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 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 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 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 (), size_type (), __n - size (), __c); } template 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 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::compare(size_type, " "size_type, const basic_string&, " "size_type, size_type) const"), __pos1, size ())); _RWSTD_REQUIRES (__pos2 <= __str.size (), (_RWSTD_ERROR_OUT_OF_RANGE, _RWSTD_FUNC ("basic_string::compare(size_type, " "size_type, const basic_string&, " "size_type, size_type) const"), __pos2, __str.size ())); const size_type __rem = __str.size () - __pos2; replace (__pos1, __n1, __str.data () + __pos2, __n2 < __rem ? __n2 : __rem); return *this; } 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 const_pointer __where = traits_type::find (_C_data + __pos, size () - __pos, __c); return __where ? __where - _C_data : npos; } template 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 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 inline basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>:: append (const basic_string &__str) { const size_type __size = size () + __str.size (); if ( capacity () < __size || size_type (1) < size_type (_C_pref ()->_C_get_ref ())) return append (__str, size_type (), __str.size ()); traits_type::copy (_C_data + size (), __str.data (), __str.size () + 1); _C_pref ()->_C_size._C_size = __size; 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.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.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.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) { // 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 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 inline bool operator== (const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT* __rhs) { return __rhs == __lhs; } // 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>&); } // namespace std _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 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; _RWSizeT __cap = _RWSTD_STATIC_CAST (_RWSizeT, __size * _RWSTD_STRING_CAPACITY_RATIO); 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 _RWSTD_SPECIALIZED_FUNCTION inline _RWSTD_STRING_SIZE_TYPE (_STD::string) __rw_new_capacity (_RWSTD_STRING_SIZE_TYPE (_STD::string) __size, const _STD::string*) { _RWSTD_STRING_SIZE_TYPE (_STD::string) __cap = _RWSTD_STATIC_CAST (_RWSTD_STRING_SIZE_TYPE (_STD::string), __size * _RWSTD_STRING_CAPACITY_RATIO); 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*) { _RWSTD_STRING_SIZE_TYPE (_STD::wstring) __cap = _RWSTD_STATIC_CAST (_RWSTD_STRING_SIZE_TYPE (_STD::wstring), __size * _RWSTD_STRING_CAPACITY_RATIO); 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 #endif // _RWSTD_DEFINE_TEMPLATE_FIRST (_BASIC_STRING) _RWSTD_NAMESPACE (std) { #if _RWSTD_INSTANTIATE (_BASIC_STRING, _CHAR) _RWSTD_INSTANTIATE_3 (class _RWSTD_EXPORT basic_string, allocator >); #endif // _RWSTD_INSTANTIATE (_BASIC_STRING, _CHAR) #if _RWSTD_INSTANTIATE (_BASIC_STRING, _WCHAR_T) _RWSTD_INSTANTIATE_3 (class _RWSTD_EXPORT basic_string, allocator >); #endif // _RWSTD_INSTANTIATE (_BASIC_STRING, _WCHAR_T) } // namespace std #if _RWSTD_DEFINE_TEMPLATE_LAST (_BASIC_STRING) # include #endif // _RWSTD_DEFINE_TEMPLATE_LAST (_BASIC_STRING) #endif // _RWSTD_STRING_INCLUDED