Use variable-length zigzag for ints and long longs

This commit is contained in:
Eric Fischer 2015-06-17 16:46:36 -07:00
parent 9b34f7e6e3
commit 55e93a5d37

View File

@ -60,13 +60,25 @@ size_t fwrite_check(const void *ptr, size_t size, size_t nitems, FILE *stream, c
} }
void serialize_int(FILE *out, int n, long long *fpos, const char *fname) { void serialize_int(FILE *out, int n, long long *fpos, const char *fname) {
fwrite_check(&n, sizeof(int), 1, out, fname); serialize_long_long(out, n, fpos, fname);
*fpos += sizeof(int);
} }
void serialize_long_long(FILE *out, long long n, long long *fpos, const char *fname) { void serialize_long_long(FILE *out, long long n, long long *fpos, const char *fname) {
fwrite_check(&n, sizeof(long long), 1, out, fname); unsigned long long zigzag = (n << 1) ^ (n >> 63);
*fpos += sizeof(long long);
while (1) {
unsigned char b = zigzag & 0x7F;
if ((zigzag >> 7) != 0) {
b |= 0x80;
fwrite_check(&b, sizeof(unsigned char), 1, out, fname);
*fpos += 1;
zigzag >>= 7;
} else {
fwrite_check(&b, sizeof(unsigned char), 1, out, fname);
*fpos += 1;
break;
}
}
} }
void serialize_byte(FILE *out, signed char n, long long *fpos, const char *fname) { void serialize_byte(FILE *out, signed char n, long long *fpos, const char *fname) {
@ -156,13 +168,29 @@ void parse_geometry(int t, json_object *j, unsigned *bbox, long long *fpos, FILE
} }
void deserialize_int(char **f, int *n) { void deserialize_int(char **f, int *n) {
memcpy(n, *f, sizeof(int)); long long ll;
*f += sizeof(int); deserialize_long_long(f, &ll);
*n = ll;
} }
void deserialize_long_long(char **f, long long *n) { void deserialize_long_long(char **f, long long *n) {
memcpy(n, *f, sizeof(long long)); unsigned long long zigzag = 0;
*f += sizeof(long long); int shift = 0;
while (1) {
if ((**f & 0x80) == 0) {
zigzag |= ((unsigned long long) **f) << shift;
*f += 1;
shift += 7;
break;
} else {
zigzag |= ((unsigned long long) (**f & 0x7F)) << shift;
*f += 1;
shift += 7;
}
}
*n = (zigzag >> 1) ^ (-(zigzag & 1));
} }
void deserialize_uint(char **f, unsigned *n) { void deserialize_uint(char **f, unsigned *n) {