virtual int32_t read_i32() override { return static_cast<int32_t>(read_i64()); }
/* fill a buffer from a stream - return -1 on failure */ static int fill_buffer(struct stream_info *sinfo, int stream) { uchar c_type; i64 header_length; i64 u_len, c_len; if (seekto(sinfo, sinfo->s[stream].last_head) != 0) return -1; if (read_u8(sinfo->fd, &c_type) != 0) return -1; /* Compatibility crap for versions < 0.4 */ if (control.major_version == 0 && control.minor_version < 4) { u32 c_len32, u_len32, last_head32; if (read_u32(sinfo->fd, &c_len32) != 0) return -1; if (read_u32(sinfo->fd, &u_len32) != 0) return -1; if (read_u32(sinfo->fd, &last_head32) != 0) return -1; c_len = c_len32; u_len = u_len32; sinfo->s[stream].last_head = last_head32; header_length = 13; } else { if (read_i64(sinfo->fd, &c_len) != 0) return -1; if (read_i64(sinfo->fd, &u_len) != 0) return -1; if (read_i64(sinfo->fd, &sinfo->s[stream].last_head) != 0) return -1; header_length = 25; } sinfo->total_read += header_length; if (sinfo->s[stream].buf) free(sinfo->s[stream].buf); sinfo->s[stream].buf = malloc(u_len); if (!sinfo->s[stream].buf) return -1; if (read_buf(sinfo->fd, sinfo->s[stream].buf, c_len) != 0) return -1; sinfo->total_read += c_len; sinfo->s[stream].buflen = u_len; sinfo->s[stream].bufp = 0; if (c_type != CTYPE_NONE) { if (c_type == CTYPE_LZMA) { if (lzma_decompress_buf(&sinfo->s[stream], (size_t)c_len)) return -1; } else if (c_type == CTYPE_LZO) { if (lzo_decompress_buf(&sinfo->s[stream], c_len)) return -1; } else if (c_type == CTYPE_BZIP2) { if (bzip2_decompress_buf(&sinfo->s[stream], c_len)) return -1; } else if (c_type == CTYPE_GZIP) { if (gzip_decompress_buf(&sinfo->s[stream], c_len)) return -1; } else if (c_type == CTYPE_ZPAQ) { if (zpaq_decompress_buf(&sinfo->s[stream])) return -1; } else fatal("Dunno wtf decompression type to use!\n"); } return 0; }
virtual void read(int64_t& out_value) override { out_value = read_i64(); }
/* prepare a set of n streams for reading on file descriptor f */ void *open_stream_in(int f, int n) { i64 header_length; int i; struct stream_info *sinfo; sinfo = calloc(sizeof(*sinfo), 1); if (!sinfo) return NULL; sinfo->num_streams = n; sinfo->fd = f; sinfo->initial_pos = lseek(f, 0, SEEK_CUR); sinfo->s = (struct stream *)calloc(sizeof(sinfo->s[0]), n); if (!sinfo->s) { free(sinfo); return NULL; } for (i = 0; i < n; i++) { uchar c; i64 v1, v2; again: if (read_u8(f, &c) != 0) goto failed; /* Compatibility crap for versions < 0.40 */ if (control.major_version == 0 && control.minor_version < 4) { u32 v132, v232, last_head32; if (read_u32(f, &v132) != 0) goto failed; if (read_u32(f, &v232) != 0) goto failed; if (read_u32(f, &last_head32) != 0) goto failed; v1 = v132; v2 = v232; sinfo->s[i].last_head = last_head32; header_length = 13; } else { if (read_i64(f, &v1) != 0) goto failed; if (read_i64(f, &v2) != 0) goto failed; if (read_i64(f, &sinfo->s[i].last_head) != 0) goto failed; header_length = 25; } if (c == CTYPE_NONE && v1 == 0 && v2 == 0 && sinfo->s[i].last_head == 0 && i == 0) { err_msg("Enabling stream close workaround\n"); sinfo->initial_pos += header_length; goto again; } sinfo->total_read += header_length; if (c != CTYPE_NONE) { err_msg("Unexpected initial tag %d in streams\n", c); goto failed; } if (v1 != 0) { err_msg("Unexpected initial c_len %lld in streams %lld\n", v1, v2); goto failed; } if (v2 != 0) { err_msg("Unexpected initial u_len %lld in streams\n", v2); goto failed; } } return (void *)sinfo; failed: free(sinfo->s); free(sinfo); return NULL; }