No, it's not a type-length-value encoding, just a length-value encoding. I should have been more explicit in my UTF-8 reference. I'm really talking about a UTF-8 like encoding, except that it doesn't specially mark any of the continuation bytes and generalizes to lengths of 9 bytes, so the encoding (plus using zigzag encoding to put the sign bit in the least significant bit) is:
0xxxxxxS : 1 byte, 7 bits of data, -64 to 63
10xxxxxx xxxxxxxS : 2 bytes, 14 bits of data, -8192 to 8191
110xxxxx xxxxxxxx xxxxxxxS : 3 bytes, 21 bits of data, -(2^20) to 2^20 -1
1110xxxx xxxxxxxx xxxxxxxx xxxxxxxS : 4 bytes, 28 bits of data, -2^27 to 2^27-1
... and so on.
int64_t zigzag_decode(uint64_t in) {
/* Signed right-shift is implementation-defined behavior in C */
COMPILE_TIME_ASSERT( (1LL << 63) >> 63 == -1, compiler_uses_signed_arith_shift );
return (int64_t) ((((int64_t) in << 63 ) >> 63 ) ^ (in >> 1));
}
You can actually get slightly more dense packing using an encoding that doesn't have any non-canonical encodings by adding a length-dependent constant before the zigzag decoding step, but that's a bit more complicated to explain, and allows some 9 byte encoding values that won't fit in an int64_t.