From eb13267f82e848d9a9b38a2791e5c7008bf8d157 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Wed, 27 Apr 2016 00:39:31 +0200 Subject: zstr: add new parameter, n: the known limit out the length of the output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- src/zstr.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/zstr.c b/src/zstr.c index d10cdff..308c7ef 100644 --- a/src/zstr.c +++ b/src/zstr.c @@ -55,10 +55,10 @@ sprintint_min(char *buf, zahl_char_t v) char * -zstr(z_t a, char *b) +zstr(z_t a, char *b, size_t n) { char buf[19 + 1]; - size_t n, len, neg; + size_t len, neg, last, tot = 0; char overridden = 0; if (unlikely(zzero(a))) { @@ -69,7 +69,17 @@ zstr(z_t a, char *b) return b; } - n = zstr_length(a, 10); + if (!n) { + /* This is not the most efficient way to handle this. It should + * be faster to allocate buffers that sprintint_fix and + * sprintint_min print to, and then allocate `b` and copy the + * buffers in reverse order into `b`. However, that is an overly + * complicated solution. You probably already know the maximum + * length or do not care about performance. Another disadvantage + * with calculating the length before-hand, means that it is not + * possible to reallocate `b` if it is too small. */ + n = zstr_length(a, 10); + } if (unlikely(!b) && unlikely(!(b = malloc(n + 1)))) libzahl_memfailure(); @@ -79,7 +89,7 @@ zstr(z_t a, char *b) b[0] = '-'; b += neg; n -= neg; - n = n > 19 ? (n - 19) : 0; + n = (last = n) > 19 ? (n - 19) : 0; for (;;) { zdivmod(num, rem, num, libzahl_const_1e19); @@ -87,12 +97,16 @@ zstr(z_t a, char *b) sprintint_fix(b + n, zzero(rem) ? 0 : rem->chars[0]); b[n + 19] = overridden; overridden = b[n]; - n = n > 19 ? (n - 19) : 0; + n = (last = n) > 19 ? (n - 19) : 0; + tot += 19; } else { len = sprintint_min(buf, rem->chars[0]); - if (overridden) - buf[len] = b[n + len]; - memcpy(b + n, buf, len + 1); + if (tot) { + memcpy(b, buf, len); + memmove(b + len, b + last, tot + 1); + } else { + memcpy(b, buf, len + 1); + } break; } } -- cgit v1.2.3-70-g09d2