]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/Common/TianoCompress.c
625f99eaca2583d5a9886ea6613f508b38e6cb53
3 Copyright (c) 2006 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Compression routine. The compression algorithm is a mixture of
19 LZ77 and Huffman coding. LZ77 transforms the source data into a
20 sequence of Original Characters and Pointers to repeated strings.
21 This sequence is further divided into Blocks and Huffman codings
22 are applied to each Block.
33 #define UINT8_MAX 0xff
38 #define WNDSIZ (1U << WNDBIT)
40 #define BLKSIZ (1U << 14) // 16 * 1024U
41 #define PERC_FLAG 0x80000000U
44 #define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)
45 #define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2)
46 #define CRCPOLY 0xA001
47 #define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT)
50 // C: the Char&Len Set; P: the Position Set; T: the exTra Set
52 #define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)
54 #define NP (WNDBIT + 1)
56 #define NT (CODE_BIT + 3)
64 // Function Prototypes
249 IN UINT16 FreqParm
[],
250 OUT UINT8 LenParm
[ ],
251 OUT UINT16 CodeParm
[]
257 STATIC UINT8
*mSrc
, *mDst
, *mSrcUpperLimit
, *mDstUpperLimit
;
259 STATIC UINT8
*mLevel
, *mText
, *mChildCount
, *mBuf
, mCLen
[NC
], mPTLen
[NPT
], *mLen
;
260 STATIC INT16 mHeap
[NC
+ 1];
261 STATIC INT32 mRemainder
, mMatchLen
, mBitCount
, mHeapSize
, mN
;
262 STATIC UINT32 mBufSiz
= 0, mOutputPos
, mOutputMask
, mSubBitBuf
, mCrc
;
263 STATIC UINT32 mCompSize
, mOrigSize
;
265 STATIC UINT16
*mFreq
, *mSortPtr
, mLenCnt
[17], mLeft
[2 * NC
- 1], mRight
[2 * NC
- 1], mCrcTable
[UINT8_MAX
+ 1],
266 mCFreq
[2 * NC
- 1], mCCode
[NC
], mPFreq
[2 * NP
- 1], mPTCode
[NPT
], mTFreq
[2 * NT
- 1];
268 STATIC NODE mPos
, mMatchPos
, mAvail
, *mPosition
, *mParent
, *mPrev
, *mNext
= NULL
;
278 IN OUT UINT32
*DstSize
284 The internal implementation of [Efi/Tiano]Compress().
288 SrcBuffer - The buffer storing the source data
289 SrcSize - The size of source data
290 DstBuffer - The buffer to store the compressed data
291 DstSize - On input, the size of DstBuffer; On output,
292 the size of the actual compressed data.
293 Version - The version of de/compression algorithm.
294 Version 1 for UEFI 2.0 de/compression algorithm.
295 Version 2 for Tiano de/compression algorithm.
299 EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case,
300 DstSize contains the size needed.
301 EFI_SUCCESS - Compression is successful.
302 EFI_OUT_OF_RESOURCES - No resource to complete function.
303 EFI_INVALID_PARAMETER - Parameter supplied is wrong.
323 mSrcUpperLimit
= mSrc
+ SrcSize
;
325 mDstUpperLimit
= mDst
+*DstSize
;
332 mOrigSize
= mCompSize
= 0;
339 if (EFI_ERROR (Status
)) {
340 return EFI_OUT_OF_RESOURCES
;
343 // Null terminate the compressed data
345 if (mDst
< mDstUpperLimit
) {
349 // Fill in compressed size and original size
352 PutDword (mCompSize
+ 1);
353 PutDword (mOrigSize
);
358 if (mCompSize
+ 1 + 8 > *DstSize
) {
359 *DstSize
= mCompSize
+ 1 + 8;
360 return EFI_BUFFER_TOO_SMALL
;
362 *DstSize
= mCompSize
+ 1 + 8;
377 Put a dword to output stream
381 Data - the dword to put
387 if (mDst
< mDstUpperLimit
) {
388 *mDst
++ = (UINT8
) (((UINT8
) (Data
)) & 0xff);
391 if (mDst
< mDstUpperLimit
) {
392 *mDst
++ = (UINT8
) (((UINT8
) (Data
>> 0x08)) & 0xff);
395 if (mDst
< mDstUpperLimit
) {
396 *mDst
++ = (UINT8
) (((UINT8
) (Data
>> 0x10)) & 0xff);
399 if (mDst
< mDstUpperLimit
) {
400 *mDst
++ = (UINT8
) (((UINT8
) (Data
>> 0x18)) & 0xff);
413 Allocate memory spaces for data structures used in compression process
420 EFI_SUCCESS - Memory is allocated successfully
421 EFI_OUT_OF_RESOURCES - Allocation fails
427 mText
= malloc (WNDSIZ
* 2 + MAXMATCH
);
428 for (Index
= 0; Index
< WNDSIZ
* 2 + MAXMATCH
; Index
++) {
432 mLevel
= malloc ((WNDSIZ
+ UINT8_MAX
+ 1) * sizeof (*mLevel
));
433 mChildCount
= malloc ((WNDSIZ
+ UINT8_MAX
+ 1) * sizeof (*mChildCount
));
434 mPosition
= malloc ((WNDSIZ
+ UINT8_MAX
+ 1) * sizeof (*mPosition
));
435 mParent
= malloc (WNDSIZ
* 2 * sizeof (*mParent
));
436 mPrev
= malloc (WNDSIZ
* 2 * sizeof (*mPrev
));
437 mNext
= malloc ((MAX_HASH_VAL
+ 1) * sizeof (*mNext
));
440 mBuf
= malloc (mBufSiz
);
441 while (mBuf
== NULL
) {
442 mBufSiz
= (mBufSiz
/ 10U) * 9U;
443 if (mBufSiz
< 4 * 1024U) {
444 return EFI_OUT_OF_RESOURCES
;
447 mBuf
= malloc (mBufSiz
);
463 Called when compression is completed to free memory previously allocated.
475 if (mLevel
!= NULL
) {
479 if (mChildCount
!= NULL
) {
483 if (mPosition
!= NULL
) {
487 if (mParent
!= NULL
) {
515 Initialize String Info Log data structures
525 for (Index
= WNDSIZ
; Index
<= WNDSIZ
+ UINT8_MAX
; Index
++) {
527 mPosition
[Index
] = NIL
; /* sentinel */
530 for (Index
= WNDSIZ
; Index
< WNDSIZ
* 2; Index
++) {
531 mParent
[Index
] = NIL
;
535 for (Index
= 1; Index
< WNDSIZ
- 1; Index
++) {
536 mNext
[Index
] = (NODE
) (Index
+ 1);
539 mNext
[WNDSIZ
- 1] = NIL
;
540 for (Index
= WNDSIZ
* 2; Index
<= MAX_HASH_VAL
; Index
++) {
555 Find child node given the parent node and the edge character
559 NodeQ - the parent node
560 CharC - the edge character
564 The child node (NIL if not found)
570 NodeR
= mNext
[HASH (NodeQ
, CharC
)];
574 mParent
[NIL
] = NodeQ
;
575 while (mParent
[NodeR
] != NodeQ
) {
576 NodeR
= mNext
[NodeR
];
593 Create a new child for a given parent node.
597 Parent - the parent node
598 CharC - the edge character
599 Child - the child node
608 Node1
= (NODE
) HASH (Parent
, CharC
);
609 Node2
= mNext
[Node1
];
610 mNext
[Node1
] = Child
;
611 mNext
[Child
] = Node2
;
612 mPrev
[Node2
] = Child
;
613 mPrev
[Child
] = Node1
;
614 mParent
[Child
] = Parent
;
615 mChildCount
[Parent
]++;
631 Old - the node to split
642 mChildCount
[New
] = 0;
643 TempNode
= mPrev
[Old
];
644 mPrev
[New
] = TempNode
;
645 mNext
[TempNode
] = New
;
646 TempNode
= mNext
[Old
];
647 mNext
[New
] = TempNode
;
648 mPrev
[TempNode
] = New
;
649 mParent
[New
] = mParent
[Old
];
650 mLevel
[New
] = (UINT8
) mMatchLen
;
651 mPosition
[New
] = mPos
;
652 MakeChild (New
, mText
[mMatchPos
+ mMatchLen
], Old
);
653 MakeChild (New
, mText
[mPos
+ mMatchLen
], mPos
);
665 Insert string info for current position into the String Info Log
681 if (mMatchLen
>= 4) {
683 // We have just got a long match, the target tree
684 // can be located by MatchPos + 1. Travese the tree
685 // from bottom up to get to a proper starting point.
686 // The usage of PERC_FLAG ensures proper node deletion
687 // in DeleteNode() later.
690 NodeR
= (NODE
) ((mMatchPos
+ 1) | WNDSIZ
);
691 NodeQ
= mParent
[NodeR
];
692 while (NodeQ
== NIL
) {
693 NodeR
= mNext
[NodeR
];
694 NodeQ
= mParent
[NodeR
];
697 while (mLevel
[NodeQ
] >= mMatchLen
) {
699 NodeQ
= mParent
[NodeQ
];
703 while (mPosition
[NodeT
] < 0) {
704 mPosition
[NodeT
] = mPos
;
705 NodeT
= mParent
[NodeT
];
708 if (NodeT
< WNDSIZ
) {
709 mPosition
[NodeT
] = (NODE
) (mPos
| (UINT32
) PERC_FLAG
);
713 // Locate the target tree
715 NodeQ
= (NODE
) (mText
[mPos
] + WNDSIZ
);
716 CharC
= mText
[mPos
+ 1];
717 NodeR
= Child (NodeQ
, CharC
);
719 MakeChild (NodeQ
, CharC
, mPos
);
727 // Traverse down the tree to find a match.
728 // Update Position value along the route.
729 // Node split or creation is involved.
732 if (NodeR
>= WNDSIZ
) {
736 Index2
= mLevel
[NodeR
];
737 mMatchPos
= (NODE
) (mPosition
[NodeR
] & (UINT32
)~PERC_FLAG
);
740 if (mMatchPos
>= mPos
) {
744 t1
= &mText
[mPos
+ mMatchLen
];
745 t2
= &mText
[mMatchPos
+ mMatchLen
];
746 while (mMatchLen
< Index2
) {
757 if (mMatchLen
>= MAXMATCH
) {
761 mPosition
[NodeR
] = mPos
;
763 NodeR
= Child (NodeQ
, *t1
);
765 MakeChild (NodeQ
, *t1
, mPos
);
772 NodeT
= mPrev
[NodeR
];
775 NodeT
= mNext
[NodeR
];
778 mParent
[mPos
] = NodeQ
;
779 mParent
[NodeR
] = NIL
;
782 // Special usage of 'next'
797 Delete outdated string info. (The Usage of PERC_FLAG
798 ensures a clean deletion)
812 if (mParent
[mPos
] == NIL
) {
818 mNext
[NodeR
] = NodeS
;
819 mPrev
[NodeS
] = NodeR
;
820 NodeR
= mParent
[mPos
];
822 if (NodeR
>= WNDSIZ
) {
826 mChildCount
[NodeR
]--;
827 if (mChildCount
[NodeR
] > 1) {
831 NodeT
= (NODE
) (mPosition
[NodeR
] & (UINT32
)~PERC_FLAG
);
837 NodeQ
= mParent
[NodeR
];
838 NodeU
= mPosition
[NodeQ
];
839 while (NodeU
& (UINT32
) PERC_FLAG
) {
840 NodeU
&= (UINT32
)~PERC_FLAG
;
849 mPosition
[NodeQ
] = (NODE
) (NodeS
| WNDSIZ
);
850 NodeQ
= mParent
[NodeQ
];
851 NodeU
= mPosition
[NodeQ
];
854 if (NodeQ
< WNDSIZ
) {
863 mPosition
[NodeQ
] = (NODE
) (NodeS
| WNDSIZ
| (UINT32
) PERC_FLAG
);
866 NodeS
= Child (NodeR
, mText
[NodeT
+ mLevel
[NodeR
]]);
867 NodeT
= mPrev
[NodeS
];
868 NodeU
= mNext
[NodeS
];
869 mNext
[NodeT
] = NodeU
;
870 mPrev
[NodeU
] = NodeT
;
871 NodeT
= mPrev
[NodeR
];
872 mNext
[NodeT
] = NodeS
;
873 mPrev
[NodeS
] = NodeT
;
874 NodeT
= mNext
[NodeR
];
875 mPrev
[NodeT
] = NodeS
;
876 mNext
[NodeS
] = NodeT
;
877 mParent
[NodeS
] = mParent
[NodeR
];
878 mParent
[NodeR
] = NIL
;
879 mNext
[NodeR
] = mAvail
;
892 Advance the current position (read in new data if needed).
893 Delete outdated string info. Find a match string for current position.
905 if (mPos
== WNDSIZ
* 2) {
906 memmove (&mText
[0], &mText
[WNDSIZ
], WNDSIZ
+ MAXMATCH
);
907 Number
= FreadCrc (&mText
[WNDSIZ
+ MAXMATCH
], WNDSIZ
);
908 mRemainder
+= Number
;
925 The main controlling routine for compression process.
931 EFI_SUCCESS - The compression is successful
932 EFI_OUT_0F_RESOURCES - Not enough memory for compression process
940 Status
= AllocateMemory ();
941 if (EFI_ERROR (Status
)) {
950 mRemainder
= FreadCrc (&mText
[WNDSIZ
], WNDSIZ
+ MAXMATCH
);
955 if (mMatchLen
> mRemainder
) {
956 mMatchLen
= mRemainder
;
959 while (mRemainder
> 0) {
960 LastMatchLen
= mMatchLen
;
961 LastMatchPos
= mMatchPos
;
963 if (mMatchLen
> mRemainder
) {
964 mMatchLen
= mRemainder
;
967 if (mMatchLen
> LastMatchLen
|| LastMatchLen
< THRESHOLD
) {
969 // Not enough benefits are gained by outputting a pointer,
970 // so just output the original character
972 Output (mText
[mPos
- 1], 0);
976 if (LastMatchLen
== THRESHOLD
) {
977 if (((mPos
- LastMatchPos
- 2) & (WNDSIZ
- 1)) > (1U << 11)) {
978 Output (mText
[mPos
- 1], 0);
983 // Outputting a pointer is beneficial enough, do it.
986 LastMatchLen
+ (UINT8_MAX
+ 1 - THRESHOLD
),
987 (mPos
- LastMatchPos
- 2) & (WNDSIZ
- 1)
990 while (LastMatchLen
> 0) {
995 if (mMatchLen
> mRemainder
) {
996 mMatchLen
= mRemainder
;
1013 Routine Description:
1015 Count the frequencies for the Extra Set
1028 for (Index
= 0; Index
< NT
; Index
++) {
1033 while (Number
> 0 && mCLen
[Number
- 1] == 0) {
1038 while (Index
< Number
) {
1039 Index3
= mCLen
[Index
++];
1042 while (Index
< Number
&& mCLen
[Index
] == 0) {
1048 mTFreq
[0] = (UINT16
) (mTFreq
[0] + Count
);
1049 } else if (Count
<= 18) {
1051 } else if (Count
== 19) {
1058 mTFreq
[Index3
+ 2]++;
1072 Routine Description:
1074 Outputs the code length array for the Extra Set or the Position Set.
1078 Number - the number of symbols
1079 nbit - the number of bits needed to represent 'n'
1080 Special - the special symbol that needs to be take care of
1089 while (Number
> 0 && mPTLen
[Number
- 1] == 0) {
1093 PutBits (nbit
, Number
);
1095 while (Index
< Number
) {
1096 Index3
= mPTLen
[Index
++];
1098 PutBits (3, Index3
);
1100 PutBits (Index3
- 3, (1U << (Index3
- 3)) - 2);
1103 if (Index
== Special
) {
1104 while (Index
< 6 && mPTLen
[Index
] == 0) {
1108 PutBits (2, (Index
- 3) & 3);
1120 Routine Description:
1122 Outputs the code length array for Char&Length Set
1136 while (Number
> 0 && mCLen
[Number
- 1] == 0) {
1140 PutBits (CBIT
, Number
);
1142 while (Index
< Number
) {
1143 Index3
= mCLen
[Index
++];
1146 while (Index
< Number
&& mCLen
[Index
] == 0) {
1152 for (Index3
= 0; Index3
< Count
; Index3
++) {
1153 PutBits (mPTLen
[0], mPTCode
[0]);
1155 } else if (Count
<= 18) {
1156 PutBits (mPTLen
[1], mPTCode
[1]);
1157 PutBits (4, Count
- 3);
1158 } else if (Count
== 19) {
1159 PutBits (mPTLen
[0], mPTCode
[0]);
1160 PutBits (mPTLen
[1], mPTCode
[1]);
1163 PutBits (mPTLen
[2], mPTCode
[2]);
1164 PutBits (CBIT
, Count
- 20);
1167 PutBits (mPTLen
[Index3
+ 2], mPTCode
[Index3
+ 2]);
1178 PutBits (mCLen
[Value
], mCCode
[Value
]);
1197 PutBits (mPTLen
[Index
], mPTCode
[Index
]);
1199 PutBits (Index
- 1, Value
& (0xFFFFFFFFU
>> (32 - Index
+ 1)));
1210 Routine Description:
1212 Huffman code the block and output it.
1231 Root
= MakeTree (NC
, mCFreq
, mCLen
, mCCode
);
1232 Size
= mCFreq
[Root
];
1236 Root
= MakeTree (NT
, mTFreq
, mPTLen
, mPTCode
);
1238 WritePTLen (NT
, TBIT
, 3);
1241 PutBits (TBIT
, Root
);
1249 PutBits (CBIT
, Root
);
1252 Root
= MakeTree (NP
, mPFreq
, mPTLen
, mPTCode
);
1254 WritePTLen (NP
, PBIT
, -1);
1257 PutBits (PBIT
, Root
);
1261 for (Index
= 0; Index
< Size
; Index
++) {
1262 if (Index
% UINT8_BIT
== 0) {
1263 Flags
= mBuf
[Pos
++];
1268 if (Flags
& (1U << (UINT8_BIT
- 1))) {
1269 EncodeC (mBuf
[Pos
++] + (1U << UINT8_BIT
));
1270 Index3
= mBuf
[Pos
++];
1271 for (Index2
= 0; Index2
< 3; Index2
++) {
1272 Index3
<<= UINT8_BIT
;
1273 Index3
+= mBuf
[Pos
++];
1278 EncodeC (mBuf
[Pos
++]);
1282 for (Index
= 0; Index
< NC
; Index
++) {
1286 for (Index
= 0; Index
< NP
; Index
++) {
1299 Routine Description:
1301 Outputs an Original Character or a Pointer
1305 CharC - The original character or the 'String Length' element of a Pointer
1306 Pos - The 'Position' field of a Pointer
1314 if ((mOutputMask
>>= 1) == 0) {
1315 mOutputMask
= 1U << (UINT8_BIT
- 1);
1317 // Check the buffer overflow per outputing UINT8_BIT symbols
1318 // which is an Original Character or a Pointer. The biggest
1319 // symbol is a Pointer which occupies 5 bytes.
1321 if (mOutputPos
>= mBufSiz
- 5 * UINT8_BIT
) {
1326 CPos
= mOutputPos
++;
1330 mBuf
[mOutputPos
++] = (UINT8
) CharC
;
1332 if (CharC
>= (1U << UINT8_BIT
)) {
1333 mBuf
[CPos
] |= mOutputMask
;
1334 mBuf
[mOutputPos
++] = (UINT8
) (Pos
>> 24);
1335 mBuf
[mOutputPos
++] = (UINT8
) (Pos
>> 16);
1336 mBuf
[mOutputPos
++] = (UINT8
) (Pos
>> (UINT8_BIT
));
1337 mBuf
[mOutputPos
++] = (UINT8
) Pos
;
1356 for (Index
= 0; Index
< NC
; Index
++) {
1360 for (Index
= 0; Index
< NP
; Index
++) {
1364 mOutputPos
= mOutputMask
= 0;
1378 // Flush remaining bits
1380 PutBits (UINT8_BIT
- 1, 0);
1395 for (Index
= 0; Index
<= UINT8_MAX
; Index
++) {
1397 for (Index2
= 0; Index2
< UINT8_BIT
; Index2
++) {
1399 Temp
= (Temp
>> 1) ^ CRCPOLY
;
1405 mCrcTable
[Index
] = (UINT16
) Temp
;
1417 Routine Description:
1419 Outputs rightmost n bits of x
1423 Number - the rightmost n bits of the data is used
1432 while (Number
>= mBitCount
) {
1434 // Number -= mBitCount should never equal to 32
1436 Temp
= (UINT8
) (mSubBitBuf
| (Value
>> (Number
-= mBitCount
)));
1437 if (mDst
< mDstUpperLimit
) {
1443 mBitCount
= UINT8_BIT
;
1446 mSubBitBuf
|= Value
<< (mBitCount
-= Number
);
1457 Routine Description:
1463 Pointer - the buffer to hold the data
1464 Number - number of bytes to read
1468 number of bytes actually read
1474 for (Index
= 0; mSrc
< mSrcUpperLimit
&& Index
< Number
; Index
++) {
1475 *Pointer
++ = *mSrc
++;
1481 mOrigSize
+= Number
;
1483 while (Index
>= 0) {
1484 UPDATE_CRC (*Pointer
++);
1497 mBitCount
= UINT8_BIT
;
1508 Routine Description:
1510 Count the number of each code length for a Huffman tree.
1514 Index - the top node
1520 STATIC INT32 Depth
= 0;
1523 mLenCnt
[(Depth
< 16) ? Depth
: 16]++;
1526 CountLen (mLeft
[Index
]);
1527 CountLen (mRight
[Index
]);
1539 Routine Description:
1541 Create code length array for a Huffman tree
1545 Root - the root of the tree
1557 for (Index
= 0; Index
<= 16; Index
++) {
1564 // Adjust the length count array so that
1565 // no code will be generated longer than its designated length
1568 for (Index
= 16; Index
> 0; Index
--) {
1569 Cum
+= mLenCnt
[Index
] << (16 - Index
);
1572 while (Cum
!= (1U << 16)) {
1574 for (Index
= 15; Index
> 0; Index
--) {
1575 if (mLenCnt
[Index
] != 0) {
1577 mLenCnt
[Index
+ 1] += 2;
1585 for (Index
= 16; Index
> 0; Index
--) {
1586 Index3
= mLenCnt
[Index
];
1588 while (Index3
>= 0) {
1589 mLen
[*mSortPtr
++] = (UINT8
) Index
;
1605 // priority queue: send Index-th entry down heap
1607 Index3
= mHeap
[Index
];
1609 while (Index2
<= mHeapSize
) {
1610 if (Index2
< mHeapSize
&& mFreq
[mHeap
[Index2
]] > mFreq
[mHeap
[Index2
+ 1]]) {
1614 if (mFreq
[Index3
] <= mFreq
[mHeap
[Index2
]]) {
1618 mHeap
[Index
] = mHeap
[Index2
];
1623 mHeap
[Index
] = (INT16
) Index3
;
1635 Routine Description:
1637 Assign code to each symbol based on the code length array
1641 Number - number of symbols
1642 Len - the code length array
1643 Code - stores codes for each symbol
1653 for (Index
= 1; Index
<= 16; Index
++) {
1654 Start
[Index
+ 1] = (UINT16
) ((Start
[Index
] + mLenCnt
[Index
]) << 1);
1657 for (Index
= 0; Index
< Number
; Index
++) {
1658 Code
[Index
] = Start
[Len
[Index
]]++;
1666 IN UINT16 FreqParm
[],
1667 OUT UINT8 LenParm
[ ],
1668 OUT UINT16 CodeParm
[]
1672 Routine Description:
1674 Generates Huffman codes given a frequency distribution of symbols
1678 NParm - number of symbols
1679 FreqParm - frequency of each symbol
1680 LenParm - code length for each symbol
1681 CodeParm - code for each symbol
1685 Root of the Huffman tree.
1695 // make tree, calculate len[], return root
1703 for (Index
= 0; Index
< mN
; Index
++) {
1707 mHeap
[mHeapSize
] = (INT16
) Index
;
1711 if (mHeapSize
< 2) {
1712 CodeParm
[mHeap
[1]] = 0;
1716 for (Index
= mHeapSize
/ 2; Index
>= 1; Index
--) {
1718 // make priority queue
1723 mSortPtr
= CodeParm
;
1727 *mSortPtr
++ = (UINT16
) Index
;
1730 mHeap
[1] = mHeap
[mHeapSize
--];
1734 *mSortPtr
++ = (UINT16
) Index2
;
1738 mFreq
[Index3
] = (UINT16
) (mFreq
[Index
] + mFreq
[Index2
]);
1739 mHeap
[1] = (INT16
) Index3
;
1741 mLeft
[Index3
] = (UINT16
) Index
;
1742 mRight
[Index3
] = (UINT16
) Index2
;
1743 } while (mHeapSize
> 1);
1745 mSortPtr
= CodeParm
;
1747 MakeCode (NParm
, LenParm
, CodeParm
);