/* * Copyright (c) 1996 Gunther Schadow. All rights reserved. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #pragma implementation #include "Buffer.h" #include #include #include Buffer::Buffer() { _base = _poi = _end = _ppoi = NULL; _size = 0; } Buffer::Buffer(size_t s) { _size = ((s - 1) / chunksize + 1) * chunksize; _base = (char *)malloc(_size); _poi = _end = _ppoi = _base; } Buffer::Buffer(const char *b, size_t s) { _size = ((s - 1) / chunksize + 1) * chunksize; _base = (char *)malloc(_size); memcpy(_base, b, s); _poi = _base; _end = _ppoi = _poi + s; } Buffer::~Buffer() { free(_base); } void Buffer::put(const char *b, size_t s) { memcpy(ppoi(s), b, s); } inline void Buffer::lshrink() // shrink Buffer if pointer leaves lower chunks { int chtr = (_poi - _base) / chunksize; if(chtr > 0) { int delta = chtr * chunksize; memmove(_poi - delta, _poi, _ppoi - _poi); _poi = _poi - delta; _end = _end - delta; _ppoi = _ppoi - delta; /* don't resize memory, since we gain size at the end */ } } size_t Buffer::get(char *b, size_t max) // get at most max bytes // shrink buffer if pointer leaves a chunk { size_t n = max < len() ? max : len(); if(n == 0) return 0; else { memcpy(b, _poi, n); _poi += n; lshrink(); return n; } } size_t Buffer::discard(size_t s) // discard at most max bytes // shrink buffer if pointer leaves a chunk { size_t n = s < len() ? s : len(); if(n == 0) return 0; else { _poi += n; lshrink(); return n; } } inline void Buffer::hshrink() // shrink buffer if ppoi leaves higher chunk { int chtr = ( ( _base + _size ) - _ppoi ) / chunksize; if(chtr > 0) { _size = ( _size - chtr * chunksize ); char *nb = (char *)realloc(_base, _size); _ppoi = _ppoi + (nb - _base); _end = _end + (nb - _base); _poi = _poi + (nb - _base); _base = nb; } } void Buffer::trunc(char *pos) // discard all bytes after pos where pos >= end! // shrink buffer if ppoi leaves higher chunks { if(pos >= _end && pos < _ppoi) { _ppoi = pos; hshrink(); } } void Buffer::setend(char *pos) // set end pointer to a new pos >= old endp. { if(pos > _end && pos <= _ppoi) _end = pos; } char *Buffer::ppoi(size_t s) // return current ppoi with min s of following space and // increase the new ppoi by s { size_t ns = ( _ppoi + s - _base ); if(ns > _size) // buffer is too small { _size = ((ns - 1) / chunksize + 1) * chunksize; char *nb = (char *)realloc(_base, _size); _poi = _poi + ( nb - _base ); _end = _end + ( nb - _base ); _ppoi = _ppoi + ( nb - _base ); _base = nb; } char *old_ppoi = _ppoi; _ppoi += s; return old_ppoi; }