/*ident "@(#)String:incl/String.h 3.2" */ /****************************************************************************** * * C++ Standard Components, Release 3.0. * * Copyright (c) 1991, 1992 AT&T and Unix System Laboratories, Inc. * Copyright (c) 1988, 1989, 1990 AT&T. All Rights Reserved. * * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T and Unix System * Laboratories, Inc. The copyright notice above does not evidence * any actual or intended publication of such source code. * ******************************************************************************/ #ifndef ATTLCSTRINGH #define ATTLCSTRINGH #include #ifndef __hpux #include #else #include #endif #include #include #include class Srep_ATTLC; class Stringsize; class String; class Tmpstring; class Substring; class ostream; class istream; class Srep_ATTLC { // String Representation public: enum { MAXS = 8, MAXL = 64 }; static Srep_ATTLC* nullrep_; // nullrep always has refc == 0 and max == 0 static Pool* Reelp; // Pool for "reel" small strings static Pool* SPoolp; // Pool for smallish strings static void initialize() { if (Reelp == 0) doinitialize(); } static void doinitialize(); static Srep_ATTLC* nullrep() { initialize(); return nullrep_; } static Srep_ATTLC *new_srep(unsigned); static Srep_ATTLC *get_long(unsigned); unsigned len; unsigned max; unsigned char refc; char str[MAXS]; Srep_ATTLC() { len = 0; max = 0; refc = 0; } void rcdec() { if(refc && --refc==0) delete_srep(); } void rcuninc() { --refc; } void rcinc() { if(refc) refc++; } void delete_srep(); }; class Stringsize { // for declarations of large Strings unsigned int i; friend class String; public: Stringsize(unsigned int x) { i = x; } ~Stringsize() {} int size() { return i; } }; class String { // the String Srep_ATTLC *d; friend class Tmpstring; friend class Substring; String(Srep_ATTLC* r) { d = r; } String& newcopy(char); void reserve_grow(int); void overflow() const; public: String() { d = Srep_ATTLC::nullrep(); } String(const char*); String(const char*,unsigned); String(char c) { d = Srep_ATTLC::new_srep(1); d->str[0]=c; } String(Stringsize s) { d = Srep_ATTLC::new_srep(s.i); d->len=0; } String(const String& s) { d = s.d; d->rcinc(); if (d->refc == 0 && d->max != 0) s.overflow(); } inline String(const Tmpstring&); inline String(const Substring&); friend String int_to_str(int); friend String long_to_str(long); inline operator const char*() const; ~String() { d->rcdec(); } /* ASSIGNMENT */ inline String& operator=(const String&); void assign(const char*, unsigned len); String& operator=(const char*); inline String& operator=(char); String& operator=(Stringsize); /* CHANGE SIZE */ void reserve(Stringsize n) { if (n.i >= d->max) reserve_grow(n.i); } inline void shrink(int); /* special version for G2++ */ void g2_shrink(int newlen) { if (newlen < d->len) d->len = newlen; } /* APPENDING */ String& operator+=(const String&); void append(const char*, unsigned len); String& operator+=(const char*); inline String& operator+=(char); inline String& put(const String&); inline String& put(const char*); inline String& put(char); /* ADDITION */ friend Tmpstring operator+(const String&,const String&); friend Tmpstring operator+(const String&,const char*); friend Tmpstring operator+(const String&,char); friend Tmpstring operator+(const char*,const String&); friend Tmpstring operator+(char,const String&); /* MISCELLANEOUS */ inline void pad(int, int = -1); /* special version for G2++ */ void g2_pad(int n, int att_pad_char = -1) { if (n + d->len >= d->max) reserve_grow(n + d->len); if (att_pad_char != -1) memset(&d->str[d->len], att_pad_char, n); d->len += n; } unsigned length() const { return d->len; } int is_empty() const { return d->len ? 0 : 1; } void make_empty() { assign("", 0); } unsigned max() const { return d->max; } int nrefs() const { return d->refc; } const Srep_ATTLC *rep() const { return d; } inline void uniq(); inline char char_at(unsigned) const; char& operator[](unsigned); char& operator[](int i) {return ((*this).operator[]((unsigned) i));} inline char operator[](unsigned) const; char operator[](int i) const {return ((*this).operator[]((unsigned) i));} Substring operator()(unsigned,unsigned); Substring operator()(unsigned); String chunk(unsigned,unsigned) const; String chunk(unsigned) const; int index(const String&,unsigned pos = 0) const; int index(char,unsigned pos = 0) const; int hashval() const; char* dump(char* s) const { memcpy(s,d->str,d->len); s[d->len]='\0'; return s; } int getX(char&); int get() { char c; return getX(c); } int unputX(char&); int unput() { char c; return unputX(c); } String& unget(char); String& unget(const String&); inline int firstX(char&) const; inline int lastX(char&) const; /* COMPARISON OPERATORS */ inline int compare(const String&) const; inline int compare(const char*) const; friend inline int operator==(const String&,const String&); friend inline int operator==(const String&,const char*); friend inline int operator!=(const String&,const String&); friend inline int operator!=(const String&,const char*); /* SYSTEM FUNCTIONS */ #if defined(SYSV) && !defined(__hpux) friend int read(int, String&, unsigned); #else friend int read(int, String&, int); #endif friend int write(int fd, const String& s) { return write(fd, s.d->str, s.d->len); } friend int puts(const String&); friend int fputs(const String&, FILE*); /* STRING(3) FUNCTIONS */ int strchr(char) const; int strrchr(char) const; int strpbrk(const String&) const; int strspn(const String&) const; int strcspn(const String&) const; /* MISCELLANEOUS */ int match(const String&) const; int match(const char *) const; int firstdiff(const String&) const; int firstdiff(const char *) const; /* INPUT/OUTPUT */ int read(istream&,int); friend /*inline*/ ostream& operator<<(ostream&,const String&); friend istream& operator>>(istream&,String&); /* CASE FUNCTIONS */ String upper() const; String lower() const; }; class Tmpstring { // Class of String temporaries for Addition Srep_ATTLC *d; char strung; friend class String; void overflow() const; public: Tmpstring(Srep_ATTLC* r) { strung=0; d = r; } Tmpstring(const String& s) { strung=0; d = s.d; s.d->rcinc(); if (s.d->refc == 0 && s.d->max != 0) s.overflow(); } Tmpstring(const Tmpstring& t) { strung=0; d = t.d; d->rcinc(); if (d->refc == 0 && d->max != 0) t.overflow(); } Tmpstring& operator+(const String&); Tmpstring& operator+(const char*); Tmpstring& operator+(char); ~Tmpstring() { if(!strung) d->rcdec(); } #ifndef __cplusplus friend ostream& operator<<(ostream&,const Tmpstring&); #endif }; class Substring { friend class String; String *ss; int oo; int ll; Substring(String &i,int o,int l) : ss(&i), oo(o), ll(l) { } public: Substring(const Substring&); void operator=(const String&); void operator=(const char* s); String *it() const { return ss; } int offset() const { return oo; } int length() const { return ll; } #ifndef __cplusplus friend ostream& operator<<(ostream&,const Substring&); #endif }; // inline functions inline String::String(const Tmpstring& t) { ((Tmpstring*) &t)->strung=1; d = t.d; } inline String::String(const Substring& s) { d = Srep_ATTLC::new_srep(s.ll); if(s.ll) memcpy(d->str,s.ss->d->str+s.oo,s.ll); } inline String::operator const char*() const { if (d->len >= d->max && d->len) ((String *) this)->reserve_grow(d->len + 1); *(d->str + d->len) = '\0'; return (d->str); } inline String& String::operator=(const String& r) { r.d->rcinc(); if (r.d->refc == 0 && r.d->max != 0) { r.d->rcuninc(); // r.d->refc == 255 r.overflow(); // make new node -- r.d->refc() == 1, oldr.d->refc == 254 r.d->rcinc(); // now r.d->refc == 2 } d->rcdec(); d = r.d; return *this; } inline String& String::operator=(char c) { if(d->refc!=1) { d->rcdec(); d = Srep_ATTLC::new_srep(1); } d->str[0] = c; d->len = 1; return *this; } inline int String::compare(const String& s) const { register int dlen = d->len; register int slen = s.d->len; register int i = memcmp(d->str,s.d->str,dlen < slen ? dlen : slen); return i ? i : (dlen - slen); } inline int String::compare(const char* s) const { register int dlen = d->len; register int ln = s ? strlen(s) : 0; register int i = memcmp(d->str,s, (dlen < ln ? dlen : ln)); return i ? i : (dlen - ln); } inline int strcmp(const String& s,const String& t) {return s.compare(t);} inline int strcmp(const String& s,const char* p) {return s.compare(p);} inline int strcmp(const char* p,const String& t) {return -(t.compare(p));} inline int compare(const String& s,const String& t) {return s.compare(t);} inline int operator==(const String& t,const String& s) { register int dlen = t.d->len; register int retval; if ((dlen != s.d->len) || (dlen && t.d->str[0] != s.d->str[0]) || (dlen>1 && t.d->str[1] != s.d->str[1])) retval = 0; else retval = !memcmp(t.d->str,s.d->str,dlen); return retval; } inline int operator==(const String& t,const char* s) { register int dlen = t.d->len; register int retval; if (!s || (dlen && t.d->str[0]!=s[0]) || (dlen>1 && s[0]!='\0' && t.d->str[1]!=s[1])) retval = 0; else retval = (dlen != strlen(s)) ? 0 : !memcmp(t.d->str,s,dlen); return retval; } inline int operator==(const char* s,const String& t) { return t==s; } inline int operator!=(const String& t,const String& s) { register int dlen = t.d->len; register int retval; if ((dlen != s.d->len) || (dlen && t.d->str[0] != s.d->str[0]) || (dlen>1 && t.d->str[1] != s.d->str[1])) retval = 1; else retval = memcmp(t.d->str,s.d->str,dlen); return retval; } inline int operator!=(const String& t,const char* s) { register int dlen = t.d->len; register int retval; if (!s || (dlen && t.d->str[0]!=s[0]) || (dlen>1 && s[0]!='\0' && t.d->str[1]!=s[1])) retval = 1; else retval = (dlen != strlen(s)) ? 1 : memcmp(t.d->str,s,dlen); return retval; } inline int operator!=(const char* s,const String& t) { return t!=s; } inline int operator>=(const String& s,const String& t) { return s.compare(t)>=0; } inline int operator>=(const String& t,const char* s) { return t.compare(s)>=0; } inline int operator>=(const char* s,const String& t) { return t.compare(s)<=0; } inline int operator>(const String& s,const String& t) { return s.compare(t)>0; } inline int operator>(const String& t,const char* s) { return t.compare(s)>0; } inline int operator>(const char* s,const String& t) { return t.compare(s)<0; } inline int operator<=(const String& s,const String& t) { return s.compare(t)<=0; } inline int operator<=(const String& t,const char* s) { return t.compare(s)<=0; } inline int operator<=(const char* s,const String& t) { return t.compare(s)>=0; } inline int operator<(const String& s,const String& t) { return s.compare(t)<0; } inline int operator<(const String& t,const char* s) { return t.compare(s)<0; } inline int operator<(const char* s,const String& t) { return t.compare(s)>0; } /* STRING(3) FUNCTIONS */ inline int strchr(const String& s,int c) { return s.strchr((char) c); } inline int strrchr(const String& s,int c){ return s.strrchr((char) c); } inline int strpbrk(const String& s,const String& t) { return s.strpbrk(t);} inline int strpbrk(const char* s,const String& t) { return String(s).strpbrk(t);} inline int strpbrk(const String& s,const char* t) { return s.strpbrk(String(t));} inline int strspn(const String& s,const String& t) { return s.strspn(t);} inline int strspn(const char* s,const String& t) { return String(s).strspn(t);} inline int strspn(const String& s,const char* t) { return s.strspn(String(t));} inline int strcspn(const String& s,const String& t) { return s.strcspn(t);} inline int strcspn(const char* s,const String& t) { return String(s).strcspn(t);} inline int strcspn(const String& s,const char* t) { return s.strcspn(String(t));} inline char String::char_at(unsigned i) const { return d->str[i]; } inline char String::operator[](unsigned i) const { return d->str[i]; } inline int String::firstX(char &c) const { return d->len > 0 ? (c=d->str[0],1) : 0; } inline int String::lastX(char &c) const { return d->len > 0 ? (c=d->str[d->len - 1],1) : 0; } inline int length(const String& s) { return s.length(); } inline int hashval(const String& s) { return s.hashval(); } String sgets(istream&); int fgets(String&, int, FILE*); int fgets(String&, FILE*); int gets(String&); char* Memcpy_String_ATTLC(register char*,register const char*,int); inline String& String::operator+=(char c) { int append_to_current = 1; if (d->refc != 1 || d->len == d->max - 1) append_to_current = 0; else d->str[d->len++] = c; String &s = append_to_current ? *this : newcopy(c); return s; } inline String& String::put(const String& s) { return *this += s; } inline String& String::put(const char* s) { return *this += s; } inline String& String::put(char c) { return *this += c; } inline void String::uniq() { register Srep_ATTLC* x; if(d->refc > 1) { x = Srep_ATTLC::new_srep(d->len); memcpy(x->str,d->str,d->len); d->rcdec(); d = x; } } inline void String::shrink(int newlen) { uniq(); if (newlen < d->len) d->len = newlen; } inline void String::pad(int n, int att_pad_char) { uniq(); if (n + d->len >= d->max) reserve_grow(n + d->len); if (att_pad_char != -1) memset(&d->str[d->len], att_pad_char, n); d->len += n; } #endif