diff options
author | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2009-10-25 13:59:15 +0800 |
---|---|---|
committer | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2009-10-25 13:59:15 +0800 |
commit | 59cb003519acc846fc6b8700a9b8a082d409d954 (patch) | |
tree | ad9ef8268393733039116a6a7893acfaf673782f | |
parent | 9c2d6734454995d1785ee45c991b0592097181eb (diff) | |
download | pttbbs-59cb003519acc846fc6b8700a9b8a082d409d954.tar pttbbs-59cb003519acc846fc6b8700a9b8a082d409d954.tar.gz pttbbs-59cb003519acc846fc6b8700a9b8a082d409d954.tar.bz2 pttbbs-59cb003519acc846fc6b8700a9b8a082d409d954.tar.lz pttbbs-59cb003519acc846fc6b8700a9b8a082d409d954.tar.xz pttbbs-59cb003519acc846fc6b8700a9b8a082d409d954.tar.zst pttbbs-59cb003519acc846fc6b8700a9b8a082d409d954.zip |
* add cstr() (flattern) to vbuf
git-svn-id: http://opensvn.csie.org/pttbbs/trunk@4988 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
-rw-r--r-- | pttbbs/common/sys/vbuf.c | 94 | ||||
-rw-r--r-- | pttbbs/include/cmsys.h | 1 |
2 files changed, 76 insertions, 19 deletions
diff --git a/pttbbs/common/sys/vbuf.c b/pttbbs/common/sys/vbuf.c index e4c2f30a..4e000fdd 100644 --- a/pttbbs/common/sys/vbuf.c +++ b/pttbbs/common/sys/vbuf.c @@ -5,7 +5,7 @@ // // Author: Hung-Te Lin (piaip) // Create: Sat Oct 24 22:44:00 CST 2009 -// An implementation from scratch, with the API names inspired by vrb +// An implementation from scratch, with the API names inspired by STL and vrb // --------------------------------------------------------------------------- // Copyright (c) 2009 Hung-Te Lin <piaip@csie.org> // All rights reserved. @@ -179,6 +179,8 @@ vbuf_strchr(VBUF *v, char c) return EOF; } +// NOTE: VBUF_*_SZ may return a size larger than capacity, so you must check +// buffer availablity before using these macro. #define VBUF_TAIL_SZ(v) ((v->head >= v->tail) ? v->head - v->tail : v->buf_end - v->tail) #define VBUF_HEAD_SZ(v) ((v->tail > v->head) ? v->tail - v->head : v->buf_end - v->head) @@ -206,28 +208,45 @@ vbuf_getblk(VBUF *v, void *p, size_t sz) return 1; } -// put data into vbuf -VBUFPROTO int -vbuf_putblk(VBUF *v, const void *p, size_t sz) +static void +vbuf_reverse(char *begin, char *end) { - size_t rw, i; - const char *s = p; - if (!sz || vbuf_space(v) < sz) - return 0; + char c; - // two phase - for (i = 0; sz && i < 2; i++) + assert(begin <= end); + while (begin < end) { - rw = VBUF_HEAD_SZ(v); - assert(rw >= 0 && rw <= v->capacity+1); - if (rw > sz) rw = sz; - memcpy(v->head, s, rw); - v->head += rw; s += rw; sz -= rw; - if (v->head == v->buf_end) - v->head = v->buf; + c = *--end; + *end = *begin; + *begin++ = c; } - assert(sz == 0); - return 1; +} + +VBUFPROTO char * +vbuf_cstr (VBUF *v) +{ + size_t sz; + if (vbuf_is_empty(v)) + return NULL; + + // if the buffer is cstr safe, simply return + if (v->head > v->tail) + { + *v->head = 0; + return v->tail; + } + + // wrapped ring buffer. now reverse 3 times to merge: + // [buf head tail buf_end] + sz = vbuf_size(v); + vbuf_reverse(v->buf, v->head); + vbuf_reverse(v->tail, v->buf_end); + memmove(v->head, v->tail, v->buf_end - v->tail); + v->tail = v->buf; + v->head = v->buf + sz; + v->buf[sz] = 0; + vbuf_reverse(v->tail, v->head); + return v->buf; } char * @@ -259,6 +278,30 @@ vbuf_putstr (VBUF *v, char *s) return 1; } +// put data into vbuf +VBUFPROTO int +vbuf_putblk(VBUF *v, const void *p, size_t sz) +{ + size_t rw, i; + const char *s = p; + if (!sz || vbuf_space(v) < sz) + return 0; + + // two phase + for (i = 0; sz && i < 2; i++) + { + rw = VBUF_HEAD_SZ(v); + assert(rw >= 0 && rw <= v->capacity+1); + if (rw > sz) rw = sz; + memcpy(v->head, s, rw); + v->head += rw; s += rw; sz -= rw; + if (v->head == v->buf_end) + v->head = v->buf; + } + assert(sz == 0); + return 1; +} + /* read/write callbacks */ static ssize_t @@ -498,6 +541,19 @@ int main() printf("put/getstr(%d): %s\n", i+1, s ? s : "(NULL)"); } + vbuf_clear(v); + vbuf_putstr(v, "1234567890ABCDEFGHIJK"); + vbuf_rpt(v); + printf("cstr test(simple): %s\n", vbuf_cstr(v)); + vbuf_clear(v); + for (i = 0; i < 4; i++) { + char xbuf[256]; + vbuf_putstr(v, "1234567890"); + vbuf_getstr(v, xbuf, sizeof(xbuf)); + } + vbuf_putstr(v, "1234567890ABCDEFGHIJK"); + vbuf_rpt(v); + printf("cstr test(unwrap): %s\n", vbuf_cstr(v)); getchar(); return 0; diff --git a/pttbbs/include/cmsys.h b/pttbbs/include/cmsys.h index 4bc239f1..bebf87cf 100644 --- a/pttbbs/include/cmsys.h +++ b/pttbbs/include/cmsys.h @@ -215,6 +215,7 @@ extern int vbuf_strchr(VBUF *v, char c); // index of first location of c, // vector of C-style NULL terminated strings extern char* vbuf_getstr(VBUF *v, char *s, size_t sz); // get a string from vbuf, return NULL if empty extern int vbuf_putstr(VBUF *v, char *s); // put a string to vbuf (with NUL), return true/false +extern char *vbuf_cstr (VBUF *v); // return flattern (unwrap) buffer and pad NUL, or NULL if empty. #define VBUF_RWSZ_ALL (0) // r/w until buffer full #define VBUF_RWSZ_MIN (-1) // r/w for minimal try (do not block for more) |