/*$Source: /usr/home/dhesi/zoo/RCS/maketbl.c,v $*/ /*$Id: maketbl.c,v 1.8 91/07/09 01:39:52 dhesi Exp $*/ /*********************************************************** maketbl.c -- make table for decoding Builds a fast lookup table + fallback tree for Huffman codes given code lengths. Used by decode_c() to map input bit patterns to symbols efficiently. Adapted from Haruhiko Okumura’s “ar” archiver. Modified for in-memory decompression by Natalia Portillo, 2025 ***********************************************************/ #include #include "ar.h" // provides NC, CODE_BIT, etc. #include "lzh.h" // provides BITBUFSIZ /* * make_table(nchar, bitlen, tablebits, table): * * nchar = number of symbols * bitlen[] = array of code lengths for each symbol [0..nchar-1] * tablebits = number of bits for fast direct lookup * table[] = output table of size (1<>= jutbits; // Weight = 2^(tablebits - i) weight[i] = (uint16_t)(1U << (tablebits - i)); } // For lengths > tablebits, weight = 2^(16 - length) for(; i <= 16; i++) weight[i] = (uint16_t)(1U << (16 - i)); // 3) Clear any unused table slots between last short code and end i = start[tablebits + 1] >> jutbits; if(i != (uint16_t)(1U << tablebits)) { k = 1U << tablebits; while(i < k) table[i++] = 0; } // Initialize tree node index after the direct table entries avail = nchar; // Mask for inspecting bits when building tree mask = 1U << (15 - tablebits); // 4) For each symbol, place its codes in table or tree for(ch = 0; ch < (uint32_t)nchar; ch++) { len = bitlen[ch]; if(len == 0) continue; // skip symbols with no code // Next code range = [start[len], start[len]+weight[len]) nextcode = start[len] + weight[len]; if(len <= tablebits) { // Direct mapping: fill all table slots in this range for(k = start[len]; k < nextcode; k++) table[k] = (uint16_t)ch; } else { // Build or extend tree for longer codes // Start at table index for this prefix k = start[len]; p = &table[k >> jutbits]; // Number of extra bits beyond tablebits uint32_t extra = len - tablebits; // Walk/construct tree nodes bit by bit while(extra-- > 0) { if(*p == 0) { // allocate a new node for left[]/right[] left[avail] = right[avail] = 0; *p = (uint16_t)avail++; } // branch left or right based on current code bit if(k & mask) p = &right[*p]; else p = &left[*p]; // shift to next bit in code k <<= 1; } // At leaf: assign symbol *p = (uint16_t)ch; } // Advance start[len] for next code of same length start[len] = nextcode; } }