summaryrefslogtreecommitdiffstats
path: root/stream.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-05-04 07:19:15 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-05-04 07:19:15 -0700
commitf32073001a616fad05b04dd8451292350d572352 (patch)
tree8da6c8bbf5b131b5c815248cdb1ecafdf80c2fbb /stream.c
parent0c07bd4a499379c47916ce7cbf8d03af79e3aa98 (diff)
downloadtxr-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.c48
1 files changed, 35 insertions, 13 deletions
diff --git a/stream.c b/stream.c
index 52389245..b565b57e 100644
--- a/stream.c
+++ b/stream.c
@@ -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;