]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: tools: add a function varint_bytes() to report the size of a varint
authorWilly Tarreau <w@1wt.eu>
Fri, 23 Aug 2019 17:02:26 +0000 (19:02 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 27 Aug 2019 15:14:19 +0000 (17:14 +0200)
It will sometimes be useful to encode varints to know the output size in
advance. Two versions are provided, one inline using a switch/case construct
which will be trivial for use with constants (and will be very fast albeit
huge) and one function iterating on the number which is 5 times smaller,
for use with variables.

include/common/standard.h
src/standard.c

index f0167d31aab971d498b6e96686640d12ad16093f..0b8a32726690ddb5cbc9784775d80f8c0808f152 100644 (file)
@@ -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 <v> 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 <i> into a varint (variable-length integer). The encoded
  * value is copied in <*buf>. Here is the encoding format:
  *
index 717c14a94624d0583c2e33e3eef6384fa887488e..08a2c0d46e5e6e347e59f3fdf69f8e5c29e556dc 100644 (file)
@@ -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 <v> 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)))