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