Index: ossp-pkg/sio/al.c RCS File: /v/ossp/cvs/ossp-pkg/sio/Attic/al.c,v rcsdiff -q -kk '-r1.28' '-r1.29' -u '/v/ossp/cvs/ossp-pkg/sio/Attic/al.c,v' 2>/dev/null --- al.c 2002/10/22 15:09:44 1.28 +++ al.c 2002/10/22 15:33:16 1.29 @@ -76,6 +76,7 @@ al_buffer_t *buf; /* (non-exlusively) referenced buffer object */ size_t begin; /* offset into buf->mem where data starts */ size_t end; /* offset into buf->mem where data ends */ + al_label_t label; /* tag data with a label, chunks with distinct labels are not coalesced */ }; struct al_buffer_st { @@ -91,6 +92,7 @@ al_chunk_t *cur; /* current chunk during traveral steps */ size_t skip; /* number of bytes to skip for traversal */ size_t togo; /* number of bytes left for traversal */ + al_label_t label; /* label filter or NULL */ al_chunk_t view; /* synthetic chunk for returning during traversal steps */ }; @@ -107,14 +109,22 @@ ((n) > (AL_CHUNK_LEN(alc) - (off)) ? \ (AL_CHUNK_LEN(alc) - (off)) : (n)) +/* return chunk label */ +#define AL_CHUNK_LABEL(alc) \ + ((alc)->label) + +/* check wether labels match */ +#define AL_SAME_LABEL(alc,label) \ + ((label) == NULL || AL_CHUNK_LABEL(alc) == (label)) + /* * number of bytes a chunk can be grown to the end * we must not grow a chunk in a shared buffer since * we do not track other chunks sharing the buffer */ -#define AL_CHUNK_RESERVE(alc) \ +#define AL_CHUNK_RESERVE(alc,label) \ ( (alc) != NULL \ - ? ( (alc)->buf->usecount > 1 \ + ? ( (alc)->buf->usecount > 1 || !AL_SAME_LABEL(alc,label) \ ? 0 \ : (alc)->buf->size - (alc)->end) \ : 0) @@ -128,9 +138,9 @@ * we must not grow a chunk in a shared buffer since * we do not track other chunks sharing the buffer */ -#define AL_CHUNK_PRESERVE(alc) \ +#define AL_CHUNK_PRESERVE(alc,label) \ ( (alc) != NULL \ - ? ( (alc)->buf->usecount > 1 \ + ? ( (alc)->buf->usecount > 1 || !AL_SAME_LABEL(alc,label) \ ? 0 \ : (alc)->begin) \ : 0) @@ -230,7 +240,7 @@ static int alc_freecount = 0; static al_rc_t -new_chunk(al_t *al, al_buffer_t *buf, al_chunk_t **alcp) +new_chunk(al_t *al, al_buffer_t *buf, al_label_t label, al_chunk_t **alcp) { al_chunk_t *alc; @@ -254,6 +264,7 @@ alc->buf = buf; alc->begin = 0; alc->end = 0; + alc->label = label; buf->usecount++; @@ -271,7 +282,7 @@ if (off < 0 || off > len) return AL_ERR_ARG; - rc = new_chunk(al, orig->buf, &alc); + rc = new_chunk(al, orig->buf, orig->label, &alc); if (rc != AL_OK) return rc; @@ -290,6 +301,7 @@ if (alc->buf->usecount == 0) dispose_buffer(al,alc->buf); alc->buf = NULL; + alc->label = NULL; /* stop freelist from growing infinitely */ if (alc_freecount >= al->m.max_freechunks) @@ -369,8 +381,9 @@ printf("AL: %p\n", al); total = 0; FOREACH(al,chunks,cur) { - printf(" C: %p (%d @ %p + %d < %d (use=%d))\n", + printf(" C: %p [%p] (%d @ %p + %d < %d (use=%d))\n", cur, + cur->label, cur->buf->size,cur->buf->mem, cur->begin,cur->end, cur->buf->usecount); @@ -451,7 +464,7 @@ * but leaves data structure consistent */ al_rc_t -al_append_bytes(al_t *al, const char *src, size_t n) +al_append_bytes(al_t *al, const char *src, size_t n, al_label_t label) { al_rc_t rc; al_chunk_t *cur; @@ -464,17 +477,17 @@ return AL_RC(AL_ERR_ARG); cur = TAIL(al,chunks); - res = AL_CHUNK_RESERVE(cur); + res = AL_CHUNK_RESERVE(cur,label); while (n > 0) { if (res == 0) { rc = new_buffer(al, &buf); if (rc != AL_OK) return AL_RC(rc); - rc = new_chunk(al,buf,&cur); + rc = new_chunk(al,buf,label,&cur); if (rc != AL_OK) return AL_RC(rc); - res = AL_CHUNK_RESERVE(cur); + res = AL_CHUNK_RESERVE(cur,label); ADDTAIL(al, chunks, cur); } step = n; @@ -487,7 +500,7 @@ src += step; AL_RESIZE(al, cur, step); n -= step; - res = AL_CHUNK_RESERVE(cur); + res = AL_CHUNK_RESERVE(cur,label); } return AL_OK; @@ -500,7 +513,7 @@ * but leaves data structure consistent */ al_rc_t -al_prepend_bytes(al_t *al, const char *src, size_t n) +al_prepend_bytes(al_t *al, const char *src, size_t n, al_label_t label) { al_rc_t rc; al_chunk_t *cur; @@ -513,7 +526,7 @@ return AL_RC(AL_ERR_ARG); cur = HEAD(al,chunks); - res = AL_CHUNK_PRESERVE(cur); + res = AL_CHUNK_PRESERVE(cur,label); src += n; @@ -522,10 +535,10 @@ rc = new_buffer(al, &buf); if (rc != AL_OK) return AL_RC(rc); - rc = new_chunk(al,buf,&cur); + rc = new_chunk(al,buf,label,&cur); if (rc != AL_OK) return AL_RC(rc); - res = AL_CHUNK_PRESERVE(cur); + res = AL_CHUNK_PRESERVE(cur,label); ADDHEAD(al, chunks, cur); } step = n; @@ -535,7 +548,7 @@ src -= step; AL_PRESIZE(al, cur, step); n -= step; - res = AL_CHUNK_PRESERVE(cur); + res = AL_CHUNK_PRESERVE(cur,label); dst = AL_CHUNK_PTR(cur, 0); memcpy(dst, src, step); @@ -552,7 +565,8 @@ * XXX - some list operations modify the buffer * */ -al_rc_t al_attach_buffer(al_t *al, char *p, size_t n, void (*freemem)(char *, size_t, void *), void *u) +al_rc_t al_attach_buffer(al_t *al, char *p, size_t n, al_label_t label, + void (*freemem)(char *, size_t, void *), void *u) { al_rc_t rc; al_buffer_t *buf; @@ -565,7 +579,7 @@ rc = make_buffer(al, p, n, freemem, u, &buf); if (rc != AL_OK) return AL_RC(rc); - rc = new_chunk(al,buf, &cur); + rc = new_chunk(al,buf,label,&cur); if (rc != AL_OK) return AL_RC(rc); ADDTAIL(al, chunks, cur); @@ -672,7 +686,8 @@ */ size_t before = tal->bytes; - rc = al_append_bytes(tal, AL_CHUNK_PTR(cur, skip), step); + rc = al_append_bytes(tal, AL_CHUNK_PTR(cur, skip), + step, AL_CHUNK_LABEL(cur)); if (rc != AL_OK) /* correct step size to actual size */ step = tal->bytes - before; @@ -802,7 +817,7 @@ * - save traversal parameters */ al_rc_t -al_traverse(al_t *al, size_t off, size_t n, al_td_t dir, al_tx_t *tx) +al_traverse(al_t *al, size_t off, size_t n, al_td_t dir, al_label_t label, al_tx_t *tx) { al_rc_t rc; @@ -812,8 +827,9 @@ if (rc != AL_OK) return AL_RC(rc); - tx->dir = dir; - tx->togo = n; + tx->dir = dir; + tx->togo = n; + tx->label = label; return AL_OK; } @@ -830,38 +846,40 @@ { size_t step; - if (tx->togo <= 0) /* XXX - togo can be negative from bad input */ - return AL_ERR_EOF; + do { + if (tx->togo <= 0) /* XXX - togo can be negative from bad input */ + return AL_ERR_EOF; - if (tx->cur == NULL) /* premature EOF */ - return AL_ERR_EOF; + if (tx->cur == NULL) /* premature EOF */ + return AL_ERR_EOF; - /* compute number of bytes to process */ - step = AL_CHUNK_SPAN(tx->cur, tx->skip, tx->togo); + /* compute number of bytes to process */ + step = AL_CHUNK_SPAN(tx->cur, tx->skip, tx->togo); - /* - * synthetic chunk which is NOT maintained in usecount - * MUST NOT BE USED for modifications to chunk list - * MUST NOT BE USED for modifications to chunk size - * ALLOWED is read access to chunk content - * ALLOWED is modification in place of chunk content - */ - tx->view = *(tx->cur); - tx->view.begin += tx->skip; - tx->view.end = tx->view.begin + step; - - switch (tx->dir) { - case AL_FORWARD: - tx->cur = NEXT(tx->cur,chunks); - tx->togo -= step; - tx->skip = 0; - break; - case AL_BACKWARD: - tx->cur = PREV(tx->cur,chunks); - tx->togo -= step; - tx->skip = 0; - break; - } + /* + * synthetic chunk which is NOT maintained in usecount + * MUST NOT BE USED for modifications to chunk list + * MUST NOT BE USED for modifications to chunk size + * ALLOWED is read access to chunk content + * ALLOWED is modification in place of chunk content + */ + tx->view = *(tx->cur); + tx->view.begin += tx->skip; + tx->view.end = tx->view.begin + step; + + switch (tx->dir) { + case AL_FORWARD: + tx->cur = NEXT(tx->cur,chunks); + tx->togo -= step; + tx->skip = 0; + break; + case AL_BACKWARD: + tx->cur = PREV(tx->cur,chunks); + tx->togo -= step; + tx->skip = 0; + break; + } + } while (!AL_SAME_LABEL(&tx->view, tx->label)); *alcp = &tx->view; return AL_OK; @@ -887,14 +905,14 @@ * traversal context is kept on stack (XXX ?) */ al_rc_t -al_traverse_cb(al_t *al, size_t off, size_t n, al_td_t dir, +al_traverse_cb(al_t *al, size_t off, size_t n, al_td_t dir, al_label_t label, al_rc_t (*cb)(al_chunk_t *, void *), void *u) { al_rc_t rc; al_tx_t tx; /* XXX - private tx structure on stack */ al_chunk_t *view; - rc = al_traverse(al, off, n, dir, &tx); + rc = al_traverse(al, off, n, dir, label, &tx); if (rc != AL_OK) return AL_RC(rc); @@ -917,10 +935,15 @@ * * returns actual number of bytes copied * + * Do not copy if destination pointer is NULL, but still count. + * This can be used to precalculate the size of the needed linear + * buffer with n set to some arbitrary huge value. + * * traversal context is kept on stack (XXX ?) */ al_rc_t -al_flatten(al_t *al, size_t off, size_t n, char *dst, size_t *lenp) +al_flatten(al_t *al, size_t off, size_t n, al_label_t label, + char *dst, size_t *lenp) { al_rc_t rc; al_tx_t tx; /* XXX - private tx structure on stack */ @@ -929,15 +952,19 @@ *lenp = 0; /* keep caller on safe side */ - rc = al_traverse(al, off, n, AL_FORWARD, &tx); + rc = al_traverse(al, off, n, AL_FORWARD, label, &tx); if (rc != AL_OK) return AL_RC(rc); total = 0; while ((rc = al_traverse_next(al, &tx, &view)) == AL_OK) { step = AL_CHUNK_LEN(view); - memmove(dst, AL_CHUNK_PTR(view, 0), step); - dst += step; + + if (dst != NULL) { + memmove(dst, AL_CHUNK_PTR(view, 0), step); + dst += step; + } + total += step; } *lenp = total; @@ -956,20 +983,20 @@ * traversal context is kept on stack (XXX ?) */ al_rc_t -al_copy(al_t *al, size_t off, size_t n, al_t *tal) +al_copy(al_t *al, size_t off, size_t n, al_label_t label, al_t *tal) { al_rc_t rc; al_tx_t tx; /* XXX - private tx structure on stack */ al_chunk_t *view; size_t step; - rc = al_traverse(al, off, n, AL_FORWARD, &tx); + rc = al_traverse(al, off, n, AL_FORWARD, label, &tx); if (rc != AL_OK) return AL_RC(rc); while ((rc = al_traverse_next(al, &tx, &view)) == AL_OK) { step = AL_CHUNK_LEN(view); - al_append_bytes(tal, AL_CHUNK_PTR(view, 0), step); + al_append_bytes(tal, AL_CHUNK_PTR(view, 0), step, AL_CHUNK_LABEL(view)); } al_traverse_end(al, &tx, 1); @@ -986,6 +1013,8 @@ * al_bytes - total number of bytes in assembly line * al_chunk_len - number of bytes in chunk * al_chunk_span - clip interval (off,off+n( against chunk length + * al_chunk_label- return chunk label + * al_same_label - check if label matches with chunk label * al_chunk_ptr - return memory pointer to byte within chunk * * off must be a valid offset within (0,len( @@ -1009,6 +1038,18 @@ return AL_CHUNK_SPAN(alc, off, n); } +al_label_t +al_chunk_label(al_chunk_t *alc) +{ + return AL_CHUNK_LABEL(alc); +} + +int +al_same_label(al_chunk_t *alc, al_label_t label) +{ + return AL_SAME_LABEL(alc, label); +} + char * al_chunk_ptr(al_chunk_t *alc, size_t off) { Index: ossp-pkg/sio/al.h RCS File: /v/ossp/cvs/ossp-pkg/sio/Attic/al.h,v rcsdiff -q -kk '-r1.12' '-r1.13' -u '/v/ossp/cvs/ossp-pkg/sio/Attic/al.h,v' 2>/dev/null --- al.h 2002/10/18 12:24:53 1.12 +++ al.h 2002/10/22 15:33:16 1.13 @@ -46,6 +46,8 @@ struct al_chunk_st; typedef struct al_chunk_st al_chunk_t; +typedef void *al_label_t; + typedef enum { AL_FORWARD, AL_BACKWARD @@ -56,25 +58,27 @@ al_rc_t al_create (al_t **alp); al_rc_t al_destroy (al_t *al); -al_rc_t al_append_bytes (al_t *al, const char *src, size_t n); -al_rc_t al_prepend_bytes(al_t *al, const char *src, size_t n); -al_rc_t al_attach_buffer(al_t *al, char *p, size_t n, void (*freemem)(char *, size_t, void *), void *u); +al_rc_t al_append_bytes (al_t *al, const char *src, size_t n, al_label_t label); +al_rc_t al_prepend_bytes(al_t *al, const char *src, size_t n, al_label_t label); +al_rc_t al_attach_buffer(al_t *al, char *p, size_t n, al_label_t label, void (*freemem)(char *, size_t, void *), void *u); al_rc_t al_txalloc (al_t *al, al_tx_t **txp); al_rc_t al_txfree (al_t *al, al_tx_t *tx); -al_rc_t al_traverse (al_t *al, size_t off, size_t n, al_td_t dir, al_tx_t *tx); +al_rc_t al_traverse (al_t *al, size_t off, size_t n, al_td_t dir, al_label_t label, al_tx_t *tx); al_rc_t al_traverse_next(al_t *al, al_tx_t *tx, al_chunk_t **alcp); al_rc_t al_traverse_end (al_t *al, al_tx_t *tx, int final); -al_rc_t al_traverse_cb (al_t *al, size_t off, size_t n, al_td_t dir, al_rc_t (*cb)(al_chunk_t *, void *), void *u); -al_rc_t al_copy (al_t *al, size_t off, size_t n, al_t *tal); +al_rc_t al_traverse_cb (al_t *al, size_t off, size_t n, al_td_t dir, al_label_t, al_rc_t (*cb)(al_chunk_t *, void *), void *u); +al_rc_t al_copy (al_t *al, size_t off, size_t n, al_label_t label, al_t *tal); al_rc_t al_splice (al_t *al, size_t off, size_t n, al_t *nal, al_t *tal); -al_rc_t al_flatten (al_t *al, size_t off, size_t n, char *dst, size_t *lenp); +al_rc_t al_flatten (al_t *al, size_t off, size_t n, al_label_t label, char *dst, size_t *lenp); -size_t al_bytes (const al_t *al); -size_t al_chunk_len (al_chunk_t *alc); -size_t al_chunk_span(al_chunk_t *alc, size_t off, size_t n); -char *al_chunk_ptr (al_chunk_t *alc, size_t off); +size_t al_bytes (const al_t *al); +size_t al_chunk_len (al_chunk_t *alc); +al_label_t al_chunk_label(al_chunk_t *alc); +int al_same_label (al_chunk_t *alc, al_label_t label); +size_t al_chunk_span (al_chunk_t *alc, size_t off, size_t n); +char *al_chunk_ptr (al_chunk_t *alc, size_t off); -const char *al_error(al_rc_t rc); +const char *al_error (al_rc_t rc); #endif /* __AL_H__ */ Index: ossp-pkg/sio/al.pod RCS File: /v/ossp/cvs/ossp-pkg/sio/Attic/al.pod,v rcsdiff -q -kk '-r1.10' '-r1.11' -u '/v/ossp/cvs/ossp-pkg/sio/Attic/al.pod,v' 2>/dev/null --- al.pod 2002/10/18 12:23:35 1.10 +++ al.pod 2002/10/22 15:33:16 1.11 @@ -79,6 +79,8 @@ al_chunk_len, al_chunk_span, +al_chunk_label, +al_same_label, al_chunk_ptr. =item B: @@ -100,7 +102,7 @@ =head1 DATA TYPES -B uses five data types in its API: +B uses six data types in its API: =over 4 @@ -141,6 +143,14 @@ used in the API. The B type is used to generate a pointer and byte count to access the data in the buffer. +=item B (Label Type) + +This is a pointer type representing a specific data flavour. You +can restrict traversal operations to data that was marked with +the specific flavour. Usually you would cast a pointer to the +object that maintains the data to B. You may use +NULL as a label but on traversal NULL matches any label. + =back =head1 FUNCTIONS @@ -172,21 +182,22 @@ Example: C -=item al_rc_t B(al_t *I, const char *I, size_t I); +=item al_rc_t B(al_t *I, const char *I, size_t I, al_label_t I