diff options
Diffstat (limited to 'lib/qstring.c')
-rw-r--r-- | lib/qstring.c | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/lib/qstring.c b/lib/qstring.c new file mode 100644 index 00000000..f847e0b0 --- /dev/null +++ b/lib/qstring.c @@ -0,0 +1,227 @@ +/* Some string handling + * Copyright (C) 2010 Chris Hall (GMCH), Highwayman + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "qstring.h" + +#include "memory.h" +#include "zassert.h" + +/*============================================================================== + */ + +/*------------------------------------------------------------------------------ + * Initialise qstring -- allocate if required. + * + * If non-zero len is given, a body is allocated (for at least len + 1). + * + * Returns: address of qstring + * + * NB: assumes initialising a new structure. If not, then caller should + * use qs_reset() or qs_set_empty(). + */ +extern qstring +qs_init_new(qstring qs, size_t len) +{ + if (qs == NULL) + qs = XCALLOC(MTYPE_QSTRING, sizeof(qstring_t)) ; + else + memset(qs, 0, sizeof(qstring_t)) ; + + /* Zeroising has set: + * + * body = NULL -- no body + * size = 0 -- no body + * + * len = 0 + * cp = 0 + * + * Nothing more to do unless initial size != 0 + */ + + if (len != 0) + qs_alloc(qs, len) ; + + return qs ; +} ; + +/*------------------------------------------------------------------------------ + * Allocate or reallocate so that string is big enough for the given length. + * + * Allocates to 16 byte boundaries. + * + * Returns: the number of bytes *allocated*, which includes the byte for + * possible trailing '\0'. + * + * NB: allocates EXTRA space for trailing '\0' beyond given length. + */ +extern size_t +qs_alloc(qstring qs, size_t len) +{ + len = (len + 0x10) & ~(size_t)(0x10 - 1) ; + + if (qs->body == NULL) + { + assert(qs->size == 0) ; + qs->size = len ; + qs->body = XMALLOC(MTYPE_QSTRING_BODY, qs->size) ; + } + else + { + assert(qs->size > 0) ; + qs->size *= 2 ; + if (qs->size < len) + qs->size = len ; + qs->body = XREALLOC(MTYPE_QSTRING_BODY, qs->body, qs->size) ; + } ; + + return qs->size ; +} ; + +/*------------------------------------------------------------------------------ + * Free body of qstring -- zeroise size, len and cp + */ +extern void +qs_free_body(qstring qs) +{ + if (qs->body != NULL) + XFREE(MTYPE_QSTRING_BODY, qs->body) ; /* sets qs->body = NULL */ + + qs->size = 0 ; + qs->len = 0 ; + qs->cp = 0 ; +} ; + +/*------------------------------------------------------------------------------ + * Reset qstring -- free body and, if required, free the structure. + * + * If not freeing the structure, zeroise size, len and cp -- qs_free_body() + * + * Returns: NULL if freed the structure + * address of structure, otherwise + */ +extern qstring +qs_reset(qstring qs, int free_structure) +{ + if (qs->body != NULL) + XFREE(MTYPE_QSTRING_BODY, qs->body) ; /* sets qs->body = NULL */ + + if (free_structure) + XFREE(MTYPE_QSTRING, qs) ; /* sets qs = NULL */ + else + { + qs->size = 0 ; + qs->len = 0 ; + qs->cp = 0 ; + } ; + + return qs ; +} ; + +/*============================================================================== + * printf(0 and vprintf() type functions + */ + +/*------------------------------------------------------------------------------ + * Formatted print to qstring -- cf printf() + */ +extern int +qs_printf(qstring qs, const char* format, ...) +{ + va_list args; + int result ; + + va_start (args, format); + result = qs_vprintf(qs, format, args); + va_end (args); + + return result; +} ; + +/*------------------------------------------------------------------------------ + * Formatted print to qstring -- cf vprintf() + * + * Note that vsnprintf() returns the length of what it would like to have + * produced, if it had the space. That length does not include the trailing + * '\0'. + * + * Also note that given a zero length the string address may be NULL, and the + * result is still the length required. + */ +extern int +qs_vprintf(qstring qs, const char *format, va_list args) +{ + va_list ac ; + int len ; + + while (1) + { + va_copy(ac, args); + qs->len = len = vsnprintf (qs->body, qs->size, format, ac) ; + va_end(ac); + + if (len < (int)qs->size) + return len ; /* quit if done (or error) */ + + qs_alloc(qs, len) ; + } ; +} ; + +/*============================================================================== + * Other operations + */ + +/*------------------------------------------------------------------------------ + * Set qstring to be copy of the given string. + * + * Sets qs->len to the length of the string (excluding trailing '\0') + * + * NB: if stc == NULL, sets qstring to be zero length string. + */ +extern size_t +qs_set(qstring qs, const char* src) +{ + qs_set_len(qs, (src != NULL) ? strlen(src) : 0) ; + if (qs->len != 0) + memcpy(qs->body, src, qs->len + 1) ; + else + *((char*)qs->body) = '\0' ; + + return qs->len ; +} ; + +/*------------------------------------------------------------------------------ + * Set qstring to be leading 'n' bytes of given string. + * + * NB: src string MUST be at least that long. + * + * NB: src may not be NULL unless len == 0. + */ +extern size_t +qs_set_n(qstring qs, const char* src, size_t n) +{ + qs_need(qs, n) ; /* sets qs->len */ + if (n != 0) + memcpy(qs->body, src, n) ; + + *((char*)qs->body + n) = '\0' ; + + return n ; +} ; |