/* Read and write compressed (up to) 64-bit integers. */
/* Writecompressedunsignedinteger,efficientversionwithoutassuming unalignedwrites.
*/ unsignedchar *compr_int_write(unsignedchar *p, uint64_t v) { // Compute bytes needed to store the value v plus 3 bits encoding length.
uint32_t needed_bits_minus_1= 66 - my_nlz(v|1);
uint32_t needed_bytes= (needed_bits_minus_1 >> 3) + 1;
// Compute the encoding of the length. // We need 1-9 bytes. Use 9 bytes instead of 8, so we can encode the // length in 3 bits for (1, 2, ..., 7, or 9 bytes).
uint32_t bytes= needed_bytes | (needed_bytes >> 3);
uint32_t len= needed_bytes - 1; // Encode 1-7 as 0-6, and encode 8,9 both as 8.
len-= (len >> 3);
// Compute the first 64-bit word to write.
uintptr_t offset= (uintptr_t)p & (uintptr_t)7;
uintptr_t offset_bits= offset << 3;
uint64_t v1= (len | (v << 3)) << offset_bits;
uint64_t *p1= (uint64_t *)(p - offset);
uint64_t mask1= ~(uint64_t)0 << offset_bits;
// Compute the second word to write (if any).
uint64_t v2= v >> ((64 - 3) - offset_bits);
uint64_t *p2= p1 + 1;
// Write the value into next one or two 64-bit words, as needed. // Two words are needed if (offset + bytes) cross into the next word. #ifdef WORDS_BIGENDIAN /* Hereitmightbepossibletouseaslightlymoreefficientendian conversiononbig-endian,sinceweknowthepointeris8-bytealigned.
*/
int8store((unsignedchar *)p1,
(uint8korr((unsignedchar *)p1) & ~mask1) | v1); #else
*p1= (*p1 & ~mask1) | v1; #endif if (offset + bytes >= 8) { #ifdef WORDS_BIGENDIAN
int8store((unsignedchar *)p2, v2); #else
*p2= v2; #endif
} return p + bytes;
}
// Smaller version that assumes unaligned writes of 8-bit values is ok, and // that there are up to 8 scratch bytes available after the value written. unsignedchar *compr_int_write_le_unaligned_buffer(unsignedchar *p, uint64_t v) { // Compute bytes needed to store the value v plus 3 bits encoding length.
uint32_t needed_bits_minus_1= 66 - my_nlz(v|1);
uint32_t needed_bytes= (needed_bits_minus_1 >> 3) + 1;
// Compute the encoding of the length. // We need 1-9 bytes. Use 9 bytes instead of 8, so we can encode the // length in 3 bits for (1, 2, ..., 7, or 9 bytes).
uint32_t bytes= needed_bytes | (needed_bytes >> 3);
uint32_t len= needed_bytes - 1; // Encode 1-7 as 0-6, and encode 8,9 both as 8.
len-= (len >> 3);
// Write the (up to) 9 bytes, prefering redundant write to conditional jump.
*(uint64_t *)p= len | (v << 3);
*(p+8)= v >> 63; return p + bytes;
}
// Generic version without assumptions. unsignedchar *compr_int_write_generic(unsignedchar *p, uint64_t v) { // Compute bytes needed to store the value v plus 3 bits encoding length.
uint32_t needed_bits_minus_1= 66 - my_nlz(v|1);
uint32_t needed_bytes= (needed_bits_minus_1 >> 3) + 1;
// Compute the encoding of the length. // We need 1-9 bytes. Use 9 bytes instead of 8, so we can encode the // length in 3 bits for (1, 2, ..., 7, or 9 bytes).
uint32_t bytes= needed_bytes | (needed_bytes >> 3);
uint32_t len= needed_bytes - 1; // Encode 1-7 as 0-6, and encode 8,9 both as 8.
len-= (len >> 3);
// Write the necessary bytes out.
*p++= len | (v << 3);
v >>= 5; while (--bytes > 0) {
*p++= v;
v>>= 8;
} return p;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.