From b3a440ca242a07ed86f89d06208f15757d947e12 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Tue, 27 Feb 2024 20:46:33 -0800 Subject: seq_build: fix: incompatible items must create list. In the make_like function, the list is converted to string or buffer if the first element of the list is a character, or integer. We need similar logic in seq_build. We can make it better. When any item is added which is incompatible, we can convert what we have so far to a list, change the seq_build type to list, and keep going. * lib.c (seq_build_convert_to_list): New static function. (seq_build_str_add, seq_build_buf_add): If the item is incompatible, convert the string or buffer to a list and pass to seq_build_convert_to_list. Then call bu->ops->add to add the item, now as a list. (seq_build_buf_pend): Function removed. (sb_buf_ops): Use the seq_build_generic_pend function for the pend operation. This is because we have to check each item one by one; we cannot use replace_buf. --- lib.c | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) (limited to 'lib.c') diff --git a/lib.c b/lib.c index 8d928c66..a0c26ff0 100644 --- a/lib.c +++ b/lib.c @@ -1438,9 +1438,16 @@ static void seq_build_vec_add(seq_build_t *bu, val item) vec_push(bu->obj, item); } +static void seq_build_convert_to_list(seq_build_t *bu, val list); + static void seq_build_str_add(seq_build_t *bu, val item) { - string_extend(bu->obj, item, nil); + if (chrp(item)) { + string_extend(bu->obj, item, nil); + } else { + seq_build_convert_to_list(bu, list_str(bu->obj)); + bu->ops->add(bu, item); + } } static void seq_build_str_finish(seq_build_t *bu) @@ -1451,17 +1458,14 @@ static void seq_build_str_finish(seq_build_t *bu) static void seq_build_buf_add(seq_build_t *bu, val item) { val buf = bu->obj; - val len = length_buf(buf); - - buf_put_uchar(buf, len, item); -} -static void seq_build_buf_pend(seq_build_t *bu, val seq) -{ - val buf = bu->obj; - val len = length_buf(buf); - - replace_buf(buf, seq, len, len); + if (integerp(item)) { + val len = length_buf(buf); + buf_put_uchar(buf, len, item); + } else { + seq_build_convert_to_list(bu, mapcar_listout(identity_f, buf)); + bu->ops->add(bu, item); + } } static void seq_build_buf_finish(seq_build_t *bu) @@ -1522,7 +1526,7 @@ static struct seq_build_ops static struct seq_build_ops sb_buf_ops = seq_build_ops_init(seq_build_buf_add, - seq_build_buf_pend, + seq_build_generic_pend, seq_build_buf_finish, seq_build_obj_mark); @@ -1544,6 +1548,20 @@ static struct seq_build_ops seq_build_list_finish, seq_build_obj_mark); +static void seq_build_convert_to_list(seq_build_t *bu, val list) +{ + if (list) { + val tail = lastcons(list); + us_rplacd(tail, list); + bu->obj = tail; + } else { + bu->obj = nil; + } + + bu->ops = &sb_list_ops; +} + + void seq_build_init(val self, seq_build_t *bu, val likeobj) { bu->self = self; -- cgit v1.2.3