home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1997 May / VPR9705A.ISO / VPR_DATA / PROGRAM / CBTRIAL / SETUP / DATA.Z / STRING.CC < prev    next >
C/C++ Source or Header  |  1997-02-14  |  23KB  |  742 lines

  1. /***************************************************************************
  2.  *
  3.  * string.cc - Definitions for the Standard Library string classes
  4.  *
  5.  * $Id: string.cc,v 1.76 1995/09/29 22:28:50 smithey Exp $
  6.  *
  7.  ***************************************************************************
  8.  *
  9.  * (c) Copyright 1994, 1995 Rogue Wave Software, Inc.
  10.  * ALL RIGHTS RESERVED
  11.  *
  12.  * The software and information contained herein are proprietary to, and
  13.  * comprise valuable trade secrets of, Rogue Wave Software, Inc., which
  14.  * intends to preserve as trade secrets such software and information.
  15.  * This software is furnished pursuant to a written license agreement and
  16.  * may be used, copied, transmitted, and stored only in accordance with
  17.  * the terms of such license and with the inclusion of the above copyright
  18.  * notice.  This software and information or any other copies thereof may
  19.  * not be provided or otherwise made available to any other person.
  20.  *
  21.  * Notwithstanding any other lease or license that may pertain to, or
  22.  * accompany the delivery of, this computer software and information, the
  23.  * rights of the Government regarding its use, reproduction and disclosure
  24.  * are as set forth in Section 52.227-19 of the FARS Computer
  25.  * Software-Restricted Rights clause.
  26.  * 
  27.  * Use, duplication, or disclosure by the Government is subject to
  28.  * restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
  29.  * Technical Data and Computer Software clause at DFARS 252.227-7013.
  30.  * Contractor/Manufacturer is Rogue Wave Software, Inc.,
  31.  * P.O. Box 2328, Corvallis, Oregon 97339.
  32.  *
  33.  * This computer software and information is distributed with "restricted
  34.  * rights."  Use, duplication or disclosure is subject to restrictions as
  35.  * set forth in NASA FAR SUP 18-52.227-79 (April 1985) "Commercial
  36.  * Computer Software-Restricted Rights (April 1985)."  If the Clause at
  37.  * 18-52.227-74 "Rights in Data General" is specified in the contract,
  38.  * then the "Alternate III" clause applies.
  39.  *
  40.  **************************************************************************/
  41.  
  42. #ifndef RWSTD_NO_NAMESPACE
  43. namespace std {
  44. #endif
  45.  
  46. //
  47. // Members for class string_ref
  48. //
  49. #ifndef RWSTD_NO_STATIC_DEF3
  50. template <class charT, class traits, class Allocator >
  51. const null_string_ref_rep<charT, traits, Allocator>
  52. basic_string<charT, traits, Allocator>::nullref 
  53.   = null_string_ref_rep<charT, traits, Allocator>();
  54. #endif
  55.  
  56. //
  57. // Members for class basic_string
  58. //
  59.  
  60.  
  61. template <class charT, class traits, class Allocator >
  62. const basic_string<charT, traits, Allocator>::size_type
  63. basic_string<charT, traits, Allocator>::npos
  64.   = (basic_string<charT, traits, Allocator>::size_type) -1;
  65.  
  66.  
  67. template <class charT, class traits, class Allocator >
  68. string_ref<charT, traits, Allocator> *
  69. basic_string<charT, traits, Allocator>::getRep (size_type capac, 
  70.                                                 size_type nchar,
  71.                                                 Allocator& alloc)
  72. {                             
  73.   if ((capac | nchar) == 0)
  74.   {
  75.     getNullRep()->addReference();
  76.     return getNullRep();
  77.   }
  78.  
  79.   string_ref<charT, traits, Allocator> * ret = 
  80.     (string_ref<charT, traits, Allocator> *) alloc.allocate(
  81.       (capac+1)*sizeof(charT) + sizeof(string_ref_rep<Allocator>));
  82.   //
  83.   // Initialize the string_ref, then
  84.   // initialize each character in the buffer.  Allocator had better
  85.   // provide a placement new for this purpose, if appropriate.
  86.   //
  87.   new (ret) string_ref<charT,traits,Allocator>;
  88.   charT * d = ret->data();
  89.   for (size_type i = 0; i <= capac; i++, d++)
  90.     new (d) charT;
  91.  
  92.   ret->capacity_ = capac;
  93.   ret->setRefCount(1);
  94.   ret->data()[ret->nchars_ = nchar] = traits::eos(); // Terminating null
  95.  
  96.   return ret;
  97. }
  98.  
  99. template <class charT, class traits, class Allocator >
  100. basic_string<charT, traits, Allocator>::basic_string (
  101.   const basic_string<charT, traits, Allocator> & s,
  102.   size_type                                      pos, 
  103.   size_type                                      n,
  104.   const Allocator&                               alloc)
  105. {                             
  106.     RWSTD_THROW(pos > s.length(), out_of_range, rwse_PosBeyondEndOfString);
  107.  
  108.     size_type rlen   = min(n, s.length() - pos);
  109.     size_type maxlen = max(n == npos ? 0 : n, rlen);
  110.     alloc_           = alloc;
  111.     data_            = getRep(maxlen, rlen, alloc_)->data();
  112.  
  113.     traits::copy(data_, &s.data_[pos], rlen);
  114. }
  115.  
  116. template <class charT, class traits, class Allocator >
  117. basic_string<charT, traits, Allocator>::basic_string (
  118.   const charT*     s,
  119.   size_type        n,
  120.   const Allocator& alloc)
  121. {                               
  122.     RWSTD_THROW(s == 0, logic_error, rwse_UnexpectedNullPtr);
  123.  
  124.     alloc_ = alloc;
  125.     data_  = getRep(n, n, alloc_)->data();
  126.  
  127.     traits::copy(data_, s, n);
  128. }
  129.  
  130. template <class charT, class traits, class Allocator >
  131. basic_string<charT, traits, Allocator>::basic_string (
  132.   const charT*     s,
  133.   const Allocator& alloc)
  134. {                             
  135.     RWSTD_THROW(s == 0, logic_error, rwse_UnexpectedNullPtr);
  136.  
  137.     size_type len = traits::length(s);
  138.     alloc_        = alloc;
  139.     data_         = getRep(len, len, alloc_)->data();
  140.  
  141.     traits::copy(data_, s, len);
  142. }
  143.  
  144. template <class charT, class traits, class Allocator >
  145. basic_string<charT, traits, Allocator>::basic_string (
  146.   size_type        n,
  147.   charT            c,
  148.   const Allocator& alloc)
  149. {
  150.     RWSTD_THROW(n == npos, length_error, rwse_InvalidSizeParam);
  151.  
  152.     alloc_ = alloc;
  153.     data_  = getRep(n, n, alloc_)->data();
  154.  
  155.     while (n--) traits::assign(data_[n], c);
  156. }
  157.  
  158. template <class charT, class traits, class Allocator >
  159. basic_string<charT, traits, Allocator> &
  160. basic_string<charT, traits, Allocator>::operator= (
  161.   const basic_string<charT, traits, Allocator>& str)
  162. {
  163.     str.pref()->addReference();
  164.     pref()->unLink(alloc_);
  165.     data_ = str.data_;
  166.     return *this;
  167. }
  168.  
  169. template <class charT, class traits, class Allocator >
  170. basic_string<charT, traits, Allocator> &
  171. basic_string<charT, traits, Allocator>::operator= (const charT* s)
  172. {
  173.     RWSTD_THROW(s == 0, logic_error, rwse_UnexpectedNullPtr);
  174.  
  175.     if (traits::eq(*s, eos()))
  176.     {
  177.         if (pref()->references() == 1)
  178.         {
  179.             pref()->nchars_ = 0;
  180.             traits::assign(data_[0], eos());
  181.         }
  182.         else
  183.         {
  184.             pref()->unLink(alloc_);
  185.             getNullRep()->addReference();
  186.             data_ = getNullRep()->data();
  187.         }
  188.         return *this;
  189.     }
  190.  
  191.     return replace(0, length(), s, traits::length(s));
  192. }
  193.  
  194. template <class charT, class traits, class Allocator >
  195. basic_string<charT, traits, Allocator> &
  196. basic_string<charT, traits, Allocator>::append (
  197.   const basic_string<charT, traits, Allocator>& str,
  198.   size_type                                     pos,
  199.   size_type                                     n)
  200. {
  201.     RWSTD_THROW(pos > str.length(), out_of_range, rwse_PosBeyondEndOfString);
  202.  
  203.     size_type rlen = min(n, str.length() - pos);
  204.  
  205.     RWSTD_THROW(length() >= npos - rlen,
  206.                 length_error,
  207.                 rwse_ResultLenInvalid);
  208.  
  209.     replace(length(), 0, str.data(), str.length(), pos, n);
  210.  
  211.     return *this;
  212. }
  213.  
  214. template <class charT, class traits, class Allocator >
  215. basic_string<charT, traits, Allocator> &
  216. basic_string<charT, traits, Allocator>::assign (
  217.   const basic_string<charT, traits, Allocator>& str,
  218.   size_type                                     pos,
  219.   size_type                                     n)
  220. {
  221.     RWSTD_THROW(pos > str.length(), out_of_range, rwse_PosBeyondEndOfString);
  222.     size_type rlen = min(n, str.length() - pos);
  223.     return replace(0, length(), str, pos, rlen);
  224. }
  225.  
  226. template <class charT, class traits, class Allocator >
  227. basic_string<charT, traits, Allocator> &
  228. basic_string<charT, traits, Allocator>::insert (
  229.   size_type                                     pos1,
  230.   const basic_string<charT, traits, Allocator>& str,
  231.   size_type                                     pos2,
  232.   size_type                                     n)
  233. {
  234.   RWSTD_THROW(pos1 > length() || pos2 > str.length(),
  235.               out_of_range,
  236.               rwse_StringIndexOutOfRange);
  237.   size_type rlen = min(n, str.length() - pos2);
  238.   RWSTD_THROW(length() >= npos - rlen, length_error, rwse_ResultLenInvalid);
  239.   return replace(pos1, 0, str, pos2, n);
  240. }
  241.  
  242. template <class charT, class traits, class Allocator >
  243. basic_string<charT, traits, Allocator>::iterator 
  244. basic_string<charT, traits, Allocator>::replace (
  245.   size_type    pos1,
  246.   size_type    n1,
  247.   const charT* cs,
  248.   size_type    cslen,
  249.   size_type    pos2,
  250.   size_type    n2)
  251. {
  252.   RWSTD_THROW(pos1 > length() || pos2 > cslen,
  253.               out_of_range,
  254.               rwse_StringIndexOutOfRange);
  255.  
  256.   size_type xlen = min(n1, length() - pos1);
  257.   size_type rlen = min(n2, cslen - pos2);
  258.  
  259.   RWSTD_THROW(length() - xlen >= (size_type)npos - rlen,
  260.               length_error,
  261.               rwse_ResultLenInvalid );
  262.  
  263.   size_type tot = length() - xlen + rlen;  // Final string length
  264.  
  265.   if (!tot)
  266.   {
  267.     //
  268.     // Special case a substitution that leaves the string empty.
  269.     //
  270.     pref()->unLink(alloc_);
  271.     getNullRep()->addReference();
  272.     data_ = getNullRep()->data();
  273.   }
  274.   else
  275.   {
  276.     size_type rem = length() - xlen - pos1;  // Length of bit at end of string
  277.     //
  278.     // Check for shared representation, insufficient capacity, or overlap copy.
  279.     //
  280. #ifdef RWSTD_MULTI_THREAD
  281.     RWSTDGuard guard(pref()->mutex_);
  282. #endif
  283.     if ( (pref()->references() > 1)
  284.       || (getCapac() < tot)
  285.       || (cs && (cs >= data() && cs < data()+length())))
  286.     {
  287.         //
  288.         // Need to allocate a new reference.
  289.         //
  290.         string_ref<charT, traits, Allocator> * temp
  291.           = getRep(tot, tot, alloc_);
  292.         if (pos1) traits::copy(temp->data(), data_, pos1);
  293.         if (rlen) traits::copy(temp->data()+pos1, cs+pos2, rlen);
  294.         if (rem ) traits::copy(temp->data()+pos1+rlen, data_+pos1+n1, rem);
  295.         pref()->unSafeunLink(alloc_);
  296.         data_ = temp->data();
  297.       }
  298.       else
  299.       {
  300.         //
  301.         // Current reference has enough room.
  302.         //
  303.         if (rem)  traits::move(data_+pos1+rlen, data_+pos1+n1, rem);
  304.         if (rlen) traits::move(data_+pos1, cs+pos2, rlen);
  305.         data_[pref()->nchars_ = tot] = eos();    // Add terminating null
  306.       }
  307.   }
  308.   return data_ + pos1;
  309. }
  310.  
  311. template <class charT, class traits, class Allocator >
  312. void
  313. basic_string<charT, traits, Allocator>::resize (size_type n, charT c)
  314. {
  315.     RWSTD_THROW(n == npos, length_error, rwse_InvalidSizeParam);
  316.  
  317.     if (n < length())
  318.         remove(n);
  319.     else if (n > length())
  320.         append(n - length(), c);
  321. }
  322.  
  323. template <class charT, class traits, class Allocator >
  324. basic_string<charT, traits, Allocator>::size_type
  325. basic_string<charT, traits, Allocator>::copy (charT* s,
  326.                                               size_type n,
  327.                                               size_type pos)
  328. {
  329.     RWSTD_THROW(pos > length(), out_of_range, rwse_PosBeyondEndOfString);
  330.     size_type rlen = min(n, length() - pos);
  331.     traits::copy(s, data_+pos, rlen);
  332.     return rlen;
  333. }
  334.  
  335. template <class charT, class traits, class Allocator >
  336. basic_string<charT, traits, Allocator>::size_type
  337. basic_string<charT, traits, Allocator>::find (
  338.   const basic_string<charT, traits, Allocator>& str,
  339.   size_type                                     pos) const
  340. {
  341.     //  
  342.     // Should be implemented in traits (strpbrk function)
  343.     //
  344.     for (size_type xpos = pos; (xpos + str.length()) <= length() ; xpos++)
  345.     {
  346.         bool found = true;
  347.         for (size_type i = 0; i < str.length() ; i++)
  348.         {
  349.             if (!traits::eq(data_[xpos + i], str.data_[i]))
  350.             {
  351.                 found = false;
  352.                 break;
  353.             }
  354.         }
  355.         if (found)
  356.             return xpos;
  357.     }
  358.  
  359.     return npos;
  360. }
  361.  
  362. template <class charT, class traits, class Allocator >
  363. basic_string<charT, traits, Allocator>::size_type
  364. basic_string<charT, traits, Allocator>::rfind (
  365.   const basic_string<charT, traits, Allocator>& str,
  366.   size_type                                     pos) const
  367. {
  368.     size_type xpos_start = length() < str.length() ?
  369.                            npos :
  370.                            min(length() - str.length(), pos);
  371.  
  372.     for (size_type xpos = xpos_start; xpos != npos ; xpos--)
  373.     {
  374.         bool found = true;
  375.         for (size_type i = 0; i < str.length() ; i++)
  376.         {
  377.             if (!traits::eq(data_[xpos + i], str.data_[i]))
  378.             {
  379.                 found = false;
  380.                 break;
  381.             }
  382.         }
  383.         if (found)
  384.             return xpos;
  385.     }
  386.  
  387.     return npos;
  388. }
  389.  
  390. template <class charT, class traits, class Allocator >
  391. basic_string<charT, traits, Allocator>::size_type
  392. basic_string<charT, traits, Allocator>::find_first_of (
  393.   const basic_string<charT, traits, Allocator>& str,
  394.   size_type                                     pos) const
  395. {
  396.     for (size_type xpos = pos; xpos < length() ; xpos++)
  397.     {
  398.         for (size_type i = 0; i < str.length() ; i++)
  399.             if (traits::eq(data_[xpos], str.data_[i]))
  400.                 return xpos;
  401.     }
  402.  
  403.     return npos;
  404. }
  405.  
  406. template <class charT, class traits, class Allocator >
  407. basic_string<charT, traits, Allocator>::size_type
  408. basic_string<charT, traits, Allocator>::find_last_of (
  409.   const basic_string<charT, traits, Allocator>& str,
  410.   size_type                                     pos) const
  411. {
  412.     size_type xpos_start = length() ? min(pos, length() - 1) : npos;
  413.  
  414.     for (size_type xpos = xpos_start; xpos != npos ; xpos--)
  415.     {
  416.         for(size_type i = 0; i < str.length() ; i++)
  417.             if (traits::eq(data_[xpos], str.data_[i]))
  418.                 return xpos;
  419.     }
  420.  
  421.     return npos;
  422. }
  423.  
  424. template <class charT, class traits, class Allocator >
  425. basic_string<charT, traits, Allocator>::size_type
  426. basic_string<charT, traits, Allocator>::find_first_not_of (
  427.   const basic_string<charT, traits, Allocator>& str,
  428.   size_type                                     pos) const
  429. {
  430.     for (size_type xpos = pos; xpos < length() ; xpos++)
  431.     {
  432.         bool found = false;
  433.         for (size_type i = 0; i < str.length() ; i++)
  434.         {
  435.             if (traits::eq(data_[xpos], str.data_[i]))
  436.             {
  437.                 found = true;
  438.                 break;
  439.             }
  440.         }
  441.         if (!found)
  442.             return xpos;
  443.     }
  444.  
  445.     return npos;
  446. }
  447.  
  448. template <class charT, class traits, class Allocator >
  449. basic_string<charT, traits, Allocator>::size_type
  450. basic_string<charT, traits, Allocator>::find_last_not_of (
  451.   const basic_string<charT, traits, Allocator>& str,
  452.   size_type                                     pos) const
  453. {
  454.     size_type xpos_start = length() ? min(pos, length() - 1) : npos;
  455.  
  456.     for (size_type xpos = xpos_start; xpos != npos ; xpos--)
  457.     {
  458.         bool found = false;
  459.         for (size_type i = 0; i < str.length() ; i++)
  460.         {
  461.             if (traits::eq(data_[xpos], str.data_[i]))
  462.             {
  463.                 found = true;
  464.                 break;
  465.             }
  466.         }
  467.         if (!found)
  468.             return xpos;
  469.     }
  470.  
  471.     return npos;
  472. }
  473.  
  474. template <class charT, class traits, class Allocator >
  475. basic_string<charT, traits, Allocator>
  476. basic_string<charT, traits, Allocator>::substr (size_type pos,
  477.                                                 size_type n) const
  478. {
  479.     RWSTD_THROW(pos > length(), out_of_range, rwse_PosBeyondEndOfString);
  480.     size_type rlen = min(n, length() - pos);
  481.     return basic_string<charT, traits, Allocator>(data_+pos, rlen);
  482. }
  483.  
  484. template <class charT, class traits, class Allocator >
  485. int
  486. basic_string<charT, traits, Allocator>::compare (
  487.   const basic_string<charT, traits, Allocator>& str,
  488.   size_type                                     pos,
  489.   size_type                                     n) const
  490. {
  491.     RWSTD_THROW(pos > length(), out_of_range, rwse_PosBeyondEndOfString);
  492.  
  493.     size_type llen = min(n, length() - pos);
  494.     size_type slen = str.length();
  495.     size_type rlen = min(llen, slen);
  496.  
  497.     int result = traits::compare(data_+pos, str.data_, rlen);
  498.  
  499.     if (result == 0)
  500.         result = (llen < slen) ? -1 : (llen != slen);
  501.  
  502.     return result;
  503. }
  504.  
  505. template <class charT, class traits, class Allocator >
  506. void basic_string<charT, traits, Allocator>::clobber (size_type nc)
  507. {
  508.     if (pref()->references() > 1 || (getCapac() < nc))
  509.     {
  510.         pref()->unLink(alloc_);
  511.         data_ = getRep(nc, 0, alloc_)->data();
  512.     }
  513.     else
  514.         data_[pref()->nchars_ = 0] = 0;
  515. }
  516.  
  517. template <class charT, class traits, class Allocator >
  518. void basic_string<charT, traits, Allocator>::unSafeClone ()
  519. {
  520.     string_ref<charT, traits, Allocator> * temp =
  521.         getRep(length(), length(), alloc_);
  522.  
  523.     traits::copy(temp->data(), data(), length());
  524.     pref()->unSafeunLink(alloc_);
  525.     data_ = temp->data();
  526. }
  527.  
  528. template <class charT, class traits, class Allocator >
  529. void basic_string<charT, traits, Allocator>::unSafeClone (size_type nc)
  530. {
  531.     size_type len = length();
  532.     if (len > nc) len = nc;
  533.     string_ref<charT, traits, Allocator> * temp = getRep(nc, len, alloc_);
  534.     traits::copy(temp->data(), data(), length());
  535.     pref()->unSafeunLink(alloc_);
  536.     data_ = temp->data();
  537. }
  538.  
  539. //
  540. // Inserters and Extractors
  541. //
  542.  
  543. #ifdef RW_STD_IOSTREAM
  544.  
  545. template<class charT, class traits, class IS_traits, class Allocator>
  546. basic_istream<charT, IS_traits > &
  547. operator>> (basic_istream<charT, IS_traits >& is,
  548.             basic_string<charT, traits, Allocator >& s)
  549. {
  550.     charT c;
  551.     traits::char_in(is, c);
  552.     while (is.good() && traits::is_del(c))
  553.         traits::char_in(is, c);
  554.  
  555.     typename Allocator::size_type i = 0;
  556.     while (is.good() && i < npos && !traits::is_del(c))
  557.     {
  558.         str[i] = c;
  559.         traits::char_in(is, c);
  560.         i++;
  561.     }
  562.  
  563.     s = str;
  564.  
  565.     return is;
  566. }
  567.  
  568. template<class charT, class traits, class IS_traits, class Allocator>
  569. basic_ostream<charT, IS_traits > &
  570. operator<< (basic_ostream<charT, IS_traits > & os,
  571.             const basic_string<charT, traits, Allocator >& a)
  572. {
  573.     typename Allocator::size_type x;
  574.     if ((os.flags() & ios::adjustfield) == ios::right)
  575.        for (x = 0; x < os.width() - s.length(); x++)
  576.           traits::char_out(os, os.fill());
  577.     for (x = 0; x < s.length() ; x++)
  578.         traits::char_out(os, s[x]);
  579.     if ((os.flags() & ios::adjustfield) == ios::left)
  580.        for (x = s.length(); x < os.width(); x++)
  581.           traits::char_out(os, os.fill());
  582.     return os;
  583. }
  584.  
  585. template<class charT, class IS_traits, class STR_traits, class STR_Alloc>
  586. basic_istream<charT, IS_traits>&
  587. getline (basic_istream<charT, IS_traits>& is,
  588.          basic_string<charT, STR_traits, STR_Alloc>& str,
  589.          charT delim)
  590. {
  591.     charT c;
  592.  
  593.     str.remove();
  594.     STR_traits::char_in(is,c);
  595.  
  596.     typename STR_Alloc::size_type i = 0;
  597.     while (is.good())
  598.     {
  599.         if (i == str.npos)
  600.         {
  601.             is.setstate(IS_traits::failbit);
  602.             break;
  603.         }
  604.         if (c == delim)
  605.             break;
  606.         str.append(1,c);
  607.         STR_traits::char_in(is,c);
  608.         i++;
  609.     }
  610.     if (!i)
  611.         is.setf(IS_traits::failbit);
  612.     return is;
  613. }  
  614.  
  615. #else
  616.  
  617. template<class charT, class traits, class Allocator>
  618. istream & operator>> (istream & is,
  619.                       basic_string<charT, traits, Allocator > & s)
  620. {
  621.     charT c;
  622.  
  623.     s.remove();
  624.     traits::char_in(is,c);
  625.     while (is.good() && traits::is_del(c))
  626.         traits::char_in(is,c);
  627.  
  628.     typename Allocator::size_type i = 0;
  629.     while (is.good() && i < s.npos && !traits::is_del(c))
  630.     {
  631.         s.append(1,c);
  632.         traits::char_in(is,c);
  633.         i++;
  634.     }
  635.  
  636.     return is;
  637. }
  638.  
  639.  
  640. template<class charT, class traits, class Allocator>
  641. ostream & operator<< (ostream & os,
  642.                       const basic_string<charT, traits, Allocator > & s)
  643. {
  644.     typename Allocator::size_type x;
  645.     if ((os.flags() & ios::adjustfield) == ios::right)
  646.        for (x = 0; x < os.width() - s.length(); x++)
  647.           traits::char_out(os, os.fill());
  648.     for (x = 0; x < s.length() ; x++)
  649.         traits::char_out(os, s[x]);
  650.     if ((os.flags() & ios::adjustfield) == ios::left)
  651.        for (x = s.length(); x < os.width(); x++)
  652.           traits::char_out(os, os.fill());
  653.     return os;
  654. }
  655.  
  656. #ifdef RWSTD_NO_SPEC_OVERLOAD
  657. istream & RWSTDExport operator>> (istream & is, string & s)
  658. {
  659.     char c;
  660.  
  661.     s.remove();
  662.     string::traits_type::char_in(is,c);
  663.     while (is.good() && string::traits_type::is_del(c))
  664.         string::traits_type::char_in(is,c);
  665.  
  666.     typename string::size_type i = 0;
  667.     while (is.good() && i < s.npos && !string::traits_type::is_del(c))
  668.     {
  669.         s.append(1,c);
  670.         string::traits_type::char_in(is,c);
  671.         i++;
  672.     }
  673.  
  674.     return is;
  675. }
  676.  
  677. ostream& RWSTDExport operator<< (ostream & os, const string& s)
  678. {
  679.     typename string::size_type x;
  680.     if ((os.flags() & ios::adjustfield) == ios::right)
  681.        for (x = 0; x < os.width() - s.length(); x++)
  682.           string::traits_type::char_out(os, os.fill());
  683.     for (x = 0; x < s.length() ; x++)
  684.         string::traits_type::char_out(os, s[x]);
  685.     if ((os.flags() & ios::adjustfield) == ios::left)
  686.        for (x = s.length(); x < os.width(); x++)
  687.           string::traits_type::char_out(os, os.fill());
  688.     return os;
  689. }
  690.  
  691. #ifndef RWSTD_NO_WSTR
  692. ostream & RWSTDExport operator<< (ostream & os, wstring& s)
  693. {
  694.     typename wstring::size_type x;
  695.     if ((os.flags() & ios::adjustfield) == ios::right)
  696.        for (x = 0; x < os.width() - s.length(); x++)
  697.           wstring::traits_type::char_out(os, os.fill());
  698.     for (x = 0; x < s.length() ; x++)
  699.         wstring::traits_type::char_out(os, s[x]);
  700.     if ((os.flags() & ios::adjustfield) == ios::left)
  701.        for (x = s.length(); x < os.width(); x++)
  702.           wstring::traits_type::char_out(os, os.fill());
  703.     return os;
  704. }
  705. #endif
  706. #endif
  707.  
  708. template<class charT, class traits, class Allocator>
  709. istream&
  710. getline (istream& is, basic_string<charT, traits, Allocator>& str, charT delim)
  711. {
  712.     charT c;
  713.  
  714.     str.remove();
  715.     traits::char_in(is, c);
  716.  
  717.     typename Allocator::size_type i = 0;
  718.     while (is.good())
  719.     {
  720.         if (i == str.npos)
  721.         {
  722.             is.setf(istream::failbit);
  723.             break;
  724.         }
  725.         if (c == delim)
  726.             break;
  727.         str.append(1,c);
  728.         traits::char_in(is,c);
  729.         i++;
  730.     }
  731.     if (!i)
  732.         is.setf(istream::failbit);
  733.     return is;
  734. }  
  735.  
  736. #endif /* not defined RW_STD_IOSTREAM */
  737.  
  738. #ifndef RWSTD_NO_NAMESPACE
  739. }
  740. #endif
  741.  
  742.