/****************************************************************************
* ResortMUD Version 5.0 was mainly programmed by Ntanel, Garinan, Josh, *
* Badastaz, Digifuzz, Senir, Kratas, Scion, Shogar and Tagith. *
* ------------------------------------------------------------------------ *
* Copyright (C) 1996 - 2001 Haslage Net Electronics: MudWorld of Lorain, *
* Ohio. ALL RIGHTS RESERVED See /doc/RMLicense.txt for more details. *
****************************************************************************/
#include <stdarg.h>
#include <string.h>
#include "mud.h"
/*
Implementation of a dynamically expanding buffer.
Inspired by Russ Taylor's <rtaylor@efn.org> buffers in ROM 2.4b2.
The buffer is primarily used for null-terminated character strings.
A buffer is allocated with buffer_new, written to using buffer_strcat,
cleared (if needed) using buffer_clear and free'ed using buffer_free.
If BUFFER_DEBUG is defined, the buffer_strcat call is defined as having
2 extra parameters, __LINE__ and __FILE__. These are then saved
to the bug file if an overflow occurs.
Erwin S. Andreasen <erwin@pip.dknet.dk>
*/
void bugf( char *fmt, ... ) __attribute__ ( ( format( printf, 1, 2 ) ) );
#if 0
#define EMEM_SIZE -1 /* find_mem_size returns this when block is too large */
#endif
#define NUL '\0'
#if 0
#define MAX_MEM_LIST 11
const int rgSizeList[MAX_MEM_LIST] = {
16, 32, 64, 128, 256, 1024, 2048, 4096, 8192, 16384, 32768 - 64
};
/* Find in rgSizeList a memory size at least this long */
int find_mem_size( int min_size )
{
int i;
for( i = 0; i < MAX_MEM_LIST; i++ )
if( rgSizeList[i] >= min_size )
return rgSizeList[i];
/*
* min_size is bigger than biggest allowable size!
*/
return EMEM_SIZE;
}
#endif
/* Create a new buffer, of at least size bytes */
#ifndef BUFFER_DEBUG /* no debugging */
BUFFER *__buffer_new( int min_size )
#else /* debugging - expect filename and line */
BUFFER *__buffer_new( int min_size, const char *file, unsigned line )
#endif
{
int size;
BUFFER *buffer;
/*
* char buf[200];
*//*
* for the bug line
*/
/*
size = find_mem_size (min_size);
*/
size = min_size;
#if 0
if( size == EMEM_SIZE )
{
#ifdef BUFFER_DEBUG
sprintf( buf, "Buffer size too big: %d bytes (%s:%u).", min_size, file, line );
#else
sprintf( buf, "Buffer size too big: %d bytes.", min_size );
#endif
bug( buf, 0 );
abort( );
}
#endif
CREATE( buffer, BUFFER, 1 );
buffer->size = size;
CREATE( buffer->data, char, size );
buffer->overflowed = FALSE;
buffer->len = 0;
return buffer;
} /* __buf_new */
/* Add a string to a buffer. Expand if necessary */
#ifndef BUFFER_DEBUG /* no debugging */
void __buffer_strcat( BUFFER * buffer, const char *text )
#else /* debugging - expect filename and line */
void __buffer_strcat( BUFFER * buffer, const char *text, const char *file, unsigned line )
#endif
{
int new_size;
int text_len;
char *new_data;
/* char buf[200]; */
if( buffer->overflowed ) /* Do not attempt to add anymore if buffer is already overflowed */
return;
if( !text ) /* Adding NULL string ? */
return;
text_len = strlen( text );
if( text_len == 0 ) /* Adding empty string ? */
return;
/*
* Will the combined len of the added text and the current text exceed our buffer?
*/
if( ( text_len + buffer->len + 1 ) > buffer->size ) /* expand? */
{
// new_size = find_mem_size (buffer->size + text_len + 1);
new_size = buffer->size + text_len + 1;
#if 0
if( new_size == EMEM_SIZE ) /* New size too big ? */
{
#ifdef BUFFER_DEBUG
sprintf( buf, "Buffer overflow, wanted %d bytes (%s:%u).", text_len + buffer->len, file, line );
#else
sprintf( buf, "Buffer overflow, wanted %d bytes.", text_len + buffer->len );
#endif
bug( buf, 0 );
buffer->overflowed = TRUE;
return;
}
#endif
/*
* Allocate the new buffer
*/
CREATE( new_data, char, new_size );
/*
* Copy the current buffer to the new buffer
*/
memcpy( new_data, buffer->data, buffer->len );
DISPOSE( buffer->data );
buffer->data = new_data;
buffer->size = new_size;
} /* if */
memcpy( buffer->data + buffer->len, text, text_len ); /* Start copying */
buffer->len += text_len; /* Adjust length */
buffer->data[buffer->len] = NUL; /* Null-terminate at new end */
} /* __buf_strcat */
/* Free a buffer */
void buffer_free( BUFFER * buffer )
{
/*
* Free data
*/
DISPOSE( buffer->data );
/*
* Free buffer
*/
DISPOSE( buffer );
}
/*
* Clear a buffer's contents...
* It now clears it completely and resets the buffer to 200
*/
void buffer_clear( BUFFER * buffer )
{
buffer->overflowed = FALSE;
DISPOSE( buffer->data );
CREATE( buffer->data, char, 200 );
buffer->size = 200;
buffer->len = 0;
}
/* print stuff, append to buffer. safe. */
int bprintf( BUFFER * buffer, char *fmt, ... )
{
char buf[MAX_STRING_LENGTH];
va_list va;
int res;
va_start( va, fmt );
res = vsnprintf( buf, MAX_STRING_LENGTH, fmt, va );
va_end( va );
if( res >= MAX_STRING_LENGTH - 1 )
{
buf[0] = NUL;
bugf( "Overflow when printing string %s", fmt );
}
else
buffer_strcat( buffer, buf );
return res;
}
void bugf( char *fmt, ... )
{
char buf[MAX_STRING_LENGTH];
va_list args;
va_start( args, fmt );
vsnprintf( buf, MAX_STRING_LENGTH, fmt, args );
va_end( args );
bug( buf, 0 );
}