]>
git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Sample/Tools/Source/Common/TianoCompress.c
3 Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
4 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.
28 #include "TianoCommon.h"
35 #define UINT8_MAX 0xff
40 #define WNDSIZ (1U << WNDBIT)
42 #define BLKSIZ (1U << 14) // 16 * 1024U
43 #define PERC_FLAG 0x80000000U
46 #define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)
47 #define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2)
48 #define CRCPOLY 0xA001
49 #define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT)
52 // C: the Char&Len Set; P: the Position Set; T: the exTra Set
54 #define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)
56 #define NP (WNDBIT + 1)
58 #define NT (CODE_BIT + 3)
66 // Function Prototypes
74 IN OUT UINT32
*DstSize
,
260 IN UINT16 FreqParm
[],
261 OUT UINT8 LenParm
[ ],
262 OUT UINT16 CodeParm
[]
268 STATIC UINT8
*mSrc
, *mDst
, *mSrcUpperLimit
, *mDstUpperLimit
;
270 STATIC UINT8
*mLevel
, *mText
, *mChildCount
, *mBuf
, mCLen
[NC
], mPTLen
[NPT
], *mLen
;
271 STATIC INT16 mHeap
[NC
+ 1];
272 STATIC INT32 mRemainder
, mMatchLen
, mBitCount
, mHeapSize
, mN
;
273 STATIC UINT32 mBufSiz
= 0, mOutputPos
, mOutputMask
, mSubBitBuf
, mCrc
;
274 STATIC UINT32 mCompSize
, mOrigSize
;
276 STATIC UINT16
*mFreq
, *mSortPtr
, mLenCnt
[17], mLeft
[2 * NC
- 1], mRight
[2 * NC
- 1], mCrcTable
[UINT8_MAX
+ 1],
277 mCFreq
[2 * NC
- 1], mCTable
[4096], mCCode
[NC
], mPFreq
[2 * NP
- 1], mPTCode
[NPT
], mTFreq
[2 * NT
- 1];
279 STATIC NODE mPos
, mMatchPos
, mAvail
, *mPosition
, *mParent
, *mPrev
, *mNext
= NULL
;
290 IN OUT UINT32
*DstSize
296 The internal implementation of [Efi/Tiano]Compress().
300 SrcBuffer - The buffer storing the source data
301 SrcSize - The size of source data
302 DstBuffer - The buffer to store the compressed data
303 DstSize - On input, the size of DstBuffer; On output,
304 the size of the actual compressed data.
305 Version - The version of de/compression algorithm.
306 Version 1 for EFI 1.1 de/compression algorithm.
307 Version 2 for Tiano de/compression algorithm.
311 EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case,
312 DstSize contains the size needed.
313 EFI_SUCCESS - Compression is successful.
314 EFI_OUT_OF_RESOURCES - No resource to complete function.
315 EFI_INVALID_PARAMETER - Parameter supplied is wrong.
335 mSrcUpperLimit
= mSrc
+ SrcSize
;
337 mDstUpperLimit
= mDst
+ *DstSize
;
344 mOrigSize
= mCompSize
= 0;
351 if (EFI_ERROR (Status
)) {
352 return EFI_OUT_OF_RESOURCES
;
355 // Null terminate the compressed data
357 if (mDst
< mDstUpperLimit
) {
361 // Fill in compressed size and original size
364 PutDword (mCompSize
+ 1);
365 PutDword (mOrigSize
);
370 if (mCompSize
+ 1 + 8 > *DstSize
) {
371 *DstSize
= mCompSize
+ 1 + 8;
372 return EFI_BUFFER_TOO_SMALL
;
374 *DstSize
= mCompSize
+ 1 + 8;
389 Put a dword to output stream
393 Data - the dword to put
399 if (mDst
< mDstUpperLimit
) {
400 *mDst
++ = (UINT8
) (((UINT8
) (Data
)) & 0xff);
403 if (mDst
< mDstUpperLimit
) {
404 *mDst
++ = (UINT8
) (((UINT8
) (Data
>> 0x08)) & 0xff);
407 if (mDst
< mDstUpperLimit
) {
408 *mDst
++ = (UINT8
) (((UINT8
) (Data
>> 0x10)) & 0xff);
411 if (mDst
< mDstUpperLimit
) {
412 *mDst
++ = (UINT8
) (((UINT8
) (Data
>> 0x18)) & 0xff);
425 Allocate memory spaces for data structures used in compression process
432 EFI_SUCCESS - Memory is allocated successfully
433 EFI_OUT_OF_RESOURCES - Allocation fails
439 mText
= malloc (WNDSIZ
* 2 + MAXMATCH
);
440 for (Index
= 0; Index
< WNDSIZ
* 2 + MAXMATCH
; Index
++) {
444 mLevel
= malloc ((WNDSIZ
+ UINT8_MAX
+ 1) * sizeof (*mLevel
));
445 mChildCount
= malloc ((WNDSIZ
+ UINT8_MAX
+ 1) * sizeof (*mChildCount
));
446 mPosition
= malloc ((WNDSIZ
+ UINT8_MAX
+ 1) * sizeof (*mPosition
));
447 mParent
= malloc (WNDSIZ
* 2 * sizeof (*mParent
));
448 mPrev
= malloc (WNDSIZ
* 2 * sizeof (*mPrev
));
449 mNext
= malloc ((MAX_HASH_VAL
+ 1) * sizeof (*mNext
));
452 mBuf
= malloc (mBufSiz
);
453 while (mBuf
== NULL
) {
454 mBufSiz
= (mBufSiz
/ 10U) * 9U;
455 if (mBufSiz
< 4 * 1024U) {
456 return EFI_OUT_OF_RESOURCES
;
459 mBuf
= malloc (mBufSiz
);
475 Called when compression is completed to free memory previously allocated.
487 if (mLevel
!= NULL
) {
491 if (mChildCount
!= NULL
) {
495 if (mPosition
!= NULL
) {
499 if (mParent
!= NULL
) {
527 Initialize String Info Log data structures
537 for (Index
= WNDSIZ
; Index
<= WNDSIZ
+ UINT8_MAX
; Index
++) {
539 mPosition
[Index
] = NIL
; /* sentinel */
542 for (Index
= WNDSIZ
; Index
< WNDSIZ
* 2; Index
++) {
543 mParent
[Index
] = NIL
;
547 for (Index
= 1; Index
< WNDSIZ
- 1; Index
++) {
548 mNext
[Index
] = (NODE
) (Index
+ 1);
551 mNext
[WNDSIZ
- 1] = NIL
;
552 for (Index
= WNDSIZ
* 2; Index
<= MAX_HASH_VAL
; Index
++) {
567 Find child node given the parent node and the edge character
571 NodeQ - the parent node
572 CharC - the edge character
576 The child node (NIL if not found)
582 NodeR
= mNext
[HASH (NodeQ
, CharC
)];
586 mParent
[NIL
] = NodeQ
;
587 while (mParent
[NodeR
] != NodeQ
) {
588 NodeR
= mNext
[NodeR
];
605 Create a new child for a given parent node.
609 Parent - the parent node
610 CharC - the edge character
611 Child - the child node
620 Node1
= (NODE
) HASH (Parent
, CharC
);
621 Node2
= mNext
[Node1
];
622 mNext
[Node1
] = Child
;
623 mNext
[Child
] = Node2
;
624 mPrev
[Node2
] = Child
;
625 mPrev
[Child
] = Node1
;
626 mParent
[Child
] = Parent
;
627 mChildCount
[Parent
]++;
643 Old - the node to split
654 mChildCount
[New
] = 0;
655 TempNode
= mPrev
[Old
];
656 mPrev
[New
] = TempNode
;
657 mNext
[TempNode
] = New
;
658 TempNode
= mNext
[Old
];
659 mNext
[New
] = TempNode
;
660 mPrev
[TempNode
] = New
;
661 mParent
[New
] = mParent
[Old
];
662 mLevel
[New
] = (UINT8
) mMatchLen
;
663 mPosition
[New
] = mPos
;
664 MakeChild (New
, mText
[mMatchPos
+ mMatchLen
], Old
);
665 MakeChild (New
, mText
[mPos
+ mMatchLen
], mPos
);
677 Insert string info for current position into the String Info Log
693 if (mMatchLen
>= 4) {
695 // We have just got a long match, the target tree
696 // can be located by MatchPos + 1. Travese the tree
697 // from bottom up to get to a proper starting point.
698 // The usage of PERC_FLAG ensures proper node deletion
699 // in DeleteNode() later.
702 NodeR
= (NODE
) ((mMatchPos
+ 1) | WNDSIZ
);
703 NodeQ
= mParent
[NodeR
];
704 while (NodeQ
== NIL
) {
705 NodeR
= mNext
[NodeR
];
706 NodeQ
= mParent
[NodeR
];
709 while (mLevel
[NodeQ
] >= mMatchLen
) {
711 NodeQ
= mParent
[NodeQ
];
715 while (mPosition
[NodeT
] < 0) {
716 mPosition
[NodeT
] = mPos
;
717 NodeT
= mParent
[NodeT
];
720 if (NodeT
< WNDSIZ
) {
721 mPosition
[NodeT
] = (NODE
) (mPos
| (UINT32
) PERC_FLAG
);
725 // Locate the target tree
727 NodeQ
= (NODE
) (mText
[mPos
] + WNDSIZ
);
728 CharC
= mText
[mPos
+ 1];
729 NodeR
= Child (NodeQ
, CharC
);
731 MakeChild (NodeQ
, CharC
, mPos
);
739 // Traverse down the tree to find a match.
740 // Update Position value along the route.
741 // Node split or creation is involved.
744 if (NodeR
>= WNDSIZ
) {
748 Index2
= mLevel
[NodeR
];
749 mMatchPos
= (NODE
) (mPosition
[NodeR
] & (UINT32
)~PERC_FLAG
);
752 if (mMatchPos
>= mPos
) {
756 t1
= &mText
[mPos
+ mMatchLen
];
757 t2
= &mText
[mMatchPos
+ mMatchLen
];
758 while (mMatchLen
< Index2
) {
769 if (mMatchLen
>= MAXMATCH
) {
773 mPosition
[NodeR
] = mPos
;
775 NodeR
= Child (NodeQ
, *t1
);
777 MakeChild (NodeQ
, *t1
, mPos
);
784 NodeT
= mPrev
[NodeR
];
787 NodeT
= mNext
[NodeR
];
790 mParent
[mPos
] = NodeQ
;
791 mParent
[NodeR
] = NIL
;
794 // Special usage of 'next'
809 Delete outdated string info. (The Usage of PERC_FLAG
810 ensures a clean deletion)
824 if (mParent
[mPos
] == NIL
) {
830 mNext
[NodeR
] = NodeS
;
831 mPrev
[NodeS
] = NodeR
;
832 NodeR
= mParent
[mPos
];
834 if (NodeR
>= WNDSIZ
) {
838 mChildCount
[NodeR
]--;
839 if (mChildCount
[NodeR
] > 1) {
843 NodeT
= (NODE
) (mPosition
[NodeR
] & (UINT32
)~PERC_FLAG
);
849 NodeQ
= mParent
[NodeR
];
850 NodeU
= mPosition
[NodeQ
];
851 while (NodeU
& (UINT32
) PERC_FLAG
) {
852 NodeU
&= (UINT32
)~PERC_FLAG
;
861 mPosition
[NodeQ
] = (NODE
) (NodeS
| WNDSIZ
);
862 NodeQ
= mParent
[NodeQ
];
863 NodeU
= mPosition
[NodeQ
];
866 if (NodeQ
< WNDSIZ
) {
875 mPosition
[NodeQ
] = (NODE
) (NodeS
| WNDSIZ
| (UINT32
) PERC_FLAG
);
878 NodeS
= Child (NodeR
, mText
[NodeT
+ mLevel
[NodeR
]]);
879 NodeT
= mPrev
[NodeS
];
880 NodeU
= mNext
[NodeS
];
881 mNext
[NodeT
] = NodeU
;
882 mPrev
[NodeU
] = NodeT
;
883 NodeT
= mPrev
[NodeR
];
884 mNext
[NodeT
] = NodeS
;
885 mPrev
[NodeS
] = NodeT
;
886 NodeT
= mNext
[NodeR
];
887 mPrev
[NodeT
] = NodeS
;
888 mNext
[NodeS
] = NodeT
;
889 mParent
[NodeS
] = mParent
[NodeR
];
890 mParent
[NodeR
] = NIL
;
891 mNext
[NodeR
] = mAvail
;
904 Advance the current position (read in new data if needed).
905 Delete outdated string info. Find a match string for current position.
917 if (mPos
== WNDSIZ
* 2) {
918 memmove (&mText
[0], &mText
[WNDSIZ
], WNDSIZ
+ MAXMATCH
);
919 Number
= FreadCrc (&mText
[WNDSIZ
+ MAXMATCH
], WNDSIZ
);
920 mRemainder
+= Number
;
937 The main controlling routine for compression process.
943 EFI_SUCCESS - The compression is successful
944 EFI_OUT_0F_RESOURCES - Not enough memory for compression process
952 Status
= AllocateMemory ();
953 if (EFI_ERROR (Status
)) {
962 mRemainder
= FreadCrc (&mText
[WNDSIZ
], WNDSIZ
+ MAXMATCH
);
967 if (mMatchLen
> mRemainder
) {
968 mMatchLen
= mRemainder
;
971 while (mRemainder
> 0) {
972 LastMatchLen
= mMatchLen
;
973 LastMatchPos
= mMatchPos
;
975 if (mMatchLen
> mRemainder
) {
976 mMatchLen
= mRemainder
;
979 if (mMatchLen
> LastMatchLen
|| LastMatchLen
< THRESHOLD
) {
981 // Not enough benefits are gained by outputting a pointer,
982 // so just output the original character
984 Output (mText
[mPos
- 1], 0);
988 if (LastMatchLen
== THRESHOLD
) {
989 if (((mPos
- LastMatchPos
- 2) & (WNDSIZ
- 1)) > (1U << 11)) {
990 Output (mText
[mPos
- 1], 0);
995 // Outputting a pointer is beneficial enough, do it.
998 LastMatchLen
+ (UINT8_MAX
+ 1 - THRESHOLD
),
999 (mPos
- LastMatchPos
- 2) & (WNDSIZ
- 1)
1002 while (LastMatchLen
> 0) {
1007 if (mMatchLen
> mRemainder
) {
1008 mMatchLen
= mRemainder
;
1025 Routine Description:
1027 Count the frequencies for the Extra Set
1040 for (Index
= 0; Index
< NT
; Index
++) {
1045 while (Number
> 0 && mCLen
[Number
- 1] == 0) {
1050 while (Index
< Number
) {
1051 Index3
= mCLen
[Index
++];
1054 while (Index
< Number
&& mCLen
[Index
] == 0) {
1060 mTFreq
[0] = (UINT16
) (mTFreq
[0] + Count
);
1061 } else if (Count
<= 18) {
1063 } else if (Count
== 19) {
1070 mTFreq
[Index3
+ 2]++;
1084 Routine Description:
1086 Outputs the code length array for the Extra Set or the Position Set.
1090 Number - the number of symbols
1091 nbit - the number of bits needed to represent 'n'
1092 Special - the special symbol that needs to be take care of
1101 while (Number
> 0 && mPTLen
[Number
- 1] == 0) {
1105 PutBits (nbit
, Number
);
1107 while (Index
< Number
) {
1108 Index3
= mPTLen
[Index
++];
1110 PutBits (3, Index3
);
1112 PutBits (Index3
- 3, (1U << (Index3
- 3)) - 2);
1115 if (Index
== Special
) {
1116 while (Index
< 6 && mPTLen
[Index
] == 0) {
1120 PutBits (2, (Index
- 3) & 3);
1132 Routine Description:
1134 Outputs the code length array for Char&Length Set
1148 while (Number
> 0 && mCLen
[Number
- 1] == 0) {
1152 PutBits (CBIT
, Number
);
1154 while (Index
< Number
) {
1155 Index3
= mCLen
[Index
++];
1158 while (Index
< Number
&& mCLen
[Index
] == 0) {
1164 for (Index3
= 0; Index3
< Count
; Index3
++) {
1165 PutBits (mPTLen
[0], mPTCode
[0]);
1167 } else if (Count
<= 18) {
1168 PutBits (mPTLen
[1], mPTCode
[1]);
1169 PutBits (4, Count
- 3);
1170 } else if (Count
== 19) {
1171 PutBits (mPTLen
[0], mPTCode
[0]);
1172 PutBits (mPTLen
[1], mPTCode
[1]);
1175 PutBits (mPTLen
[2], mPTCode
[2]);
1176 PutBits (CBIT
, Count
- 20);
1179 PutBits (mPTLen
[Index3
+ 2], mPTCode
[Index3
+ 2]);
1190 PutBits (mCLen
[Value
], mCCode
[Value
]);
1209 PutBits (mPTLen
[Index
], mPTCode
[Index
]);
1211 PutBits (Index
- 1, Value
& (0xFFFFFFFFU
>> (32 - Index
+ 1)));
1222 Routine Description:
1224 Huffman code the block and output it.
1243 Root
= MakeTree (NC
, mCFreq
, mCLen
, mCCode
);
1244 Size
= mCFreq
[Root
];
1248 Root
= MakeTree (NT
, mTFreq
, mPTLen
, mPTCode
);
1250 WritePTLen (NT
, TBIT
, 3);
1253 PutBits (TBIT
, Root
);
1261 PutBits (CBIT
, Root
);
1264 Root
= MakeTree (NP
, mPFreq
, mPTLen
, mPTCode
);
1266 WritePTLen (NP
, PBIT
, -1);
1269 PutBits (PBIT
, Root
);
1273 for (Index
= 0; Index
< Size
; Index
++) {
1274 if (Index
% UINT8_BIT
== 0) {
1275 Flags
= mBuf
[Pos
++];
1280 if (Flags
& (1U << (UINT8_BIT
- 1))) {
1281 EncodeC (mBuf
[Pos
++] + (1U << UINT8_BIT
));
1282 Index3
= mBuf
[Pos
++];
1283 for (Index2
= 0; Index2
< 3; Index2
++) {
1284 Index3
<<= UINT8_BIT
;
1285 Index3
+= mBuf
[Pos
++];
1290 EncodeC (mBuf
[Pos
++]);
1294 for (Index
= 0; Index
< NC
; Index
++) {
1298 for (Index
= 0; Index
< NP
; Index
++) {
1311 Routine Description:
1313 Outputs an Original Character or a Pointer
1317 CharC - The original character or the 'String Length' element of a Pointer
1318 Pos - The 'Position' field of a Pointer
1326 if ((mOutputMask
>>= 1) == 0) {
1327 mOutputMask
= 1U << (UINT8_BIT
- 1);
1329 // Check the buffer overflow per outputing UINT8_BIT symbols
1330 // which is an Original Character or a Pointer. The biggest
1331 // symbol is a Pointer which occupies 5 bytes.
1333 if (mOutputPos
>= mBufSiz
- 5 * UINT8_BIT
) {
1338 CPos
= mOutputPos
++;
1342 mBuf
[mOutputPos
++] = (UINT8
) CharC
;
1344 if (CharC
>= (1U << UINT8_BIT
)) {
1345 mBuf
[CPos
] |= mOutputMask
;
1346 mBuf
[mOutputPos
++] = (UINT8
) (Pos
>> 24);
1347 mBuf
[mOutputPos
++] = (UINT8
) (Pos
>> 16);
1348 mBuf
[mOutputPos
++] = (UINT8
) (Pos
>> (UINT8_BIT
));
1349 mBuf
[mOutputPos
++] = (UINT8
) Pos
;
1368 for (Index
= 0; Index
< NC
; Index
++) {
1372 for (Index
= 0; Index
< NP
; Index
++) {
1376 mOutputPos
= mOutputMask
= 0;
1390 // Flush remaining bits
1392 PutBits (UINT8_BIT
- 1, 0);
1407 for (Index
= 0; Index
<= UINT8_MAX
; Index
++) {
1409 for (Index2
= 0; Index2
< UINT8_BIT
; Index2
++) {
1411 Temp
= (Temp
>> 1) ^ CRCPOLY
;
1417 mCrcTable
[Index
] = (UINT16
) Temp
;
1429 Routine Description:
1431 Outputs rightmost n bits of x
1435 Number - the rightmost n bits of the data is used
1444 while (Number
>= mBitCount
) {
1446 // Number -= mBitCount should never equal to 32
1448 Temp
= (UINT8
) (mSubBitBuf
| (Value
>> (Number
-= mBitCount
)));
1449 if (mDst
< mDstUpperLimit
) {
1455 mBitCount
= UINT8_BIT
;
1458 mSubBitBuf
|= Value
<< (mBitCount
-= Number
);
1469 Routine Description:
1475 Pointer - the buffer to hold the data
1476 Number - number of bytes to read
1480 number of bytes actually read
1486 for (Index
= 0; mSrc
< mSrcUpperLimit
&& Index
< Number
; Index
++) {
1487 *Pointer
++ = *mSrc
++;
1493 mOrigSize
+= Number
;
1495 while (Index
>= 0) {
1496 UPDATE_CRC (*Pointer
++);
1509 mBitCount
= UINT8_BIT
;
1520 Routine Description:
1522 Count the number of each code length for a Huffman tree.
1526 Index - the top node
1532 STATIC INT32 Depth
= 0;
1535 mLenCnt
[(Depth
< 16) ? Depth
: 16]++;
1538 CountLen (mLeft
[Index
]);
1539 CountLen (mRight
[Index
]);
1551 Routine Description:
1553 Create code length array for a Huffman tree
1557 Root - the root of the tree
1569 for (Index
= 0; Index
<= 16; Index
++) {
1576 // Adjust the length count array so that
1577 // no code will be generated longer than its designated length
1580 for (Index
= 16; Index
> 0; Index
--) {
1581 Cum
+= mLenCnt
[Index
] << (16 - Index
);
1584 while (Cum
!= (1U << 16)) {
1586 for (Index
= 15; Index
> 0; Index
--) {
1587 if (mLenCnt
[Index
] != 0) {
1589 mLenCnt
[Index
+ 1] += 2;
1597 for (Index
= 16; Index
> 0; Index
--) {
1598 Index3
= mLenCnt
[Index
];
1600 while (Index3
>= 0) {
1601 mLen
[*mSortPtr
++] = (UINT8
) Index
;
1617 // priority queue: send Index-th entry down heap
1619 Index3
= mHeap
[Index
];
1621 while (Index2
<= mHeapSize
) {
1622 if (Index2
< mHeapSize
&& mFreq
[mHeap
[Index2
]] > mFreq
[mHeap
[Index2
+ 1]]) {
1626 if (mFreq
[Index3
] <= mFreq
[mHeap
[Index2
]]) {
1630 mHeap
[Index
] = mHeap
[Index2
];
1635 mHeap
[Index
] = (INT16
) Index3
;
1647 Routine Description:
1649 Assign code to each symbol based on the code length array
1653 Number - number of symbols
1654 Len - the code length array
1655 Code - stores codes for each symbol
1665 for (Index
= 1; Index
<= 16; Index
++) {
1666 Start
[Index
+ 1] = (UINT16
) ((Start
[Index
] + mLenCnt
[Index
]) << 1);
1669 for (Index
= 0; Index
< Number
; Index
++) {
1670 Code
[Index
] = Start
[Len
[Index
]]++;
1678 IN UINT16 FreqParm
[],
1679 OUT UINT8 LenParm
[ ],
1680 OUT UINT16 CodeParm
[]
1684 Routine Description:
1686 Generates Huffman codes given a frequency distribution of symbols
1690 NParm - number of symbols
1691 FreqParm - frequency of each symbol
1692 LenParm - code length for each symbol
1693 CodeParm - code for each symbol
1697 Root of the Huffman tree.
1707 // make tree, calculate len[], return root
1715 for (Index
= 0; Index
< mN
; Index
++) {
1719 mHeap
[mHeapSize
] = (INT16
) Index
;
1723 if (mHeapSize
< 2) {
1724 CodeParm
[mHeap
[1]] = 0;
1728 for (Index
= mHeapSize
/ 2; Index
>= 1; Index
--) {
1730 // make priority queue
1735 mSortPtr
= CodeParm
;
1739 *mSortPtr
++ = (UINT16
) Index
;
1742 mHeap
[1] = mHeap
[mHeapSize
--];
1746 *mSortPtr
++ = (UINT16
) Index2
;
1750 mFreq
[Index3
] = (UINT16
) (mFreq
[Index
] + mFreq
[Index2
]);
1751 mHeap
[1] = (INT16
) Index3
;
1753 mLeft
[Index3
] = (UINT16
) Index
;
1754 mRight
[Index3
] = (UINT16
) Index2
;
1755 } while (mHeapSize
> 1);
1757 mSortPtr
= CodeParm
;
1759 MakeCode (NParm
, LenParm
, CodeParm
);