diff --git a/include/cc_print.h b/include/cc_print.h index f26da912a..55d87edf7 100644 --- a/include/cc_print.h +++ b/include/cc_print.h @@ -44,7 +44,10 @@ extern "C" { /* behavior undefined if there isn't enough space in buf */ size_t cc_print_uint64_unsafe(char *buf, uint64_t n); +size_t cc_print_int64_unsafe(char *buf, int64_t n); + size_t cc_print_uint64(char *buf, size_t size, uint64_t n); +size_t cc_print_int64(char *buf, size_t size, int64_t n); size_t _scnprintf(char *buf, size_t size, const char *fmt, ...); size_t _vscnprintf(char *buf, size_t size, const char *fmt, va_list args); diff --git a/include/cc_util.h b/include/cc_util.h index e0967a852..d9c13955b 100644 --- a/include/cc_util.h +++ b/include/cc_util.h @@ -57,6 +57,8 @@ extern "C" { * # define UINT16_MAX (65535) * # define UINT32_MAX (4294967295U) * # define UINT64_MAX (__UINT64_C(18446744073709551615)) + * + * # define INT64_MIN -9223372036854775808LL */ #define CC_UINT8_MAXLEN (3 + 1) #define CC_UINT16_MAXLEN (5 + 1) @@ -64,6 +66,8 @@ extern "C" { #define CC_UINT64_MAXLEN (20 + 1) #define CC_UINTMAX_MAXLEN CC_UINT64_MAXLEN +#define CC_INT64_MAXLEN (1 + 19 + 1) + /* alignment */ /* Make data 'd' or pointer 'p', n-byte aligned, where n is a power of 2 */ #define CC_ALIGNMENT sizeof(unsigned long) /* platform word */ diff --git a/src/cc_print.c b/src/cc_print.c index 65243fa41..7000ff269 100644 --- a/src/cc_print.c +++ b/src/cc_print.c @@ -22,6 +22,9 @@ * implementation as a reference (folly/Conv.h) */ +/* use our own macro instead of llabs() to make sure it works with INT64_MIN */ +#define abs_int64(_x) ((_x) >= 0 ? (_x) : -(_x)) + static inline void _print_uint64(char *buf, size_t d, uint64_t n) { @@ -46,6 +49,22 @@ cc_print_uint64_unsafe(char *buf, uint64_t n) return d; } +size_t +cc_print_int64_unsafe(char *buf, int64_t n) +{ + size_t d; + uint64_t ab = abs_int64(n); + + if (n < 0) { + *buf++ = '-'; + } + + d = digits(ab); + _print_uint64(buf, d, n); + + return (n < 0) ? d + 1 : d; +} + size_t cc_print_uint64(char *buf, size_t size, uint64_t n) { @@ -61,6 +80,27 @@ cc_print_uint64(char *buf, size_t size, uint64_t n) return d; } +size_t +cc_print_int64(char *buf, size_t size, int64_t n) +{ + size_t d; + uint64_t ab = abs_int64(n); + + d = digits(ab) + (n < 0); + if (size < d) { + return 0; + } + + if (n < 0) { + *buf++ = '-'; + d--; + } + + _print_uint64(buf, d, n); + + return (n < 0) ? d + 1 : d; +} + size_t _vscnprintf(char *buf, size_t size, const char *fmt, va_list args) {