modules/up/src/Core/util/Buffer.cc
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- mymalloc
- myfree
- compress
- uncompress
- extend
- append
- appendf
- append
- insert
- flush
- makeString
- contains
- main
//
// $Id: Buffer.cc,v 1.1.1.1 2000/03/10 16:32:20 engin Exp $
//
// Author: Ramesh Govindan <govindan@isi.edu>
// Cengiz Alaettinoglu
// WeeSan Lee <wlee@isi.edu>
//
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <cstdio>
#include <cstdlib>
#include <cstdarg>
#include <cassert>
#include <iomanip.h>
#ifdef NEED_COMPRESSION
#include <zlib.h>
#include "util/Trail.hh"
#endif // NEED_COMPRESSION
#include "util/Buffer.hh"
#ifdef NEVER
int myallocCnt = 0;
static void *mymalloc(int opaque, int n, int sz) {
/* [<][>][^][v][top][bottom][index][help] */
myallocCnt++;
return malloc(n * sz);
}
static void myfree(int opaque, void *ptr) {
/* [<][>][^][v][top][bottom][index][help] */
printf("freeing\n");
myallocCnt--;
free(ptr);
}
#else
#define mymalloc 0
#define myfree 0
#endif // never
ostream &operator<<(ostream &os, const Buffer &b)
{
os << setw(b.getSize()) << b.getContents() << " (" << b.getSize() << ")";
return os;
}
Buffer*
Buffer::compress()
/* [<][>][^][v][top][bottom][index][help] */
{
#ifdef NEED_COMPRESSION
z_stream cp;
int err;
Buffer* nbuf;
// Need at most 1.1 * length for the decompressed buffer
nbuf = new Buffer((unsigned long) ((1.1 * size) + 12));
// Compress the incoming data
cp.zalloc = (alloc_func) mymalloc;
cp.zfree = (free_func) myfree;
cp.opaque = (voidpf) 0;
err = deflateInit(&cp, Z_BEST_COMPRESSION);
if (err != Z_OK) {
ERROR("zlib error %d while initializing stream\n", err);
delete nbuf;
return NULL;
}
cp.next_in = (unsigned char*) contents;
cp.avail_in = size;
cp.next_out = (unsigned char*) nbuf->contents;
cp.avail_out = nbuf->capacity;
err = deflate(&cp, Z_FINISH);
if (err != Z_STREAM_END) {
ERROR("zlib error %d when compressing data\n", err);
delete nbuf;
return NULL;
}
err = deflateEnd(&cp);
if (err != Z_OK) {
ERROR("zlib error %d when closing compression stream\n", err);
delete nbuf;
return NULL;
}
nbuf->size = cp.total_out;
return nbuf;
#else
return new Buffer(*this);
#endif
}
Buffer*
Buffer::uncompress()
/* [<][>][^][v][top][bottom][index][help] */
{
#ifdef NEED_COMPRESSION
z_stream decompress;
int error;
Buffer* nbuf;
unsigned int guess;
guess = size;
while (1) {
guess <<= 2;
nbuf = new Buffer(guess);
decompress.zalloc = (alloc_func) mymalloc;
decompress.zfree = (free_func) myfree;
decompress.opaque = (voidpf) 0;
decompress.next_in = (unsigned char*) contents;
decompress.avail_in = size;
decompress.next_out = (unsigned char*) nbuf->contents;
decompress.avail_out = nbuf->capacity;
error = inflateInit(&decompress);
if (error != Z_OK) {
ERROR("error number %d while initializing decompression stream\n",
error);
delete nbuf;
return NULL;
}
error = inflate(&decompress, Z_FINISH);
if (error == Z_STREAM_END) {
error = inflateEnd(&decompress);
if (error != Z_OK) {
ERROR("error number %d while closing decompression stream\n",
error);
delete nbuf;
return NULL;
}
nbuf->size = decompress.total_out;
return nbuf;
}
delete nbuf;
}
// Not Reached
#else
return new Buffer(*this);
#endif
}
void Buffer::extend(unsigned long minExtend) {
/* [<][>][^][v][top][bottom][index][help] */
assert(!callerAllocated); // !!!
capacity = (capacity + BufferExtendIncrement) >? (size + minExtend);
contents = (char *)realloc(contents, capacity);
}
void
Buffer::append(const char *buf, unsigned long sz)
/* [<][>][^][v][top][bottom][index][help] */
{
if (size + sz > capacity)
extend(sz);
memcpy(contents + size, buf, sz);
size += sz;
}
void Buffer::appendf(const char *format, ...) {
/* [<][>][^][v][top][bottom][index][help] */
if (size + BufferExtendIncrement / 2 > capacity)
extend();
va_list ap;
va_start(ap, format);
#ifdef HAVE_VSNPRINTF
(void) vsnprintf(contents + size, capacity - size, format, ap);
#else
(void) vsprintf(contents + size, format, ap);
#endif
va_end(ap);
size += strlen(contents + size);
}
void Buffer::append(Buffer &buf) {
/* [<][>][^][v][top][bottom][index][help] */
if (size + buf.size > capacity)
extend(buf.size);
memcpy(contents + size, buf.contents, buf.size);
size += buf.size;
}
void Buffer::insert(Buffer &buf, unsigned long atOffset = 0) {
/* [<][>][^][v][top][bottom][index][help] */
if (size + buf.size > capacity)
extend(buf.size);
memmove(contents + atOffset + buf.size,
contents + atOffset,
size - atOffset);
memcpy(contents + atOffset, buf.contents, buf.size);
size += buf.size;
}
void Buffer::flush(unsigned long sz, unsigned long atOffset) {
/* [<][>][^][v][top][bottom][index][help] */
if (sz == 0 || size == 0)
return;
assert(atOffset + sz <= size);
memcpy(contents + atOffset, contents + atOffset + sz, size - atOffset - sz);
size -= sz;
if (offset >= atOffset)
offset = (offset - sz) >? 0;
}
char *Buffer::makeString() const {
/* [<][>][^][v][top][bottom][index][help] */
char *str = (char *) malloc(size + 1);
strncpy(str, contents, size);
*(str + size) = 0;
return str;
}
bool Buffer::contains(const char *needle) { // search for needle in buffer
/* [<][>][^][v][top][bottom][index][help] */
if (capacity > size) {
*(contents + size) = 0;
return strstr(contents, needle);
}
char last = *(contents + size - 1);
*(contents + size - 1) = 0;
if (strstr(contents, needle)) {
*(contents + size - 1) = last;
return true;
}
char last2 = *(needle + strlen(needle) - 1);
if (last != last2) {
*(contents + size - 1) = last;
return false;
}
char *needle2 = strdup(needle);
*(needle2 + strlen(needle2) - 1) = 0;
if (strstr(contents + size - strlen(needle), needle2)) {
*(contents + size - 1) = last;
free(needle2);
return true;
}
*(contents + size - 1) = last;
free(needle2);
return false;
}
#ifdef BUFFER_MAIN
void main() {
/* [<][>][^][v][top][bottom][index][help] */
Buffer buf(4);
buf.append("foo", 3);
buf.contains("foo");
buf.contains("fo");
buf.contains("oo");
}
#endif // BUFFER_MAIN_DEBUG
//
// Copyright (c) 1994 by the University of Southern California.
// All rights reserved.
//
// Permission to use, copy, modify, and distribute this software and
// its documentation in source and binary forms for lawful
// non-commercial purposes and without fee is hereby granted, provided
// that the above copyright notice appear in all copies and that both
// the copyright notice and this permission notice appear in supporting
// documentation, and that any documentation, advertising materials,
// and other materials related to such distribution and use acknowledge
// that the software was developed by the University of Southern
// California and/or Information Sciences Institute.
// The name of the University of Southern California may not
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY REPRESENTATIONS
// ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. THIS SOFTWARE IS
// PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
// NON-INFRINGEMENT.
//
// IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
// SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
// TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH,
// THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// Questions concerning this software should be directed to
// info-ra@isi.edu.
//
// Author(s): Ramesh Govindan <govindan@isi.edu>