diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-10-13 06:33:27 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-10-13 06:33:27 -0700 |
commit | 5f91ddea0f7f69fc5d4c1238edcb2775216bf4a8 (patch) | |
tree | a7262b5f89e371cd96463059fe1fb6110a60f948 | |
parent | 17cd878844f524ebae0024edb60c2f58ac56285d (diff) | |
download | txr-5f91ddea0f7f69fc5d4c1238edcb2775216bf4a8.tar.gz txr-5f91ddea0f7f69fc5d4c1238edcb2775216bf4a8.tar.bz2 txr-5f91ddea0f7f69fc5d4c1238edcb2775216bf4a8.zip |
find: convert to seq_info classification.
* lib.c (find): Convert switch statement to use the seq_info
function to classify the sequence. For SEQ_VECLIKE,
we still check whether the original object is a literal
or regular string to treat it specially.
-rw-r--r-- | lib.c | 80 |
1 files changed, 36 insertions, 44 deletions
@@ -8408,65 +8408,57 @@ val find(val item, val seq, val testfun, val keyfun) { testfun = default_arg(testfun, equal_f); keyfun = default_arg(keyfun, identity_f); + seq_info_t si = seq_info(seq); - seq = nullify(seq); - - switch (type(seq)) { - case NIL: - break; - case COBJ: - if (!structp(seq)) - break; - if (maybe_slot(seq, length_s)) - goto vec; - if (!maybe_slot(seq, car_s)) - break; - /* fallthrough */ - case CONS: - case LCONS: + switch (si.kind) { + case SEQ_NIL: + return nil; + case SEQ_LISTLIKE: { gc_hint(seq); - for (; seq; seq = cdr(seq)) { + for (seq = z(si.obj); seq; seq = cdr(seq)) { val elem = car(seq); val key = funcall1(keyfun, elem); if (funcall2(testfun, item, key)) return elem; } - return nil; - } - case STR: - case LIT: - if (keyfun == identity_f && - (testfun == equal_f || testfun == eql_f || testfun == eq_f)) - { - const wchar_t ch = c_chr(item); - const wchar_t *cstr = c_str(seq); - if (wcschr(cstr, ch)) - return item; - return nil; } - /* fallthrough */ - case LSTR: - vec: - { - cnum len = c_num(length(seq)); - cnum i; - - for (i = 0; i < len; i++) { - val elem = ref(seq, num(i)); - val key = funcall1(keyfun, elem); - if (funcall2(testfun, item, key)) - return elem; + return nil; + case SEQ_VECLIKE: + switch (si.type) { + case STR: + case LIT: + if (keyfun == identity_f && + (testfun == equal_f || testfun == eql_f || testfun == eq_f)) + { + const wchar_t ch = c_chr(item); + const wchar_t *cstr = c_str(seq); + if (wcschr(cstr, ch)) + return item; + return nil; } - - return nil; + /* fallthrough */ + default: + { + val vec = si.obj; + cnum len = c_num(length(vec)); + cnum i; + + for (i = 0; i < len; i++) { + val elem = ref(vec, num(i)); + val key = funcall1(keyfun, elem); + if (funcall2(testfun, item, key)) + return elem; + } + } + break; } + return nil; default: - break; + uw_throwf(error_s, lit("find: unsupported object ~s"), seq, nao); } - uw_throwf(error_s, lit("find: unsupported object ~s"), seq, nao); } val rfind(val item, val list, val testfun, val keyfun) |