diff options
Diffstat (limited to 'lib/tstring.h')
-rw-r--r-- | lib/tstring.h | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/lib/tstring.h b/lib/tstring.h new file mode 100644 index 00000000..4dd45edb --- /dev/null +++ b/lib/tstring.h @@ -0,0 +1,139 @@ +/* Temporary string handling -- header + * Copyright (C) 2009 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. + */ + +#ifndef _ZEBRA_TSTRING_H +#define _ZEBRA_TSTRING_H + +#include "misc.h" +#include "zassert.h" +#include "memory.h" + +/*============================================================================== + * tstrings are allocated on the stack, but if (unexpectedly) the standard + * size is not enough, then they can be allocated dynamically. + * + * To declare a "tstring": + * + * tstring(foo, 64) ; // creates a "tstring" variable called "foo" + * // with 64 char buffer. + * + * Can then: + * + * s = tstring_set_len(foo, n) ; // ensures have buffer for n+1 chars + * s = tstring_set(foo, "...") ; // copies "..." (with '\0') to buffer + * s = tstring_set_n(foo, q, n) ; // copies n characters from q to buffer + * and '\0' terminates + * + * If can fit stuff in the buffer, will do so. Otherwise will allocate an + * MTYPE_TMP buffer to work in. + * + * And before leaving the scope of "foo" must: + * + * tstring_free(foo) ; // releases any dynamically allocated memory. + */ + +struct tstring +{ + usize size ; + char* str ; + char* alloc ; +} ; + +typedef struct tstring tstring[1] ; + +/* tstring(foo, 93) ; -- declare the variable "foo". */ +#define tstring_t(name, sz) \ + char _zlxq_##name##_b[ ((sz) + 7) & 0xFFFFFFF8] ; \ + tstring name = { { .size = ((sz) + 7) & 0xFFFFFFF8, \ + .str = _zlxq_##name##_b, \ + .alloc = NULL } } + +/*------------------------------------------------------------------------------ + * Ensure the tstring "foo" can accomodate at least "len" characters plus the + * terminating '\0'. + * + * Returns: address of buffer + * + * NB: address of buffer may not be the same as returned by a previous operation + * on foo. Also, previous contents of foo may be lost. + */ +Inline char* +tstring_set_len(struct tstring* ts, usize len) +{ + if (len >= ts->size) + { + ts->size = len + 1 ; + ts->str = ts->alloc = XREALLOC(MTYPE_TMP, ts->alloc, len + 1) ; + } ; + + return ts->str ; +} ; + +/*------------------------------------------------------------------------------ + * Copy "len" characters from "src" to the tstring "foo", and append a + * terminating '\0'. + * + * The "src" address is ignored if "len" == 0 (sets "foo" to be empty string). + * + * Returns: address of buffer + * + * NB: address of buffer may not be the same as returned by a previous operation + * on foo. Also, previous contents of foo may be lost. + */ +static inline char* +tstring_set_n(struct tstring* ts, const char* str, usize len) +{ + char* tss = tstring_set_len(ts, len) ; + + if (len > 0) + memcpy(tss, str, len) ; + *(tss + len) = '\0' ; + + return tss ; +} ; + +/*------------------------------------------------------------------------------ + * Copy the string "str" to the tstring "foo", with terminating '\0'. + * + * If "str" is NULL, sets "foo" to be an empty string. + * + * Returns: address of buffer + * + * NB: address of buffer may not be the same as returned by a previous operation + * on foo. Also, previous contents of foo may be lost. + */ +static inline char* +tstring_set(struct tstring* ts, const char* str) +{ + return tstring_set_n(ts, str, (str != NULL) ? strlen(str) : 0) ; +} ; + +/*------------------------------------------------------------------------------ + * If have dynamically allocated buffer for tstring "foo", release it now. + */ +static inline void +tstring_free(struct tstring* ts) +{ + if (ts->alloc != NULL) + XFREE(MTYPE_TMP, ts->alloc) ; /* sets ts->alloc NULL */ +} ; + +#endif /* _ZEBRA_TSTRING_H */ |