ossp-pkg/cfg/cfg_buf.c
1.4
/*
** OSSP cfg - Configuration Parsing
** Copyright (c) 1999-2002 Ralf S. Engelschall <rse@engelschall.com>
** Copyright (c) 1999-2002 The OSSP Project (http://www.ossp.org/)
** Copyright (c) 2001-2002 Cable & Wireless Deutschland (http://www.cw.com/de/)
**
** This file is part of OSSP cfg, a configuration parsing
** library which can be found at http://www.ossp.org/pkg/lib/cfg/.
**
** Permission to use, copy, modify, and distribute this software for
** any purpose with or without fee is hereby granted, provided that
** the above copyright notice and this permission notice appear in all
** copies.
**
** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRCFG, STRICT LIABILITY,
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
** SUCH DAMAGE.
**
** cfg_buf.c: auto-resizing buffer
*/
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "cfg.h"
#include "cfg_buf.h"
#include "cfg_fmt.h"
struct cfg_buf_st {
char *buf_ptr;
size_t buf_size;
size_t buf_len;
};
cfg_rc_t cfg_buf_create(cfg_buf_t **buf)
{
if (buf == NULL)
return CFG_ERR_ARG;
if ((*buf = (cfg_buf_t *)malloc(sizeof(cfg_buf_t))) == NULL)
return CFG_ERR_SYS;
(*buf)->buf_ptr = NULL;
(*buf)->buf_len = 0;
(*buf)->buf_size = 0;
return CFG_OK;
}
cfg_rc_t cfg_buf_resize(cfg_buf_t *buf, signed int n)
{
char *cp;
if (buf == NULL)
return CFG_ERR_ARG;
if (n == 0) {
/* destroy buffer */
if (buf->buf_ptr != NULL)
free(buf->buf_ptr);
buf->buf_ptr = NULL;
buf->buf_len = 0;
buf->buf_size = 0;
}
else {
/* shrink or grow buffer */
if (buf->buf_ptr == NULL) {
if ((buf->buf_ptr = malloc(n+1)) == NULL)
return CFG_ERR_SYS;
buf->buf_size = n+1;
buf->buf_len = 0;
}
else {
if ((cp = realloc(buf->buf_ptr, buf->buf_size+n)) == NULL)
return CFG_ERR_SYS;
buf->buf_ptr = cp;
buf->buf_size += n;
if (buf->buf_len >= buf->buf_size) {
buf->buf_len = buf->buf_size-1;
*(buf->buf_ptr + buf->buf_len) = '\0';
}
}
}
return CFG_OK;
}
cfg_rc_t cfg_buf_format(cfg_buf_t *buf, const char *fmt, ...)
{
va_list ap;
cfg_rc_t rc;
va_start(ap, fmt);
rc = cfg_buf_vformat(buf, fmt, ap);
va_end(ap);
return rc;
}
cfg_rc_t cfg_buf_vformat(cfg_buf_t *buf, const char *fmt, va_list ap)
{
cfg_rc_t rc;
int n;
if (buf == NULL || fmt == NULL)
return CFG_ERR_ARG;
if ((n = cfg_fmt_vsprintf(NULL, -1, fmt, ap)) == -1)
return CFG_ERR_FMT;
if ((rc = cfg_buf_resize(buf, n)) != CFG_OK)
return rc;
if ((n = cfg_fmt_vsprintf(buf->buf_ptr + buf->buf_len,
buf->buf_size - buf->buf_len,
fmt, ap)) == -1)
return CFG_ERR_FMT;
buf->buf_len += n;
return CFG_OK;
}
cfg_rc_t cfg_buf_content(cfg_buf_t *buf, char **ptr, size_t *len, size_t *size)
{
if (buf == NULL)
return CFG_ERR_ARG;
if (ptr != NULL)
*ptr = buf->buf_ptr;
if (len != NULL)
*len = buf->buf_len;
if (size != NULL)
*size = buf->buf_size;
return CFG_OK;
}
cfg_rc_t cfg_buf_destroy(cfg_buf_t *buf)
{
if (buf == NULL)
return CFG_ERR_ARG;
if (buf->buf_ptr != NULL)
free(buf->buf_ptr);
free(buf);
return CFG_OK;
}