100 lines
3.5 KiB
C
100 lines
3.5 KiB
C
// "variablebyte.h" C Version port by powturbo from https://github.com/lemire/FastPFor
|
|
/**
|
|
* This code is released under the
|
|
* Apache License Version 2.0 http://www.apache.org/licenses/.
|
|
*
|
|
* (c) Daniel Lemire, http://lemire.me/en/
|
|
*/
|
|
|
|
#define extract7bits(i, val) (val >> (7 * i)) & ((1U << 7) - 1)
|
|
#define extract7bitsmaskless(i, val) (val >> (7 * i))
|
|
|
|
unsigned char *vbyteenc(unsigned *in, const size_t length, unsigned *out/*,
|
|
size_t &nvalue*/) {
|
|
unsigned char *bout = (unsigned char *)(out);
|
|
//const unsigned char *const initbout = (unsigned char *)(out);
|
|
//unsigned prev = 0;
|
|
size_t k;
|
|
for (k = 0; k < length; ++k) {
|
|
const unsigned val = /*delta ? in[k] - prev :*/ in[k];
|
|
//if (delta) prev = in[k];
|
|
/**
|
|
* Code below could be shorter. Whether it could be faster
|
|
* depends on your compiler and machine.
|
|
*/
|
|
if (val < (1U << 7)) {
|
|
*bout = (unsigned char)(val | (1U << 7));
|
|
++bout;
|
|
} else if (val < (1U << 14)) {
|
|
*bout = extract7bits(0,val);
|
|
++bout;
|
|
*bout = extract7bitsmaskless(1,val) | (1U << 7);
|
|
++bout;
|
|
} else if (val < (1U << 21)) {
|
|
*bout = extract7bits(0,val);
|
|
++bout;
|
|
*bout = extract7bits(1,val);
|
|
++bout;
|
|
*bout = extract7bitsmaskless(2,val) | (1U << 7);
|
|
++bout;
|
|
} else if (val < (1U << 28)) {
|
|
*bout = extract7bits(0, val);
|
|
++bout;
|
|
*bout = extract7bits(1, val);
|
|
++bout;
|
|
*bout = extract7bits(2, val);
|
|
++bout;
|
|
*bout = extract7bitsmaskless(3, val) | (1U << 7);
|
|
++bout;
|
|
} else {
|
|
*bout = extract7bits(0,val);
|
|
++bout;
|
|
*bout = extract7bits(1,val);
|
|
++bout;
|
|
*bout = extract7bits(2,val);
|
|
++bout;
|
|
*bout = extract7bits(3,val);
|
|
++bout;
|
|
*bout = extract7bitsmaskless(4,val) | (1U << 7);
|
|
++bout;
|
|
}
|
|
}
|
|
/*while (needPaddingTo32Bits(bout)) {
|
|
*bout++ = 0;
|
|
}
|
|
const size_t storageinbytes = bout - initbout;
|
|
assert((storageinbytes % 4) == 0);
|
|
nvalue = storageinbytes / 4;*/
|
|
return bout;
|
|
}
|
|
|
|
|
|
unsigned char *vbytedec(const unsigned char *in, const size_t length,
|
|
unsigned *out/*, size_t &nvalue*/) {
|
|
unsigned prev = 0;
|
|
if (length == 0) {
|
|
//nvalue = 0;
|
|
return (unsigned char *)in;//abort
|
|
}
|
|
const unsigned char *inbyte = (const unsigned char *)(in);
|
|
const unsigned char *const endbyte = (const unsigned char *)(out
|
|
+ length);
|
|
//const unsigned *const initout(out);
|
|
|
|
while ((unsigned *)endbyte > out) {
|
|
unsigned int shift = 0; unsigned v;
|
|
for (v = 0; (unsigned *)endbyte > out; shift += 7) {
|
|
unsigned char c = *inbyte++;
|
|
v += ((c & 127) << shift);
|
|
if ((c & 128)) {
|
|
*out++ = /*delta ? (prev = v + prev) :*/ v;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//nvalue = out - initout;
|
|
//inbyte = padTo32bits(inbyte);
|
|
return (unsigned char *)inbyte;
|
|
}
|
|
|