blob: 297c31655eb8787d8061392f5bd3c8b77eebbf1a [file] [log] [blame]
/*
* Copyright (c) 2005, 2006 by KoanLogic s.r.l. - All rights reserved.
*/
static const char rcsid[] =
"$Id: buf.c,v 1.1 2006/05/28 15:39:43 tat Exp $";
#ifdef HAVE_CONFIG_H
#include <wsman_config.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <u/libu.h>
#include <u/buf.h>
struct u_buf_s
{
char *data;
size_t size, len;
};
/**
* \defgroup string String
* \{
*/
/**
* \brief Enlarge the underlaying memory block of the given buffer
*
* Enlarge the buffer data block to (at least) \a size bytes.
*
* \param ubuf buffer object
* \param size requested size
*
* \return \c 0 on success, not zero on failure
*/
int u_buf_reserve(u_buf_t *ubuf, size_t size)
{
char *nbuf;
dbg_err_if(ubuf == NULL);
if(size <= ubuf->size)
return 0; /* nothing to do */
/* size plus 1 char to store a '\0' */
nbuf = u_realloc(ubuf->data, size+1);
dbg_err_if(nbuf == NULL);
/* buffer data will always be zero-terminated (but the len field will not
* count the last '\0') */
nbuf[size] = 0;
ubuf->data = (void*)nbuf;
ubuf->size = size;
return 0;
err:
return ~0;
}
/**
* \brief Append some data to the buffer
*
* Append \a data of size \a size to the given buffer. If needed the buffer
* will be enlarged.
*
* \param ubuf buffer object
* \param data the data block to append
* \param size size of \a data
*
* \return \c 0 on success, not zero on failure
*/
int u_buf_append(u_buf_t *ubuf, void *data, size_t size)
{
dbg_err_if(ubuf == NULL);
// dbg_err_if(data == NULL);
dbg_err_if(size == 0);
if(ubuf->size - ubuf->len < size)
{ /* buffer too small, need to resize */
dbg_err_if(u_buf_reserve(ubuf, ubuf->size + ubuf->len + 2*size));
}
if (data) {
memcpy(ubuf->data + ubuf->len, data, size);
ubuf->len += size;
/* zero term the buffer so it can be used (when applicable) as a string */
ubuf->data[ubuf->len] = 0;
}
return 0;
err:
return ~0;
}
void u_buf_set_len(u_buf_t *buf, size_t len)
{
buf->len = len;
}
/**
* \brief Fill a buffer object with the content of a file
*
* Open \a filename and copy its whole content into the given buffer.
*
* \param ubuf buffer object
* \param filename the source filename
*
* \return \c 0 on success, not zero on failure
*/
int u_buf_load(u_buf_t *ubuf, char *filename)
{
enum { BUFSZ = 4096 };
struct stat st;
FILE *fp = NULL;
dbg_err_if(ubuf == NULL);
dbg_err_if(filename == NULL);
dbg_err_if(stat(filename, &st));
/* clear the current data */
dbg_err_if(u_buf_clear(ubuf));
/* be sure to have a big enough buffer */
dbg_err_if(u_buf_reserve(ubuf, st.st_size));
warn_err_sif((fp = fopen(filename, "r")) == NULL);
/* fill the buffer with the whole file content */
dbg_err_if(fread(ubuf->data, st.st_size, 1, fp) == 0);
ubuf->len = st.st_size;
fclose(fp);
return 0;
err:
if(fp)
fclose(fp);
return ~0;
}
/**
* \brief Release buffer's underlaying memory block without freeing it
*
* Release the underlaying memory block of the given buffer without
* calling free() on it. The caller must free the buffer later on (probably
* after using it somwhow).
*
* Use u_buf_ptr() to get the pointer of the memory block, u_buf_size() to
* get its size and u_buf_len() to get its length.
*
* \param ubuf buffer object
*
* \return \c 0 on success, not zero on failure
*/
int u_buf_detach(u_buf_t *ubuf)
{
dbg_err_if(ubuf == NULL);
ubuf->data = NULL;
ubuf->size = 0;
ubuf->len = 0;
return 0;
err:
return ~0;
}
/**
* \brief Return the size of memory block allocated by the buffer
*
* Return the size of memory block allocated by the buffer.
*
* \param ubuf buffer object
*
* \return the data buffer length
*/
size_t u_buf_size(u_buf_t *ubuf)
{
dbg_err_if(ubuf == NULL);
return ubuf->size;
err:
return 0;
}
/**
* \brief Return the length of the buffer
*
* Return the length of data store in the given buffer.
*
* \param ubuf buffer object
*
* \return the data buffer length
*/
size_t u_buf_len(u_buf_t *ubuf)
{
dbg_err_if(ubuf == NULL);
return ubuf->len;
err:
return 0;
}
/**
* \brief Clear a buffer
*
* Totally erase the content of the given buffer. The memory allocated by
* the buffer will not be released until u_buf_free() is called.
*
* \param ubuf buffer object
*
* \return \c 0 on success, not zero on failure
*/
int u_buf_clear(u_buf_t *ubuf)
{
dbg_err_if(ubuf == NULL);
ubuf->len = 0;
return 0;
err:
return ~0;
}
/**
* \brief Set the value of a buffer
*
* Set the value of \a ubuf to \a data. If needed the buffer object will alloc
* more memory to store the \a data value.
*
* \param ubuf buffer object
* \param data the value that will be copied into the buffer
* \param size size of \a data
*
* \return \c 0 on success, not zero on failure
*/
int u_buf_set(u_buf_t *ubuf, void *data, size_t size)
{
dbg_err_if(ubuf == NULL);
dbg_err_if(data == NULL);
dbg_err_if(size == 0);
dbg_err_if(u_buf_clear(ubuf));
dbg_err_if(u_buf_append(ubuf, data, size));
return 0;
err:
return ~0;
}
char *u_buf_steal(u_buf_t *ubuf)
{
char *buf = ubuf->data;
ubuf->data = NULL;
ubuf->size = 0;
ubuf->len = 0;
return buf;
}
/**
* \brief Return a pointer to the buffer internal momory block
*
* Return a void* pointer to the memory block allocated by the buffer object.
*
* \param ubuf buffer object
*
* \return \c 0 on success, not zero on failure
*/
void* u_buf_ptr(u_buf_t *ubuf)
{
dbg_err_if(ubuf == NULL);
return ubuf->data;
err:
return NULL;
}
/**
* \brief Free a buffer
*
* Release all resources and free the given buffer object.
*
* \param ubuf buffer object
*
* \return \c 0 on success, not zero on failure
*/
int u_buf_free(u_buf_t *ubuf)
{
dbg_err_if(ubuf == NULL);
if(ubuf->data)
u_free(ubuf->data);
u_free(ubuf);
return 0;
err:
return ~0;
}
/**
* \brief Create a new buffer
*
* Create a new buffer object and save its pointer to \a *ps.
*
* \param pubuf on success will get the new buffer object
*
* \return \c 0 on success, not zero on failure
*/
int u_buf_create(u_buf_t **pubuf)
{
u_buf_t *ubuf = NULL;
dbg_err_if(pubuf == NULL);
ubuf = (u_buf_t*)u_zalloc(sizeof(u_buf_t));
dbg_err_if(ubuf == NULL);
*pubuf = ubuf;
return 0;
err:
return ~0;
}
int u_buf_construct(u_buf_t *ubuf, void *ptr, size_t size, size_t len)
{
if (ubuf->data) {
free(ubuf->data);
}
ubuf->data = ptr;
ubuf->size = size;
ubuf->len = len;
return 0;
}
/**
* \}
*/