int sexp_iterator_check_type(struct sexp_iterator *iterator, const uint8_t *type) { return (sexp_iterator_enter_list(iterator) && iterator->type == SEXP_ATOM && !iterator->display && strlen(type) == iterator->atom_length && !memcmp(type, iterator->atom, iterator->atom_length) && sexp_iterator_next(iterator)); }
const uint8_t * sexp_iterator_check_types(struct sexp_iterator *iterator, unsigned ntypes, const uint8_t * const *types) { if (sexp_iterator_enter_list(iterator) && iterator->type == SEXP_ATOM && !iterator->display) { unsigned i; for (i = 0; i<ntypes; i++) if (strlen(types[i]) == iterator->atom_length && !memcmp(types[i], iterator->atom, iterator->atom_length)) return sexp_iterator_next(iterator) ? types[i] : NULL; } return NULL; }
int sexp_iterator_next(struct sexp_iterator *iterator) { switch (iterator->type) { case SEXP_END: return 1; case SEXP_LIST: /* Skip this list */ return sexp_iterator_enter_list(iterator) && sexp_iterator_exit_list(iterator); case SEXP_ATOM: /* iterator->pos should already point at the start of the next * element. */ return sexp_iterator_parse(iterator); } /* If we get here, we have a bug. */ abort(); }
int sexp_iterator_assoc(struct sexp_iterator *iterator, unsigned nkeys, const uint8_t * const *keys, struct sexp_iterator *values) { TMP_DECL(found, int, NETTLE_MAX_SEXP_ASSOC); unsigned nfound; unsigned i; TMP_ALLOC(found, nkeys); for (i = 0; i<nkeys; i++) found[i] = 0; nfound = 0; for (;;) { switch (iterator->type) { case SEXP_LIST: /* FIXME: Use sexp_iterator_check_type? Problem is to * distinguish syntax errors from unkown keys (which we want * to just ignore). */ if (!sexp_iterator_enter_list(iterator)) return 0; if (iterator->type == SEXP_ATOM && !iterator->display) { /* Compare to the given keys */ for (i = 0; i<nkeys; i++) { /* NOTE: The strlen could be put outside of the * loop */ if (strlen(keys[i]) == iterator->atom_length && !memcmp(keys[i], iterator->atom, iterator->atom_length)) { if (found[i]) /* We don't allow duplicates */ return 0; /* Advance to point to value */ if (!sexp_iterator_next(iterator)) return 0; found[i] = 1; nfound++; /* Record this position. */ values[i] = *iterator; break; } } } if (!sexp_iterator_exit_list(iterator)) return 0; break; case SEXP_ATOM: /* Just ignore */ if (!sexp_iterator_next(iterator)) return 0; break; case SEXP_END: return sexp_iterator_exit_list(iterator) && (nfound == nkeys); default: abort(); } } }
void test_main(void) { struct sexp_iterator i; uint32_t x; ASSERT(sexp_iterator_first(&i, LDATA(""))); ASSERT(i.type == SEXP_END); ASSERT(sexp_iterator_first(&i, LDATA("()"))); ASSERT(i.type == SEXP_LIST && sexp_iterator_enter_list(&i) && i.type == SEXP_END && sexp_iterator_exit_list(&i) && i.type == SEXP_END); ASSERT(sexp_iterator_first(&i, LDATA("("))); ASSERT(i.type == SEXP_LIST && !sexp_iterator_enter_list(&i)); /* Check integers. */ ASSERT(sexp_iterator_first(&i, LDATA("1:\0" "1:\x11" "2:\x00\x11" "2:\x00\x80" "5:\x00\xaa\xbb\xcc\xdd"))); ASSERT(sexp_iterator_get_uint32(&i, &x) && x == 0); ASSERT(sexp_iterator_get_uint32(&i, &x) && x == 0x11); ASSERT(sexp_iterator_get_uint32(&i, &x) && x == 0x11); ASSERT(sexp_iterator_get_uint32(&i, &x) && x == 0x80); ASSERT(sexp_iterator_get_uint32(&i, &x) && x == 0xaabbccdd); ASSERT(sexp_iterator_first(&i, LDATA("3:foo0:[3:bar]12:xxxxxxxxxxxx"))); ASSERT(i.type == SEXP_ATOM && !i.display_length && !i.display && i.atom_length == 3 && MEMEQ(3, "foo", i.atom) && sexp_iterator_next(&i) && i.type == SEXP_ATOM && !i.display_length && !i.display && !i.atom_length && i.atom && sexp_iterator_next(&i) && i.type == SEXP_ATOM && i.display_length == 3 && MEMEQ(3, "bar", i.display) && i.atom_length == 12 && MEMEQ(12, "xxxxxxxxxxxx", i.atom) && sexp_iterator_next(&i) && i.type == SEXP_END); /* Same data, transport encoded. */ { struct tstring *s = tstring_data(LDATA("{Mzpmb28=} {MDo=} {WzM6YmFyXTEyOnh4eHh4eHh4eHh4eA==}")); ASSERT(sexp_transport_iterator_first (&i, s->length, s->data)); ASSERT(i.type == SEXP_ATOM && !i.display_length && !i.display && i.atom_length == 3 && MEMEQ(3, "foo", i.atom) && sexp_iterator_next(&i) && i.type == SEXP_ATOM && !i.display_length && !i.display && !i.atom_length && i.atom && sexp_iterator_next(&i) && i.type == SEXP_ATOM && i.display_length == 3 && MEMEQ(3, "bar", i.display) && i.atom_length == 12 && MEMEQ(12, "xxxxxxxxxxxx", i.atom) && sexp_iterator_next(&i) && i.type == SEXP_END); } { static const uint8_t *keys[2] = { "n", "e" }; struct sexp_iterator v[2]; ASSERT(sexp_iterator_first(&i, LDATA("((1:n2:xx3:foo)0:(1:y)(1:e))"))); ASSERT(sexp_iterator_enter_list(&i) && sexp_iterator_assoc(&i, 2, keys, v)); ASSERT(v[0].type == SEXP_ATOM && !v[0].display_length && !v[0].display && v[0].atom_length == 2 && MEMEQ(2, "xx", v[0].atom) && sexp_iterator_next(&v[0]) && v[0].type == SEXP_ATOM && !v[0].display_length && !v[0].display && v[0].atom_length == 3 && MEMEQ(3, "foo", v[0].atom) && sexp_iterator_next(&v[0]) && v[0].type == SEXP_END); ASSERT(v[1].type == SEXP_END); ASSERT(sexp_iterator_first(&i, LDATA("((1:n))"))); ASSERT(sexp_iterator_enter_list(&i) && !sexp_iterator_assoc(&i, 2, keys, v)); ASSERT(sexp_iterator_first(&i, LDATA("((1:n)(1:n3:foo))"))); ASSERT(sexp_iterator_enter_list(&i) && !sexp_iterator_assoc(&i, 2, keys, v)); } }