📄 pgpztrees.c
字号:
/*____________________________________________________________________________
Copyright (C) 1997 Network Associates Inc. and affiliated companies.
All rights reserved.
$Id: pgpZTrees.c,v 1.14 1999/03/10 03:00:14 heller Exp $
____________________________________________________________________________*/
/*
* Copyright (C) 1990-1993 Mark Adler, Richard B. Wales, Jean-loup Gailly,
* Kai Uwe Rommel and Igor Mandrichenko.
* Permission is granted to any individual or institution to use, copy,
* or redistribute this software so long as all of the original files
* are included, that it is not sold for profit, and that this copyright
* notice is retained.
*
* $Id: pgpZTrees.c,v 1.14 1999/03/10 03:00:14 heller Exp $
*/
/*
* trees.c by Jean-loup Gailly
*
* This is a new version of im_ctree.c originally written by Richard B. Wales
* for the defunct implosion method.
*
* PURPOSE
*
* Encode various sets of source values using variable-length
* binary code trees.
*
* DISCUSSION
*
* The PKZIP "deflation" process uses several Huffman trees. The more
* common source values are represented by shorter bit sequences.
*
* Each code tree is stored in the ZIP file in a compressed form
* which is itself a Huffman encoding of the lengths of
* all the code strings (in ascending order by source values).
* The actual code strings are reconstructed from the lengths in
* the UNZIP process, as described in the "application note"
* (APPNOTE.TXT) distributed as part of PKWARE's PKZIP program.
*
* REFERENCES
*
* Lynch, Thomas J.
* Data Compression: Techniques and Applications, pp. 53-55.
* Lifetime Learning Publications, 1985. ISBN 0-534-03418-7.
*
* Storer, James A.
* Data Compression: Methods and Theory, pp. 49-50.
* Computer Science Press, 1988. ISBN 0-7167-8156-5.
*
* Sedgewick, R.
* Algorithms, p290.
* Addison-Wesley, 1983. ISBN 0-201-06672-6.
*
* INTERFACE
*
* void ct_init (void))
* Allocate the match buffer and initialize the various tables.
*
* void ct_tally (unsigned dist, unsigned lc);
* Save the match info and tally the frequency counts.
*
* long flush_block (char const *buf, PGPUInt32 stored_len, int eof)
* Determine the best encoding for the current block: dynamic trees,
* static trees or store, and output the encoded block to the zip
* file. Returns the total compressed length for the file so far.
*
*/
#include "pgpConfig.h"
#include <ctype.h>
#include "pgpZip.h"
/* ===========================================================================
* Constants
*/
#define MAX_BITS 15
/* All codes must not exceed MAX_BITS bits */
#define MAX_BL_BITS 7
/* Bit length codes must not exceed MAX_BL_BITS bits */
#define LENGTH_CODES 29
/* number of length codes, not counting the special END_BLOCK code */
#define LITERALS 256
/* number of literal bytes 0..255 */
#define END_BLOCK 256
/* end of block literal code */
#define L_CODES (LITERALS+1+LENGTH_CODES)
/* number of Literal or Length codes, including the END_BLOCK code */
#define D_CODES 30
/* number of distance codes */
#define BL_CODES 19
/* number of codes used to transfer the bit lengths */
/* extra bits for each length code */
static int const near extra_lbits[LENGTH_CODES]
= {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
/* extra bits for each distance code */
static int const near extra_dbits[D_CODES]
= {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
/* extra bits for each bit length code */
static int const near extra_blbits[BL_CODES]
= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
static PGPByte const near bl_order[BL_CODES]
= {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
/* The lengths of the bit length codes are sent in order of decreasing
* probability, to avoid transmitting the lengths for unused bit length codes.
*/
#define STORED_BLOCK 0
#define STATIC_TREES 1
#define DYN_TREES 2
/* The three kinds of block type */
#ifndef LIT_BUFSIZE
# ifdef SMALL_MEM
# define LIT_BUFSIZE 0x2000
# else
# ifdef MEDIUM_MEM
# define LIT_BUFSIZE 0x4000
# else
# define LIT_BUFSIZE 0x8000
# endif
# endif
#endif
#define DIST_BUFSIZE LIT_BUFSIZE
/* Sizes of match buffers for literals/lengths and distances. There are
* 4 reasons for limiting LIT_BUFSIZE to < 64K:
* - frequencies can be kept in 16 bit counters
* - if compression is not successful for the first block, all input data is
* still in the window so we can still emit a stored block even when input
* comes from standard input. (This can also be done for all blocks if
* LIT_BUFSIZE is not greater than 32K.)
* - if compression is not successful for a file smaller than 64K, we can
* even emit a stored file instead of a stored block (saving 5 bytes).
* - creating new Huffman trees less frequently may not provide fast
* adaptation to changes in the input data statistics. (Take for
* example a binary file with poorly compressible code followed by
* a highly compressible string table.) Smaller buffer sizes give
* fast adaptation but have of course the overhead of transmitting trees
* more frequently.
* - I can't count above 4
* The current code is general and allows DIST_BUFSIZE < LIT_BUFSIZE (to save
* memory at the expense of compression). Some optimizations would be possible
* if we rely on DIST_BUFSIZE == LIT_BUFSIZE.
*/
#define REP_3_6 16
/* repeat previous bit length 3-6 times (2 bits of repeat count) */
#define REPZ_3_10 17
/* repeat a zero length 3-10 times (3 bits of repeat count) */
#define REPZ_11_138 18
/* repeat a zero length 11-138 times (7 bits of repeat count) */
/* ===========================================================================
* Local data
*/
/* Data structure describing a single value and its code string. */
typedef struct ct_data
{
union {
PGPUInt16 freq; /* frequency count */
PGPUInt16 code; /* bit string */
} fc;
union {
PGPUInt16 dad; /* father node in Huffman tree */
PGPUInt16 len; /* length of bit string */
} dl;
} ct_data;
#define Freq fc.freq
#define Code fc.code
#define Dad dl.dad
#define Len dl.len
#define HEAP_SIZE (2*L_CODES+1)
/* maximum heap size */
typedef struct tree_desc {
ct_data near *dyn_tree; /* the dynamic tree */
ct_data near *static_tree; /* corresponding static tree or NULL */
int const near *extra_bits; /* extra bits for each code or NULL */
int extra_base; /* base index for extra_bits */
int elems; /* max number of elements in the tree */
int max_length; /* max bit length for the codes */
int max_code; /* largest code with non zero frequency*/
} tree_desc;
/* Tables for initializing context tables. The local pointers are set up in
* ct_init.
*/
static const tree_desc near l_desc_init =
{/*dyn_ltree*/0, /*static_ltree*/0, extra_lbits, LITERALS+1, L_CODES,
MAX_BITS, 0};
static const tree_desc near d_desc_init =
{/*dyn_dtree*/0, /*fstatic_dtree*/0, extra_dbits, 0, D_CODES, MAX_BITS, 0};
static const tree_desc near bl_desc_init =
{/*bl_tree*/0, NULL, extra_blbits, 0, BL_CODES, MAX_BL_BITS, 0};
typedef struct ZTreesContext {
PGPContextRef cdkContext;
ct_data near dyn_ltree[HEAP_SIZE]; /* literal and length tree*/
ct_data near dyn_dtree[2*D_CODES+1]; /* distance tree */
ct_data near static_ltree[L_CODES+2];
/* The static literal tree. Since the bit lengths are imposed, there is no
* need for the L_CODES extra codes used during heap construction. However
* The codes 286 and 287 are needed to build a canonical tree (see ct_init
* below).
*/
ct_data near static_dtree[D_CODES];
/* The static distance tree. (Actually a trivial tree since all codes use
* 5 bits.)
*/
ct_data near bl_tree[2*BL_CODES+1];
/* Huffman tree for the bit lengths */
tree_desc near l_desc;
tree_desc near d_desc;
tree_desc near bl_desc;
PGPUInt16 near bl_count[MAX_BITS+1];
/* number of codes at each bit length for an optimal tree */
int near heap[2*L_CODES+1]; /*heap used to build the Huffman trees*/
int heap_len; /* number of elements in the heap */
int heap_max; /* element of largest frequency */
/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
* The same heap array is used to build all trees.
*/
PGPByte near depth[2*L_CODES+1];
/* Depth of each subtree used as tie breaker for trees of equal frequency*/
PGPByte length_code[MAX_MATCH-MIN_MATCH+1];
/* length code for each normalized match length (0 == MIN_MATCH) */
PGPByte dist_code[512];
/* distance codes. The first 256 values correspond to the distances
* 3 .. 258, the last 256 values correspond to the top 8 bits of
* the 15 bit distances.
*/
int near base_length[LENGTH_CODES];
/* First normalized length for each code (0 = MIN_MATCH) */
int near base_dist[D_CODES];
/* First normalized distance for each code (0 = distance of 1) */
#ifndef DYN_ALLOC
PGPByte far l_buf[LIT_BUFSIZE]; /* buffer for literals/lengths */
PGPUInt16 far d_buf[DIST_BUFSIZE]; /* buffer for distances */
#else
PGPByte far *l_buf;
PGPUInt16 far *d_buf;
#endif
PGPByte near flag_buf[(LIT_BUFSIZE/8)];
/* flag_buf is a bit array distinguishing literals from lengths in
* l_buf, and thus indicating the presence or absence of a distance.
*/
unsigned last_lit; /* running index in l_buf */
unsigned last_dist; /* running index in d_buf */
unsigned last_flags; /* running index in flag_buf */
PGPByte flags; /* current flags not yet saved in flag_buf */
PGPByte flag_bit; /* current bit used in flags */
/* bits are filled in flags starting at bit 0 (least significant).
* Note: these flags are overkill in the current code since we don't
* take advantage of DIST_BUFSIZE == LIT_BUFSIZE.
*/
/* bit length of current block with optimal trees*/
PGPUInt32 opt_len;
/* bit length of current block with static trees */
PGPUInt32 static_len;
PGPUInt32 compressed_len; /* total bit length of compressed file */
PGPUInt32 input_len; /* total byte length of input file */
/* input_len is for debugging only since we can get it by other means. */
} ZTreesContext;
#ifdef ZIPDEBUG
extern PGPUInt32 bits_sent; /* bit length of the compressed data */
extern PGPUInt32 isize; /* byte length of input file */
#endif
/* ===========================================================================
* Local (static) routines in this file.
*/
static void init_block(ZTreesContext *);
static void pqdownheap(ZTreesContext *, ct_data near *tree, int k);
static void gen_bitlen(ZTreesContext *, tree_desc near *desc);
static void gen_codes(ZTreesContext *, ct_data near *tree, int max_code);
static void build_tree(ZTreesContext *, tree_desc near *desc);
static void scan_tree(ZTreesContext *, ct_data near *tree, int max_code);
static void send_tree(ZTreesContext *, struct ZBitsContext *,
ct_data near *tree, int max_code);
static int build_bl_tree(ZTreesContext *);
static void send_all_trees(ZTreesContext *, struct ZBitsContext *,
int lcodes, int dcodes, int blcodes);
static void compress_block(ZTreesContext *, struct ZBitsContext *,
ct_data near *ltree, ct_data near *dtree);
#ifndef ZIPDEBUG
# define send_code(zbctx, c, tree) send_bits(zbctx, tree[c].Code, tree[c].Len)
/* Send a code of the given tree. c and tree must not have side effects */
#else /* ZIPDEBUG */
# define send_code(zbctx, c, tree) \
{ if (verbose > 1) fprintf(stderr,"\ncd %3d ",(c)); \
send_bits(zbctx, tree[c].Code, tree[c].Len); }
#endif
#define d_code(ctx, dist) \
((dist) < 256 ? (ctx)->dist_code[dist] : (ctx)->dist_code[256+((dist)>>7)])
/* Mapping from a distance to a distance code. dist is the distance - 1 and
* must not have side effects. dist_code[256] and dist_code[257] are never
* used.
*/
#define MAX(a,b) (a >= b ? a : b)
/* the arguments must not have side effects */
/* ===========================================================================
* Reverse k low-order bits in a word. Not speed-critical.
*/
static unsigned
bit_reverse(unsigned value, int len)
{
unsigned result = 0;
do {
result <<= 1;
result |= value & 1;
value >>= 1;
} while (--len);
return result;
}
/* ===========================================================================
* Allocate the match buffer and initialize the various tables.
*/
ZTreesContext *
ct_init(PGPContextRef cdkContext)
{
ZTreesContext *ctx;
int n; /* iterates over tree elements */
int bits; /* bit counter */
int length; /* length value */
int code; /* code value */
int dist; /* distance index */
ctx = (ZTreesContext *) pgpContextMemAlloc (cdkContext,
sizeof(*ctx), kPGPMemoryMgrFlags_Clear);
if (IsNull (ctx) )
return NULL;
ctx->cdkContext = cdkContext;
/* Initialize tables */
pgpCopyMemory (&l_desc_init, &ctx->l_desc, sizeof(l_desc_init));
ctx->l_desc.dyn_tree = ctx->dyn_ltree;
ctx->l_desc.static_tree = ctx->static_ltree;
pgpCopyMemory (&d_desc_init, &ctx->d_desc, sizeof(d_desc_init));
ctx->d_desc.dyn_tree = ctx->dyn_dtree;
ctx->d_desc.static_tree = ctx->static_dtree;
pgpCopyMemory (&bl_desc_init, &ctx->bl_desc, sizeof(bl_desc_init));
ctx->bl_desc.dyn_tree = ctx->bl_tree;
ctx->bl_desc.static_tree = NULL;
ctx->compressed_len = ctx->input_len = 0L;
#ifdef DYN_ALLOC
/* Allocate the buffers */
ctx->d_buf = (PGPUInt16 far *)pgpContextMemAlloc (cdkContext,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -