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