|
|
|
|
|
by KMag
3748 days ago
|
|
A real implementation would probably be switch-driven, but I whipped up a terse implementation for a big-endian bijective encoder to go with my other comment (tested, but test code omitted): int varint_u64_encode(uint8_t** start, const uint8_t* limit, uint64_t value) {
uint64_t offset;
uint8_t* position;
int bytes;
for (bytes = 1, offset = 0x80; value >= offset && bytes < 9; ++bytes) {
offset = (offset << 7 ) | 0x80;
}
position = *start;
value -= ( offset >> 7 ) ^ 1;
if (position + bytes > limit) {return 0; /* not enough space */}
*position = (((uint8_t)0xFF) << (9-bytes)) | (uint8_t)(value >> ((bytes-1) * 8 ));
for (++position; --bytes > 0; ++position) {
*position = (uint8_t) (value >> ((bytes-1) * 8));
}
*start = position;
return 1;
}
int varint_u64_decode(const uint8_t** start, const uint8_t* limit, uint64_t* result) {
uint64_t value;
uint64_t offset;
const uint8_t* position;
int bytes;
uint8_t mask;
position = *start; offset = 0;
for(bytes=1, mask = 0x80; (mask & *position) == mask && bytes < 9; ++bytes) {
mask = 0x80 | (mask >> 1);
offset = (offset << 7) | 0x80;
}
if (position + bytes > limit) { return 0; /* not enough space */}
value = (~mask) & *position;
++ position;
for(; --bytes > 0; ++position) {
value = (value << 8) + *position;
}
value += offset;
if (bytes == 9 && value < (1uLL << 56)) {return 0; /* overflow, non-canonical encoding */ }
*result = value;
*start = position;
return 1;
}
|
|