#include #include #include #include #include #include #include #define MICO_HEADER "\211MiC\r\n\032\n" 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 int64_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); int64_t v = getsigned(input, 32); v <<= 32; v |= getbits1_msb(input, 32); return v; } #define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32)) int main(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "usage: %s input.zip\n", argv[0]); exit(-1); } zip = zip_open(argv[1], 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; char header[8]; uint64_t len, lenv; int ret = zip_fread(ts.input, &header, sizeof header); if (ret < 0) { printf("err: %s", zip_strerror(zip)); } if (memcmp(header, MICO_HEADER, 8) != 0) { printf("wrong header\n"); continue; } ret = zip_fread(ts.input, &len, sizeof len); if (ret < 0) { printf("err: %s", zip_strerror(zip)); } len = ntohll(len); ret = zip_fread(vs.input, &header, sizeof header); if (ret < 0) { printf("err: %s", zip_strerror(zip)); } if (memcmp(header, MICO_HEADER, 8) != 0) { printf("wrong header\n"); continue; } ret = zip_fread(vs.input, &lenv, sizeof lenv); if (ret < 0) { printf("err: %s", zip_strerror(zip)); } lenv = ntohll(lenv); printf("len=%ld lenv=%d\n", len, lenv); if (len != lenv) { fprintf(stderr, "time and value length don't agree\n"); exit(-1); } int64_t t = 0, td = 0; double v = 0.0; for (uint64_t j = 0; j < len; j++) { int64_t tdd = get1(&ts); int64_t vd = get1(&vs); td += tdd; t += td; v += vd; printf("%s %f %ld\n", name, v/10000.0, t); } } }