summaryrefslogtreecommitdiffstats
path: root/lib/qstring.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/qstring.h')
-rw-r--r--lib/qstring.h247
1 files changed, 175 insertions, 72 deletions
diff --git a/lib/qstring.h b/lib/qstring.h
index 1841657e..0597eda8 100644
--- a/lib/qstring.h
+++ b/lib/qstring.h
@@ -27,6 +27,8 @@
#include <stddef.h>
#include <stdint.h>
+#include "memory.h"
+
#ifndef Inline
#define Inline static inline
#endif
@@ -39,10 +41,14 @@
#endif /* __GNUC__ */
/*==============================================================================
- * These "qstrings" address the ...
- *
+ * These "qstrings" address address the lack of a flexible length string in 'C'.
*
+ * This is not a general purpose strings module, but provides a limited number
+ * of useful string operations such that the caller does not need to worry
+ * about the length of the string, and allocating space and so on.
*
+ * The caller does, however, have to explicitly release the contents of a
+ * qstring when it is done with.
*/
typedef struct qstring qstring_t ;
@@ -50,7 +56,13 @@ typedef struct qstring* qstring ;
struct qstring
{
- void* body ;
+ union
+ {
+ void* body ;
+ const void* const_body ;
+ char* char_body ;
+ unsigned char* uchar_body ;
+ } ;
size_t size ;
size_t len ;
@@ -115,117 +127,161 @@ qs_ep_byte(qstring qs)
* 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) ;
+extern qstring qs_init_new(qstring qs, size_t len) ;
+extern qstring qs_make_to_length(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) ;
+Inline qstring qs_new(void) ;
+Inline qstring qs_dummy(qstring qs, const char* src, int pos) ;
-extern int
-qs_vprintf(qstring qs, const char *format, va_list args) ;
+extern qstring qs_printf(qstring qs, const char* format, ...)
+ PRINTF_ATTRIBUTE(2, 3) ;
+extern qstring qs_vprintf(qstring qs, const char *format, va_list args) ;
-extern size_t
-qs_set(qstring qs, const char* s) ;
+extern qstring qs_set(qstring qs, const char* src) ;
+extern qstring qs_set_n(qstring qs, const char* src, size_t n) ;
-extern size_t
-qs_set_n(qstring qs, const char* s, size_t len) ;
+extern qstring qs_append(qstring qs, const char* src) ;
+extern qstring qs_append_n(qstring qs, const char* src, size_t n) ;
-Inline size_t
-qs_need(qstring qs, size_t len) ;
+Inline qstring qs_need(qstring qs, size_t len) ;
+Inline qstring qs_set_len(qstring qs, size_t len) ;
+extern qstring qs_add_len(qstring qs, size_t n, char** p_ep) ;
+Inline void qs_clear(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_set_len(qstring qs, size_t len) ;
+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) ;
-Inline void
-qs_set_empty(qstring qs) ;
+extern qstring qs_copy(qstring dst, qstring src) ;
+extern int qs_cmp_sig(qstring a, qstring b) ;
-Inline size_t
-qs_len(qstring qs) ;
-
-Inline size_t
-qs_size(qstring qs) ;
-
-Inline void*
-qs_term(qstring qs) ;
+/*==============================================================================
+ * The Inline functions.
+ */
-Inline size_t
-qs_insert(qstring qs, const void* src, size_t n) ;
+/*------------------------------------------------------------------------------
+ * Make a brand new, completely empty qstring
+ */
+Inline qstring
+qs_new(void)
+{
+ /* Zeroising has set:
+ *
+ * body = NULL -- no body
+ * size = 0 -- no body
+ *
+ * len = 0
+ * cp = 0
+ *
+ * Nothing more to do unless initial size != 0
+ */
+ return XCALLOC(MTYPE_QSTRING, sizeof(qstring_t)) ;
+} ;
-Inline void
-qs_replace(qstring qs, const void* src, size_t n) ;
+/*------------------------------------------------------------------------------
+ * Construct a "dummy" qstring from the given string.
+ *
+ * Allocates a qstring if required.
+ *
+ * This sets: body = the src
+ * len = strlen(src) (0 if src is NULL)
+ * cp = 0 if 'pos' is zero
+ * len otherwise
+ * size = 0
+ *
+ * The zero size means that the qstring handling will not attempt to free
+ * the body, nor will it write to it... Operations which require the qstring
+ * to have a size will allocate a new body, and discard this one.
+ *
+ * Returns: the address of the dummy qstring.
+ */
+Inline qstring
+qs_dummy(qstring qs, const char* src, int pos)
+{
+ if (qs == NULL)
+ qs = qs_new() ;
-Inline size_t
-qs_delete(qstring qs, size_t n) ;
+ qs->const_body = src ;
+ qs->len = (src != NULL) ? strlen(src) : 0 ;
+ qs->cp = (pos == 0) ? 0 : qs->len ;
+ qs->size = 0 ;
-/*==============================================================================
- * The Inline functions.
- */
+ return qs ;
+}
/*------------------------------------------------------------------------------
* 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')
+ * Allocates the qstring, if required.
+ *
+ * Returns: address of qstring
*
* NB: asking for 0 bytes will cause a body to be allocated, ready for any
* '\0' !
*
- * NB: has no effect on 'cp' or 'len'.
+ * NB: has no effect on 'cp' or 'len'. (Will be zero if new qstring allocated.)
*/
-Inline size_t
+Inline qstring
qs_need(qstring qs, size_t len)
{
- if (len < qs->size)
- {
- assert(qs->body != NULL) ;
- return qs->size ;
- }
- else
- return qs_alloc(qs, len) ;
+ if ((qs == NULL) || (len >= qs->size))
+ return qs_make_to_length(qs, len) ;
+
+ assert(qs->body != NULL) ;
+ return qs ;
} ;
/*------------------------------------------------------------------------------
* Set 'len' -- allocate or extend body as required.
*
- * Returns: size of the qstring body
- * (which includes the extra space allowed for '\0')
+ * Allocates the qstring, if required.
*
- * NB: asking for 0 bytes will cause a body to be allocated, ready for any
+ * Returns: address of qstring
+ *
+ * NB: setting len == 0 bytes will cause a body to be allocated, ready for any
* '\0' !
*
* NB: has no effect on 'cp' -- even if 'cp' > 'len'.
+ *
+ * NB: if this is a "dummy" qstring, a copy is made of the original body.
*/
-Inline size_t
+Inline qstring
qs_set_len(qstring qs, size_t len)
{
+ qs = qs_need(qs, len) ;
qs->len = len ;
- return qs_need(qs, len) ;
+ return qs ;
} ;
/*------------------------------------------------------------------------------
* Reset contents of qstring.
*
+ * Does nothing if qstring is NULL
+ *
* Sets 'cp' = 'len' = 0. Sets first byte of body (if any) to NULL.
+ *
+ * For "dummy" qstring, discards the body.
*/
Inline void
-qs_set_empty(qstring qs)
+qs_clear(qstring qs)
{
- qs->len = 0 ;
- qs->cp = 0 ;
- if (qs->body != NULL)
- *((char*)qs->body) = '\0' ;
+ if (qs != NULL)
+ {
+ qs->len = 0 ;
+ qs->cp = 0 ;
+ if (qs->size > 0)
+ *((char*)qs->body) = '\0' ;
+ else
+ qs->body = NULL ;
+ } ;
} ;
/*------------------------------------------------------------------------------
@@ -238,31 +294,63 @@ qs_set_empty(qstring qs)
Inline size_t
qs_len(qstring qs)
{
- return qs->len = (qs->body != NULL) ? strlen(qs_chars(qs)) : 0 ;
+ return (qs != NULL) ? (qs->len = (qs->body != NULL) ? strlen(qs_chars(qs))
+ : 0)
+ : 0 ;
} ;
/*------------------------------------------------------------------------------
* Get size of qstring body.
*
- * NB: if no body has been allocated, size = 0
+ * NB: if no body has been allocated, size == 0
+ * if qstring is NULL, size == 0
+ *
+ * NB: if this is a "dummy" qstring, size == 0.
*/
Inline size_t
qs_size(qstring qs)
{
- return qs->size ;
+ return (qs != NULL) ? qs->size : 0 ;
+} ;
+
+/*------------------------------------------------------------------------------
+ * Get address of current end of qstring body -- ie byte at 'len'.
+ *
+ * NB: allocates body if required.
+ *
+ * There will be space for '\0' after 'len', so the address returned
+ * is within the real body of the string.
+ *
+ * NB: if this is a "dummy" qstring, a copy is made of the original body.
+ *
+ * NB: address of qstring may NOT be NULL.
+ */
+Inline void*
+qs_end(qstring qs)
+{
+ if (qs->len >= qs->size)
+ qs_make_to_length(qs, qs->len) ; /* allows for trailing '\0' */
+
+ return (char*)qs->body + qs->len ;
} ;
/*------------------------------------------------------------------------------
* Set '\0' at qs->len -- allocate or extend body as required.
*
- * Returns address of body.
+ * Returns address of body -- NULL if the qstring is NULL
+ *
+ * NB: if this is a "dummy" qstring, a copy is made of the original body.
*/
Inline void*
qs_term(qstring qs)
{
size_t len ;
+
+ if (qs == NULL)
+ return NULL ;
+
if ((len = qs->len) >= qs->size)
- qs_alloc(qs, len) ;
+ qs_make_to_length(qs, len) ;
*qs_chars_at(qs, len) = '\0' ;
@@ -276,10 +364,14 @@ qs_term(qstring qs)
*
* Returns: number of bytes beyond 'cp' that were moved before insert.
*
+ * NB: qstring MUST NOT be NULL
+ *
* NB: if 'cp' > 'len', then sets 'len' = 'cp' first -- which will introduce
* one or more undefined bytes.
*
* NB: the string is NOT re-terminated.
+ *
+ * NB: if this is a "dummy" qstring, a copy is made of the original body.
*/
Inline size_t
qs_insert(qstring qs, const void* src, size_t n)
@@ -308,15 +400,19 @@ qs_insert(qstring qs, const void* src, size_t n)
*
* May increase 'len'. but does not affect 'cp'.
*
+ * NB: qstring MUST NOT be NULL
+ *
* NB: if 'cp' > 'len', then sets 'len' = 'cp' first -- which will introduce
* one or more undefined bytes.
*
* NB: the string is NOT re-terminated.
+ *
+ * NB: if this is a "dummy" qstring, a copy is made of the original body.
*/
Inline void
qs_replace(qstring qs, const void* src, size_t n)
{
- if (qs->len < qs->cp + n)
+ if ((qs->len < qs->cp + n) || (qs->size == 0))
qs_set_len(qs, qs->cp + n) ; /* set len and ensure have space */
if (n > 0)
@@ -330,6 +426,8 @@ qs_replace(qstring qs, const void* src, size_t n)
*
* Returns: number of bytes beyond 'cp' that were moved before insert.
*
+ * NB: qstring MUST NOT be NULL
+ *
* NB: if 'cp' > 'len', then sets 'len' = 'cp' first -- which will introduce
* one or more undefined bytes.
*
@@ -341,6 +439,10 @@ qs_delete(qstring qs, size_t n)
size_t after ;
char* p ;
+ /* Watch out for "dummy" */
+ if (qs->size == 0)
+ qs_make_to_length(qs, qs->len) ;
+
/* If deleting up to or beyond len, then simply set len == cp */
if ((qs->cp + n) >= qs->len)
{
@@ -362,4 +464,5 @@ qs_delete(qstring qs, size_t n)
return after ;
} ;
+
#endif /* _ZEBRA_QSTRING_H */