## modules/up/src/gnug++/String.h

/* [<][>][^][v][top][bottom][index][help] */

## FUNCTIONS

This source file includes following functions.

1. String
2. SubString
3. SubString
4. String
5. String
6. SubString
7. empty
8. chars
9. allocation
10. length
11. empty
12. chars
13. String
14. String
15. String
16. String
17. String
18. String
19. String
20. SubString
21. SubString
22. SubString
23. cat
24. cat
25. cat
26. cat
27. cat
28. cat
29. cat
30. cat
31. cat
32. cat
33. cat
34. cat
35. cat
36. cat
37. cat
38. cat
39. cat
40. cat
41. cat
42. cat
43. cat
44. cat
45. cat
46. cat
47. cat
48. cat
49. cat
50. cat
51. cat
52. cat
53. cat
54. cat
55. cat
56. cat
57. cat
58. cat
59. reverse
60. upcase
61. downcase
62. capitalize
63. reverse
64. upcase
65. downcase
66. capitalize
67. prepend
68. prepend
69. prepend
70. prepend
71. reverse
72. upcase
73. downcase
74. capitalize
75. elem
76. firstchar
77. lastchar
78. index
79. index
80. index
81. index
82. index
83. contains
84. contains
85. contains
86. contains
87. contains
88. contains
89. contains
90. contains
91. contains
92. contains
93. matches
94. matches
95. matches
96. matches
97. matches
98. contains
99. contains
100. contains
101. contains
102. contains
103. matches
104. gsub
105. gsub
106. gsub
107. gsub
108. gsub
109. _substr

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

/* [<][>][^][v][top][bottom][index][help] */