diff --git a/lzw.c b/lzw.c index f9d103fff47e0615d8f15e2cb5f5b27b7b19b4d9..b35f32919781cefe16e7d1ac9cd86e0a88131207 100644 --- a/lzw.c +++ b/lzw.c @@ -25,7 +25,7 @@ typedef struct LZW_context_S * Table for storing sequences represented by an LZW code * 0-255, and 256 are special, representing literals, and the reset code. We could explicitly pre-fill them, but it's probably not necessary. */ - HBytes * lzw_code_table[4096]; + HBytes lzw_code_table[4096]; /* * Holds the next expected LZW code. We also use this for telling LZW_9bitcodeword, LZW_10bitcodeword, etc. apart. Parses fail if "next" is larger than what can be represented on that many bits. @@ -48,16 +48,12 @@ LZW_clear_table(LZW_context_T *ctx) */ for(int i = 258; i < ctx->next; ++i) { - HBytes * sequence = ctx->lzw_code_table[i]; - if(sequence != NULL) - { - /* - * Assumption: only the HBytes in the LZW table refer to the particular uint8_t arrays we're freeing. - */ - free((uint8_t *)sequence->token); - free(sequence); - } - ctx->lzw_code_table[i] = NULL; + HBytes sequence = ctx->lzw_code_table[i]; + /* + * Assumption: only the HBytes in the LZW table refer to the + * particular uint8_t arrays we're freeing. + */ + free((uint8_t *)sequence.token); } } @@ -68,10 +64,7 @@ LZW_clear_table(LZW_context_T *ctx) static void lzw_table_insert(LZW_context_T *ctx, uint8_t *token, size_t token_len) { - HBytes * next_entry = malloc(sizeof(HBytes)); - next_entry->token = token; - next_entry->len = token_len; - ctx->lzw_code_table[ctx->next] = next_entry; + ctx->lzw_code_table[ctx->next] = (HBytes){token, token_len}; ctx->next++; } @@ -160,8 +153,8 @@ validate_output(HParseResult *p, void *u) static HParsedToken* act_output(const HParseResult *p, void *u) { - HBytes * code_str; - HBytes * last_str; + HBytes code_str; + HBytes last_str; uint64_t code = H_CAST_UINT(p->ast); uint8_t * output_token; uint8_t * next_entry_token; @@ -182,8 +175,7 @@ act_output(const HParseResult *p, void *u) * This is what we'll wrap in a HBytes for returning. */ code_str = ctx->lzw_code_table[code]; - assert(code_str != NULL); - assert(code_str->len > 0); + assert(code_str.len > 0); /* * Fill in the missing last character of a previously assigned code, @@ -191,8 +183,8 @@ act_output(const HParseResult *p, void *u) */ if (ctx->next > 258) { last_str = ctx->lzw_code_table[ctx->next - 1]; - ((uint8_t *)last_str->token)[last_str->len - 1] = - code_str->token[0]; + ((uint8_t *)last_str.token)[last_str.len - 1] = + code_str.token[0]; // XXX casting away the const. we know what we're doing. // could avoid HBytes by using our own struct but come on. // a different design might avoid byte arrays in the @@ -204,16 +196,16 @@ act_output(const HParseResult *p, void *u) * Update the dictionary with a new entry that is missing the last * character which we will only learn when we process the next code. */ - next_entry_token = calloc(code_str->len + 1, sizeof(uint8_t)); - memcpy(next_entry_token, code_str->token, code_str->len); - lzw_table_insert(ctx, next_entry_token, code_str->len + 1); + next_entry_token = calloc(code_str.len + 1, sizeof(uint8_t)); + memcpy(next_entry_token, code_str.token, code_str.len); + lzw_table_insert(ctx, next_entry_token, code_str.len + 1); /* * Return a copy of the output. */ - output_token = h_arena_malloc(p->arena, code_str->len); - memcpy(output_token, code_str->token, code_str->len); - return H_MAKE_BYTES(output_token, code_str->len); + output_token = h_arena_malloc(p->arena, code_str.len); + memcpy(output_token, code_str.token, code_str.len); + return H_MAKE_BYTES(output_token, code_str.len); } static HParsedToken* @@ -264,7 +256,7 @@ act_lzwdata(const HParseResult *p, void *u) /*for(int i = 258; i < ctx->next; ++i) // DEBUG { fprintf(debug, "i: %u, str: ", i); - fwrite(ctx->lzw_code_table[i]->token, ctx->lzw_code_table[i]->len, 1, debug); + fwrite(ctx->lzw_code_table[i].token, ctx->lzw_code_table[i].len, 1, debug); fprintf(debug, "\n"); } fflush(debug); // DEBUG */ @@ -283,12 +275,8 @@ void init_LZW_parser() { uint8_t *token = malloc(sizeof(uint8_t)); *token = i; - HBytes *lit = malloc(sizeof(HBytes)); - lit->token = token; - lit->len = 1; - context->lzw_code_table[i] = lit; + context->lzw_code_table[i] = (HBytes){token, 1}; } - context->lzw_code_table[256] = calloc(1, sizeof(HBytes)); context->earlychange = 1; H_VDRULE(code9, h_bits(9, false), context); @@ -321,15 +309,12 @@ HParseResult* parse_LZW_data(const uint8_t* input, size_t length) void init_LZW_context(int earlychange) { - for(int i = 258; i < 4096; ++i) - { - if(context->lzw_code_table[i] != NULL) - { - free((uint8_t *) context->lzw_code_table[i]->token); // These can be freed without issue, because HParsedTokens containing them have separate deep copies - free(context->lzw_code_table[i]); - } - context->lzw_code_table[i] = NULL; - } + /* + * Only the HBytes in the LZW table refer to the strings we're freeing, + * since the HParsedTokens created from them get their own copies. + */ + for(int i = 258; i < context->next; ++i) + free((uint8_t *) context->lzw_code_table[i].token); context->next = 258; context->earlychange = earlychange; }