diff options
Diffstat (limited to 'lib/qstring.c')
-rw-r--r-- | lib/qstring.c | 757 |
1 files changed, 532 insertions, 225 deletions
diff --git a/lib/qstring.c b/lib/qstring.c index 5ca4d868..c7e5b81c 100644 --- a/lib/qstring.c +++ b/lib/qstring.c @@ -19,6 +19,9 @@ * Boston, MA 02111-1307, USA. */ +#include <stdio.h> +#include <ctype.h> + #include "qstring.h" #include "memory.h" @@ -28,131 +31,57 @@ */ /*------------------------------------------------------------------------------ - * Initialise qstring -- allocate if required. - * - * If non-zero len is given, a body is allocated (for at least len + 1). - * - * Returns: address of qstring - * - * NB: assumes initialising a new structure. If not, then caller should - * use qs_reset() or qs_clear(). + * Create a new, empty qs */ extern qstring -qs_init_new(qstring qs, size_t len) +qs_new(void) { - if (qs == NULL) - qs = qs_new() ; - else - memset(qs, 0, sizeof(qstring_t)) ; /* see qs_new() */ - - if (len != 0) - return qs_make_to_length(qs, len) ; - - return qs ; + /* zeroising sets a completely empty qstring -- see qs_init_new() */ + return XCALLOC(MTYPE_QSTRING, sizeof(qstring_t)) ; } ; /*------------------------------------------------------------------------------ - * Allocate or reallocate so that string is big enough for the given length. + * Initialise qstring -- allocate if required. * - * Allocate qstring if required. Returns with a body with size > 0. + * If non-zero slen is given, a body is allocated (for at least slen + 1). + * If zero slen is given, no body is allocated. * - * Allocates to 16 byte boundaries with space for '\0' beyond given length. + * Sets qs->len = qs->cp = 0. '\0' terminates body if allocates one. * * Returns: address of qstring * - * NB: allocates new body if the size == 0. - * - * If the qstring is a "dummy", its contents are now copied to the new - * real qstring body -- up to a maximum of the new length. + * NB: assumes initialising a new structure. If not, then caller should + * use qs_reset() or qs_clear(). */ extern qstring -qs_make_to_length(qstring qs, size_t len) +qs_init_new(qstring qs, usize slen) { - size_t size = (len + 0x10) & ~(size_t)(0x10 - 1) ; - if (qs == NULL) qs = qs_new() ; + else + memset(qs, 0, sizeof(qstring_t)) ; - if (size > qs->size) - { - if (qs->size == 0) - { - void* old ; - old = qs->body ; - - qs->size = size ; - qs->body = XMALLOC(MTYPE_QSTRING_BODY, qs->size) ; - - if ((qs->len != 0) && (old != NULL)) - memcpy(qs->body, old, (qs->len <= len) ? qs->len : len) ; - } - else - { - qs->size *= 2 ; - if (qs->size < size) - qs->size = size ; - qs->body = XREALLOC(MTYPE_QSTRING_BODY, qs->body, qs->size) ; - } ; - }; - - return qs ; -} ; - -/*------------------------------------------------------------------------------ - * Add 'n' to the current string length, allocating or extending the body as - * required. - * - * Allocate qstring if required. Returns with a body with size > 0. - * - * Allocates to 16 byte boundaries with space for '\0' beyond new length. - * - * Returns: address of qstring - * - * also: sets char** p_ep to point at the *end* of the new len. - * - * NB: allocates new body if the size == 0. - * - * If the qstring is a "dummy", its contents are now copied to the new - * real qstring body -- up to a maximum of the new length. - */ -extern qstring -qs_add_len(qstring qs, size_t n, char** p_ep) -{ - size_t len ; - len = (qs != NULL) ? qs->len + n : n ; - - qs = qs_make_to_length(qs, len) ; + confirm(QSTRING_INIT_ALL_ZEROS) ; - qs->len = len ; + /* Zeroising has set: + * + * body = NULL -- no body + * size = 0 -- no body + * + * len = 0 + * cp = 0 + * + * b_body = NULL -- no body buffer + * b_size = 0 -- no body buffer + */ - *p_ep = (char*)qs->body + len ; + if (slen != 0) + qs_make_to_size(qs, slen, false) ; return qs ; } ; /*------------------------------------------------------------------------------ - * Free body of qstring -- zeroise size, len and cp - * - * Does nothing if qstring is NULL - * - * NB: frees the body if the size != 0. So, a "dummy" qstring will not retain - * the old body. - */ -extern void -qs_free_body(qstring qs) -{ - if (qs != NULL) - { - if (qs->size != 0) - XFREE(MTYPE_QSTRING_BODY, qs->body) ; /* sets qs->body = NULL */ - - qs->size = 0 ; - qs->len = 0 ; - qs->cp = 0 ; - } ; -} ; - -/*------------------------------------------------------------------------------ * Reset qstring -- free body and, if required, free the structure. * * If not freeing the structure, zeroise size, len and cp -- qs_free_body() @@ -164,110 +93,97 @@ qs_free_body(qstring qs) * the old body. */ extern qstring -qs_reset(qstring qs, int free_structure) +qs_reset(qstring qs, free_keep_b free_structure) { if (qs != NULL) { - if (qs->size != 0) - XFREE(MTYPE_QSTRING_BODY, qs->body) ; /* sets qs->body = NULL */ + if (qs->b_body != NULL) + XFREE(MTYPE_STRING, qs->b_body) ; /* sets qs->b_body = NULL */ if (free_structure) - XFREE(MTYPE_QSTRING, qs) ; /* sets qs = NULL */ + XFREE(MTYPE_QSTRING, qs) ; /* sets qs = NULL */ else - { - qs->size = 0 ; - qs->len = 0 ; - qs->cp = 0 ; - } ; + memset(qs, 0, sizeof(qstring_t)) ; /* see qs_init_new */ } ; return qs ; } ; -/*============================================================================== - * printf() and vprintf() type functions - */ - /*------------------------------------------------------------------------------ - * Formatted print to qstring -- cf printf() + * Allocate or reallocate body so that is big enough for the given "slen". * - * Allocate qstring if required. + * If the qstring is currently an alias, copies all of the alias to a new + * body -- so always returns a non-alias qstring. * - * Returns: address of qstring if OK - * NULL if failed (unlikely though that is) - */ -extern qstring -qs_printf(qstring qs, const char* format, ...) -{ - va_list args; - - va_start (args, format); - qs = qs_vprintf(qs, format, args); - va_end (args); - - return qs; -} ; - -/*------------------------------------------------------------------------------ - * Formatted print to qstring -- cf vprintf() + * Returns with a body with size > 0. Allocates to 16 byte boundaries with + * space for '\0' beyond given length. * - * Allocate qstring if required. + * Does NOT affect qs->len or qs->cp. Does NOT re-terminate. * - * Returns: address of qstring if OK - * NULL if failed (unlikely though that is) + * NB: will allocate a new body even if the slen == 0. + * + * NB: always copies all of any aliased string (even if the slen == 0). + * + * NB: sets terminated false */ -extern qstring -qs_vprintf(qstring qs, const char *format, va_list args) +Private void +qs_make_to_size(qstring qs, usize slen, bool keep) { - va_list ac ; - int len ; - qstring qqs ; - - qqs = qs ; - if (qs == NULL) - qs = qs_new() ; + usize size ; + usize alen ; - while (1) + /* Worry about alias. If we keep it, we keep all of it. */ + if (keep && (qs->size == 0)) { - /* Note that vsnprintf() returns the length of what it would like to have - * produced, if it had the space. That length does not include the - * trailing '\0'. - * - * Also note that given a zero length the string address may be NULL, and - * the result is still the length required. - */ - va_copy(ac, args); - qs->len = len = vsnprintf (qs->body, qs->size, format, ac) ; - va_end(ac); - - if (len < 0) - break ; + alen = qs_len_nn(qs) ; /* alias stuff to keep */ + if (slen <= alen) + slen = alen + 1 ; /* making sure can do that. */ + } + else + alen = 0 ; /* no alias stuff to keep */ - if (len < (int)qs->size) - return qs ; + /* Calculate the new size -- multiple of 16, >= 16. */ + size = (slen + 0x10) & ~(usize)(0x10 - 1) ; + dassert(size != 0) ; - qs_make_to_length(qs, len) ; + /* If that requires the body to be extended, do that now */ + if (size > qs->b_size) + { + /* Need to allocate or extend the buffer. + * + * If current size is not zero, extend by doubling size or making at + * least the multiple of 16 calculated for new len. + */ + qs->b_size *= 2 ; + if (qs->b_size < size) + qs->b_size = size ; + qs->b_body = XREALLOC(MTYPE_STRING, qs->b_body, qs->b_size) ; } ; - if (qqs == NULL) - qs_reset_free(qs) ; /* discard what was allocated */ - else - qs->len = 0 ; + /* If this is a non-empty alias, copy all or part of it. */ + if (alen != 0) + memcpy(qs->b_body, qs_body_nn(qs), alen) ; + + /* Update body and size, and no longer known to be terminated */ + qs_set_body_nn(qs, qs->b_body) ; + qs->size = qs->b_size ; + - return NULL ; } ; /*============================================================================== - * Other operations + * Setting value of qstring */ /*------------------------------------------------------------------------------ * Set qstring to be copy of the given string. * - * Allocates a qstring, if required. + * Allocate qstring if required (setting qs->len = qs->cp = 0). * - * Sets qs->len to the length of the string (excluding trailing '\0') + * Allocates a body and copies src to it, adding '\0'. Treats src == NULL as + * an empty string. * - * NB: if src == NULL, sets qstring to be zero length string. + * Sets qs->len to the length of the string (excluding trailing '\0'). + * Sets qs->cp == 0. * * Returns: address of the qstring copied to. * @@ -276,101 +192,97 @@ qs_vprintf(qstring qs, const char *format, va_list args) extern qstring qs_set(qstring qs, const char* src) { - qs = qs_set_len(qs, (src != NULL) ? strlen(src) : 0) ; - if (qs->len != 0) - memcpy(qs->body, src, qs->len + 1) ; - else - *((char*)qs->body) = '\0' ; - - return qs ; + return qs_set_n(qs, src, (src != NULL ? strlen(src) : 0)) ; } ; /*------------------------------------------------------------------------------ * Set qstring to be leading 'n' bytes of given string. * - * Allocates qstring if required. + * Allocate qstring if required (setting qs->len = qs->cp = 0). * - * Inserts '\0' terminator after the 'n' bytes copied. + * Allocates a body and copies 'n' bytes from src to it, adding '\0'. The + * src pointer is ignored if n == 0. + * + * Sets qs->len to the length of the string (excluding trailing '\0'). + * Sets qs->cp == 0. * * Returns: address of the qstring copied to. * - * NB: src string MUST be at least 'n' bytes long. + * NB: if n == 0, src may be NULL * - * NB: src may not be NULL unless n == 0. + * NB: if n > 0, src string MUST be at least 'n' bytes long. * * NB: if copying to a dummy qstring, the old body is simply discarded. */ extern qstring -qs_set_n(qstring qs, const char* src, size_t n) +qs_set_n(qstring qs, const char* src, usize len) { - qs = qs_set_len(qs, n) ; /* ensures have body > n */ - if (n != 0) - memcpy(qs->body, src, n) ; + char* p ; + + qs = qs_new_len(qs, len) ; /* ensures have body > n */ + + p = qs_char_nn(qs) ; + + if (len != 0) + memcpy(p, src, len) ; + + *(p + len) = '\0' ; - *((char*)qs->body + n) = '\0' ; + qs_set_term_nn(qs, true) ; + qs->cp = 0 ; return qs ; } ; /*------------------------------------------------------------------------------ - * Append given string to a qstring. + * Append given string to a qstring -- adding at qs->len position. * - * Allocates a qstring, if required. + * Allocate qstring if required (setting qs->len = qs->cp = 0). * - * Sets qs->len to the length of the result (excluding trailing '\0') + * Allocates or extends the body and copies bytes from src to it, adding '\0'. + * Treats src == NULL as an empty string. * - * NB: if src == NULL, appends nothing -- but result will be '\0' terminated. + * Sets qs->len to the length of the result (excluding trailing '\0') + * Does not change qs->cp. * - * Returns: address of the qstring copied to. + * Returns: address of the qstring appended to. * - * NB: if copying to a dummy qstring, the old body is simply discarded. + * NB: if appending to a dummy qstring, the old body is copied first. */ extern qstring qs_append(qstring qs, const char* src) { - size_t n ; - char* ep ; - - n = (src != NULL) ? strlen(src) : 0 ; - - qs = qs_add_len(qs, n, &ep) ; - ep = (char*)qs->body + qs->len ; - - if (n != 0) - memcpy(ep - n, src, n + 1) ; - else - *ep = '\0' ; - - return qs ; + return qs_append_n(qs, src, (src != NULL) ? strlen(src) : 0) ; } ; /*------------------------------------------------------------------------------ - * Set qstring to be leading 'n' bytes of given string. + * Append leading 'n' bytes of given string to a qstring -- adding at qs->len + * position. * - * Allocates qstring if required. + * Allocate qstring if required (setting qs->len = qs->cp = 0). * - * Returns: address of the qstring copied to. + * Allocates or extends the body and copies 'n' bytes from src to it, + * adding '\0'. The src pointer is ignored if n == 0. * - * NB: src string MUST be at least 'n' bytes long. + * Sets qs->len to the length of the result (excluding trailing '\0') + * Does not change qs->cp. * - * NB: src may not be NULL unless n == 0. + * Returns: address of the qstring appended to. * - * NB: if n == 0, appends nothing -- but result will be '\0' terminated. + * NB: if n == 0, src may be NULL * - * NB: if copying to a dummy qstring, the old body is simply discarded. + * NB: if n > 0, src string MUST be at least 'n' bytes long. * - * NB: if copying to a dummy qstring, the old body is simply discarded. + * NB: if appending to a dummy qstring, the old body is copied first. */ extern qstring -qs_append_n(qstring qs, const char* src, size_t n) +qs_append_n(qstring qs, const char* src, usize n) { char* ep ; qs = qs_add_len(qs, n, &ep) ; if (n != 0) - memcpy(ep - n, src, n) ; - - *ep = '\0' ; + memcpy(ep, src, n) ; return qs ; } ; @@ -398,7 +310,7 @@ qs_append_n(qstring qs, const char* src, size_t n) extern qstring qs_copy(qstring dst, qstring src) { - size_t n ; + usize n ; if (src == NULL) { @@ -417,17 +329,263 @@ qs_copy(qstring dst, qstring src) dst->cp = src->cp ; } ; - qs_set_len(dst, n) ; + qs_set_len(dst, n) ; /* TODO: Copies alias !! */ if (n > 0) - memcpy(dst->body, src->body, n) ; + memcpy(dst->s.body, src->s.body, n) ; - *((char*)dst->body + n) = '\0' ; + *(dst->s.char_body + n) = '\0' ; return dst ; } ; /*------------------------------------------------------------------------------ + * Construct a qstring which is an alias for the given string. + * + * Allocates a qstring if required. + * + * Given string must be '\0' terminated. + * + * Does NOT copy the given string, but sets the qstring to be a pointer to it. + * + * NB: it is the caller's responsibility to ensure that the original string + * stays put for however long the qstring is an alias for it. + * + * It is also the caller's responsibility to see that the original string + * is discarded as required (once the alias is no longer required.) + * + * NB: if the qstring is changed in any way, a copy of the aliased string will + * be made first. + * + * NB: if a pointer to the body of the qstring is taken, then while that is in + * use, the qstring must not be released, so that the alias is not + * released. + * + * Returns: the address of the qstring. + */ +extern qstring +qs_set_alias(qstring qs, const char* src) +{ + if (qs == NULL) + qs = qs_init_new(NULL, 0) ; + + /* Make the alias. Note that any existing b_body and b_size are preserved, + * so that any current body can be reused at a later date. + */ + qs->s.const_body = (src != NULL) ? src : "" ; + qs->len = strlen(src) ; + qs->cp = 0 ; + qs->size = 0 ; /* <=> this is an alias ! */ + qs->terminated = true ; + + return qs ; +} ; + +/*------------------------------------------------------------------------------ + * Construct a qstring which is an alias for the 'n' given characters. + * + * Allocates a qstring if required. + * + * Given characters are assumed not to be '\0' terminated. + * + * Does NOT copy the given characters, but sets the qstring to be a pointer to + * them. + * + * NB: it is the caller's responsibility to ensure that the original characters + * stays put for however long the qstring is an alias for them. + * + * It is also the caller's responsibility to see that the original + * characters are discarded as required (once the alias is no longer + * required.) + * + * NB: if the qstring is changed in any way, a copy of the aliased characters + * will be made first. + * + * NB: if a pointer to the body of the qstring is taken, then while that is in + * use, the qstring must not be released, so that the alias is not + * released. + * + * Returns: the address of the qstring. + */ +extern qstring +qs_set_alias_n(qstring qs, const char* src, usize len) +{ + if (qs == NULL) + qs = qs_init_new(NULL, 0) ; + + if (len == 0) + src = "" ; + else + assert(src != NULL) ; + + /* Make the alias. Note that any existing b_body and b_size are preserved, + * so that any current body can be reused at a later date. + */ + qs->s.const_body = src ; + qs->len = len ; + qs->cp = 0 ; + qs->size = 0 ; /* <=> this is an alias ! */ + qs->terminated = false ; + + return qs ; +} ; + + + + + + + + + + + + + + + +/*------------------------------------------------------------------------------ + * Add 'n' to the current string length, allocating or extending the body. + * + * Allocate qstring if required (setting qs->len = qs->cp = 0). + * + * Returns with a body with size > 0. Allocates to 16 byte boundaries with + * space for '\0' beyond given length. + * + * Does NOT affect qs->cp. + * Does set the new qs->len -- qs->len += n + * Does NOT reterminate. + * + * Returns: address of qstring + * + * also: sets char** p_ep to point at the *end* of the old len. + * + * NB: will allocate a new body even if the new len == 0. + * + * NB: always copies all of any aliased string (even if the slen == 0). + */ +extern qstring +qs_add_len(qstring qs, usize n, char** p_ep) +{ + usize slen ; + usize len ; + + len = qs_len(qs) ; + slen = len + n ; + + /* Set the new length -- creating if required. + * + * Will always return with a body and no longer an alias (if was one). + */ + qs = qs_set_len(qs, slen) ; + + /* Set pointer to old end (len) position. */ + *p_ep = ((char*)qs_body_nn(qs)) + len ; + + return qs ; +} ; + +/*============================================================================== + * printf() and vprintf() type functions + */ + +/*------------------------------------------------------------------------------ + * Formatted print to qstring -- cf printf() + * + * Allocate qstring if required (setting qs->len = qs->cp = 0). + * + * If OK: + * + * Sets qs->len to the length of the null terminated result. + * Does NOT affect qs->cp. + * + * If fails: + * + * Sets qs->len = qs->cp = 0 and terminates to zero length. + * + * Returns: address of qstring if OK + * NULL if failed (unlikely though that is) -- qstring set empty. + */ +extern qstring +qs_printf(qstring qs, const char* format, ...) +{ + va_list args; + + va_start (args, format); + qs = qs_vprintf(qs, format, args); + va_end (args); + + return qs; +} ; + +/*------------------------------------------------------------------------------ + * Formatted print to qstring -- cf vprintf() + * + * Allocate qstring if required (setting qs->len = qs->cp = 0). + * + * If OK: + * + * Sets qs->len to the length of the null terminated result. + * Does NOT affect qs->cp. + * + * If fails: + * + * Sets qs->len = qs->cp = 0 and terminates to zero length. + * + * Returns: address of qstring if OK + * NULL if failed (unlikely though that is) + */ +extern qstring +qs_vprintf(qstring qs, const char *format, va_list args) +{ + va_list ac ; + int slen ; + qstring qqs ; + + qqs = qs ; + if (qs == NULL) + qs = qs_new() ; /* sets size == 0 */ + else + qs_set_len_nn(qs, 0) ; /* Forget current contents */ + + while (1) + { + /* Note that vsnprintf() returns the length of what it would like to have + * produced, if it had the space. That length does not include the + * trailing '\0'. + * + * Also note that given a zero length the string address may be NULL, and + * the result is still the length required. + */ + va_copy(ac, args); + slen = vsnprintf (qs_body_nn(qs), qs->size, format, ac) ; + va_end(ac); + + if (slen < 0) + break ; /* Quit if failed */ + + if ((usize)slen < qs->size) + { + qs_set_len_nn(qs, slen) ; + return qs ; /* Exit if succeeded */ + } ; + + qs_make_to_size(qs, slen) ; /* Extend body to required len */ + } ; + + if (qqs == NULL) + qs_reset(qs, free_it) ; /* discard what was allocated */ + else + qs_clear(qs) ; + + return NULL ; +} ; + +/*============================================================================== + * Other operations + */ + +/*------------------------------------------------------------------------------ * Compare significant parts of two qstrings. * * By significant, mean excluding leading/trailing isspace() and treating @@ -455,7 +613,7 @@ qs_cmp_sig(qstring a, qstring b) */ if (a != NULL) { - p_a = a->body ; + p_a = a->s.uchar_body ; e_a = p_a + a->len ; while ((p_a < e_a) && isspace(*p_a)) @@ -471,7 +629,7 @@ qs_cmp_sig(qstring a, qstring b) if (b != NULL) { - p_b = b->body ; + p_b = b->s.uchar_body ; e_b = p_b + b->len ; while ((p_b < e_b) && isspace(*p_b)) @@ -509,3 +667,152 @@ qs_cmp_sig(qstring a, qstring b) else return 0 ; } ; + +/*------------------------------------------------------------------------------ + * 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: 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 aliased qstring, a copy is made of the original body. + */ +extern usize +qs_insert(qstring qs, const void* src, usize n) +{ + usize after ; + usize len ; + char* p ; + + qs->terminated = false ; /* NB: require qs != NULL ! */ + + len = qs_len_nn(qs) ; + if (len < qs->cp) /* make len = max(len, cp) ! */ + len = qs->cp ; + + after = len - qs->cp ; + + qs_set_len(qs, len + n) ; /* set len and ensure have space + Makes copy of any aliased string. */ + 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: 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 aliased qstring, a copy is made of the original body. + */ +extern void +qs_replace(qstring qs, const void* src, usize n) +{ + usize len ; + + qs->terminated = false ; /* NB: require qs != NULL ! */ + + len = qs_len_nn(qs) ; + if (len < (qs->cp + n)) /* make len = max(len, cp + n) */ + len = qs->cp + n ; + + qs_set_len(qs, len) ; /* set len and ensure have space. + Makes copy of any aliased string. */ + + 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: 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 aliased qstring, a copy is made of the original body. + */ +extern usize +qs_delete(qstring qs, usize n) +{ + usize after ; + char* p ; + usize len ; + + qs->terminated = false ; /* NB: require qs != NULL ! */ + + len = qs_len_nn(qs) ; + + /* If deleting to or beyond 'len', force len to cp */ + if ((qs->cp + n) >= len) + { + len = qs->cp ; + qs_set_len_nn(qs, len) ; /* truncate now, so that if this is an + aliased string, only copy what is + going to be kept. */ + after = 0 ; /* nothing to move */ + } + else + after = len - (qs->cp + n) ; + + qs_set_len(qs, len) ; /* set len and ensure have space. + Makes copy of any aliased string. */ + + + + /* Watch out for "dummy" */ + if (qs->size == 0) + qs_make_to_size(qs, len) ; + + /* If deleting up to or beyond len, then simply set len == cp + * note that this may reduce or increase len ! + */ + if ((qs->cp + n) >= len) + { + if (qs->cp < len) + qs_set_len_nn(qs, qs->cp) ; /* discard stuff after qs->cp */ + + qs_set_len(qs, qs->cp) ; /* set len */ + return 0 ; /* nothing after */ + } + + /* There is at least one byte after cp (so body must exist) */ + after = len - (qs->cp + n) ; + + if (n > 0) + { + p = qs_cp_char(qs) ; + memmove (p, p + n, after) ; + + qs_set_len_nn(qs, len - n) ; + } ; + + return after ; +} ; |