// __PRETTY_FUNCTION__ // http://www.icce.rug.nl/documents/cplusplus/cplusplus02.html#l13 #ifndef DSTRING_H #define DSTRING_H #include #include #include #include #include #include "types.h" // Default increment of string length (uses here a number divisible by 4) #define DSTRING_INCR 8 // Tolerable waste of space #define DSTRING_MAX_WASTE (3 * DSTRING_INCR - 1) #define MAXL(ll) \ ( (ll) < (u32)dstring::STR_MAXLEN ? (ll) : (u32)dstring::STR_MAXLEN ) class dstring { private: u32 data_length; u32 alloc_length; char *data; char bad_char[1]; public: // Maximum (iostream) input string length enum {STR_MAXLEN = 4096}; enum {INPUT_MAXLEN = 256}; /* Summary: dstring(); dstring(const dstring &_str); dstring(const char *_txt); dstring(char _ch, u32 _count); dstring(const char _ch); dstring(const int _i); <--- Converts _i to string dstring(const unsigned int _i); <--- Converts _i to string ~dstring(); dstring &operator = (const dstring &_str); inline dstring &operator += (const dstring &_str); inline dstring &operator += (const char _ch); char &at(u32 _pos); char &operator [] (u32 _pos); dstring &erase(u32 _len); dstring &resize(u32 _len, const char _ch = '\0'); int operator == (const dstring &_str); int operator != (const dstring &_str); int operator > (const dstring &_str); int operator >= (const dstring &_str); int operator < (const dstring &_str); int operator <= (const dstring &_str); void squeeze(); friend dstring operator + (const dstring &_str1, const dstring &_str2); friend dstring operator + (const dstring &_str1, const char _ch); friend dstring operator + (const dstring &_str1, const char *_txt); friend std::ostream &operator << (std::ostream &_out, const dstring &_str); friend std::istream &operator >> (std::istream &_in, dstring &_str); friend std::istream &getline(std::istream &_in, dstring &_str); */ private: void deleteData() { if (data) delete [] data; init0(); } void allocateData(u32 _length) { u32 siz; try { // Expand? if (_length > alloc_length) { char *p; // Calculate new size siz = (((_length - 1)/ DSTRING_INCR)* DSTRING_INCR) + DSTRING_INCR; p = new char[siz * sizeof(char)]; // Enough memory? if (!p) throw "dstring::allocate: Cannot allocate memory"; if (data) { memmove(p, data, data_length *sizeof(char)); delete [] data; } data = p; // Set new slots to NULL memset(data + data_length, '\0', (siz - data_length)*sizeof(char)); alloc_length = siz; } } catch ( char *e) { std::cerr << e << std::endl; throw; } } void init0() { data = NULL; data_length = alloc_length = 0; } public: inline u32 length() const { if (data_length == 0) return 0; else return data_length - 1; } inline u32 size() const { return length(); } inline bool empty() const { return length() == 0; } inline operator const char *() const { return (const char *)data; } ; inline const char *c_str() const { return (const char *)data; } inline int isNull() { return (!data_length); } dstring() { init0(); } ~dstring() { this->deleteData(); } // Copy constructor dstring(const dstring &_str) { init0(); copyFromText(_str.c_str()); } dstring(const char *_txt) { init0(); copyFromText(_txt); } dstring(char _ch, u32 _count) { u32 len; init0(); len = MAXL(_count+1); allocateData(len); _count = len - 1; while (_count--) data[_count] = _ch; data[len] = '\0'; data_length = len; } dstring(const char _ch) { u32 len; init0(); len = 2; allocateData(len); *data = _ch; *(data +1) = '\0'; data_length = len; } dstring(const int _i) { // Integer --> String char s[48]; init0(); sprintf(s, "%d", _i); copyFromText(s); } dstring(const unsigned int _i) { // Unsigned integer --> String char s[48]; init0(); sprintf(s, "%d", _i); copyFromText(s); } dstring(double _d) { // Double --> String char s[48]; init0(); sprintf(s, "%lf", _d); copyFromText(s); } void copyFromText(const char *_txt) { u32 len = MAXL(dstring::s_strlen(_txt)+1); this->allocateData(len); dstring::s_strncpy(data, (char*)_txt, len-1); *(data + len) = '\0'; data_length = len; } dstring &operator = (const dstring &_str) { deleteData(); copyFromText(_str.c_str()); return *this; } inline dstring &operator += (const dstring &_str) { *this = *this + _str; return *this; } inline dstring &operator += (const char _ch) { *this = *this + _ch; return *this; } char &at(u32 _pos) { if (_pos < length()) return data[_pos]; else return dstring::bad_char[0]; } char &operator [] (u32 _pos) { return this->at(_pos); } dstring &erase(u32 _len) { if (_len < length()) { // dstring("abcdef").erase(3) => "abc\0" data[_len] = '\0'; data_length = _len+1; squeeze(); } return *this; } dstring &resize(u32 _len, const char _ch = '\0') { if (_len < length()) { erase(_len); } else { dstring tempstr(_ch, _len - length()); *this += tempstr; } return *this; } void squeeze() { return; } // --------------------------------------- // Compare operators inline int operator == (const dstring &_str) { // Case insensitive return dstring::s_stricmp(data, (char*)_str.c_str()) == 0; } inline int operator != (const dstring &_str) { // Case insensitive return dstring::s_stricmp(data, (char*)_str.c_str()) != 0; } inline int operator > (const dstring &_str) { // Case insensitive return dstring::s_stricmp(data, (char*)_str.c_str()) > 0; } inline int operator >= (const dstring &_str) { // Case insensitive return dstring::s_stricmp(data, (char*)_str.c_str()) > 0; } inline int operator < (const dstring &_str) { // Case insensitive return dstring::s_stricmp(data, (char*)_str.c_str()) < 0; } inline int operator <= (const dstring &_str) { // Case insensitive return dstring::s_stricmp(data, (char*)_str.c_str()) <= 0; } // --------------------------------------- // Inlined standard string (c) functions // --------------------------------------- static u32 s_strlen(const char *_txt) { return strlen(_txt); } static char *s_strncpy(char *_dest, char *_source, u32 _len) { strncpy(_dest, _source, _len); return _dest; } static int s_stricmp(char *_txt1, char *_txt2) { // Depending on the compiler and platform if (!(_txt1 || _txt2)) return 0; else if (_txt1 && !_txt2) return 1; else if (!_txt1 && _txt2) return -1; else return strcasecmp(_txt1, _txt2); } static int s_strcmp(char *_txt1, char *_txt2) { // Depending on the compiler and platform if (!(_txt1 || _txt2)) return 0; else if (_txt1 && !_txt2) return 1; else if (!_txt1 && _txt2) return -1; else return strcmp(_txt1, _txt2); } // --------------------------------------- // Friends for output and input friend std::ostream & operator<<( std::ostream & out, const dstring &_str) { if (_str.length()) return out << (const char*)_str.c_str(); else return out; } friend std::istream & operator>>(std::istream & _in, dstring &_str) { char cbuf[dstring::INPUT_MAXLEN]; _in >> cbuf; _str = cbuf; return _in; } friend std::istream & getline(std::istream &_in, dstring & _str) { char cbuf[dstring::INPUT_MAXLEN]; _in.getline(cbuf, dstring::INPUT_MAXLEN); _str = cbuf; return _in; } friend std::fstream & operator>>(std::fstream & _in, dstring &_str) { char cbuf[dstring::INPUT_MAXLEN]; _in.width(dstring::INPUT_MAXLEN); _in >> cbuf; _str = cbuf; return _in; } friend std::fstream &getline(std::fstream &_in, dstring & _str) { char cbuf[dstring::INPUT_MAXLEN]; _in.getline(cbuf, dstring::INPUT_MAXLEN); _str = cbuf; return _in; } friend dstring operator + (const dstring &_str1, const dstring &_str2) { dstring tempstr; u32 len; len = MAXL(_str1.length() + _str2.length()); if (!len) return tempstr; tempstr.allocateData(len+1); tempstr.data_length = len+1; if (_str1.length()) dstring::s_strncpy(tempstr.data, (char*)_str1.c_str(), MAXL(_str1.length())); if ((int)(len - _str1.length()) > 0) dstring::s_strncpy(tempstr.data + _str1.length(), (char*)_str2.c_str(), len - _str1.length()); tempstr.data[tempstr.data_length] = '\0'; return tempstr; } friend dstring operator + (const dstring &_str, const char *_txt) { dstring tempstr(_txt); return _str + tempstr; } friend dstring operator + (const dstring &_str, const char _ch) { dstring tempstr(_ch); return _str + tempstr; } }; // class dstring #endif