diff --git a/include/common/standard.h b/include/common/standard.h index f0167d31a..0b8a32726 100644 --- a/include/common/standard.h +++ b/include/common/standard.h @@ -201,6 +201,27 @@ static inline const char *LIM2A(unsigned long n, const char *alt) return ret; } +/* returns the number of bytes needed to encode as a varint. Be careful, use + * it only with constants as it generates a large code (typ. 180 bytes). Use the + * varint_bytes() version instead in case of doubt. + */ +int varint_bytes(uint64_t v); +static inline int __varint_bytes(uint64_t v) +{ + switch (v) { + case 0x0000000000000000 ... 0x00000000000000ef: return 1; + case 0x00000000000000f0 ... 0x00000000000008ef: return 2; + case 0x00000000000008f0 ... 0x00000000000408ef: return 3; + case 0x00000000000408f0 ... 0x00000000020408ef: return 4; + case 0x00000000020408f0 ... 0x00000001020408ef: return 5; + case 0x00000001020408f0 ... 0x00000081020408ef: return 6; + case 0x00000081020408f0 ... 0x00004081020408ef: return 7; + case 0x00004081020408f0 ... 0x00204081020408ef: return 8; + case 0x00204081020408f0 ... 0x10204081020408ef: return 9; + default: return 10; + } +} + /* Encode the integer into a varint (variable-length integer). The encoded * value is copied in <*buf>. Here is the encoding format: * diff --git a/src/standard.c b/src/standard.c index 717c14a94..08a2c0d46 100644 --- a/src/standard.c +++ b/src/standard.c @@ -4340,6 +4340,26 @@ int parse_dotted_uints(const char *str, unsigned int **nums, size_t *sz) return 1; } + +/* returns the number of bytes needed to encode as a varint. An inline + * version exists for use with constants (__varint_bytes()). + */ +int varint_bytes(uint64_t v) +{ + int len = 1; + + if (v >= 240) { + v = (v - 240) >> 4; + while (1) { + len++; + if (v < 128) + break; + v = (v - 128) >> 7; + } + } + return len; +} + /* do nothing, just a placeholder for debugging calls, the real one is in trace.c */ #ifndef USE_OBSOLETE_LINKER __attribute__((weak,format(printf, 1, 2)))