diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-05-04 07:19:15 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-05-04 07:19:15 -0700 |
commit | f32073001a616fad05b04dd8451292350d572352 (patch) | |
tree | 8da6c8bbf5b131b5c815248cdb1ecafdf80c2fbb /stream.c | |
parent | 0c07bd4a499379c47916ce7cbf8d03af79e3aa98 (diff) | |
download | txr-f32073001a616fad05b04dd8451292350d572352.tar.gz txr-f32073001a616fad05b04dd8451292350d572352.tar.bz2 txr-f32073001a616fad05b04dd8451292350d572352.zip |
format: ~x/~X specifiers support buffers.
* buf.c (buf_hex): New function.
* buf.h (buf_hex): Declared.
* stream.c (formatv): Support printing of buffers in hex
via temporary buffer containing hex characters, similarly
to how bignums are handled.
* tests/018/format.tl: New file, providing some coverage over
new and affected code.
Diffstat (limited to 'stream.c')
-rw-r--r-- | stream.c | 48 |
1 files changed, 35 insertions, 13 deletions
@@ -3407,19 +3407,41 @@ val formatv(val stream_in, val fmtstr, struct args *al) obj = args_get_checked(self, al, &arg_ix); typ = type(obj); hex: - if (typ == BGNUM) { - int nchars = mp_radix_size(mp(obj), 16); - if (nchars >= convert(int, sizeof (num_buf))) - pnum = coerce(char *, chk_malloc(nchars + 1)); - mp_toradix_case(mp(obj), coerce(unsigned char *, pnum), 16, ch == 'x'); - } else { - const char *fmt = ch == 'x' ? num_fmt->hex : num_fmt->HEX; - value = c_num(obj, self); - if (value < 0) { - num_buf[0] = '-'; - sprintf(num_buf + 1, fmt, -value); - } else { - sprintf(num_buf, fmt, value); + switch (typ) { + case BGNUM: + { + int nchars = mp_radix_size(mp(obj), 16); + if (nchars >= convert(int, sizeof (num_buf))) + pnum = coerce(char *, chk_malloc(nchars + 1)); + mp_toradix_case(mp(obj), coerce(unsigned char *, pnum), 16, ch == 'x'); + } + break; + case BUF: + { + ucnum len = c_unum(length_buf(obj), self); + ucnum nchars = 2 * len + 1; + + if (len >= INT_PTR_MAX) + uw_throwf(error_s, lit("~a: ~~~a conversion given " + "too large a buf argument"), + self, chr(ch), nao); + + pnum = coerce(char *, chk_malloc(nchars)); + buf_hex(obj, pnum, nchars, ch == 'X'); + } + break; + case NUM: + case CHR: + default: + { + const char *fmt = ch == 'x' ? num_fmt->hex : num_fmt->HEX; + value = c_num(obj, self); + if (value < 0) { + num_buf[0] = '-'; + sprintf(num_buf + 1, fmt, -value); + } else { + sprintf(num_buf, fmt, value); + } } } goto output_num; |