// -*- C++ -*-
/***************************************************************************
 *
 * <string> - definition of the C++ Standard Library basic_string template
 *
 * $Id: string 651447 2008-04-24 22:50:34Z sebor $
 *
 ***************************************************************************
 *
 * 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_MEMBER_TEMPLATES)   \
        || defined (_RWSTD_NO_EXTERN_MEMBER_TEMPLATE))
#  define _RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES
#endif   // _RWSTD_NO_STRING_MEMBER_TEMPLATES


#ifndef _RWSTD_NO_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
#endif   // _RWSTD_NO_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 ());


#ifndef _RWSTD_NO_MEMBER_TEMPLATES

    // 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);
    }

#endif   // _RWSTD_NO_MEMBER_TEMPLATES

    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));
    }

#ifndef _RWSTD_NO_MEMBER_TEMPLATES

    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);
    }

#else   // if defined (_RWSTD_NO_MEMBER_TEMPLATES)

    basic_string& append (const_pointer __first, const_pointer __last) {
        return append (__first, __last - __first);
    }

#endif   // _RWSTD_NO_MEMBER_TEMPLATES

    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));
    }


#ifndef _RWSTD_NO_MEMBER_TEMPLATES

    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);
    }

#else   // if defined (_RWSTD_NO_MEMBER_TEMPLATES)

    basic_string& assign (const_pointer __first, const_pointer __last) {
        replace (size_type (), size (), __first, __last - __first);
        return *this;
    }

#endif   // _RWSTD_NO_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) {
        const size_type __inx = _C_off (__pos);
        return insert (__inx, &__c, 1), begin () + __inx;
    }

#ifndef _RWSTD_NO_MEMBER_TEMPLATES

    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

#else   // if defined (_RWSTD_NO_MEMBER_TEMPLATES)

    void insert (iterator __p, const_pointer __first, const_pointer __last) {
        if (__first >= _C_data && __first <= _C_data + size ())
            insert (_C_off (__p), basic_string (__first, __last));
        else
            replace (__p, __p, __first, __last);
    }

#endif   // _RWSTD_NO_MEMBER_TEMPLATES
    

    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);
    }

#ifndef _RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES

    template <class _InputIter>
    basic_string& __replace_aux (iterator, iterator, _InputIter, _InputIter);

#else

public:

    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_MEMBER_TEMPLATES

#  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));
    }

#else   // if defined (_RWSTD_NO_MEMBER_TEMPLATES)

    basic_string&
    replace (iterator __first1, iterator __last1,
             const_pointer __first2, const_pointer __last2) {
        replace (_C_off (__first1), _C_off (__first1, __last1),
                 __first2, size_type (__last2 - __first2));
        return *this;
    }

#endif   // _RWSTD_NO_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_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)


_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


#if _RWSTD_DEFINE_TEMPLATE_LAST (_BASIC_STRING)
#  include <string.cc>
#endif   // _RWSTD_DEFINE_TEMPLATE_LAST (_BASIC_STRING)


#endif   // _RWSTD_STRING_INCLUDED
