3 * Parsing s-expressions.
6 /* nettle, low-level cryptographics library
8 * Copyright (C) 2002 Niels Möller
10 * The nettle library is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or (at your
13 * option) any later version.
15 * The nettle library is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 * License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with the nettle library; see the file COPYING.LIB. If not, write to
22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
36 #include "nettle-internal.h"
38 /* Initializes the iterator, but one has to call next to get to the
41 sexp_iterator_init(struct sexp_iterator
*iterator
,
42 unsigned length
, const uint8_t *input
)
44 iterator
->length
= length
;
45 iterator
->buffer
= input
;
48 iterator
->type
= SEXP_END
; /* Value doesn't matter */
49 iterator
->display_length
= 0;
50 iterator
->display
= NULL
;
51 iterator
->atom_length
= 0;
52 iterator
->atom
= NULL
;
55 #define EMPTY(i) ((i)->pos == (i)->length)
56 #define NEXT(i) ((i)->buffer[(i)->pos++])
59 sexp_iterator_simple(struct sexp_iterator
*iterator
,
61 const uint8_t **string
)
66 if (EMPTY(iterator
)) return 0;
68 if (EMPTY(iterator
)) return 0;
70 if (c
>= '1' && c
<= '9')
73 length
= length
* 10 + (c
- '0');
74 if (length
> (iterator
->length
- iterator
->pos
))
77 if (EMPTY(iterator
)) return 0;
80 while (c
>= '0' && c
<= '9');
83 /* There can be only one */
92 *string
= iterator
->buffer
+ iterator
->pos
;
93 iterator
->pos
+= length
;
98 /* All these functions return 1 on success, 0 on failure */
100 /* Look at the current position in the data. Sets iterator->type, and
101 * ignores the old value. */
104 sexp_iterator_parse(struct sexp_iterator
*iterator
)
106 iterator
->start
= iterator
->pos
;
113 iterator
->type
= SEXP_END
;
116 switch (iterator
->buffer
[iterator
->pos
])
118 case '(': /* A list */
119 iterator
->type
= SEXP_LIST
;
123 if (!iterator
->level
)
127 iterator
->type
= SEXP_END
;
130 case '[': /* Atom with display type */
132 if (!sexp_iterator_simple(iterator
,
133 &iterator
->display_length
,
136 if (EMPTY(iterator
) || NEXT(iterator
) != ']')
142 /* Must be either a decimal digit or a syntax error.
143 * Errors are detected by sexp_iterator_simple. */
144 iterator
->display_length
= 0;
145 iterator
->display
= NULL
;
150 iterator
->type
= SEXP_ATOM
;
152 return sexp_iterator_simple(iterator
,
153 &iterator
->atom_length
,
158 sexp_iterator_first(struct sexp_iterator
*iterator
,
159 unsigned length
, const uint8_t *input
)
161 sexp_iterator_init(iterator
, length
, input
);
162 return sexp_iterator_parse(iterator
);
166 sexp_iterator_next(struct sexp_iterator
*iterator
)
168 switch (iterator
->type
)
174 return sexp_iterator_enter_list(iterator
)
175 && sexp_iterator_exit_list(iterator
);
177 /* iterator->pos should already point at the start of the next
179 return sexp_iterator_parse(iterator
);
181 /* If we get here, we have a bug. */
185 /* Current element must be a list. */
187 sexp_iterator_enter_list(struct sexp_iterator
*iterator
)
189 if (iterator
->type
!= SEXP_LIST
)
192 if (EMPTY(iterator
) || NEXT(iterator
) != '(')
198 return sexp_iterator_parse(iterator
);
201 /* Skips the rest of the current list */
203 sexp_iterator_exit_list(struct sexp_iterator
*iterator
)
205 if (!iterator
->level
)
208 while(iterator
->type
!= SEXP_END
)
209 if (!sexp_iterator_next(iterator
))
214 return sexp_iterator_parse(iterator
);
218 /* What's a reasonable interface for this? */
220 sexp_iterator_exit_lists(struct sexp_iterator
*iterator
,
223 assert(iterator
->level
>= level
);
225 while (iterator
->level
> level
)
226 if (!sexp_iterator_exit_list(iterator
))
234 sexp_iterator_subexpr(struct sexp_iterator
*iterator
,
237 unsigned start
= iterator
->start
;
238 if (!sexp_iterator_next(iterator
))
241 *length
= iterator
->start
- start
;
242 return iterator
->buffer
+ start
;
246 sexp_iterator_get_uint32(struct sexp_iterator
*iterator
,
249 if (iterator
->type
== SEXP_ATOM
250 && !iterator
->display
251 && iterator
->atom_length
252 && iterator
->atom
[0] < 0x80)
254 unsigned length
= iterator
->atom_length
;
255 const uint8_t *p
= iterator
->atom
;
257 /* Skip leading zeros. */
283 return sexp_iterator_next(iterator
);
289 sexp_iterator_check_type(struct sexp_iterator
*iterator
,
292 return (sexp_iterator_enter_list(iterator
)
293 && iterator
->type
== SEXP_ATOM
294 && !iterator
->display
295 && strlen(type
) == iterator
->atom_length
296 && !memcmp(type
, iterator
->atom
, iterator
->atom_length
)
297 && sexp_iterator_next(iterator
));
301 sexp_iterator_check_types(struct sexp_iterator
*iterator
,
303 const uint8_t * const *types
)
305 if (sexp_iterator_enter_list(iterator
)
306 && iterator
->type
== SEXP_ATOM
307 && !iterator
->display
)
310 for (i
= 0; i
<ntypes
; i
++)
311 if (strlen(types
[i
]) == iterator
->atom_length
312 && !memcmp(types
[i
], iterator
->atom
,
313 iterator
->atom_length
))
314 return sexp_iterator_next(iterator
) ? types
[i
] : NULL
;
320 sexp_iterator_assoc(struct sexp_iterator
*iterator
,
322 const uint8_t * const *keys
,
323 struct sexp_iterator
*values
)
325 TMP_DECL(found
, int, NETTLE_MAX_SEXP_ASSOC
);
329 TMP_ALLOC(found
, nkeys
);
330 for (i
= 0; i
<nkeys
; i
++)
337 switch (iterator
->type
)
341 if (!sexp_iterator_enter_list(iterator
))
344 if (iterator
->type
== SEXP_ATOM
345 && !iterator
->display
)
347 /* Compare to the given keys */
348 for (i
= 0; i
<nkeys
; i
++)
350 /* NOTE: The strlen could be put outside of the
352 if (strlen(keys
[i
]) == iterator
->atom_length
353 && !memcmp(keys
[i
], iterator
->atom
,
354 iterator
->atom_length
))
357 /* We don't allow duplicates */
360 /* Advance to point to value */
361 if (!sexp_iterator_next(iterator
))
367 /* Record this position. */
368 values
[i
] = *iterator
;
374 if (!sexp_iterator_exit_list(iterator
))
379 if (!sexp_iterator_next(iterator
))
384 return sexp_iterator_exit_list(iterator
)
385 && (nfound
== nkeys
);