/* ** OSSP al -- Assembly Line ** Copyright (c) 2002 The OSSP Project ** Copyright (c) 2002 Cable & Wireless Deutschland ** Copyright (c) 2002 Ralf S. Engelschall ** Copyright (c) 2002 Michael van Elst ** ** This file is part of OSSP al, an abstract datatype of a data buffer ** that can assemble, move and truncate data but avoids actual copying. ** ** Permission to use, copy, modify, and distribute this software for ** any purpose with or without fee is hereby granted, provided that ** the above copyright notice and this permission notice appear in all ** copies. ** ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 AUTHORS AND COPYRIGHT HOLDERS AND THEIR ** 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. ** ** al_test.c: assembly line library, minimal test suite */ #include #include #include #include #include "al.h" /* get unique pointers */ static char label, label2, label3; #define LABEL ((al_label_t)&label) #define LABEL2 ((al_label_t)&label2) #define LABEL3 ((al_label_t)&label3) #define S(s) s, strlen(s) static const char *fill(char *p, int n) { static char buf[4 * 80 + 1]; int max = sizeof(buf)-5; int k; k=0; while (n > 0 && k < max) { if (isprint(*p)) { buf[k] = *p; k += 1; } else { sprintf(buf+k,"<%2.2x>",*p); k += 4; } ++p; --n; } buf[k] = '\0'; return (const char *)buf; } static al_rc_t printchunk(al_chunk_t *alc, void *u) { size_t len, pre, post; len = al_chunk_len(alc); pre = 16; if (pre > len) pre = len; post = 16; if (post > len-pre) post = len-pre; printf("C: %08lx + %-6d [%08lx] = ", (long)al_chunk_ptr(alc, 0), al_chunk_len(alc), (long)al_chunk_label(alc)); fputs(fill(al_chunk_ptr(alc,0),pre), stdout); if (post > 0) { fputs(" .. ", stdout); fputs(fill(al_chunk_ptr(alc,len-post),post), stdout); } fputs("\n", stdout); return AL_OK; } #define DUMP(tag,al) do {\ printf("+DUMP(%s)\n",tag);\ al_traverse_cb(al, 0, al_bytes(al), AL_FORWARD, NULL, printchunk, NULL);\ printf("-DUMP(%s)\n\n",tag);\ } while (0) static void print(const char *tag, al_t *al) { #if 0 char *buf; size_t n, len; n = al_bytes(al); buf = (char *)malloc(n); if (buf == NULL) abort(); al_flatten(al, 0, n, AL_FORWARD, LABEL, buf, &len); printf("%s = %d of %d\n",tag,len,n); fwrite(">>", 2, 1, stdout); fwrite(buf, len, 1, stdout); fwrite("<<", 2, 1, stdout); printf("\n\n"); free(buf); #endif } static void checklen(const char *tag, al_t *al) { al_tx_t *tx; al_chunk_t *cur; size_t total, total2; total = 0; al_txalloc(al, &tx); al_traverse(al, 0, al_bytes(al), AL_FORWARD, NULL, tx); while (al_traverse_next(al, tx, &cur) == AL_OK) total += al_chunk_len(cur); al_traverse_end(al, tx, 1); al_txfree(al, tx); total2 = al_bytes(al); if (total != total2) printf("ERROR: al_bytes(%s=%p): count %d != sum %d\n", tag,(void *)al,total,total2); } static void reclaim(char *p, size_t n, void *u) { printf("*** reclaiming buffer %p size %d ***\n",p,n); } int main(int argc, char *argv[]) { al_rc_t rc; al_t *al, *al2, *al3, *al4; char baf[] = "Mittendrin\n"; int i; size_t off, span; al_create(&al); al_create(&al2); al_create(&al3); al_append_bytes(al, S("Hello world\n"), LABEL); al_attach_buffer(al, S(baf), LABEL, reclaim, NULL); for (i=0; i<500; ++i) al_append_bytes(al, S("Huhu world\n"), LABEL); al_append_bytes(al2, S("Hello world\n"), LABEL); al_append_bytes(al3, S("HUHU WORLD\n"), LABEL2); DUMP("DATA",al); DUMP("BUFFER",al2); DUMP("REPLACEMENT", al3); rc = al_splice(al, al_bytes(al)-500, 500, al3, al2); printf("splice result: %d (%s)\n\n",rc,al_error(rc)); checklen("SPLICED",al); checklen("BUFFER",al2); checklen("REPLACEMENT",al3); al_create(&al4); rc = al_copy(al, al_bytes(al)-42, 38, LABEL, al4); printf("copy result: %d (%s)\n\n",rc,al_error(rc)); checklen("SPLICED",al); checklen("COPY",al4); rc = al_setlabel(al4, 7, 2, NULL, LABEL3); printf("setlabel result: %d (%s)\n\n",rc,al_error(rc)); rc = al_setlabel(al4, 5, 9, LABEL, LABEL2); printf("setlabel result: %d (%s)\n\n",rc,al_error(rc)); checklen("COPY",al4); rc = al_spanlabel(al4, 8, al_bytes(al), LABEL, &off, &span); printf("spanlabel result: %d (%s)\n\n",rc,al_error(rc)); printf("offset = %d, span = %d\n",off,span); DUMP("SPLICED",al); print("SPLICED", al); DUMP("BUFFER",al2); print("BUFFER", al2); DUMP("REPLACEMENT", al3); print("REPLACEMENT", al3); printf("free REPLACEMENT\n"); fflush(stdout); al_destroy(al3); printf("free BUFFER\n"); fflush(stdout); al_destroy(al2); printf("free SPLICED\n"); fflush(stdout); al_destroy(al); DUMP("COPY", al4); print("COPY", al4); printf("free COPY\n"); fflush(stdout); al_destroy(al4); return 0; }