home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Internet 2000 May / MICD_2000_05.iso / CBuilder5 / INSTALL / DATA1.CAB / Program_Built_Files / Include / string.cc < prev    next >
C/C++ Source or Header  |  2000-02-01  |  36KB  |  1,011 lines

  1. #ifndef __STRING_CC
  2. #define __STRING_CC
  3. #pragma option push -b -a8 -pc -Vx- -Ve- -w-inl -w-aus -w-sig
  4. /***************************************************************************
  5.  *
  6.  * string.cc - Definitions for the Standard Library string classes
  7.  *
  8.  ***************************************************************************
  9.  *
  10.  * Copyright (c) 1994-1999 Rogue Wave Software, Inc.  All Rights Reserved.
  11.  *
  12.  * This computer software is owned by Rogue Wave Software, Inc. and is
  13.  * protected by U.S. copyright laws and other laws and by international
  14.  * treaties.  This computer software is furnished by Rogue Wave Software,
  15.  * Inc. pursuant to a written license agreement and may be used, copied,
  16.  * transmitted, and stored only in accordance with the terms of such
  17.  * license and with the inclusion of the above copyright notice.  This
  18.  * computer software or any other copies thereof may not be provided or
  19.  * otherwise made available to any other person.
  20.  *
  21.  * U.S. Government Restricted Rights.  This computer software is provided
  22.  * with Restricted Rights.  Use, duplication, or disclosure by the
  23.  * Government is subject to restrictions as set forth in subparagraph (c)
  24.  * (1) (ii) of The Rights in Technical Data and Computer Software clause
  25.  * at DFARS 252.227-7013 or subparagraphs (c) (1) and (2) of the
  26.  * Commercial Computer Software û Restricted Rights at 48 CFR 52.227-19,
  27.  * as applicable.  Manufacturer is Rogue Wave Software, Inc., 5500
  28.  * Flatiron Parkway, Boulder, Colorado 80301 USA.
  29.  *
  30.  **************************************************************************/
  31. #include <stdcomp.h>
  32.  
  33. //
  34. // Members for class basic_string
  35. //
  36.  
  37. #ifndef _RWSTD_NO_NAMESPACE
  38. namespace std {
  39. #endif
  40.  
  41. // basic_string<...>::__nullref
  42. #ifndef _RWSTD_NO_STATIC_DEF3
  43.   template <class charT, class traits, class Allocator >
  44.   const _TYPENAME basic_string<charT, traits, Allocator>::__null_ref_type
  45.   basic_string<charT, traits, Allocator>::__nullref;
  46. #endif
  47. // basic_string<...>::npos
  48. #if defined(__BORLANDC__) && !defined(_RTLDLL)
  49. #ifdef _RWSTD_MSC22_STATIC_INIT_BUG
  50. #define npos (size_type)-1
  51. #else
  52.   template <class charT, class traits, class Allocator >
  53.   const _TYPENAME basic_string<charT, traits, Allocator>::size_type
  54.   basic_string<charT, traits, Allocator>::npos
  55. #ifdef _RWSTD_NO_STATIC_CAST
  56.   = (_TYPENAME basic_string<charT, traits, Allocator>::size_type) -1;
  57. #else
  58.   = static_cast</* _TYPENAME */ basic_string<charT, traits, Allocator>::size_type>(-1); // RW_BUG
  59. #endif
  60.  
  61. #endif /* __BORLANDC__ && !_RTLDLL */
  62. #endif /*_RWSTD_MSC22_STATIC_INIT_BUG*/
  63.  
  64.   template <class charT, class traits, class Allocator >
  65.   _TYPENAME basic_string<charT, traits, Allocator>::__string_ref_type *
  66.   basic_string<charT, traits, Allocator>::__getRep (size_type capac, 
  67.                                                     size_type nchar)
  68.                                               
  69.   {                                                     
  70.     if (capac < nchar)
  71.        capac = nchar;
  72.  
  73.     if ((capac | nchar) == 0)
  74.     {
  75.       __getNullRep()->__addReference();
  76.       return __getNullRep();
  77.     }
  78.  
  79.     //
  80.     // Allocate, then initialize the __string_ref, then
  81.     // initialize each character in the buffer. 
  82.     //
  83.     __value_alloc_type va(__data_);
  84. #ifdef _RWSTD_NO_STATIC_CAST
  85.     __string_ref_type * ret = (__string_ref_type *)
  86.     va.allocate(capac + sizeof(__rep_type)/sizeof(charT) + 2,0);
  87. #else
  88.     __string_ref_type * ret = 
  89.     reinterpret_cast<__string_ref_type*>
  90.     (va.allocate(capac + sizeof(__rep_type)/sizeof(charT) + 2,0));
  91. #endif
  92.  
  93.     __ref_alloc_type(__data_).construct(ret, __string_ref_type());
  94.     charT * d = ret->data();
  95.     va.construct(d,charT());
  96.  
  97.     ret->__capacity_ = capac;
  98.     ret->__setRefCount(1);
  99.     ret->data()[ret->__nchars_ = nchar] = (charT)0; // Terminating null
  100.     return ret;
  101.   }
  102.  
  103.   template <class charT, class traits, class Allocator >
  104.   basic_string<charT, traits, Allocator>::basic_string (
  105.       const basic_string<charT, traits, Allocator> & s,
  106.       size_type pos, size_type  n,
  107.       const Allocator& alloc)
  108.     : __data_(0,alloc)
  109.   {
  110.    _RWSTD_THROW(pos > s.length(), out_of_range,
  111.     __RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
  112.        "basic_string( const basic_string&,size_type,size_type)", pos,s.length()).msgstr());
  113.  
  114.     size_type slen = s.length() - pos;
  115.     size_type rlen = n < slen ? n : slen;
  116.     size_type nlen =  n == npos ? 0 : n;
  117.     size_type maxlen = nlen > rlen ? nlen : rlen;
  118.     __data_            = __getRep(maxlen, rlen)->data();
  119.  
  120.     traits::copy(__data_.data(), &s.__data_.data()[pos], rlen);
  121.   }
  122.  
  123.   template <class charT, class traits, class Allocator >
  124.   void basic_string<charT, traits, Allocator>::__initn (
  125.       size_type        n,
  126.       charT            c)
  127.   {
  128.    _RWSTD_THROW(n == npos, length_error,
  129.      __RWSTD::except_msg_string(__RWSTD::__rwse_InvalidSizeParam,
  130.         "basic_string::__initn(size_t,char)", n,npos).msgstr());
  131.  
  132.     __data_  = __getRep(n, n)->data();
  133.  
  134.     while (n--) traits::assign(__data_.data()[n], c);
  135.   }
  136.  
  137.   template <class charT, class traits, class Allocator >
  138.   basic_string<charT, traits, Allocator>::basic_string (
  139.       const charT*     s,
  140.       size_type        n,
  141.       const Allocator& alloc)
  142.   : __data_(0,alloc)
  143.   {     
  144.     _RWSTD_THROW(s == 0, logic_error,
  145.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  146.        "basic_string( const charT*,size_type,const Allocator&)").msgstr());
  147.  
  148.     _RWSTD_THROW(n == npos, length_error,
  149.      __RWSTD::except_msg_string(__RWSTD::__rwse_InvalidSizeParam,
  150.         "basic_string( const charT*,size_type,const Allocator&)",n,npos).msgstr());
  151.  
  152.     __data_  = __getRep(n, n)->data();
  153.     traits::copy(__data_.data(), s, n);
  154.   }
  155.  
  156.   template <class charT, class traits, class Allocator >
  157.   basic_string<charT, traits, Allocator>::basic_string (
  158.       const charT*     s,
  159.       const Allocator& alloc)
  160.   : __data_(0,alloc)
  161.   {     
  162.     _RWSTD_THROW(s == 0, logic_error,
  163.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  164.         "basic_string(const charT*,const Allocator&)").msgstr());
  165.  
  166.     size_type len = traits::length(s);
  167.     __data_         = __getRep(len, len)->data();
  168.  
  169.     traits::copy(__data_.data(), s, len);
  170.   }
  171.  
  172. #ifdef _RWSTD_NO_DEFAULT_TEMPLATE_ARGS
  173.   template <class charT, class traits, class Allocator >
  174.   basic_string<charT, traits, Allocator>::basic_string (
  175.       const charT*     s,
  176.       size_type        n)
  177.   : __data_(0,Allocator())
  178.   {     
  179.     _RWSTD_THROW(s == 0, logic_error,
  180.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  181.          "basic_string( const charT*,size_type)").msgstr());
  182.  
  183.     _RWSTD_THROW(n == npos,  length_error,
  184.      __RWSTD::except_msg_string(__RWSTD::__rwse_InvalidSizeParam,
  185.         "basic_string(const charT*,size_type)",n,npos).msgstr());
  186.  
  187.     __data_  = __getRep(n, n)->data();
  188.  
  189.     traits::copy(__data_.data(), s, n);
  190.   }
  191.  
  192.   template <class charT, class traits, class Allocator >
  193.   basic_string<charT, traits, Allocator>::basic_string (
  194.       const charT*     s)
  195.   : __data_(0,Allocator())
  196.   {     
  197.     _RWSTD_THROW(s == 0, logic_error,
  198.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  199.         "basic_string(const charT*)").msgstr());
  200.  
  201.     size_type len = traits::length(s);
  202.     __data_         = __getRep(len, len)->data();
  203.  
  204.     traits::copy(__data_.data(), s, len);
  205.   }
  206. #endif
  207.  
  208. #ifndef _RWSTD_NO_MEMBER_TEMPLATES
  209.   template <class charT, class traits , class Allocator >
  210.   template <class InputIterator>
  211.   basic_string<charT, traits, Allocator>::basic_string (InputIterator first,
  212.                                                         InputIterator last,
  213.                                                         const Allocator &alloc)
  214.   : __data_(0,alloc)
  215.   {
  216.     __data_ = __getRep(1,0)->data();
  217.     replace(__data_.data(),__data_.data(),first,last);
  218.   }
  219. #endif /* _RWSTD_NO_MEMBER_TEMPLATES */
  220.  
  221.   template <class charT, class traits , class Allocator  >
  222.   basic_string<charT, traits, Allocator>::basic_string (const charT* first,
  223.                                                         const charT* last,
  224.                                                         const Allocator& alloc)
  225.   : __data_(0,alloc)
  226.   {
  227.     __data_ = __getRep(last-first,0)->data();
  228.     replace(0,0,first,last-first,0,last-first);
  229.   }
  230.  
  231. #ifdef _RWSTD_NO_DEFAULT_TEMPLATE_ARGS
  232.   template <class charT, class traits , class Allocator  >
  233.   basic_string<charT, traits, Allocator>::basic_string (const charT* first,
  234.                                                         const charT* last)
  235.   : __data_(0,Allocator())
  236.   {
  237.     __data_ = __getRep(last-first,0)->data();
  238.     replace(0,0,first,last-first,0,last-first);
  239.   }
  240. #endif /* _RWSTD_NO_DEFAULT_TEMPLATE_ARGS */
  241.   template <class charT, class traits, class Allocator >
  242.   basic_string<charT, traits, Allocator> &
  243.   basic_string<charT, traits, Allocator>::operator= (
  244.       const basic_string<charT, traits, Allocator>& str)
  245.   {
  246.     if (this != &str)
  247.     {
  248.       if (str.__pref()->__references() > 0)
  249.       {
  250.         str.__pref()->__addReference();
  251.         __unLink();
  252.         __data_ = str.__data_.data();
  253.       }
  254.       else
  255.         this->operator=(str.c_str());
  256.     }
  257.     return *this;
  258.   }
  259.  
  260.   template <class charT, class traits, class Allocator >
  261.   basic_string<charT, traits, Allocator> &
  262.   basic_string<charT, traits, Allocator>::operator= (const charT* s)
  263.   {
  264.     _RWSTD_THROW(s == 0, logic_error,
  265.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  266.          "basic_string::operator= (const charT*)").msgstr());
  267.  
  268.     if (traits::eq(*s, __eos()))
  269.     {
  270.       if (__pref()->__references() == 1)
  271.       {
  272.         __pref()->__nchars_ = 0;
  273.         traits::assign(__data_.data()[0], __eos());
  274.       }
  275.       else
  276.       {
  277.         __unLink();
  278.         __getNullRep()->__addReference();
  279.         __data_ = __getNullRep()->data();
  280.       }
  281.       return *this;
  282.     }
  283.  
  284.     return replace(0, length(), s, traits::length(s));
  285.   }
  286.  
  287.   template <class charT, class traits, class Allocator >
  288.   basic_string<charT, traits, Allocator> &
  289.   basic_string<charT, traits, Allocator>::append (
  290.       const basic_string<charT, traits, Allocator>& str,
  291.       size_type                                     pos,
  292.       size_type                                     n)
  293.   {
  294.      _RWSTD_THROW(pos > str.length(), out_of_range,
  295.       __RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
  296.         "basic_string::append(basic_string&,size_type,size_type)", pos,str.length()).msgstr());
  297.  
  298.     size_type slen = str.length() - pos;
  299.     size_type rlen = n < slen ? n : slen; 
  300.  
  301.     _RWSTD_THROW(length() >= npos - rlen, length_error,
  302.      __RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
  303.           "basic_string::append(const basic_string&,size_type,size_type)",
  304.             length(),npos-rlen).msgstr());
  305.  
  306.     replace(length(), 0, str.data(), str.length(), pos, n);
  307.  
  308.     return *this;
  309.   }
  310.  
  311.   template <class charT, class traits, class Allocator >
  312.   basic_string<charT, traits, Allocator> &
  313.   basic_string<charT, traits, Allocator>::append (
  314.       const basic_string<charT, traits, Allocator>& str)
  315.   {
  316.     _RWSTD_THROW(length() >= npos - str.length(), length_error,
  317.      __RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
  318.           "basic_string::append(const basic_string&)",length(),str.length()).msgstr());
  319.  
  320.     replace(length(), 0, str.data(), str.length());
  321.  
  322.     return *this;
  323.   }
  324.  
  325.   template <class charT, class traits, class Allocator >
  326.   basic_string<charT, traits, Allocator> &
  327.   basic_string<charT, traits, Allocator>::assign (
  328.       const basic_string<charT, traits, Allocator>& str,
  329.       size_type                                     pos,
  330.       size_type                                     n)
  331.   {
  332.     _RWSTD_THROW(pos > str.length(), out_of_range,
  333.       __RWSTD::except_msg_string(__RWSTD::__rwse_PosBeyondEndOfString,
  334.         "basic_string::assign(basic_string&,size_type,size_type)", pos,str.length()).msgstr());
  335.  
  336.     size_type slen = str.length() - pos;
  337.     size_type rlen = n < slen ? n : slen; 
  338.     return replace(0, length(), str, pos, rlen);
  339.   }
  340.  
  341.   template <class charT, class traits, class Allocator >
  342.   basic_string<charT, traits, Allocator> &
  343.   basic_string<charT, traits, Allocator>::assign (
  344.       const basic_string<charT, traits, Allocator>& str)
  345.   {
  346.     return replace(0, length(), str);
  347.   }
  348.  
  349.   template <class charT, class traits, class Allocator >
  350.   basic_string<charT, traits, Allocator> &
  351.   basic_string<charT, traits, Allocator>::insert (
  352.       size_type                                     pos1,
  353.       const basic_string<charT, traits, Allocator>& str,
  354.       size_type                                     pos2,
  355.       size_type                                     n)
  356.   {
  357.     _RWSTD_THROW(pos1 > length() || pos2 > str.length(), out_of_range,
  358.      __RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
  359.         "basic_string::insert(size_t,const basic_string&,size_t,size_t)",
  360.            pos1 > length() ? pos1:pos2,str.length()).msgstr());
  361.  
  362.     size_type slen = str.length() - pos2;
  363.     size_type rlen = n < slen ? n : slen; 
  364.  
  365.     _RWSTD_THROW( length() >= npos - rlen, length_error,
  366.      __RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
  367.         "basic_string::insert(size_t,const basic_string&,size_t,size_t)",
  368.             length(),npos - rlen).msgstr());
  369.  
  370.     return replace(pos1, 0, str, pos2, n);
  371.   }
  372.  
  373.   template <class charT, class traits, class Allocator >
  374.   basic_string<charT, traits, Allocator> &
  375.   basic_string<charT, traits, Allocator>::insert (
  376.       size_type                                     pos1,
  377.       const basic_string<charT, traits, Allocator>& str)
  378.   {
  379.     _RWSTD_THROW(pos1 > length(), out_of_range,
  380.      __RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
  381.         "basic_string::insert(size_t,const basic_string&)",pos1,length()).msgstr());
  382.  
  383.     _RWSTD_THROW(length() >= npos - str.length(),  length_error,
  384.      __RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
  385.         "basic_string::insert(size_t,const basic_string&)",
  386.           length(), npos - str.length()).msgstr());
  387.  
  388.     return replace(pos1, 0, str);
  389.   }
  390.  
  391.   template <class charT, class traits, class Allocator >
  392.   _TYPENAME basic_string<charT, traits, Allocator>::iterator 
  393.   basic_string<charT, traits, Allocator>::replace (
  394.       size_type    pos1,
  395.       size_type    n1,
  396.       const charT* cs,
  397.       size_type    cslen,
  398.       size_type    pos2,
  399.       size_type    n2)
  400.   {
  401.      _RWSTD_THROW(pos1 > length() || pos2 > cslen, out_of_range,
  402.      __RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
  403.         "basic_string::replace(size_t,size_t,char*,size_t,size_t,size_t)",
  404.            pos1 > length() ? pos1:pos2,length() > cslen ? length():cslen).msgstr());
  405.  
  406.     size_type slen = length() - pos1;
  407.     size_type xlen = n1 < slen ? n1 : slen; 
  408.     size_type clen = cslen - pos2;
  409.     size_type rlen = n2 < clen ? n2 : clen; 
  410.  
  411.     _RWSTD_THROW(length() - xlen >= npos - rlen, length_error,
  412.      __RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
  413.         "basic_string::replace(size_t,size_t,char*,size_t,size_t,size_t)",
  414.           length()-xlen,npos - rlen).msgstr());
  415.  
  416.     size_type tot = length() - xlen + rlen;  // Final string length.
  417.  
  418.     if (!tot)
  419.     {
  420.       // Special case a substitution that leaves the string empty.
  421.       __unLink();
  422.       __getNullRep()->__addReference();
  423.       __data_ = __getNullRep()->data();
  424.     }
  425.     else
  426.     {
  427.       size_type rem = length() - xlen - pos1;  // Length of bit at end of string
  428.       // Check for shared representation, insufficient capacity, 
  429.       //  or overlap copy.
  430.       if ( (__pref()->__references() > 1)
  431.            || (__getCapac() < tot)
  432.            || (cs && (cs >= data() && cs < data()+length())))
  433.       {
  434.         // Need to allocate a new reference.
  435.         __string_ref_type * temp = __getRep(tot,tot);
  436.         if (pos1) traits::copy(temp->data(), __data_.data(), pos1);
  437.         if (rlen) traits::copy(temp->data()+pos1, cs+pos2, rlen);
  438.         if (rem ) traits::copy(temp->data()+pos1+rlen, __data_.data()+pos1+n1, rem);
  439.         __unLink();
  440.         __data_ = temp->data();
  441.       }
  442.       else
  443.       {
  444.         // Current reference has enough room.
  445.         if (rem)  traits::move(__data_.data()+pos1+rlen, __data_.data()+pos1+n1, rem);
  446.         if (rlen) traits::move(__data_.data()+pos1, cs+pos2, rlen);
  447.         __data_.data()[__pref()->__nchars_ = tot] = __eos();   // Add terminating null
  448.       }
  449.     }
  450.     return __data_.data() + pos1;
  451.   }
  452.  
  453.   template <class charT, class traits , class Allocator  >
  454.   basic_string<charT, traits, Allocator> &
  455.   basic_string<charT, traits, Allocator>::replace (size_type pos,
  456.                                                    size_type n,
  457.                                                    size_type n2,
  458.                                                    charT c)
  459.   {
  460.     _RWSTD_THROW(pos > length(), out_of_range,
  461.      __RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
  462.         "basic_string:::replace(size_t,size_t,size_t,char)", pos,length()).msgstr());
  463.  
  464.     size_type slen = length() - pos;
  465.     size_type xlen = n < slen ? n : slen; 
  466.  
  467.     _RWSTD_THROW(length() - xlen >= npos - n2, length_error,
  468.      __RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
  469.           "basic_string::replace(size_t,size_t,size_t,char)",
  470.             length()-xlen,npos - n2).msgstr());
  471.  
  472.     size_type tot = length() - xlen + n2;  // Final string length.
  473.  
  474.     if (!tot)
  475.     {
  476.       // Special case a substitution that leaves the string empty.
  477.       __unLink();
  478.       __getNullRep()->__addReference();
  479.       __data_ = __getNullRep()->data();
  480.     }
  481.     else
  482.     {
  483.       size_type rem = length() - xlen - pos; // Length of bit at end of string
  484.       // Check for shared representation, insufficient capacity, 
  485.       if ( (__pref()->__references() > 1) || (__getCapac() < tot))
  486.       {
  487.         // Need to allocate a new reference.
  488.         __string_ref_type * temp = __getRep(tot,tot);
  489.         if (pos) traits::copy(temp->data(), __data_.data(), pos);
  490.         if (n2) traits::assign(temp->data()+pos, n2,c);
  491.         if (rem ) traits::copy(temp->data()+pos+n2, __data_.data()+pos+n, rem);
  492.         __unLink();
  493.         __data_ = temp->data();
  494.       }
  495.       else
  496.       {
  497.         // Current reference has enough room.
  498.         if (rem)  traits::move(__data_.data()+pos+n2, __data_.data()+pos+n, rem);
  499.         if (n2) traits::assign(__data_.data()+pos, n2, c);
  500.         __data_.data()[__pref()->__nchars_ = tot] = __eos();   // Add terminating null
  501.       }
  502.     }
  503.     return *this;
  504.   }
  505.  
  506. #ifndef _RWSTD_NO_MEMBER_TEMPLATES
  507.  
  508.   // Since we have no way of knowing how much is out there
  509.   // between first2 and last2 we have to allocate some space
  510.   // in chunks as needed and copy over characters in groups
  511.   // until we reach the end of the range.  After that 
  512.   // we can tidy things up.  We avoid this using replace_aux
  513.   // any time we have an InputIterator capable of giving us
  514.   // the distance information we need.  If InputIterator
  515.   // is really a charT* then we should never even get here.
  516.   template<class charT, class traits , class Allocator >
  517.   template<class InputIterator>
  518.   inline basic_string<charT, traits, Allocator>& 
  519.   basic_string<charT, traits, Allocator>::replace (
  520.       iterator first1, 
  521.       iterator last1,
  522.       InputIterator first2,
  523.       InputIterator last2)
  524.   {
  525.      iterator first = first1;
  526.      iterator last = last1;
  527.  
  528.      // Use a (probably)faster algorithm if possible
  529.      if (__is_bidirectional_iterator(__iterator_category(first2)))
  530.        return __replace_aux(first1,last1,first2,last2);
  531.  
  532.      _RWSTD_THROW((first > end() || last > end()),out_of_range,
  533.      __RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
  534.           "basic_string::replace(iterator,iterator,InputIterato,InputIterato)"
  535.            ,first > end() ? first : last,end()).msgstr());
  536.  
  537.      while (first2 != last2)
  538.      {
  539.      _RWSTD_THROW(first  - __data_.data() == (int)npos,length_error,
  540.      __RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
  541.           "basic_string::replace(iterator,iterator,InputIterator,InputIterator)"
  542.            ,first-__data_.data(),npos).msgstr());
  543.        if (first == last)
  544.        {
  545.          // Need to allocate a more room.
  546.          // First get the amount to increase buffer size         
  547.          size_type delta =  __RWSTD::__rw_allocation_size((value_type*)0,
  548.                                                         (size_type)0,
  549.                                                         (size_type)0);
  550.          delta = delta > 0 ? delta : 1;
  551.          size_type tot = delta + size();
  552.          // Now get new buffer
  553.          __string_ref_type * temp = __getRep(tot,tot);
  554.          // Now copy data from old to new, leaving a hole for additions
  555.          size_type current = last-begin();
  556.          traits::copy(temp->data(),__data_.data(),current);
  557.          traits::copy(temp->data()+current+delta,last,end()-last);
  558.          __unLink();
  559.          __data_ = temp->data();
  560.          first = __data_.data() + current;
  561.          last = first + delta;
  562.        }
  563.        // Copy data over
  564.        *first++ = *first2++;
  565.      }    
  566.      if (first != last)
  567.        replace(first-__data_.data(),last-first,0,(charT)' ');   // Clean up  
  568.  
  569.      return *this;
  570.   }
  571.  
  572.   // Special function for random access and bi-directional iterators
  573.   // Avoids the possibility of multiple allocations
  574.   // We still have to copy characters over one at a time.
  575.   template<class charT, class traits , class Allocator >
  576.   template<class InputIterator>
  577.   inline basic_string<charT, traits, Allocator>& 
  578.   basic_string<charT, traits, Allocator>::__replace_aux (
  579.       iterator first1, 
  580.       iterator last1,
  581.       InputIterator first2,
  582.       InputIterator last2)
  583.   {
  584.     difference_type n2 = 0;
  585.     distance(first2,last2,n2);
  586.     size_type n = last1-first1;
  587.     size_type pos = first1 - __data_.data();
  588.  
  589.     _RWSTD_THROW(pos > length(),out_of_range,
  590.      __RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
  591.           "basic_string::__replace_aux(iterator,iterator,InputIterator,InputIterator)"
  592.            ,pos,length()).msgstr());
  593.  
  594.     size_type slen = length() - pos;
  595.     size_type xlen = n < slen ? n : slen; 
  596.  
  597.    _RWSTD_THROW(length() - xlen >= npos - n2,length_error,
  598.     __RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
  599.          "basic_string::__replace_aux(iterator,iterator,InputIterator,InputIterator)"
  600.            ,length() - xlen, npos - n2).msgstr());
  601.  
  602.     size_type tot = length() - xlen + n2;  // Final string length.
  603.  
  604.     if (!tot)
  605.     {
  606.       // Special case a substitution that leaves the string empty.
  607.       __unLink();
  608.       __getNullRep()->__addReference();
  609.       __data_ = __getNullRep()->data();
  610.     }
  611.  
  612.     else
  613.     {
  614.       size_type d = 0;
  615.       size_type rem = length() - xlen - pos; // Length of bit at end of string
  616.       // Check for shared representation, insufficient capacity, 
  617.       if ( (__pref()->__references() > 1) || (__getCapac() < tot))
  618.       {
  619.         // Need to allocate a new reference.
  620.         __string_ref_type * temp = __getRep(tot,tot);
  621.         if (pos) traits::copy(temp->data(), __data_.data(), pos);
  622.         for (d = 0; d < (size_type)n2; d++)
  623.           *(temp->data()+pos+d) = *first2++;
  624.         if (rem ) 
  625.           traits::copy(temp->data()+pos+n2, __data_.data()+pos+n, rem);
  626.         __unLink();
  627.         __data_ = temp->data();
  628.       }
  629.       else
  630.       {
  631.         // Current reference has enough room.
  632.         if (rem)  
  633.           traits::move(__data_.data()+pos+n2, __data_.data()+pos+n, rem);
  634.         for (d = 0; d < (size_type)n2; d++)
  635.           *(__data_.data()+pos+d) = *first2++;
  636.         __data_.data()[__pref()->__nchars_ = tot] = __eos();   // Add terminating null
  637.       }
  638.     }
  639.     return *this;
  640.   }
  641. #endif // _RWSTD_NO_MEMBER_TEMPLATES
  642.  
  643.   template <class charT, class traits, class Allocator >
  644.   _TYPENAME basic_string<charT, traits, Allocator>::size_type
  645.   basic_string<charT, traits, Allocator>::copy (charT* s,
  646.                                                 size_type n,
  647.                                                 size_type pos) const
  648.   {
  649.     _RWSTD_THROW(pos > length(), out_of_range,
  650.      __RWSTD::except_msg_string(__RWSTD::__rwse_PosBeyondEndOfString,
  651.           "basic_string::copy(char*,size_t,size_t)",pos,length()).msgstr());
  652.  
  653.     size_type slen = length() - pos;
  654.     size_type rlen = n < slen ? n : slen;
  655.     traits::copy(s, __data_.data()+pos, rlen);
  656.     return rlen;
  657.   }
  658.   template <class charT, class traits , class Allocator  >
  659.   _TYPENAME basic_string<charT, traits, Allocator>::size_type
  660.   basic_string<charT, traits, Allocator>::find (const charT* s,
  661.                                                 size_type pos,
  662.                                                 size_type n) const
  663.   {
  664.     _RWSTD_THROW(s == 0, logic_error,
  665.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  666.           "basic_string::find(char*,size_t,size_t) const").msgstr());
  667.  
  668.     for (size_type xpos = pos; (xpos + n) <= length() ; xpos++)
  669.     {
  670.       if (!traits::compare(__data_.data()+xpos,s,n))
  671.         return xpos;
  672.     }
  673.  
  674.     return npos;
  675.   }
  676.  
  677.   template <class charT, class traits , class Allocator  >
  678.   _TYPENAME basic_string<charT, traits, Allocator>::size_type
  679.   basic_string<charT, traits, Allocator>::rfind (const charT* s,
  680.                                                  size_type pos,
  681.                                                  size_type n) const
  682.   {
  683.  
  684.     _RWSTD_THROW(s == 0, logic_error,
  685.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  686.           "basic_string::rfind(char*,size_t,size_t) const").msgstr());
  687.  
  688.     if (length() < n)
  689.       return npos;
  690.     
  691.     size_type slen = length() -n;
  692.     size_type xpos_start = slen < pos ? slen : pos; 
  693.  
  694.     for (size_type xpos = xpos_start+1; xpos != 0 ; xpos--)
  695.     {
  696.       if (!traits::compare(__data_.data()+xpos-1,s,n))
  697.         return xpos-1;
  698.     }
  699.  
  700.     return npos;
  701.   }
  702.  
  703.   template <class charT, class traits , class Allocator  >
  704.   _TYPENAME basic_string<charT, traits, Allocator>::size_type
  705.   basic_string<charT, traits, Allocator>::find_first_of (const charT* s,
  706.                                                          size_type pos,
  707.                                                          size_type n) const
  708.   {
  709.  
  710.     _RWSTD_THROW(s == 0, logic_error,
  711.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  712.           "basic_string::find_first_of(char*,size_t,size_t) const").msgstr());
  713.  
  714.     for (size_type xpos = pos; xpos < length() ; xpos++)
  715.     {
  716.       for (size_type i = 0; i < n ; i++)
  717.         if (traits::eq(__data_.data()[xpos], s[i]))
  718.           return xpos;
  719.     }
  720.  
  721.     return npos;
  722.   }
  723.   template <class charT, class traits , class Allocator  >
  724.   _TYPENAME basic_string<charT, traits, Allocator>::size_type
  725.   basic_string<charT, traits, Allocator>::find_last_of (const charT* s,
  726.                                                         size_type pos,
  727.                                                         size_type n) const
  728.   {
  729.     _RWSTD_THROW(s == 0, logic_error,
  730.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  731.           "basic_string::find_last_of(char*,size_t,size_t) const").msgstr());
  732.  
  733.     if (length())
  734.     {
  735.       size_type slen = length() -1;
  736.       size_type xpos_start = pos < slen ? pos : slen; 
  737.       for (size_type xpos = xpos_start+1; xpos != 0 ; xpos--)
  738.       {
  739.         for(size_type i = 0; i < n ; i++)
  740.           if (traits::eq(__data_.data()[xpos-1], s[i]))
  741.             return xpos-1;
  742.       } 
  743.     }
  744.     return npos;
  745.   }
  746.  
  747.   template <class charT, class traits , class Allocator  >
  748.   _TYPENAME basic_string<charT, traits, Allocator>::size_type
  749.   basic_string<charT, traits, Allocator>::find_first_not_of (const charT* s,
  750.                                                              size_type pos,
  751.                                                              size_type n) const
  752.   {
  753.     _RWSTD_THROW(s == 0, logic_error,
  754.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  755.           "basic_string::find_first_not_of(char*,size_t,size_t) const").msgstr());
  756.  
  757.     for (size_type xpos = pos; xpos < length() ; xpos++)
  758.     {
  759.       bool found = false;
  760.       for (size_type i = 0; i < n ; i++)
  761.       {
  762.         if (traits::eq(__data_.data()[xpos], s[i]))
  763.         {
  764.           found = true;
  765.           break;
  766.         }
  767.       }
  768.       if (!found)
  769.         return xpos;
  770.     }
  771.  
  772.     return npos;
  773.   }
  774.  
  775.   template <class charT, class traits , class Allocator  >
  776.   _TYPENAME basic_string<charT, traits, Allocator>::size_type
  777.   basic_string<charT, traits, Allocator>::find_last_not_of(const charT* s,
  778.                                                            size_type pos,
  779.                                                            size_type n) const
  780.   {
  781.     _RWSTD_THROW(s == 0, logic_error,
  782.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  783.           "basic_string::find_last_not_of(char*,size_t,size_t) const").msgstr());
  784.  
  785.     if (length())
  786.     {
  787.       size_type slen = length() -1;
  788.       size_type xpos_start = pos < slen ? pos : slen; 
  789.       for (size_type xpos = xpos_start+1; xpos != 0 ; xpos--)
  790.       {
  791.         bool found = false;
  792.         for (size_type i = 0; i < n ; i++)
  793.         {
  794.           if (traits::eq(__data_.data()[xpos-1], s[i]))
  795.           {
  796.             found = true;
  797.             break;
  798.           }
  799.         }
  800.         if (!found)
  801.           return xpos-1;
  802.       }
  803.     }
  804.  
  805.     return npos;
  806.   }
  807.  
  808.   template <class charT, class traits, class Allocator >
  809.   basic_string<charT, traits, Allocator>
  810.   basic_string<charT, traits, Allocator>::substr (size_type pos,
  811.                                                   size_type n) const
  812.   {
  813.     _RWSTD_THROW(pos > length(), out_of_range,
  814.      __RWSTD::except_msg_string(__RWSTD::__rwse_PosBeyondEndOfString,
  815.           "basic_string::substr(size_t,size_t) const",pos, length()).msgstr());
  816.  
  817.     size_type slen = length() -pos;
  818.     size_type rlen = n < slen ? n : slen; 
  819.     return basic_string<charT, traits, Allocator>(__data_.data()+pos, rlen);
  820.   }
  821.  
  822.   template <class charT, class traits, class Allocator >
  823.   int
  824.   basic_string<charT, traits, Allocator>::compare (
  825.       size_type pos1, size_type n1,
  826.       const basic_string<charT, traits, Allocator>& str,
  827.       size_type pos2, size_type n2) const
  828.   {
  829.     _RWSTD_THROW(pos1+n1 > length() || pos2+n2 > str.length(),out_of_range,
  830.      __RWSTD::except_msg_string(__RWSTD::__rwse_PosBeyondEndOfString,
  831.        "basic_string::compare(size_t,size_t,const basic_string&,size_t,size_t) const",
  832.          pos1+n1 > length() ?  (pos1+n1) : (pos2+n2),length() > str.length() ? length(): str.length()).msgstr());
  833.  
  834.     return compare(pos1,n1,str.c_str()+pos2,n2);
  835.   }
  836.  
  837.   template <class charT, class traits, class Allocator >
  838.   int
  839.   basic_string<charT, traits, Allocator>::compare (
  840.       size_type pos1, size_type n1,
  841.       const basic_string<charT, traits, Allocator>& str) const
  842.   {
  843.     _RWSTD_THROW(pos1+n1 > length() ,out_of_range,
  844.      __RWSTD::except_msg_string(__RWSTD::__rwse_PosBeyondEndOfString,
  845.        "basic_string::compare(size_t,size_t,const basic_string&) const",
  846.          pos1+n1 ,length()).msgstr());
  847.  
  848.     return compare(pos1,n1,str.c_str(),str.length());
  849.   }
  850.  
  851.   template <class charT, class traits , class Allocator  >
  852.   int
  853.   basic_string<charT, traits, Allocator>::compare (size_type pos,
  854.                                                    size_type n1,
  855.                                                    const charT* s,
  856.                                                    size_type n2) const
  857.   {
  858.      _RWSTD_THROW(pos > length() ,out_of_range,
  859.      __RWSTD::except_msg_string(__RWSTD::__rwse_PosBeyondEndOfString,
  860.        "basic_string::compare(size_t,size_t,const const charT*,size_t) const",
  861.          pos ,length()).msgstr());
  862.     if(length() - pos < n1)
  863.       n1 = length() - pos;
  864.     size_type rlen = n1 < n2 ? n1 : n2; 
  865.     int result = traits::compare(__data_.data()+pos, s, rlen);
  866.  
  867.     if (result == 0)
  868.       result = (n1 < n2) ? -1 : (n1 != n2);
  869.  
  870.     return result;
  871.   }
  872.  
  873.   template <class charT, class traits, class Allocator >
  874.   void basic_string<charT, traits, Allocator>::__clobber (size_type nc)
  875.   {
  876.     if (__pref()->__references() > 1 || (__getCapac() < nc))
  877.     {
  878.       __unLink();
  879.       __data_ = __getRep(nc, 0)->data();
  880.     }
  881.     else
  882.       __data_.data()[__pref()->__nchars_ = 0] = 0;
  883.   }
  884.  
  885.   template <class charT, class traits, class Allocator >
  886.   void basic_string<charT, traits, Allocator>::__clone()
  887.   {
  888.     __string_ref_type * temp = __getRep(length(), length());
  889.     traits::copy(temp->data(), data(), length());
  890.     __unLink();
  891.     __data_ = temp->data();
  892.   }
  893.  
  894.   template <class charT, class traits, class Allocator >
  895.   void basic_string<charT, traits, Allocator>::__clone (size_type nc)
  896.   {
  897.     size_type len = length();
  898.     if (len > nc) len = nc;
  899.     __string_ref_type * temp = __getRep(nc, len);
  900.     traits::copy(temp->data(), data(), length());
  901.     __unLink();
  902.     __data_ = temp->data();
  903.   }
  904.  
  905. #ifdef _RWSTD_MSC22_STATIC_INIT_BUG
  906. #undef npos
  907. #endif
  908.  
  909. //
  910. // Inserters and Extractors
  911. //
  912.  
  913. #ifndef _RW_STD_IOSTREAM
  914.  
  915.   template<class charT, class traits, class Allocator>
  916.   istream & _RWSTDExportTemplate operator>> (istream & is,
  917.                                              basic_string<charT, traits, Allocator > & s)
  918.   {
  919.     int c;
  920.  
  921.     if (!is.ipfx())
  922.       return is;
  923.  
  924.     s.erase();
  925.     c = is.rdbuf()->sbumpc();
  926.  
  927. #ifdef _RWSTD_MS40_ISTREAM_BUG
  928.     _TYPENAME size_t i =0;
  929.     _TYPENAME size_t end = s.max_size();
  930. #else
  931.     _TYPENAME Allocator::size_type i   = 0;
  932.     _TYPENAME Allocator::size_type end = s.max_size();
  933. #endif
  934.     if (is.width())
  935.       end =  (int)end < is.width() ? end : is.width(); 
  936.  
  937.     while (c != EOF && !isspace(c))
  938.     {
  939.       s.append(1,(charT)c);
  940.       i++;
  941.       if (i == end)
  942.         break;
  943.       c = is.rdbuf()->sbumpc();
  944.     }
  945.     if (c == EOF) 
  946.       is.clear(ios::eofbit | is.rdstate());      
  947.     if (!i)
  948.       is.clear(ios::failbit | is.rdstate());      
  949.  
  950.     is.width(0);
  951.     return is;
  952.   }
  953.   template<class charT, class traits, class Allocator>
  954.   ostream & _RWSTDExportTemplate operator<< (ostream & os,
  955.                                              const basic_string<charT, traits, Allocator > & s)
  956.   {
  957.     os << s.data();
  958.     return os;
  959.   }
  960.  
  961.   template<class Stream, class charT, class traits, class Allocator>
  962.   Stream& _RWSTDExportTemplate
  963.   getline (Stream& is, basic_string<charT, traits, Allocator>& str, charT delim)
  964.   {
  965.     int c;
  966.     
  967.     if (!is.ipfx(1))
  968.       return is;
  969.  
  970.     str.erase();
  971.     c = is.rdbuf()->sbumpc();
  972.  
  973. #ifdef _RWSTD_MS40_ISTREAM_BUG
  974.     size_t i = 0;
  975.     size_t end = str.max_size();
  976. #else
  977.     _TYPENAME Allocator::size_type i = 0;
  978.     _TYPENAME Allocator::size_type end = str.max_size();
  979. #endif
  980.  
  981.     while (c != EOF)
  982.     {
  983.       i++;
  984.       if ((charT)c == delim)
  985.         break;
  986.       if (i == end)
  987.       {
  988.         is.clear(ios::failbit | is.rdstate());      
  989.         break;
  990.       }
  991.         
  992.       str.append(1,(charT)c);
  993.       c = is.rdbuf()->sbumpc();
  994.     }
  995.     if (c == EOF) 
  996.       is.clear(ios::eofbit | is.rdstate());      
  997.     if (!i)
  998.       is.clear(ios::failbit | is.rdstate());      
  999.  
  1000.     is.isfx();
  1001.     return is;
  1002.   }  
  1003. #endif /* not defined _RW_STD_IOSTREAM */
  1004.  
  1005. #ifndef _RWSTD_NO_NAMESPACE
  1006. }
  1007. #endif
  1008.  
  1009. #pragma option pop
  1010. #endif /* __STRING_CC */
  1011.