From 121f2f888e02a28e7896f84dde019cb320f0b11d Mon Sep 17 00:00:00 2001 From: Chris Hall Date: Tue, 21 Dec 2010 11:12:30 +0000 Subject: Creation of pipework branch --- lib/elstring.h | 354 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 354 insertions(+) create mode 100644 lib/elstring.h (limited to 'lib/elstring.h') diff --git a/lib/elstring.h b/lib/elstring.h new file mode 100644 index 00000000..051e5962 --- /dev/null +++ b/lib/elstring.h @@ -0,0 +1,354 @@ +/* Length/String 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_ELSTRING_H +#define _ZEBRA_ELSTRING_H + +#include "misc.h" +#include "zassert.h" +#include "memory.h" + +/*============================================================================== + * This is some very simple support for strings which are Length/Body + * objects. + * + * NB: this object knows NOTHING about memory allocation etc. The objective + * is the simplest possible encapsulation of strings which are NOT '\0' + * terminated. + * + * + * + */ +struct elstring +{ + union + { + void* v ; /* may be NULL iff len == 0 */ + const void* cv ; + } body ; + + ulen len ; + bool term ; /* true <=> body is '\0' terminated */ +} ; + +typedef struct elstring elstring_t[1] ; +typedef struct elstring* elstring ; + +/* Setting an elstring object to all zeros is enough to initialise it to + * an empty string. + */ +enum +{ + ELSTRING_INIT_ALL_ZEROS = true +} ; + +/*------------------------------------------------------------------------------ + * Various forms of body -- NB: + */ + +Inline void* +els_body_nn(elstring els) +{ + return els->body.v ; +} ; + +Inline void* +els_body(elstring els) +{ + return (els != NULL) ? els_body_nn(els) : NULL ; +} ; + +Inline ulen +els_len_nn(elstring els) +{ + return els->len ; +} ; + +Inline ulen +els_len(elstring els) +{ + return (els != NULL) ? els_len_nn(els) : 0 ; +} ; + +Inline bool +els_term_nn(elstring els) +{ + return els->term ; +} ; + +Inline bool +els_term(elstring els) +{ + return (els != NULL) ? els_term_nn(els) : false ; +} ; + +/*============================================================================== + * All so simple that everything is implemented as Inline + */ + +/*------------------------------------------------------------------------------ + * Initialise or create a new elstring + */ +Inline elstring +els_init_new(elstring els) +{ + if (els == NULL) + els = XCALLOC(MTYPE_TMP, sizeof(elstring_t)) ; + else + memset(els, 0, sizeof(elstring_t)) ; + + confirm(ELSTRING_INIT_ALL_ZEROS) ; + + return els ; +} ; + +/*------------------------------------------------------------------------------ + * Set elstring value from ordinary string. + * + * NB: elstring MUST NOT be NULL. + * + * NB: treats str == NULL as a zero length string. + * + * NB: sets "term" unless str == NULL. + */ +Inline void +els_set_nn(elstring els, const void* str) +{ + els->body.cv = str ; + els->len = (str != NULL) ? strlen(str) : 0 ; + els->term = (str != NULL) ; +} ; + +/*------------------------------------------------------------------------------ + * Set elstring value from ordinary string. + * + * Creates elstring object if required (ie if els == NULL). + * + * See: els_set_nn. + */ +Inline elstring +els_set(elstring els, const void* str) +{ + if (els == NULL) + els = XCALLOC(MTYPE_TMP, sizeof(elstring_t)) ; + + els_set_nn(els, str) ; + + return els ; +} ; + +/*------------------------------------------------------------------------------ + * Set elstring value from body + length. + * + * NB: sets term = false. + * + * NB: elstring MUST NOT be NULL. + * + * NB: treats str == NULL as a zero length string. + */ +Inline void +els_set_n_nn(elstring els, const void* body, ulen len) +{ + els->body.cv = body ; + els->len = len ; + els->term = false ; +} ; + +/*------------------------------------------------------------------------------ + * Set elstring value from body + length. + * + * Creates elstring object if required (ie if els == NULL). + * + * See els_set_n_nn. + */ +Inline elstring +els_set_n(elstring els, const void* body, ulen len) +{ + if (els == NULL) + els = XCALLOC(MTYPE_TMP, sizeof(elstring_t)) ; + + els_set_n_nn(els, body, len) ; + + return els ; +} ; + +/*------------------------------------------------------------------------------ + * Clear contents of an elstring (if any) + * + * NB: it is the callers responsibility to free the contents of the elstring. + * if that is required, before freeing the elstring itself. + */ +Inline void +els_clear(elstring els) +{ + if (els != NULL) + { + els->body.v = NULL ; + els->len = 0 ; + els->term = false ; + } ; +} ; + +/*------------------------------------------------------------------------------ + * Release dynamically allocated elstring. + * + * Returns NULL. + * + * NB: it is the callers responsibility to free the contents of the elstring. + * if that is required, before freeing the elstring itself. + */ +Inline elstring +els_free(elstring els) +{ + if (els != NULL) + XFREE(MTYPE_TMP, els) ; + + return NULL ; +} ; + +/*------------------------------------------------------------------------------ + * Set elstring length. And set term false. + * + * NB: it is the caller's responsibility to set a valid length !! + * + * NB: elstring MUST NOT be NULL. + */ +Inline void +els_set_len_nn(elstring els, ulen len) +{ + els->len = len ; + els->term = false ; +} ; + +/*------------------------------------------------------------------------------ + * Set elstring body. And set term false. + * + * NB: it is the caller's responsibility to set a valid body !! + * + * NB: elstring MUST NOT be NULL. + */ +Inline void +els_set_body_nn(elstring els, const void* body) +{ + els->body.cv = body ; + els->term = false ; +} ; + +/*------------------------------------------------------------------------------ + * Set elstring terminated. + * + * NB: it is the caller's responsibility to set a valid body !! + * + * NB: elstring MUST NOT be NULL. + */ +Inline void +els_set_term_nn(elstring els, bool term) +{ + els->term = term ; +} ; + +/*------------------------------------------------------------------------------ + * Compare two elstrings -- returns the usual -ve, 0, +ve cmp result. + */ +Inline int +els_cmp(elstring a, elstring b) +{ + const uchar* ap ; + const uchar* bp ; + ulen al, bl ; + ulen n ; + + ap = els_body(a) ; + bp = els_body(b) ; + al = els_len(a) ; + bl = els_len(b) ; + + n = (al <= bl) ? al : bl ; + + while (n) + { + int d = *ap++ - *bp++ ; + if (d != 0) + return d ; + --n ; + } ; + + return al < bl ? -1 : (al == bl) ? 0 : +1 ; +} ; + +/*------------------------------------------------------------------------------ + * Are two elstrings equal ? -- returns true if strings equal. + */ +Inline bool +els_equal(elstring a, elstring b) +{ + const uchar* ap ; + const uchar* bp ; + ulen n ; + + n = els_len(b) ; + if (n != els_len(a)) + return false ; + + ap = els_body(a) ; + bp = els_body(b) ; + + while (n) + { + if (*ap++ != *bp++) + return false ; + --n ; + } ; + + return true ; +} ; + +/*------------------------------------------------------------------------------ + * Is 'b' a leading substring of 'a' ? -- returns true if it is. + * + * If 'b' is empty it is always a leading substring. + */ +Inline int +els_substring(elstring a, elstring b) +{ + const uchar* ap ; + const uchar* bp ; + ulen n ; + + n = els_len(b) ; + if (n > els_len(a)) + return false ; + + ap = els_body(a) ; + bp = els_body(b) ; + + while (n) + { + if (*ap++ != *bp++) + return false ; + --n ; + } ; + + return true ; +} ; + +#endif /* _ZEBRA_ELSTRING_H */ + -- cgit v1.2.3