diff --git a/CHANGES b/CHANGES index e7b9e13..970d6e1 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,7 @@ use inttypes.h to declare ints in uint*.h escape more in fmt_ldapescape try to catch malicious input in textcode fmt_* functions + fmt_xlonglong was utterly broken (Johannes Vetter) 0.25: array_allocate no longer truncates the array diff --git a/fmt/fmt_xlonglong.c b/fmt/fmt_xlonglong.c index ff9e9e8..2920712 100644 --- a/fmt/fmt_xlonglong.c +++ b/fmt/fmt_xlonglong.c @@ -1,10 +1,17 @@ #include "fmt.h" +static inline char tohex(char c) { + return c>=10?c-10+'a':c+'0'; +} + size_t fmt_xlonglong(char *dest,unsigned long long i) { - int tmp=0; - if (i>>32) { - tmp=fmt_xlong(dest,i>>32); - if (dest) dest+=tmp; - } - return tmp+fmt_xlong(dest,i&0xffffffff); + unsigned long long len,tmp; + /* first count the number of bytes needed */ + for (len=1, tmp=i; tmp>15; ++len) tmp>>=4; + if (dest) + for (tmp=i, dest+=len; ; ) { + *--dest = tohex(tmp&15); + if (!(tmp>>=4)) break; + } + return len; } diff --git a/test/fmt_longlong.c b/test/fmt_longlong.c index 796f0fa..76643fa 100644 --- a/test/fmt_longlong.c +++ b/test/fmt_longlong.c @@ -2,6 +2,7 @@ #include #include #include +#include int main() { char buf[1024]; @@ -25,5 +26,7 @@ int main() { assert(fmt_longlong(buf,-1234567890)==11); buf[11]=0; assert(str_equal(buf,"-1234567890")); assert(scan_longlong(buf,&l)==11); assert(l==-1234567890); + + assert(fmt_xlonglong(buf,0x8000000000000000)==16 && byte_equal(buf,16,"8000000000000000")); return 0; }