17dd7cddfSDavid du Colombier /* Copyright (C) 1994, 1996, 1998 Aladdin Enterprises. All rights reserved.
27dd7cddfSDavid du Colombier
3*593dc095SDavid du Colombier This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier implied.
57dd7cddfSDavid du Colombier
6*593dc095SDavid du Colombier This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier
10*593dc095SDavid du Colombier For more information about licensing, please refer to
11*593dc095SDavid du Colombier http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier San Rafael, CA 94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier
17*593dc095SDavid du Colombier /* $Id: shcgen.c,v 1.4 2002/02/21 22:24:54 giles Exp $ */
187dd7cddfSDavid du Colombier /* Generate (bounded) Huffman code definitions from frequencies, */
197dd7cddfSDavid du Colombier /* and tables from definitions. */
207dd7cddfSDavid du Colombier #include "memory_.h"
217dd7cddfSDavid du Colombier #include "stdio_.h"
227dd7cddfSDavid du Colombier #include <stdlib.h> /* for qsort */
237dd7cddfSDavid du Colombier #include "gdebug.h"
247dd7cddfSDavid du Colombier #include "gserror.h"
257dd7cddfSDavid du Colombier #include "gserrors.h"
267dd7cddfSDavid du Colombier #include "gsmemory.h"
277dd7cddfSDavid du Colombier #include "scommon.h"
287dd7cddfSDavid du Colombier #include "shc.h"
297dd7cddfSDavid du Colombier #include "shcgen.h"
307dd7cddfSDavid du Colombier
317dd7cddfSDavid du Colombier /* ------ Frequency -> definition procedure ------ */
327dd7cddfSDavid du Colombier
337dd7cddfSDavid du Colombier /* Define a node for the Huffman code tree. */
347dd7cddfSDavid du Colombier typedef struct count_node_s count_node;
357dd7cddfSDavid du Colombier struct count_node_s {
367dd7cddfSDavid du Colombier long freq; /* frequency of value */
377dd7cddfSDavid du Colombier uint value; /* data value being encoded */
387dd7cddfSDavid du Colombier uint code_length; /* length of Huffman code */
397dd7cddfSDavid du Colombier count_node *next; /* next node in freq-sorted list */
407dd7cddfSDavid du Colombier count_node *left; /* left child in tree (smaller code_length) */
417dd7cddfSDavid du Colombier count_node *right; /* right child in tree (greater code_length) */
427dd7cddfSDavid du Colombier };
437dd7cddfSDavid du Colombier
447dd7cddfSDavid du Colombier #ifdef DEBUG
457dd7cddfSDavid du Colombier # define debug_print_nodes(nodes, n, tag, lengths)\
467dd7cddfSDavid du Colombier if ( gs_debug_c('W') ) print_nodes_proc(nodes, n, tag, lengths);
477dd7cddfSDavid du Colombier private void
print_nodes_proc(const count_node * nodes,int n,const char * tag,int lengths)487dd7cddfSDavid du Colombier print_nodes_proc(const count_node * nodes, int n, const char *tag, int lengths)
497dd7cddfSDavid du Colombier {
507dd7cddfSDavid du Colombier int i;
517dd7cddfSDavid du Colombier
527dd7cddfSDavid du Colombier dlprintf1("[w]---------------- %s ----------------\n", tag);
537dd7cddfSDavid du Colombier for (i = 0; i < n; ++i)
547dd7cddfSDavid du Colombier dlprintf7("[w]node %d: f=%ld v=%d len=%d N=%d L=%d R=%d\n",
557dd7cddfSDavid du Colombier i, nodes[i].freq, nodes[i].value, nodes[i].code_length,
567dd7cddfSDavid du Colombier (nodes[i].next == 0 ? -1 : (int)(nodes[i].next - nodes)),
577dd7cddfSDavid du Colombier (nodes[i].left == 0 ? -1 : (int)(nodes[i].left - nodes)),
587dd7cddfSDavid du Colombier (nodes[i].right == 0 ? -1 : (int)(nodes[i].right - nodes)));
597dd7cddfSDavid du Colombier for (i = lengths; i > 0;) {
607dd7cddfSDavid du Colombier int j = i;
617dd7cddfSDavid du Colombier int len = nodes[--j].code_length;
627dd7cddfSDavid du Colombier
637dd7cddfSDavid du Colombier while (j > 0 && nodes[j - 1].code_length == len)
647dd7cddfSDavid du Colombier --j;
657dd7cddfSDavid du Colombier dlprintf2("[w]%d codes of length %d\n", i - j, len);
667dd7cddfSDavid du Colombier i = j;
677dd7cddfSDavid du Colombier }
687dd7cddfSDavid du Colombier }
697dd7cddfSDavid du Colombier #else
707dd7cddfSDavid du Colombier # define debug_print_nodes(nodes, n, tag, lengths) DO_NOTHING
717dd7cddfSDavid du Colombier #endif
727dd7cddfSDavid du Colombier
737dd7cddfSDavid du Colombier /* Node comparison procedures for sorting. */
747dd7cddfSDavid du Colombier #define pn1 ((const count_node *)p1)
757dd7cddfSDavid du Colombier #define pn2 ((const count_node *)p2)
767dd7cddfSDavid du Colombier /* Sort by decreasing frequency. */
777dd7cddfSDavid du Colombier private int
compare_freqs(const void * p1,const void * p2)787dd7cddfSDavid du Colombier compare_freqs(const void *p1, const void *p2)
797dd7cddfSDavid du Colombier {
807dd7cddfSDavid du Colombier long diff = pn2->freq - pn1->freq;
817dd7cddfSDavid du Colombier
827dd7cddfSDavid du Colombier return (diff < 0 ? -1 : diff > 0 ? 1 : 0);
837dd7cddfSDavid du Colombier }
847dd7cddfSDavid du Colombier /* Sort by increasing code length, and secondarily by decreasing frequency. */
857dd7cddfSDavid du Colombier private int
compare_code_lengths(const void * p1,const void * p2)867dd7cddfSDavid du Colombier compare_code_lengths(const void *p1, const void *p2)
877dd7cddfSDavid du Colombier {
887dd7cddfSDavid du Colombier int diff = pn1->code_length - pn2->code_length;
897dd7cddfSDavid du Colombier
907dd7cddfSDavid du Colombier return (diff < 0 ? -1 : diff > 0 ? 1 : compare_freqs(p1, p2));
917dd7cddfSDavid du Colombier }
927dd7cddfSDavid du Colombier /* Sort by increasing code value. */
937dd7cddfSDavid du Colombier private int
compare_values(const void * p1,const void * p2)947dd7cddfSDavid du Colombier compare_values(const void *p1, const void *p2)
957dd7cddfSDavid du Colombier {
967dd7cddfSDavid du Colombier return (pn1->value < pn2->value ? -1 :
977dd7cddfSDavid du Colombier pn1->value > pn2->value ? 1 : 0);
987dd7cddfSDavid du Colombier }
997dd7cddfSDavid du Colombier #undef pn1
1007dd7cddfSDavid du Colombier #undef pn2
1017dd7cddfSDavid du Colombier
1027dd7cddfSDavid du Colombier /* Adjust code lengths so that none of them exceeds max_length. */
1037dd7cddfSDavid du Colombier /* We break this out just to help organize the code; it's only called */
1047dd7cddfSDavid du Colombier /* from one place in hc_compute. */
1057dd7cddfSDavid du Colombier private void
hc_limit_code_lengths(count_node * nodes,uint num_values,int max_length)1067dd7cddfSDavid du Colombier hc_limit_code_lengths(count_node * nodes, uint num_values, int max_length)
1077dd7cddfSDavid du Colombier {
1087dd7cddfSDavid du Colombier int needed; /* # of max_length codes we need to free up */
1097dd7cddfSDavid du Colombier count_node *longest = nodes + num_values;
1107dd7cddfSDavid du Colombier
1117dd7cddfSDavid du Colombier { /* Compute the number of additional max_length codes */
1127dd7cddfSDavid du Colombier /* we need to make available. */
1137dd7cddfSDavid du Colombier int length = longest[-1].code_length;
1147dd7cddfSDavid du Colombier int next_length;
1157dd7cddfSDavid du Colombier int avail = 0;
1167dd7cddfSDavid du Colombier
1177dd7cddfSDavid du Colombier while ((next_length = longest[-1].code_length) > max_length) {
1187dd7cddfSDavid du Colombier avail >>= length - next_length;
1197dd7cddfSDavid du Colombier length = next_length;
1207dd7cddfSDavid du Colombier (--longest)->code_length = max_length;
1217dd7cddfSDavid du Colombier ++avail;
1227dd7cddfSDavid du Colombier }
1237dd7cddfSDavid du Colombier needed = (nodes + num_values - longest) -
1247dd7cddfSDavid du Colombier (avail >>= (length - max_length));
1257dd7cddfSDavid du Colombier if_debug2('W', "[w]avail=%d, needed=%d\n",
1267dd7cddfSDavid du Colombier avail, needed);
1277dd7cddfSDavid du Colombier }
1287dd7cddfSDavid du Colombier /* Skip over all max_length codes. */
1297dd7cddfSDavid du Colombier while (longest[-1].code_length == max_length)
1307dd7cddfSDavid du Colombier --longest;
1317dd7cddfSDavid du Colombier
1327dd7cddfSDavid du Colombier /*
1337dd7cddfSDavid du Colombier * To make available a code of length N, suppose that the next
1347dd7cddfSDavid du Colombier * shortest used code is of length M.
1357dd7cddfSDavid du Colombier * We take the lowest-frequency code of length M and change it
1367dd7cddfSDavid du Colombier * to M+1; we then have to compensate by reducing the length of
1377dd7cddfSDavid du Colombier * some of the highest-frequency codes of length N, as follows:
1387dd7cddfSDavid du Colombier * M new lengths for codes of length N
1397dd7cddfSDavid du Colombier * --- -----------
1407dd7cddfSDavid du Colombier * N-1 (none)
1417dd7cddfSDavid du Colombier * N-2 N-1
1427dd7cddfSDavid du Colombier * <N-2 M+2, M+2, N-1
1437dd7cddfSDavid du Colombier * In the present situation, N = max_length.
1447dd7cddfSDavid du Colombier */
1457dd7cddfSDavid du Colombier for (; needed > 0; --needed) { /* longest points to the first code of length max_length. */
1467dd7cddfSDavid du Colombier /* Since codes are sorted by increasing code length, */
1477dd7cddfSDavid du Colombier /* longest-1 is the desired code of length M. */
1487dd7cddfSDavid du Colombier int M1 = ++(longest[-1].code_length);
1497dd7cddfSDavid du Colombier
1507dd7cddfSDavid du Colombier switch (max_length - M1) {
1517dd7cddfSDavid du Colombier case 0: /* M == N-1 */
1527dd7cddfSDavid du Colombier --longest;
1537dd7cddfSDavid du Colombier break;
1547dd7cddfSDavid du Colombier case 1: /* M == N-2 */
1557dd7cddfSDavid du Colombier longest++->code_length = M1;
1567dd7cddfSDavid du Colombier break;
1577dd7cddfSDavid du Colombier default:
1587dd7cddfSDavid du Colombier longest->code_length = M1 + 1;
1597dd7cddfSDavid du Colombier longest[1].code_length = M1 + 1;
1607dd7cddfSDavid du Colombier longest[2].code_length--;
1617dd7cddfSDavid du Colombier longest += 3;
1627dd7cddfSDavid du Colombier }
1637dd7cddfSDavid du Colombier }
1647dd7cddfSDavid du Colombier }
1657dd7cddfSDavid du Colombier
1667dd7cddfSDavid du Colombier /* Compute an optimal Huffman code from an input data set. */
1677dd7cddfSDavid du Colombier /* The client must have set all the elements of *def. */
1687dd7cddfSDavid du Colombier int
hc_compute(hc_definition * def,const long * freqs,gs_memory_t * mem)1697dd7cddfSDavid du Colombier hc_compute(hc_definition * def, const long *freqs, gs_memory_t * mem)
1707dd7cddfSDavid du Colombier {
1717dd7cddfSDavid du Colombier uint num_values = def->num_values;
1727dd7cddfSDavid du Colombier count_node *nodes =
1737dd7cddfSDavid du Colombier (count_node *) gs_alloc_byte_array(mem, num_values * 2 - 1,
1747dd7cddfSDavid du Colombier sizeof(count_node), "hc_compute");
1757dd7cddfSDavid du Colombier int i;
1767dd7cddfSDavid du Colombier count_node *lowest;
1777dd7cddfSDavid du Colombier count_node *comb;
1787dd7cddfSDavid du Colombier
1797dd7cddfSDavid du Colombier if (nodes == 0)
1807dd7cddfSDavid du Colombier return_error(gs_error_VMerror);
1817dd7cddfSDavid du Colombier
1827dd7cddfSDavid du Colombier /* Create leaf nodes for the input data. */
1837dd7cddfSDavid du Colombier for (i = 0; i < num_values; ++i)
1847dd7cddfSDavid du Colombier nodes[i].freq = freqs[i], nodes[i].value = i;
1857dd7cddfSDavid du Colombier
1867dd7cddfSDavid du Colombier /* Create a list sorted by increasing frequency. */
1877dd7cddfSDavid du Colombier /* Also initialize the tree structure. */
1887dd7cddfSDavid du Colombier qsort(nodes, num_values, sizeof(count_node), compare_freqs);
1897dd7cddfSDavid du Colombier for (i = 0; i < num_values; ++i)
1907dd7cddfSDavid du Colombier nodes[i].next = &nodes[i - 1],
1917dd7cddfSDavid du Colombier nodes[i].code_length = 0,
1927dd7cddfSDavid du Colombier nodes[i].left = nodes[i].right = 0;
1937dd7cddfSDavid du Colombier nodes[0].next = 0;
1947dd7cddfSDavid du Colombier debug_print_nodes(nodes, num_values, "after sort", 0);
1957dd7cddfSDavid du Colombier
1967dd7cddfSDavid du Colombier /* Construct the Huffman code tree. */
1977dd7cddfSDavid du Colombier for (lowest = &nodes[num_values - 1], comb = &nodes[num_values];;
1987dd7cddfSDavid du Colombier ++comb
1997dd7cddfSDavid du Colombier ) {
2007dd7cddfSDavid du Colombier count_node *pn1 = lowest;
2017dd7cddfSDavid du Colombier count_node *pn2 = pn1->next;
2027dd7cddfSDavid du Colombier long freq = pn1->freq + pn2->freq;
2037dd7cddfSDavid du Colombier
2047dd7cddfSDavid du Colombier /* Create a parent for the two lowest-frequency nodes. */
2057dd7cddfSDavid du Colombier lowest = pn2->next;
2067dd7cddfSDavid du Colombier comb->freq = freq;
2077dd7cddfSDavid du Colombier if (pn1->code_length <= pn2->code_length)
2087dd7cddfSDavid du Colombier comb->left = pn1, comb->right = pn2,
2097dd7cddfSDavid du Colombier comb->code_length = pn2->code_length + 1;
2107dd7cddfSDavid du Colombier else
2117dd7cddfSDavid du Colombier comb->left = pn2, comb->right = pn1,
2127dd7cddfSDavid du Colombier comb->code_length = pn1->code_length + 1;
2137dd7cddfSDavid du Colombier if (lowest == 0) /* no nodes left to combine */
2147dd7cddfSDavid du Colombier break;
2157dd7cddfSDavid du Colombier /* Insert comb in the sorted list. */
2167dd7cddfSDavid du Colombier if (freq < lowest->freq)
2177dd7cddfSDavid du Colombier comb->next = lowest, lowest = comb;
2187dd7cddfSDavid du Colombier else {
2197dd7cddfSDavid du Colombier count_node *here = lowest;
2207dd7cddfSDavid du Colombier
2217dd7cddfSDavid du Colombier while (here->next != 0 && freq >= here->next->freq)
2227dd7cddfSDavid du Colombier here = here->next;
2237dd7cddfSDavid du Colombier comb->next = here->next;
2247dd7cddfSDavid du Colombier here->next = comb;
2257dd7cddfSDavid du Colombier }
2267dd7cddfSDavid du Colombier }
2277dd7cddfSDavid du Colombier
2287dd7cddfSDavid du Colombier /* comb (i.e., &nodes[num_values * 2 - 2] is the root of the tree. */
2297dd7cddfSDavid du Colombier /* Note that the left and right children of an interior node */
2307dd7cddfSDavid du Colombier /* were constructed before, and therefore have lower indices */
2317dd7cddfSDavid du Colombier /* in the nodes array than, the parent node. Thus we can assign */
2327dd7cddfSDavid du Colombier /* the code lengths (node depths) in a single descending-order */
2337dd7cddfSDavid du Colombier /* sweep. */
2347dd7cddfSDavid du Colombier comb++->code_length = 0;
2357dd7cddfSDavid du Colombier while (comb > nodes + num_values) {
2367dd7cddfSDavid du Colombier --comb;
2377dd7cddfSDavid du Colombier comb->left->code_length = comb->right->code_length =
2387dd7cddfSDavid du Colombier comb->code_length + 1;
2397dd7cddfSDavid du Colombier }
2407dd7cddfSDavid du Colombier debug_print_nodes(nodes, num_values * 2 - 1, "after combine", 0);
2417dd7cddfSDavid du Colombier
2427dd7cddfSDavid du Colombier /* Sort the leaves again by code length. */
2437dd7cddfSDavid du Colombier qsort(nodes, num_values, sizeof(count_node), compare_code_lengths);
2447dd7cddfSDavid du Colombier debug_print_nodes(nodes, num_values, "after re-sort", num_values);
2457dd7cddfSDavid du Colombier
2467dd7cddfSDavid du Colombier /* Limit the code length to def->num_counts. */
2477dd7cddfSDavid du Colombier hc_limit_code_lengths(nodes, num_values, def->num_counts);
2487dd7cddfSDavid du Colombier debug_print_nodes(nodes, num_values, "after limit", num_values);
2497dd7cddfSDavid du Colombier
2507dd7cddfSDavid du Colombier /* Sort within each code length by increasing code value. */
2517dd7cddfSDavid du Colombier /* This doesn't affect data compression, but it makes */
2527dd7cddfSDavid du Colombier /* the code definition itself compress better using our */
2537dd7cddfSDavid du Colombier /* incremental encoding. */
2547dd7cddfSDavid du Colombier for (i = num_values; i > 0;) {
2557dd7cddfSDavid du Colombier int j = i;
2567dd7cddfSDavid du Colombier int len = nodes[--j].code_length;
2577dd7cddfSDavid du Colombier
2587dd7cddfSDavid du Colombier while (j > 0 && nodes[j - 1].code_length == len)
2597dd7cddfSDavid du Colombier --j;
2607dd7cddfSDavid du Colombier qsort(&nodes[j], i - j, sizeof(count_node), compare_values);
2617dd7cddfSDavid du Colombier i = j;
2627dd7cddfSDavid du Colombier }
2637dd7cddfSDavid du Colombier
2647dd7cddfSDavid du Colombier /* Extract the definition from the nodes. */
2657dd7cddfSDavid du Colombier memset(def->counts, 0, sizeof(*def->counts) * (def->num_counts + 1));
2667dd7cddfSDavid du Colombier for (i = 0; i < num_values; ++i) {
2677dd7cddfSDavid du Colombier def->values[i] = nodes[i].value;
2687dd7cddfSDavid du Colombier def->counts[nodes[i].code_length]++;
2697dd7cddfSDavid du Colombier }
2707dd7cddfSDavid du Colombier
2717dd7cddfSDavid du Colombier /* All done, release working storage. */
2727dd7cddfSDavid du Colombier gs_free_object(mem, nodes, "hc_compute");
2737dd7cddfSDavid du Colombier return 0;
2747dd7cddfSDavid du Colombier }
2757dd7cddfSDavid du Colombier
2767dd7cddfSDavid du Colombier /* ------ Byte string <-> definition procedures ------ */
2777dd7cddfSDavid du Colombier
2787dd7cddfSDavid du Colombier /*
2797dd7cddfSDavid du Colombier * We define a compressed representation for (well-behaved) definitions
2807dd7cddfSDavid du Colombier * as a byte string. A "well-behaved" definition is one where if
2817dd7cddfSDavid du Colombier * code values A and B have the same code length and A < B,
2827dd7cddfSDavid du Colombier * A precedes B in the values table of the definition, and hence
2837dd7cddfSDavid du Colombier * A's encoding lexicographically precedes B's.
2847dd7cddfSDavid du Colombier *
2857dd7cddfSDavid du Colombier * The successive bytes in the compressed string give the code lengths for
2867dd7cddfSDavid du Colombier * runs of decoded values, in the form nnnnllll where nnnn is the number of
2877dd7cddfSDavid du Colombier * consecutive values -1 and llll is the code length -1.
2887dd7cddfSDavid du Colombier */
2897dd7cddfSDavid du Colombier
2907dd7cddfSDavid du Colombier /* Convert a definition to a byte string. */
2917dd7cddfSDavid du Colombier /* The caller must provide the byte string, of length def->num_values. */
2927dd7cddfSDavid du Colombier /* Assume (do not check) that the definition is well-behaved. */
2937dd7cddfSDavid du Colombier /* Return the actual length of the string. */
2947dd7cddfSDavid du Colombier int
hc_bytes_from_definition(byte * dbytes,const hc_definition * def)2957dd7cddfSDavid du Colombier hc_bytes_from_definition(byte * dbytes, const hc_definition * def)
2967dd7cddfSDavid du Colombier {
2977dd7cddfSDavid du Colombier int i, j;
2987dd7cddfSDavid du Colombier byte *bp = dbytes;
2997dd7cddfSDavid du Colombier const byte *lp = dbytes;
3007dd7cddfSDavid du Colombier const byte *end = dbytes + def->num_values;
3017dd7cddfSDavid du Colombier const ushort *values = def->values;
3027dd7cddfSDavid du Colombier
3037dd7cddfSDavid du Colombier /* Temporarily use the output string as a map from */
3047dd7cddfSDavid du Colombier /* values to code lengths. */
3057dd7cddfSDavid du Colombier for (i = 1; i <= def->num_counts; i++)
3067dd7cddfSDavid du Colombier for (j = 0; j < def->counts[i]; j++)
3077dd7cddfSDavid du Colombier bp[*values++] = i;
3087dd7cddfSDavid du Colombier
3097dd7cddfSDavid du Colombier /* Now construct the actual string. */
3107dd7cddfSDavid du Colombier while (lp < end) {
3117dd7cddfSDavid du Colombier const byte *vp;
3127dd7cddfSDavid du Colombier byte len = *lp;
3137dd7cddfSDavid du Colombier
3147dd7cddfSDavid du Colombier for (vp = lp + 1; vp < end && vp < lp + 16 && *vp == len;)
3157dd7cddfSDavid du Colombier vp++;
3167dd7cddfSDavid du Colombier *bp++ = ((vp - lp - 1) << 4) + (len - 1);
3177dd7cddfSDavid du Colombier lp = vp;
3187dd7cddfSDavid du Colombier }
3197dd7cddfSDavid du Colombier
3207dd7cddfSDavid du Colombier return bp - dbytes;
3217dd7cddfSDavid du Colombier }
3227dd7cddfSDavid du Colombier
3237dd7cddfSDavid du Colombier /* Extract num_counts and num_values from a byte string. */
3247dd7cddfSDavid du Colombier void
hc_sizes_from_bytes(hc_definition * def,const byte * dbytes,int num_bytes)3257dd7cddfSDavid du Colombier hc_sizes_from_bytes(hc_definition * def, const byte * dbytes, int num_bytes)
3267dd7cddfSDavid du Colombier {
3277dd7cddfSDavid du Colombier uint num_counts = 0, num_values = 0;
3287dd7cddfSDavid du Colombier int i;
3297dd7cddfSDavid du Colombier
3307dd7cddfSDavid du Colombier for (i = 0; i < num_bytes; i++) {
3317dd7cddfSDavid du Colombier int n = (dbytes[i] >> 4) + 1;
3327dd7cddfSDavid du Colombier int l = (dbytes[i] & 15) + 1;
3337dd7cddfSDavid du Colombier
3347dd7cddfSDavid du Colombier if (l > num_counts)
3357dd7cddfSDavid du Colombier num_counts = l;
3367dd7cddfSDavid du Colombier num_values += n;
3377dd7cddfSDavid du Colombier }
3387dd7cddfSDavid du Colombier def->num_counts = num_counts;
3397dd7cddfSDavid du Colombier def->num_values = num_values;
3407dd7cddfSDavid du Colombier }
3417dd7cddfSDavid du Colombier
3427dd7cddfSDavid du Colombier /* Convert a byte string back to a definition. */
3437dd7cddfSDavid du Colombier /* The caller must initialize *def, including allocating counts and values. */
3447dd7cddfSDavid du Colombier void
hc_definition_from_bytes(hc_definition * def,const byte * dbytes)3457dd7cddfSDavid du Colombier hc_definition_from_bytes(hc_definition * def, const byte * dbytes)
3467dd7cddfSDavid du Colombier {
3477dd7cddfSDavid du Colombier int v, i;
3487dd7cddfSDavid du Colombier ushort counts[max_hc_length + 1];
3497dd7cddfSDavid du Colombier
3507dd7cddfSDavid du Colombier /* Make a first pass to set the counts for each code length. */
3517dd7cddfSDavid du Colombier memset(counts, 0, sizeof(counts[0]) * (def->num_counts + 1));
3527dd7cddfSDavid du Colombier for (i = 0, v = 0; v < def->num_values; i++) {
3537dd7cddfSDavid du Colombier int n = (dbytes[i] >> 4) + 1;
3547dd7cddfSDavid du Colombier int l = (dbytes[i] & 15) + 1;
3557dd7cddfSDavid du Colombier
3567dd7cddfSDavid du Colombier counts[l] += n;
3577dd7cddfSDavid du Colombier v += n;
3587dd7cddfSDavid du Colombier }
3597dd7cddfSDavid du Colombier
3607dd7cddfSDavid du Colombier /* Now fill in the definition. */
3617dd7cddfSDavid du Colombier memcpy(def->counts, counts, sizeof(counts[0]) * (def->num_counts + 1));
3627dd7cddfSDavid du Colombier for (i = 1, v = 0; i <= def->num_counts; i++) {
3637dd7cddfSDavid du Colombier uint prev = counts[i];
3647dd7cddfSDavid du Colombier
3657dd7cddfSDavid du Colombier counts[i] = v;
3667dd7cddfSDavid du Colombier v += prev;
3677dd7cddfSDavid du Colombier }
3687dd7cddfSDavid du Colombier for (i = 0, v = 0; v < def->num_values; i++) {
3697dd7cddfSDavid du Colombier int n = (dbytes[i] >> 4) + 1;
3707dd7cddfSDavid du Colombier int l = (dbytes[i] & 15) + 1;
3717dd7cddfSDavid du Colombier int j;
3727dd7cddfSDavid du Colombier
3737dd7cddfSDavid du Colombier for (j = 0; j < n; n++)
3747dd7cddfSDavid du Colombier def->values[counts[l]++] = v++;
3757dd7cddfSDavid du Colombier }
3767dd7cddfSDavid du Colombier }
3777dd7cddfSDavid du Colombier
3787dd7cddfSDavid du Colombier /* ------ Definition -> table procedures ------ */
3797dd7cddfSDavid du Colombier
3807dd7cddfSDavid du Colombier /* Generate the encoding table from the definition. */
3817dd7cddfSDavid du Colombier /* The size of the encode array is def->num_values. */
3827dd7cddfSDavid du Colombier void
hc_make_encoding(hce_code * encode,const hc_definition * def)3837dd7cddfSDavid du Colombier hc_make_encoding(hce_code * encode, const hc_definition * def)
3847dd7cddfSDavid du Colombier {
3857dd7cddfSDavid du Colombier uint next = 0;
3867dd7cddfSDavid du Colombier const ushort *pvalue = def->values;
3877dd7cddfSDavid du Colombier uint i, k;
3887dd7cddfSDavid du Colombier
3897dd7cddfSDavid du Colombier for (i = 1; i <= def->num_counts; i++) {
3907dd7cddfSDavid du Colombier for (k = 0; k < def->counts[i]; k++, pvalue++, next++) {
3917dd7cddfSDavid du Colombier hce_code *pce = encode + *pvalue;
3927dd7cddfSDavid du Colombier
3937dd7cddfSDavid du Colombier pce->code = next;
3947dd7cddfSDavid du Colombier pce->code_length = i;
3957dd7cddfSDavid du Colombier }
3967dd7cddfSDavid du Colombier next <<= 1;
3977dd7cddfSDavid du Colombier }
3987dd7cddfSDavid du Colombier }
3997dd7cddfSDavid du Colombier
4007dd7cddfSDavid du Colombier /* We decode in two steps, first indexing into a table with */
4017dd7cddfSDavid du Colombier /* a fixed number of bits from the source, and then indexing into */
4027dd7cddfSDavid du Colombier /* an auxiliary table if necessary. (See shc.h for details.) */
4037dd7cddfSDavid du Colombier
4047dd7cddfSDavid du Colombier /* Calculate the size of the decoding table. */
4057dd7cddfSDavid du Colombier uint
hc_sizeof_decoding(const hc_definition * def,int initial_bits)4067dd7cddfSDavid du Colombier hc_sizeof_decoding(const hc_definition * def, int initial_bits)
4077dd7cddfSDavid du Colombier {
4087dd7cddfSDavid du Colombier uint size = 1 << initial_bits;
4097dd7cddfSDavid du Colombier uint carry = 0, mask = (uint) ~ 1;
4107dd7cddfSDavid du Colombier uint i;
4117dd7cddfSDavid du Colombier
4127dd7cddfSDavid du Colombier for (i = initial_bits + 1; i <= def->num_counts;
4137dd7cddfSDavid du Colombier i++, carry <<= 1, mask <<= 1
4147dd7cddfSDavid du Colombier ) {
4157dd7cddfSDavid du Colombier carry += def->counts[i];
4167dd7cddfSDavid du Colombier size += carry & mask;
4177dd7cddfSDavid du Colombier carry &= ~mask;
4187dd7cddfSDavid du Colombier }
4197dd7cddfSDavid du Colombier return size;
4207dd7cddfSDavid du Colombier }
4217dd7cddfSDavid du Colombier
4227dd7cddfSDavid du Colombier /* Generate the decoding tables. */
4237dd7cddfSDavid du Colombier void
hc_make_decoding(hcd_code * decode,const hc_definition * def,int initial_bits)4247dd7cddfSDavid du Colombier hc_make_decoding(hcd_code * decode, const hc_definition * def,
4257dd7cddfSDavid du Colombier int initial_bits)
4267dd7cddfSDavid du Colombier { /* Make entries for single-dispatch codes. */
4277dd7cddfSDavid du Colombier {
4287dd7cddfSDavid du Colombier hcd_code *pcd = decode;
4297dd7cddfSDavid du Colombier const ushort *pvalue = def->values;
4307dd7cddfSDavid du Colombier uint i, k, d;
4317dd7cddfSDavid du Colombier
4327dd7cddfSDavid du Colombier for (i = 0; i <= initial_bits; i++) {
4337dd7cddfSDavid du Colombier for (k = 0; k < def->counts[i]; k++, pvalue++) {
4347dd7cddfSDavid du Colombier for (d = 1 << (initial_bits - i); d > 0;
4357dd7cddfSDavid du Colombier d--, pcd++
4367dd7cddfSDavid du Colombier )
4377dd7cddfSDavid du Colombier pcd->value = *pvalue,
4387dd7cddfSDavid du Colombier pcd->code_length = i;
4397dd7cddfSDavid du Colombier }
4407dd7cddfSDavid du Colombier }
4417dd7cddfSDavid du Colombier }
4427dd7cddfSDavid du Colombier /* Make entries for two-dispatch codes. */
4437dd7cddfSDavid du Colombier /* By working backward, we can do this more easily */
4447dd7cddfSDavid du Colombier /* in a single pass. */
4457dd7cddfSDavid du Colombier {
4467dd7cddfSDavid du Colombier uint dsize = hc_sizeof_decoding(def, initial_bits);
4477dd7cddfSDavid du Colombier hcd_code *pcd = decode + (1 << initial_bits);
4487dd7cddfSDavid du Colombier hcd_code *pcd2 = decode + dsize;
4497dd7cddfSDavid du Colombier const ushort *pvalue = def->values + def->num_values;
4507dd7cddfSDavid du Colombier uint entries_left = 0, slots_left = 0, mult_shift = 0;
4517dd7cddfSDavid du Colombier uint i = def->num_counts + 1, j;
4527dd7cddfSDavid du Colombier
4537dd7cddfSDavid du Colombier for (;;) {
4547dd7cddfSDavid du Colombier if (slots_left == 0) {
4557dd7cddfSDavid du Colombier if (entries_left != 0) {
4567dd7cddfSDavid du Colombier slots_left = 1 << (i - initial_bits);
4577dd7cddfSDavid du Colombier mult_shift = 0;
4587dd7cddfSDavid du Colombier continue;
4597dd7cddfSDavid du Colombier }
4607dd7cddfSDavid du Colombier if (--i <= initial_bits)
4617dd7cddfSDavid du Colombier break;
4627dd7cddfSDavid du Colombier entries_left = def->counts[i];
4637dd7cddfSDavid du Colombier continue;
4647dd7cddfSDavid du Colombier }
4657dd7cddfSDavid du Colombier if (entries_left == 0) {
4667dd7cddfSDavid du Colombier entries_left = def->counts[--i];
4677dd7cddfSDavid du Colombier mult_shift++;
4687dd7cddfSDavid du Colombier continue;
4697dd7cddfSDavid du Colombier }
4707dd7cddfSDavid du Colombier --entries_left, --pvalue;
4717dd7cddfSDavid du Colombier for (j = 1 << mult_shift; j > 0; j--) {
4727dd7cddfSDavid du Colombier --pcd2;
4737dd7cddfSDavid du Colombier pcd2->value = *pvalue;
4747dd7cddfSDavid du Colombier pcd2->code_length = i - initial_bits;
4757dd7cddfSDavid du Colombier }
4767dd7cddfSDavid du Colombier if ((slots_left -= 1 << mult_shift) == 0) {
4777dd7cddfSDavid du Colombier --pcd;
4787dd7cddfSDavid du Colombier pcd->value = pcd2 - decode;
4797dd7cddfSDavid du Colombier pcd->code_length = i + mult_shift;
4807dd7cddfSDavid du Colombier }
4817dd7cddfSDavid du Colombier }
4827dd7cddfSDavid du Colombier }
4837dd7cddfSDavid du Colombier }
484