diff options
-rw-r--r-- | pttbbs/common/sys/vbuf.c | 101 | ||||
-rw-r--r-- | pttbbs/include/cmsys.h | 18 | ||||
-rw-r--r-- | pttbbs/include/vtuikit.h | 4 | ||||
-rw-r--r-- | pttbbs/mbbsd/vtuikit.c | 16 |
4 files changed, 115 insertions, 24 deletions
diff --git a/pttbbs/common/sys/vbuf.c b/pttbbs/common/sys/vbuf.c index d141ce98..e4c2f30a 100644 --- a/pttbbs/common/sys/vbuf.c +++ b/pttbbs/common/sys/vbuf.c @@ -67,6 +67,14 @@ vbuf_space(VBUF *v) return v->capacity - vbuf_size(v); } +VBUFPROTO int +vbuf_peek(VBUF *v) +{ + if (vbuf_is_empty(v)) + return EOF; + return (unsigned char)(*v->tail); +} + #endif VBUFPROTO void @@ -110,11 +118,18 @@ vbuf_clear(VBUF *v) } VBUFPROTO int -vbuf_peek(VBUF *v) +vbuf_peekat(VBUF *v, int i) { - if (vbuf_is_empty(v)) - return -1; - return (unsigned char)(*v->tail); + const char *s = v->tail + i; + if (vbuf_is_empty(v) || i >= vbuf_capacity(v)) + return EOF; + if (s < v->head) + return (unsigned char)*s; + if (s >= v->buf_end) + s -= v->buf_end - v->buf; + if (s < v->head) + return (unsigned char)*s; + return EOF; } VBUFPROTO int @@ -127,7 +142,7 @@ vbuf_pop(VBUF *v) } VBUFPROTO int -vbuf_push(VBUF *v, char c) +vbuf_add(VBUF *v, char c) { if (vbuf_is_full(v)) return 0; @@ -143,7 +158,7 @@ vbuf_strchr(VBUF *v, char c) const char *s = v->tail, *d = v->head; if (vbuf_is_empty(v)) - return -1; + return EOF; if (d < s) d = v->buf_end; @@ -153,7 +168,7 @@ vbuf_strchr(VBUF *v, char c) return s - v->tail -1; if (v->head > v->tail) - return -1; + return EOF; s = v->buf; d = v->head; @@ -161,17 +176,18 @@ vbuf_strchr(VBUF *v, char c) if (*s++ == c) return (v->buf_end - v->tail) + s - v->buf -1; - return -1; + return EOF; } #define VBUF_TAIL_SZ(v) ((v->head >= v->tail) ? v->head - v->tail : v->buf_end - v->tail) -#define VBUF_HEAD_SZ(v) ((v->head >= v->tail) ? v->buf_end - v->head : v->tail - v->head) +#define VBUF_HEAD_SZ(v) ((v->tail > v->head) ? v->tail - v->head : v->buf_end - v->head) // get data from vbuf VBUFPROTO int -vbuf_get(VBUF *v, char *s, size_t sz) +vbuf_getblk(VBUF *v, void *p, size_t sz) { size_t rw, i; + char *s = p; if (!sz || vbuf_size(v) < sz) return 0; @@ -179,6 +195,7 @@ vbuf_get(VBUF *v, char *s, size_t sz) for (i = 0; sz && i < 2; i++) { rw = VBUF_TAIL_SZ(v); + assert(rw >= 0 && rw <= v->capacity+1); if (rw > sz) rw = sz; memcpy(s, v->tail, rw); v->tail += rw; s += rw; sz -= rw; @@ -191,9 +208,10 @@ vbuf_get(VBUF *v, char *s, size_t sz) // put data into vbuf VBUFPROTO int -vbuf_put(VBUF *v, const char *s, size_t sz) +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; @@ -201,6 +219,7 @@ vbuf_put(VBUF *v, const char *s, size_t sz) 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; @@ -211,6 +230,35 @@ vbuf_put(VBUF *v, const char *s, size_t sz) return 1; } +char * +vbuf_getstr (VBUF *v, char *s, size_t sz) +{ + char *sbase = s; + assert(sz > 0); + if (vbuf_is_empty(v)) + return NULL; + + while (sz-- > 0 && !vbuf_is_empty(v)) + { + if ('\0' == (*s++ = vbuf_pop(v))) + return sbase; + } + + // need to pad NUL. + s[ sz == 0 ? 0 : -1] = '\0'; + return sbase; +} + +int +vbuf_putstr (VBUF *v, char *s) +{ + int len = strlen(s) + 1; + if (vbuf_space(v) < len) + return 0; + vbuf_putblk(v, s, len); + return 1; +} + /* read/write callbacks */ static ssize_t @@ -326,7 +374,7 @@ vbuf_general_write(VBUF *v, ssize_t sz, void *ctx, if (rw < 0) return copied > 0 ? copied : -1; - assert(rw < VBUF_HEAD_SZ(v)); + assert(rw <= sz); v->tail += rw; sz -= rw; if (v->tail >= v->buf_end) v->tail -= v->buf_end - v->buf; @@ -371,7 +419,7 @@ vbuf_general_read(VBUF *v, ssize_t sz, void *ctx, if (rw < 0) return copied > 0 ? copied : -1; - assert(rw < VBUF_HEAD_SZ(v)); + assert(rw <= sz); v->head += rw; sz -= rw; if (v->head >= v->buf_end) v->head -= v->buf_end - v->buf; @@ -402,13 +450,13 @@ int main() vbuf_new(v, 50); for (i = 0; i < 10; i++) { - vbuf_put(v, "blah", sizeof("blah")); + vbuf_putblk(v, "blah", sizeof("blah")); vbuf_rpt(v); } for (i = 0; i < 10; i++) { char buf[64] = ""; - vbuf_get(v, buf, 5); + vbuf_getblk(v, buf, 5); printf("[got: %s] ", buf); vbuf_rpt(v); } @@ -416,8 +464,8 @@ int main() for (i = 0; i < 10; i++) { char buf[64] = ""; - vbuf_put(v, "blah", sizeof("blah")); - vbuf_get(v, buf, 5); + vbuf_putblk(v, "blah", sizeof("blah")); + vbuf_getblk(v, buf, 5); printf("[got: %s] ", buf); vbuf_rpt(v); } @@ -429,11 +477,28 @@ int main() printf("index of 't' = %d\n", vbuf_strchr(v, 't')); vbuf_rpt(v); printf("give me 4 chars: "); fflush(stdout); - vbuf_read(v, 0, 5); + vbuf_read(v, 0, 4); vbuf_rpt(v); printf("\n flushing vbuf: ["); fflush(stdout); vbuf_write(v, 1, VBUF_RWSZ_ALL); printf("]\n"); + vbuf_putblk(v, "peek test\n", sizeof("peek test\n")); + while (EOF != (i = vbuf_pop(v))) + putchar(i); + + vbuf_clear(v); + vbuf_putstr(v, "string test(1)"); + vbuf_putstr(v, "string test(2)"); + vbuf_putstr(v, "string test(3)"); + + for (i = 0; i < 4; i++) + { + char xbuf[256]; + char *s = vbuf_getstr(v, xbuf, sizeof(xbuf)); + printf("put/getstr(%d): %s\n", i+1, + s ? s : "(NULL)"); + } + getchar(); return 0; } diff --git a/pttbbs/include/cmsys.h b/pttbbs/include/cmsys.h index 04cde60a..4bc239f1 100644 --- a/pttbbs/include/cmsys.h +++ b/pttbbs/include/cmsys.h @@ -190,11 +190,13 @@ typedef struct VBUF { size_t capacity; } VBUF; +// speedy macros #define vbuf_is_empty(v) ((v)->head == (v)->tail) #define vbuf_is_full(v) (!vbuf_space(v)) #define vbuf_capacity(v) ((v)->capacity) #define vbuf_size(v) ((size_t)((v)->head >= (v)->tail ? (v)->head - (v)->tail : (v)->buf_end - (v)->tail + (v)->head - (v)->buf)) #define vbuf_space(v) ((size_t)((v)->capacity - vbuf_size(v))) +#define vbuf_peek(v) (vbuf_is_empty(v) ? EOF : (unsigned char)(*v->tail)) // buffer management extern void vbuf_new (VBUF *v, size_t szbuf); extern void vbuf_delete(VBUF *v); @@ -202,13 +204,17 @@ extern void vbuf_attach(VBUF *v, char *buf, size_t szbuf); extern void vbuf_detach(VBUF *v); extern void vbuf_clear (VBUF *v); // data accessing -extern int vbuf_get (VBUF *v, char *s, size_t sz); // get data from vbuf, return true/false -extern int vbuf_put (VBUF *v, const char *s, size_t sz); // put data into vbuf, return true/false -extern int vbuf_peek (VBUF *v); // peek one byte from vbuf, -1 if buffer empty -extern int vbuf_pop (VBUF *v); // pop one byte from vbuf, -1 if buffer empty -extern int vbuf_push (VBUF *v, char c); // push one byte into vbuf, return true/false +extern int vbuf_getblk(VBUF *v, void *p, size_t sz); // get data from vbuf, return true/false +extern int vbuf_putblk(VBUF *v, const void *p, size_t sz); // put data into vbuf, return true/false +extern int vbuf_peekat(VBUF *v, int i); // peek at given index, EOF(-1) if invalid index +extern int vbuf_pop (VBUF *v); // pop one byte from vbuf, EOF(-1) if buffer empty +extern int vbuf_add (VBUF *v, char c); // append one byte into vbuf, return true/false // search and test -extern int vbuf_strchr(VBUF *v, char c); // index of first location of c, otherwise -1 +extern int vbuf_strchr(VBUF *v, char c); // index of first location of c, otherwise EOF(-1) + +// 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 #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) diff --git a/pttbbs/include/vtuikit.h b/pttbbs/include/vtuikit.h index 63694bc3..2c6c8b22 100644 --- a/pttbbs/include/vtuikit.h +++ b/pttbbs/include/vtuikit.h @@ -112,6 +112,10 @@ void prints(const char *fmt, ...) GCC_CHECK_FORMAT(1,2); void mvprints(int y, int x, const char *fmt, ...) GCC_CHECK_FORMAT(3,4); void mvouts(int y, int x, const char *str); +// vbuf rendering +void outs_vbuf (VBUF *v); +void outns_vbuf(VBUF *v, int n); + // input history int InputHistoryAdd (const char *s); int InputHistoryExists (const char *s); diff --git a/pttbbs/mbbsd/vtuikit.c b/pttbbs/mbbsd/vtuikit.c index 7e14fdcb..6847d82e 100644 --- a/pttbbs/mbbsd/vtuikit.c +++ b/pttbbs/mbbsd/vtuikit.c @@ -184,6 +184,22 @@ mvouts(int y, int x, const char *str) outs(str); } +void +outs_vbuf(VBUF *v) +{ + int c; + while (EOF != (c = vbuf_pop(v))) + outc(c); +} + +void +outns_vbuf(VBUF *v, int n) +{ + int c; + while (EOF != (c = vbuf_pop(v)) && n-- > 0) + outc(c); +} + /** * vfill(n, flags, s): 印出並填滿 n 個字元的空間 * |