Source code of Windows XP (NT5)
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.

369 lines
8.7 KiB

  1. /*
  2. * encapi.c
  3. *
  4. * Encoder API entrypoints.
  5. */
  6. #define ALLOC_VARS
  7. #include "encoder.h"
  8. bool
  9. __fastcall
  10. LZX_EncodeInit(
  11. t_encoder_context ** enc_context,
  12. long compression_window_size,
  13. long second_partition_size,
  14. PFNALLOC pfnma,
  15. HANDLE hAllocator,
  16. int (__stdcall * pfnlzx_output_callback)(
  17. void * pfol,
  18. unsigned char * compressed_data,
  19. long compressed_size,
  20. long uncompressed_size
  21. ),
  22. void * fci_data
  23. )
  24. {
  25. t_encoder_context *context = pfnma( hAllocator, sizeof( t_encoder_context ));
  26. if ( context == NULL ) {
  27. return false;
  28. }
  29. *enc_context = context;
  30. /* to pass back in lzx_output_callback() */
  31. context->enc_fci_data = fci_data;
  32. context->enc_window_size = compression_window_size;
  33. /*
  34. * The second partition size must be a multiple of 32K
  35. */
  36. if (second_partition_size & (CHUNK_SIZE-1))
  37. second_partition_size &= (~(CHUNK_SIZE-1));
  38. /*
  39. * The minimum allowed is 32K because of the way that
  40. * our translation works.
  41. */
  42. if (second_partition_size < CHUNK_SIZE)
  43. second_partition_size = CHUNK_SIZE;
  44. /*
  45. * Our window size must be at least 32K
  46. */
  47. if (compression_window_size < CHUNK_SIZE)
  48. return false;
  49. context->enc_encoder_second_partition_size = second_partition_size;
  50. context->enc_output_callback_function = pfnlzx_output_callback;
  51. context->enc_malloc = pfnma;
  52. context->enc_mallochandle = hAllocator;
  53. /* Error allocating memory? */
  54. if (comp_alloc_compress_memory(context) == false)
  55. return false;
  56. LZX_EncodeNewGroup(context);
  57. return true;
  58. }
  59. /*
  60. * Sets up the encoder for a new group of files.
  61. *
  62. * All this does is reset the lookup table, re-initialise to the
  63. * default match estimation tables for the optimal parser, and
  64. * reset a few variables.
  65. */
  66. void __fastcall LZX_EncodeNewGroup(t_encoder_context *context)
  67. {
  68. init_compression_memory(context);
  69. }
  70. long __fastcall LZX_Encode(
  71. t_encoder_context *context,
  72. byte * input_data,
  73. long input_size,
  74. long * estimated_bytes_compressed,
  75. long file_size_for_translation
  76. )
  77. {
  78. context->enc_input_ptr = input_data;
  79. context->enc_input_left = input_size;
  80. context->enc_file_size_for_translation = file_size_for_translation;
  81. /* perform the encoding */
  82. encoder_start(context);
  83. if (context->enc_output_overflow)
  84. {
  85. *estimated_bytes_compressed = 0;
  86. return ENCODER_WRITE_FAILURE;
  87. }
  88. *estimated_bytes_compressed = estimate_buffer_contents(context);
  89. return ENCODER_SUCCESS;
  90. }
  91. bool __fastcall LZX_EncodeFlush(t_encoder_context *context)
  92. {
  93. flush_all_pending_blocks(context);
  94. if (context->enc_output_overflow)
  95. return false;
  96. return true;
  97. }
  98. //
  99. // But doesn't remove history data
  100. //
  101. bool __fastcall LZX_EncodeResetState(t_encoder_context *context)
  102. {
  103. /*
  104. * Most of this copied from init.c
  105. */
  106. /*
  107. * Clear item array and reset literal and distance
  108. * counters
  109. */
  110. memset(context->enc_ItemType, 0, (MAX_LITERAL_ITEMS/8));
  111. context->enc_literals = 0;
  112. context->enc_distances = 0;
  113. /*
  114. * Reset encoder state
  115. */
  116. context->enc_last_matchpos_offset[0] = 1;
  117. context->enc_last_matchpos_offset[1] = 1;
  118. context->enc_last_matchpos_offset[2] = 1;
  119. context->enc_repeated_offset_at_literal_zero[0] = 1;
  120. context->enc_repeated_offset_at_literal_zero[1] = 1;
  121. context->enc_repeated_offset_at_literal_zero[2] = 1;
  122. context->enc_input_running_total = 0;
  123. /*
  124. * The last lengths are zeroed in both the encoder and decoder,
  125. * since our tree representation is delta format.
  126. */
  127. memset(context->enc_main_tree_prev_len, 0, MAIN_TREE_ELEMENTS);
  128. memset(context->enc_secondary_tree_prev_len, 0, NUM_SECONDARY_LENGTHS);
  129. /* reset bit buffer */
  130. context->enc_bitcount = 32;
  131. context->enc_bitbuf = 0;
  132. context->enc_output_overflow = false;
  133. /* need to recalculate stats soon */
  134. context->enc_need_to_recalc_stats = true;
  135. context->enc_next_tree_create = TREE_CREATE_INTERVAL;
  136. /* pretend we just output everything up to now as a block */
  137. context->enc_bufpos_last_output_block = context->enc_BufPos;
  138. /* don't allow re-doing */
  139. context->enc_first_block = false;
  140. /* reset instruction pointer (for translation) to zero */
  141. reset_translation(context);
  142. /* so we output the file xlat header */
  143. context->enc_first_time_this_group = true;
  144. /* reset frame counter */
  145. context->enc_num_cfdata_frames = 0;
  146. /* haven't split the block */
  147. context->enc_num_block_splits = 0;
  148. return true;
  149. }
  150. unsigned char * __fastcall LZX_GetInputData(
  151. t_encoder_context *context,
  152. unsigned long *input_position,
  153. unsigned long *bytes_available
  154. )
  155. {
  156. unsigned long filepos;
  157. // note that BufPos-window_size is the real position in the file
  158. filepos = context->enc_BufPos - context->enc_window_size;
  159. if (filepos < context->enc_window_size)
  160. {
  161. *input_position = 0;
  162. *bytes_available = filepos;
  163. return &context->enc_MemWindow[context->enc_window_size];
  164. }
  165. else
  166. {
  167. *input_position = filepos - context->enc_window_size;
  168. *bytes_available = context->enc_window_size;
  169. return &context->enc_MemWindow[context->enc_BufPos - context->enc_window_size];
  170. }
  171. }
  172. //
  173. // This is used to quickly insert the old file into the history.
  174. //
  175. bool __fastcall LZX_EncodeInsertDictionary(
  176. t_encoder_context *context,
  177. byte * input_data,
  178. ulong input_size
  179. )
  180. {
  181. ulong BufPos;
  182. ulong RealBufPos;
  183. ulong BufPosEnd;
  184. ulong BytesRead;
  185. ulong i;
  186. ulong end_pos;
  187. context->enc_input_ptr = input_data;
  188. context->enc_input_left = input_size;
  189. context->enc_file_size_for_translation = 0;
  190. context->enc_first_time_this_group = false;
  191. RealBufPos = context->enc_BufPos - (ulong)(context->enc_RealMemWindow - context->enc_MemWindow);
  192. BytesRead = comp_read_input(context, RealBufPos, input_size);
  193. BufPos = context->enc_BufPos;
  194. BufPosEnd = context->enc_BufPos + BytesRead;
  195. while (BufPos < BufPosEnd)
  196. {
  197. quick_insert_bsearch_findmatch(
  198. context,
  199. BufPos,
  200. BufPos - context->enc_window_size+4
  201. );
  202. BufPos++;
  203. }
  204. context->enc_earliest_window_data_remaining = BufPos - context->enc_window_size;
  205. end_pos = BufPos - (context->enc_window_size-4-BREAK_LENGTH);
  206. for (i = 1; (i <= BREAK_LENGTH); i++)
  207. binary_search_remove_node(context, BufPos-i, end_pos);
  208. context->enc_BufPos = BufPos;
  209. context->enc_bufpos_at_last_block = BufPos;
  210. return true;
  211. }
  212. #ifdef TRACING
  213. ULONG TracingRunningTotal;
  214. ULONG TracingPrevPos;
  215. void
  216. __stdcall
  217. EncTracingMatch(
  218. ulong BufPos,
  219. ulong MatchLength,
  220. ulong MatchPos,
  221. ulong MatchOff
  222. )
  223. {
  224. if ( BufPos < TracingPrevPos ) {
  225. printf( "REWIND to %08X\n", BufPos );
  226. TracingRunningTotal -= ( TracingPrevPos - BufPos );
  227. }
  228. TracingPrevPos = BufPos;
  229. TracingRunningTotal += MatchLength;
  230. #ifdef TRACING2
  231. printf(
  232. "MATCH: At %08X, %c%c Off %08X (%08X), Length %5d, Total %08X\n",
  233. BufPos,
  234. MatchPos < 3 ? 'R' : ' ',
  235. MatchPos < 3 ? MatchPos + '0' : ' ',
  236. MatchOff,
  237. BufPos - MatchOff,
  238. MatchLength,
  239. TracingRunningTotal
  240. );
  241. #else
  242. printf(
  243. "MATCH: At %08X, From %08X, Length %5d\n",
  244. BufPos,
  245. BufPos - MatchOff,
  246. MatchLength
  247. );
  248. #endif
  249. }
  250. void
  251. __stdcall
  252. EncTracingLiteral(
  253. ulong BufPos,
  254. ulong ch
  255. )
  256. {
  257. if ( BufPos < TracingPrevPos ) {
  258. printf( "REWIND to %08X\n", BufPos );
  259. TracingRunningTotal -= ( TracingPrevPos - BufPos );
  260. }
  261. TracingPrevPos = BufPos;
  262. ++TracingRunningTotal;
  263. #ifdef TRACING2
  264. printf(
  265. "LITER: At %08X, 0x%02X Total %08X\n",
  266. BufPos,
  267. ch,
  268. TracingRunningTotal
  269. );
  270. #else
  271. printf(
  272. "LITER: At %08X, 0x%02X\n",
  273. BufPos,
  274. ch
  275. );
  276. #endif
  277. }
  278. void
  279. __stdcall
  280. EncTracingDefineOffsets(
  281. unsigned long WindowSize,
  282. unsigned long InterFileBytes,
  283. unsigned long OldFileSize
  284. )
  285. {
  286. }
  287. #endif /* TRACING */