//====================================================================== // Copyright (C) 2002 Daniel Heck // // 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., // 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. //====================================================================== #include "buffer.hh" #include using namespace px; using namespace std; Buffer::Buffer(size_t startlen) : buf(new char[startlen]) , rpos(buf), wpos(buf) , sz(0) , capacity(startlen) , iostate(GOODBIT) {} char* Buffer::get_wspace(size_t len) { size_t newcap = capacity; while (wpos + len > buf + newcap) newcap *= 2; if (newcap != capacity) { char* newbuf = new char[newcap]; memcpy(newbuf, buf, sz); capacity = newcap; wpos = (wpos - buf) + newbuf; rpos = (rpos - buf) + newbuf; delete[] buf; buf = newbuf; } char* data = wpos; wpos += len; sz += len; return data; } char* Buffer::get_rspace(size_t len) { if (!good() || rpos + len > buf + sz) { iostate = State(iostate | FAILBIT | EOFBIT); return 0; } char* data = rpos; rpos += len; return data; } int Buffer::read() { if (good() && rpos < buf+sz) return *rpos++; else return -1; } Buffer& Buffer::write(char c) { char* ptr = get_wspace(1); *ptr = c; return *this; } Buffer& Buffer::read(void* dest, size_t len) { if (!good() || (rpos + len > buf + sz)) { iostate = State(iostate | EOFBIT | FAILBIT); } else { memcpy(dest, rpos, len); rpos += len; } return *this; } Buffer& Buffer::write(const void* src, size_t len) { if (char* dest = get_wspace(len)) memcpy(dest, src, len); return *this; } int Buffer::seekr(long pos, SeekMode whence) { size_t offs = 0; switch (whence) { case SET: offs = pos; break; case CUR: offs = (rpos - buf) + pos; break; case END: offs = sz + pos; break; } if (offs < 0 || offs > sz) return -1; rpos = buf + offs; return 0; } int Buffer::seekw(long pos, SeekMode whence) { size_t offs = 0; switch (whence) { case SET: offs = pos; break; case CUR: offs = (wpos - buf) + pos; break; case END: offs = sz + pos; break; } if (offs < 0 || offs > sz) return -1; wpos = buf + offs; return 0; } Buffer::operator void*() const { return (iostate & FAILBIT) ? 0 : reinterpret_cast(1); } bool Buffer::operator!() const { return (iostate & FAILBIT) ? true : false; } //---------------------------------------- // Buffer helper routines. //---------------------------------------- /* ** === Read and write bytes === */ Buffer& px::read(Buffer& buf, Uint8& byte) { int a = buf.read(); if (a != -1) byte = a; return buf; } Buffer& px::write(Buffer& buf, Uint8 byte) { buf.write(byte); return buf; } /* ** === Read and write words === */ Buffer& px::read(Buffer& buf, Uint16& word) { Uint8* ptr = (Uint8*) buf.get_rspace(2); if (ptr != 0) word = ptr[0] + (ptr[1] << 8); return buf; } Buffer& px::write(Buffer& buf, Uint16 word) { Uint8* ptr = (Uint8*) buf.get_wspace(2); ptr[0] = word & 0xff; ptr[1] = (word >> 8) & 0xff; return buf; } /* ** === Read and write dwords === */ Buffer& px::read(Buffer& buf, Uint32& dword) { Uint8* ptr = (Uint8*) buf.get_rspace(4); if (ptr != 0) { dword = ptr[0]; dword |= (ptr[1] << 8); dword |= (ptr[2] << 16); dword |= (ptr[3] << 24); } return buf; } Buffer& px::write(Buffer& buf, Uint32 dword) { Uint8* ptr = (Uint8*) buf.get_wspace(4); ptr[0] = dword & 0xff; ptr[1] = (dword >> 8) & 0xff; ptr[2] = (dword >> 16) & 0xff; ptr[3] = (dword >> 24) & 0xff; return buf; } /* ** === Read and write doubles === */ Buffer& px::read(Buffer& buf, double& dvar) { Uint32 a; if (buf >> a) dvar = static_cast(Sint32(a)) / 2048; return buf; } Buffer& px::write(Buffer& buf, double dvar) { Sint32 a = static_cast (dvar * 2048); write(buf, Uint32(a)); return buf; } /* ** === Read and write another buffer === */ Buffer& px::read(Buffer& srcbuf, Buffer& destbuf, int len) { if (&srcbuf != &destbuf) { char* dest = destbuf.get_wspace(len); char* src = srcbuf.get_rspace(len); if (src != 0) memcpy(dest, src, len); } return srcbuf; } Buffer& px::write(Buffer& buf, const Buffer& databuf) { if (&buf != &databuf) { buf.write(databuf.data(), databuf.size()); } return buf; } /* ** === Read and write strings === */ Buffer& px::read(Buffer& buf, string& str) { Uint16 size; if (buf >> size) { char* ptr = buf.get_rspace(size); if (ptr != 0) str.assign(ptr, ptr+size); } return buf; } Buffer& px::write(Buffer& buf, const string& str) { Uint16 size = str.size(); buf << size; buf.write(str.c_str(), size); return buf; } /* ** Read and write from and to streams */ ostream& px::operator<<(ostream& os, const Buffer& buf) { os.write(buf.data(), buf.size()); return os; } istream& px::operator>>(istream& is, Buffer& buf) { buf.clear(); char tmp[2048]; while (is.read(tmp, sizeof tmp)) { buf.write(tmp, sizeof tmp); } buf.write(tmp, is.gcount()); return is; }