/*--------------------------------------------------------------------*/ /* U s t r . c p p */ /* */ /* Implementation of "Str" class */ /*--------------------------------------------------------------------*/ /* Copyright (c) 2002 by Fyodor Ustinov */ /* FIDONet 2:5020/79 */ /* */ /* All rights reserved. */ /*--------------------------------------------------------------------*/ // #include #include #include #include "ustr.hpp" #define CHUNK_SIZE 512 /*--------------------------------------------------------------------*/ /* Constructors & destructor */ /*--------------------------------------------------------------------*/ Str::Str() { MemLen = 0; Len = 0; Ptr = NULL; _Base = 10; alloc(1); } Str::Str(char const *Nstr) { MemLen = 0; _Base = 10; Ptr = NULL; if (Nstr == NULL) { Len = 0; alloc(1); } else { Len = strlen(Nstr); alloc(Len+1); strncpy(Ptr,Nstr,Len); } } Str::Str(const Str &s) { Len = s.Len; _Base = 10; MemLen = 0; Ptr = NULL; alloc(Len+1); strncpy(Ptr,s.Ptr,Len+1); } Str & Str::operator=(const Str &s) { if (&s != this) { free(); alloc(s.Len+1); Len = s.Len; memcpy(Ptr,s.Ptr,Len); } return *this; } Str & Str::operator=(const char *s) { free(); alloc(1); if (s == NULL) return *this; if (*s == '\0') return *this; Len = strlen(s); alloc(Len+1); strncpy(Ptr,s,Len); return *this; } Str & Str::operator=(const char c) { free(); alloc(1); *Ptr = c; Len = 1; return *this; } Str::~Str() { free(); } /*--------------------------------------------------------------------*/ /* Allocate and free memory */ /*--------------------------------------------------------------------*/ void Str::alloc(size_t sz) { char *tmt; size_t rsz; if (sz == 0) throw "Str: Attempt to allocate 0 bytes"; // cout << "MemLen == " << MemLen << " sz == " << sz << "\n"; if (MemLen != 0 && sz < MemLen && sz >= MemLen-CHUNK_SIZE) return; tmt = Ptr; rsz = (((sz / CHUNK_SIZE) + 1) * CHUNK_SIZE) + 1; Ptr = (char *) malloc(rsz); if (Ptr == NULL) throw "Str: Unable to allocate memory"; if (tmt != NULL) { if (rsz > MemLen) { memmove(Ptr,tmt,MemLen); } else { memmove(Ptr,tmt,rsz); Len = rsz-1; } ::free(tmt); } MemLen = rsz; // cout << "at end MemLen == " << MemLen << " Len == " << Len << "\n"; } void Str::free(void) { if (Ptr != NULL) { ::free(Ptr); Ptr = NULL; Len = 0; MemLen = 0; } } /*--------------------------------------------------------------------*/ /* Return pointers to c string */ /*--------------------------------------------------------------------*/ Str::operator char const *(){ Ptr[Len] = '\0'; return Ptr; } Str::operator char const *() const { Ptr[Len] = '\0'; return Ptr; } Str::operator char*() { Ptr[Len] = '\0'; return Ptr; } /*--------------------------------------------------------------------*/ /* Add to string */ /*--------------------------------------------------------------------*/ void Str::AddChar(char const c) { alloc(Len + 1); Ptr[Len++] = c; } static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; void Str::ParseDig(signed long n) { int i; char s[128]; if (n < 0L) { n = -n; AddChar('-'); } i = 0; do { s[i++] = digits[(int)(n % _Base)]; } while (n /= _Base); do { AddChar(s[--i]); } while (i != 0); } void Str::ParseDig(unsigned long n) { int i; char s[128]; i = 0; do { s[i++] = digits[(int)(n % _Base)]; } while (n /= _Base); do { i--; AddChar(s[i]); } while (i != 0); } Str & Str::operator += (Str const &s) { alloc(Len + s.Len + 1); memcpy(Ptr+Len,s.Ptr,s.Len); Len += s.Len; return *this; } Str & Str::operator += (char const *s) { int slen; if (s == NULL) return *this; if (*s == '\0') return *this; slen = strlen(s); alloc(Len + slen + 1); strncpy(Ptr+Len,s,slen); Len += slen; return *this; } /*--------------------------------------------------------------------*/ /* Substrings */ /*--------------------------------------------------------------------*/ Str Str::operator () ( size_t _p, size_t _l) const { Str s; if (_p == 0 || _p > Len || (_p + _l - 1) > Len) throw "Diapason out of range"; if (_l == 0) { s.Len = Len - _p + 1; } else { s.Len = _l; } if (s.Len != 0) { s.alloc(s.Len + 1); memcpy(s.Ptr,Ptr+_p-1,s.Len); } return s; } /*--------------------------------------------------------------------*/ /* Comparasion */ /*--------------------------------------------------------------------*/ int operator == (Str const &s1, Str const &s2) { if (s1.Len != s2.Len) return 0; if (memcmp(s1.Ptr,s2.Ptr,s1.Len) != 0) return 0; return -1; } int operator == (Str const &s1, char const *s2) { if (s2 == NULL) return 0; if (s1.Len != strlen(s2)) return 0; if (memcmp(s1.Ptr,s2,s1.Len) != 0) return 0; return -1; } int operator == (char const *s2, Str const &s1) { if (s2 == NULL) return 0; if (s1.Len != strlen(s2)) return 0; if (memcmp(s1.Ptr,s2,s1.Len) != 0) return 0; return -1; } /*--------------------------------------------------------------------*/ /* Characters */ /*--------------------------------------------------------------------*/ char & Str::operator [] (size_t _p) { if (_p == 0) throw "Index is 0"; if (_p > Len) throw "Index out of range"; return *(Ptr+_p-1); } char const & Str::operator [] (size_t _p) const { if (Ptr == NULL) throw "Str is NULL"; if (_p == 0) throw "Index is 0"; if (_p > Len) throw "Index out of range"; return *(Ptr+_p-1); } Str &Str::Trim(char const *Del) { char *tmt; if (Del == NULL) return *this; while (Len != 0 && strchr(Del,Ptr[Len-1]) != NULL) Len--; if (Len == 0) return *this; for (tmt = Ptr; strchr(Del,*tmt) != NULL && Len != 0; Len--,tmt++); if (Len == 0) return *this; memmove(Ptr,tmt,Len); return *this; } size_t Str::Pos(char const *s) { char *tmt; if (s == NULL) return 0; Ptr[Len] = '\0'; if ((tmt = strstr(Ptr,s)) == NULL) return 0; return (tmt-Ptr+1); } Str &Str::Cut(size_t _p, size_t _l) { if (_p == 0 || _p > Len || (_p + _l - 1) > Len) throw "Diapason out of range"; if (_l == 0) { Len = _p - 1; } else { Len -= _l; memmove(Ptr+_p-1,Ptr+_p+_l-1,Len-_p+1); } return *this; } Str &Str::Upper(void) { for (unsigned int i = 0; i < Len; i++) { Ptr[i] = toupper(Ptr[i]); } return *this; } /*--------------------------------------------------------------------*/ /* In/Out */ /*--------------------------------------------------------------------*/ ostream & operator << (ostream &io, Str const &s) { if (s.Len != 0) io.write(s.Ptr,s.Len); return io; } /*--------------------------------------------------------------------*/ #if 0 void main(void) { try { Str a; Str b("123456"); b = b; a = b; cout << b << "\n"; b[2] = 'c'; a += b; a += " This is a test!"; cout << b << "\n"; cout << a << "\n"; a = NULL; cout << a << "\n"; a = "Test"; cout << a << "\n"; a.Base(16); a += 'c'; a += 'd'; a += ' '; a += 255; a += ' '; a += -255; a += ' '; a += 255L; a += ' '; a += -255L; cout << a << "\n"; for (int i = 1; i < 4; i++) { cout << "i == " << i << " c == " << b[i] << "\n"; } cout << "5" << "\n"; cout <<"->"<< b(5,2) << "<-\n"; } catch (char *s) { cout << "\nException: " << s << "\n"; } catch (...) { cout << "\nException: " << "\n"; } } #endif