Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

278 lines
5.6 KiB

  1. //
  2. // deftree.c
  3. //
  4. // Tree creation for the compressor
  5. //
  6. #include "deflate.h"
  7. #include <string.h>
  8. #include <crtdbg.h>
  9. //
  10. // MAX_LITERAL_TREE elements is the largest number of elements that will ever be passed
  11. // in to this routine
  12. //
  13. typedef struct
  14. {
  15. // Made left_right a single long array for performance reasons. We always access them
  16. // one after the other, so there is no disadvantage.
  17. // left[] in lower 16 bits, right[] in upper 16 bits
  18. // short left[2*MAX_LITERAL_TREE_ELEMENTS];
  19. // short right[2*MAX_LITERAL_TREE_ELEMENTS];
  20. unsigned long left_right[2*MAX_LITERAL_TREE_ELEMENTS];
  21. int heap[MAX_LITERAL_TREE_ELEMENTS+1];
  22. int num_elements;
  23. // Maximum allowable code length (7 for pre-tree, 15 for other trees)
  24. int max_code_length;
  25. unsigned short *freq; // passed in as parameter
  26. unsigned short *code; // passed in as parameter
  27. short * sortptr;
  28. int depth;
  29. int heapsize;
  30. int len_cnt[17];
  31. } t_tree_context;
  32. static void countLen(t_tree_context *context, int i) /* call with i = root */
  33. {
  34. if (i < context->num_elements)
  35. {
  36. // check for max code length allowed
  37. context->len_cnt[(context->depth < context->max_code_length) ? context->depth : context->max_code_length]++;
  38. }
  39. else
  40. {
  41. unsigned long lr_value = context->left_right[i];
  42. context->depth++;
  43. countLen(context, lr_value & 65535); // formerly left[i]
  44. countLen(context, lr_value >> 16); // formerly right[i]
  45. context->depth--;
  46. }
  47. }
  48. static void makeLen(t_tree_context *context, int root, BYTE *len)
  49. {
  50. int k;
  51. int cum;
  52. int i;
  53. for (i = 0; i <= 16; i++)
  54. context->len_cnt[i] = 0;
  55. countLen(context, root);
  56. cum = 0;
  57. for (i = context->max_code_length; i > 0; i--)
  58. cum += (context->len_cnt[i] << (context->max_code_length - i));
  59. while (cum != (1 << context->max_code_length))
  60. {
  61. context->len_cnt[context->max_code_length]--;
  62. for (i = context->max_code_length-1; i > 0; i--)
  63. {
  64. if (context->len_cnt[i] != 0)
  65. {
  66. context->len_cnt[i]--;
  67. context->len_cnt[i+1] += 2;
  68. break;
  69. }
  70. }
  71. cum--;
  72. }
  73. for (i = 16; i > 0; i--)
  74. {
  75. k = context->len_cnt[i];
  76. while (--k >= 0)
  77. len[ *context->sortptr++ ] = (byte) i;
  78. }
  79. }
  80. /* priority queue; send i-th entry down heap */
  81. static void downHeap(t_tree_context *context, int i)
  82. {
  83. int j, k;
  84. k = context->heap[i];
  85. while ((j = (i<<1)) <= context->heapsize)
  86. {
  87. if (j < context->heapsize &&
  88. context->freq[context->heap[j]] > context->freq[context->heap[j + 1]])
  89. j++;
  90. if (context->freq[k] <= context->freq[context->heap[j]])
  91. break;
  92. context->heap[i] = context->heap[j];
  93. i = j;
  94. }
  95. context->heap[i] = k;
  96. }
  97. //
  98. // Reverse the bits, len > 0
  99. //
  100. static unsigned int bitReverse(unsigned int code, int len)
  101. {
  102. unsigned int new_code = 0;
  103. do
  104. {
  105. new_code |= (code & 1);
  106. new_code <<= 1;
  107. code >>= 1;
  108. } while (--len > 0);
  109. return new_code >> 1;
  110. }
  111. void makeCode(int num_elements, const int *len_cnt, const BYTE *len, USHORT *code)
  112. {
  113. int start[18];
  114. int i;
  115. start[1] = 0;
  116. for (i = 1; i <= 16; i++)
  117. start[i + 1] = (start[i] + len_cnt[i]) << 1;
  118. for (i = 0; i < num_elements; i++)
  119. {
  120. unsigned int unreversed_code;
  121. unreversed_code = start[len[i]]++;
  122. code[i] = (USHORT) bitReverse(unreversed_code, len[i]);
  123. }
  124. }
  125. void makeTree(
  126. int num_elements,
  127. int max_code_length,
  128. unsigned short * freq,
  129. unsigned short * code,
  130. byte * len
  131. )
  132. {
  133. t_tree_context tree;
  134. int k;
  135. int avail;
  136. int i;
  137. _ASSERT(num_elements <= MAX_LITERAL_TREE_ELEMENTS);
  138. // init tree context
  139. tree.depth = 0;
  140. tree.freq = freq;
  141. tree.code = code;
  142. tree.num_elements = num_elements;
  143. tree.max_code_length = max_code_length;
  144. avail = num_elements;
  145. tree.heapsize = 0;
  146. tree.heap[1] = 0;
  147. for (i = 0; i < tree.num_elements; i++)
  148. {
  149. len[i] = 0;
  150. if (tree.freq[i] != 0)
  151. tree.heap[++tree.heapsize] = i;
  152. }
  153. //
  154. // Less than 2 elements in the tree?
  155. //
  156. if (tree.heapsize < 2)
  157. {
  158. if (tree.heapsize == 0)
  159. {
  160. //
  161. // No elements in the tree?
  162. //
  163. // Then insert two fake elements and retry.
  164. //
  165. tree.freq[0] = 1;
  166. tree.freq[1] = 1;
  167. }
  168. else
  169. {
  170. //
  171. // One element in the tree, so add a fake code
  172. //
  173. // If our only element is element #0 (heap[1] == 0), then
  174. // make element #1 have a frequency of 1.
  175. //
  176. // Else make element #0 have a frequency of 1.
  177. //
  178. if (tree.heap[1] == 0)
  179. tree.freq[1] = 1;
  180. else
  181. tree.freq[0] = 1;
  182. }
  183. //
  184. // Retry with these new frequencies
  185. //
  186. makeTree(num_elements, max_code_length, freq, code, len);
  187. return;
  188. }
  189. for (i = tree.heapsize >> 1; i >= 1; i--)
  190. downHeap(&tree, i); /* make priority queue */
  191. tree.sortptr = tree.code;
  192. do
  193. {
  194. int i, j;
  195. /* while queue has at least two entries */
  196. i = tree.heap[1]; /* take out least-freq entry */
  197. if (i < tree.num_elements)
  198. *tree.sortptr++ = (short) i;
  199. tree.heap[1] = tree.heap[tree.heapsize--];
  200. downHeap(&tree, 1);
  201. j = tree.heap[1]; /* next least-freq entry */
  202. if (j < tree.num_elements)
  203. *tree.sortptr++ = (short) j;
  204. k = avail++; /* generate new node */
  205. tree.freq[k] = tree.freq[i] + tree.freq[j];
  206. tree.heap[1] = k;
  207. downHeap(&tree, 1); /* put into queue */
  208. // tree.left[k] = (short) i;
  209. // tree.right[k] = (short) j;
  210. tree.left_right[k] = (j << 16) | i;
  211. } while (tree.heapsize > 1);
  212. tree.sortptr = tree.code;
  213. makeLen(&tree, k, len);
  214. makeCode(num_elements, tree.len_cnt, len, code);
  215. }