diff options
author | Niels Möller <nisse@lysator.liu.se> | 2002-11-03 11:37:25 +0100 |
---|---|---|
committer | Niels Möller <nisse@lysator.liu.se> | 2002-11-03 11:37:25 +0100 |
commit | b3648c8fd09484a711ff115d769248a927f0827a (patch) | |
tree | dcdf3c9d7ec3b59e52753facc72fcd46879e0837 /sexp-format.c | |
parent | f0c0947bba6d2aa68dd5d494356ce95029b8f188 (diff) | |
download | nettle-b3648c8fd09484a711ff115d769248a927f0827a.tar.gz |
renamed file
Rev: src/nettle/sexp-format.c:1.1
Rev: src/nettle/sexp_format.c:1.4(DEAD)
Diffstat (limited to 'sexp-format.c')
-rw-r--r-- | sexp-format.c | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/sexp-format.c b/sexp-format.c new file mode 100644 index 00000000..2480613c --- /dev/null +++ b/sexp-format.c @@ -0,0 +1,154 @@ +/* sexp-output.c + * + * Writing s-expressions. + */ + +/* nettle, low-level cryptographics library + * + * Copyright (C) 2002 Niels Möller + * + * The nettle library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The nettle library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the nettle library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include "sexp.h" +#include "buffer.h" + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#if HAVE_LIBGMP +# include "bignum.h" +#endif + +static int +format_prefix(struct nettle_buffer *buffer, + unsigned length) +{ + unsigned prefix_length; + char prefix[10]; + + /* NOTE: Using the return value of sprintf is not entirely + * portable. */ + prefix_length = snprintf(prefix, sizeof(prefix), "%u:", length); + if (prefix_length >= sizeof(prefix)) + return 0; + + return nettle_buffer_write(buffer, prefix_length, prefix); +} + +static int +format_length_string(struct nettle_buffer *buffer, + unsigned length, const char *s) +{ + return format_prefix(buffer, length) + && nettle_buffer_write(buffer, length, s); +} + +static uint8_t * +format_space(struct nettle_buffer *buffer, + unsigned length) +{ + return format_prefix(buffer, length) + ? nettle_buffer_space(buffer, length) : NULL; +} + +static int +format_string(struct nettle_buffer *buffer, + const char *s) +{ + return format_length_string(buffer, strlen(s), s); +} + +int +sexp_format(struct nettle_buffer *buffer, const char *format, ...) +{ + va_list args; + unsigned nesting = 0; + + va_start(args, format); + + for (;;) + switch (*format++) + { + case '\0': + if (nesting) + { + fail: + va_end(args); + return 0; + } + else + { + va_end(args); + return 1; + } + case '(': + if (!NETTLE_BUFFER_PUTC(buffer, '(')) + goto fail; + + nesting++; + break; + + case ')': + if (!nesting) + abort(); + if (!NETTLE_BUFFER_PUTC(buffer, ')')) + goto fail; + + nesting--; + break; + + case '%': + switch (*format++) + { + case 's': + { + const char *s = va_arg(args, const char *); + format_string(buffer, s); + break; + } + case 'b': + { +#if HAVE_LIBGMP + const MP_INT *n = va_arg(args, const MP_INT *); + uint8_t *space; + unsigned length; + + if (mpz_sgn(n) < 0) + goto fail; + + length = nettle_mpz_sizeinbase_256(n); + + space = format_space(buffer, length); + if (!space) + goto fail; + nettle_mpz_get_str_256(length, space, n); +#else /* ! HAVE_LIBGMP */ + abort(); +#endif /* ! HAVE_LIBGMP */ + break; + } + default: + abort(); + } + } +} |