--- 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)
{
|