/* Web Polygraph http://www.web-polygraph.org/ * (C) 2003-2006 The Measurement Factory * Licensed under the Apache License, Version 2.0 */ #ifndef POLYGRAPH__XSTD_STRING_H #define POLYGRAPH__XSTD_STRING_H #include #include "xstd/h/iosfwd.h" #include "xstd/h/sstream.h" #include "xstd/Area.h" // memory storage to help with copy-on-write support class StrBuf { public: StrBuf(): theBuf(0), theSize(0), theUseLvl(0) {} ~StrBuf() { delete[] theBuf; } void set(const char *aBuf, int aSize); void alloc(int aSize); void realloc(int newSize); StrBuf *use() { theUseLvl++; return this; } StrBuf *abandon() { if (!--theUseLvl) delete this; return 0; } StrBuf *clone() const; public: char *theBuf; int theSize; mutable int theUseLvl; }; // a simple string class; to be improved later if needed class String { public: static const int npos = INT_MAX; public: String(): theBuf(0) {} String(const String &s): theBuf(0) { set(s); } String(const char *s): theBuf(0) { set(s); } String(const char *s, int aLen); ~String() { set(0); } String &operator =(const String &s) { set(s); return *this; } String &operator =(const char *s) { set(s); return *this; } const char *cstr() const { /* terminate(); */ return theBuf ? theBuf->theBuf : ""; } const char *data() const { return theBuf ? theBuf->theBuf : 0; } //int size() const { return theBuf ? theBuf->theSize : 0; } int len() const { return theBuf ? theBuf->theSize - 1 : 0; } const char *chr(char c) const; const char *rchr(char c) const; const char *str(const char *s) const; const char *str(const String &s) const; int cmp(const String &s) const; int cmp(const String &s, int len) const; int cmp(const char *s) const; int cmp(const char *s, int len) const; bool startsWith(const String &s) const; bool prefixOf(const char *buf) const; bool casePrefixOf(const char *buf, int l) const; bool caseEndsWith(const char *buf, int l) const; operator void*() const { return len() ? (void*)-1 : (void*)0; } bool operator !() const { return len() == 0; } int find(const Area &area, int offset = 0) const; int find(char c, int offset = 0) const; char operator [](int idx) const { return theBuf->theBuf[idx]; } char &operator [](int idx) { aboutToMod(); return theBuf->theBuf[idx]; } char operator *() const { return *theBuf->theBuf; } String operator +(char c) const; char last() const { return (*this)[len()-1]; } int hash() const; // cheap and lame // substring: [min, maxp1) String operator ()(int min, int maxp1) const; Area area(int offset, int size = npos) const; // append void append(const char *buf, int size); // also adds 0 if not there String &operator +=(const String &s); String &operator +=(char c); // case sensitive bool operator ==(const String &s) const { return cmp(s) == 0; } bool operator !=(const String &s) const { return !(*this == s); } bool operator ==(const char *s) const { return cmp(s) == 0; } bool operator !=(const char *s) const { return !(*this == s); } // low level access to internal buffer for reading, avoid char *alloc(int size); protected: String(StrBuf &aBuf): theBuf(&aBuf) { theBuf->use(); } void set(const char *s); void set(const String &s); void stretch(int newSize); void aboutToMod(); protected: StrBuf *theBuf; }; // probably faster than writing a constant "string" extern ostream &operator <<(ostream &os, const String &s); // slow but convenient extern String operator +(const String &s1, const String &s2); extern String Stream2String(ostringstream &os); // a strtok() replacement class StrIter { public: StrIter(const String &aStr, char aDel); bool eos() const { return !theTokBeg || !*theTokBeg; } operator void *() const { return eos() ? 0 : (void*)-1; } const char *tokBeg() const { return theTokBeg; } const char *tokEnd() const { return theTokEnd; } int tokLen() const { return tokEnd() - tokBeg(); } String token() const; StrIter &operator ++() { next(); return *this; } protected: void next(); void moveEnd(); protected: const String &theStr; const char *theTokBeg; const char *theTokEnd; const char theDel; // delimiter }; #endif