5 Copyright (C) 2002 Niels Möller
7 This file is part of GNU Nettle.
9 GNU Nettle is free software: you can redistribute it and/or
10 modify it under the terms of either:
12 * the GNU Lesser General Public License as published by the Free
13 Software Foundation; either version 3 of the License, or (at your
14 option) any later version.
18 * the GNU General Public License as published by the Free
19 Software Foundation; either version 2 of the License, or (at your
20 option) any later version.
22 or both in parallel, as here.
24 GNU Nettle is distributed in the hope that it will be useful,
25 but WITHOUT ANY WARRANTY; without even the implied warranty of
26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 General Public License for more details.
29 You should have received copies of the GNU General Public License and
30 the GNU Lesser General Public License along with this program. If
31 not, see http://www.gnu.org/licenses/.
44 #include "nettle-internal.h"
46 /* Initializes the iterator, but one has to call next to get to the
49 sexp_iterator_init(struct sexp_iterator *iterator,
50 unsigned length, const uint8_t *input)
52 iterator->length = length;
53 iterator->buffer = input;
56 iterator->type = SEXP_END; /* Value doesn't matter */
57 iterator->display_length = 0;
58 iterator->display = NULL;
59 iterator->atom_length = 0;
60 iterator->atom = NULL;
63 #define EMPTY(i) ((i)->pos == (i)->length)
64 #define NEXT(i) ((i)->buffer[(i)->pos++])
67 sexp_iterator_simple(struct sexp_iterator *iterator,
69 const uint8_t **string)
74 if (EMPTY(iterator)) return 0;
76 if (EMPTY(iterator)) return 0;
78 if (c >= '1' && c <= '9')
81 length = length * 10 + (c - '0');
82 if (length > (iterator->length - iterator->pos))
85 if (EMPTY(iterator)) return 0;
88 while (c >= '0' && c <= '9');
91 /* There can be only one */
100 *string = iterator->buffer + iterator->pos;
101 iterator->pos += length;
106 /* All these functions return 1 on success, 0 on failure */
108 /* Look at the current position in the data. Sets iterator->type, and
109 * ignores the old value. */
112 sexp_iterator_parse(struct sexp_iterator *iterator)
114 iterator->start = iterator->pos;
121 iterator->type = SEXP_END;
124 switch (iterator->buffer[iterator->pos])
126 case '(': /* A list */
127 iterator->type = SEXP_LIST;
131 if (!iterator->level)
135 iterator->type = SEXP_END;
138 case '[': /* Atom with display type */
140 if (!sexp_iterator_simple(iterator,
141 &iterator->display_length,
144 if (EMPTY(iterator) || NEXT(iterator) != ']')
150 /* Must be either a decimal digit or a syntax error.
151 * Errors are detected by sexp_iterator_simple. */
152 iterator->display_length = 0;
153 iterator->display = NULL;
158 iterator->type = SEXP_ATOM;
160 return sexp_iterator_simple(iterator,
161 &iterator->atom_length,
166 sexp_iterator_first(struct sexp_iterator *iterator,
167 size_t length, const uint8_t *input)
169 sexp_iterator_init(iterator, length, input);
170 return sexp_iterator_parse(iterator);
174 sexp_iterator_next(struct sexp_iterator *iterator)
176 switch (iterator->type)
182 return sexp_iterator_enter_list(iterator)
183 && sexp_iterator_exit_list(iterator);
185 /* iterator->pos should already point at the start of the next
187 return sexp_iterator_parse(iterator);
189 /* If we get here, we have a bug. */
193 /* Current element must be a list. */
195 sexp_iterator_enter_list(struct sexp_iterator *iterator)
197 if (iterator->type != SEXP_LIST)
200 if (EMPTY(iterator) || NEXT(iterator) != '(')
206 return sexp_iterator_parse(iterator);
209 /* Skips the rest of the current list */
211 sexp_iterator_exit_list(struct sexp_iterator *iterator)
213 if (!iterator->level)
216 while(iterator->type != SEXP_END)
217 if (!sexp_iterator_next(iterator))
222 return sexp_iterator_parse(iterator);
226 /* What's a reasonable interface for this? */
228 sexp_iterator_exit_lists(struct sexp_iterator *iterator,
231 assert(iterator->level >= level);
233 while (iterator->level > level)
234 if (!sexp_iterator_exit_list(iterator))
242 sexp_iterator_subexpr(struct sexp_iterator *iterator,
245 size_t start = iterator->start;
246 if (!sexp_iterator_next(iterator))
249 *length = iterator->start - start;
250 return iterator->buffer + start;
254 sexp_iterator_get_uint32(struct sexp_iterator *iterator,
257 if (iterator->type == SEXP_ATOM
258 && !iterator->display
259 && iterator->atom_length
260 && iterator->atom[0] < 0x80)
262 size_t length = iterator->atom_length;
263 const uint8_t *p = iterator->atom;
265 /* Skip leading zeros. */
291 return sexp_iterator_next(iterator);
297 sexp_iterator_check_type(struct sexp_iterator *iterator,
300 return (sexp_iterator_enter_list(iterator)
301 && iterator->type == SEXP_ATOM
302 && !iterator->display
303 && strlen(type) == iterator->atom_length
304 && !memcmp(type, iterator->atom, iterator->atom_length)
305 && sexp_iterator_next(iterator));
309 sexp_iterator_check_types(struct sexp_iterator *iterator,
311 const char * const *types)
313 if (sexp_iterator_enter_list(iterator)
314 && iterator->type == SEXP_ATOM
315 && !iterator->display)
318 for (i = 0; i<ntypes; i++)
319 if (strlen(types[i]) == iterator->atom_length
320 && !memcmp(types[i], iterator->atom,
321 iterator->atom_length))
322 return sexp_iterator_next(iterator) ? types[i] : NULL;
328 sexp_iterator_assoc(struct sexp_iterator *iterator,
330 const char * const *keys,
331 struct sexp_iterator *values)
333 TMP_DECL(found, int, NETTLE_MAX_SEXP_ASSOC);
337 TMP_ALLOC(found, nkeys);
338 for (i = 0; i<nkeys; i++)
345 switch (iterator->type)
349 if (!sexp_iterator_enter_list(iterator))
352 if (iterator->type == SEXP_ATOM
353 && !iterator->display)
355 /* Compare to the given keys */
356 for (i = 0; i<nkeys; i++)
358 /* NOTE: The strlen could be put outside of the
360 if (strlen(keys[i]) == iterator->atom_length
361 && !memcmp(keys[i], iterator->atom,
362 iterator->atom_length))
365 /* We don't allow duplicates */
368 /* Advance to point to value */
369 if (!sexp_iterator_next(iterator))
375 /* Record this position. */
376 values[i] = *iterator;
382 if (!sexp_iterator_exit_list(iterator))
387 if (!sexp_iterator_next(iterator))
392 return sexp_iterator_exit_list(iterator)
393 && (nfound == nkeys);