3 * Writing 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,
42 format_prefix(struct nettle_buffer *buffer,
46 unsigned prefix_length = 1;
50 unsigned next = digit * 10;
60 for (; digit; length %= digit, digit /= 10)
61 if (!NETTLE_BUFFER_PUTC(buffer, '0' + length / digit))
64 if (!NETTLE_BUFFER_PUTC(buffer, ':'))
68 return prefix_length + 1;
72 format_string(struct nettle_buffer *buffer,
73 unsigned length, const uint8_t *s)
75 unsigned prefix_length = format_prefix(buffer, length);
79 if (buffer && !nettle_buffer_write(buffer, length, s))
82 return prefix_length + length;
86 sexp_vformat(struct nettle_buffer *buffer, const char *format, va_list args)
96 const char *start = format - 1;
97 unsigned length = 1 + strcspn(format, "()% \t");
98 unsigned output_length = format_string(buffer, length, start);
102 done += output_length;
103 format = start + length;
116 if (buffer && !NETTLE_BUFFER_PUTC(buffer, '('))
125 if (buffer && !NETTLE_BUFFER_PUTC(buffer, ')'))
148 /* Allow unbalanced parenthesis */
149 if (buffer && !NETTLE_BUFFER_PUTC(buffer, format[-1]))
158 unsigned output_length;
162 s = va_arg(args, const char *);
167 length = va_arg(args, unsigned);
168 s = va_arg(args, const char *);
171 output_length = format_string(buffer, length, s);
175 done += output_length;
182 unsigned output_length;
186 s = va_arg(args, const char *);
194 length = va_arg(args, unsigned);
195 s = va_arg(args, const char *);
200 if (buffer && !NETTLE_BUFFER_PUTC(buffer, '['))
204 output_length = format_string(buffer, length, s);
209 done += output_length;
211 if (buffer && !NETTLE_BUFFER_PUTC(buffer, ']'))
225 s = va_arg(args, const char *);
230 length = va_arg(args, unsigned);
231 s = va_arg(args, const char *);
234 if (buffer && !nettle_buffer_write(buffer, length, s))
242 uint32_t x = va_arg(args, uint32_t);
247 else if (x < 0x8000L)
249 else if (x < 0x800000L)
251 else if (x < 0x80000000L)
256 if (buffer && !(NETTLE_BUFFER_PUTC(buffer, '0' + length)
257 && NETTLE_BUFFER_PUTC(buffer, ':')))
260 done += (2 + length);
266 /* Leading byte needed for the sign. */
267 if (!NETTLE_BUFFER_PUTC(buffer, 0))
271 if (!NETTLE_BUFFER_PUTC(buffer, x >> 24))
275 if (!NETTLE_BUFFER_PUTC(buffer, (x >> 16) & 0xff))
279 if (!NETTLE_BUFFER_PUTC(buffer, (x >> 8) & 0xff))
283 if (!NETTLE_BUFFER_PUTC(buffer, x & 0xff))
293 const MP_INT *n = va_arg(args, const MP_INT *);
295 unsigned prefix_length;
297 length = nettle_mpz_sizeinbase_256_s(n);
298 prefix_length = format_prefix(buffer, length);
302 done += prefix_length;
306 uint8_t *space = nettle_buffer_space(buffer, length);
310 nettle_mpz_get_str_256(length, space, n);
323 sexp_format(struct nettle_buffer *buffer, const char *format, ...)
328 va_start(args, format);
329 done = sexp_vformat(buffer, format, args);