diff options
-rw-r--r-- | lib.c | 130 | ||||
-rw-r--r-- | tests/015/split.tl | 13 | ||||
-rw-r--r-- | txr.1 | 64 |
3 files changed, 111 insertions, 96 deletions
@@ -5632,12 +5632,14 @@ struct cat_str { val sep; cnum len_sep; size_t total; + int seen_one; wchar_t *str, *ptr; }; static void cat_str_init(struct cat_str *cs, val sep, wchar_t *onech, val self) { cs->sep = sep; + cs->seen_one = 0; cs->total = 1; cs->str = cs->ptr = 0; @@ -5652,7 +5654,7 @@ static void cat_str_init(struct cat_str *cs, val sep, wchar_t *onech, val self) } } -static void cat_str_measure(struct cat_str *cs, val item, int more_p, val self) +static void cat_str_measure(struct cat_str *cs, val item, val self) { if (!item) return; @@ -5660,8 +5662,12 @@ static void cat_str_measure(struct cat_str *cs, val item, int more_p, val self) if (stringp(item)) { size_t ntotal = cs->total + c_num(length_str(item), self); - if (cs->len_sep && more_p) - ntotal += cs->len_sep; + if (cs->len_sep) { + if (cs->seen_one) + ntotal += cs->len_sep; + else + cs->seen_one = 1; + } if (ntotal < cs->total) goto oflow; @@ -5673,8 +5679,12 @@ static void cat_str_measure(struct cat_str *cs, val item, int more_p, val self) if (chrp(item)) { size_t ntotal = cs->total + 1; - if (cs->len_sep && more_p) - ntotal += cs->len_sep; + if (cs->len_sep) { + if (cs->seen_one) + ntotal += cs->len_sep; + else + cs->seen_one = 1; + } if (ntotal < cs->total) goto oflow; @@ -5683,32 +5693,54 @@ static void cat_str_measure(struct cat_str *cs, val item, int more_p, val self) return; } - uw_throwf(error_s, lit("~a: ~s is not a character or string"), self, - item, nao); + if (seqp(item)) { + seq_iter_t item_iter; + seq_iter_init(self, &item_iter, item); + + while (seq_get(&item_iter, &item)) + cat_str_measure(cs, item, self); + + return; + } + + uw_throwf(error_s, lit("~a: ~s neither character, string nor sequence"), + self, item, nao); oflow: uw_throwf(error_s, lit("~a: string length overflow"), self, nao); } static void cat_str_alloc(struct cat_str *cs) { + cs->seen_one = 0; cs->ptr = cs->str = chk_wmalloc(cs->total); } -static void cat_str_append(struct cat_str *cs, val item, int more_p, val self) +static void cat_str_append(struct cat_str *cs, val item, val self) { if (!item) return; - if (stringp(item)) { - cnum len = c_num(length_str(item), self); - wmemcpy(cs->ptr, c_str(item, self), len); - cs->ptr += len; + if (stringp(item) || chrp(item)) { + if (cs->len_sep) { + if (cs->seen_one) { + wmemcpy(cs->ptr, c_str(cs->sep, self), cs->len_sep); + cs->ptr += cs->len_sep; + } else { + cs->seen_one = 1; + } + } + if (chrp(item)) { + *cs->ptr++ = c_chr(item); + } else { + cnum len = c_num(length_str(item), self); + wmemcpy(cs->ptr, c_str(item, self), len); + cs->ptr += len; + } } else { - *cs->ptr++ = c_chr(item); - } + seq_iter_t item_iter; + seq_iter_init(self, &item_iter, item); - if (cs->len_sep && more_p) { - wmemcpy(cs->ptr, c_str(cs->sep, self), cs->len_sep); - cs->ptr += cs->len_sep; + while (seq_get(&item_iter, &item)) + cat_str_append(cs, item, self); } } @@ -5721,56 +5753,33 @@ static val cat_str_get(struct cat_str *cs) val cat_str(val items, val sep) { val self = lit("cat-str"); - seq_iter_t item_iter; - val item, peek = nil; - int more = 0; struct cat_str cs; wchar_t onech[] = wini(" "); - cat_str_init(&cs, sep, onech, self); - - seq_iter_init(self, &item_iter, items); - more = seq_get(&item_iter, &item); - while (more) - { - cat_str_measure(&cs, item, more = seq_get(&item_iter, &peek), self); - item = peek; - } - + cat_str_measure(&cs, items, self); cat_str_alloc(&cs); - - seq_iter_init(self, &item_iter, items); - more = seq_get(&item_iter, &item); - while (more) - { - cat_str_append(&cs, item, more = seq_get(&item_iter, &peek), self); - item = peek; - } + cat_str_append(&cs, items, self); return cat_str_get(&cs); } static val vscat(val sep, va_list vl1, va_list vl2, val self) { - val item, next; + val item; struct cat_str cs; wchar_t onech[] = wini(" "); cat_str_init(&cs, sep, onech, self); - for (item = va_arg(vl1, val); item != nao; item = next) - { - next = va_arg(vl1, val); - cat_str_measure(&cs, item, next != nao, self); - } + while ((item = va_arg(vl1, val)) != nao) + cat_str_measure(&cs, item, self); cat_str_alloc(&cs); - for (item = va_arg(vl2, val); item != nao; item = next) + while ((item = va_arg(vl2, val)) != nao) { - next = va_arg(vl2, val); - cat_str_append(&cs, item, next != nao, self); + cat_str_append(&cs, item, self); } return cat_str_get(&cs); @@ -5796,13 +5805,13 @@ val scat2(val s1, val s2) cat_str_init(&cs, nil, NULL, self); - cat_str_measure(&cs, s1, 1, self); - cat_str_measure(&cs, s2, 0, self); + cat_str_measure(&cs, s1, self); + cat_str_measure(&cs, s2, self); cat_str_alloc(&cs); - cat_str_append(&cs, s1, 1, self); - cat_str_append(&cs, s2, 0, self); + cat_str_append(&cs, s1, self); + cat_str_append(&cs, s2, self); return cat_str_get(&cs); } @@ -5815,13 +5824,13 @@ val scat3(val s1, val sep, val s2) cat_str_init(&cs, sep, onech, self); - cat_str_measure(&cs, s1, 1, self); - cat_str_measure(&cs, s2, 0, self); + cat_str_measure(&cs, s1, self); + cat_str_measure(&cs, s2, self); cat_str_alloc(&cs); - cat_str_append(&cs, s1, 1, self); - cat_str_append(&cs, s2, 0, self); + cat_str_append(&cs, s1, self); + cat_str_append(&cs, s2, self); return cat_str_get(&cs); } @@ -5831,26 +5840,23 @@ val join_with(val sep, struct args *args) val self = lit("join-with"); cnum index; val iter; - int more; struct cat_str cs; wchar_t onech[] = wini(" "); cat_str_init(&cs, sep, onech, self); - for (index = 0, iter = args->list, more = args_more_nozap(args, index, iter); - more;) + for (index = 0, iter = args->list; args_more_nozap(args, index, iter);) { val item = args_get_nozap(args, &index, &iter); - cat_str_measure(&cs, item, more = args_more_nozap(args, index, iter), self); + cat_str_measure(&cs, item, self); } cat_str_alloc(&cs); - for (index = 0, iter = args->list, more = args_more_nozap(args, index, iter); - more;) + for (index = 0, iter = args->list; args_more_nozap(args, index, iter);) { val item = args_get_nozap(args, &index, &iter); - cat_str_append(&cs, item, more = args_more_nozap(args, index, iter), self); + cat_str_append(&cs, item, self); } return cat_str_get(&cs); diff --git a/tests/015/split.tl b/tests/015/split.tl index 15b3f2a7..1cb13647 100644 --- a/tests/015/split.tl +++ b/tests/015/split.tl @@ -298,3 +298,16 @@ (spln 2 "," "a,b,c") ("a" "b" "c") (spln 3 "," "a,b,c") ("a" "b" "c") (spln 4 "," "a,b,c") ("a" "b" "c")) + +(mtest + (cat-str '()) "" + (cat-str '() "-") "" + (cat-str '(()) "-") "" + (cat-str '((()) ()) "-") "" + (cat-str '((()) #()) "-") "" + (cat-str '((("a" ("b")) #(#\c))) "-") "a-b-c") + +(mtest + (join-with "--" '()) "" + (join-with "--" '(("b"))) "b" + (join-with "--" '("b" #(("c") ()) "d")) "b--c--d") @@ -25644,12 +25644,17 @@ functions combine items into a single string, which is returned. Every .meta item -argument must be a character or string object. The same is true of the +argument must be a character, string or else a possibly empty +sequence of items. This rule applies recursively. + +If a .meta sep -argument, if present. +argument is present, it must be a character or string. + The .meta item-seq -argument must be a sequence of any mixture of characters or strings. +argument must be a sequence of any mixture of items which are +characters, strings or sequences of items. Note that this means that if .meta item-seq is a character string, it is a valid argument, since it is a sequence @@ -25662,47 +25667,38 @@ is empty, or no arguments are present, then all three functions return an empty string. -The +All three functions operate on an abstract sequence of character and string +items, produced by a left-to-right recursive traversal of their +.meta item-seq +or +.meta item +arguments. + +Under the +.code join-with +function, as well as the .code cat-str -function receives the items as a single list. If the +function a .meta sep -argument is present, the items are catenated together such that +argument is given to it, +the items are catenated together such that .meta sep -is interposed between them. If -.meta item-seq -contains +is interposed between them. If there are .I n -items, then +character or string items, then .I "n - 1" copies of .meta sep -occur in the resulting string. +occur in the resulting string, which is returned. -If -.meta sep -is absent, then -.code cat-str -catenates the items together directly, without any separator. - -Copies of the items appear in the resulting string in the same -order as the items appear in -.metn item-seq . - -The -.code join-with -function receives the items as arguments rather than a single -.meta item-seq -arguments. The arguments are joined into a single character string -in order, with -.meta sep -interposed between them. - -The +Under the .code join -function takes no +function, or +.code cat-str +function invoked without a .meta sep -argument. It joins all of its argument items into a single -string, in order. +argument, the items are catenated together directly, without any separator. +The resulting string is returned. .coNP Function @ split-str .synb |