summaryrefslogtreecommitdiff
path: root/sexp-format.c
diff options
context:
space:
mode:
authorNiels Möller <nisse@lysator.liu.se>2002-11-03 11:37:25 +0100
committerNiels Möller <nisse@lysator.liu.se>2002-11-03 11:37:25 +0100
commitb3648c8fd09484a711ff115d769248a927f0827a (patch)
treedcdf3c9d7ec3b59e52753facc72fcd46879e0837 /sexp-format.c
parentf0c0947bba6d2aa68dd5d494356ce95029b8f188 (diff)
downloadnettle-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.c154
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();
+ }
+ }
+}