// This may look like C code, but it is really -*- C++ -*- /* Copyright (C) 1988 Free Software Foundation written by Doug Lea (dl@rocky.oswego.edu) This file is part of GNU CC. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU CC General Public License for full details. Everyone is granted permission to copy, modify and redistribute GNU CC, but only under the conditions described in the GNU CC General Public License. A copy of this license is supposed to have been given to you along with GNU CC so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #if defined(SHORT_NAMES) || defined(VMS) #define re_compile_pattern recmppat #define re_pattern_buffer repatbuf #define re_registers reregs #endif #ifndef _String_h #ifdef __GNUG__ #pragma once #pragma interface #endif #define _String_h 1 #include #include struct StrRep // internal String representations { unsigned short len; // string length unsigned short sz; // allocated space char s[1]; // the string starts here // (at least 1 char for trailing null) // allocated & expanded via non-public fcts }; // primitive ops on StrReps -- nearly all String fns go through these. StrRep* Salloc(StrRep*, const char*, int, int); StrRep* Scopy(StrRep*, StrRep*); StrRep* Sresize(StrRep*, int); StrRep* Scat(StrRep*, const char*, int, const char*, int); StrRep* Scat(StrRep*, const char*, int,const char*,int, const char*,int); StrRep* Sprepend(StrRep*, const char*, int); StrRep* Sreverse(StrRep*, StrRep*); StrRep* Supcase(StrRep*, StrRep*); StrRep* Sdowncase(StrRep*, StrRep*); StrRep* Scapitalize(StrRep*, StrRep*); // These classes need to be defined in the order given class String; class SubString; class SubString { friend class String; protected: String& S; // The String I'm a substring of unsigned short pos; // starting position in S's rep unsigned short len; // length of substring void assign(StrRep*, const char*, int = -1); SubString(String& x, int p, int l); SubString(const SubString& x); public: // Note there are no public constructors. SubStrings are always // created via String operations ~SubString(); void operator = (const String& y); void operator = (const SubString& y); void operator = (const char* t); void operator = (char c); // return 1 if target appears anywhere in SubString; else 0 int contains(char c) const; int contains(const String& y) const; int contains(const SubString& y) const; int contains(const char* t) const; int contains(const Regex& r) const; // return 1 if target matches entire SubString int matches(const Regex& r) const; // IO friend ostream& operator<<(ostream& s, const SubString& x); // status int length() const; int empty() const; const char* chars() const; int OK() const; }; class String { friend class SubString; protected: StrRep* rep; // Strings are pointers to their representations // some helper functions int search(int, int, const char*, int = -1) const; int search(int, int, char) const; int match(int, int, int, const char*, int = -1) const; int _gsub(const char*, int, const char* ,int); int _gsub(const Regex&, const char*, int); SubString _substr(int, int); public: // constructors & assignment String(); String(const String& x); String(const SubString& x); String(const char* t); String(const char* t, int len); String(char c); ~String(); void operator = (const String& y); void operator = (const char* y); void operator = (char c); void operator = (const SubString& y); // concatenation void operator += (const String& y); void operator += (const SubString& y); void operator += (const char* t); void operator += (char c); void prepend(const String& y); void prepend(const SubString& y); void prepend(const char* t); void prepend(char c); // procedural versions: // concatenate first 2 args, store result in last arg friend void cat(const String&, const String&, String&); friend void cat(const String&, const SubString&, String&); friend void cat(const String&, const char*, String&); friend void cat(const String&, char, String&); friend void cat(const SubString&, const String&, String&); friend void cat(const SubString&, const SubString&, String&); friend void cat(const SubString&, const char*, String&); friend void cat(const SubString&, char, String&); friend void cat(const char*, const String&, String&); friend void cat(const char*, const SubString&, String&); friend void cat(const char*, const char*, String&); friend void cat(const char*, char, String&); // double concatenation, by request. (yes, there are too many versions, // but if one is supported, then the others should be too...) // Concatenate first 3 args, store in last arg friend void cat(const String&,const String&, const String&,String&); friend void cat(const String&,const String&,const SubString&,String&); friend void cat(const String&,const String&, const char*, String&); friend void cat(const String&,const String&, char, String&); friend void cat(const String&,const SubString&,const String&,String&); friend void cat(const String&,const SubString&,const SubString&,String&); friend void cat(const String&,const SubString&, const char*, String&); friend void cat(const String&,const SubString&, char, String&); friend void cat(const String&,const char*, const String&, String&); friend void cat(const String&,const char*, const SubString&, String&); friend void cat(const String&,const char*, const char*, String&); friend void cat(const String&,const char*, char, String&); friend void cat(const char*, const String&, const String&,String&); friend void cat(const char*,const String&,const SubString&,String&); friend void cat(const char*,const String&, const char*, String&); friend void cat(const char*,const String&, char, String&); friend void cat(const char*,const SubString&,const String&,String&); friend void cat(const char*,const SubString&,const SubString&,String&); friend void cat(const char*,const SubString&, const char*, String&); friend void cat(const char*,const SubString&, char, String&); friend void cat(const char*,const char*, const String&, String&); friend void cat(const char*,const char*, const SubString&, String&); friend void cat(const char*,const char*, const char*, String&); friend void cat(const char*,const char*, char, String&); // searching & matching // return position of target in string or -1 for failure int index(char c, int startpos = 0) const; int index(const String& y, int startpos = 0) const; int index(const SubString& y, int startpos = 0) const; int index(const char* t, int startpos = 0) const; int index(const Regex& r, int startpos = 0) const; // return 1 if target appears anyhere in String; else 0 int contains(char c) const; int contains(const String& y) const; int contains(const SubString& y) const; int contains(const char* t) const; int contains(const Regex& r) const; // return 1 if target appears anywhere after position pos // (or before, if pos is negative) in String; else 0 int contains(char c, int pos) const; int contains(const String& y, int pos) const; int contains(const SubString& y, int pos) const; int contains(const char* t, int pos) const; int contains(const Regex& r, int pos) const; // return 1 if target appears at position pos in String; else 0 int matches(char c, int pos = 0) const; int matches(const String& y, int pos = 0) const; int matches(const SubString& y, int pos = 0) const; int matches(const char* t, int pos = 0) const; int matches(const Regex& r, int pos = 0) const; // return number of occurences of target in String int freq(char c) const; int freq(const String& y) const; int freq(const SubString& y) const; int freq(const char* t) const; // SubString extraction // Note that you can't take a substring of a const String, since // this leaves open the possiblility of indirectly modifying the // String through the SubString SubString at(int pos, int len); SubString operator () (int pos, int len); // synonym for at SubString at(const String& x, int startpos = 0); SubString at(const SubString& x, int startpos = 0); SubString at(const char* t, int startpos = 0); SubString at(char c, int startpos = 0); SubString at(const Regex& r, int startpos = 0); SubString before(int pos); SubString before(const String& x, int startpos = 0); SubString before(const SubString& x, int startpos = 0); SubString before(const char* t, int startpos = 0); SubString before(char c, int startpos = 0); SubString before(const Regex& r, int startpos = 0); SubString through(int pos); SubString through(const String& x, int startpos = 0); SubString through(const SubString& x, int startpos = 0); SubString through(const char* t, int startpos = 0); SubString through(char c, int startpos = 0); SubString through(const Regex& r, int startpos = 0); SubString from(int pos); SubString from(const String& x, int startpos = 0); SubString from(const SubString& x, int startpos = 0); SubString from(const char* t, int startpos = 0); SubString from(char c, int startpos = 0); SubString from(const Regex& r, int startpos = 0); SubString after(int pos); SubString after(const String& x, int startpos = 0); SubString after(const SubString& x, int startpos = 0); SubString after(const char* t, int startpos = 0); SubString after(char c, int startpos = 0); SubString after(const Regex& r, int startpos = 0); // deletion // delete len chars starting at pos void del(int pos, int len); // delete the first occurrence of target after startpos void del(const String& y, int startpos = 0); void del(const SubString& y, int startpos = 0); void del(const char* t, int startpos = 0); void del(char c, int startpos = 0); void del(const Regex& r, int startpos = 0); // global substitution: substitute all occurrences of pat with repl int gsub(const String& pat, const String& repl); int gsub(const SubString& pat, const String& repl); int gsub(const char* pat, const String& repl); int gsub(const char* pat, const char* repl); int gsub(const Regex& pat, const String& repl); // friends & utilities // split string into array res at separators; return number of elements friend int split(const String& x, String res[], int maxn, const String& sep); friend int split(const String& x, String res[], int maxn, const Regex& sep); friend String common_prefix(const String& x, const String& y, int startpos = 0); friend String common_suffix(const String& x, const String& y, int startpos = -1); friend String replicate(char c, int n); friend String replicate(const String& y, int n); friend String join(String src[], int n, const String& sep); // simple builtin transformations friend String reverse(const String& x); friend String upcase(const String& x); friend String downcase(const String& x); friend String capitalize(const String& x); // in-place versions of above void reverse(); void upcase(); void downcase(); void capitalize(); // element extraction char& operator [] (int i); char elem(int i) const; char firstchar() const; char lastchar() const; // conversion operator const char*() const; const char* chars() const; // IO friend ostream& operator<<(ostream& s, const String& x); friend ostream& operator<<(ostream& s, const SubString& x); friend istream& operator>>(istream& s, String& x); friend int readline(istream& s, String& x, char terminator = '\n', int discard_terminator = 1); // status int length() const; int empty() const; // preallocate some space for String void alloc(int newsize); // report current allocation (not length!) int allocation() const; volatile void error(const char* msg) const; int OK() const; }; typedef String StrTmp; // for backward compatibility // other externs int compare(const String& x, const String& y); int compare(const String& x, const SubString& y); int compare(const String& x, const char* y); int compare(const SubString& x, const String& y); int compare(const SubString& x, const SubString& y); int compare(const SubString& x, const char* y); int fcompare(const String& x, const String& y); // ignore case extern StrRep _nilStrRep; extern String _nilString; // other inlines String operator + (const String& x, const String& y); String operator + (const String& x, const SubString& y); String operator + (const String& x, const char* y); String operator + (const String& x, char y); String operator + (const SubString& x, const String& y); String operator + (const SubString& x, const SubString& y); String operator + (const SubString& x, const char* y); String operator + (const SubString& x, char y); String operator + (const char* x, const String& y); String operator + (const char* x, const SubString& y); int operator==(const String& x, const String& y); int operator!=(const String& x, const String& y); int operator> (const String& x, const String& y); int operator>=(const String& x, const String& y); int operator< (const String& x, const String& y); int operator<=(const String& x, const String& y); int operator==(const String& x, const SubString& y); int operator!=(const String& x, const SubString& y); int operator> (const String& x, const SubString& y); int operator>=(const String& x, const SubString& y); int operator< (const String& x, const SubString& y); int operator<=(const String& x, const SubString& y); int operator==(const String& x, const char* t); int operator!=(const String& x, const char* t); int operator> (const String& x, const char* t); int operator>=(const String& x, const char* t); int operator< (const String& x, const char* t); int operator<=(const String& x, const char* t); int operator==(const SubString& x, const String& y); int operator!=(const SubString& x, const String& y); int operator> (const SubString& x, const String& y); int operator>=(const SubString& x, const String& y); int operator< (const SubString& x, const String& y); int operator<=(const SubString& x, const String& y); int operator==(const SubString& x, const SubString& y); int operator!=(const SubString& x, const SubString& y); int operator> (const SubString& x, const SubString& y); int operator>=(const SubString& x, const SubString& y); int operator< (const SubString& x, const SubString& y); int operator<=(const SubString& x, const SubString& y); int operator==(const SubString& x, const char* t); int operator!=(const SubString& x, const char* t); int operator> (const SubString& x, const char* t); int operator>=(const SubString& x, const char* t); int operator< (const SubString& x, const char* t); int operator<=(const SubString& x, const char* t); #if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES) // status reports, needed before defining other things inline int String::length() const { return rep->len; } inline int String::empty() const { return rep->len == 0; } inline const char* String::chars() const { return &(rep->s[0]); } inline int String::allocation() const { return rep->sz; } inline void String::alloc(int newsize) { rep = Sresize(rep, newsize); } inline int SubString::length() const { return len; } inline int SubString::empty() const { return len == 0; } inline const char* SubString::chars() const { return &(S.rep->s[pos]); } // constructors inline String::String() : rep(&_nilStrRep) {} inline String::String(const String& x) : rep(Scopy(0, x.rep)) {} inline String::String(const char* t) : rep(Salloc(0, t, -1, -1)) {} inline String::String(const char* t, int tlen) : rep(Salloc(0, t, tlen, tlen)) {} inline String::String(const SubString& y) : rep(Salloc(0, y.chars(), y.length(), y.length())) {} inline String::String(char c) : rep(Salloc(0, &c, 1, 1)) {} inline String::~String() { if (rep != &_nilStrRep) delete rep; } inline SubString::SubString(const SubString& x) :S(x.S), pos(x.pos), len(x.len) {} inline SubString::SubString(String& x, int first, int l) :S(x), pos(first), len(l) {} inline SubString::~SubString() {} // assignment inline void String::operator = (const String& y) { rep = Scopy(rep, y.rep); } inline void String::operator=(const char* t) { rep = Salloc(rep, t, -1, -1); } inline void String::operator=(const SubString& y) { rep = Salloc(rep, y.chars(), y.length(), y.length()); } inline void String::operator=(char c) { rep = Salloc(rep, &c, 1, 1); } inline void SubString::operator = (const char* ys) { assign(0, ys); } inline void SubString::operator = (char ch) { assign(0, &ch, 1); } inline void SubString::operator = (const String& y) { assign(y.rep, y.chars(), y.length()); } inline void SubString::operator = (const SubString& y) { assign(y.S.rep, y.chars(), y.length()); } // Zillions of cats... inline void cat(const String& x, const String& y, String& r) { r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const String& x, const SubString& y, String& r) { r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const String& x, const char* y, String& r) { r.rep = Scat(r.rep, x.chars(), x.length(), y, -1); } inline void cat(const String& x, char y, String& r) { r.rep = Scat(r.rep, x.chars(), x.length(), &y, 1); } inline void cat(const SubString& x, const String& y, String& r) { r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const SubString& x, const SubString& y, String& r) { r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const SubString& x, const char* y, String& r) { r.rep = Scat(r.rep, x.chars(), x.length(), y, -1); } inline void cat(const SubString& x, char y, String& r) { r.rep = Scat(r.rep, x.chars(), x.length(), &y, 1); } inline void cat(const char* x, const String& y, String& r) { r.rep = Scat(r.rep, x, -1, y.chars(), y.length()); } inline void cat(const char* x, const SubString& y, String& r) { r.rep = Scat(r.rep, x, -1, y.chars(), y.length()); } inline void cat(const char* x, const char* y, String& r) { r.rep = Scat(r.rep, x, -1, y, -1); } inline void cat(const char* x, char y, String& r) { r.rep = Scat(r.rep, x, -1, &y, 1); } inline void cat(const String& a, const String& x, const String& y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const String& a, const String& x, const SubString& y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const String& a, const String& x, const char* y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y, -1); } inline void cat(const String& a, const String& x, char y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), &y, 1); } inline void cat(const String& a, const SubString& x, const String& y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const String& a, const SubString& x, const SubString& y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const String& a, const SubString& x, const char* y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y, -1); } inline void cat(const String& a, const SubString& x, char y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), &y, 1); } inline void cat(const String& a, const char* x, const String& y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y.chars(), y.length()); } inline void cat(const String& a, const char* x, const SubString& y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y.chars(), y.length()); } inline void cat(const String& a, const char* x, const char* y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y, -1); } inline void cat(const String& a, const char* x, char y, String& r) { r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, &y, 1); } inline void cat(const char* a, const String& x, const String& y, String& r) { r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const char* a, const String& x, const SubString& y, String& r) { r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const char* a, const String& x, const char* y, String& r) { r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y, -1); } inline void cat(const char* a, const String& x, char y, String& r) { r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), &y, 1); } inline void cat(const char* a, const SubString& x, const String& y, String& r) { r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const char* a, const SubString& x, const SubString& y, String& r) { r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length()); } inline void cat(const char* a, const SubString& x, const char* y, String& r) { r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y, -1); } inline void cat(const char* a, const SubString& x, char y, String& r) { r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), &y, 1); } inline void cat(const char* a, const char* x, const String& y, String& r) { r.rep = Scat(r.rep, a, -1, x, -1, y.chars(), y.length()); } inline void cat(const char* a, const char* x, const SubString& y, String& r) { r.rep = Scat(r.rep, a, -1, x, -1, y.chars(), y.length()); } inline void cat(const char* a, const char* x, const char* y, String& r) { r.rep = Scat(r.rep, a, -1, x, -1, y, -1); } inline void cat(const char* a, const char* x, char y, String& r) { r.rep = Scat(r.rep, a, -1, x, -1, &y, 1); } // operator versions inline void String::operator +=(const String& y) { cat(*this, y, *this); } inline void String::operator +=(const SubString& y) { cat(*this, y, *this); } inline void String::operator += (const char* y) { cat(*this, y, *this); } inline void String:: operator +=(char y) { cat(*this, y, *this); } // constructive concatenation #if defined(__GNUG__) && !defined(NO_NRV) inline String operator + (const String& x, const String& y) return r; { cat(x, y, r); } inline String operator + (const String& x, const SubString& y) return r; { cat(x, y, r); } inline String operator + (const String& x, const char* y) return r; { cat(x, y, r); } inline String operator + (const String& x, char y) return r; { cat(x, y, r); } inline String operator + (const SubString& x, const String& y) return r; { cat(x, y, r); } inline String operator + (const SubString& x, const SubString& y) return r; { cat(x, y, r); } inline String operator + (const SubString& x, const char* y) return r; { cat(x, y, r); } inline String operator + (const SubString& x, char y) return r; { cat(x, y, r); } inline String operator + (const char* x, const String& y) return r; { cat(x, y, r); } inline String operator + (const char* x, const SubString& y) return r; { cat(x, y, r); } inline String reverse(const String& x) return r; { r.rep = Sreverse(x.rep, r.rep); } inline String upcase(const String& x) return r; { r.rep = Supcase(x.rep, r.rep); } inline String downcase(const String& x) return r; { r.rep = Sdowncase(x.rep, r.rep); } inline String capitalize(const String& x) return r; { r.rep = Scapitalize(x.rep, r.rep); } #else /* NO_NRV */ inline String operator + (const String& x, const String& y) { String r; cat(x, y, r); return r; } inline String operator + (const String& x, const SubString& y) { String r; cat(x, y, r); return r; } inline String operator + (const String& x, const char* y) { String r; cat(x, y, r); return r; } inline String operator + (const String& x, char y) { String r; cat(x, y, r); return r; } inline String operator + (const SubString& x, const String& y) { String r; cat(x, y, r); return r; } inline String operator + (const SubString& x, const SubString& y) { String r; cat(x, y, r); return r; } inline String operator + (const SubString& x, const char* y) { String r; cat(x, y, r); return r; } inline String operator + (const SubString& x, char y) { String r; cat(x, y, r); return r; } inline String operator + (const char* x, const String& y) { String r; cat(x, y, r); return r; } inline String operator + (const char* x, const SubString& y) { String r; cat(x, y, r); return r; } inline String reverse(const String& x) { String r; r.rep = Sreverse(x.rep, r.rep); return r; } inline String upcase(const String& x) { String r; r.rep = Supcase(x.rep, r.rep); return r; } inline String downcase(const String& x) { String r; r.rep = Sdowncase(x.rep, r.rep); return r; } inline String capitalize(const String& x) { String r; r.rep = Scapitalize(x.rep, r.rep); return r; } #endif // prepend inline void String::prepend(const String& y) { rep = Sprepend(rep, y.chars(), y.length()); } inline void String::prepend(const char* y) { rep = Sprepend(rep, y, -1); } inline void String::prepend(char y) { rep = Sprepend(rep, &y, 1); } inline void String::prepend(const SubString& y) { rep = Sprepend(rep, y.chars(), y.length()); } // misc transformations inline void String::reverse() { rep = Sreverse(rep, rep); } inline void String::upcase() { rep = Supcase(rep, rep); } inline void String::downcase() { rep = Sdowncase(rep, rep); } inline void String::capitalize() { rep = Scapitalize(rep, rep); } // element extraction inline char& String::operator [] (int i) { if (((unsigned)i) >= length()) error("invalid index"); return rep->s[i]; } inline char String::elem (int i) const { if (((unsigned)i) >= length()) error("invalid index"); return rep->s[i]; } inline char String::firstchar() const { return elem(0); } inline char String::lastchar() const { return elem(length() - 1); } // searching inline int String::index(char c, int startpos) const { return search(startpos, length(), c); } inline int String::index(const char* t, int startpos) const { return search(startpos, length(), t); } inline int String::index(const String& y, int startpos) const { return search(startpos, length(), y.chars(), y.length()); } inline int String::index(const SubString& y, int startpos) const { return search(startpos, length(), y.chars(), y.length()); } inline int String::index(const Regex& r, int startpos) const { int unused; return r.search(chars(), length(), unused, startpos); } inline int String::contains(char c) const { return search(0, length(), c) >= 0; } inline int String::contains(const char* t) const { return search(0, length(), t) >= 0; } inline int String::contains(const String& y) const { return search(0, length(), y.chars(), y.length()) >= 0; } inline int String::contains(const SubString& y) const { return search(0, length(), y.chars(), y.length()) >= 0; } inline int String::contains(char c, int p) const { return match(p, length(), 0, &c, 1) >= 0; } inline int String::contains(const char* t, int p) const { return match(p, length(), 0, t) >= 0; } inline int String::contains(const String& y, int p) const { return match(p, length(), 0, y.chars(), y.length()) >= 0; } inline int String::contains(const SubString& y, int p) const { return match(p, length(), 0, y.chars(), y.length()) >= 0; } inline int String::contains(const Regex& r) const { int unused; return r.search(chars(), length(), unused, 0) >= 0; } inline int String::contains(const Regex& r, int p) const { return r.match(chars(), length(), p) >= 0; } inline int String::matches(const SubString& y, int p) const { return match(p, length(), 1, y.chars(), y.length()) >= 0; } inline int String::matches(const String& y, int p) const { return match(p, length(), 1, y.chars(), y.length()) >= 0; } inline int String::matches(const char* t, int p) const { return match(p, length(), 1, t) >= 0; } inline int String::matches(char c, int p) const { return match(p, length(), 1, &c, 1) >= 0; } inline int String::matches(const Regex& r, int p) const { int l = (p < 0)? -p : length() - p; return r.match(chars(), length(), p) == l; } inline int SubString::contains(const char* t) const { return S.search(pos, pos+len, t) >= 0; } inline int SubString::contains(const String& y) const { return S.search(pos, pos+len, y.chars(), y.length()) >= 0; } inline int SubString::contains(const SubString& y) const { return S.search(pos, pos+len, y.chars(), y.length()) >= 0; } inline int SubString::contains(char c) const { return S.search(pos, pos+len, 0, c) >= 0; } inline int SubString::contains(const Regex& r) const { int unused; return r.search(chars(), len, unused, 0) >= 0; } inline int SubString::matches(const Regex& r) const { return r.match(chars(), len, 0) == len; } inline int String::gsub(const String& pat, const String& r) { return _gsub(pat.chars(), pat.length(), r.chars(), r.length()); } inline int String::gsub(const SubString& pat, const String& r) { return _gsub(pat.chars(), pat.length(), r.chars(), r.length()); } inline int String::gsub(const Regex& pat, const String& r) { return _gsub(pat, r.chars(), r.length()); } inline int String::gsub(const char* pat, const String& r) { return _gsub(pat, -1, r.chars(), r.length()); } inline int String::gsub(const char* pat, const char* r) { return _gsub(pat, -1, r, -1); } inline String::operator const char*() const { return str(chars()); } inline ostream& operator<<(ostream& s, const String& x) { #ifdef VMS s << x.chars(); return s; #else s.put(x.chars()); return s; #endif } // a zillion comparison operators inline int operator==(const String& x, const String& y) { return compare(x, y) == 0; } inline int operator!=(const String& x, const String& y) { return compare(x, y) != 0; } inline int operator>(const String& x, const String& y) { return compare(x, y) > 0; } inline int operator>=(const String& x, const String& y) { return compare(x, y) >= 0; } inline int operator<(const String& x, const String& y) { return compare(x, y) < 0; } inline int operator<=(const String& x, const String& y) { return compare(x, y) <= 0; } inline int operator==(const String& x, const SubString& y) { return compare(x, y) == 0; } inline int operator!=(const String& x, const SubString& y) { return compare(x, y) != 0; } inline int operator>(const String& x, const SubString& y) { return compare(x, y) > 0; } inline int operator>=(const String& x, const SubString& y) { return compare(x, y) >= 0; } inline int operator<(const String& x, const SubString& y) { return compare(x, y) < 0; } inline int operator<=(const String& x, const SubString& y) { return compare(x, y) <= 0; } inline int operator==(const String& x, const char* t) { return compare(x, t) == 0; } inline int operator!=(const String& x, const char* t) { return compare(x, t) != 0; } inline int operator>(const String& x, const char* t) { return compare(x, t) > 0; } inline int operator>=(const String& x, const char* t) { return compare(x, t) >= 0; } inline int operator<(const String& x, const char* t) { return compare(x, t) < 0; } inline int operator<=(const String& x, const char* t) { return compare(x, t) <= 0; } inline int operator==(const SubString& x, const String& y) { return compare(y, x) == 0; } inline int operator!=(const SubString& x, const String& y) { return compare(y, x) != 0; } inline int operator>(const SubString& x, const String& y) { return compare(y, x) < 0; } inline int operator>=(const SubString& x, const String& y) { return compare(y, x) <= 0; } inline int operator<(const SubString& x, const String& y) { return compare(y, x) > 0; } inline int operator<=(const SubString& x, const String& y) { return compare(y, x) >= 0; } inline int operator==(const SubString& x, const SubString& y) { return compare(x, y) == 0; } inline int operator!=(const SubString& x, const SubString& y) { return compare(x, y) != 0; } inline int operator>(const SubString& x, const SubString& y) { return compare(x, y) > 0; } inline int operator>=(const SubString& x, const SubString& y) { return compare(x, y) >= 0; } inline int operator<(const SubString& x, const SubString& y) { return compare(x, y) < 0; } inline int operator<=(const SubString& x, const SubString& y) { return compare(x, y) <= 0; } inline int operator==(const SubString& x, const char* t) { return compare(x, t) == 0; } inline int operator!=(const SubString& x, const char* t) { return compare(x, t) != 0; } inline int operator>(const SubString& x, const char* t) { return compare(x, t) > 0; } inline int operator>=(const SubString& x, const char* t) { return compare(x, t) >= 0; } inline int operator<(const SubString& x, const char* t) { return compare(x, t) < 0; } inline int operator<=(const SubString& x, const char* t) { return compare(x, t) <= 0; } // a helper needed by at, before, etc. inline SubString String::_substr(int first, int l) { if (first < 0 || (unsigned)(first + l) > length()) return SubString(_nilString, 0, 0) ; else return SubString(*this, first, l); } #endif #endif