home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 2000 May / PCP163A.iso / Runimage / Cbuilder4 / Include / STRING.CC < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-26  |  30.2 KB  |  871 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.  * (c) Copyright 1994, 1998 Rogue Wave Software, Inc.
  11.  * ALL RIGHTS RESERVED
  12.  *
  13.  * The software and information contained herein are proprietary to, and
  14.  * comprise valuable trade secrets of, Rogue Wave Software, Inc., which
  15.  * intends to preserve as trade secrets such software and information.
  16.  * This software is furnished pursuant to a written license agreement and
  17.  * may be used, copied, transmitted, and stored only in accordance with
  18.  * the terms of such license and with the inclusion of the above copyright
  19.  * notice.  This software and information or any other copies thereof may
  20.  * not be provided or otherwise made available to any other person.
  21.  *
  22.  * Notwithstanding any other lease or license that may pertain to, or
  23.  * accompany the delivery of, this computer software and information, the
  24.  * rights of the Government regarding its use, reproduction and disclosure
  25.  * are as set forth in Section 52.227-19 of the FARS Computer
  26.  * Software-Restricted Rights clause.
  27.  * 
  28.  * Use, duplication, or disclosure by the Government is subject to
  29.  * restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
  30.  * Technical Data and Computer Software clause at DFARS 252.227-7013.
  31.  * Contractor/Manufacturer is Rogue Wave Software, Inc.,
  32.  * P.O. Box 2328, Corvallis, Oregon 97339.
  33.  *
  34.  * This computer software and information is distributed with "restricted
  35.  * rights."  Use, duplication or disclosure is subject to restrictions as
  36.  * set forth in NASA FAR SUP 18-52.227-79 (April 1985) "Commercial
  37.  * Computer Software-Restricted Rights (April 1985)."  If the Clause at
  38.  * 18-52.227-74 "Rights in Data General" is specified in the contract,
  39.  * then the "Alternate III" clause applies.
  40.  *
  41.  **************************************************************************/
  42. #include <stdcomp.h>
  43.  
  44. //
  45. // Members for class basic_string
  46. //
  47.  
  48. #ifndef _RWSTD_NO_NAMESPACE
  49. namespace std {
  50. #endif
  51.  
  52. // basic_string<...>::__nullref
  53. #ifndef _RWSTD_NO_STATIC_DEF3
  54.   template <class charT, class traits, class Allocator >
  55.   const _TYPENAME basic_string<charT, traits, Allocator>::__null_ref_type
  56.   basic_string<charT, traits, Allocator>::__nullref;
  57. #endif
  58. // basic_string<...>::npos
  59. #if defined(__BORLANDC__) && !defined(_RTLDLL)
  60. #ifdef _RWSTD_MSC22_STATIC_INIT_BUG
  61. #define npos (size_type)-1
  62. #else
  63.   template <class charT, class traits, class Allocator >
  64.   const _TYPENAME basic_string<charT, traits, Allocator>::size_type
  65.   basic_string<charT, traits, Allocator>::npos
  66. #ifdef _RWSTD_NO_STATIC_CAST
  67.   = (_TYPENAME basic_string<charT, traits, Allocator>::size_type) -1;
  68. #else
  69.   = static_cast<_TYPENAME basic_string<charT, traits, Allocator>::size_type>(-1);
  70. #endif
  71.  
  72. #endif /* __BORLANDC__ && !_RTLDLL */
  73. #endif /*_RWSTD_MSC22_STATIC_INIT_BUG*/
  74.  
  75.   template <class charT, class traits, class Allocator >
  76.   _TYPENAME basic_string<charT, traits, Allocator>::__string_ref_type *
  77.   basic_string<charT, traits, Allocator>::__getRep (size_type capac, 
  78.                                                     size_type nchar)
  79.                                               
  80.   {                                                     
  81.     if (capac < nchar)
  82.        capac = nchar;
  83.  
  84.     if ((capac | nchar) == 0)
  85.     {
  86.       __getNullRep()->__addReference();
  87.       return __getNullRep();
  88.     }
  89.  
  90.     //
  91.     // Allocate, then initialize the __string_ref, then
  92.     // initialize each character in the buffer. 
  93.     //
  94.     __value_alloc_type va(__data_);
  95. #ifdef _RWSTD_NO_STATIC_CAST
  96.     __string_ref_type * ret = (__string_ref_type *)
  97.     va.allocate(capac + sizeof(__rep_type)/sizeof(charT) + 2,0);
  98. #else
  99.     __string_ref_type * ret = 
  100.     reinterpret_cast<__string_ref_type*>
  101.     (va.allocate(capac + sizeof(__rep_type)/sizeof(charT) + 2,0));
  102. #endif
  103.  
  104.     __ref_alloc_type(__data_).construct(ret, __string_ref_type());
  105.     charT * d = ret->data();
  106.     va.construct(d,charT());
  107.  
  108.     ret->__capacity_ = capac;
  109.     ret->__setRefCount(1);
  110.     ret->data()[ret->__nchars_ = nchar] = (charT)0; // Terminating null
  111.     return ret;
  112.   }
  113.  
  114.   template <class charT, class traits, class Allocator >
  115.   basic_string<charT, traits, Allocator>::basic_string (
  116.       const basic_string<charT, traits, Allocator> & s,
  117.       size_type pos, size_type  n,
  118.       const Allocator& alloc)
  119.     : __data_(0,alloc)
  120.   {
  121.    _RWSTD_THROW(pos > s.length(), out_of_range,
  122.     __RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
  123.        "basic_string( const basic_string&,size_type,size_type)", pos,s.length()).msgstr());
  124.  
  125.     size_type slen = s.length() - pos;
  126.     size_type rlen = n < slen ? n : slen; 
  127.     size_type nlen =  n == npos ? 0 : n;
  128.     size_type maxlen = nlen > rlen ? nlen : rlen; 
  129.     __data_            = __getRep(maxlen, rlen)->data();
  130.  
  131.     traits::copy(__data_.data(), &s.__data_.data()[pos], rlen);
  132.   }
  133.  
  134.   template <class charT, class traits, class Allocator >
  135.   void basic_string<charT, traits, Allocator>::__init_n (
  136.       size_type        n,
  137.       charT            c)
  138.   {
  139.    _RWSTD_THROW(n == npos, length_error,
  140.      __RWSTD::except_msg_string(__RWSTD::__rwse_InvalidSizeParam,
  141.         "basic_string::__init_n(size_t,char)", n,npos).msgstr());
  142.  
  143.     __data_  = __getRep(n, n)->data();
  144.  
  145.     while (n--) traits::assign(__data_.data()[n], c);
  146.   }
  147.  
  148.   template <class charT, class traits, class Allocator >
  149.   basic_string<charT, traits, Allocator>::basic_string (
  150.       const charT*     s,
  151.       size_type        n,
  152.       const Allocator& alloc)
  153.   : __data_(0,alloc)
  154.   {     
  155.     _RWSTD_THROW(s == 0, logic_error,
  156.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  157.        "basic_string( const charT*,size_type,const Allocator&)").msgstr());
  158.  
  159.     _RWSTD_THROW(n == npos, length_error,
  160.      __RWSTD::except_msg_string(__RWSTD::__rwse_InvalidSizeParam,
  161.         "basic_string( const charT*,size_type,const Allocator&)",n,npos).msgstr());
  162.  
  163.     __data_  = __getRep(n, n)->data();
  164.     traits::copy(__data_.data(), s, n);
  165.   }
  166.  
  167.   template <class charT, class traits, class Allocator >
  168.   basic_string<charT, traits, Allocator>::basic_string (
  169.       const charT*     s,
  170.       const Allocator& alloc)
  171.   : __data_(0,alloc)
  172.   {     
  173.     _RWSTD_THROW(s == 0, logic_error,
  174.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  175.         "basic_string(const charT*,const Allocator&)").msgstr());
  176.  
  177.     size_type len = traits::length(s);
  178.     __data_         = __getRep(len, len)->data();
  179.  
  180.     traits::copy(__data_.data(), s, len);
  181.   }
  182.  
  183. #ifdef _RWSTD_NO_DEFAULT_TEMPLATE_ARGS
  184.   template <class charT, class traits, class Allocator >
  185.   basic_string<charT, traits, Allocator>::basic_string (
  186.       const charT*     s,
  187.       size_type        n)
  188.   : __data_(0,Allocator())
  189.   {     
  190.     _RWSTD_THROW(s == 0, logic_error,
  191.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  192.          "basic_string( const charT*,size_type)").msgstr());
  193.  
  194.     _RWSTD_THROW(n == npos,  length_error,
  195.      __RWSTD::except_msg_string(__RWSTD::__rwse_InvalidSizeParam,
  196.         "basic_string(const charT*,size_type)",n,npos).msgstr());
  197.  
  198.     __data_  = __getRep(n, n)->data();
  199.  
  200.     traits::copy(__data_.data(), s, n);
  201.   }
  202.  
  203.   template <class charT, class traits, class Allocator >
  204.   basic_string<charT, traits, Allocator>::basic_string (
  205.       const charT*     s)
  206.   : __data_(0,Allocator())
  207.   {     
  208.     _RWSTD_THROW(s == 0, logic_error,
  209.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  210.         "basic_string(const charT*)").msgstr());
  211.  
  212.     size_type len = traits::length(s);
  213.     __data_         = __getRep(len, len)->data();
  214.  
  215.     traits::copy(__data_.data(), s, len);
  216.   }
  217. #endif
  218.  
  219.   template <class charT, class traits , class Allocator  >
  220.   basic_string<charT, traits, Allocator>::basic_string (const charT* first,
  221.                                                         const charT* last,
  222.                                                         const Allocator& alloc)
  223.   : __data_(0,alloc)
  224.   {
  225.     __data_ = __getRep(last-first,0)->data();
  226.     replace(0,0,first,last-first,0,last-first);
  227.   }
  228.  
  229. #ifdef _RWSTD_NO_DEFAULT_TEMPLATE_ARGS
  230.   template <class charT, class traits , class Allocator  >
  231.   basic_string<charT, traits, Allocator>::basic_string (const charT* first,
  232.                                                         const charT* last)
  233.   : __data_(0,Allocator())
  234.   {
  235.     __data_ = __getRep(last-first,0)->data();
  236.     replace(0,0,first,last-first,0,last-first);
  237.   }
  238. #endif /* _RWSTD_NO_DEFAULT_TEMPLATE_ARGS */
  239.   template <class charT, class traits, class Allocator >
  240.   basic_string<charT, traits, Allocator> &
  241.   basic_string<charT, traits, Allocator>::operator= (
  242.       const basic_string<charT, traits, Allocator>& str)
  243.   {
  244.     if (this != &str)
  245.     {
  246.       if (str.__pref()->__references() > 0)
  247.       {
  248.         str.__pref()->__addReference();
  249.         __unLink();
  250.         __data_ = str.__data_.data();
  251.       }
  252.       else
  253.         this->operator=(str.c_str());
  254.     }
  255.     return *this;
  256.   }
  257.  
  258.   template <class charT, class traits, class Allocator >
  259.   basic_string<charT, traits, Allocator> &
  260.   basic_string<charT, traits, Allocator>::operator= (const charT* s)
  261.   {
  262.     _RWSTD_THROW(s == 0, logic_error,
  263.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  264.          "basic_string::operator= (const charT*)").msgstr());
  265.  
  266.     if (traits::eq(*s, __eos()))
  267.     {
  268.       if (__pref()->__references() == 1)
  269.       {
  270.         __pref()->__nchars_ = 0;
  271.         traits::assign(__data_.data()[0], __eos());
  272.       }
  273.       else
  274.       {
  275.         __unLink();
  276.         __getNullRep()->__addReference();
  277.         __data_ = __getNullRep()->data();
  278.       }
  279.       return *this;
  280.     }
  281.  
  282.     return replace(0, length(), s, traits::length(s));
  283.   }
  284.  
  285.   template <class charT, class traits, class Allocator >
  286.   basic_string<charT, traits, Allocator> &
  287.   basic_string<charT, traits, Allocator>::append (
  288.       const basic_string<charT, traits, Allocator>& str,
  289.       size_type                                     pos,
  290.       size_type                                     n)
  291.   {
  292.      _RWSTD_THROW(pos > str.length(), out_of_range,
  293.       __RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
  294.         "basic_string::append(basic_string&,size_type,size_type)", pos,str.length()).msgstr());
  295.  
  296.     size_type slen = str.length() - pos;
  297.     size_type rlen = n < slen ? n : slen; 
  298.  
  299.     _RWSTD_THROW(length() >= npos - rlen, length_error,
  300.      __RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
  301.           "basic_string::append(const basic_string&,size_type,size_type)",
  302.             length(),npos-rlen).msgstr());
  303.  
  304.     replace(length(), 0, str.data(), str.length(), pos, n);
  305.  
  306.     return *this;
  307.   }
  308.  
  309.   template <class charT, class traits, class Allocator >
  310.   basic_string<charT, traits, Allocator> &
  311.   basic_string<charT, traits, Allocator>::append (
  312.       const basic_string<charT, traits, Allocator>& str)
  313.   {
  314.     _RWSTD_THROW(length() >= npos - str.length(), length_error,
  315.      __RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
  316.           "basic_string::append(const basic_string&)",length(),str.length()).msgstr());
  317.  
  318.     replace(length(), 0, str.data(), str.length());
  319.  
  320.     return *this;
  321.   }
  322.  
  323.   template <class charT, class traits, class Allocator >
  324.   basic_string<charT, traits, Allocator> &
  325.   basic_string<charT, traits, Allocator>::assign (
  326.       const basic_string<charT, traits, Allocator>& str,
  327.       size_type                                     pos,
  328.       size_type                                     n)
  329.   {
  330.     _RWSTD_THROW(pos > str.length(), out_of_range,
  331.       __RWSTD::except_msg_string(__RWSTD::__rwse_PosBeyondEndOfString,
  332.         "basic_string::assign(basic_string&,size_type,size_type)", pos,str.length()).msgstr());
  333.  
  334.     size_type slen = str.length() - pos;
  335.     size_type rlen = n < slen ? n : slen; 
  336.     return replace(0, length(), str, pos, rlen);
  337.   }
  338.  
  339.   template <class charT, class traits, class Allocator >
  340.   basic_string<charT, traits, Allocator> &
  341.   basic_string<charT, traits, Allocator>::assign (
  342.       const basic_string<charT, traits, Allocator>& str)
  343.   {
  344.     return replace(0, length(), str);
  345.   }
  346.  
  347.   template <class charT, class traits, class Allocator >
  348.   basic_string<charT, traits, Allocator> &
  349.   basic_string<charT, traits, Allocator>::insert (
  350.       size_type                                     pos1,
  351.       const basic_string<charT, traits, Allocator>& str,
  352.       size_type                                     pos2,
  353.       size_type                                     n)
  354.   {
  355.     _RWSTD_THROW(pos1 > length() || pos2 > str.length(), out_of_range,
  356.      __RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
  357.         "basic_string::insert(size_t,const basic_string&,size_t,size_t)",
  358.            pos1 > length() ? pos1:pos2,str.length()).msgstr());
  359.  
  360.     size_type slen = str.length() - pos2;
  361.     size_type rlen = n < slen ? n : slen; 
  362.  
  363.     _RWSTD_THROW( length() >= npos - rlen, length_error,
  364.      __RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
  365.         "basic_string::insert(size_t,const basic_string&,size_t,size_t)",
  366.             length(),npos - rlen).msgstr());
  367.  
  368.     return replace(pos1, 0, str, pos2, n);
  369.   }
  370.  
  371.   template <class charT, class traits, class Allocator >
  372.   basic_string<charT, traits, Allocator> &
  373.   basic_string<charT, traits, Allocator>::insert (
  374.       size_type                                     pos1,
  375.       const basic_string<charT, traits, Allocator>& str)
  376.   {
  377.     _RWSTD_THROW(pos1 > length(), out_of_range,
  378.      __RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
  379.         "basic_string::insert(size_t,const basic_string&)",pos1,length()).msgstr());
  380.  
  381.     _RWSTD_THROW(length() >= npos - str.length(),  length_error,
  382.      __RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
  383.         "basic_string::insert(size_t,const basic_string&)",
  384.           length(), npos - str.length()).msgstr());
  385.  
  386.     return replace(pos1, 0, str);
  387.   }
  388.  
  389.   template <class charT, class traits, class Allocator >
  390.   _TYPENAME basic_string<charT, traits, Allocator>::iterator 
  391.   basic_string<charT, traits, Allocator>::replace (
  392.       size_type    pos1,
  393.       size_type    n1,
  394.       const charT* cs,
  395.       size_type    cslen,
  396.       size_type    pos2,
  397.       size_type    n2)
  398.   {
  399.      _RWSTD_THROW(pos1 > length() || pos2 > cslen, out_of_range,
  400.      __RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
  401.         "basic_string::replace(size_t,size_t,char*,size_t,size_t,size_t)",
  402.            pos1 > length() ? pos1:pos2,length() > cslen ? length():cslen).msgstr());
  403.  
  404.     size_type slen = length() - pos1;
  405.     size_type xlen = n1 < slen ? n1 : slen; 
  406.     size_type clen = cslen - pos2;
  407.     size_type rlen = n2 < clen ? n2 : clen; 
  408.  
  409.     _RWSTD_THROW(length() - xlen >= npos - rlen, length_error,
  410.      __RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
  411.         "basic_string::replace(size_t,size_t,char*,size_t,size_t,size_t)",
  412.           length()-xlen,npos - rlen).msgstr());
  413.  
  414.     size_type tot = length() - xlen + rlen;  // Final string length.
  415.  
  416.     if (!tot)
  417.     {
  418.       // Special case a substitution that leaves the string empty.
  419.       __unLink();
  420.       __getNullRep()->__addReference();
  421.       __data_ = __getNullRep()->data();
  422.     }
  423.     else
  424.     {
  425.       size_type rem = length() - xlen - pos1;  // Length of bit at end of string
  426.       // Check for shared representation, insufficient capacity, 
  427.       //  or overlap copy.
  428.       if ( (__pref()->__references() > 1)
  429.            || (__getCapac() < tot)
  430.            || (cs && (cs >= data() && cs < data()+length())))
  431.       {
  432.         // Need to allocate a new reference.
  433.         __string_ref_type * temp = __getRep(tot,tot);
  434.         if (pos1) traits::copy(temp->data(), __data_.data(), pos1);
  435.         if (rlen) traits::copy(temp->data()+pos1, cs+pos2, rlen);
  436.         if (rem ) traits::copy(temp->data()+pos1+rlen, __data_.data()+pos1+n1, rem);
  437.         __unLink();
  438.         __data_ = temp->data();
  439.       }
  440.       else
  441.       {
  442.         // Current reference has enough room.
  443.         if (rem)  traits::move(__data_.data()+pos1+rlen, __data_.data()+pos1+n1, rem);
  444.         if (rlen) traits::move(__data_.data()+pos1, cs+pos2, rlen);
  445.         __data_.data()[__pref()->__nchars_ = tot] = __eos();   // Add terminating null
  446.       }
  447.     }
  448.     return __data_.data() + pos1;
  449.   }
  450.  
  451.   template <class charT, class traits , class Allocator  >
  452.   basic_string<charT, traits, Allocator> &
  453.   basic_string<charT, traits, Allocator>::replace (size_type pos,
  454.                                                    size_type n,
  455.                                                    size_type n2,
  456.                                                    charT c)
  457.   {
  458.     _RWSTD_THROW(pos > length(), out_of_range,
  459.      __RWSTD::except_msg_string(__RWSTD::__rwse_StringIndexOutOfRange,
  460.         "basic_string:::replace(size_t,size_t,size_t,char)", pos,length()).msgstr());
  461.  
  462.     size_type slen = length() - pos;
  463.     size_type xlen = n < slen ? n : slen; 
  464.  
  465.     _RWSTD_THROW(length() - xlen >= npos - n2, length_error,
  466.      __RWSTD::except_msg_string(__RWSTD::__rwse_ResultLenInvalid,
  467.           "basic_string::replace(size_t,size_t,size_t,char)",
  468.             length()-xlen,npos - n2).msgstr());
  469.  
  470.     size_type tot = length() - xlen + n2;  // Final string length.
  471.  
  472.     if (!tot)
  473.     {
  474.       // Special case a substitution that leaves the string empty.
  475.       __unLink();
  476.       __getNullRep()->__addReference();
  477.       __data_ = __getNullRep()->data();
  478.     }
  479.     else
  480.     {
  481.       size_type rem = length() - xlen - pos; // Length of bit at end of string
  482.       // Check for shared representation, insufficient capacity, 
  483.       if ( (__pref()->__references() > 1) || (__getCapac() < tot))
  484.       {
  485.         // Need to allocate a new reference.
  486.         __string_ref_type * temp = __getRep(tot,tot);
  487.         if (pos) traits::copy(temp->data(), __data_.data(), pos);
  488.         if (n2) traits::assign(temp->data()+pos, n2,c);
  489.         if (rem ) traits::copy(temp->data()+pos+n2, __data_.data()+pos+n, rem);
  490.         __unLink();
  491.         __data_ = temp->data();
  492.       }
  493.       else
  494.       {
  495.         // Current reference has enough room.
  496.         if (rem)  traits::move(__data_.data()+pos+n2, __data_.data()+pos+n, rem);
  497.         if (n2) traits::assign(__data_.data()+pos, n2, c);
  498.         __data_.data()[__pref()->__nchars_ = tot] = __eos();   // Add terminating null
  499.       }
  500.     }
  501.     return *this;
  502.   }
  503.  
  504.   template <class charT, class traits, class Allocator >
  505.   _TYPENAME basic_string<charT, traits, Allocator>::size_type
  506.   basic_string<charT, traits, Allocator>::copy (charT* s,
  507.                                                 size_type n,
  508.                                                 size_type pos) const
  509.   {
  510.     _RWSTD_THROW(pos > length(), out_of_range,
  511.      __RWSTD::except_msg_string(__RWSTD::__rwse_PosBeyondEndOfString,
  512.           "basic_string::copy(char*,size_t,size_t)",pos,length()).msgstr());
  513.  
  514.     size_type slen = length() - pos;
  515.     size_type rlen = n < slen ? n : slen;
  516.     traits::copy(s, __data_.data()+pos, rlen);
  517.     return rlen;
  518.   }
  519.   template <class charT, class traits , class Allocator  >
  520.   _TYPENAME basic_string<charT, traits, Allocator>::size_type
  521.   basic_string<charT, traits, Allocator>::find (const charT* s,
  522.                                                 size_type pos,
  523.                                                 size_type n) const
  524.   {
  525.     _RWSTD_THROW(s == 0, logic_error,
  526.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  527.           "basic_string::find(char*,size_t,size_t) const").msgstr());
  528.  
  529.     for (size_type xpos = pos; (xpos + n) <= length() ; xpos++)
  530.     {
  531.       if (!traits::compare(__data_.data()+xpos,s,n))
  532.         return xpos;
  533.     }
  534.  
  535.     return npos;
  536.   }
  537.  
  538.   template <class charT, class traits , class Allocator  >
  539.   _TYPENAME basic_string<charT, traits, Allocator>::size_type
  540.   basic_string<charT, traits, Allocator>::rfind (const charT* s,
  541.                                                  size_type pos,
  542.                                                  size_type n) const
  543.   {
  544.  
  545.     _RWSTD_THROW(s == 0, logic_error,
  546.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  547.           "basic_string::rfind(char*,size_t,size_t) const").msgstr());
  548.  
  549.     if (length() < n)
  550.       return npos;
  551.     
  552.     size_type slen = length() -n;
  553.     size_type xpos_start = slen < pos ? slen : pos; 
  554.  
  555.     for (size_type xpos = xpos_start+1; xpos != 0 ; xpos--)
  556.     {
  557.       if (!traits::compare(__data_.data()+xpos-1,s,n))
  558.         return xpos-1;
  559.     }
  560.  
  561.     return npos;
  562.   }
  563.  
  564.   template <class charT, class traits , class Allocator  >
  565.   _TYPENAME basic_string<charT, traits, Allocator>::size_type
  566.   basic_string<charT, traits, Allocator>::find_first_of (const charT* s,
  567.                                                          size_type pos,
  568.                                                          size_type n) const
  569.   {
  570.  
  571.     _RWSTD_THROW(s == 0, logic_error,
  572.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  573.           "basic_string::find_first_of(char*,size_t,size_t) const").msgstr());
  574.  
  575.     for (size_type xpos = pos; xpos < length() ; xpos++)
  576.     {
  577.       for (size_type i = 0; i < n ; i++)
  578.         if (traits::eq(__data_.data()[xpos], s[i]))
  579.           return xpos;
  580.     }
  581.  
  582.     return npos;
  583.   }
  584.   template <class charT, class traits , class Allocator  >
  585.   _TYPENAME basic_string<charT, traits, Allocator>::size_type
  586.   basic_string<charT, traits, Allocator>::find_last_of (const charT* s,
  587.                                                         size_type pos,
  588.                                                         size_type n) const
  589.   {
  590.     _RWSTD_THROW(s == 0, logic_error,
  591.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  592.           "basic_string::find_last_of(char*,size_t,size_t) const").msgstr());
  593.  
  594.     if (length())
  595.     {
  596.       size_type slen = length() -1;
  597.       size_type xpos_start = pos < slen ? pos : slen; 
  598.       for (size_type xpos = xpos_start+1; xpos != 0 ; xpos--)
  599.       {
  600.         for(size_type i = 0; i < n ; i++)
  601.           if (traits::eq(__data_.data()[xpos-1], s[i]))
  602.             return xpos-1;
  603.       } 
  604.     }
  605.     return npos;
  606.   }
  607.  
  608.   template <class charT, class traits , class Allocator  >
  609.   _TYPENAME basic_string<charT, traits, Allocator>::size_type
  610.   basic_string<charT, traits, Allocator>::find_first_not_of (const charT* s,
  611.                                                              size_type pos,
  612.                                                              size_type n) const
  613.   {
  614.     _RWSTD_THROW(s == 0, logic_error,
  615.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  616.           "basic_string::find_first_not_of(char*,size_t,size_t) const").msgstr());
  617.  
  618.     for (size_type xpos = pos; xpos < length() ; xpos++)
  619.     {
  620.       bool found = false;
  621.       for (size_type i = 0; i < n ; i++)
  622.       {
  623.         if (traits::eq(__data_.data()[xpos], s[i]))
  624.         {
  625.           found = true;
  626.           break;
  627.         }
  628.       }
  629.       if (!found)
  630.         return xpos;
  631.     }
  632.  
  633.     return npos;
  634.   }
  635.  
  636.   template <class charT, class traits , class Allocator  >
  637.   _TYPENAME basic_string<charT, traits, Allocator>::size_type
  638.   basic_string<charT, traits, Allocator>::find_last_not_of(const charT* s,
  639.                                                            size_type pos,
  640.                                                            size_type n) const
  641.   {
  642.     _RWSTD_THROW(s == 0, logic_error,
  643.      __RWSTD::except_msg_string(__RWSTD::__rwse_UnexpectedNullPtr,
  644.           "basic_string::find_last_not_of(char*,size_t,size_t) const").msgstr());
  645.  
  646.     if (length())
  647.     {
  648.       size_type slen = length() -1;
  649.       size_type xpos_start = pos < slen ? pos : slen; 
  650.       for (size_type xpos = xpos_start+1; xpos != 0 ; xpos--)
  651.       {
  652.         bool found = false;
  653.         for (size_type i = 0; i < n ; i++)
  654.         {
  655.           if (traits::eq(__data_.data()[xpos-1], s[i]))
  656.           {
  657.             found = true;
  658.             break;
  659.           }
  660.         }
  661.         if (!found)
  662.           return xpos-1;
  663.       }
  664.     }
  665.  
  666.     return npos;
  667.   }
  668.  
  669.   template <class charT, class traits, class Allocator >
  670.   basic_string<charT, traits, Allocator>
  671.   basic_string<charT, traits, Allocator>::substr (size_type pos,
  672.                                                   size_type n) const
  673.   {
  674.     _RWSTD_THROW(pos > length(), out_of_range,
  675.      __RWSTD::except_msg_string(__RWSTD::__rwse_PosBeyondEndOfString,
  676.           "basic_string::substr(size_t,size_t) const",pos, length()).msgstr());
  677.  
  678.     size_type slen = length() -pos;
  679.     size_type rlen = n < slen ? n : slen; 
  680.     return basic_string<charT, traits, Allocator>(__data_.data()+pos, rlen);
  681.   }
  682.  
  683.   template <class charT, class traits, class Allocator >
  684.   int
  685.   basic_string<charT, traits, Allocator>::compare (
  686.       size_type pos1, size_type n1,
  687.       const basic_string<charT, traits, Allocator>& str,
  688.       size_type pos2, size_type n2) const
  689.   {
  690.     _RWSTD_THROW(pos1+n1 > length() || pos2+n2 > str.length(),out_of_range,
  691.      __RWSTD::except_msg_string(__RWSTD::__rwse_PosBeyondEndOfString,
  692.        "basic_string::compare(size_t,size_t,const basic_string&,size_t,size_t) const",
  693.          pos1+n1 > length() ?  (pos1+n1) : (pos2+n2),length() > str.length() ? length(): str.length()).msgstr());
  694.  
  695.     return compare(pos1,n1,str.c_str()+pos2,n2);
  696.   }
  697.  
  698.   template <class charT, class traits, class Allocator >
  699.   int
  700.   basic_string<charT, traits, Allocator>::compare (
  701.       size_type pos1, size_type n1,
  702.       const basic_string<charT, traits, Allocator>& str) const
  703.   {
  704.     _RWSTD_THROW(pos1+n1 > length() ,out_of_range,
  705.      __RWSTD::except_msg_string(__RWSTD::__rwse_PosBeyondEndOfString,
  706.        "basic_string::compare(size_t,size_t,const basic_string&) const",
  707.          pos1+n1 ,length()).msgstr());
  708.  
  709.     return compare(pos1,n1,str.c_str(),str.length());
  710.   }
  711.  
  712.   template <class charT, class traits , class Allocator  >
  713.   int
  714.   basic_string<charT, traits, Allocator>::compare (size_type pos,
  715.                                                    size_type n1,
  716.                                                    const charT* s,
  717.                                                    size_type n2) const
  718.   {
  719.      _RWSTD_THROW(pos > length() ,out_of_range,
  720.      __RWSTD::except_msg_string(__RWSTD::__rwse_PosBeyondEndOfString,
  721.        "basic_string::compare(size_t,size_t,const const charT*,size_t) const",
  722.          pos ,length()).msgstr());
  723.     if(length() - pos < n1)
  724.       n1 = length() - pos;
  725.     size_type rlen = n1 < n2 ? n1 : n2; 
  726.     int result = traits::compare(__data_.data()+pos, s, rlen);
  727.  
  728.     if (result == 0)
  729.       result = (n1 < n2) ? -1 : (n1 != n2);
  730.  
  731.     return result;
  732.   }
  733.  
  734.   template <class charT, class traits, class Allocator >
  735.   void basic_string<charT, traits, Allocator>::__clobber (size_type nc)
  736.   {
  737.     if (__pref()->__references() > 1 || (__getCapac() < nc))
  738.     {
  739.       __unLink();
  740.       __data_ = __getRep(nc, 0)->data();
  741.     }
  742.     else
  743.       __data_.data()[__pref()->__nchars_ = 0] = 0;
  744.   }
  745.  
  746.   template <class charT, class traits, class Allocator >
  747.   void basic_string<charT, traits, Allocator>::__clone()
  748.   {
  749.     __string_ref_type * temp = __getRep(length(), length());
  750.     traits::copy(temp->data(), data(), length());
  751.     __unLink();
  752.     __data_ = temp->data();
  753.   }
  754.  
  755.   template <class charT, class traits, class Allocator >
  756.   void basic_string<charT, traits, Allocator>::__clone (size_type nc)
  757.   {
  758.     size_type len = length();
  759.     if (len > nc) len = nc;
  760.     __string_ref_type * temp = __getRep(nc, len);
  761.     traits::copy(temp->data(), data(), length());
  762.     __unLink();
  763.     __data_ = temp->data();
  764.   }
  765.  
  766. #ifdef _RWSTD_MSC22_STATIC_INIT_BUG
  767. #undef npos
  768. #endif
  769.  
  770. //
  771. // Inserters and Extractors
  772. //
  773.  
  774. #ifndef _RW_STD_IOSTREAM
  775.  
  776.   template<class charT, class traits, class Allocator>
  777.   istream & _RWSTDExportTemplate operator>> (istream & is,
  778.                                              basic_string<charT, traits, Allocator > & s)
  779.   {
  780.     int c;
  781.  
  782.     if (!is.ipfx())
  783.       return is;
  784.  
  785.     s.erase();
  786.     c = is.rdbuf()->sbumpc();
  787.  
  788. #ifdef _RWSTD_MS40_ISTREAM_BUG
  789.     _TYPENAME size_t i =0;
  790.     _TYPENAME size_t end = s.max_size();
  791. #else
  792.     _TYPENAME Allocator::size_type i   = 0;
  793.     _TYPENAME Allocator::size_type end = s.max_size();
  794. #endif
  795.     if (is.width())
  796.       end =  (int)end < is.width() ? end : is.width(); 
  797.  
  798.     while (c != EOF && !isspace(c))
  799.     {
  800.       s.append(1,(charT)c);
  801.       i++;
  802.       if (i == end)
  803.         break;
  804.       c = is.rdbuf()->sbumpc();
  805.     }
  806.     if (c == EOF) 
  807.       is.clear(ios::eofbit | is.rdstate());      
  808.     if (!i)
  809.       is.clear(ios::failbit | is.rdstate());      
  810.  
  811.     is.width(0);
  812.     return is;
  813.   }
  814.   template<class charT, class traits, class Allocator>
  815.   ostream & _RWSTDExportTemplate operator<< (ostream & os,
  816.                                              const basic_string<charT, traits, Allocator > & s)
  817.   {
  818.     os << s.data();
  819.     return os;
  820.   }
  821.  
  822.   template<class Stream, class charT, class traits, class Allocator>
  823.   Stream& _RWSTDExportTemplate
  824.   getline (Stream& is, basic_string<charT, traits, Allocator>& str, charT delim)
  825.   {
  826.     int c;
  827.     
  828.     if (!is.ipfx(1))
  829.       return is;
  830.  
  831.     str.erase();
  832.     c = is.rdbuf()->sbumpc();
  833.  
  834. #ifdef _RWSTD_MS40_ISTREAM_BUG
  835.     size_t i = 0;
  836.     size_t end = str.max_size();
  837. #else
  838.     _TYPENAME Allocator::size_type i = 0;
  839.     _TYPENAME Allocator::size_type end = str.max_size();
  840. #endif
  841.  
  842.     while (c != EOF)
  843.     {
  844.       i++;
  845.       if ((charT)c == delim)
  846.         break;
  847.       if (i == end)
  848.       {
  849.         is.clear(ios::failbit | is.rdstate());      
  850.         break;
  851.       }
  852.         
  853.       str.append(1,(charT)c);
  854.       c = is.rdbuf()->sbumpc();
  855.     }
  856.     if (c == EOF) 
  857.       is.clear(ios::eofbit | is.rdstate());      
  858.     if (!i)
  859.       is.clear(ios::failbit | is.rdstate());      
  860.  
  861.     is.isfx();
  862.     return is;
  863.   }  
  864. #endif /* not defined _RW_STD_IOSTREAM */
  865.  
  866. #ifndef _RWSTD_NO_NAMESPACE
  867. }
  868. #endif
  869. #pragma option pop
  870. #endif /* __STRING_CC */
  871.