From: Sebastian Harl Date: Wed, 12 Sep 2012 13:31:44 +0000 (+0200) Subject: strbuf: Added a string buffer class for dynamically growing strings. X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=e2682945314d1a2abc8e9e879a80a72dcf638e9e;p=libjunos.git strbuf: Added a string buffer class for dynamically growing strings. For now, the class provides a method to append to the string in a sprintf() fashion. --- diff --git a/src/Makefile.am b/src/Makefile.am index ffee374..fa170d3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,7 +8,8 @@ BUILT_SOURCES = libjunos_features.h libjunos_la_SOURCES = junos.c junos.h \ libjunos_features.h \ access_ssh.c \ - netrc.c + netrc.c \ + strbuf.c libjunos_la_CFLAGS = $(AM_CFLAGS) \ @LIBSSH2_CFLAGS@ \ @LIBXML2_CFLAGS@ diff --git a/src/junos.h b/src/junos.h index 5f31e91..055cd03 100644 --- a/src/junos.h +++ b/src/junos.h @@ -52,6 +52,12 @@ extern "C" { typedef struct junos junos_t; +/* string buffer */ + +typedef struct junos_strbuf junos_strbuf_t; + +/* netrc */ + typedef struct { char *machine; char *login; @@ -112,6 +118,28 @@ junos_disconnect(junos_t *junos); void junos_free(junos_t *junos); +/* + * string buffer + */ + +junos_strbuf_t * +junos_strbuf_new(size_t size); + +void +junos_strbuf_free(junos_strbuf_t *strbuf); + +ssize_t +junos_strbuf_sprintf(junos_strbuf_t *strbuf, const char *fmt, ...); + +ssize_t +junos_strbuf_vsprintf(junos_strbuf_t *strbuf, const char *fmt, va_list ap); + +char * +junos_strbuf_string(junos_strbuf_t *strbuf); + +size_t +junos_strbuf_len(junos_strbuf_t *strbuf); + /* * netrc */ diff --git a/src/strbuf.c b/src/strbuf.c new file mode 100644 index 0000000..c0b2a26 --- /dev/null +++ b/src/strbuf.c @@ -0,0 +1,164 @@ +/* + * libJUNOS - src/strbuf.c + * Copyright (C) 2012 Sebastian 'tokkee' Harl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS 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 COPYRIGHT HOLDERS OR + * 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 CONTRACT, 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. + */ + +/* + * String buffer object. + */ + +#include "junos.h" + +#include + +#include +#include +#include + +/* + * private data structures + */ + +struct junos_strbuf { + char *string; + size_t size; + size_t pos; +}; + +/* + * private helper functions + */ + +static int +strbuf_resize(junos_strbuf_t *strbuf) +{ + char *tmp; + + tmp = realloc(strbuf->string, 2 * strbuf->size); + if (! tmp) + return -1; + + strbuf->string = tmp; + strbuf->size *= 2; + + strbuf->string[strbuf->pos] = '\0'; + return 0; +} /* strbuf_resize */ + +/* + * public API + */ + +junos_strbuf_t * +junos_strbuf_new(size_t size) +{ + junos_strbuf_t *strbuf; + + strbuf = calloc(1, sizeof(*strbuf)); + if (! strbuf) + return NULL; + + if (! size) + return strbuf; + + strbuf->string = malloc(size); + if (strbuf->string) { + strbuf->string[0] = '\0'; + strbuf->size = size; + } + + return strbuf; +} /* junos_strbuf_new */ + +void +junos_strbuf_free(junos_strbuf_t *strbuf) +{ + if (! strbuf) + return; + + free(strbuf->string); + free(strbuf); +} /* junos_strbuf_free */ + +ssize_t +junos_strbuf_vsprintf(junos_strbuf_t *strbuf, const char *fmt, va_list ap) +{ + int status; + + if (! strbuf) + return -1; + + assert(strbuf->string[strbuf->pos] == '\0'); + + if (strbuf->pos >= strbuf->size) + if (strbuf_resize(strbuf)) + return -1; + + status = vsnprintf(strbuf->string + strbuf->pos, + strbuf->size - strbuf->pos, fmt, ap); + + if (status < 0) + return status; + + if ((size_t)status >= strbuf->size - strbuf->pos) { + strbuf_resize(strbuf); + return junos_strbuf_vsprintf(strbuf, fmt, ap); + } + + strbuf->pos += (size_t)status; + return (ssize_t)strbuf->pos; +} /* junos_strbuf_vsprintf */ + +ssize_t +junos_strbuf_sprintf(junos_strbuf_t *strbuf, const char *fmt, ...) +{ + va_list ap; + ssize_t status; + + va_start(ap, fmt); + status = junos_strbuf_vsprintf(strbuf, fmt, ap); + va_end(ap); + + return status; +} /* junos_strbuf_sprintf */ + +char * +junos_strbuf_string(junos_strbuf_t *strbuf) +{ + if (! strbuf) + return NULL; + return strbuf->string; +} /* junos_strbuf_string */ + +size_t +junos_strbuf_len(junos_strbuf_t *strbuf) +{ + if (! strbuf) + return 0; + return strbuf->pos; +} /* junos_strbuf_string */ + +/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ +