home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / libg++-2.7.1-bin.lha / lib / g++-include / String.h < prev    next >
C/C++ Source or Header  |  1996-10-12  |  34KB  |  1,285 lines

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /* 
  3. Copyright (C) 1988 Free Software Foundation
  4.     written by Doug Lea (dl@rocky.oswego.edu)
  5.  
  6. This file is part of the GNU C++ Library.  This library is free
  7. software; you can redistribute it and/or modify it under the terms of
  8. the GNU Library General Public License as published by the Free
  9. Software Foundation; either version 2 of the License, or (at your
  10. option) any later version.  This library is distributed in the hope
  11. that it will be useful, but WITHOUT ANY WARRANTY; without even the
  12. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  13. PURPOSE.  See the GNU Library General Public License for more details.
  14. You should have received a copy of the GNU Library General Public
  15. License along with this library; if not, write to the Free Software
  16. Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18.  
  19.  
  20. #ifndef _String_h
  21. #ifdef __GNUG__
  22. #pragma interface
  23. #endif
  24. #define _String_h 1
  25.  
  26. #include <iostream.h>
  27. #include <Regex.h>
  28.  
  29. #undef OK
  30.  
  31. struct StrRep                     // internal String representations
  32. {
  33.   unsigned short    len;         // string length 
  34.   unsigned short    sz;          // allocated space
  35.   char              s[1];        // the string starts here 
  36.                                  // (at least 1 char for trailing null)
  37.                                  // allocated & expanded via non-public fcts
  38. };
  39.  
  40. // primitive ops on StrReps -- nearly all String fns go through these.
  41.  
  42. StrRep*     Salloc(StrRep*, const char*, int, int);
  43. StrRep*     Scopy(StrRep*, const StrRep*);
  44. StrRep*     Scat(StrRep*, const char*, int, const char*, int);
  45. StrRep*     Scat(StrRep*, const char*, int,const char*,int, const char*,int);
  46. StrRep*     Sprepend(StrRep*, const char*, int);
  47. StrRep*     Sreverse(const StrRep*, StrRep*);
  48. StrRep*     Supcase(const StrRep*, StrRep*);
  49. StrRep*     Sdowncase(const StrRep*, StrRep*);
  50. StrRep*     Scapitalize(const StrRep*, StrRep*);
  51.  
  52. // These classes need to be defined in the order given
  53.  
  54. class String;
  55. class SubString;
  56.  
  57. class SubString
  58. {
  59.   friend class      String;
  60. protected:
  61.  
  62.   String&           S;        // The String I'm a substring of
  63.   unsigned short    pos;      // starting position in S's rep
  64.   unsigned short    len;      // length of substring
  65.  
  66.   void              assign(const StrRep*, const char*, int = -1);
  67.                     SubString(String& x, int p, int l);
  68.                     SubString(const SubString& x);
  69.  
  70. public:
  71.  
  72. // Note there are no public constructors. SubStrings are always
  73. // created via String operations
  74.  
  75.                    ~SubString();
  76.  
  77.   SubString&        operator =  (const String&     y);
  78.   SubString&        operator =  (const SubString&  y);
  79.   SubString&        operator =  (const char* t);
  80.   SubString&        operator =  (char        c);
  81.  
  82. // return 1 if target appears anywhere in SubString; else 0
  83.  
  84.   int               contains(char        c) const;
  85.   int               contains(const String&     y) const;
  86.   int               contains(const SubString&  y) const;
  87.   int               contains(const char* t) const;
  88.   int               contains(const Regex&       r) const;
  89.  
  90. // return 1 if target matches entire SubString
  91.  
  92.   int               matches(const Regex&  r) const;
  93.  
  94. // IO 
  95.  
  96.   friend ostream&   operator<<(ostream& s, const SubString& x);
  97.  
  98. // status
  99.  
  100.   unsigned int      length() const;
  101.   int               empty() const;
  102.   const char*       chars() const;
  103.  
  104.   int               OK() const; 
  105.  
  106. };
  107.  
  108.  
  109. class String
  110. {
  111.   friend class      SubString;
  112.  
  113. protected:
  114.   StrRep*           rep;   // Strings are pointers to their representations
  115.  
  116. // some helper functions
  117.  
  118.   int               search(int, int, const char*, int = -1) const;
  119.   int               search(int, int, char) const;
  120.   int               match(int, int, int, const char*, int = -1) const;
  121.   int               _gsub(const char*, int, const char* ,int);
  122.   int               _gsub(const Regex&, const char*, int);
  123.   SubString         _substr(int, int);
  124.  
  125. public:
  126.  
  127. // constructors & assignment
  128.  
  129.                     String();
  130.                     String(const String& x);
  131.                     String(const SubString&  x);
  132.                     String(const char* t);
  133.                     String(const char* t, int len);
  134.                     String(char c);
  135.  
  136.                     ~String();
  137.  
  138.   String&           operator =  (const String&     y);
  139.   String&           operator =  (const char* y);
  140.   String&           operator =  (char        c);
  141.   String&           operator =  (const SubString&  y);
  142.  
  143. // concatenation
  144.  
  145.   String&           operator += (const String&     y); 
  146.   String&           operator += (const SubString&  y);
  147.   String&           operator += (const char* t);
  148.   String&           operator += (char        c);
  149.  
  150.   void              prepend(const String&     y); 
  151.   void              prepend(const SubString&  y);
  152.   void              prepend(const char* t);
  153.   void              prepend(char        c);
  154.  
  155.  
  156. // procedural versions:
  157. // concatenate first 2 args, store result in last arg
  158.  
  159.   friend inline void     cat(const String&, const String&, String&);
  160.   friend inline void     cat(const String&, const SubString&, String&);
  161.   friend inline void     cat(const String&, const char*, String&);
  162.   friend inline void     cat(const String&, char, String&);
  163.  
  164.   friend inline void     cat(const SubString&, const String&, String&);
  165.   friend inline void     cat(const SubString&, const SubString&, String&);
  166.   friend inline void     cat(const SubString&, const char*, String&);
  167.   friend inline void     cat(const SubString&, char, String&);
  168.  
  169.   friend inline void     cat(const char*, const String&, String&);
  170.   friend inline void     cat(const char*, const SubString&, String&);
  171.   friend inline void     cat(const char*, const char*, String&);
  172.   friend inline void     cat(const char*, char, String&);
  173.  
  174. // double concatenation, by request. (yes, there are too many versions, 
  175. // but if one is supported, then the others should be too...)
  176. // Concatenate first 3 args, store in last arg
  177.  
  178.   friend inline void     cat(const String&,const String&, const String&,String&);
  179.   friend inline void     cat(const String&,const String&,const SubString&,String&);
  180.   friend inline void     cat(const String&,const String&, const char*, String&);
  181.   friend inline void     cat(const String&,const String&, char, String&);
  182.   friend inline void     cat(const String&,const SubString&,const String&,String&);
  183.   inline friend void     cat(const String&,const SubString&,const SubString&,String&);
  184.   friend inline void     cat(const String&,const SubString&, const char*, String&);
  185.   friend inline void     cat(const String&,const SubString&, char, String&);
  186.   friend inline void     cat(const String&,const char*, const String&,    String&);
  187.   friend inline void     cat(const String&,const char*, const SubString&, String&);
  188.   friend inline void     cat(const String&,const char*, const char*, String&);
  189.   friend inline void     cat(const String&,const char*, char, String&);
  190.  
  191.   friend inline void     cat(const char*, const String&, const String&,String&);
  192.   friend inline void     cat(const char*,const String&,const SubString&,String&);
  193.   friend inline void     cat(const char*,const String&, const char*, String&);
  194.   friend inline void     cat(const char*,const String&, char, String&);
  195.   friend inline void     cat(const char*,const SubString&,const String&,String&);
  196.   friend inline void     cat(const char*,const SubString&,const SubString&,String&);
  197.   friend inline void     cat(const char*,const SubString&, const char*, String&);
  198.   friend inline void     cat(const char*,const SubString&, char, String&);
  199.   friend inline void     cat(const char*,const char*, const String&,    String&);
  200.   friend inline void     cat(const char*,const char*, const SubString&, String&);
  201.   friend inline void     cat(const char*,const char*, const char*, String&);
  202.   friend inline void     cat(const char*,const char*, char, String&);
  203.  
  204.  
  205. // searching & matching
  206.  
  207. // return position of target in string or -1 for failure
  208.  
  209.   int               index(char        c, int startpos = 0) const;      
  210.   int               index(const String&     y, int startpos = 0) const;      
  211.   int               index(const SubString&  y, int startpos = 0) const;      
  212.   int               index(const char* t, int startpos = 0) const;  
  213.   int               index(const Regex&      r, int startpos = 0) const;       
  214.  
  215. // return 1 if target appears anyhere in String; else 0
  216.  
  217.   int               contains(char        c) const;
  218.   int               contains(const String&     y) const;
  219.   int               contains(const SubString&  y) const;
  220.   int               contains(const char* t) const;
  221.   int               contains(const Regex&      r) const;
  222.  
  223. // return 1 if target appears anywhere after position pos 
  224. // (or before, if pos is negative) in String; else 0
  225.  
  226.   int               contains(char        c, int pos) const;
  227.   int               contains(const String&     y, int pos) const;
  228.   int               contains(const SubString&  y, int pos) const;
  229.   int               contains(const char* t, int pos) const;
  230.   int               contains(const Regex&      r, int pos) const;
  231.  
  232. // return 1 if target appears at position pos in String; else 0
  233.  
  234.   int               matches(char        c, int pos = 0) const;
  235.   int               matches(const String&     y, int pos = 0) const;
  236.   int               matches(const SubString&  y, int pos = 0) const;
  237.   int               matches(const char* t, int pos = 0) const;
  238.   int               matches(const Regex&      r, int pos = 0) const;
  239.  
  240. //  return number of occurences of target in String
  241.  
  242.   int               freq(char        c) const; 
  243.   int               freq(const String&     y) const;
  244.   int               freq(const SubString&  y) const;
  245.   int               freq(const char* t) const;
  246.  
  247. // SubString extraction
  248.  
  249. // Note that you can't take a substring of a const String, since
  250. // this leaves open the possiblility of indirectly modifying the
  251. // String through the SubString
  252.  
  253.   SubString         at(int         pos, int len);
  254.   SubString         operator () (int         pos, int len); // synonym for at
  255.  
  256.   SubString         at(const String&     x, int startpos = 0); 
  257.   SubString         at(const SubString&  x, int startpos = 0); 
  258.   SubString         at(const char* t, int startpos = 0);
  259.   SubString         at(char        c, int startpos = 0);
  260.   SubString         at(const Regex&      r, int startpos = 0); 
  261.  
  262.   SubString         before(int          pos);
  263.   SubString         before(const String&      x, int startpos = 0);
  264.   SubString         before(const SubString&   x, int startpos = 0);
  265.   SubString         before(const char*  t, int startpos = 0);
  266.   SubString         before(char         c, int startpos = 0);
  267.   SubString         before(const Regex&       r, int startpos = 0);
  268.  
  269.   SubString         through(int          pos);
  270.   SubString         through(const String&      x, int startpos = 0);
  271.   SubString         through(const SubString&   x, int startpos = 0);
  272.   SubString         through(const char*  t, int startpos = 0);
  273.   SubString         through(char         c, int startpos = 0);
  274.   SubString         through(const Regex&       r, int startpos = 0);
  275.  
  276.   SubString         from(int          pos);
  277.   SubString         from(const String&      x, int startpos = 0);
  278.   SubString         from(const SubString&   x, int startpos = 0);
  279.   SubString         from(const char*  t, int startpos = 0);
  280.   SubString         from(char         c, int startpos = 0);
  281.   SubString         from(const Regex&       r, int startpos = 0);
  282.  
  283.   SubString         after(int         pos);
  284.   SubString         after(const String&     x, int startpos = 0);
  285.   SubString         after(const SubString&  x, int startpos = 0);
  286.   SubString         after(const char* t, int startpos = 0);
  287.   SubString         after(char        c, int startpos = 0);
  288.   SubString         after(const Regex&      r, int startpos = 0);
  289.  
  290.  
  291. // deletion
  292.  
  293. // delete len chars starting at pos
  294.   void              del(int         pos, int len);
  295.  
  296. // delete the first occurrence of target after startpos
  297.  
  298.   void              del(const String&     y, int startpos = 0);
  299.   void              del(const SubString&  y, int startpos = 0);
  300.   void              del(const char* t, int startpos = 0);
  301.   void              del(char        c, int startpos = 0);
  302.   void              del(const Regex&      r, int startpos = 0);
  303.  
  304. // global substitution: substitute all occurrences of pat with repl
  305.  
  306.   int               gsub(const String&     pat, const String&     repl);
  307.   int               gsub(const SubString&  pat, const String&     repl);
  308.   int               gsub(const char* pat, const String&     repl);
  309.   int               gsub(const char* pat, const char* repl);
  310.   int               gsub(const Regex&      pat, const String&     repl);
  311.  
  312. // friends & utilities
  313.  
  314. // split string into array res at separators; return number of elements
  315.  
  316.   friend int        split(const String& x, String res[], int maxn, 
  317.                           const String& sep);
  318.   friend int        split(const String& x, String res[], int maxn, 
  319.                           const Regex&  sep);
  320.  
  321.   friend String     common_prefix(const String& x, const String& y, 
  322.                                   int startpos = 0);
  323.   friend String     common_suffix(const String& x, const String& y, 
  324.                                   int startpos = -1);
  325.   friend String     replicate(char        c, int n);
  326.   friend String     replicate(const String&     y, int n);
  327.   friend String     join(String src[], int n, const String& sep);
  328.  
  329. // simple builtin transformations
  330.  
  331.   friend inline String     reverse(const String& x);
  332.   friend inline String     upcase(const String& x);
  333.   friend inline String     downcase(const String& x);
  334.   friend inline String     capitalize(const String& x);
  335.  
  336. // in-place versions of above
  337.  
  338.   void              reverse();
  339.   void              upcase();
  340.   void              downcase();
  341.   void              capitalize();
  342.  
  343. // element extraction
  344.  
  345.   char&             operator [] (int i);
  346.   const char&       operator [] (int i) const;
  347.   char              elem(int i) const;
  348.   char              firstchar() const;
  349.   char              lastchar() const;
  350.  
  351. // conversion
  352.  
  353.                     operator const char*() const;
  354.   const char*       chars() const;
  355.  
  356.  
  357. // IO
  358.  
  359.   friend inline ostream&   operator<<(ostream& s, const String& x);
  360.   friend ostream&   operator<<(ostream& s, const SubString& x);
  361.   friend istream&   operator>>(istream& s, String& x);
  362.  
  363.   friend int        readline(istream& s, String& x, 
  364.                              char terminator = '\n',
  365.                              int discard_terminator = 1);
  366.  
  367. // status
  368.  
  369.   unsigned int      length() const;
  370.   int               empty() const;
  371.  
  372. // preallocate some space for String
  373.   void              alloc(int newsize);
  374.  
  375. // report current allocation (not length!)
  376.  
  377.   int               allocation() const;
  378.  
  379.  
  380.   void     error(const char* msg) const;
  381.  
  382.   int               OK() const;
  383. };
  384.  
  385. typedef String StrTmp; // for backward compatibility
  386.  
  387. // other externs
  388.  
  389. int        compare(const String&    x, const String&     y);
  390. int        compare(const String&    x, const SubString&  y);
  391. int        compare(const String&    x, const char* y);
  392. int        compare(const SubString& x, const String&     y);
  393. int        compare(const SubString& x, const SubString&  y);
  394. int        compare(const SubString& x, const char* y);
  395. int        fcompare(const String&   x, const String&     y); // ignore case
  396.  
  397. extern StrRep  _nilStrRep;
  398. extern String _nilString;
  399.  
  400. // status reports, needed before defining other things
  401.  
  402. inline unsigned int String::length() const {  return rep->len; }
  403. inline int         String::empty() const { return rep->len == 0; }
  404. inline const char* String::chars() const { return &(rep->s[0]); }
  405. inline int         String::allocation() const { return rep->sz; }
  406.  
  407. inline unsigned int SubString::length() const { return len; }
  408. inline int         SubString::empty() const { return len == 0; }
  409. inline const char* SubString::chars() const { return &(S.rep->s[pos]); }
  410.  
  411.  
  412. // constructors
  413.  
  414. inline String::String() 
  415.   : rep(&_nilStrRep) {}
  416. inline String::String(const String& x) 
  417.   : rep(Scopy(0, x.rep)) {}
  418. inline String::String(const char* t) 
  419.   : rep(Salloc(0, t, -1, -1)) {}
  420. inline String::String(const char* t, int tlen)
  421.   : rep(Salloc(0, t, tlen, tlen)) {}
  422. inline String::String(const SubString& y)
  423.   : rep(Salloc(0, y.chars(), y.length(), y.length())) {}
  424. inline String::String(char c) 
  425.   : rep(Salloc(0, &c, 1, 1)) {}
  426.  
  427. inline String::~String() { if (rep != &_nilStrRep) delete rep; }
  428.  
  429. inline SubString::SubString(const SubString& x)
  430.   :S(x.S), pos(x.pos), len(x.len) {}
  431. inline SubString::SubString(String& x, int first, int l)
  432.   :S(x), pos(first), len(l) {}
  433.  
  434. inline SubString::~SubString() {}
  435.  
  436. // assignment
  437.  
  438. inline String& String::operator =  (const String& y)
  439.   rep = Scopy(rep, y.rep);
  440.   return *this;
  441. }
  442.  
  443. inline String& String::operator=(const char* t)
  444. {
  445.   rep = Salloc(rep, t, -1, -1);
  446.   return *this;
  447. }
  448.  
  449. inline String& String::operator=(const SubString&  y)
  450. {
  451.   rep = Salloc(rep, y.chars(), y.length(), y.length());
  452.   return *this;
  453. }
  454.  
  455. inline String& String::operator=(char c)
  456. {
  457.   rep = Salloc(rep, &c, 1, 1);
  458.   return *this;
  459. }
  460.  
  461.  
  462. inline SubString& SubString::operator = (const char* ys)
  463. {
  464.   assign(0, ys);
  465.   return *this;
  466. }
  467.  
  468. inline SubString& SubString::operator = (char ch)
  469. {
  470.   assign(0, &ch, 1);
  471.   return *this;
  472. }
  473.  
  474. inline SubString& SubString::operator = (const String& y)
  475. {
  476.   assign(y.rep, y.chars(), y.length());
  477.   return *this;
  478. }
  479.  
  480. inline SubString& SubString::operator = (const SubString& y)
  481. {
  482.   assign(y.S.rep, y.chars(), y.length());
  483.   return *this;
  484. }
  485.  
  486. // Zillions of cats...
  487.  
  488. inline void cat(const String& x, const String& y, String& r)
  489. {
  490.   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
  491. }
  492.  
  493. inline void cat(const String& x, const SubString& y, String& r)
  494. {
  495.   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
  496. }
  497.  
  498. inline void cat(const String& x, const char* y, String& r)
  499. {
  500.   r.rep = Scat(r.rep, x.chars(), x.length(), y, -1);
  501. }
  502.  
  503. inline void cat(const String& x, char y, String& r)
  504. {
  505.   r.rep = Scat(r.rep, x.chars(), x.length(), &y, 1);
  506. }
  507.  
  508. inline void cat(const SubString& x, const String& y, String& r)
  509. {
  510.   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
  511. }
  512.  
  513. inline void cat(const SubString& x, const SubString& y, String& r)
  514. {
  515.   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
  516. }
  517.  
  518. inline void cat(const SubString& x, const char* y, String& r)
  519. {
  520.   r.rep = Scat(r.rep, x.chars(), x.length(), y, -1);
  521. }
  522.  
  523. inline void cat(const SubString& x, char y, String& r)
  524. {
  525.   r.rep = Scat(r.rep, x.chars(), x.length(), &y, 1);
  526. }
  527.  
  528. inline void cat(const char* x, const String& y, String& r)
  529. {
  530.   r.rep = Scat(r.rep, x, -1, y.chars(), y.length());
  531. }
  532.  
  533. inline void cat(const char* x, const SubString& y, String& r)
  534. {
  535.   r.rep = Scat(r.rep, x, -1, y.chars(), y.length());
  536. }
  537.  
  538. inline void cat(const char* x, const char* y, String& r)
  539. {
  540.   r.rep = Scat(r.rep, x, -1, y, -1);
  541. }
  542.  
  543. inline void cat(const char* x, char y, String& r)
  544. {
  545.   r.rep = Scat(r.rep, x, -1, &y, 1);
  546. }
  547.  
  548. inline void cat(const String& a, const String& x, const String& y, String& r)
  549. {
  550.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
  551. }
  552.  
  553. inline void cat(const String& a, const String& x, const SubString& y, String& r)
  554. {
  555.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
  556. }
  557.  
  558. inline void cat(const String& a, const String& x, const char* y, String& r)
  559. {
  560.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y, -1);
  561. }
  562.  
  563. inline void cat(const String& a, const String& x, char y, String& r)
  564. {
  565.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), &y, 1);
  566. }
  567.  
  568. inline void cat(const String& a, const SubString& x, const String& y, String& r)
  569. {
  570.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
  571. }
  572.  
  573. inline void cat(const String& a, const SubString& x, const SubString& y, String& r)
  574. {
  575.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
  576. }
  577.  
  578. inline void cat(const String& a, const SubString& x, const char* y, String& r)
  579. {
  580.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y, -1);
  581. }
  582.  
  583. inline void cat(const String& a, const SubString& x, char y, String& r)
  584. {
  585.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), &y, 1);
  586. }
  587.  
  588. inline void cat(const String& a, const char* x, const String& y, String& r)
  589. {
  590.   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y.chars(), y.length());
  591. }
  592.  
  593. inline void cat(const String& a, const char* x, const SubString& y, String& r)
  594. {
  595.   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y.chars(), y.length());
  596. }
  597.  
  598. inline void cat(const String& a, const char* x, const char* y, String& r)
  599. {
  600.   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y, -1);
  601. }
  602.  
  603. inline void cat(const String& a, const char* x, char y, String& r)
  604. {
  605.   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, &y, 1);
  606. }
  607.  
  608.  
  609. inline void cat(const char* a, const String& x, const String& y, String& r)
  610. {
  611.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
  612. }
  613.  
  614. inline void cat(const char* a, const String& x, const SubString& y, String& r)
  615. {
  616.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
  617. }
  618.  
  619. inline void cat(const char* a, const String& x, const char* y, String& r)
  620. {
  621.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y, -1);
  622. }
  623.  
  624. inline void cat(const char* a, const String& x, char y, String& r)
  625. {
  626.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), &y, 1);
  627. }
  628.  
  629. inline void cat(const char* a, const SubString& x, const String& y, String& r)
  630. {
  631.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
  632. }
  633.  
  634. inline void cat(const char* a, const SubString& x, const SubString& y, String& r)
  635. {
  636.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
  637. }
  638.  
  639. inline void cat(const char* a, const SubString& x, const char* y, String& r)
  640. {
  641.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y, -1);
  642. }
  643.  
  644. inline void cat(const char* a, const SubString& x, char y, String& r)
  645. {
  646.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), &y, 1);
  647. }
  648.  
  649. inline void cat(const char* a, const char* x, const String& y, String& r)
  650. {
  651.   r.rep = Scat(r.rep, a, -1, x, -1, y.chars(), y.length());
  652. }
  653.  
  654. inline void cat(const char* a, const char* x, const SubString& y, String& r)
  655. {
  656.   r.rep = Scat(r.rep, a, -1, x, -1, y.chars(), y.length());
  657. }
  658.  
  659. inline void cat(const char* a, const char* x, const char* y, String& r)
  660. {
  661.   r.rep = Scat(r.rep, a, -1, x, -1, y, -1);
  662. }
  663.  
  664. inline void cat(const char* a, const char* x, char y, String& r)
  665. {
  666.   r.rep = Scat(r.rep, a, -1, x, -1, &y, 1);
  667. }
  668.  
  669.  
  670. // operator versions
  671.  
  672. inline String& String::operator +=(const String& y)
  673. {
  674.   cat(*this, y, *this);
  675.   return *this;
  676. }
  677.  
  678. inline String& String::operator +=(const SubString& y)
  679. {
  680.   cat(*this, y, *this);
  681.   return *this;
  682. }
  683.  
  684. inline String& String::operator += (const char* y)
  685. {
  686.   cat(*this, y, *this);
  687.   return *this;
  688. }
  689.  
  690. inline String& String:: operator +=(char y)
  691. {
  692.   cat(*this, y, *this);
  693.   return *this;
  694. }
  695.  
  696. // constructive concatenation
  697.  
  698. #if defined(__GNUG__) && !defined(_G_NO_NRV)
  699.  
  700. inline String operator + (const String& x, const String& y) return r;
  701. {
  702.   cat(x, y, r);
  703. }
  704.  
  705. inline String operator + (const String& x, const SubString& y) return r;
  706. {
  707.   cat(x, y, r);
  708. }
  709.  
  710. inline String operator + (const String& x, const char* y) return r;
  711. {
  712.   cat(x, y, r);
  713. }
  714.  
  715. inline String operator + (const String& x, char y) return r;
  716. {
  717.   cat(x, y, r);
  718. }
  719.  
  720. inline String operator + (const SubString& x, const String& y) return r;
  721. {
  722.   cat(x, y, r);
  723. }
  724.  
  725. inline String operator + (const SubString& x, const SubString& y) return r;
  726. {
  727.   cat(x, y, r);
  728. }
  729.  
  730. inline String operator + (const SubString& x, const char* y) return r;
  731. {
  732.   cat(x, y, r);
  733. }
  734.  
  735. inline String operator + (const SubString& x, char y) return r;
  736. {
  737.   cat(x, y, r);
  738. }
  739.  
  740. inline String operator + (const char* x, const String& y) return r;
  741. {
  742.   cat(x, y, r);
  743. }
  744.  
  745. inline String operator + (const char* x, const SubString& y) return r;
  746. {
  747.   cat(x, y, r);
  748. }
  749.  
  750. inline String reverse(const String& x) return r;
  751. {
  752.   r.rep = Sreverse(x.rep, r.rep);
  753. }
  754.  
  755. inline String upcase(const String& x) return r;
  756. {
  757.   r.rep = Supcase(x.rep, r.rep);
  758. }
  759.  
  760. inline String downcase(const String& x) return r;
  761. {
  762.   r.rep = Sdowncase(x.rep, r.rep);
  763. }
  764.  
  765. inline String capitalize(const String& x) return r;
  766. {
  767.   r.rep = Scapitalize(x.rep, r.rep);
  768. }
  769.  
  770. #else /* NO_NRV */
  771.  
  772. inline String operator + (const String& x, const String& y)
  773. {
  774.   String r;  cat(x, y, r);  return r;
  775. }
  776.  
  777. inline String operator + (const String& x, const SubString& y) 
  778. {
  779.   String r; cat(x, y, r); return r;
  780. }
  781.  
  782. inline String operator + (const String& x, const char* y) 
  783. {
  784.   String r; cat(x, y, r); return r;
  785. }
  786.  
  787. inline String operator + (const String& x, char y) 
  788. {
  789.   String r; cat(x, y, r); return r;
  790. }
  791.  
  792. inline String operator + (const SubString& x, const String& y) 
  793. {
  794.   String r; cat(x, y, r); return r;
  795. }
  796.  
  797. inline String operator + (const SubString& x, const SubString& y) 
  798. {
  799.   String r; cat(x, y, r); return r;
  800. }
  801.  
  802. inline String operator + (const SubString& x, const char* y) 
  803. {
  804.   String r; cat(x, y, r); return r;
  805. }
  806.  
  807. inline String operator + (const SubString& x, char y) 
  808. {
  809.   String r; cat(x, y, r); return r;
  810. }
  811.  
  812. inline String operator + (const char* x, const String& y) 
  813. {
  814.   String r; cat(x, y, r); return r;
  815. }
  816.  
  817. inline String operator + (const char* x, const SubString& y) 
  818. {
  819.   String r; cat(x, y, r); return r;
  820. }
  821.  
  822. inline String reverse(const String& x) 
  823. {
  824.   String r; r.rep = Sreverse(x.rep, r.rep); return r;
  825. }
  826.  
  827. inline String upcase(const String& x) 
  828. {
  829.   String r; r.rep = Supcase(x.rep, r.rep); return r;
  830. }
  831.  
  832. inline String downcase(const String& x) 
  833. {
  834.   String r; r.rep = Sdowncase(x.rep, r.rep); return r;
  835. }
  836.  
  837. inline String capitalize(const String& x) 
  838. {
  839.   String r; r.rep = Scapitalize(x.rep, r.rep); return r;
  840. }
  841.  
  842. #endif
  843.  
  844. // prepend
  845.  
  846. inline void String::prepend(const String& y)
  847. {
  848.   rep = Sprepend(rep, y.chars(), y.length());
  849. }
  850.  
  851. inline void String::prepend(const char* y)
  852. {
  853.   rep = Sprepend(rep, y, -1); 
  854. }
  855.  
  856. inline void String::prepend(char y)
  857. {
  858.   rep = Sprepend(rep, &y, 1); 
  859. }
  860.  
  861. inline void String::prepend(const SubString& y)
  862. {
  863.   rep = Sprepend(rep, y.chars(), y.length());
  864. }
  865.  
  866. // misc transformations
  867.  
  868.  
  869. inline void String::reverse()
  870. {
  871.   rep = Sreverse(rep, rep);
  872. }
  873.  
  874.  
  875. inline void String::upcase()
  876. {
  877.   rep = Supcase(rep, rep);
  878. }
  879.  
  880.  
  881. inline void String::downcase()
  882. {
  883.   rep = Sdowncase(rep, rep);
  884. }
  885.  
  886.  
  887. inline void String::capitalize()
  888. {
  889.   rep = Scapitalize(rep, rep);
  890. }
  891.  
  892. // element extraction
  893.  
  894. inline char&  String::operator [] (int i) 
  895.   if (((unsigned)i) >= length()) error("invalid index");
  896.   return rep->s[i];
  897. }
  898.  
  899. inline const char&  String::operator [] (int i) const
  900.   if (((unsigned)i) >= length()) error("invalid index");
  901.   return rep->s[i];
  902. }
  903.  
  904. inline char  String::elem (int i) const
  905.   if (((unsigned)i) >= length()) error("invalid index");
  906.   return rep->s[i];
  907. }
  908.  
  909. inline char  String::firstchar() const
  910.   return elem(0);
  911. }
  912.  
  913. inline char  String::lastchar() const
  914.   return elem(length() - 1);
  915. }
  916.  
  917. // searching
  918.  
  919. inline int String::index(char c, int startpos) const
  920. {
  921.   return search(startpos, length(), c);
  922. }
  923.  
  924. inline int String::index(const char* t, int startpos) const
  925. {   
  926.   return search(startpos, length(), t);
  927. }
  928.  
  929. inline int String::index(const String& y, int startpos) const
  930. {   
  931.   return search(startpos, length(), y.chars(), y.length());
  932. }
  933.  
  934. inline int String::index(const SubString& y, int startpos) const
  935. {   
  936.   return search(startpos, length(), y.chars(), y.length());
  937. }
  938.  
  939. inline int String::index(const Regex& r, int startpos) const
  940. {
  941.   int unused;  return r.search(chars(), length(), unused, startpos);
  942. }
  943.  
  944. inline int String::contains(char c) const
  945. {
  946.   return search(0, length(), c) >= 0;
  947. }
  948.  
  949. inline int String::contains(const char* t) const
  950. {   
  951.   return search(0, length(), t) >= 0;
  952. }
  953.  
  954. inline int String::contains(const String& y) const
  955. {   
  956.   return search(0, length(), y.chars(), y.length()) >= 0;
  957. }
  958.  
  959. inline int String::contains(const SubString& y) const
  960. {   
  961.   return search(0, length(), y.chars(), y.length()) >= 0;
  962. }
  963.  
  964. inline int String::contains(char c, int p) const
  965. {
  966.   return match(p, length(), 0, &c, 1) >= 0;
  967. }
  968.  
  969. inline int String::contains(const char* t, int p) const
  970. {
  971.   return match(p, length(), 0, t) >= 0;
  972. }
  973.  
  974. inline int String::contains(const String& y, int p) const
  975. {
  976.   return match(p, length(), 0, y.chars(), y.length()) >= 0;
  977. }
  978.  
  979. inline int String::contains(const SubString& y, int p) const
  980. {
  981.   return match(p, length(), 0, y.chars(), y.length()) >= 0;
  982. }
  983.  
  984. inline int String::contains(const Regex& r) const
  985. {
  986.   int unused;  return r.search(chars(), length(), unused, 0) >= 0;
  987. }
  988.  
  989. inline int String::contains(const Regex& r, int p) const
  990. {
  991.   return r.match(chars(), length(), p) >= 0;
  992. }
  993.  
  994.  
  995. inline int String::matches(const SubString& y, int p) const
  996. {
  997.   return match(p, length(), 1, y.chars(), y.length()) >= 0;
  998. }
  999.  
  1000. inline int String::matches(const String& y, int p) const
  1001. {
  1002.   return match(p, length(), 1, y.chars(), y.length()) >= 0;
  1003. }
  1004.  
  1005. inline int String::matches(const char* t, int p) const
  1006. {
  1007.   return match(p, length(), 1, t) >= 0;
  1008. }
  1009.  
  1010. inline int String::matches(char c, int p) const
  1011. {
  1012.   return match(p, length(), 1, &c, 1) >= 0;
  1013. }
  1014.  
  1015. inline int String::matches(const Regex& r, int p) const
  1016. {
  1017.   int l = (p < 0)? -p : length() - p;
  1018.   return r.match(chars(), length(), p) == l;
  1019. }
  1020.  
  1021.  
  1022. inline int SubString::contains(const char* t) const
  1023. {   
  1024.   return S.search(pos, pos+len, t) >= 0;
  1025. }
  1026.  
  1027. inline int SubString::contains(const String& y) const
  1028. {   
  1029.   return S.search(pos, pos+len, y.chars(), y.length()) >= 0;
  1030. }
  1031.  
  1032. inline int SubString::contains(const SubString&  y) const
  1033. {   
  1034.   return S.search(pos, pos+len, y.chars(), y.length()) >= 0;
  1035. }
  1036.  
  1037. inline int SubString::contains(char c) const
  1038. {
  1039.   return S.search(pos, pos+len, c) >= 0;
  1040. }
  1041.  
  1042. inline int SubString::contains(const Regex& r) const
  1043. {
  1044.   int unused;  return r.search(chars(), len, unused, 0) >= 0;
  1045. }
  1046.  
  1047. inline int SubString::matches(const Regex& r) const
  1048. {
  1049.   return r.match(chars(), len, 0) == len;
  1050. }
  1051.  
  1052.  
  1053. inline int String::gsub(const String& pat, const String& r)
  1054. {
  1055.   return _gsub(pat.chars(), pat.length(), r.chars(), r.length());
  1056. }
  1057.  
  1058. inline int String::gsub(const SubString&  pat, const String& r)
  1059. {
  1060.   return _gsub(pat.chars(), pat.length(), r.chars(), r.length());
  1061. }
  1062.  
  1063. inline int String::gsub(const Regex& pat, const String& r)
  1064. {
  1065.   return _gsub(pat, r.chars(), r.length());
  1066. }
  1067.  
  1068. inline int String::gsub(const char* pat, const String& r)
  1069. {
  1070.   return _gsub(pat, -1, r.chars(), r.length());
  1071. }
  1072.  
  1073. inline int String::gsub(const char* pat, const char* r)
  1074. {
  1075.   return _gsub(pat, -1, r, -1);
  1076. }
  1077.  
  1078.  
  1079.  
  1080. inline  ostream& operator<<(ostream& s, const String& x)
  1081. {
  1082.    s << x.chars(); return s;
  1083. }
  1084.  
  1085. // a zillion comparison operators
  1086.  
  1087. inline int operator==(const String& x, const String& y) 
  1088. {
  1089.   return compare(x, y) == 0; 
  1090. }
  1091.  
  1092. inline int operator!=(const String& x, const String& y)
  1093. {
  1094.   return compare(x, y) != 0; 
  1095. }
  1096.  
  1097. inline int operator>(const String& x, const String& y)
  1098. {
  1099.   return compare(x, y) > 0; 
  1100. }
  1101.  
  1102. inline int operator>=(const String& x, const String& y)
  1103. {
  1104.   return compare(x, y) >= 0; 
  1105. }
  1106.  
  1107. inline int operator<(const String& x, const String& y)
  1108. {
  1109.   return compare(x, y) < 0; 
  1110. }
  1111.  
  1112. inline int operator<=(const String& x, const String& y)
  1113. {
  1114.   return compare(x, y) <= 0; 
  1115. }
  1116.  
  1117. inline int operator==(const String& x, const SubString&  y) 
  1118. {
  1119.   return compare(x, y) == 0; 
  1120. }
  1121.  
  1122. inline int operator!=(const String& x, const SubString&  y)
  1123. {
  1124.   return compare(x, y) != 0; 
  1125. }
  1126.  
  1127. inline int operator>(const String& x, const SubString&  y)      
  1128. {
  1129.   return compare(x, y) > 0; 
  1130. }
  1131.  
  1132. inline int operator>=(const String& x, const SubString&  y)
  1133. {
  1134.   return compare(x, y) >= 0; 
  1135. }
  1136.  
  1137. inline int operator<(const String& x, const SubString&  y) 
  1138. {
  1139.   return compare(x, y) < 0; 
  1140. }
  1141.  
  1142. inline int operator<=(const String& x, const SubString&  y)
  1143. {
  1144.   return compare(x, y) <= 0; 
  1145. }
  1146.  
  1147. inline int operator==(const String& x, const char* t) 
  1148. {
  1149.   return compare(x, t) == 0; 
  1150. }
  1151.  
  1152. inline int operator!=(const String& x, const char* t) 
  1153. {
  1154.   return compare(x, t) != 0; 
  1155. }
  1156.  
  1157. inline int operator>(const String& x, const char* t)  
  1158. {
  1159.   return compare(x, t) > 0; 
  1160. }
  1161.  
  1162. inline int operator>=(const String& x, const char* t) 
  1163. {
  1164.   return compare(x, t) >= 0; 
  1165. }
  1166.  
  1167. inline int operator<(const String& x, const char* t)  
  1168. {
  1169.   return compare(x, t) < 0; 
  1170. }
  1171.  
  1172. inline int operator<=(const String& x, const char* t) 
  1173. {
  1174.   return compare(x, t) <= 0; 
  1175. }
  1176.  
  1177. inline int operator==(const SubString& x, const String& y) 
  1178. {
  1179.   return compare(y, x) == 0; 
  1180. }
  1181.  
  1182. inline int operator!=(const SubString& x, const String& y)
  1183. {
  1184.   return compare(y, x) != 0;
  1185. }
  1186.  
  1187. inline int operator>(const SubString& x, const String& y)      
  1188. {
  1189.   return compare(y, x) < 0;
  1190. }
  1191.  
  1192. inline int operator>=(const SubString& x, const String& y)     
  1193. {
  1194.   return compare(y, x) <= 0;
  1195. }
  1196.  
  1197. inline int operator<(const SubString& x, const String& y)      
  1198. {
  1199.   return compare(y, x) > 0;
  1200. }
  1201.  
  1202. inline int operator<=(const SubString& x, const String& y)     
  1203. {
  1204.   return compare(y, x) >= 0;
  1205. }
  1206.  
  1207. inline int operator==(const SubString& x, const SubString&  y) 
  1208. {
  1209.   return compare(x, y) == 0; 
  1210. }
  1211.  
  1212. inline int operator!=(const SubString& x, const SubString&  y)
  1213. {
  1214.   return compare(x, y) != 0;
  1215. }
  1216.  
  1217. inline int operator>(const SubString& x, const SubString&  y)      
  1218. {
  1219.   return compare(x, y) > 0;
  1220. }
  1221.  
  1222. inline int operator>=(const SubString& x, const SubString&  y)
  1223. {
  1224.   return compare(x, y) >= 0;
  1225. }
  1226.  
  1227. inline int operator<(const SubString& x, const SubString&  y) 
  1228. {
  1229.   return compare(x, y) < 0;
  1230. }
  1231.  
  1232. inline int operator<=(const SubString& x, const SubString&  y)
  1233. {
  1234.   return compare(x, y) <= 0;
  1235. }
  1236.  
  1237. inline int operator==(const SubString& x, const char* t) 
  1238. {
  1239.   return compare(x, t) == 0; 
  1240. }
  1241.  
  1242. inline int operator!=(const SubString& x, const char* t) 
  1243. {
  1244.   return compare(x, t) != 0;
  1245. }
  1246.  
  1247. inline int operator>(const SubString& x, const char* t)  
  1248. {
  1249.   return compare(x, t) > 0; 
  1250. }
  1251.  
  1252. inline int operator>=(const SubString& x, const char* t) 
  1253. {
  1254.   return compare(x, t) >= 0; 
  1255. }
  1256.  
  1257. inline int operator<(const SubString& x, const char* t)  
  1258. {
  1259.   return compare(x, t) < 0; 
  1260. }
  1261.  
  1262. inline int operator<=(const SubString& x, const char* t) 
  1263. {
  1264.   return compare(x, t) <= 0; 
  1265. }
  1266.  
  1267.  
  1268. // a helper needed by at, before, etc.
  1269.  
  1270. inline SubString String::_substr(int first, int l)
  1271. {
  1272.   if (first < 0 || (unsigned)(first + l) > length() )
  1273.     return SubString(_nilString, 0, 0) ;
  1274.   else 
  1275.     return SubString(*this, first, l);
  1276. }
  1277.  
  1278. #endif
  1279.