diff --git a/index.c b/index.c index 23384fd..8412cae 100644 --- a/index.c +++ b/index.c @@ -2,14 +2,13 @@ #include -#define CHUNKSIZE 32 +#define CHUNKSIZE 4096 // Approximate static bool pixz_index_is_prefix(const char *name); static void pixz_index_add_record(pixz_index *i, size_t offset, const char *name); -typedef struct pixz_index_write_state pixz_index_write_state; -static size_t pixz_index_write_buf(pixz_index_write_state *state, uint8_t *buf); +static uint8_t *pixz_index_write_buf(pixz_index_record **rec, size_t *outsize); pixz_index *pixz_index_new(void) { pixz_index *i = malloc(sizeof(pixz_index)); @@ -76,121 +75,81 @@ void pixz_index_dump(pixz_index *i, FILE *out) { fprintf(out, "Total: %zu\n", rec->offset); } -typedef enum { - PIXZ_WRITE_NAME, - PIXZ_WRITE_LONG_NAME, - PIXZ_WRITE_SIZE, -} pixz_index_write_part; - -struct pixz_index_write_state { - pixz_index_write_part part; - pixz_index_record *rec; - size_t namepos; // Position within a long-name - size_t namelen; // Total length of a long-name -}; - -static size_t pixz_index_write_buf(pixz_index_write_state *state, uint8_t *buf) { - uint8_t *end = buf + CHUNKSIZE; - bool done = false; - while (!done) { - switch (state->part) { - case PIXZ_WRITE_SIZE: - if (buf + sizeof(uint64_t) + 1 > end) { - done = true; - } else { - pixz_offset_write(state->rec->offset, buf); - buf += sizeof(uint64_t); - *buf++ = '\0'; - - state->rec = state->rec->next; - state->part = PIXZ_WRITE_NAME; - } - break; - - case PIXZ_WRITE_NAME: - if (!state->rec) { - done = true; - } else { // We have a record - const char *name = state->rec->name; - if (!name) - name = ""; // End record - printf("%s\n", name); - - size_t len = strlen(name) + 1; - if (len > CHUNKSIZE) { - state->namelen = len; - state->namepos = 0; - state->part = PIXZ_WRITE_LONG_NAME; - } else { - memcpy(buf, name, len); - buf += len; - state->part = PIXZ_WRITE_SIZE; - } - } - break; - - case PIXZ_WRITE_LONG_NAME: { - size_t todo = state->namelen + 1 - state->namepos; - if (todo > end - buf) - todo = end - buf; - memcpy(buf, state->rec->name + state->namepos, todo); - buf += todo; - state->namepos += todo; - - state->part = state->namepos == state->namelen - ? PIXZ_WRITE_SIZE : PIXZ_WRITE_LONG_NAME; - done = true; - } - break; - } +static uint8_t *pixz_index_write_buf(pixz_index_record **rec, size_t *outsize) { + // How much space do we need? + size_t space = 0; + pixz_index_record *end = *rec; + do { + if (end->name) + space += strlen(end->name); + space += 2 + sizeof(uint64_t); // offset and two nulls + end = end->next; + } while (end && space < CHUNKSIZE); + + // Write it! + uint8_t *buf, *pos; + buf = pos = malloc(space); + for (; *rec != end; *rec = (*rec)->next) { + const char *name = (*rec)->name; + if (!name) + name = ""; + printf("%s\n", name); + + size_t len = strlen(name); + strncpy((char*)pos, name, len + 1); + pos += len + 1; + pixz_offset_write((*rec)->offset, pos); + pos += sizeof(uint64_t); + *pos++ = '\0'; } - return CHUNKSIZE - (end - buf); + + *outsize = space; + return buf; } fixme_err pixz_index_write(pixz_index *i, FILE *out, pixz_encode_options *opts) { lzma_block block; pixz_encode_initialize_block(&block, opts->check, opts->filters); - uint8_t inbuf[CHUNKSIZE], outbuf[CHUNKSIZE]; - pixz_encode_block_header(&block, outbuf, CHUNKSIZE); - if (fwrite(outbuf, block.header_size, 1, out) != 1) + uint8_t buf[CHUNKSIZE]; + pixz_encode_block_header(&block, buf, CHUNKSIZE); + if (fwrite(buf, block.header_size, 1, out) != 1) pixz_die("Error writing file index header\n"); lzma_stream stream = LZMA_STREAM_INIT; lzma_ret err = lzma_block_encoder(&stream, &block); if (err != LZMA_OK) pixz_die("Error #%d creating file index block encoder.\n", err); - stream.avail_in = 0; - pixz_index_write_state state = { .part = PIXZ_WRITE_NAME, - .rec = i->first, .namepos = 0 }; - while (true) { + uint8_t *inbuf = NULL; + stream.avail_in = 0; + pixz_index_record *rec = i->first; + while (rec) { if (stream.avail_in == 0) { - stream.avail_in = pixz_index_write_buf(&state, inbuf); - if (stream.avail_in == 0) { + free(inbuf); + stream.next_in = inbuf = pixz_index_write_buf(&rec, &stream.avail_in); + if (!inbuf) { if (lzma_code(&stream, LZMA_FINISH) != LZMA_STREAM_END) pixz_die("Error finishing file index\n"); break; } - stream.next_in = inbuf; } - stream.next_out = outbuf; + stream.next_out = buf; stream.avail_out = CHUNKSIZE; if (lzma_code(&stream, LZMA_RUN) != LZMA_OK) pixz_die("Error encoding file index\n"); - if (stream.next_out != outbuf) { - printf("%ld\n", stream.next_out - outbuf); - if (fwrite(outbuf, stream.next_out - outbuf, 1, out) != 1) + size_t wr = stream.next_out - buf; + if (wr) { + if (fwrite(buf, wr, 1, out) != 1) pixz_die("Error writing file index\n"); } } + lzma_end(&stream); return 31337; } fixme_err pixz_index_read_in_place(pixz_index **i, FILE *in) { - uint8_t inbuf[CHUNKSIZE], outbuf[CHUNKSIZE]; - - + return 31337; }