home *** CD-ROM | disk | FTP | other *** search
/ PC World 2000 January / PCWorld_2000-01_cd.bin / Software / Servis / Devc / _SETUP.5 / Group22 / bastring.cc next >
C/C++ Source or Header  |  1998-03-08  |  13KB  |  519 lines

  1. // Member templates for the -*- C++ -*- string classes.
  2. // Copyright (C) 1994, 1998 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)
  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.   size_t xpos = length () - 1;
  329.   if (xpos > pos)
  330.     xpos = pos;
  331.   for (; xpos; --xpos)
  332.     if (_find (s, data () [xpos], 0, n) != npos)
  333.       return xpos;
  334.   return npos;
  335. }
  336.  
  337. template <class charT, class traits, class Allocator>
  338. basic_string <charT, traits, Allocator>::size_type
  339. basic_string <charT, traits, Allocator>::
  340. find_first_not_of (const charT* s, size_type pos, size_type n) const
  341. {
  342.   size_t xpos = pos;
  343.   for (; xpos < length (); ++xpos)
  344.     if (_find (s, data () [xpos], 0, n) == npos)
  345.       return xpos;
  346.   return npos;
  347. }
  348.  
  349. template <class charT, class traits, class Allocator>
  350. basic_string <charT, traits, Allocator>::size_type
  351. basic_string <charT, traits, Allocator>::
  352. find_first_not_of (charT c, size_type pos) const
  353. {
  354.   size_t xpos = pos;
  355.   for (; xpos < length (); ++xpos)
  356.     if (traits::ne (data () [xpos], c))
  357.       return xpos;
  358.   return npos;
  359. }
  360.  
  361. template <class charT, class traits, class Allocator>
  362. basic_string <charT, traits, Allocator>::size_type
  363. basic_string <charT, traits, Allocator>::
  364. find_last_not_of (const charT* s, size_type pos, size_type n) const
  365. {
  366.   size_t xpos = length () - 1;
  367.   if (xpos > pos)
  368.     xpos = pos;
  369.   for (; xpos; --xpos)
  370.     if (_find (s, data () [xpos], 0, n) == npos)
  371.       return xpos;
  372.   return npos;
  373. }
  374.  
  375. template <class charT, class traits, class Allocator>
  376. basic_string <charT, traits, Allocator>::size_type
  377. basic_string <charT, traits, Allocator>::
  378. find_last_not_of (charT c, size_type pos) const
  379. {
  380.   size_t xpos = length () - 1;
  381.   if (xpos > pos)
  382.     xpos = pos;
  383.   for (; xpos; --xpos)
  384.     if (traits::ne (data () [xpos], c))
  385.       return xpos;
  386.   return npos;
  387. }
  388.  
  389. template <class charT, class traits, class Allocator>
  390. int basic_string <charT, traits, Allocator>::
  391. compare (const basic_string& str, size_type pos, size_type n) const
  392. {
  393.   OUTOFRANGE (pos > length ());
  394.  
  395.   size_t rlen = length () - pos;
  396.   if (rlen > n)
  397.     rlen = n;
  398.   if (rlen > str.length ())
  399.     rlen = str.length ();
  400.   int r = traits::compare (data () + pos, str.data (), rlen);
  401.   if (r != 0)
  402.     return r;
  403.   if (rlen == n)
  404.     return 0;
  405.   return (length () - pos) - str.length ();
  406. }
  407.  
  408. template <class charT, class traits, class Allocator>
  409. int basic_string <charT, traits, Allocator>::
  410. compare (const charT* s, size_type pos, size_type n) const
  411. {
  412.   OUTOFRANGE (pos > length ());
  413.  
  414.   size_t rlen = length () - pos;
  415.   if (rlen > n)
  416.     rlen = n;
  417.   int r = traits::compare (data () + pos, s, rlen);
  418.   if (r != 0)
  419.     return r;
  420.   return (length () - pos) - n;
  421. }
  422.  
  423. #include <iostream.h>
  424.  
  425. template <class charT, class traits, class Allocator>
  426. istream &
  427. operator>> (istream &is, basic_string <charT, traits, Allocator> &s)
  428. {
  429.   int w = is.width (0);
  430.   if (is.ipfx0 ())
  431.     {
  432.       register streambuf *sb = is.rdbuf ();
  433.       s.resize (0);
  434.       while (1)
  435.     {
  436.       int ch = sb->sbumpc ();
  437.       if (ch == EOF)
  438.         {
  439.           is.setstate (ios::eofbit);
  440.           break;
  441.         }
  442.       else if (traits::is_del (ch))
  443.         {
  444.           sb->sungetc ();
  445.           break;
  446.         }
  447.       s += ch;
  448.       if (--w == 1)
  449.         break;
  450.     }
  451.     }
  452.  
  453.   is.isfx ();
  454.   if (s.length () == 0)
  455.     is.setstate (ios::failbit);
  456.  
  457.   return is;
  458. }
  459.  
  460. template <class charT, class traits, class Allocator>
  461. ostream &
  462. operator<< (ostream &o, const basic_string <charT, traits, Allocator>& s)
  463. {
  464.   return o.write (s.data (), s.length ());
  465. }
  466.  
  467. template <class charT, class traits, class Allocator>
  468. istream&
  469. getline (istream &is, basic_string <charT, traits, Allocator>& s, charT delim)
  470. {
  471.   if (is.ipfx1 ())
  472.     {
  473.       _IO_size_t count = 0;
  474.       streambuf *sb = is.rdbuf ();
  475.       s.resize (0);
  476.  
  477.       while (1)
  478.     {
  479.       int ch = sb->sbumpc ();
  480.       if (ch == EOF)
  481.         {
  482.           is.setstate (count == 0
  483.                ? (ios::failbit|ios::eofbit)
  484.                : ios::eofbit);
  485.           break;
  486.         }
  487.  
  488.       ++count;
  489.  
  490.       if (ch == delim)
  491.         break;
  492.  
  493.       s += ch;
  494.  
  495.       if (s.length () == s.npos - 1)
  496.         {
  497.           is.setstate (ios::failbit);
  498.           break;
  499.         }
  500.     }
  501.     }
  502.  
  503.   // We need to be friends with istream to do this.
  504.   // is._gcount = count;
  505.   is.isfx ();
  506.  
  507.   return is;
  508. }
  509.  
  510. template <class charT, class traits, class Allocator>
  511. basic_string <charT, traits, Allocator>::Rep
  512. basic_string<charT, traits, Allocator>::nilRep = { 0, 0, 1, false };
  513.  
  514. template <class charT, class traits, class Allocator>
  515. const basic_string <charT, traits, Allocator>::size_type
  516. basic_string <charT, traits, Allocator>::npos;
  517.  
  518. } // extern "C++"
  519.