home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 March / PCWorld_2001-03_cd.bin / Software / TemaCD / devc / _SETUP.6 / Group12 / bastring.cc next >
C/C++ Source or Header  |  2000-01-21  |  14KB  |  525 lines

  1. // Member templates for the -*- C++ -*- string classes.
  2. // Copyright (C) 1994 Free Software Foundation
  3.  
  4. // This file is part of the GNU ANSI C++ Library.  This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 2, or (at your option)
  8. // any later version.
  9.  
  10. // This library is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14.  
  15. // You should have received a copy of the GNU General Public License
  16. // along with this library; see the file COPYING.  If not, write to the Free
  17. // Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. // As a special exception, if you link this library with files
  20. // compiled with a GNU compiler to produce an executable, this does not cause
  21. // the resulting executable to be covered by the GNU General Public License.
  22. // This exception does not however invalidate any other reasons why
  23. // the executable file might be covered by the GNU General Public License.
  24.  
  25. // Written by Jason Merrill based upon the specification by Takanori Adachi
  26. // in ANSI X3J16/94-0013R2.
  27.  
  28. extern "C++" {
  29. template <class charT, class traits, class Allocator>
  30. inline void * basic_string <charT, traits, Allocator>::Rep::
  31. operator new (size_t s, size_t extra)
  32. {
  33.   return Allocator::allocate(s + extra * sizeof (charT));
  34. }
  35.  
  36. template <class charT, class traits, class Allocator>
  37. inline void basic_string <charT, traits, Allocator>::Rep::
  38. operator delete (void * ptr)
  39. {
  40.   Allocator::deallocate(ptr, sizeof(Rep) +
  41.             reinterpret_cast<Rep *>(ptr)->res *
  42.             sizeof (charT));
  43. }
  44.  
  45. template <class charT, class traits, class Allocator>
  46. inline size_t basic_string <charT, traits, Allocator>::Rep::
  47. frob_size (size_t s)
  48. {
  49.   size_t i = 16;
  50.   while (i < s) i *= 2;
  51.   return i;
  52. }
  53.  
  54. template <class charT, class traits, class Allocator>
  55. inline basic_string <charT, traits, Allocator>::Rep *
  56. basic_string <charT, traits, Allocator>::Rep::
  57. create (size_t extra)
  58. {
  59.   extra = frob_size (extra + 1);
  60.   Rep *p = new (extra) Rep;
  61.   p->res = extra;
  62.   p->ref = 1;
  63.   p->selfish = false;
  64.   return p;
  65. }
  66.  
  67. template <class charT, class traits, class Allocator>
  68. charT * basic_string <charT, traits, Allocator>::Rep::
  69. clone ()
  70. {
  71.   Rep *p = Rep::create (len);
  72.   p->copy (0, data (), len);
  73.   p->len = len;
  74.   return p->data ();
  75. }
  76.  
  77. template <class charT, class traits, class Allocator>
  78. inline bool basic_string <charT, traits, Allocator>::Rep::
  79. excess_slop (size_t s, size_t r)
  80. {
  81.   return 2 * (s <= 16 ? 16 : s) < r;
  82. }
  83.  
  84. template <class charT, class traits, class Allocator>
  85. inline bool basic_string <charT, traits, Allocator>::
  86. check_realloc (basic_string::size_type s) const
  87. {
  88.   s += sizeof (charT);
  89.   rep ()->selfish = false;
  90.   return (rep ()->ref > 1
  91.       || s > capacity ()
  92.       || Rep::excess_slop (s, capacity ()));
  93. }
  94.  
  95. template <class charT, class traits, class Allocator>
  96. void basic_string <charT, traits, Allocator>::
  97. alloc (basic_string::size_type size, bool save)
  98. {
  99.   if (! check_realloc (size))
  100.     return;
  101.  
  102.   Rep *p = Rep::create (size);
  103.  
  104.   if (save)
  105.     {
  106.       p->copy (0, data (), length ());
  107.       p->len = length ();
  108.     }
  109.   else
  110.     p->len = 0;
  111.  
  112.   repup (p);
  113. }
  114.  
  115. template <class charT, class traits, class Allocator>
  116. basic_string <charT, traits, Allocator>&
  117. basic_string <charT, traits, Allocator>::
  118. replace (size_type pos1, size_type n1,
  119.      const basic_string& str, size_type pos2, size_type n2)
  120. {
  121.   const size_t len2 = str.length ();
  122.  
  123.   if (pos1 == 0 && n1 >= length () && pos2 == 0 && n2 >= len2)
  124.     return operator= (str);
  125.  
  126.   OUTOFRANGE (pos2 > len2);
  127.  
  128.   if (n2 > len2 - pos2)
  129.     n2 = len2 - pos2;
  130.  
  131.   return replace (pos1, n1, str.data () + pos2, n2);
  132. }
  133.  
  134. template <class charT, class traits, class Allocator>
  135. inline void basic_string <charT, traits, Allocator>::Rep::
  136. copy (size_t pos, const charT *s, size_t n)
  137. {
  138.   if (n)
  139.     traits::copy (data () + pos, s, n);
  140. }
  141.  
  142. template <class charT, class traits, class Allocator>
  143. inline void basic_string <charT, traits, Allocator>::Rep::
  144. move (size_t pos, const charT *s, size_t n)
  145. {
  146.   if (n)
  147.     traits::move (data () + pos, s, n);
  148. }
  149.  
  150. template <class charT, class traits, class Allocator>
  151. basic_string <charT, traits, Allocator>&
  152. basic_string <charT, traits, Allocator>::
  153. replace (size_type pos, size_type n1, const charT* s, size_type n2)
  154. {
  155.   const size_type len = length ();
  156.   OUTOFRANGE (pos > len);
  157.   if (n1 > len - pos)
  158.     n1 = len - pos;
  159.   LENGTHERROR (len - n1 > max_size () - n2);
  160.   size_t newlen = len - n1 + n2;
  161.  
  162.   if (check_realloc (newlen))
  163.     {
  164.       Rep *p = Rep::create (newlen);
  165.       p->copy (0, data (), pos);
  166.       p->copy (pos + n2, data () + pos + n1, len - (pos + n1));
  167.       p->copy (pos, s, n2);
  168.       repup (p);
  169.     }
  170.   else
  171.     {
  172.       rep ()->move (pos + n2, data () + pos + n1, len - (pos + n1));
  173.       rep ()->copy (pos, s, n2);
  174.     }
  175.   rep ()->len = newlen;
  176.  
  177.   return *this;
  178. }
  179.  
  180. template <class charT, class traits, class Allocator>
  181. inline void basic_string <charT, traits, Allocator>::Rep::
  182. set (size_t pos, const charT c, size_t n)
  183. {
  184.   traits::set  (data () + pos, c, n);
  185. }
  186.  
  187. template <class charT, class traits, class Allocator>
  188. basic_string <charT, traits, Allocator>& basic_string <charT, traits, Allocator>::
  189. replace (size_type pos, size_type n1, size_type n2, charT c)
  190. {
  191.   const size_t len = length ();
  192.   OUTOFRANGE (pos > len);
  193.   if (n1 > len - pos)
  194.     n1 = len - pos;
  195.   LENGTHERROR (len - n1 > max_size () - n2);
  196.   size_t newlen = len - n1 + n2;
  197.  
  198.   if (check_realloc (newlen))
  199.     {
  200.       Rep *p = Rep::create (newlen);
  201.       p->copy (0, data (), pos);
  202.       p->copy (pos + n2, data () + pos + n1, len - (pos + n1));
  203.       p->set  (pos, c, n2);
  204.       repup (p);
  205.     }
  206.   else
  207.     {
  208.       rep ()->move (pos + n2, data () + pos + n1, len - (pos + n1));
  209.       rep ()->set  (pos, c, n2);
  210.     }
  211.   rep ()->len = newlen;
  212.  
  213.   return *this;
  214. }
  215.  
  216. template <class charT, class traits, class Allocator>
  217. void basic_string <charT, traits, Allocator>::
  218. resize (size_type n, charT c)
  219. {
  220.   LENGTHERROR (n > max_size ());
  221.  
  222.   if (n > length ())
  223.     append (n - length (), c);
  224.   else
  225.     erase (n);
  226. }
  227.  
  228. template <class charT, class traits, class Allocator>
  229. basic_string <charT, traits, Allocator>::size_type
  230. basic_string <charT, traits, Allocator>::
  231. copy (charT* s, size_type n, size_type pos) const
  232. {
  233.   OUTOFRANGE (pos > length ());
  234.  
  235.   if (n > length () - pos)
  236.     n = length () - pos;
  237.  
  238.   traits::copy (s, data () + pos, n);
  239.   return n;
  240. }
  241.  
  242. template <class charT, class traits, class Allocator>
  243. basic_string <charT, traits, Allocator>::size_type
  244. basic_string <charT, traits, Allocator>::
  245. find (const charT* s, size_type pos, size_type n) const
  246. {
  247.   size_t xpos = pos;
  248.   for (; xpos + n <= length (); ++xpos)
  249.     if (traits::eq (data () [xpos], *s)
  250.     && traits::compare (data () + xpos, s, n) == 0)
  251.       return xpos;
  252.   return npos;
  253. }
  254.  
  255. template <class charT, class traits, class Allocator>
  256. inline basic_string <charT, traits, Allocator>::size_type
  257. basic_string <charT, traits, Allocator>::
  258. _find (const charT* ptr, charT c, size_type xpos, size_type len)
  259. {
  260.   for (; xpos < len; ++xpos)
  261.     if (traits::eq (ptr [xpos], c))
  262.       return xpos;
  263.   return npos;
  264. }
  265.  
  266. template <class charT, class traits, class Allocator>
  267. basic_string <charT, traits, Allocator>::size_type
  268. basic_string <charT, traits, Allocator>::
  269. find (charT c, size_type pos) const
  270. {
  271.   return _find (data (), c, pos, length ());
  272. }
  273.  
  274. template <class charT, class traits, class Allocator>
  275. basic_string <charT, traits, Allocator>::size_type
  276. basic_string <charT, traits, Allocator>::
  277. rfind (const charT* s, size_type pos, size_type n) const
  278. {
  279.   if (n > length ())
  280.     return npos;
  281.  
  282.   size_t xpos = length () - n;
  283.   if (xpos > pos)
  284.     xpos = pos;
  285.  
  286.   for (++xpos; xpos-- > 0; )
  287.     if (traits::eq (data () [xpos], *s)
  288.     && traits::compare (data () + xpos, s, n) == 0)
  289.       return xpos;
  290.   return npos;
  291. }
  292.  
  293. template <class charT, class traits, class Allocator>
  294. basic_string <charT, traits, Allocator>::size_type
  295. basic_string <charT, traits, Allocator>::
  296. rfind (charT c, size_type pos) const
  297. {
  298.   if (1 > length ())
  299.     return npos;
  300.  
  301.   size_t xpos = length () - 1;
  302.   if (xpos > pos)
  303.     xpos = pos;
  304.  
  305.   for (++xpos; xpos-- > 0; )
  306.     if (traits::eq (data () [xpos], c))
  307.       return xpos;
  308.   return npos;
  309. }
  310.  
  311. template <class charT, class traits, class Allocator>
  312. basic_string <charT, traits, Allocator>::size_type
  313. basic_string <charT, traits, Allocator>::
  314. find_first_of (const charT* s, size_type pos, size_type n) const
  315. {
  316.   size_t xpos = pos;
  317.   for (; xpos < length (); ++xpos)
  318.     if (_find (s, data () [xpos], 0, n) != npos)
  319.       return xpos;
  320.   return npos;
  321. }
  322.  
  323. template <class charT, class traits, class Allocator>
  324. basic_string <charT, traits, Allocator>::size_type
  325. basic_string <charT, traits, Allocator>::
  326. find_last_of (const charT* s, size_type pos, size_type n) const
  327. {
  328.   if (length() == 0)
  329.     return npos;
  330.   size_t xpos = length () - 1;
  331.   if (xpos > pos)
  332.     xpos = pos;
  333.   for (++xpos; xpos-- > 0;)
  334.     if (_find (s, data () [xpos], 0, n) != npos)
  335.       return xpos;
  336.   return npos;
  337. }
  338.  
  339. template <class charT, class traits, class Allocator>
  340. basic_string <charT, traits, Allocator>::size_type
  341. basic_string <charT, traits, Allocator>::
  342. find_first_not_of (const charT* s, size_type pos, size_type n) const
  343. {
  344.   size_t xpos = pos;
  345.   for (; xpos < length (); ++xpos)
  346.     if (_find (s, data () [xpos], 0, n) == npos)
  347.       return xpos;
  348.   return npos;
  349. }
  350.  
  351. template <class charT, class traits, class Allocator>
  352. basic_string <charT, traits, Allocator>::size_type
  353. basic_string <charT, traits, Allocator>::
  354. find_first_not_of (charT c, size_type pos) const
  355. {
  356.   size_t xpos = pos;
  357.   for (; xpos < length (); ++xpos)
  358.     if (traits::ne (data () [xpos], c))
  359.       return xpos;
  360.   return npos;
  361. }
  362.  
  363. template <class charT, class traits, class Allocator>
  364. basic_string <charT, traits, Allocator>::size_type
  365. basic_string <charT, traits, Allocator>::
  366. find_last_not_of (const charT* s, size_type pos, size_type n) const
  367. {
  368.   if (length() == 0)
  369.     return npos;
  370.   size_t xpos = length () - 1;
  371.   if (xpos > pos)
  372.     xpos = pos;
  373.   for (++xpos; xpos-- > 0;)
  374.     if (_find (s, data () [xpos], 0, n) == npos)
  375.       return xpos;
  376.   return npos;
  377. }
  378.  
  379. template <class charT, class traits, class Allocator>
  380. basic_string <charT, traits, Allocator>::size_type
  381. basic_string <charT, traits, Allocator>::
  382. find_last_not_of (charT c, size_type pos) const
  383. {
  384.   if (length() == 0)
  385.     return npos;
  386.   size_t xpos = length () - 1;
  387.   if (xpos > pos)
  388.     xpos = pos;
  389.   for (++xpos; xpos-- > 0;)
  390.     if (traits::ne (data () [xpos], c))
  391.       return xpos;
  392.   return npos;
  393. }
  394.  
  395. template <class charT, class traits, class Allocator>
  396. int basic_string <charT, traits, Allocator>::
  397. compare (const basic_string& str, size_type pos, size_type n) const
  398. {
  399.   OUTOFRANGE (pos > length ());
  400.  
  401.   size_t rlen = length () - pos;
  402.   if (rlen > n)
  403.     rlen = n;
  404.   if (rlen > str.length ())
  405.     rlen = str.length ();
  406.   int r = traits::compare (data () + pos, str.data (), rlen);
  407.   if (r != 0)
  408.     return r;
  409.   if (rlen == n)
  410.     return 0;
  411.   return (length () - pos) - str.length ();
  412. }
  413.  
  414. template <class charT, class traits, class Allocator>
  415. int basic_string <charT, traits, Allocator>::
  416. compare (const charT* s, size_type pos, size_type n) const
  417. {
  418.   OUTOFRANGE (pos > length ());
  419.  
  420.   size_t rlen = length () - pos;
  421.   if (rlen > n)
  422.     rlen = n;
  423.   int r = traits::compare (data () + pos, s, rlen);
  424.   if (r != 0)
  425.     return r;
  426.   return (length () - pos) - n;
  427. }
  428.  
  429. #include <iostream.h>
  430.  
  431. template <class charT, class traits, class Allocator>
  432. istream &
  433. operator>> (istream &is, basic_string <charT, traits, Allocator> &s)
  434. {
  435.   int w = is.width (0);
  436.   if (is.ipfx0 ())
  437.     {
  438.       register streambuf *sb = is.rdbuf ();
  439.       s.resize (0);
  440.       while (1)
  441.     {
  442.       int ch = sb->sbumpc ();
  443.       if (ch == EOF)
  444.         {
  445.           is.setstate (ios::eofbit);
  446.           break;
  447.         }
  448.       else if (traits::is_del (ch))
  449.         {
  450.           sb->sungetc ();
  451.           break;
  452.         }
  453.       s += static_cast<charT> (ch);
  454.       if (--w == 1)
  455.         break;
  456.     }
  457.     }
  458.  
  459.   is.isfx ();
  460.   if (s.length () == 0)
  461.     is.setstate (ios::failbit);
  462.  
  463.   return is;
  464. }
  465.  
  466. template <class charT, class traits, class Allocator>
  467. ostream &
  468. operator<< (ostream &o, const basic_string <charT, traits, Allocator>& s)
  469. {
  470.   return o.write (s.data (), s.length ());
  471. }
  472.  
  473. template <class charT, class traits, class Allocator>
  474. istream&
  475. getline (istream &is, basic_string <charT, traits, Allocator>& s, charT delim)
  476. {
  477.   if (is.ipfx1 ())
  478.     {
  479.       _IO_size_t count = 0;
  480.       streambuf *sb = is.rdbuf ();
  481.       s.resize (0);
  482.  
  483.       while (1)
  484.     {
  485.       int ch = sb->sbumpc ();
  486.       if (ch == EOF)
  487.         {
  488.           is.setstate (count == 0
  489.                ? (ios::failbit|ios::eofbit)
  490.                : ios::eofbit);
  491.           break;
  492.         }
  493.  
  494.       ++count;
  495.  
  496.       if (ch == delim)
  497.         break;
  498.  
  499.       s += static_cast<charT> (ch);
  500.  
  501.       if (s.length () == s.npos - 1)
  502.         {
  503.           is.setstate (ios::failbit);
  504.           break;
  505.         }
  506.     }
  507.     }
  508.  
  509.   // We need to be friends with istream to do this.
  510.   // is._gcount = count;
  511.   is.isfx ();
  512.  
  513.   return is;
  514. }
  515.  
  516. template <class charT, class traits, class Allocator>
  517. basic_string <charT, traits, Allocator>::Rep
  518. basic_string<charT, traits, Allocator>::nilRep = { 0, 0, 1, false };
  519.  
  520. template <class charT, class traits, class Allocator>
  521. const basic_string <charT, traits, Allocator>::size_type
  522. basic_string <charT, traits, Allocator>::npos;
  523.  
  524. } // extern "C++"
  525.