summaryrefslogtreecommitdiffstats
path: root/lib/tstring.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tstring.h')
-rw-r--r--lib/tstring.h139
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 */