waveview/ttg/dbuf.c

408 lines
7.6 KiB
C

/*
* dbuf.c - dynamic buffer functions
*
* include LICENSE
*/
#define _GNU_SOURCE /* for vasprintf */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <dbuf.h>
#ifdef TRACE_MEM
#include <tracemem.h>
#endif
/**
* \brief Allocates memory for a new DBuf object.
* size : the initial size of the buffer
* buffer : if not null, an external buffer that can be worked as a dbuf
* except reallocation. (Use for read only, for example)
*/
DBuf *
dbuf_new( int size, char *ext_buf )
{
DBuf *dbuf;
dbuf = app_new0(DBuf, 1 );
dbuf_construct( dbuf, size, ext_buf );
app_class_overload_destroy( (AppClass *) dbuf, dbuf_destroy );
return dbuf;
}
/** \brief Constructor for the DBuf object. */
void dbuf_construct( DBuf *dbuf, int size, char *ext_buf )
{
app_class_construct( (AppClass *) dbuf );
if (size == 0 ){
size = BUFSIZ;
}
if ( ext_buf ) {
dbuf->ext_buf = dbuf->s = ext_buf;
dbuf->len = size;
} else {
size = app_power_of_2(size);
dbuf->s = app_new(char, size );
*(dbuf->s) = 0;
}
dbuf->size = size ;
}
/** \brief Destructor for the DBuf object. */
void dbuf_destroy( void *dbuf)
{
DBuf *this = (DBuf *) dbuf;
if ( dbuf == NULL ) {
return;
}
if ( ! this->ext_buf ){
app_free(this->s);
}
app_class_destroy( dbuf );
}
void dbuf_set_fill_cb( DBuf *dbuf, Dbuf_Fill_FP fill_func, AppClass *caller)
{
dbuf->fill_func = fill_func;
dbuf->caller = caller;
}
void dbuf_renew( DBuf *dbuf, int newsize)
{
if ( dbuf->ext_buf ){
msg_fatal("external buffer to allowed to reallocate");
}
dbuf->size = app_power_of_2(newsize + 1);
dbuf->nRenew++;
dbuf->s = app_renew( char, dbuf->s , dbuf->size);
}
void dbuf_set_flags( DBuf *dest, int flags)
{
dest->flags = flags ;
}
int dbuf_is_empty( DBuf *dest)
{
if ( dest->pos < dest->len ){
return 0 ;
}
return 1 ;
}
int dbuf_get_available( DBuf *dest)
{
return dest->len - dest->pos;
}
void dbuf_set_pos( DBuf *dest, int pos)
{
dest->pos = pos ;
}
int dbuf_get_size( DBuf *dest)
{
return dest->size ;
}
int dbuf_get_pos( DBuf *dest)
{
return dest->pos ;
}
void dbuf_set_len( DBuf *dest, int len)
{
dest->len = len ;
if ( dest->len > dest->size - 1) {
dbuf_renew( dest, dest->len );
}
char *p = dest->s + dest->len ;
*p = 0;
}
int dbuf_get_len( DBuf *dest)
{
return dest->len ;
}
void dbuf_inc_len( DBuf *dest)
{
dbuf_set_len( dest, dest->len + 1);
}
void dbuf_clear( DBuf *dest)
{
dest->pos = 0 ;
dest->len = 0 ;
dest->lineno = 0;
*(dest->s) = 0;
}
/*
* concatenate n bytes from (src->s + pos) to dest
*/
void dbuf_ncat( DBuf *dest, DBuf *src, int slen)
{
int len = dest->len ;
dest->len += slen ;
if ( dest->len >= dest->size - 1) {
dbuf_renew( dest, dest->len );
}
memmove(dest->s + len, src->s + src->pos, slen );
*(dest->s + dest->len) = 0;
src->pos += slen;
}
/*
* Warning : src start at src->s + src->pos and not at start of buffer
*/
void dbuf_cat( DBuf *dest, DBuf *src)
{
int slen = src->len - src->pos;
dbuf_ncat( dest, src, slen);
}
void dbuf_ncopy( DBuf *dest, DBuf *src, int slen)
{
dest->pos = 0 ;
dest->len = 0 ;
dbuf_ncat( dest, src, slen);
}
void dbuf_copy( DBuf *dest, DBuf *src)
{
dbuf_ncopy( dest, src, src->len);
}
void dbuf_strncpy( DBuf *dest, char *src, int slen)
{
dest->pos = 0 ;
dest->len = slen ;
if ( dest->len >= dest->size - 1) {
dbuf_renew( dest, dest->len );
}
memmove(dest->s, src, slen);
*(dest->s + dest->len) = 0;
}
void dbuf_strcpy( DBuf *dest, char *src)
{
dbuf_strncpy( dest, src, app_strlen(src));
}
void dbuf_strncat( DBuf *dest, char *src, int slen)
{
int dlen = dest->len ;
dest->len += slen ;
if ( dest->len >= dest->size - 1) {
dbuf_renew( dest, dest->len );
}
memmove(dest->s + dlen, src, slen );
*(dest->s + dest->len) = 0;
}
void dbuf_strcat( DBuf *dest, char *src)
{
dbuf_strncat( dest, src, app_strlen(src));
}
/*
* concatanate all arguments of a NULL terminated list
*/
void dbuf_concat( DBuf *dest, ...)
{
va_list args;
const char *p;
if ((p = ( const char *) dest) == NULL) {
return ;
}
va_start (args, dest);
p = va_arg (args, const char *);
while (p != NULL) {
dbuf_strcat( dest, (char *) p);
p = va_arg (args, const char *);
}
va_end (args);
}
/*
* return a pointer on the next char in buffer
* instead of the char itself
*/
char *dbuf_next_char(DBuf *sbuf)
{
if (sbuf->pos >= sbuf->len) {
if ( sbuf->fill_func == NULL) {
return NULL;
} else {
int lineno = sbuf->lineno;
dbuf_clear(sbuf);
if ( sbuf->fill_func(sbuf->caller, (AppClass *) sbuf) == NULL ) {
return NULL;
}
sbuf->lineno = lineno;
}
}
char *p = sbuf->s + sbuf->pos++;
if (*p == '\n') {
sbuf->lineno++;
}
return p;
}
/*
* return a single char from buffer
* or -1 if no more chars.
*/
int dbuf_get_char(DBuf *sbuf)
{
char *p = dbuf_next_char(sbuf);
if ( ! p ){
return -1;
}
return (unsigned char) *p;
}
/*
* return a duped binary string from dbuf of len chars
* string may countain 0.
* Caller must free the returned ptr.
*/
char *dbuf_get_dupchars(DBuf *sbuf, int len)
{
if (sbuf->pos + len >= sbuf->len) {
return NULL;
}
char *ptr = app_new0( char, len + 1) ;
memmove(ptr, sbuf->s + sbuf->pos, len);
sbuf->pos += len;
return ptr;
}
char *dbuf_get_line(DBuf *dest, DBuf *src)
{
char *p;
int c = 0; /* compiler warning */
int lastc = 0;
dbuf_clear(dest);
while ( (p = dbuf_next_char(src)) ) {
c = *p;
if ( c == '\n' && lastc == '\\' && (dest->flags & DB_JOIN_LINES) ) {
dbuf_unput_char( dest ); /* remove lastc */
c = ' ';
}
if (c == '\n' || c == 0 ) {
break;
}
if ( c == '\r' && (dest->flags & DB_STRIP_CR) ) {
continue;
}
dbuf_put_char( dest, c);
lastc = c;
}
if ( p == NULL && dest->len == 0) {
return NULL;
}
if ( dest->flags & DB_KEEP_LF) {
dbuf_put_char( dest, c);
}
return dest->s;
}
/*
* undo a get_char
*/
int dbuf_unget_char(DBuf *sbuf)
{
if (--sbuf->pos < 0) {
return -1;
}
char c = sbuf->s[sbuf->pos];
return (unsigned char) c;
}
/*
* undo a put_char
*/
int dbuf_unput_char(DBuf *sbuf)
{
if (--sbuf->len < 0) {
return -1;
}
char c = sbuf->s[sbuf->len];
sbuf->s[sbuf->len] = 0;
return (unsigned char) c;
}
void dbuf_put_char( DBuf *dest, char c)
{
if ( dest->len >= dest->size - 2) {
dbuf_renew( dest, dest->len + 1 );
}
char *p = dest->s + dest->len++ ;
*p++ = c;
*p = 0;
}
/*
* dbuf_printf is like sprintf but to dbuf ; concatatenate the result
*/
void dbuf_vprintf( DBuf *dest, const char *format, va_list args )
{
char *buffer = NULL;
/* vasprintf returns malloc-allocated memory */
int len = vasprintf(&buffer, format, args);
if ( len < 0 ){
msg_error("vasprintf returned -1.");
return;
}
dbuf_strncat(dest, buffer, len);
app_free (buffer);
}
void dbuf_printf( DBuf *dest, const char *format, ...)
{
va_list args;
va_start (args, format);
dbuf_vprintf( dest, format, args );
va_end (args);
}
/*
* move remaining data at beginning of buffer
*/
void dbuf_move_beg( DBuf *dbuf)
{
if ( dbuf->pos && dbuf->pos != dbuf->len ){
dbuf->len -= dbuf->pos;
memmove(dbuf->s, dbuf->s + dbuf->pos, dbuf->len );
dbuf->pos = 0;
}
}
int dbuf_get_lineno( DBuf *dbuf)
{
return dbuf->lineno;
}