/*- * Copyright (c) 2008 Wojciech A. Koszek * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * [id for your version control system, if any] */ #include #include #include #include /* * Assumptions * * Some characters within TTYs carry additional flags like "quoted", * "typical", "whitespace" etc. * * TTYs already have a notion of those flags. * * Instead * * Consider manipulation of flag/character separately--for a given * integer: * * 0x####@@@@ * * representing a character, make: * * cbuf_putc(cb, @) * * Put 0x0000@@@@ valua in cbuf, while: * * cbuf_fputc(cb, @, #) * * would put: * * 0x####@@@@ * * */ /* * Inserting/getting byte-stream from/to cbuf to be done. */ struct cbuf { #define CBUF_MAGIC0 0x12345678 unsigned cbuf_magic0; #define CBUF_INIT(c) ((c)->cbuf_magic0 = CBUF_MAGIC0) #define CBUF_ASSERT(c) assert((c)->cbuf_magic0 == CBUF_MAGIC0) int *b; int *e; int *p; }; static struct cbuf * cbuf_alloc(size_t bufsize) { struct cbuf *r; int *mem; r = calloc(1, sizeof(*r)); assert(r != NULL); CBUF_INIT(r); mem = calloc(sizeof(*r->b), bufsize); assert(mem != NULL); r->b = mem; r->p = mem; r->e = mem + bufsize; CBUF_ASSERT(r); return (r); } static void cbuf_free(struct cbuf *cb) { assert(cb != NULL); CBUF_ASSERT(cb); free(cb->b); } static int cbuf_isempty(struct cbuf *cb) { assert(cb != NULL); CBUF_ASSERT(cb); return (cb->p == cb->b); } static int cbuf_full(struct cbuf *cb) { assert(cb != NULL); CBUF_ASSERT(cb); return (cb->p == cb->e); } static int cbuf_putc(struct cbuf *cb, int c) { assert(cb != NULL); CBUF_ASSERT(cb); if (cb->p == cb->e) return (-1); cb->p++; *cb->p = c; return (0); } static int cbuf_getc(struct cbuf *cb) { int r; assert(cb != NULL); CBUF_ASSERT(cb); r = *cb->p; cb->p--; return (r); } static void cbuf_clear(struct cbuf *cb) { assert(cb != NULL); CBUF_ASSERT(cb); memset(cb->b, 0, cb->e - cb->b); cb->p = cb->b; } static int cbuf_cmp(struct cbuf *cb0, struct cbuf *cb1) { int l0, l1; assert(cb0 != NULL); assert(cb1 != NULL); CBUF_ASSERT(cb0); CBUF_ASSERT(cb1); l0 = cb0->e - cb0->b; l1 = cb1->e - cb1->b; if (l0 != l1) return (-1); return (memcmp(cb0->b, cb1->b, l0)); } static int cbuf_equal(struct cbuf *cb0, struct cbuf *cb1) { return (!cbuf_cmp(cb0, cb1)); } static void CB_TestEmpty(void) { struct cbuf *cb; int e; cb = cbuf_alloc(1024); e = cbuf_isempty(cb); assert(e == 1); cbuf_free(cb); } static void CB_TestPutGet(void) { struct cbuf *cb; int e; cb = cbuf_alloc(10); assert(cb); CBUF_ASSERT(cb); e = cbuf_putc(cb, 'W'); assert(e == 0); e = cbuf_getc(cb); assert(e == 'W'); cbuf_free(cb); cb = cbuf_alloc(10); assert(cb); CBUF_ASSERT(cb); e = cbuf_putc(cb, 'W'); assert(e == 0); e = cbuf_putc(cb, 'A'); assert(e == 0); e = cbuf_putc(cb, 'K'); assert(e == 0); e = cbuf_getc(cb); assert(e == 'K'); e = cbuf_getc(cb); assert(e == 'A'); e = cbuf_getc(cb); assert(e == 'W'); cbuf_free(cb); } static void CB_TestFull(void) { struct cbuf *cb; int e, i; cb = cbuf_alloc(1024); for (i = 0; i < 1024; i++) { e = cbuf_putc(cb, i); assert(e == 0); } e = cbuf_full(cb); assert(e == 1 && "cbuf_full(cb)"); } static void CB_TestClear(void) { struct cbuf *cb; int e, i; cb = cbuf_alloc(1000); for (i = 0; i < 1000; i++) cbuf_putc(cb, i); e = cbuf_full(cb); assert(e == 1 && "cbuf_full(cb)"); cbuf_clear(cb); e = cbuf_isempty(cb); assert(e == 1 && "cbuf_isempty(cb)"); } static void CB_TestCmp(void) { char test[] = "CB_TestCMP"; struct cbuf *c0; struct cbuf *c1; int sz; int e; int i; sz = sizeof(test); c0 = cbuf_alloc(sz); c1 = cbuf_alloc(sz); cbuf_clear(c0); cbuf_clear(c1); for (i = 0; i < sz; i++) { cbuf_putc(c0, test[i]); cbuf_putc(c1, test[i]); } e = cbuf_cmp(c0, c1); assert(e == 0 && "cbuf_cmp(c0, c1)"); e = cbuf_equal(c0, c1); assert(e == 1 && "cbuf_equal(c0, c1)"); } int main(int argc __unused, char **argv __unused) { CB_TestEmpty(); CB_TestPutGet(); CB_TestFull(); CB_TestClear(); CB_TestCmp(); exit(EXIT_SUCCESS); }