mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-26 14:28:30 +00:00
Initial import
This commit is contained in:
commit
c91b3c5006
14915 changed files with 590219 additions and 0 deletions
87
libc/str/varint.h
Normal file
87
libc/str/varint.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_VARINT_H_
|
||||
#define COSMOPOLITAN_LIBC_VARINT_H_
|
||||
#include "libc/limits.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
#define unzigzag(x) ((x >> 1) ^ -(x & 1))
|
||||
#define zigzag(x) _Generic((x), int32_t : zigzag32, default : zigzag64)(x)
|
||||
|
||||
forceinline int32_t zigzag32(int32_t x) {
|
||||
return (int64_t)((uint64_t)x << 1) ^ (x >> 31);
|
||||
}
|
||||
|
||||
forceinline int64_t zigzag64(int64_t x) {
|
||||
return (int64_t)((uint64_t)x << 1) ^ (x >> 63);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies variable-length integer to buffer.
|
||||
*
|
||||
* @param p needs 10+ bytes for 64-bit and 5+ for 32-bit
|
||||
* @param x is unsigned number to encode
|
||||
* @return pointer past last written byte
|
||||
* @see writesint() which has more efficient encoding for signed numbers
|
||||
*/
|
||||
forceinline uint8_t *writevint(uint8_t *p, uint64_t x) {
|
||||
do {
|
||||
*p++ = (uint8_t)(x | 0x80);
|
||||
x >>= 7;
|
||||
} while (x > 0);
|
||||
p[-1] &= 0x7f;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies variable-length signed integer to buffer.
|
||||
*
|
||||
* @param p needs 10+ bytes for 64-bit and 5+ for 32-bit
|
||||
* @param x is unsigned number to encode
|
||||
* @return pointer past last written byte
|
||||
*/
|
||||
forceinline uint8_t *writesint(uint8_t *p, int64_t x) {
|
||||
return writevint(p, zigzag(x));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads variable-length integer from buffer.
|
||||
*
|
||||
* @param x is unsigned number to encode
|
||||
* @return pointer past last read byte or -1ul on error
|
||||
*/
|
||||
forceinline uint8_t *readvint(uint8_t *p, uint8_t *pe, uint64_t *res) {
|
||||
uint8_t b;
|
||||
uint64_t x, o;
|
||||
x = 0;
|
||||
b = 0;
|
||||
while (p < pe) {
|
||||
o = *p++;
|
||||
x |= ((uint64_t)o & 0x7f) << b;
|
||||
if (!(o & 0x80)) {
|
||||
*res = x;
|
||||
return p;
|
||||
}
|
||||
if ((b += 7) > 64) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (uint8_t *)-1ul;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads variable-length zig-zagged integer from buffer.
|
||||
*
|
||||
* @param x is unsigned number to encode
|
||||
* @return pointer past last read byte or -1ul on error
|
||||
*/
|
||||
forceinline uint8_t *readsint(uint8_t *p, uint8_t *pe, int64_t *res) {
|
||||
uint64_t u;
|
||||
if ((p = readvint(p, pe, &u)) != (uint8_t *)-1ul) {
|
||||
*res = unzigzag((int64_t)u);
|
||||
return p;
|
||||
} else {
|
||||
return (uint8_t *)-1ul;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_VARINT_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue