String.cc
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:28k
源码类别:

DVD

开发平台:

Unix_Linux

  1. /* 
  2. Copyright (C) 1988 Free Software Foundation
  3.     written by Doug Lea (dl@rocky.oswego.edu)
  4. This file is part of the GNU C++ Library.  This library is free
  5. software; you can redistribute it and/or modify it under the terms of
  6. the GNU Library General Public License as published by the Free
  7. Software Foundation; either version 2 of the License, or (at your
  8. option) any later version.  This library is distributed in the hope
  9. that it will be useful, but WITHOUT ANY WARRANTY; without even the
  10. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE.  See the GNU Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public
  13. License along with this library; if not, write to the Free Software
  14. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. /* 
  17.   String class implementation
  18.  */
  19. #ifdef __GNUG__
  20. #pragma implementation
  21. #endif
  22. #include <String.h>
  23. #include <unistd.h>
  24. #include <ctype.h>
  25. #include <limits.h>
  26. #include <new.h>
  27. #include <builtin.h>
  28. void String::error(const char* msg) const
  29. {
  30.   (*lib_error_handler)("String", msg);
  31. }
  32. String::operator const char*() const
  33.   return (const char*)chars();
  34. }
  35. //  globals
  36. StrRep  _nilStrRep = { 0, 1, { 0 } }; // nil strings point here
  37. String _nilString;               // nil SubStrings point here
  38. /*
  39.  the following inline fcts are specially designed to work
  40.  in support of String classes, and are not meant as generic replacements
  41.  for libc "str" functions.
  42.  inline copy fcts -  I like left-to-right from->to arguments.
  43.  all versions assume that `to' argument is non-null
  44.  These are worth doing inline, rather than through calls because,
  45.  via procedural integration, adjacent copy calls can be smushed
  46.  together by the optimizer.
  47. */
  48. // copy n bytes
  49. inline static void ncopy(const char* from, char* to, int n)
  50. {
  51.   if (from != to) while (--n >= 0) *to++ = *from++;
  52. }
  53. // copy n bytes, null-terminate
  54. inline static void ncopy0(const char* from, char* to, int n)
  55. {
  56.   if (from != to) 
  57.   {
  58.     while (--n >= 0) *to++ = *from++;
  59.     *to = 0;
  60.   }
  61.   else
  62.     to[n] = 0;
  63. }
  64. // copy until null
  65. inline static void scopy(const char* from, char* to)
  66. {
  67.   if (from != 0) while((*to++ = *from++) != 0);
  68. }
  69. // copy right-to-left
  70. inline static void revcopy(const char* from, char* to, short n)
  71. {
  72.   if (from != 0) while (--n >= 0) *to-- = *from--;
  73. }
  74. inline static int slen(const char* t) // inline  strlen
  75. {
  76.   if (t == 0)
  77.     return 0;
  78.   else
  79.   {
  80.     const char* a = t;
  81.     while (*a++ != 0);
  82.     return a - 1 - t;
  83.   }
  84. }
  85. // minimum & maximum representable rep size
  86. #define MAXStrRep_SIZE   ((1 << (sizeof(short) * CHAR_BIT - 1)) - 1)
  87. #define MINStrRep_SIZE   16
  88. #ifndef MALLOC_MIN_OVERHEAD
  89. #define MALLOC_MIN_OVERHEAD  4
  90. #endif
  91. // The basic allocation primitive:
  92. // Always round request to something close to a power of two.
  93. // This ensures a bit of padding, which often means that
  94. // concatenations don't have to realloc. Plus it tends to
  95. // be faster when lots of Strings are created and discarded,
  96. // since just about any version of malloc (op new()) will
  97. // be faster when it can reuse identically-sized chunks
  98. inline static StrRep* Snew(int newsiz)
  99. {
  100.   unsigned int siz = sizeof(StrRep) + newsiz + MALLOC_MIN_OVERHEAD;
  101.   unsigned int allocsiz = MINStrRep_SIZE;
  102.   while (allocsiz < siz) allocsiz <<= 1;
  103.   allocsiz -= MALLOC_MIN_OVERHEAD;
  104.   if (allocsiz >= MAXStrRep_SIZE)
  105.     (*lib_error_handler)("String", "Requested length out of range");
  106.     
  107.   StrRep* rep = (StrRep *) new char[allocsiz];
  108.   rep->sz = allocsiz - sizeof(StrRep);
  109.   return rep;
  110. }
  111. // Do-something-while-allocating routines.
  112. // We live with two ways to signify empty Sreps: either the
  113. // null pointer (0) or a pointer to the nilStrRep.
  114. // We always signify unknown source lengths (usually when fed a char*)
  115. // via len == -1, in which case it is computed.
  116. // allocate, copying src if nonull
  117. StrRep* Salloc(StrRep* old, const char* src, int srclen, int newlen)
  118. {
  119.   if (old == &_nilStrRep) old = 0;
  120.   if (srclen < 0) srclen = slen(src);
  121.   if (newlen < srclen) newlen = srclen;
  122.   StrRep* rep;
  123.   if (old == 0 || newlen > old->sz)
  124.     rep = Snew(newlen);
  125.   else
  126.     rep = old;
  127.   rep->len = newlen;
  128.   ncopy0(src, rep->s, srclen);
  129.   if (old != rep && old != 0) delete old;
  130.   return rep;
  131. }
  132. // reallocate: Given the initial allocation scheme, it will
  133. // generally be faster in the long run to get new space & copy
  134. // than to call realloc
  135. static StrRep*
  136. Sresize(StrRep* old, int newlen)
  137. {
  138.   if (old == &_nilStrRep) old = 0;
  139.   StrRep* rep;
  140.   if (old == 0)
  141.     rep = Snew(newlen);
  142.   else if (newlen > old->sz)
  143.   {
  144.     rep = Snew(newlen);
  145.     ncopy0(old->s, rep->s, old->len);
  146.     delete old;
  147.   }
  148.   else
  149.     rep = old;
  150.   rep->len = newlen;
  151.   return rep;
  152. }
  153. void
  154. String::alloc (int newsize)
  155. {
  156.   unsigned short old_len = rep->len;
  157.   rep = Sresize(rep, newsize);
  158.   rep->len = old_len;
  159. }
  160. // like allocate, but we know that src is a StrRep
  161. StrRep* Scopy(StrRep* old, const StrRep* s)
  162. {
  163.   if (old == &_nilStrRep) old = 0;
  164.   if (s == &_nilStrRep) s = 0;
  165.   if (old == s) 
  166.     return (old == 0)? &_nilStrRep : old;
  167.   else if (s == 0)
  168.   {
  169.     old->s[0] = 0;
  170.     old->len = 0;
  171.     return old;
  172.   }
  173.   else 
  174.   {
  175.     StrRep* rep;
  176.     int newlen = s->len;
  177.     if (old == 0 || newlen > old->sz)
  178.     {
  179.       if (old != 0) delete old;
  180.       rep = Snew(newlen);
  181.     }
  182.     else
  183.       rep = old;
  184.     rep->len = newlen;
  185.     ncopy0(s->s, rep->s, newlen);
  186.     return rep;
  187.   }
  188. }
  189. // allocate & concatenate
  190. StrRep* Scat(StrRep* old, const char* s, int srclen, const char* t, int tlen)
  191. {
  192.   if (old == &_nilStrRep) old = 0;
  193.   if (srclen < 0) srclen = slen(s);
  194.   if (tlen < 0) tlen = slen(t);
  195.   int newlen = srclen + tlen;
  196.   StrRep* rep;
  197.   if (old == 0 || newlen > old->sz || 
  198.       (t >= old->s && t < &(old->s[old->len]))) // beware of aliasing
  199.     rep = Snew(newlen);
  200.   else
  201.     rep = old;
  202.   rep->len = newlen;
  203.   ncopy(s, rep->s, srclen);
  204.   ncopy0(t, &(rep->s[srclen]), tlen);
  205.   if (old != rep && old != 0) delete old;
  206.   return rep;
  207. }
  208. // double-concatenate
  209. StrRep* Scat(StrRep* old, const char* s, int srclen, const char* t, int tlen,
  210.              const char* u, int ulen)
  211. {
  212.   if (old == &_nilStrRep) old = 0;
  213.   if (srclen < 0) srclen = slen(s);
  214.   if (tlen < 0) tlen = slen(t);
  215.   if (ulen < 0) ulen = slen(u);
  216.   int newlen = srclen + tlen + ulen;
  217.   StrRep* rep;
  218.   if (old == 0 || newlen > old->sz || 
  219.       (t >= old->s && t < &(old->s[old->len])) ||
  220.       (u >= old->s && u < &(old->s[old->len])))
  221.     rep = Snew(newlen);
  222.   else
  223.     rep = old;
  224.   rep->len = newlen;
  225.   ncopy(s, rep->s, srclen);
  226.   ncopy(t, &(rep->s[srclen]), tlen);
  227.   ncopy0(u, &(rep->s[srclen+tlen]), ulen);
  228.   if (old != rep && old != 0) delete old;
  229.   return rep;
  230. }
  231. // like cat, but we know that new stuff goes in the front of existing rep
  232. StrRep* Sprepend(StrRep* old, const char* t, int tlen)
  233. {
  234.   char* s;
  235.   int srclen;
  236.   if (old == &_nilStrRep || old == 0)
  237.   {
  238.     s = 0; old = 0; srclen = 0;
  239.   }
  240.   else
  241.   {
  242.     s = old->s; srclen = old->len;
  243.   }
  244.   if (tlen < 0) tlen = slen(t);
  245.   int newlen = srclen + tlen;
  246.   StrRep* rep;
  247.   if (old == 0 || newlen > old->sz || 
  248.       (t >= old->s && t < &(old->s[old->len])))
  249.     rep = Snew(newlen);
  250.   else
  251.     rep = old;
  252.   rep->len = newlen;
  253.   revcopy(&(s[srclen]), &(rep->s[newlen]), srclen+1);
  254.   ncopy(t, rep->s, tlen);
  255.   if (old != rep && old != 0) delete old;
  256.   return rep;
  257. }
  258. // string compare: first argument is known to be non-null
  259. inline static int scmp(const char* a, const char* b)
  260. {
  261.   if (b == 0)
  262.     return *a != 0;
  263.   else
  264.   {
  265.     signed char diff = 0;
  266.     while ((diff = *a - *b++) == 0 && *a++ != 0);
  267.     return diff;
  268.   }
  269. }
  270. inline static int ncmp(const char* a, int al, const char* b, int bl)
  271. {
  272.   int n = (al <= bl)? al : bl;
  273.   signed char diff;
  274.   while (n-- > 0) if ((diff = *a++ - *b++) != 0) return diff;
  275.   return al - bl;
  276. }
  277. int fcompare(const String& x, const String& y)
  278. {
  279.   const char* a = x.chars();
  280.   const char* b = y.chars();
  281.   int al = x.length();
  282.   int bl = y.length();
  283.   int n = (al <= bl)? al : bl;
  284.   signed char diff = 0;
  285.   while (n-- > 0)
  286.   {
  287.     char ac = *a++;
  288.     char bc = *b++;
  289.     if ((diff = ac - bc) != 0)
  290.     {
  291.       if (ac >= 'a' && ac <= 'z')
  292.         ac = ac - 'a' + 'A';
  293.       if (bc >= 'a' && bc <= 'z')
  294.         bc = bc - 'a' + 'A';
  295.       if ((diff = ac - bc) != 0)
  296.         return diff;
  297.     }
  298.   }
  299.   return al - bl;
  300. }
  301. // these are not inline, but pull in the above inlines, so are 
  302. // pretty fast
  303. int compare(const String& x, const char* b)
  304. {
  305.   return scmp(x.chars(), b);
  306. }
  307. int compare(const String& x, const String& y)
  308. {
  309.   return scmp(x.chars(), y.chars());
  310. }
  311. int compare(const String& x, const SubString& y)
  312. {
  313.   return ncmp(x.chars(), x.length(), y.chars(), y.length());
  314. }
  315. int compare(const SubString& x, const String& y)
  316. {
  317.   return ncmp(x.chars(), x.length(), y.chars(), y.length());
  318. }
  319. int compare(const SubString& x, const SubString& y)
  320. {
  321.   return ncmp(x.chars(), x.length(), y.chars(), y.length());
  322. }
  323. int compare(const SubString& x, const char* b)
  324. {
  325.   if (b == 0)
  326.     return x.length();
  327.   else
  328.   {
  329.     const char* a = x.chars();
  330.     int n = x.length();
  331.     signed char diff;
  332.     while (n-- > 0) if ((diff = *a++ - *b++) != 0) return diff;
  333.     return (*b == 0) ? 0 : -1;
  334.   }
  335. }
  336. /*
  337.  index fcts
  338. */
  339. int String::search(int start, int sl, char c) const
  340. {
  341.   const char* s = chars();
  342.   if (sl > 0)
  343.   {
  344.     if (start >= 0)
  345.     {
  346.       const char* a = &(s[start]);
  347.       const char* lasta = &(s[sl]);
  348.       while (a < lasta) if (*a++ == c) return --a - s;
  349.     }
  350.     else
  351.     {
  352.       const char* a = &(s[sl + start + 1]);
  353.       while (--a >= s) if (*a == c) return a - s;
  354.     }
  355.   }
  356.   return -1;
  357. }
  358. int String::search(int start, int sl, const char* t, int tl) const
  359. {
  360.   const char* s = chars();
  361.   if (tl < 0) tl = slen(t);
  362.   if (sl > 0 && tl > 0)
  363.   {
  364.     if (start >= 0)
  365.     {
  366.       const char* lasts = &(s[sl - tl]);
  367.       const char* lastt = &(t[tl]);
  368.       const char* p = &(s[start]);
  369.       while (p <= lasts)
  370.       {
  371.         const char* x = p++;
  372.         const char* y = t;
  373.         while (*x++ == *y++) if (y >= lastt) return --p - s;
  374.       }
  375.     }
  376.     else
  377.     {
  378.       const char* firsts = &(s[tl - 1]);
  379.       const char* lastt =  &(t[tl - 1]);
  380.       const char* p = &(s[sl + start + 1]); 
  381.       while (--p >= firsts)
  382.       {
  383.         const char* x = p;
  384.         const char* y = lastt;
  385.         while (*x-- == *y--) if (y < t) return ++x - s;
  386.       }
  387.     }
  388.   }
  389.   return -1;
  390. }
  391. int String::match(int start, int sl, int exact, const char* t, int tl) const
  392. {
  393.   if (tl < 0) tl = slen(t);
  394.   if (start < 0)
  395.   {
  396.     start = sl + start - tl + 1;
  397.     if (start < 0 || (exact && start != 0))
  398.       return -1;
  399.   }
  400.   else if (exact && sl - start != tl)
  401.     return -1;
  402.   if (sl == 0 || tl == 0 || sl - start < tl || start >= sl)
  403.     return -1;
  404.   int n = tl;
  405.   const char* s = &(rep->s[start]);
  406.   while (--n >= 0) if (*s++ != *t++) return -1;
  407.   return tl;
  408. }
  409. void SubString::assign(const StrRep* ysrc, const char* ys, int ylen)
  410. {
  411.   if (&S == &_nilString) return;
  412.   if (ylen < 0) ylen = slen(ys);
  413.   StrRep* targ = S.rep;
  414.   int sl = targ->len - len + ylen;
  415.   if (ysrc == targ || sl >= targ->sz)
  416.   {
  417.     StrRep* oldtarg = targ;
  418.     targ = Sresize(0, sl);
  419.     ncopy(oldtarg->s, targ->s, pos);
  420.     ncopy(ys, &(targ->s[pos]), ylen);
  421.     scopy(&(oldtarg->s[pos + len]), &(targ->s[pos + ylen]));
  422.     delete oldtarg;
  423.   }
  424.   else if (len == ylen)
  425.     ncopy(ys, &(targ->s[pos]), len);
  426.   else if (ylen < len)
  427.   {
  428.     ncopy(ys, &(targ->s[pos]), ylen);
  429.     scopy(&(targ->s[pos + len]), &(targ->s[pos + ylen]));
  430.   }
  431.   else
  432.   {
  433.     revcopy(&(targ->s[targ->len]), &(targ->s[sl]), targ->len-pos-len +1);
  434.     ncopy(ys, &(targ->s[pos]), ylen);
  435.   }
  436.   targ->len = sl;
  437.   S.rep = targ;
  438. }
  439. /*
  440.  * substitution
  441.  */
  442. int String::_gsub(const char* pat, int pl, const char* r, int rl)
  443. {
  444.   int nmatches = 0;
  445.   if (pl < 0) pl = slen(pat);
  446.   if (rl < 0) rl = slen(r);
  447.   int sl = length();
  448.   if (sl <= 0 || pl <= 0 || sl < pl)
  449.     return nmatches;
  450.   
  451.   const char* s = chars();
  452.   // prepare to make new rep
  453.   StrRep* nrep = 0;
  454.   int nsz = 0;
  455.   char* x = 0;
  456.   int si = 0;
  457.   int xi = 0;
  458.   int remaining = sl;
  459.   while (remaining >= pl)
  460.   {
  461.     int pos = search(si, sl, pat, pl);
  462.     if (pos < 0)
  463.       break;
  464.     else
  465.     {
  466.       ++nmatches;
  467.       int mustfit = xi + remaining + rl - pl;
  468.       if (mustfit >= nsz)
  469.       {
  470.         if (nrep != 0) nrep->len = xi;
  471.         nrep = Sresize(nrep, mustfit);
  472.         nsz = nrep->sz;
  473.         x = nrep->s;
  474.       }
  475.       pos -= si;
  476.       ncopy(&(s[si]), &(x[xi]), pos);
  477.       ncopy(r, &(x[xi + pos]), rl);
  478.       si += pos + pl;
  479.       remaining -= pos + pl;
  480.       xi += pos + rl;
  481.     }
  482.   }
  483.   if (nrep == 0)
  484.   {
  485.     if (nmatches == 0)
  486.       return nmatches;
  487.     else
  488.       nrep = Sresize(nrep, xi+remaining);
  489.   }
  490.   ncopy0(&(s[si]), &(x[xi]), remaining);
  491.   nrep->len = xi + remaining;
  492.   if (nrep->len <= rep->sz)   // fit back in if possible
  493.   {
  494.     rep->len = nrep->len;
  495.     ncopy0(nrep->s, rep->s, rep->len);
  496.     delete(nrep);
  497.   }
  498.   else
  499.   {
  500.     delete(rep);
  501.     rep = nrep;
  502.   }
  503.   return nmatches;
  504. }
  505. int String::_gsub(const Regex& pat, const char* r, int rl)
  506. {
  507.   int nmatches = 0;
  508.   int sl = length();
  509.   if (sl <= 0)
  510.     return nmatches;
  511.   if (rl < 0) rl = slen(r);
  512.   const char* s = chars();
  513.   StrRep* nrep = 0;
  514.   int nsz = 0;
  515.   char* x = 0;
  516.   int si = 0;
  517.   int xi = 0;
  518.   int remaining = sl;
  519.   int  pos, pl = 0;   // how long is a regular expression?
  520.   while (remaining > 0)
  521.   {
  522.     pos = pat.search(s, sl, pl, si); // unlike string search, the pos returned here is absolute
  523.     if (pos < 0 || pl <= 0)
  524.       break;
  525.     else
  526.     {
  527.       ++nmatches;
  528.       int mustfit = xi + remaining + rl - pl;
  529.       if (mustfit >= nsz)
  530.       {
  531.         if (nrep != 0) nrep->len = xi;
  532.         nrep = Sresize(nrep, mustfit);
  533.         x = nrep->s;
  534.         nsz = nrep->sz;
  535.       }
  536.       pos -= si;
  537.       ncopy(&(s[si]), &(x[xi]), pos);
  538.       ncopy(r, &(x[xi + pos]), rl);
  539.       si += pos + pl;
  540.       remaining -= pos + pl;
  541.       xi += pos + rl;
  542.     }
  543.   }
  544.   if (nrep == 0)
  545.   {
  546.     if (nmatches == 0)
  547.       return nmatches;
  548.     else
  549.       nrep = Sresize(nrep, xi+remaining);
  550.   }
  551.   ncopy0(&(s[si]), &(x[xi]), remaining);
  552.   nrep->len = xi + remaining;
  553.   if (nrep->len <= rep->sz)   // fit back in if possible
  554.   {
  555.     rep->len = nrep->len;
  556.     ncopy0(nrep->s, rep->s, rep->len);
  557.     delete(nrep);
  558.   }
  559.   else
  560.   {
  561.     delete(rep);
  562.     rep = nrep;
  563.   }
  564.   return nmatches;
  565. }
  566. /*
  567.  * deletion
  568.  */
  569. void String::del(int pos, int len)
  570. {
  571.   if (pos < 0 || len <= 0 || (unsigned)(pos + len) > length()) return;
  572.   int nlen = length() - len;
  573.   int first = pos + len;
  574.   ncopy0(&(rep->s[first]), &(rep->s[pos]), length() - first);
  575.   rep->len = nlen;
  576. }
  577. void String::del(const Regex& r, int startpos)
  578. {
  579.   int mlen;
  580.   int first = r.search(chars(), length(), mlen, startpos);
  581.   del(first, mlen);
  582. }
  583. void String::del(const char* t, int startpos)
  584. {
  585.   int tlen = slen(t);
  586.   int p = search(startpos, length(), t, tlen);
  587.   del(p, tlen);
  588. }
  589. void String::del(const String& y, int startpos)
  590. {
  591.   del(search(startpos, length(), y.chars(), y.length()), y.length());
  592. }
  593. void String::del(const SubString& y, int startpos)
  594. {
  595.   del(search(startpos, length(), y.chars(), y.length()), y.length());
  596. }
  597. void String::del(char c, int startpos)
  598. {
  599.   del(search(startpos, length(), c), 1);
  600. }
  601. /*
  602.  * substring extraction
  603.  */
  604. SubString String::at(int first, int len)
  605. {
  606.   return _substr(first, len);
  607. }
  608. SubString String::operator() (int first, int len)
  609. {
  610.   return _substr(first, len);
  611. }
  612. SubString String::before(int pos)
  613. {
  614.   return _substr(0, pos);
  615. }
  616. SubString String::through(int pos)
  617. {
  618.   return _substr(0, pos+1);
  619. }
  620. SubString String::after(int pos)
  621. {
  622.   return _substr(pos + 1, length() - (pos + 1));
  623. }
  624. SubString String::from(int pos)
  625. {
  626.   return _substr(pos, length() - pos);
  627. }
  628. SubString String::at(const String& y, int startpos)
  629. {
  630.   int first = search(startpos, length(), y.chars(), y.length());
  631.   return _substr(first,  y.length());
  632. }
  633. SubString String::at(const SubString& y, int startpos)
  634. {
  635.   int first = search(startpos, length(), y.chars(), y.length());
  636.   return _substr(first, y.length());
  637. }
  638. SubString String::at(const Regex& r, int startpos)
  639. {
  640.   int mlen;
  641.   int first = r.search(chars(), length(), mlen, startpos);
  642.   return _substr(first, mlen);
  643. }
  644. SubString String::at(const char* t, int startpos)
  645. {
  646.   int tlen = slen(t);
  647.   int first = search(startpos, length(), t, tlen);
  648.   return _substr(first, tlen);
  649. }
  650. SubString String::at(char c, int startpos)
  651. {
  652.   int first = search(startpos, length(), c);
  653.   return _substr(first, 1);
  654. }
  655. SubString String::before(const String& y, int startpos)
  656. {
  657.   int last = search(startpos, length(), y.chars(), y.length());
  658.   return _substr(0, last);
  659. }
  660. SubString String::before(const SubString& y, int startpos)
  661. {
  662.   int last = search(startpos, length(), y.chars(), y.length());
  663.   return _substr(0, last);
  664. }
  665. SubString String::before(const Regex& r, int startpos)
  666. {
  667.   int mlen;
  668.   int first = r.search(chars(), length(), mlen, startpos);
  669.   return _substr(0, first);
  670. }
  671. SubString String::before(char c, int startpos)
  672. {
  673.   int last = search(startpos, length(), c);
  674.   return _substr(0, last);
  675. }
  676. SubString String::before(const char* t, int startpos)
  677. {
  678.   int tlen = slen(t);
  679.   int last = search(startpos, length(), t, tlen);
  680.   return _substr(0, last);
  681. }
  682. SubString String::through(const String& y, int startpos)
  683. {
  684.   int last = search(startpos, length(), y.chars(), y.length());
  685.   if (last >= 0) last += y.length();
  686.   return _substr(0, last);
  687. }
  688. SubString String::through(const SubString& y, int startpos)
  689. {
  690.   int last = search(startpos, length(), y.chars(), y.length());
  691.   if (last >= 0) last += y.length();
  692.   return _substr(0, last);
  693. }
  694. SubString String::through(const Regex& r, int startpos)
  695. {
  696.   int mlen;
  697.   int first = r.search(chars(), length(), mlen, startpos);
  698.   if (first >= 0) first += mlen;
  699.   return _substr(0, first);
  700. }
  701. SubString String::through(char c, int startpos)
  702. {
  703.   int last = search(startpos, length(), c);
  704.   if (last >= 0) last += 1;
  705.   return _substr(0, last);
  706. }
  707. SubString String::through(const char* t, int startpos)
  708. {
  709.   int tlen = slen(t);
  710.   int last = search(startpos, length(), t, tlen);
  711.   if (last >= 0) last += tlen;
  712.   return _substr(0, last);
  713. }
  714. SubString String::after(const String& y, int startpos)
  715. {
  716.   int first = search(startpos, length(), y.chars(), y.length());
  717.   if (first >= 0) first += y.length();
  718.   return _substr(first, length() - first);
  719. }
  720. SubString String::after(const SubString& y, int startpos)
  721. {
  722.   int first = search(startpos, length(), y.chars(), y.length());
  723.   if (first >= 0) first += y.length();
  724.   return _substr(first, length() - first);
  725. }
  726. SubString String::after(char c, int startpos)
  727. {
  728.   int first = search(startpos, length(), c);
  729.   if (first >= 0) first += 1;
  730.   return _substr(first, length() - first);
  731. }
  732. SubString String::after(const Regex& r, int startpos)
  733. {
  734.   int mlen;
  735.   int first = r.search(chars(), length(), mlen, startpos);
  736.   if (first >= 0) first += mlen;
  737.   return _substr(first, length() - first);
  738. }
  739. SubString String::after(const char* t, int startpos)
  740. {
  741.   int tlen = slen(t);
  742.   int first = search(startpos, length(), t, tlen);
  743.   if (first >= 0) first += tlen;
  744.   return _substr(first, length() - first);
  745. }
  746. SubString String::from(const String& y, int startpos)
  747. {
  748.   int first = search(startpos, length(), y.chars(), y.length());
  749.   return _substr(first, length() - first);
  750. }
  751. SubString String::from(const SubString& y, int startpos)
  752. {
  753.   int first = search(startpos, length(), y.chars(), y.length());
  754.   return _substr(first, length() - first);
  755. }
  756. SubString String::from(const Regex& r, int startpos)
  757. {
  758.   int mlen;
  759.   int first = r.search(chars(), length(), mlen, startpos);
  760.   return _substr(first, length() - first);
  761. }
  762. SubString String::from(char c, int startpos)
  763. {
  764.   int first = search(startpos, length(), c);
  765.   return _substr(first, length() - first);
  766. }
  767. SubString String::from(const char* t, int startpos)
  768. {
  769.   int tlen = slen(t);
  770.   int first = search(startpos, length(), t, tlen);
  771.   return _substr(first, length() - first);
  772. }
  773. /*
  774.  * split/join
  775.  */
  776. int split(const String& src, String results[], int n, const String& sep)
  777. {
  778.   String x = src;
  779.   const char* s = x.chars();
  780.   int sl = x.length();
  781.   int i = 0;
  782.   int pos = 0;
  783.   while (i < n && pos < sl)
  784.   {
  785.     int p = x.search(pos, sl, sep.chars(), sep.length());
  786.     if (p < 0)
  787.       p = sl;
  788.     results[i].rep = Salloc(results[i].rep, &(s[pos]), p - pos, p - pos);
  789.     i++;
  790.     pos = p + sep.length();
  791.   }
  792.   return i;
  793. }
  794. int split(const String& src, String results[], int n, const Regex& r)
  795. {
  796.   String x = src;
  797.   const char* s = x.chars();
  798.   int sl = x.length();
  799.   int i = 0;
  800.   int pos = 0;
  801.   int p, matchlen;
  802.   while (i < n && pos < sl)
  803.   {
  804.     p = r.search(s, sl, matchlen, pos);
  805.     if (p < 0)
  806.       p = sl;
  807.     results[i].rep = Salloc(results[i].rep, &(s[pos]), p - pos, p - pos);
  808.     i++;
  809.     pos = p + matchlen;
  810.   }
  811.   return i;
  812. }
  813. #if defined(__GNUG__) && !defined(_G_NO_NRV)
  814. #define RETURN(r) return
  815. #define RETURNS(r) return r;
  816. #define RETURN_OBJECT(TYPE, NAME) /* nothing */
  817. #else /* _G_NO_NRV */
  818. #define RETURN(r) return r
  819. #define RETURNS(r) /* nothing */
  820. #define RETURN_OBJECT(TYPE, NAME) TYPE NAME;
  821. #endif
  822. String join(String src[], int n, const String& separator) RETURNS(x)
  823. {
  824.   RETURN_OBJECT(String,x)
  825.   int i;
  826.   String sep = separator;
  827.   int xlen = 0;
  828.   for (int i = 0; i < n; ++i)
  829.     xlen += src[i].length();
  830.   xlen += (n - 1) * sep.length();
  831.   x.rep = Sresize (x.rep, xlen);
  832.   int j = 0;
  833.   
  834.   for (i = 0; i < n - 1; ++i)
  835.   {
  836.     ncopy(src[i].chars(), &(x.rep->s[j]), src[i].length());
  837.     j += src[i].length();
  838.     ncopy(sep.chars(), &(x.rep->s[j]), sep.length());
  839.     j += sep.length();
  840.   }
  841.   ncopy0(src[i].chars(), &(x.rep->s[j]), src[i].length());
  842.   RETURN(x);
  843. }
  844.   
  845. /*
  846.  misc
  847. */
  848.     
  849. StrRep* Sreverse(const StrRep* src, StrRep* dest)
  850. {
  851.   int n = src->len;
  852.   if (src != dest)
  853.     dest = Salloc(dest, src->s, n, n);
  854.   if (n > 0)
  855.   {
  856.     char* a = dest->s;
  857.     char* b = &(a[n - 1]);
  858.     while (a < b)
  859.     {
  860.       char t = *a;
  861.       *a++ = *b;
  862.       *b-- = t;
  863.     }
  864.   }
  865.   return dest;
  866. }
  867. StrRep* Supcase(const StrRep* src, StrRep* dest)
  868. {
  869.   int n = src->len;
  870.   if (src != dest) dest = Salloc(dest, src->s, n, n);
  871.   char* p = dest->s;
  872.   char* e = &(p[n]);
  873.   for (; p < e; ++p) if (islower(*p)) *p = toupper(*p);
  874.   return dest;
  875. }
  876. StrRep* Sdowncase(const StrRep* src, StrRep* dest)
  877. {
  878.   int n = src->len;
  879.   if (src != dest) dest = Salloc(dest, src->s, n, n);
  880.   char* p = dest->s;
  881.   char* e = &(p[n]);
  882.   for (; p < e; ++p) if (isupper(*p)) *p = tolower(*p);
  883.   return dest;
  884. }
  885. StrRep* Scapitalize(const StrRep* src, StrRep* dest)
  886. {
  887.   int n = src->len;
  888.   if (src != dest) dest = Salloc(dest, src->s, n, n);
  889.   char* p = dest->s;
  890.   char* e = &(p[n]);
  891.   for (; p < e; ++p)
  892.   {
  893.     int at_word;
  894.     if ((at_word = islower(*p)))
  895.       *p = toupper(*p);
  896.     else 
  897.       at_word = isupper(*p) || isdigit(*p);
  898.     if (at_word)
  899.     {
  900.       while (++p < e)
  901.       {
  902.         if (isupper(*p))
  903.           *p = tolower(*p);
  904. /* A ''' does not break a word, so that "Nathan's" stays
  905.    "Nathan's" rather than turning into "Nathan'S". */
  906.         else if (!islower(*p) && !isdigit(*p) && (*p != '''))
  907.           break;
  908.       }
  909.     }
  910.   }
  911.   return dest;
  912. }
  913. #if defined(__GNUG__) && !defined(_G_NO_NRV)
  914. String replicate(char c, int n) return w;
  915. {
  916.   w.rep = Sresize(w.rep, n);
  917.   char* p = w.rep->s;
  918.   while (n-- > 0) *p++ = c;
  919.   *p = 0;
  920. }
  921. String replicate(const String& y, int n) return w
  922. {
  923.   int len = y.length();
  924.   w.rep = Sresize(w.rep, n * len);
  925.   char* p = w.rep->s;
  926.   while (n-- > 0)
  927.   {
  928.     ncopy(y.chars(), p, len);
  929.     p += len;
  930.   }
  931.   *p = 0;
  932. }
  933. String common_prefix(const String& x, const String& y, int startpos) return r;
  934. {
  935.   int l;
  936.   const char* xchars = x.chars();
  937.   const char* ychars = y.chars();
  938.   const char* xs = &(xchars[startpos]);
  939.   const char* ss = xs;
  940.   const char* topx = &(xchars[x.length()]);
  941.   const char* ys = &(ychars[startpos]);
  942.   const char* topy = &(ychars[y.length()]);
  943.   for (l = 0; xs < topx && ys < topy && *xs++ == *ys++; ++l);
  944.   r.rep = Salloc(r.rep, ss, l, l);
  945. }
  946. String common_suffix(const String& x, const String& y, int startpos) return r;
  947. {
  948.   int l;
  949.   const char* xchars = x.chars();
  950.   const char* ychars = y.chars();
  951.   const char* xs = &(xchars[x.length() + startpos]);
  952.   const char* botx = xchars;
  953.   const char* ys = &(ychars[y.length() + startpos]);
  954.   const char* boty = ychars;
  955.   for (l = 0; xs >= botx && ys >= boty && *xs == *ys ; --xs, --ys, ++l);
  956.   r.rep = Salloc(r.rep, ++xs, l, l);
  957. }
  958. #else
  959. String replicate(char c, int n)
  960. {
  961.   String w;
  962.   w.rep = Sresize(w.rep, n);
  963.   char* p = w.rep->s;
  964.   while (n-- > 0) *p++ = c;
  965.   *p = 0;
  966.   return w;
  967. }
  968. String replicate(const String& y, int n)
  969. {
  970.   String w;
  971.   int len = y.length();
  972.   w.rep = Sresize(w.rep, n * len);
  973.   char* p = w.rep->s;
  974.   while (n-- > 0)
  975.   {
  976.     ncopy(y.chars(), p, len);
  977.     p += len;
  978.   }
  979.   *p = 0;
  980.   return w;
  981. }
  982. String common_prefix(const String& x, const String& y, int startpos)
  983. {
  984.   String r;
  985.   const char* xchars = x.chars();
  986.   const char* ychars = y.chars();
  987.   const char* xs = &(xchars[startpos]);
  988.   const char* ss = xs;
  989.   const char* topx = &(xchars[x.length()]);
  990.   const char* ys = &(ychars[startpos]);
  991.   const char* topy = &(ychars[y.length()]);
  992.   for (int l = 0; xs < topx && ys < topy && *xs++ == *ys++; ++l);
  993.   r.rep = Salloc(r.rep, ss, l, l);
  994.   return r;
  995. }
  996. String common_suffix(const String& x, const String& y, int startpos) 
  997. {
  998.   String r;
  999.   const char* xchars = x.chars();
  1000.   const char* ychars = y.chars();
  1001.   const char* xs = &(xchars[x.length() + startpos]);
  1002.   const char* botx = xchars;
  1003.   const char* ys = &(ychars[y.length() + startpos]);
  1004.   const char* boty = ychars;
  1005.   for (int l = 0; xs >= botx && ys >= boty && *xs == *ys ; --xs, --ys, ++l);
  1006.   r.rep = Salloc(r.rep, ++xs, l, l);
  1007.   return r;
  1008. }
  1009. #endif
  1010. // IO
  1011. istream& operator>>(istream& s, String& x)
  1012. {
  1013.   if (!s.ipfx(0) || (!(s.flags() & ios::skipws) && !ws(s)))
  1014.   {
  1015.     s.clear(ios::failbit|s.rdstate()); // Redundant if using GNU iostreams.
  1016.     return s;
  1017.   }
  1018.   int ch;
  1019.   int i = 0;
  1020.   x.rep = Sresize(x.rep, 20);
  1021.   register streambuf *sb = s.rdbuf();
  1022.   while ((ch = sb->sbumpc()) != EOF)
  1023.   {
  1024.     if (isspace(ch))
  1025.       break;
  1026.     if (i >= x.rep->sz - 1)
  1027.       x.rep = Sresize(x.rep, i+1);
  1028.     x.rep->s[i++] = ch;
  1029.   }
  1030.   x.rep->s[i] = 0;
  1031.   x.rep->len = i;
  1032.   int new_state = s.rdstate();
  1033.   if (i == 0) new_state |= ios::failbit;
  1034.   if (ch == EOF) new_state |= ios::eofbit;
  1035.   s.clear(new_state);
  1036.   return s;
  1037. }
  1038. int readline(istream& s, String& x, char terminator, int discard)
  1039. {
  1040.   if (!s.ipfx(0))
  1041.     return 0;
  1042.   int ch;
  1043.   int i = 0;
  1044.   x.rep = Sresize(x.rep, 80);
  1045.   register streambuf *sb = s.rdbuf();
  1046.   while ((ch = sb->sbumpc()) != EOF)
  1047.   {
  1048.     if (ch != terminator || !discard)
  1049.     {
  1050.       if (i >= x.rep->sz - 1)
  1051.         x.rep = Sresize(x.rep, i+1);
  1052.       x.rep->s[i++] = ch;
  1053.     }
  1054.     if (ch == terminator)
  1055.       break;
  1056.   }
  1057.   x.rep->s[i] = 0;
  1058.   x.rep->len = i;
  1059.   if (ch == EOF) s.clear(ios::eofbit|s.rdstate());
  1060.   return i;
  1061. }
  1062. ostream& operator<<(ostream& s, const SubString& x)
  1063.   const char* a = x.chars();
  1064.   const char* lasta = &(a[x.length()]);
  1065.   while (a < lasta)
  1066.     s.put(*a++);
  1067.   return(s);
  1068. }
  1069. // from John.Willis@FAS.RI.CMU.EDU
  1070. int String::freq(const SubString& y) const
  1071. {
  1072.   int found = 0;
  1073.   for (unsigned int i = 0; i < length(); i++) 
  1074.     if (match(i,length(),0,y.chars(), y.length())>= 0) found++;
  1075.   return(found);
  1076. }
  1077. int String::freq(const String& y) const
  1078. {
  1079.   int found = 0;
  1080.   for (unsigned int i = 0; i < length(); i++) 
  1081.     if (match(i,length(),0,y.chars(),y.length()) >= 0) found++;
  1082.   return(found);
  1083. }
  1084. int String::freq(const char* t) const
  1085. {
  1086.   int found = 0;
  1087.   for (unsigned int i = 0; i < length(); i++) 
  1088.     if (match(i,length(),0,t) >= 0) found++;
  1089.   return(found);
  1090. }
  1091. int String::freq(char c) const
  1092. {
  1093.   int found = 0;
  1094.   for (unsigned int i = 0; i < length(); i++) 
  1095.     if (match(i,length(),0,&c,1) >= 0) found++;
  1096.   return(found);
  1097. }
  1098. int String::OK() const
  1099. {
  1100.   if (rep == 0             // don't have a rep
  1101.     || rep->len > rep->sz     // string oustide bounds
  1102.     || rep->s[rep->len] != 0)   // not null-terminated
  1103.       error("invariant failure");
  1104.   return 1;
  1105. }
  1106. int SubString::OK() const
  1107. {
  1108.   int v = S != (const char*)0; // have a String;
  1109.   v &= S.OK();                 // that is legal
  1110.   v &= pos + len >= S.rep->len;// pos and len within bounds
  1111.   if (!v) S.error("SubString invariant failure");
  1112.   return v;
  1113. }