From 9de2e02418df7db9d4eab50250014155acbe3c29 Mon Sep 17 00:00:00 2001 From: H Hautakoski Date: Sun, 12 Sep 2010 13:32:20 +0200 Subject: [PATCH] common/strbuf: "\0" pointer for new buffers and squeeze. --- TODO | 3 -- src/common/strbuf.c | 128 ++++++++++++++++++++++++++++++-------------- src/common/strbuf.h | 24 ++++++--- test/t_strbuf.c | 55 +++++++++++++++---- 4 files changed, 150 insertions(+), 60 deletions(-) diff --git a/TODO b/TODO index f5950ae..0523655 100644 --- a/TODO +++ b/TODO @@ -6,8 +6,5 @@ * Use queue in inotify_read(), tree and remove indexer * path: * normalize - * strbuf: - * "\0" default string. - * strbuf_squeeze: squeeze repeated characters into one. * ini-like config support * fix mysql module diff --git a/src/common/strbuf.c b/src/common/strbuf.c index beeee10..d859c07 100644 --- a/src/common/strbuf.c +++ b/src/common/strbuf.c @@ -9,42 +9,50 @@ */ #include +#include #include #include #include "strbuf.h" #define CHNK_SIZE 128 -static void buf_expand(strbuf_t *s, size_t l) { +char strbuf_null = '\0'; - if (l <= s->alloc_size) - return; +static void* xrealloc(void *ptr, size_t size) { - do - s->alloc_size += CHNK_SIZE; - while(l > s->alloc_size); - - s->buf = realloc(s->buf, s->alloc_size); - assert(s->buf != NULL); + assert(size); + ptr = realloc(ptr, size); + assert(ptr != NULL); + return ptr; +} + +static void* xcalloc(size_t nmemb, size_t size) { + + assert(nmemb); + assert(size); + void *ptr = calloc(nmemb, size); + assert(ptr != NULL); + return ptr; } void strbuf_init(strbuf_t *s) { - s->buf = NULL; - s->len = 0; - s->alloc_size = 0; + s->buf = &strbuf_null; + s->alloc_size = s->len = 0; } -void strbuf_append(strbuf_t *s, char *str, size_t len) { +void strbuf_expand(strbuf_t *s, size_t len) { - if (str == NULL) + if (s->len + len + 1 < s->alloc_size) return; + if (!s->alloc_size) + s->buf = NULL; - buf_expand(s, s->len + len + 1); + do + s->alloc_size += CHNK_SIZE; + while(s->len + len + 1 > s->alloc_size); - memcpy(s->buf + s->len, str, len); - s->len += len; - s->buf[s->len] = '\0'; + s->buf = xrealloc(s->buf, s->alloc_size); } void strbuf_reduce(strbuf_t *s, size_t len) { @@ -56,6 +64,51 @@ void strbuf_reduce(strbuf_t *s, size_t len) { s->buf[s->len] = '\0'; } +char* strbuf_release(strbuf_t *s) { + + char *ret; + + if (!s->alloc_size) + ret = xcalloc(1, 1); + else if (s->len + 1 != s->alloc_size) + ret = xrealloc(s->buf, s->len + 1); + else + ret = s->buf; + + strbuf_init(s); + + return ret; +} + +void strbuf_free(strbuf_t *s) { + + if (!s->alloc_size) + return; + + free(s->buf); + strbuf_init(s); +} + +void strbuf_append(strbuf_t *s, void *ptr, size_t len) { + + strbuf_expand(s, len); + memcpy(s->buf + s->len, ptr, len); + s->len += len; + s->buf[s->len] = '\0'; +} + +void strbuf_append_str(strbuf_t *s, char *str) { + + strbuf_append(s, str, strlen(str)); +} + +void strbuf_append_ch(strbuf_t *s, char ch) { + + strbuf_expand(s, 1); + s->buf[s->len++] = ch; + s->buf[s->len] = '\0'; +} + void strbuf_trim(strbuf_t *s) { strbuf_rtrim(s); @@ -64,7 +117,7 @@ void strbuf_trim(strbuf_t *s) { void strbuf_rtrim(strbuf_t *s) { - for(; s->len > 0 && isspace(s->buf[s->len-1]); s->len--); + for(; s->len && isspace(s->buf[s->len-1]); s->len--); s->buf[s->len] = '\0'; } @@ -93,27 +146,20 @@ void strbuf_rev(strbuf_t *s) { } } -char* strbuf_release(strbuf_t *s) { +void strbuf_squeeze(strbuf_t *s, char ch) { - char *ret; - - if (s->len + 1 != s->alloc_size) { - ret = realloc(s->buf, s->len + 1); - assert(ret != NULL); - } else { - ret = s->buf; - } - - strbuf_init(s); - - return ret; + size_t p; + + for(p=s->len; p; p--) { + + if (s->buf[p] != ch) + continue; + + size_t np = p, of = 0; + + for(; np >= 1 && s->buf[np-1] == ch; np--) + of++; + for(s->len -= of; np <= s->len; np++) + s->buf[np] = s->buf[np + of]; + } } - -void strbuf_free(strbuf_t *s) { - - if (s->alloc_size > 0) - free(s->buf); - s->buf = NULL; -} - - diff --git a/src/common/strbuf.h b/src/common/strbuf.h index 6c74741..187a4de 100644 --- a/src/common/strbuf.h +++ b/src/common/strbuf.h @@ -11,9 +11,7 @@ #ifndef __COMMON_STRBUF_H #define __COMMON_STRBUF_H -#include - -#define STRBUF_INIT { 0, 0, NULL } +#include typedef struct { size_t alloc_size; @@ -21,12 +19,26 @@ typedef struct { char *buf; } strbuf_t; +extern char strbuf_null; + +#define STRBUF_INIT { 0, 0, &strbuf_null } + void strbuf_init(strbuf_t *s); -void strbuf_append(strbuf_t *s, char *str, size_t len); +void strbuf_expand(strbuf_t *s, size_t len); void strbuf_reduce(strbuf_t *s, size_t len); +char* strbuf_release(strbuf_t *s); + +void strbuf_free(strbuf_t *s); + +void strbuf_append(strbuf_t *s, void *ptr, size_t len); + +void strbuf_append_str(strbuf_t *s, char *str); + +void strbuf_append_ch(strbuf_t *s, char ch); + void strbuf_trim(strbuf_t *s); void strbuf_rtrim(strbuf_t *s); @@ -35,8 +47,6 @@ void strbuf_ltrim(strbuf_t *s); void strbuf_rev(strbuf_t *s); -char* strbuf_release(strbuf_t *s); - -void strbuf_free(strbuf_t *s); +void strbuf_squeeze(strbuf_t *s, char ch); #endif /* __COMMON_STRBUF_H */ diff --git a/test/t_strbuf.c b/test/t_strbuf.c index 6ad14b6..ef2ff74 100644 --- a/test/t_strbuf.c +++ b/test/t_strbuf.c @@ -1,20 +1,50 @@ #include #include +#include #include #include "../src/common/strbuf.h" +typedef unsigned int uint; + void print_strbuf(strbuf_t *s) { assert(s->len == strlen(s->buf)); - printf("block: %i, len: %i |%s|\n", s->alloc_size, s->len, s->buf); + printf("block: %u, len: %u |%s|\n", (uint)s->alloc_size, (uint)s->len, s->buf); } -int main() { +void test_release_empty() { strbuf_t b = STRBUF_INIT; - char *str; + + char *ptr = strbuf_release(&b); + + assert(*ptr == '\0'); + + free(ptr); +} + +void test_squeeze() { + + strbuf_t b = STRBUF_INIT; + + strbuf_append_str(&b, "aaabXXXcdefXXXXghijklXXmmmnopXXXXXqrstuXXvwxyXXz"); + strbuf_squeeze(&b, 'X'); + print_strbuf(&b); + strbuf_free(&b); + + strbuf_append_str(&b, "XXXX"); + strbuf_squeeze(&b, 'X'); + print_strbuf(&b); + strbuf_free(&b); +} + +void test() { + + strbuf_t b = STRBUF_INIT; + + print_strbuf(&b); strbuf_append(&b, " ", 4); strbuf_append(&b, "abcdef", 6); @@ -22,7 +52,8 @@ int main() { print_strbuf(&b); strbuf_append(&b, "012345678901234567890123456789", 30); - strbuf_append(&b, " ", 6); + strbuf_append_ch(&b, 'a'); + strbuf_append_str(&b, " "); print_strbuf(&b); @@ -46,15 +77,21 @@ int main() { print_strbuf(&b); - strbuf_reduce(&b, 95); - - print_strbuf(&b); - - str = strbuf_release(&b); + /* testing release */ + char *str = strbuf_release(&b); printf("released |%s|\n", str); free(str); +} +int main() { + + test(); + + test_release_empty(); + + test_squeeze(); + return 0; }