Created
November 6, 2012 17:34
-
-
Save matteobertozzi/4026228 to your computer and use it in GitHub Desktop.
VarInt with with length in the head
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * Variable length int encoding. The 1st byte contains the number of bytes left. | |
| * Compared to the 7bit vint-encoding, is worst on small numbers (< 21bit) but | |
| * better with large numbers. | |
| * | |
| * 0: 11110000 -> 4 v7 | |
| * 1: 00000000 -> 8 (12) v7 (14) | |
| * 2: 00000000 -> 8 (20) v7 (21) | |
| * 3: 00000000 -> 8 (28) v7 (28) | |
| * 4: 00000000 -> 8 (36) v7 (35) | |
| * 5: 00000000 -> 8 (44) v7 (42) | |
| * 6: 00000000 -> 8 (52) v7 (49) | |
| * 7: 00000000 -> 8 (60) v7 (56) | |
| * 8: 00000000 -> 8 (68) v7 (63) | |
| * 9: v7 (64) | |
| */ | |
| unsigned int vint_length (uint64_t value) { | |
| if (value < (1ULL << 28)) { | |
| if (value < (1 << 12)) { | |
| if (value < (1 << 4)) return(1); | |
| return(2); | |
| } | |
| if (value < (1ULL << 20)) return(3); | |
| return(4); | |
| } else { | |
| if (value < (1ULL << 36)) return(5); | |
| if (value < (1ULL << 44)) return(6); | |
| if (value < (1ULL << 52)) return(7); | |
| if (value < (1ULL << 60)) return(8); | |
| } | |
| return(9); | |
| } | |
| int vint_encode (unsigned char *buf, uint64_t value) { | |
| unsigned int length = vint_length(value) - 1; | |
| buf[0] = (length << 4) | (value & 0xf); | |
| switch (length) { | |
| case 8: buf[8] = (value >> 60) & 0xff; | |
| case 7: buf[7] = (value >> 52) & 0xff; | |
| case 6: buf[6] = (value >> 44) & 0xff; | |
| case 5: buf[5] = (value >> 36) & 0xff; | |
| case 4: buf[4] = (value >> 28) & 0xff; | |
| case 3: buf[3] = (value >> 20) & 0xff; | |
| case 2: buf[2] = (value >> 12) & 0xff; | |
| case 1: buf[1] = (value >> 4) & 0xff; | |
| } | |
| return(1 + length); | |
| } | |
| int vint_decode (unsigned char *buf, uint64_t *value) { | |
| unsigned int length; | |
| uint64_t result; | |
| result = buf[0] & 0xf; | |
| switch ((length = buf[0] >> 4)) { | |
| case 8: result += ((uint64_t)buf[8]) << 60; | |
| case 7: result += ((uint64_t)buf[7]) << 52; | |
| case 6: result += ((uint64_t)buf[6]) << 44; | |
| case 5: result += ((uint64_t)buf[5]) << 36; | |
| case 4: result += ((uint64_t)buf[4]) << 28; | |
| case 3: result += ((uint64_t)buf[3]) << 20; | |
| case 2: result += buf[2] << 12; | |
| case 1: result += buf[1] << 4; | |
| } | |
| *value = result; | |
| return(1 + length); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment