]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
New file, implementing an sexp canonical syntax
authorNiels Möller <nisse@lysator.liu.se>
Sun, 29 Sep 2002 18:06:20 +0000 (20:06 +0200)
committerNiels Möller <nisse@lysator.liu.se>
Sun, 29 Sep 2002 18:06:20 +0000 (20:06 +0200)
formatter.

Rev: src/nettle/sexp_format.c:1.1

sexp_format.c [new file with mode: 0644]

diff --git a/sexp_format.c b/sexp_format.c
new file mode 100644 (file)
index 0000000..50fe6cf
--- /dev/null
@@ -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 *output,
+             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(output, length)
+    ? nettle_buffer_space(output, 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;
+  va_start(args, format);
+
+  unsigned nesting = 0;
+  
+  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();
+         }
+      }
+}