summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpiaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2009-10-25 13:59:15 +0800
committerpiaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2009-10-25 13:59:15 +0800
commit59cb003519acc846fc6b8700a9b8a082d409d954 (patch)
treead9ef8268393733039116a6a7893acfaf673782f
parent9c2d6734454995d1785ee45c991b0592097181eb (diff)
downloadpttbbs-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.c94
-rw-r--r--pttbbs/include/cmsys.h1
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)