]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/Common/TianoCompress.c
2 Compression routine. The compression algorithm is a mixture of LZ77 and Huffman
3 coding. LZ77 transforms the source data into a sequence of Original Characters
4 and Pointers to repeated strings. This sequence is further divided into Blocks
5 and Huffman codings are applied to each Block.
7 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
19 #define UINT8_MAX 0xff
24 #define WNDSIZ (1U << WNDBIT)
26 #define BLKSIZ (1U << 14) // 16 * 1024U
27 #define PERC_FLAG 0x80000000U
30 #define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)
31 #define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2)
32 #define CRCPOLY 0xA001
33 #define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT)
36 // C: the Char&Len Set; P: the Position Set; T: the exTra Set
38 #define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)
40 #define NP (WNDBIT + 1)
42 #define NT (CODE_BIT + 3)
50 // Function Prototypes
235 IN UINT16 FreqParm
[],
236 OUT UINT8 LenParm
[ ],
237 OUT UINT16 CodeParm
[]
243 STATIC UINT8
*mSrc
, *mDst
, *mSrcUpperLimit
, *mDstUpperLimit
;
245 STATIC UINT8
*mLevel
, *mText
, *mChildCount
, *mBuf
, mCLen
[NC
], mPTLen
[NPT
], *mLen
;
246 STATIC INT16 mHeap
[NC
+ 1];
247 STATIC INT32 mRemainder
, mMatchLen
, mBitCount
, mHeapSize
, mN
;
248 STATIC UINT32 mBufSiz
= 0, mOutputPos
, mOutputMask
, mSubBitBuf
, mCrc
;
249 STATIC UINT32 mCompSize
, mOrigSize
;
251 STATIC UINT16
*mFreq
, *mSortPtr
, mLenCnt
[17], mLeft
[2 * NC
- 1], mRight
[2 * NC
- 1], mCrcTable
[UINT8_MAX
+ 1],
252 mCFreq
[2 * NC
- 1], mCCode
[NC
], mPFreq
[2 * NP
- 1], mPTCode
[NPT
], mTFreq
[2 * NT
- 1];
254 STATIC NODE mPos
, mMatchPos
, mAvail
, *mPosition
, *mParent
, *mPrev
, *mNext
= NULL
;
264 IN OUT UINT32
*DstSize
270 The internal implementation of [Efi/Tiano]Compress().
274 SrcBuffer - The buffer storing the source data
275 SrcSize - The size of source data
276 DstBuffer - The buffer to store the compressed data
277 DstSize - On input, the size of DstBuffer; On output,
278 the size of the actual compressed data.
279 Version - The version of de/compression algorithm.
280 Version 1 for UEFI 2.0 de/compression algorithm.
281 Version 2 for Tiano de/compression algorithm.
285 EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case,
286 DstSize contains the size needed.
287 EFI_SUCCESS - Compression is successful.
288 EFI_OUT_OF_RESOURCES - No resource to complete function.
289 EFI_INVALID_PARAMETER - Parameter supplied is wrong.
309 mSrcUpperLimit
= mSrc
+ SrcSize
;
311 mDstUpperLimit
= mDst
+*DstSize
;
318 mOrigSize
= mCompSize
= 0;
325 if (EFI_ERROR (Status
)) {
326 return EFI_OUT_OF_RESOURCES
;
329 // Null terminate the compressed data
331 if (mDst
< mDstUpperLimit
) {
335 // Fill in compressed size and original size
338 PutDword (mCompSize
+ 1);
339 PutDword (mOrigSize
);
344 if (mCompSize
+ 1 + 8 > *DstSize
) {
345 *DstSize
= mCompSize
+ 1 + 8;
346 return EFI_BUFFER_TOO_SMALL
;
348 *DstSize
= mCompSize
+ 1 + 8;
363 Put a dword to output stream
367 Data - the dword to put
373 if (mDst
< mDstUpperLimit
) {
374 *mDst
++ = (UINT8
) (((UINT8
) (Data
)) & 0xff);
377 if (mDst
< mDstUpperLimit
) {
378 *mDst
++ = (UINT8
) (((UINT8
) (Data
>> 0x08)) & 0xff);
381 if (mDst
< mDstUpperLimit
) {
382 *mDst
++ = (UINT8
) (((UINT8
) (Data
>> 0x10)) & 0xff);
385 if (mDst
< mDstUpperLimit
) {
386 *mDst
++ = (UINT8
) (((UINT8
) (Data
>> 0x18)) & 0xff);
399 Allocate memory spaces for data structures used in compression process
406 EFI_SUCCESS - Memory is allocated successfully
407 EFI_OUT_OF_RESOURCES - Allocation fails
413 mText
= malloc (WNDSIZ
* 2 + MAXMATCH
);
415 return EFI_OUT_OF_RESOURCES
;
417 for (Index
= 0; Index
< WNDSIZ
* 2 + MAXMATCH
; Index
++) {
421 mLevel
= malloc ((WNDSIZ
+ UINT8_MAX
+ 1) * sizeof (*mLevel
));
422 mChildCount
= malloc ((WNDSIZ
+ UINT8_MAX
+ 1) * sizeof (*mChildCount
));
423 mPosition
= malloc ((WNDSIZ
+ UINT8_MAX
+ 1) * sizeof (*mPosition
));
424 mParent
= malloc (WNDSIZ
* 2 * sizeof (*mParent
));
425 mPrev
= malloc (WNDSIZ
* 2 * sizeof (*mPrev
));
426 mNext
= malloc ((MAX_HASH_VAL
+ 1) * sizeof (*mNext
));
427 if (mLevel
== NULL
|| mChildCount
== NULL
|| mPosition
== NULL
||
428 mParent
== NULL
|| mPrev
== NULL
|| mNext
== NULL
) {
429 return EFI_OUT_OF_RESOURCES
;
433 mBuf
= malloc (mBufSiz
);
434 while (mBuf
== NULL
) {
435 mBufSiz
= (mBufSiz
/ 10U) * 9U;
436 if (mBufSiz
< 4 * 1024U) {
437 return EFI_OUT_OF_RESOURCES
;
440 mBuf
= malloc (mBufSiz
);
456 Called when compression is completed to free memory previously allocated.
468 if (mLevel
!= NULL
) {
472 if (mChildCount
!= NULL
) {
476 if (mPosition
!= NULL
) {
480 if (mParent
!= NULL
) {
508 Initialize String Info Log data structures
518 for (Index
= WNDSIZ
; Index
<= WNDSIZ
+ UINT8_MAX
; Index
++) {
520 mPosition
[Index
] = NIL
; /* sentinel */
523 for (Index
= WNDSIZ
; Index
< WNDSIZ
* 2; Index
++) {
524 mParent
[Index
] = NIL
;
528 for (Index
= 1; Index
< WNDSIZ
- 1; Index
++) {
529 mNext
[Index
] = (NODE
) (Index
+ 1);
532 mNext
[WNDSIZ
- 1] = NIL
;
533 for (Index
= WNDSIZ
* 2; Index
<= MAX_HASH_VAL
; Index
++) {
548 Find child node given the parent node and the edge character
552 NodeQ - the parent node
553 CharC - the edge character
557 The child node (NIL if not found)
563 NodeR
= mNext
[HASH (NodeQ
, CharC
)];
567 mParent
[NIL
] = NodeQ
;
568 while (mParent
[NodeR
] != NodeQ
) {
569 NodeR
= mNext
[NodeR
];
586 Create a new child for a given parent node.
590 Parent - the parent node
591 CharC - the edge character
592 Child - the child node
601 Node1
= (NODE
) HASH (Parent
, CharC
);
602 Node2
= mNext
[Node1
];
603 mNext
[Node1
] = Child
;
604 mNext
[Child
] = Node2
;
605 mPrev
[Node2
] = Child
;
606 mPrev
[Child
] = Node1
;
607 mParent
[Child
] = Parent
;
608 mChildCount
[Parent
]++;
624 Old - the node to split
635 mChildCount
[New
] = 0;
636 TempNode
= mPrev
[Old
];
637 mPrev
[New
] = TempNode
;
638 mNext
[TempNode
] = New
;
639 TempNode
= mNext
[Old
];
640 mNext
[New
] = TempNode
;
641 mPrev
[TempNode
] = New
;
642 mParent
[New
] = mParent
[Old
];
643 mLevel
[New
] = (UINT8
) mMatchLen
;
644 mPosition
[New
] = mPos
;
645 MakeChild (New
, mText
[mMatchPos
+ mMatchLen
], Old
);
646 MakeChild (New
, mText
[mPos
+ mMatchLen
], mPos
);
658 Insert string info for current position into the String Info Log
674 if (mMatchLen
>= 4) {
676 // We have just got a long match, the target tree
677 // can be located by MatchPos + 1. Traverse the tree
678 // from bottom up to get to a proper starting point.
679 // The usage of PERC_FLAG ensures proper node deletion
680 // in DeleteNode() later.
683 NodeR
= (NODE
) ((mMatchPos
+ 1) | WNDSIZ
);
684 NodeQ
= mParent
[NodeR
];
685 while (NodeQ
== NIL
) {
686 NodeR
= mNext
[NodeR
];
687 NodeQ
= mParent
[NodeR
];
690 while (mLevel
[NodeQ
] >= mMatchLen
) {
692 NodeQ
= mParent
[NodeQ
];
696 while (mPosition
[NodeT
] < 0) {
697 mPosition
[NodeT
] = mPos
;
698 NodeT
= mParent
[NodeT
];
701 if (NodeT
< WNDSIZ
) {
702 mPosition
[NodeT
] = (NODE
) (mPos
| (UINT32
) PERC_FLAG
);
706 // Locate the target tree
708 NodeQ
= (NODE
) (mText
[mPos
] + WNDSIZ
);
709 CharC
= mText
[mPos
+ 1];
710 NodeR
= Child (NodeQ
, CharC
);
712 MakeChild (NodeQ
, CharC
, mPos
);
720 // Traverse down the tree to find a match.
721 // Update Position value along the route.
722 // Node split or creation is involved.
725 if (NodeR
>= WNDSIZ
) {
729 Index2
= mLevel
[NodeR
];
730 mMatchPos
= (NODE
) (mPosition
[NodeR
] & (UINT32
)~PERC_FLAG
);
733 if (mMatchPos
>= mPos
) {
737 t1
= &mText
[mPos
+ mMatchLen
];
738 t2
= &mText
[mMatchPos
+ mMatchLen
];
739 while (mMatchLen
< Index2
) {
750 if (mMatchLen
>= MAXMATCH
) {
754 mPosition
[NodeR
] = mPos
;
756 NodeR
= Child (NodeQ
, *t1
);
758 MakeChild (NodeQ
, *t1
, mPos
);
765 NodeT
= mPrev
[NodeR
];
768 NodeT
= mNext
[NodeR
];
771 mParent
[mPos
] = NodeQ
;
772 mParent
[NodeR
] = NIL
;
775 // Special usage of 'next'
790 Delete outdated string info. (The Usage of PERC_FLAG
791 ensures a clean deletion)
805 if (mParent
[mPos
] == NIL
) {
811 mNext
[NodeR
] = NodeS
;
812 mPrev
[NodeS
] = NodeR
;
813 NodeR
= mParent
[mPos
];
815 if (NodeR
>= WNDSIZ
) {
819 mChildCount
[NodeR
]--;
820 if (mChildCount
[NodeR
] > 1) {
824 NodeT
= (NODE
) (mPosition
[NodeR
] & (UINT32
)~PERC_FLAG
);
830 NodeQ
= mParent
[NodeR
];
831 NodeU
= mPosition
[NodeQ
];
832 while (NodeU
& (UINT32
) PERC_FLAG
) {
833 NodeU
&= (UINT32
)~PERC_FLAG
;
842 mPosition
[NodeQ
] = (NODE
) (NodeS
| WNDSIZ
);
843 NodeQ
= mParent
[NodeQ
];
844 NodeU
= mPosition
[NodeQ
];
847 if (NodeQ
< WNDSIZ
) {
856 mPosition
[NodeQ
] = (NODE
) (NodeS
| WNDSIZ
| (UINT32
) PERC_FLAG
);
859 NodeS
= Child (NodeR
, mText
[NodeT
+ mLevel
[NodeR
]]);
860 NodeT
= mPrev
[NodeS
];
861 NodeU
= mNext
[NodeS
];
862 mNext
[NodeT
] = NodeU
;
863 mPrev
[NodeU
] = NodeT
;
864 NodeT
= mPrev
[NodeR
];
865 mNext
[NodeT
] = NodeS
;
866 mPrev
[NodeS
] = NodeT
;
867 NodeT
= mNext
[NodeR
];
868 mPrev
[NodeT
] = NodeS
;
869 mNext
[NodeS
] = NodeT
;
870 mParent
[NodeS
] = mParent
[NodeR
];
871 mParent
[NodeR
] = NIL
;
872 mNext
[NodeR
] = mAvail
;
885 Advance the current position (read in new data if needed).
886 Delete outdated string info. Find a match string for current position.
898 if (mPos
== WNDSIZ
* 2) {
899 memmove (&mText
[0], &mText
[WNDSIZ
], WNDSIZ
+ MAXMATCH
);
900 Number
= FreadCrc (&mText
[WNDSIZ
+ MAXMATCH
], WNDSIZ
);
901 mRemainder
+= Number
;
918 The main controlling routine for compression process.
924 EFI_SUCCESS - The compression is successful
925 EFI_OUT_0F_RESOURCES - Not enough memory for compression process
933 Status
= AllocateMemory ();
934 if (EFI_ERROR (Status
)) {
943 mRemainder
= FreadCrc (&mText
[WNDSIZ
], WNDSIZ
+ MAXMATCH
);
948 if (mMatchLen
> mRemainder
) {
949 mMatchLen
= mRemainder
;
952 while (mRemainder
> 0) {
953 LastMatchLen
= mMatchLen
;
954 LastMatchPos
= mMatchPos
;
956 if (mMatchLen
> mRemainder
) {
957 mMatchLen
= mRemainder
;
960 if (mMatchLen
> LastMatchLen
|| LastMatchLen
< THRESHOLD
) {
962 // Not enough benefits are gained by outputting a pointer,
963 // so just output the original character
965 Output (mText
[mPos
- 1], 0);
969 if (LastMatchLen
== THRESHOLD
) {
970 if (((mPos
- LastMatchPos
- 2) & (WNDSIZ
- 1)) > (1U << 11)) {
971 Output (mText
[mPos
- 1], 0);
976 // Outputting a pointer is beneficial enough, do it.
979 LastMatchLen
+ (UINT8_MAX
+ 1 - THRESHOLD
),
980 (mPos
- LastMatchPos
- 2) & (WNDSIZ
- 1)
983 while (LastMatchLen
> 0) {
988 if (mMatchLen
> mRemainder
) {
989 mMatchLen
= mRemainder
;
1006 Routine Description:
1008 Count the frequencies for the Extra Set
1021 for (Index
= 0; Index
< NT
; Index
++) {
1026 while (Number
> 0 && mCLen
[Number
- 1] == 0) {
1031 while (Index
< Number
) {
1032 Index3
= mCLen
[Index
++];
1035 while (Index
< Number
&& mCLen
[Index
] == 0) {
1041 mTFreq
[0] = (UINT16
) (mTFreq
[0] + Count
);
1042 } else if (Count
<= 18) {
1044 } else if (Count
== 19) {
1051 mTFreq
[Index3
+ 2]++;
1065 Routine Description:
1067 Outputs the code length array for the Extra Set or the Position Set.
1071 Number - the number of symbols
1072 nbit - the number of bits needed to represent 'n'
1073 Special - the special symbol that needs to be take care of
1082 while (Number
> 0 && mPTLen
[Number
- 1] == 0) {
1086 PutBits (nbit
, Number
);
1088 while (Index
< Number
) {
1089 Index3
= mPTLen
[Index
++];
1091 PutBits (3, Index3
);
1093 PutBits (Index3
- 3, (1U << (Index3
- 3)) - 2);
1096 if (Index
== Special
) {
1097 while (Index
< 6 && mPTLen
[Index
] == 0) {
1101 PutBits (2, (Index
- 3) & 3);
1113 Routine Description:
1115 Outputs the code length array for Char&Length Set
1129 while (Number
> 0 && mCLen
[Number
- 1] == 0) {
1133 PutBits (CBIT
, Number
);
1135 while (Index
< Number
) {
1136 Index3
= mCLen
[Index
++];
1139 while (Index
< Number
&& mCLen
[Index
] == 0) {
1145 for (Index3
= 0; Index3
< Count
; Index3
++) {
1146 PutBits (mPTLen
[0], mPTCode
[0]);
1148 } else if (Count
<= 18) {
1149 PutBits (mPTLen
[1], mPTCode
[1]);
1150 PutBits (4, Count
- 3);
1151 } else if (Count
== 19) {
1152 PutBits (mPTLen
[0], mPTCode
[0]);
1153 PutBits (mPTLen
[1], mPTCode
[1]);
1156 PutBits (mPTLen
[2], mPTCode
[2]);
1157 PutBits (CBIT
, Count
- 20);
1160 PutBits (mPTLen
[Index3
+ 2], mPTCode
[Index3
+ 2]);
1171 PutBits (mCLen
[Value
], mCCode
[Value
]);
1190 PutBits (mPTLen
[Index
], mPTCode
[Index
]);
1192 PutBits (Index
- 1, Value
& (0xFFFFFFFFU
>> (32 - Index
+ 1)));
1203 Routine Description:
1205 Huffman code the block and output it.
1224 Root
= MakeTree (NC
, mCFreq
, mCLen
, mCCode
);
1225 Size
= mCFreq
[Root
];
1229 Root
= MakeTree (NT
, mTFreq
, mPTLen
, mPTCode
);
1231 WritePTLen (NT
, TBIT
, 3);
1234 PutBits (TBIT
, Root
);
1242 PutBits (CBIT
, Root
);
1245 Root
= MakeTree (NP
, mPFreq
, mPTLen
, mPTCode
);
1247 WritePTLen (NP
, PBIT
, -1);
1250 PutBits (PBIT
, Root
);
1254 for (Index
= 0; Index
< Size
; Index
++) {
1255 if (Index
% UINT8_BIT
== 0) {
1256 Flags
= mBuf
[Pos
++];
1261 if (Flags
& (1U << (UINT8_BIT
- 1))) {
1262 EncodeC (mBuf
[Pos
++] + (1U << UINT8_BIT
));
1263 Index3
= mBuf
[Pos
++];
1264 for (Index2
= 0; Index2
< 3; Index2
++) {
1265 Index3
<<= UINT8_BIT
;
1266 Index3
+= mBuf
[Pos
++];
1271 EncodeC (mBuf
[Pos
++]);
1275 for (Index
= 0; Index
< NC
; Index
++) {
1279 for (Index
= 0; Index
< NP
; Index
++) {
1292 Routine Description:
1294 Outputs an Original Character or a Pointer
1298 CharC - The original character or the 'String Length' element of a Pointer
1299 Pos - The 'Position' field of a Pointer
1307 if ((mOutputMask
>>= 1) == 0) {
1308 mOutputMask
= 1U << (UINT8_BIT
- 1);
1310 // Check the buffer overflow per outputing UINT8_BIT symbols
1311 // which is an Original Character or a Pointer. The biggest
1312 // symbol is a Pointer which occupies 5 bytes.
1314 if (mOutputPos
>= mBufSiz
- 5 * UINT8_BIT
) {
1319 CPos
= mOutputPos
++;
1323 mBuf
[mOutputPos
++] = (UINT8
) CharC
;
1325 if (CharC
>= (1U << UINT8_BIT
)) {
1326 mBuf
[CPos
] |= mOutputMask
;
1327 mBuf
[mOutputPos
++] = (UINT8
) (Pos
>> 24);
1328 mBuf
[mOutputPos
++] = (UINT8
) (Pos
>> 16);
1329 mBuf
[mOutputPos
++] = (UINT8
) (Pos
>> (UINT8_BIT
));
1330 mBuf
[mOutputPos
++] = (UINT8
) Pos
;
1349 for (Index
= 0; Index
< NC
; Index
++) {
1353 for (Index
= 0; Index
< NP
; Index
++) {
1357 mOutputPos
= mOutputMask
= 0;
1371 // Flush remaining bits
1373 PutBits (UINT8_BIT
- 1, 0);
1388 for (Index
= 0; Index
<= UINT8_MAX
; Index
++) {
1390 for (Index2
= 0; Index2
< UINT8_BIT
; Index2
++) {
1392 Temp
= (Temp
>> 1) ^ CRCPOLY
;
1398 mCrcTable
[Index
] = (UINT16
) Temp
;
1410 Routine Description:
1412 Outputs rightmost n bits of x
1416 Number - the rightmost n bits of the data is used
1425 while (Number
>= mBitCount
) {
1427 // Number -= mBitCount should never equal to 32
1429 Temp
= (UINT8
) (mSubBitBuf
| (Value
>> (Number
-= mBitCount
)));
1430 if (mDst
< mDstUpperLimit
) {
1436 mBitCount
= UINT8_BIT
;
1439 mSubBitBuf
|= Value
<< (mBitCount
-= Number
);
1450 Routine Description:
1456 Pointer - the buffer to hold the data
1457 Number - number of bytes to read
1461 number of bytes actually read
1467 for (Index
= 0; mSrc
< mSrcUpperLimit
&& Index
< Number
; Index
++) {
1468 *Pointer
++ = *mSrc
++;
1474 mOrigSize
+= Number
;
1476 while (Index
>= 0) {
1477 UPDATE_CRC (*Pointer
++);
1490 mBitCount
= UINT8_BIT
;
1501 Routine Description:
1503 Count the number of each code length for a Huffman tree.
1507 Index - the top node
1513 STATIC INT32 Depth
= 0;
1516 mLenCnt
[(Depth
< 16) ? Depth
: 16]++;
1519 CountLen (mLeft
[Index
]);
1520 CountLen (mRight
[Index
]);
1532 Routine Description:
1534 Create code length array for a Huffman tree
1538 Root - the root of the tree
1550 for (Index
= 0; Index
<= 16; Index
++) {
1557 // Adjust the length count array so that
1558 // no code will be generated longer than its designated length
1561 for (Index
= 16; Index
> 0; Index
--) {
1562 Cum
+= mLenCnt
[Index
] << (16 - Index
);
1565 while (Cum
!= (1U << 16)) {
1567 for (Index
= 15; Index
> 0; Index
--) {
1568 if (mLenCnt
[Index
] != 0) {
1570 mLenCnt
[Index
+ 1] += 2;
1578 for (Index
= 16; Index
> 0; Index
--) {
1579 Index3
= mLenCnt
[Index
];
1581 while (Index3
>= 0) {
1582 mLen
[*mSortPtr
++] = (UINT8
) Index
;
1598 // priority queue: send Index-th entry down heap
1600 Index3
= mHeap
[Index
];
1602 while (Index2
<= mHeapSize
) {
1603 if (Index2
< mHeapSize
&& mFreq
[mHeap
[Index2
]] > mFreq
[mHeap
[Index2
+ 1]]) {
1607 if (mFreq
[Index3
] <= mFreq
[mHeap
[Index2
]]) {
1611 mHeap
[Index
] = mHeap
[Index2
];
1616 mHeap
[Index
] = (INT16
) Index3
;
1628 Routine Description:
1630 Assign code to each symbol based on the code length array
1634 Number - number of symbols
1635 Len - the code length array
1636 Code - stores codes for each symbol
1646 for (Index
= 1; Index
<= 16; Index
++) {
1647 Start
[Index
+ 1] = (UINT16
) ((Start
[Index
] + mLenCnt
[Index
]) << 1);
1650 for (Index
= 0; Index
< Number
; Index
++) {
1651 Code
[Index
] = Start
[Len
[Index
]]++;
1659 IN UINT16 FreqParm
[],
1660 OUT UINT8 LenParm
[ ],
1661 OUT UINT16 CodeParm
[]
1665 Routine Description:
1667 Generates Huffman codes given a frequency distribution of symbols
1671 NParm - number of symbols
1672 FreqParm - frequency of each symbol
1673 LenParm - code length for each symbol
1674 CodeParm - code for each symbol
1678 Root of the Huffman tree.
1688 // make tree, calculate len[], return root
1696 for (Index
= 0; Index
< mN
; Index
++) {
1700 mHeap
[mHeapSize
] = (INT16
) Index
;
1704 if (mHeapSize
< 2) {
1705 CodeParm
[mHeap
[1]] = 0;
1709 for (Index
= mHeapSize
/ 2; Index
>= 1; Index
--) {
1711 // make priority queue
1716 mSortPtr
= CodeParm
;
1720 *mSortPtr
++ = (UINT16
) Index
;
1723 mHeap
[1] = mHeap
[mHeapSize
--];
1727 *mSortPtr
++ = (UINT16
) Index2
;
1731 mFreq
[Index3
] = (UINT16
) (mFreq
[Index
] + mFreq
[Index2
]);
1732 mHeap
[1] = (INT16
) Index3
;
1734 mLeft
[Index3
] = (UINT16
) Index
;
1735 mRight
[Index3
] = (UINT16
) Index2
;
1736 } while (mHeapSize
> 1);
1738 mSortPtr
= CodeParm
;
1740 MakeCode (NParm
, LenParm
, CodeParm
);