Commit 46f46afa authored by Pekka Pessi's avatar Pekka Pessi

Added tl_llist(), tl_vllist(). Better semantics for tl_next().

darcs-hash:20051012173724-65a35-3e87ff167c73d4697c180f65315cb1eb158c83f2.gz
parent 40642538
......@@ -126,7 +126,7 @@ int tl_tremove(tagi_t lst[], tag_type_t tag, tag_value_t value, ...);
/* Low-level taglist manipulation functions */
size_t tl_len(tagi_t const lst[]);
size_t tl_xtra(tagi_t const lst[], size_t offset);
tagi_t const *tl_next(tagi_t const *lst);
tagi_t *tl_next(tagi_t const *lst);
tagi_t *tl_move(tagi_t *dst, tagi_t const src[]);
tagi_t *tl_dup(tagi_t dst[], tagi_t const lst[], void **bb);
tagi_t *tl_adup(su_home_t *, tagi_t const lst[]);
......@@ -142,6 +142,8 @@ size_t tl_vlen(va_list ap);
tagi_t *tl_list(tag_type_t tag, tag_value_t value, ...);
tagi_t *tl_vlist2(tag_type_t tag, tag_value_t value, va_list ap);
tagi_t *tl_vlist(va_list ap);
tagi_t *tl_llist(tag_type_t tag, tag_value_t value, ...);
tagi_t *tl_vllist(tag_type_t tag, tag_value_t value, va_list ap);
void tl_vfree(tagi_t *t);
/** Align to pointer size */
......
......@@ -288,7 +288,7 @@ static int test_stackargs(int l, ...)
static int test_stackargs(int l, ...) { return 0; }
#endif
/** Test tl_list and tl_dup */
/** Test tl_list, tl_llist and tl_dup */
static int test_dup(void)
{
tagi_t const rest[] = {{ TAG_A("Foo") }, { TAG_NULL() }};
......@@ -318,6 +318,31 @@ static int test_dup(void)
TEST(tl_xtra(dup, 0), strlen("Moro" "Vaan" "Foo") + 3);
su_free(NULL, dup);
dup = tl_llist(TAG_B("Moi"), TAG_NEXT(lst));
TEST(dup[0].t_tag, tag_b);
TEST(dup[1].t_tag, tag_a);
TEST(dup[2].t_tag, tag_a);
TEST(dup[3].t_tag, tag_i);
TEST(dup[4].t_tag, tag_a);
TEST(dup[5].t_tag, NULL);
su_free(NULL, dup);
dup = tl_llist(TAG_NEXT(NULL));
TEST(dup[0].t_tag, 0);
su_free(NULL, dup);
dup = tl_llist(TAG_END());
TEST(dup[0].t_tag, 0);
su_free(NULL, dup);
dup = tl_llist(TAG_SKIP(1), TAG_NEXT(lst + 4));
TEST(dup[0].t_tag, tag_a);
TEST(dup[1].t_tag, 0);
su_free(NULL, dup);
tl_vfree(lst);
END();
......@@ -420,10 +445,6 @@ static int test_tagargs2(tag_type_t tag, tag_value_t value, ...)
TEST(t->t_tag, tag_a);
TEST_S((char *)t->t_value, "a");
t = tl_next(t);
TEST(t->t_tag, tag_next);
TEST_1(t->t_value != 0);
t = tl_next(t);
TEST(t->t_tag, tag_b);
TEST_S((char *)t->t_value, "b");
......
......@@ -150,9 +150,17 @@ int t_snprintf(tagi_t const *t, char b[], size_t size)
/** Get next tag item from list.
*/
tagi_t const *tl_next(tagi_t const *t)
tagi_t *tl_next(tagi_t const *t)
{
return t_next(t);
tag_type_t tt;
t = t_next(t);
for (tt = TAG_TYPE_OF(t); t && tt->tt_next; tt = TAG_TYPE_OF(t)) {
t = tt->tt_next(t);
}
return (tagi_t *)t;
}
/**Move a tag list.
......@@ -680,8 +688,7 @@ tagi_t *tl_vlist2(tag_type_t tag, tag_value_t value, va_list ap)
return rv;
}
/** Make a tag list */
/** Make a tag list until TAG_NEXT() or TAG_END() */
tagi_t *tl_list(tag_type_t tag, tag_value_t value, ...)
{
va_list ap;
......@@ -694,14 +701,97 @@ tagi_t *tl_list(tag_type_t tag, tag_value_t value, ...)
return t;
}
/** Free a tag list allocated by tl_list() or tl_vlist(). */
/** Calculate length of a linear tag list. */
size_t tl_vllen(tag_type_t tag, tag_value_t value, va_list ap)
{
size_t len = sizeof(tagi_t);
tagi_t const *next;
tagi_t tagi[3];
tagi[0].t_tag = tag;
tagi[0].t_value = value;
tagi[1].t_tag = tag_any;
tagi[1].t_value = 0;
for (;;) {
next = tl_next(tagi);
if (next != tagi + 1)
break;
if (tagi->t_tag != tag_skip)
len += sizeof(tagi_t);
tagi->t_tag = va_arg(ap, tag_type_t);
tagi->t_value = va_arg(ap, tag_value_t);
}
for (; next; next = tl_next(next))
len += sizeof(tagi_t);
return len;
}
/** Make a linear tag list. */
tagi_t *tl_vllist(tag_type_t tag, tag_value_t value, va_list ap)
{
va_list aq;
tagi_t *t, *rv;
tagi_t const *next;
tagi_t tagi[2];
int size;
va_copy(aq, ap);
size = tl_vllen(tag, value, aq);
va_end(aq);
t = rv = malloc(size);
tagi[0].t_tag = tag;
tagi[0].t_value = value;
tagi[1].t_tag = tag_any;
tagi[1].t_value = 0;
for (;;) {
next = tl_next(tagi);
if (next != tagi + 1)
break;
if (tagi->t_tag != tag_skip)
*t++ = *tagi;
tagi->t_tag = va_arg(ap, tag_type_t);
tagi->t_value = va_arg(ap, tag_value_t);
}
for (; next; next = tl_next(next))
*t++ = *next;
t->t_tag = NULL; t->t_value = 0; t++;
assert((char *)rv + size == (char *)t);
return rv;
}
/** Make a linear tag list until TAG_END() */
tagi_t *tl_llist(tag_type_t tag, tag_value_t value, ...)
{
va_list ap;
tagi_t *t;
va_start(ap, value);
t = tl_vllist(tag, value, ap);
va_end(ap);
return t;
}
/** Free a tag list allocated by tl_list(), tl_llist() or tl_vlist(). */
void tl_vfree(tagi_t *t)
{
if (t)
free(t);
}
/** Convert a string to the a value of a tag. */
int t_scan(tag_type_t tt, su_home_t *home, char const *s,
tag_value_t *return_value)
......@@ -765,6 +855,11 @@ tag_class_t null_tag_class[1] =
/* tc_scan */ NULL,
}};
tagi_t const *t_skip_next(tagi_t const *t)
{
return t + 1;
}
tagi_t *t_skip_move(tagi_t *dst, tagi_t const *src)
{
return dst;
......@@ -783,7 +878,7 @@ tagi_t *t_skip_dup(tagi_t *dst, tagi_t const *src, void **bb)
tag_class_t skip_tag_class[1] =
{{
sizeof(skip_tag_class),
/* tc_next */ NULL,
/* tc_next */ t_skip_next,
/* tc_len */ t_skip_len,
/* tc_move */ t_skip_move,
/* tc_xtra */ NULL,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment