summaryrefslogtreecommitdiffstats
path: root/lib/qstring.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/qstring.h')
-rw-r--r--lib/qstring.h365
1 files changed, 365 insertions, 0 deletions
diff --git a/lib/qstring.h b/lib/qstring.h
new file mode 100644
index 00000000..1841657e
--- /dev/null
+++ b/lib/qstring.h
@@ -0,0 +1,365 @@
+/* Some 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_QSTRING_H
+#define _ZEBRA_QSTRING_H
+
+#include "zebra.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifndef Inline
+#define Inline static inline
+#endif
+
+/* GCC have printf type attribute check. */
+#ifdef __GNUC__
+#define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
+#else
+#define PRINTF_ATTRIBUTE(a,b)
+#endif /* __GNUC__ */
+
+/*==============================================================================
+ * These "qstrings" address the ...
+ *
+ *
+ *
+ */
+
+typedef struct qstring qstring_t ;
+typedef struct qstring* qstring ;
+
+struct qstring
+{
+ void* body ;
+ size_t size ;
+
+ size_t len ;
+ size_t cp ;
+} ;
+
+/*------------------------------------------------------------------------------
+ * Access functions for body of qstring -- to take care of casting pointers
+ *
+ * NB: if the body has not yet been allocated, these functions will return
+ * NULL or NULL + the offset.
+ */
+Inline char* /* pointer to body of qstring */
+qs_chars(qstring qs)
+{
+ return (char*)qs->body ;
+} ;
+
+Inline unsigned char* /* pointer to body of qstring */
+qs_bytes(qstring qs)
+{
+ return (unsigned char*)qs->body ;
+} ;
+
+Inline char* /* pointer to given offset in qstring */
+qs_chars_at(qstring qs, size_t off)
+{
+ return qs_chars(qs) + off ;
+} ;
+
+Inline unsigned char* /* pointer to given offset in qstring */
+qs_bytes_at(qstring qs, size_t off)
+{
+ return qs_bytes(qs) + off ;
+} ;
+
+Inline char* /* pointer to 'cp' offset in qstring */
+qs_cp_char(qstring qs)
+{
+ return qs_chars_at(qs, qs->cp) ;
+} ;
+
+Inline unsigned char* /* pointer to 'cp' offset in qstring */
+qs_cp_byte(qstring qs)
+{
+ return qs_bytes_at(qs, qs->cp) ;
+} ;
+
+Inline char* /* pointer to 'len' offset in qstring */
+qs_ep_char(qstring qs)
+{
+ return qs_chars_at(qs, qs->len) ;
+} ;
+
+Inline unsigned char* /* pointer to 'len' offset in qstring */
+qs_ep_byte(qstring qs)
+{
+ return qs_bytes_at(qs, qs->len) ;
+} ;
+
+/*==============================================================================
+ * Functions
+ */
+
+extern qstring
+qs_init_new(qstring qs, size_t len) ;
+
+extern size_t
+qs_alloc(qstring qs, size_t len) ;
+
+extern void
+qs_free_body(qstring qs) ;
+
+extern qstring
+qs_reset(qstring qs, int free_structure) ;
+
+#define qs_reset_keep(qs) qs_reset(qs, 0)
+#define qs_reset_free(qs) qs_reset(qs, 1)
+
+extern int
+qs_printf(qstring qs, const char* format, ...) PRINTF_ATTRIBUTE(2, 3) ;
+
+extern int
+qs_vprintf(qstring qs, const char *format, va_list args) ;
+
+extern size_t
+qs_set(qstring qs, const char* s) ;
+
+extern size_t
+qs_set_n(qstring qs, const char* s, size_t len) ;
+
+Inline size_t
+qs_need(qstring qs, size_t len) ;
+
+Inline size_t
+qs_set_len(qstring qs, size_t len) ;
+
+Inline void
+qs_set_empty(qstring qs) ;
+
+Inline size_t
+qs_len(qstring qs) ;
+
+Inline size_t
+qs_size(qstring qs) ;
+
+Inline void*
+qs_term(qstring qs) ;
+
+Inline size_t
+qs_insert(qstring qs, const void* src, size_t n) ;
+
+Inline void
+qs_replace(qstring qs, const void* src, size_t n) ;
+
+Inline size_t
+qs_delete(qstring qs, size_t n) ;
+
+/*==============================================================================
+ * The Inline functions.
+ */
+
+/*------------------------------------------------------------------------------
+ * Need space for a string of 'len' characters (plus possible '\0').
+ *
+ * Returns: size of the qstring body
+ * (which includes the extra space allowed for '\0')
+ *
+ * NB: asking for 0 bytes will cause a body to be allocated, ready for any
+ * '\0' !
+ *
+ * NB: has no effect on 'cp' or 'len'.
+ */
+Inline size_t
+qs_need(qstring qs, size_t len)
+{
+ if (len < qs->size)
+ {
+ assert(qs->body != NULL) ;
+ return qs->size ;
+ }
+ else
+ return qs_alloc(qs, len) ;
+} ;
+
+/*------------------------------------------------------------------------------
+ * Set 'len' -- allocate or extend body as required.
+ *
+ * Returns: size of the qstring body
+ * (which includes the extra space allowed for '\0')
+ *
+ * NB: asking for 0 bytes will cause a body to be allocated, ready for any
+ * '\0' !
+ *
+ * NB: has no effect on 'cp' -- even if 'cp' > 'len'.
+ */
+Inline size_t
+qs_set_len(qstring qs, size_t len)
+{
+ qs->len = len ;
+ return qs_need(qs, len) ;
+} ;
+
+/*------------------------------------------------------------------------------
+ * Reset contents of qstring.
+ *
+ * Sets 'cp' = 'len' = 0. Sets first byte of body (if any) to NULL.
+ */
+Inline void
+qs_set_empty(qstring qs)
+{
+ qs->len = 0 ;
+ qs->cp = 0 ;
+ if (qs->body != NULL)
+ *((char*)qs->body) = '\0' ;
+} ;
+
+/*------------------------------------------------------------------------------
+ * Get length of qstring -- by doing strlen() -- and record it in qs->len.
+ *
+ * Returns: the string length
+ *
+ * NB: if no body has been allocated, length = 0
+ */
+Inline size_t
+qs_len(qstring qs)
+{
+ return qs->len = (qs->body != NULL) ? strlen(qs_chars(qs)) : 0 ;
+} ;
+
+/*------------------------------------------------------------------------------
+ * Get size of qstring body.
+ *
+ * NB: if no body has been allocated, size = 0
+ */
+Inline size_t
+qs_size(qstring qs)
+{
+ return qs->size ;
+} ;
+
+/*------------------------------------------------------------------------------
+ * Set '\0' at qs->len -- allocate or extend body as required.
+ *
+ * Returns address of body.
+ */
+Inline void*
+qs_term(qstring qs)
+{
+ size_t len ;
+ if ((len = qs->len) >= qs->size)
+ qs_alloc(qs, len) ;
+
+ *qs_chars_at(qs, len) = '\0' ;
+
+ return qs->body ;
+} ;
+
+/*------------------------------------------------------------------------------
+ * Insert 'n' bytes at 'cp' -- moves anything cp..len up.
+ *
+ * Increases 'len'. but does not affect 'cp'.
+ *
+ * Returns: number of bytes beyond 'cp' that were moved before insert.
+ *
+ * NB: if 'cp' > 'len', then sets 'len' = 'cp' first -- which will introduce
+ * one or more undefined bytes.
+ *
+ * NB: the string is NOT re-terminated.
+ */
+Inline size_t
+qs_insert(qstring qs, const void* src, size_t n)
+{
+ size_t after ;
+ char* p ;
+
+ if (qs->len < qs->cp)
+ qs->len = qs->cp ;
+ after = qs->len - qs->cp ;
+
+ qs_set_len(qs, qs->len + n) ; /* set len and ensure have space */
+
+ p = qs_cp_char(qs) ;
+ if (after > 0)
+ memmove (p + n, p, after) ;
+
+ if (n > 0)
+ memmove(p, src, n) ;
+
+ return after ;
+} ;
+
+/*------------------------------------------------------------------------------
+ * Replace 'n' bytes at 'cp' -- extending if required.
+ *
+ * May increase 'len'. but does not affect 'cp'.
+ *
+ * NB: if 'cp' > 'len', then sets 'len' = 'cp' first -- which will introduce
+ * one or more undefined bytes.
+ *
+ * NB: the string is NOT re-terminated.
+ */
+Inline void
+qs_replace(qstring qs, const void* src, size_t n)
+{
+ if (qs->len < qs->cp + n)
+ qs_set_len(qs, qs->cp + n) ; /* set len and ensure have space */
+
+ if (n > 0)
+ memmove(qs_cp_char(qs), src, n) ;
+} ;
+
+/*------------------------------------------------------------------------------
+ * Remove 'n' bytes at 'cp' -- extending if required.
+ *
+ * May change 'len'. but does not affect 'cp'.
+ *
+ * Returns: number of bytes beyond 'cp' that were moved before insert.
+ *
+ * NB: if 'cp' > 'len', then sets 'len' = 'cp' first -- which will introduce
+ * one or more undefined bytes.
+ *
+ * NB: the string is NOT re-terminated.
+ */
+Inline size_t
+qs_delete(qstring qs, size_t n)
+{
+ size_t after ;
+ char* p ;
+
+ /* If deleting up to or beyond len, then simply set len == cp */
+ if ((qs->cp + n) >= qs->len)
+ {
+ qs_set_len(qs, qs->cp) ; /* set len, looks after cp > len */
+ return 0 ; /* nothing after */
+ }
+
+ /* There is at least one byte after cp (so body must exist) */
+ after = qs->len - (qs->cp + n) ;
+
+ if (n > 0)
+ {
+ p = qs_cp_char(qs) ;
+ memmove (p, p + n, after) ;
+
+ qs->len -= n ;
+ } ;
+
+ return after ;
+} ;
+
+#endif /* _ZEBRA_QSTRING_H */