/************************************************************************* * * HTCd - Copyright (C) 1998-2006 Henrik Rydberg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MSTRINGH #define MSTRINGH #include #include const int ms_mincaps=32; class mstring : public sref { public: mstring(); explicit mstring(int n); mstring(int n,char c); mstring(const char* s); mstring(const char* s,int n); mstring(const sref& s); mstring(const mstring& s); ~mstring(); //////////////////////////////////////////////////////////////// const char* c_str() const { return map; } int capacity() const { return caps; } void clear() { map[dim=0]=0; } int own(const sref& s) const { int p=s.data()-map; return p>=0&&p=caps) reserve(dim+1); map[dim++]=c; map[dim]=0; } void put(const sref& s) { reserve(dim+s.size()); memcpy(map+dim,s.data(),s.size()); map[dim+=s.size()]=0; } mstring& append(int sdim,char c) { reserve(dim+sdim); memset(map+dim,c,sdim); map[dim+=sdim]=0; return *this; } mstring& append(const sref& s) { reserve(dim+s.size()); memmove(map+dim,s.data(),s.size()); map[dim+=s.size()]=0; return *this; } int insert(int pos,int n) { if(pos<0||pos>dim) return 0; if(n) { reserve(dim+n); memmove(map+pos+n,map+pos,dim-pos); map[dim+=n]=0; } return 1; } mstring& insert(int pos,int sdim,char c) { if(insert(pos,sdim)) memset(map+pos,c,sdim); return *this; } mstring& insert(int pos,const sref& s) { if(insert(pos,s.size())) memcpy(map+pos,s.data(),s.size()); return *this; } mstring& replace(int pos,int n,int sdim,char c) { if(insert(pos+n,sdim-n)) memset(map+pos,c,sdim); return *this; } mstring& replace(int pos,int n,const sref& s) { if(insert(pos+n,s.size()-n)) memcpy(map+pos,s.data(),s.size()); return *this; } //////////////////////////////////////////////////////////////// void erase(int pos,int n=-1); void reserve(int n); void resize(int n) { reserve(n); map[dim=n]=0; } //////////////////////////////////////////////////////////////// mstring& operator=(const mstring& s) { assign(s); return *this; } mstring& operator=(const sref& s) { assign(s); return *this; } mstring& operator=(char c) { assign(1,c); return *this; } mstring& operator+=(const sref& s) { return append(s); } mstring& operator+=(char c) { return append(1,c); } //////////////////////////////////////////////////////////////// int load(const mstring& path); //////////////////////////////////////////////////////////////// // NOTE: if you apply convert to %s or any unbound data, // you're in trouble. Internal buffer is sref_t. mstring& convert(const char* format,...); protected: static uniheap heap; private: int caps; }; /////////////////////////////////////////////////////////////////// inline void swap(mstring& a,mstring& b) { char buf[sizeof(mstring)]; memcpy(buf,&a,sizeof(mstring)); memcpy(&a,&b,sizeof(mstring)); memcpy(&b,buf,sizeof(mstring)); } /////////////////////////////////////////////////////////////////// inline mstring operator+(const sref& a,const sref& b) { return mstring(a).append(b); } inline mstring operator+(const sref& a,char b) { return mstring(a).append(1,b); } inline mstring operator+(char a,const sref& b) { return mstring(1,a).append(b); } /////////////////////////////////////////////////////////////////// inline mstring btoa(int b) { return mstring(1,b?'1':'0'); } inline mstring itoa(int i) { sref_t buf; return mstring(itoa(buf,i)); } inline mstring ftoa(double f) { sref_t buf; return mstring(ftoa(buf,f)); } /////////////////////////////////////////////////////////////////// const mstring ms_empty; /////////////////////////////////////////////////////////////////// struct swrite : public cvt_stream { mstring* mp; int appc(char c); int apps(const sref& s); swrite() : mp(0) {} swrite(mstring& m) : mp(&m) { mp->clear(); } swrite& operator()(mstring& m) { (mp=&m)->clear(); return *this; } swrite& hold(mstring& m) { mp=&m; return *this; } }; /////////////////////////////////////////////////////////////////// class mswrite : public cvt_stream { public: mstring m; int appc(char c); int apps(const sref& s); const mstring& str() const { return m; } // compatibility void clear() { m.clear(); } mswrite() : m() {} private: mswrite(mstring&) {} // make no mistakes due to similarity with swrite }; /////////////////////////////////////////////////////////////////// struct merror_t : public cvt_stream { int num; mstring desc; int appc(char c); int apps(const sref& s); merror_t(int n) : num(n),desc() {} }; #define THROW(x) { merror_t merr(0); merr<