1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <zip.h>
zip_t *zip;
struct bitreader {
zip_file_t *input;
uint64_t bitbuf; // value of bits in write buffer
int bitcount; // number of bits in write buffer
int eof;
};
static uint64_t
getbits1_msb(struct bitreader *input, int count)
{
assert(count >= 1 && count <= 57);
// Keep reading extra bytes until we have enough bits buffered
// Big endian; our current bits are at the top of the word,
// new bits get added at the bottom.
while (input->bitcount < count) {
unsigned char buf;
int ret = zip_fread(input->input, &buf, sizeof buf);
if (ret < 0) {
printf("err: %s", zip_strerror(zip));
}
if (ret == 0) {
input->eof = 1;
return 0;
}
input->bitbuf |= (uint64_t)buf << (56 - input->bitcount);
input->bitcount += 8;
}
// We now have enough bits present; the most significant
// "count" bits in "bitbuf" are our result.
uint64_t result = input->bitbuf >> (64 - count);
// Now remove these bits from the buffer
input->bitbuf <<= count;
input->bitcount -= count;
return result;
}
static int32_t
getsigned(struct bitreader *input, int count)
{
uint64_t bits = getbits1_msb(input, count);
uint64_t sign = 1 << (count - 1);
if (bits & sign)
return -(bits ^ sign) - 1;
else
return bits;
}
static int32_t
get1(struct bitreader *input)
{
if (getbits1_msb(input, 1) == 0)
return 0;
if (getbits1_msb(input, 1) == 0)
return getsigned(input, 7);
if (getbits1_msb(input, 1) == 0)
return getsigned(input, 9);
if (getbits1_msb(input, 1) == 0)
return getsigned(input, 12);
return getsigned(input, 32);
}
int
main()
{
zip = zip_open("out.zip", ZIP_RDONLY, 0);
int entries = zip_get_num_entries(zip, 0);
for (int i = 0; i < entries; i += 2) {
struct bitreader ts = { 0 };
struct bitreader vs = { 0 };
/* XXX verify assumptions on zip file order */
ts.input = zip_fopen_index(zip, i, 0);
vs.input = zip_fopen_index(zip, i+1, 0);
char *name = strdup(zip_get_name(zip, i, ZIP_FL_ENC_RAW));
char *s = strchr(name, '/');
*s = '{';
s = strrchr(name, '/');
*s++ = '}';
*s = 0;
int64_t t = 0, td = 0;
double v = 0.0;
while (!ts.eof) {
int32_t tdd = get1(&ts);
int32_t vd = get1(&vs);
td += tdd;
t += td;
v += vd;
printf("%s %f %ld\n", name, v/10000.0, t);
}
}
}
|