home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer) / NeXT_Developer-3.3.iso / NextDeveloper / Headers / g++ / String.h < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-06  |  35.4 KB  |  1,318 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. #pragma cplusplus
  24. #endif
  25. #define _String_h 1
  26.  
  27. #include <iostream.h>
  28. #include <Regex.h>
  29.  
  30. struct StrRep                     // internal String representations
  31. {
  32.   unsigned short    len;         // string length 
  33.   unsigned short    sz;          // allocated space
  34.   char              s[1];        // the string starts here 
  35.                                  // (at least 1 char for trailing null)
  36.                                  // allocated & expanded via non-public fcts
  37. };
  38.  
  39. // primitive ops on StrReps -- nearly all String fns go through these.
  40.  
  41. StrRep*     Salloc(StrRep*, const char*, int, int);
  42. StrRep*     Scopy(StrRep*, StrRep*);
  43. StrRep*     Sresize(StrRep*, int);
  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(StrRep*, StrRep*);
  48. StrRep*     Supcase(StrRep*, StrRep*);
  49. StrRep*     Sdowncase(StrRep*, StrRep*);
  50. StrRep*     Scapitalize(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(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.   void              operator =  (const String&     y);
  78.   void              operator =  (const SubString&  y);
  79.   void              operator =  (const char* t);
  80.   void              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.   void              operator =  (const String&     y);
  139.   void              operator =  (const char* y);
  140.   void              operator =  (char        c);
  141.   void              operator =  (const SubString&  y);
  142.  
  143. // concatenation
  144.  
  145.   void              operator += (const String&     y); 
  146.   void              operator += (const SubString&  y);
  147.   void              operator += (const char* t);
  148.   void              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 void     cat(const String&, const String&, String&);
  160.   friend void     cat(const String&, const SubString&, String&);
  161.   friend void     cat(const String&, const char*, String&);
  162.   friend void     cat(const String&, char, String&);
  163.  
  164.   friend void     cat(const SubString&, const String&, String&);
  165.   friend void     cat(const SubString&, const SubString&, String&);
  166.   friend void     cat(const SubString&, const char*, String&);
  167.   friend void     cat(const SubString&, char, String&);
  168.  
  169.   friend void     cat(const char*, const String&, String&);
  170.   friend void     cat(const char*, const SubString&, String&);
  171.   friend void     cat(const char*, const char*, String&);
  172.   friend 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 void     cat(const String&,const String&, const String&,String&);
  179.   friend void     cat(const String&,const String&,const SubString&,String&);
  180.   friend void     cat(const String&,const String&, const char*, String&);
  181.   friend void     cat(const String&,const String&, char, String&);
  182.   friend void     cat(const String&,const SubString&,const String&,String&);
  183.   friend void     cat(const String&,const SubString&,const SubString&,String&);
  184.   friend void     cat(const String&,const SubString&, const char*, String&);
  185.   friend void     cat(const String&,const SubString&, char, String&);
  186.   friend void     cat(const String&,const char*, const String&,    String&);
  187.   friend void     cat(const String&,const char*, const SubString&, String&);
  188.   friend void     cat(const String&,const char*, const char*, String&);
  189.   friend void     cat(const String&,const char*, char, String&);
  190.  
  191.   friend void     cat(const char*, const String&, const String&,String&);
  192.   friend void     cat(const char*,const String&,const SubString&,String&);
  193.   friend void     cat(const char*,const String&, const char*, String&);
  194.   friend void     cat(const char*,const String&, char, String&);
  195.   friend void     cat(const char*,const SubString&,const String&,String&);
  196.   friend void     cat(const char*,const SubString&,const SubString&,String&);
  197.   friend void     cat(const char*,const SubString&, const char*, String&);
  198.   friend void     cat(const char*,const SubString&, char, String&);
  199.   friend void     cat(const char*,const char*, const String&,    String&);
  200.   friend void     cat(const char*,const char*, const SubString&, String&);
  201.   friend void     cat(const char*,const char*, const char*, String&);
  202.   friend 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 String     reverse(const String& x);
  332.   friend String     upcase(const String& x);
  333.   friend String     downcase(const String& x);
  334.   friend 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.   char              elem(int i) const;
  347.   char              firstchar() const;
  348.   char              lastchar() const;
  349.  
  350. // conversion
  351.  
  352.                     operator const char*() const;
  353.   const char*       chars() const;
  354.  
  355.  
  356. // IO
  357.  
  358.   friend ostream&   operator<<(ostream& s, const String& x);
  359.   friend ostream&   operator<<(ostream& s, const SubString& x);
  360.   friend istream&   operator>>(istream& s, String& x);
  361.  
  362.   friend int        readline(istream& s, String& x, 
  363.                              char terminator = '\n',
  364.                              int discard_terminator = 1);
  365.  
  366. // status
  367.  
  368.   unsigned int      length() const;
  369.   int               empty() const;
  370.  
  371. // preallocate some space for String
  372.   void              alloc(int newsize);
  373.  
  374. // report current allocation (not length!)
  375.  
  376.   int               allocation() const;
  377.  
  378.  
  379.   void     error(const char* msg) const;
  380.  
  381.   int               OK() const;
  382. };
  383.  
  384. typedef String StrTmp; // for backward compatibility
  385.  
  386. // other externs
  387.  
  388. int        compare(const String&    x, const String&     y);
  389. int        compare(const String&    x, const SubString&  y);
  390. int        compare(const String&    x, const char* y);
  391. int        compare(const SubString& x, const String&     y);
  392. int        compare(const SubString& x, const SubString&  y);
  393. int        compare(const SubString& x, const char* y);
  394. int        fcompare(const String&   x, const String&     y); // ignore case
  395.  
  396. extern StrRep  _nilStrRep;
  397. extern String _nilString;
  398.  
  399. // other inlines
  400.  
  401. String operator + (const String& x, const String& y);
  402. String operator + (const String& x, const SubString& y);
  403. String operator + (const String& x, const char* y);
  404. String operator + (const String& x, char y);
  405. String operator + (const SubString& x, const String& y);
  406. String operator + (const SubString& x, const SubString& y);
  407. String operator + (const SubString& x, const char* y);
  408. String operator + (const SubString& x, char y);
  409. String operator + (const char* x, const String& y);
  410. String operator + (const char* x, const SubString& y);
  411.  
  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 String& 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 SubString&  y);
  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 String& x, const char* t);
  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 String& 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 SubString&  y);
  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. int operator<=(const SubString& x, const char* t);
  448.  
  449.  
  450. // status reports, needed before defining other things
  451.  
  452. inline unsigned int String::length() const {  return rep->len; }
  453. inline int         String::empty() const { return rep->len == 0; }
  454. inline const char* String::chars() const { return &(rep->s[0]); }
  455. inline int         String::allocation() const { return rep->sz; }
  456. inline void        String::alloc(int newsize) { rep = Sresize(rep, newsize); }
  457.  
  458. inline unsigned int SubString::length() const { return len; }
  459. inline int         SubString::empty() const { return len == 0; }
  460. inline const char* SubString::chars() const { return &(S.rep->s[pos]); }
  461.  
  462.  
  463. // constructors
  464.  
  465. inline String::String() 
  466.   : rep(&_nilStrRep) {}
  467. inline String::String(const String& x) 
  468.   : rep(Scopy(0, x.rep)) {}
  469. inline String::String(const char* t) 
  470.   : rep(Salloc(0, t, -1, -1)) {}
  471. inline String::String(const char* t, int tlen)
  472.   : rep(Salloc(0, t, tlen, tlen)) {}
  473. inline String::String(const SubString& y)
  474.   : rep(Salloc(0, y.chars(), y.length(), y.length())) {}
  475. inline String::String(char c) 
  476.   : rep(Salloc(0, &c, 1, 1)) {}
  477.  
  478. inline String::~String() { if (rep != &_nilStrRep) delete rep; }
  479.  
  480. inline SubString::SubString(const SubString& x)
  481.   :S(x.S), pos(x.pos), len(x.len) {}
  482. inline SubString::SubString(String& x, int first, int l)
  483.   :S(x), pos(first), len(l) {}
  484.  
  485. inline SubString::~SubString() {}
  486.  
  487. // assignment
  488.  
  489. inline void String::operator =  (const String& y)
  490.   rep = Scopy(rep, y.rep);
  491. }
  492.  
  493. inline void String::operator=(const char* t)
  494. {
  495.   rep = Salloc(rep, t, -1, -1); 
  496. }
  497.  
  498. inline void String::operator=(const SubString&  y)
  499. {
  500.   rep = Salloc(rep, y.chars(), y.length(), y.length());
  501. }
  502.  
  503. inline void String::operator=(char c)
  504. {
  505.   rep = Salloc(rep, &c, 1, 1); 
  506. }
  507.  
  508.  
  509. inline void SubString::operator = (const char* ys)
  510. {
  511.   assign(0, ys);
  512. }
  513.  
  514. inline void SubString::operator = (char ch)
  515. {
  516.   assign(0, &ch, 1);
  517. }
  518.  
  519. inline void SubString::operator = (const String& y)
  520. {
  521.   assign(y.rep, y.chars(), y.length());
  522. }
  523.  
  524. inline void SubString::operator = (const SubString& y)
  525. {
  526.   assign(y.S.rep, y.chars(), y.length());
  527. }
  528.  
  529. // Zillions of cats...
  530.  
  531. inline void cat(const String& x, const String& y, String& r)
  532. {
  533.   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
  534. }
  535.  
  536. inline void cat(const String& x, const SubString& y, String& r)
  537. {
  538.   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
  539. }
  540.  
  541. inline void cat(const String& x, const char* y, String& r)
  542. {
  543.   r.rep = Scat(r.rep, x.chars(), x.length(), y, -1);
  544. }
  545.  
  546. inline void cat(const String& x, char y, String& r)
  547. {
  548.   r.rep = Scat(r.rep, x.chars(), x.length(), &y, 1);
  549. }
  550.  
  551. inline void cat(const SubString& x, const String& y, String& r)
  552. {
  553.   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
  554. }
  555.  
  556. inline void cat(const SubString& x, const SubString& y, String& r)
  557. {
  558.   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
  559. }
  560.  
  561. inline void cat(const SubString& x, const char* y, String& r)
  562. {
  563.   r.rep = Scat(r.rep, x.chars(), x.length(), y, -1);
  564. }
  565.  
  566. inline void cat(const SubString& x, char y, String& r)
  567. {
  568.   r.rep = Scat(r.rep, x.chars(), x.length(), &y, 1);
  569. }
  570.  
  571. inline void cat(const char* x, const String& y, String& r)
  572. {
  573.   r.rep = Scat(r.rep, x, -1, y.chars(), y.length());
  574. }
  575.  
  576. inline void cat(const char* x, const SubString& y, String& r)
  577. {
  578.   r.rep = Scat(r.rep, x, -1, y.chars(), y.length());
  579. }
  580.  
  581. inline void cat(const char* x, const char* y, String& r)
  582. {
  583.   r.rep = Scat(r.rep, x, -1, y, -1);
  584. }
  585.  
  586. inline void cat(const char* x, char y, String& r)
  587. {
  588.   r.rep = Scat(r.rep, x, -1, &y, 1);
  589. }
  590.  
  591. inline void cat(const String& a, const String& x, const String& y, String& r)
  592. {
  593.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
  594. }
  595.  
  596. inline void cat(const String& a, const String& x, const SubString& y, String& r)
  597. {
  598.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
  599. }
  600.  
  601. inline void cat(const String& a, const String& x, const char* y, String& r)
  602. {
  603.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y, -1);
  604. }
  605.  
  606. inline void cat(const String& a, const String& x, char y, String& r)
  607. {
  608.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), &y, 1);
  609. }
  610.  
  611. inline void cat(const String& a, const SubString& x, const String& y, String& r)
  612. {
  613.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
  614. }
  615.  
  616. inline void cat(const String& a, const SubString& x, const SubString& y, String& r)
  617. {
  618.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
  619. }
  620.  
  621. inline void cat(const String& a, const SubString& x, const char* y, String& r)
  622. {
  623.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y, -1);
  624. }
  625.  
  626. inline void cat(const String& a, const SubString& x, char y, String& r)
  627. {
  628.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), &y, 1);
  629. }
  630.  
  631. inline void cat(const String& a, const char* x, const String& y, String& r)
  632. {
  633.   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y.chars(), y.length());
  634. }
  635.  
  636. inline void cat(const String& a, const char* x, const SubString& y, String& r)
  637. {
  638.   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y.chars(), y.length());
  639. }
  640.  
  641. inline void cat(const String& a, const char* x, const char* y, String& r)
  642. {
  643.   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y, -1);
  644. }
  645.  
  646. inline void cat(const String& a, const char* x, char y, String& r)
  647. {
  648.   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, &y, 1);
  649. }
  650.  
  651.  
  652. inline void cat(const char* a, const String& x, const String& y, String& r)
  653. {
  654.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
  655. }
  656.  
  657. inline void cat(const char* a, const String& x, const SubString& y, String& r)
  658. {
  659.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
  660. }
  661.  
  662. inline void cat(const char* a, const String& x, const char* y, String& r)
  663. {
  664.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y, -1);
  665. }
  666.  
  667. inline void cat(const char* a, const String& x, char y, String& r)
  668. {
  669.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), &y, 1);
  670. }
  671.  
  672. inline void cat(const char* a, const SubString& x, const String& y, String& r)
  673. {
  674.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
  675. }
  676.  
  677. inline void cat(const char* a, const SubString& x, const SubString& y, String& r)
  678. {
  679.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
  680. }
  681.  
  682. inline void cat(const char* a, const SubString& x, const char* y, String& r)
  683. {
  684.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y, -1);
  685. }
  686.  
  687. inline void cat(const char* a, const SubString& x, char y, String& r)
  688. {
  689.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), &y, 1);
  690. }
  691.  
  692. inline void cat(const char* a, const char* x, const String& y, String& r)
  693. {
  694.   r.rep = Scat(r.rep, a, -1, x, -1, y.chars(), y.length());
  695. }
  696.  
  697. inline void cat(const char* a, const char* x, const SubString& y, String& r)
  698. {
  699.   r.rep = Scat(r.rep, a, -1, x, -1, y.chars(), y.length());
  700. }
  701.  
  702. inline void cat(const char* a, const char* x, const char* y, String& r)
  703. {
  704.   r.rep = Scat(r.rep, a, -1, x, -1, y, -1);
  705. }
  706.  
  707. inline void cat(const char* a, const char* x, char y, String& r)
  708. {
  709.   r.rep = Scat(r.rep, a, -1, x, -1, &y, 1);
  710. }
  711.  
  712.  
  713. // operator versions
  714.  
  715. inline void String::operator +=(const String& y)
  716. {
  717.   cat(*this, y, *this);
  718. }
  719.  
  720. inline void String::operator +=(const SubString& y)
  721. {
  722.   cat(*this, y, *this);
  723. }
  724.  
  725. inline void String::operator += (const char* y)
  726. {
  727.   cat(*this, y, *this);
  728. }
  729.  
  730. inline void String:: operator +=(char y)
  731. {
  732.   cat(*this, y, *this);
  733. }
  734.  
  735. // constructive concatenation
  736.  
  737. #if defined(__GNUG__) && !defined(NO_NRV)
  738.  
  739. inline String operator + (const String& x, const String& y) return r;
  740. {
  741.   cat(x, y, r);
  742. }
  743.  
  744. inline String operator + (const String& x, const SubString& y) return r;
  745. {
  746.   cat(x, y, r);
  747. }
  748.  
  749. inline String operator + (const String& x, const char* y) return r;
  750. {
  751.   cat(x, y, r);
  752. }
  753.  
  754. inline String operator + (const String& x, char y) return r;
  755. {
  756.   cat(x, y, r);
  757. }
  758.  
  759. inline String operator + (const SubString& x, const String& y) return r;
  760. {
  761.   cat(x, y, r);
  762. }
  763.  
  764. inline String operator + (const SubString& x, const SubString& y) return r;
  765. {
  766.   cat(x, y, r);
  767. }
  768.  
  769. inline String operator + (const SubString& x, const char* y) return r;
  770. {
  771.   cat(x, y, r);
  772. }
  773.  
  774. inline String operator + (const SubString& x, char y) return r;
  775. {
  776.   cat(x, y, r);
  777. }
  778.  
  779. inline String operator + (const char* x, const String& y) return r;
  780. {
  781.   cat(x, y, r);
  782. }
  783.  
  784. inline String operator + (const char* x, const SubString& y) return r;
  785. {
  786.   cat(x, y, r);
  787. }
  788.  
  789. inline String reverse(const String& x) return r;
  790. {
  791.   r.rep = Sreverse(x.rep, r.rep);
  792. }
  793.  
  794. inline String upcase(const String& x) return r;
  795. {
  796.   r.rep = Supcase(x.rep, r.rep);
  797. }
  798.  
  799. inline String downcase(const String& x) return r;
  800. {
  801.   r.rep = Sdowncase(x.rep, r.rep);
  802. }
  803.  
  804. inline String capitalize(const String& x) return r;
  805. {
  806.   r.rep = Scapitalize(x.rep, r.rep);
  807. }
  808.  
  809. #else /* NO_NRV */
  810.  
  811. inline String operator + (const String& x, const String& y)
  812. {
  813.   String r;  cat(x, y, r);  return r;
  814. }
  815.  
  816. inline String operator + (const String& x, const SubString& y) 
  817. {
  818.   String r; cat(x, y, r); return r;
  819. }
  820.  
  821. inline String operator + (const String& x, const char* y) 
  822. {
  823.   String r; cat(x, y, r); return r;
  824. }
  825.  
  826. inline String operator + (const String& x, char y) 
  827. {
  828.   String r; cat(x, y, r); return r;
  829. }
  830.  
  831. inline String operator + (const SubString& x, const String& y) 
  832. {
  833.   String r; cat(x, y, r); return r;
  834. }
  835.  
  836. inline String operator + (const SubString& x, const SubString& y) 
  837. {
  838.   String r; cat(x, y, r); return r;
  839. }
  840.  
  841. inline String operator + (const SubString& x, const char* y) 
  842. {
  843.   String r; cat(x, y, r); return r;
  844. }
  845.  
  846. inline String operator + (const SubString& x, char y) 
  847. {
  848.   String r; cat(x, y, r); return r;
  849. }
  850.  
  851. inline String operator + (const char* x, const String& y) 
  852. {
  853.   String r; cat(x, y, r); return r;
  854. }
  855.  
  856. inline String operator + (const char* x, const SubString& y) 
  857. {
  858.   String r; cat(x, y, r); return r;
  859. }
  860.  
  861. inline String reverse(const String& x) 
  862. {
  863.   String r; r.rep = Sreverse(x.rep, r.rep); return r;
  864. }
  865.  
  866. inline String upcase(const String& x) 
  867. {
  868.   String r; r.rep = Supcase(x.rep, r.rep); return r;
  869. }
  870.  
  871. inline String downcase(const String& x) 
  872. {
  873.   String r; r.rep = Sdowncase(x.rep, r.rep); return r;
  874. }
  875.  
  876. inline String capitalize(const String& x) 
  877. {
  878.   String r; r.rep = Scapitalize(x.rep, r.rep); return r;
  879. }
  880.  
  881. #endif
  882.  
  883. // prepend
  884.  
  885. inline void String::prepend(const String& y)
  886. {
  887.   rep = Sprepend(rep, y.chars(), y.length());
  888. }
  889.  
  890. inline void String::prepend(const char* y)
  891. {
  892.   rep = Sprepend(rep, y, -1); 
  893. }
  894.  
  895. inline void String::prepend(char y)
  896. {
  897.   rep = Sprepend(rep, &y, 1); 
  898. }
  899.  
  900. inline void String::prepend(const SubString& y)
  901. {
  902.   rep = Sprepend(rep, y.chars(), y.length());
  903. }
  904.  
  905. // misc transformations
  906.  
  907.  
  908. inline void String::reverse()
  909. {
  910.   rep = Sreverse(rep, rep);
  911. }
  912.  
  913.  
  914. inline void String::upcase()
  915. {
  916.   rep = Supcase(rep, rep);
  917. }
  918.  
  919.  
  920. inline void String::downcase()
  921. {
  922.   rep = Sdowncase(rep, rep);
  923. }
  924.  
  925.  
  926. inline void String::capitalize()
  927. {
  928.   rep = Scapitalize(rep, rep);
  929. }
  930.  
  931. // element extraction
  932.  
  933. inline char&  String::operator [] (int i) 
  934.   if (((unsigned)i) >= length()) error("invalid index");
  935.   return rep->s[i];
  936. }
  937.  
  938. inline char  String::elem (int i) const
  939.   if (((unsigned)i) >= length()) error("invalid index");
  940.   return rep->s[i];
  941. }
  942.  
  943. inline char  String::firstchar() const
  944.   return elem(0);
  945. }
  946.  
  947. inline char  String::lastchar() const
  948.   return elem(length() - 1);
  949. }
  950.  
  951. // searching
  952.  
  953. inline int String::index(char c, int startpos) const
  954. {
  955.   return search(startpos, length(), c);
  956. }
  957.  
  958. inline int String::index(const char* t, int startpos) const
  959. {   
  960.   return search(startpos, length(), t);
  961. }
  962.  
  963. inline int String::index(const String& y, int startpos) const
  964. {   
  965.   return search(startpos, length(), y.chars(), y.length());
  966. }
  967.  
  968. inline int String::index(const SubString& y, int startpos) const
  969. {   
  970.   return search(startpos, length(), y.chars(), y.length());
  971. }
  972.  
  973. inline int String::index(const Regex& r, int startpos) const
  974. {
  975.   int unused;  return r.search(chars(), length(), unused, startpos);
  976. }
  977.  
  978. inline int String::contains(char c) const
  979. {
  980.   return search(0, length(), c) >= 0;
  981. }
  982.  
  983. inline int String::contains(const char* t) const
  984. {   
  985.   return search(0, length(), t) >= 0;
  986. }
  987.  
  988. inline int String::contains(const String& y) const
  989. {   
  990.   return search(0, length(), y.chars(), y.length()) >= 0;
  991. }
  992.  
  993. inline int String::contains(const SubString& y) const
  994. {   
  995.   return search(0, length(), y.chars(), y.length()) >= 0;
  996. }
  997.  
  998. inline int String::contains(char c, int p) const
  999. {
  1000.   return match(p, length(), 0, &c, 1) >= 0;
  1001. }
  1002.  
  1003. inline int String::contains(const char* t, int p) const
  1004. {
  1005.   return match(p, length(), 0, t) >= 0;
  1006. }
  1007.  
  1008. inline int String::contains(const String& y, int p) const
  1009. {
  1010.   return match(p, length(), 0, y.chars(), y.length()) >= 0;
  1011. }
  1012.  
  1013. inline int String::contains(const SubString& y, int p) const
  1014. {
  1015.   return match(p, length(), 0, y.chars(), y.length()) >= 0;
  1016. }
  1017.  
  1018. inline int String::contains(const Regex& r) const
  1019. {
  1020.   int unused;  return r.search(chars(), length(), unused, 0) >= 0;
  1021. }
  1022.  
  1023. inline int String::contains(const Regex& r, int p) const
  1024. {
  1025.   return r.match(chars(), length(), p) >= 0;
  1026. }
  1027.  
  1028.  
  1029. inline int String::matches(const SubString& y, int p) const
  1030. {
  1031.   return match(p, length(), 1, y.chars(), y.length()) >= 0;
  1032. }
  1033.  
  1034. inline int String::matches(const String& y, int p) const
  1035. {
  1036.   return match(p, length(), 1, y.chars(), y.length()) >= 0;
  1037. }
  1038.  
  1039. inline int String::matches(const char* t, int p) const
  1040. {
  1041.   return match(p, length(), 1, t) >= 0;
  1042. }
  1043.  
  1044. inline int String::matches(char c, int p) const
  1045. {
  1046.   return match(p, length(), 1, &c, 1) >= 0;
  1047. }
  1048.  
  1049. inline int String::matches(const Regex& r, int p) const
  1050. {
  1051.   int l = (p < 0)? -p : length() - p;
  1052.   return r.match(chars(), length(), p) == l;
  1053. }
  1054.  
  1055.  
  1056. inline int SubString::contains(const char* t) const
  1057. {   
  1058.   return S.search(pos, pos+len, t) >= 0;
  1059. }
  1060.  
  1061. inline int SubString::contains(const String& y) const
  1062. {   
  1063.   return S.search(pos, pos+len, y.chars(), y.length()) >= 0;
  1064. }
  1065.  
  1066. inline int SubString::contains(const SubString&  y) const
  1067. {   
  1068.   return S.search(pos, pos+len, y.chars(), y.length()) >= 0;
  1069. }
  1070.  
  1071. inline int SubString::contains(char c) const
  1072. {
  1073.   return S.search(pos, pos+len, c) >= 0;
  1074. }
  1075.  
  1076. inline int SubString::contains(const Regex& r) const
  1077. {
  1078.   int unused;  return r.search(chars(), len, unused, 0) >= 0;
  1079. }
  1080.  
  1081. inline int SubString::matches(const Regex& r) const
  1082. {
  1083.   return r.match(chars(), len, 0) == len;
  1084. }
  1085.  
  1086.  
  1087. inline int String::gsub(const String& pat, const String& r)
  1088. {
  1089.   return _gsub(pat.chars(), pat.length(), r.chars(), r.length());
  1090. }
  1091.  
  1092. inline int String::gsub(const SubString&  pat, const String& r)
  1093. {
  1094.   return _gsub(pat.chars(), pat.length(), r.chars(), r.length());
  1095. }
  1096.  
  1097. inline int String::gsub(const Regex& pat, const String& r)
  1098. {
  1099.   return _gsub(pat, r.chars(), r.length());
  1100. }
  1101.  
  1102. inline int String::gsub(const char* pat, const String& r)
  1103. {
  1104.   return _gsub(pat, -1, r.chars(), r.length());
  1105. }
  1106.  
  1107. inline int String::gsub(const char* pat, const char* r)
  1108. {
  1109.   return _gsub(pat, -1, r, -1);
  1110. }
  1111.  
  1112.  
  1113.  
  1114. inline  ostream& operator<<(ostream& s, const String& x)
  1115. {
  1116.    s << x.chars(); return s;
  1117. }
  1118.  
  1119. // a zillion comparison operators
  1120.  
  1121. inline int operator==(const String& x, const String& y) 
  1122. {
  1123.   return compare(x, y) == 0; 
  1124. }
  1125.  
  1126. inline int operator!=(const String& x, const String& y)
  1127. {
  1128.   return compare(x, y) != 0; 
  1129. }
  1130.  
  1131. inline int operator>(const String& x, const String& y)
  1132. {
  1133.   return compare(x, y) > 0; 
  1134. }
  1135.  
  1136. inline int operator>=(const String& x, const String& y)
  1137. {
  1138.   return compare(x, y) >= 0; 
  1139. }
  1140.  
  1141. inline int operator<(const String& x, const String& y)
  1142. {
  1143.   return compare(x, y) < 0; 
  1144. }
  1145.  
  1146. inline int operator<=(const String& x, const String& y)
  1147. {
  1148.   return compare(x, y) <= 0; 
  1149. }
  1150.  
  1151. inline int operator==(const String& x, const SubString&  y) 
  1152. {
  1153.   return compare(x, y) == 0; 
  1154. }
  1155.  
  1156. inline int operator!=(const String& x, const SubString&  y)
  1157. {
  1158.   return compare(x, y) != 0; 
  1159. }
  1160.  
  1161. inline int operator>(const String& x, const SubString&  y)      
  1162. {
  1163.   return compare(x, y) > 0; 
  1164. }
  1165.  
  1166. inline int operator>=(const String& x, const SubString&  y)
  1167. {
  1168.   return compare(x, y) >= 0; 
  1169. }
  1170.  
  1171. inline int operator<(const String& x, const SubString&  y) 
  1172. {
  1173.   return compare(x, y) < 0; 
  1174. }
  1175.  
  1176. inline int operator<=(const String& x, const SubString&  y)
  1177. {
  1178.   return compare(x, y) <= 0; 
  1179. }
  1180.  
  1181. inline int operator==(const String& x, const char* t) 
  1182. {
  1183.   return compare(x, t) == 0; 
  1184. }
  1185.  
  1186. inline int operator!=(const String& x, const char* t) 
  1187. {
  1188.   return compare(x, t) != 0; 
  1189. }
  1190.  
  1191. inline int operator>(const String& x, const char* t)  
  1192. {
  1193.   return compare(x, t) > 0; 
  1194. }
  1195.  
  1196. inline int operator>=(const String& x, const char* t) 
  1197. {
  1198.   return compare(x, t) >= 0; 
  1199. }
  1200.  
  1201. inline int operator<(const String& x, const char* t)  
  1202. {
  1203.   return compare(x, t) < 0; 
  1204. }
  1205.  
  1206. inline int operator<=(const String& x, const char* t) 
  1207. {
  1208.   return compare(x, t) <= 0; 
  1209. }
  1210.  
  1211. inline int operator==(const SubString& x, const String& y) 
  1212. {
  1213.   return compare(y, x) == 0; 
  1214. }
  1215.  
  1216. inline int operator!=(const SubString& x, const String& y)
  1217. {
  1218.   return compare(y, x) != 0;
  1219. }
  1220.  
  1221. inline int operator>(const SubString& x, const String& y)      
  1222. {
  1223.   return compare(y, x) < 0;
  1224. }
  1225.  
  1226. inline int operator>=(const SubString& x, const String& y)     
  1227. {
  1228.   return compare(y, x) <= 0;
  1229. }
  1230.  
  1231. inline int operator<(const SubString& x, const String& y)      
  1232. {
  1233.   return compare(y, x) > 0;
  1234. }
  1235.  
  1236. inline int operator<=(const SubString& x, const String& y)     
  1237. {
  1238.   return compare(y, x) >= 0;
  1239. }
  1240.  
  1241. inline int operator==(const SubString& x, const SubString&  y) 
  1242. {
  1243.   return compare(x, y) == 0; 
  1244. }
  1245.  
  1246. inline int operator!=(const SubString& x, const SubString&  y)
  1247. {
  1248.   return compare(x, y) != 0;
  1249. }
  1250.  
  1251. inline int operator>(const SubString& x, const SubString&  y)      
  1252. {
  1253.   return compare(x, y) > 0;
  1254. }
  1255.  
  1256. inline int operator>=(const SubString& x, const SubString&  y)
  1257. {
  1258.   return compare(x, y) >= 0;
  1259. }
  1260.  
  1261. inline int operator<(const SubString& x, const SubString&  y) 
  1262. {
  1263.   return compare(x, y) < 0;
  1264. }
  1265.  
  1266. inline int operator<=(const SubString& x, const SubString&  y)
  1267. {
  1268.   return compare(x, y) <= 0;
  1269. }
  1270.  
  1271. inline int operator==(const SubString& x, const char* t) 
  1272. {
  1273.   return compare(x, t) == 0; 
  1274. }
  1275.  
  1276. inline int operator!=(const SubString& x, const char* t) 
  1277. {
  1278.   return compare(x, t) != 0;
  1279. }
  1280.  
  1281. inline int operator>(const SubString& x, const char* t)  
  1282. {
  1283.   return compare(x, t) > 0; 
  1284. }
  1285.  
  1286. inline int operator>=(const SubString& x, const char* t) 
  1287. {
  1288.   return compare(x, t) >= 0; 
  1289. }
  1290.  
  1291. inline int operator<(const SubString& x, const char* t)  
  1292. {
  1293.   return compare(x, t) < 0; 
  1294. }
  1295.  
  1296. inline int operator<=(const SubString& x, const char* t) 
  1297. {
  1298.   return compare(x, t) <= 0; 
  1299. }
  1300.  
  1301.  
  1302. // a helper needed by at, before, etc.
  1303.  
  1304. inline SubString String::_substr(int first, int l)
  1305. {
  1306.   if (first < 0 || (unsigned)(first + l) > length() )
  1307.     return SubString(_nilString, 0, 0) ;
  1308.   else 
  1309.     return SubString(*this, first, l);
  1310. }
  1311.  
  1312. #endif
  1313.