2 Main file for compression routine.
4 Compression routine. The compression algorithm is a mixture of
5 LZ77 and Huffman coding. LZ77 transforms the source data into a
6 sequence of Original Characters and Pointers to repeated strings.
7 This sequence is further divided into Blocks and Huffman codings
8 are applied to each Block.
10 Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
11 This program and the accompanying materials
12 are licensed and made available under the terms and conditions of the BSD License
13 which accompanies this distribution. The full text of the license may be found at
14 http://opensource.org/licenses/bsd-license.php
16 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 #include <Library/MemoryAllocationLib.h>
22 #include <Library/BaseMemoryLib.h>
23 #include <Library/DebugLib.h>
24 #include <ShellBase.h>
31 #define UINT8_MAX 0xff
36 #define WNDSIZ (1U << WNDBIT)
38 #define BLKSIZ (1U << 14) // 16 * 1024U
39 #define PERC_FLAG 0x8000U
42 #define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)
43 #define HASH(LoopVar7, LoopVar5) ((LoopVar7) + ((LoopVar5) << (WNDBIT - 9)) + WNDSIZ * 2)
44 #define CRCPOLY 0xA001
45 #define UPDATE_CRC(LoopVar5) mCrc = mCrcTable[(mCrc ^ (LoopVar5)) & 0xFF] ^ (mCrc >> UINT8_BIT)
48 // C: the Char&Len Set; P: the Position Set; T: the exTra Set
50 #define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)
52 #define NP (WNDBIT + 1)
54 #define NT (CODE_BIT + 3)
62 // Function Prototypes
66 Put a dword to output stream
68 @param[in] Data The dword to put.
80 STATIC UINT8
*mSrcUpperLimit
;
81 STATIC UINT8
*mDstUpperLimit
;
85 STATIC UINT8
*mChildCount
;
87 STATIC UINT8 mCLen
[NC
];
88 STATIC UINT8 mPTLen
[NPT
];
90 STATIC INT16 mHeap
[NC
+ 1];
91 STATIC INT32 mRemainder
;
92 STATIC INT32 mMatchLen
;
93 STATIC INT32 mBitCount
;
94 STATIC INT32 mHeapSize
;
95 STATIC INT32 mTempInt32
;
96 STATIC UINT32 mBufSiz
= 0;
97 STATIC UINT32 mOutputPos
;
98 STATIC UINT32 mOutputMask
;
99 STATIC UINT32 mSubBitBuf
;
101 STATIC UINT32 mCompSize
;
102 STATIC UINT32 mOrigSize
;
104 STATIC UINT16
*mFreq
;
105 STATIC UINT16
*mSortPtr
;
106 STATIC UINT16 mLenCnt
[17];
107 STATIC UINT16 mLeft
[2 * NC
- 1];
108 STATIC UINT16 mRight
[2 * NC
- 1];
109 STATIC UINT16 mCrcTable
[UINT8_MAX
+ 1];
110 STATIC UINT16 mCFreq
[2 * NC
- 1];
111 STATIC UINT16 mCCode
[NC
];
112 STATIC UINT16 mPFreq
[2 * NP
- 1];
113 STATIC UINT16 mPTCode
[NPT
];
114 STATIC UINT16 mTFreq
[2 * NT
- 1];
117 STATIC NODE mMatchPos
;
119 STATIC NODE
*mPosition
;
120 STATIC NODE
*mParent
;
122 STATIC NODE
*mNext
= NULL
;
123 INT32 mHuffmanDepth
= 0;
140 for (LoopVar1
= 0; LoopVar1
<= UINT8_MAX
; LoopVar1
++) {
142 for (LoopVar2
= 0; LoopVar2
< UINT8_BIT
; LoopVar2
++) {
143 if ((LoopVar4
& 1) != 0) {
144 LoopVar4
= (LoopVar4
>> 1) ^ CRCPOLY
;
150 mCrcTable
[LoopVar1
] = (UINT16
) LoopVar4
;
155 Put a dword to output stream
157 @param[in] Data The dword to put.
164 if (mDst
< mDstUpperLimit
) {
165 *mDst
++ = (UINT8
) (((UINT8
) (Data
)) & 0xff);
168 if (mDst
< mDstUpperLimit
) {
169 *mDst
++ = (UINT8
) (((UINT8
) (Data
>> 0x08)) & 0xff);
172 if (mDst
< mDstUpperLimit
) {
173 *mDst
++ = (UINT8
) (((UINT8
) (Data
>> 0x10)) & 0xff);
176 if (mDst
< mDstUpperLimit
) {
177 *mDst
++ = (UINT8
) (((UINT8
) (Data
>> 0x18)) & 0xff);
182 Allocate memory spaces for data structures used in compression process.
184 @retval EFI_SUCCESS Memory was allocated successfully.
185 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
192 mText
= AllocateZeroPool (WNDSIZ
* 2 + MAXMATCH
);
193 mLevel
= AllocateZeroPool ((WNDSIZ
+ UINT8_MAX
+ 1) * sizeof (*mLevel
));
194 mChildCount
= AllocateZeroPool ((WNDSIZ
+ UINT8_MAX
+ 1) * sizeof (*mChildCount
));
195 mPosition
= AllocateZeroPool ((WNDSIZ
+ UINT8_MAX
+ 1) * sizeof (*mPosition
));
196 mParent
= AllocateZeroPool (WNDSIZ
* 2 * sizeof (*mParent
));
197 mPrev
= AllocateZeroPool (WNDSIZ
* 2 * sizeof (*mPrev
));
198 mNext
= AllocateZeroPool ((MAX_HASH_VAL
+ 1) * sizeof (*mNext
));
201 mBuf
= AllocateZeroPool (mBufSiz
);
202 while (mBuf
== NULL
) {
203 mBufSiz
= (mBufSiz
/ 10U) * 9U;
204 if (mBufSiz
< 4 * 1024U) {
205 return EFI_OUT_OF_RESOURCES
;
208 mBuf
= AllocateZeroPool (mBufSiz
);
217 Called when compression is completed to free memory previously allocated.
225 SHELL_FREE_NON_NULL (mText
);
226 SHELL_FREE_NON_NULL (mLevel
);
227 SHELL_FREE_NON_NULL (mChildCount
);
228 SHELL_FREE_NON_NULL (mPosition
);
229 SHELL_FREE_NON_NULL (mParent
);
230 SHELL_FREE_NON_NULL (mPrev
);
231 SHELL_FREE_NON_NULL (mNext
);
232 SHELL_FREE_NON_NULL (mBuf
);
236 Initialize String Info Log data structures.
245 SetMem (mLevel
+ WNDSIZ
, (UINT8_MAX
+ 1) * sizeof (UINT8
), 1);
246 SetMem (mPosition
+ WNDSIZ
, (UINT8_MAX
+ 1) * sizeof (NODE
), 0);
248 SetMem (mParent
+ WNDSIZ
, WNDSIZ
* sizeof (NODE
), 0);
251 for (LoopVar1
= 1; LoopVar1
< WNDSIZ
- 1; LoopVar1
++) {
252 mNext
[LoopVar1
] = (NODE
) (LoopVar1
+ 1);
255 mNext
[WNDSIZ
- 1] = NIL
;
256 SetMem (mNext
+ WNDSIZ
* 2, (MAX_HASH_VAL
- WNDSIZ
* 2 + 1) * sizeof (NODE
), 0);
260 Find child node given the parent node and the edge character
262 @param[in] LoopVar6 The parent node.
263 @param[in] LoopVar5 The edge character.
265 @return The child node.
266 @retval NIL(Zero) No child could be found.
277 LoopVar4
= mNext
[HASH (LoopVar6
, LoopVar5
)];
278 mParent
[NIL
] = LoopVar6
; /* sentinel */
279 while (mParent
[LoopVar4
] != LoopVar6
) {
280 LoopVar4
= mNext
[LoopVar4
];
287 Create a new child for a given parent node.
289 @param[in] LoopVar6 The parent node.
290 @param[in] LoopVar5 The edge character.
291 @param[in] LoopVar4 The child node.
304 LoopVar12
= (NODE
) HASH (LoopVar6
, LoopVar5
);
305 LoopVar10
= mNext
[LoopVar12
];
306 mNext
[LoopVar12
] = LoopVar4
;
307 mNext
[LoopVar4
] = LoopVar10
;
308 mPrev
[LoopVar10
] = LoopVar4
;
309 mPrev
[LoopVar4
] = LoopVar12
;
310 mParent
[LoopVar4
] = LoopVar6
;
311 mChildCount
[LoopVar6
]++;
317 @param[in] Old The node to split.
330 mChildCount
[New
] = 0;
331 LoopVar10
= mPrev
[Old
];
332 mPrev
[New
] = LoopVar10
;
333 mNext
[LoopVar10
] = New
;
334 LoopVar10
= mNext
[Old
];
335 mNext
[New
] = LoopVar10
;
336 mPrev
[LoopVar10
] = New
;
337 mParent
[New
] = mParent
[Old
];
338 mLevel
[New
] = (UINT8
) mMatchLen
;
339 mPosition
[New
] = mPos
;
340 MakeChild (New
, mText
[mMatchPos
+ mMatchLen
], Old
);
341 MakeChild (New
, mText
[mPos
+ mMatchLen
], mPos
);
345 Insert string info for current position into the String Info Log.
364 if (mMatchLen
>= 4) {
366 // We have just got a long match, the target tree
367 // can be located by MatchPos + 1. Travese the tree
368 // from bottom up to get to a proper starting point.
369 // The usage of PERC_FLAG ensures proper node deletion
370 // in DeleteNode() later.
373 LoopVar4
= (NODE
) ((mMatchPos
+ 1) | WNDSIZ
);
374 LoopVar6
= mParent
[LoopVar4
];
375 while (LoopVar6
== NIL
) {
376 LoopVar4
= mNext
[LoopVar4
];
377 LoopVar6
= mParent
[LoopVar4
];
380 while (mLevel
[LoopVar6
] >= mMatchLen
) {
382 LoopVar6
= mParent
[LoopVar6
];
385 LoopVar10
= LoopVar6
;
386 while (mPosition
[LoopVar10
] < 0) {
387 mPosition
[LoopVar10
] = mPos
;
388 LoopVar10
= mParent
[LoopVar10
];
391 if (LoopVar10
< WNDSIZ
) {
392 mPosition
[LoopVar10
] = (NODE
) (mPos
| PERC_FLAG
);
396 // Locate the target tree
398 LoopVar6
= (NODE
) (mText
[mPos
] + WNDSIZ
);
399 LoopVar5
= mText
[mPos
+ 1];
400 LoopVar4
= Child (LoopVar6
, LoopVar5
);
401 if (LoopVar4
== NIL
) {
402 MakeChild (LoopVar6
, LoopVar5
, mPos
);
410 // Traverse down the tree to find a match.
411 // Update Position value along the route.
412 // Node split or creation is involved.
415 if (LoopVar4
>= WNDSIZ
) {
417 mMatchPos
= LoopVar4
;
419 LoopVar2
= mLevel
[LoopVar4
];
420 mMatchPos
= (NODE
) (mPosition
[LoopVar4
] & ~PERC_FLAG
);
423 if (mMatchPos
>= mPos
) {
427 TempString3
= &mText
[mPos
+ mMatchLen
];
428 TempString2
= &mText
[mMatchPos
+ mMatchLen
];
429 while (mMatchLen
< LoopVar2
) {
430 if (*TempString3
!= *TempString2
) {
440 if (mMatchLen
>= MAXMATCH
) {
444 mPosition
[LoopVar4
] = mPos
;
446 LoopVar4
= Child (LoopVar6
, *TempString3
);
447 if (LoopVar4
== NIL
) {
448 MakeChild (LoopVar6
, *TempString3
, mPos
);
455 LoopVar10
= mPrev
[LoopVar4
];
456 mPrev
[mPos
] = LoopVar10
;
457 mNext
[LoopVar10
] = mPos
;
458 LoopVar10
= mNext
[LoopVar4
];
459 mNext
[mPos
] = LoopVar10
;
460 mPrev
[LoopVar10
] = mPos
;
461 mParent
[mPos
] = LoopVar6
;
462 mParent
[LoopVar4
] = NIL
;
465 // Special usage of 'next'
467 mNext
[LoopVar4
] = mPos
;
472 Delete outdated string info. (The Usage of PERC_FLAG
473 ensures a clean deletion).
491 if (mParent
[mPos
] == NIL
) {
495 LoopVar4
= mPrev
[mPos
];
496 LoopVar11
= mNext
[mPos
];
497 mNext
[LoopVar4
] = LoopVar11
;
498 mPrev
[LoopVar11
] = LoopVar4
;
499 LoopVar4
= mParent
[mPos
];
501 if (LoopVar4
>= WNDSIZ
) {
505 mChildCount
[LoopVar4
]--;
506 if (mChildCount
[LoopVar4
] > 1) {
510 LoopVar10
= (NODE
) (mPosition
[LoopVar4
] & ~PERC_FLAG
);
511 if (LoopVar10
>= mPos
) {
515 LoopVar11
= LoopVar10
;
516 LoopVar6
= mParent
[LoopVar4
];
517 LoopVar9
= mPosition
[LoopVar6
];
518 while ((LoopVar9
& PERC_FLAG
) != 0){
519 LoopVar9
&= ~PERC_FLAG
;
520 if (LoopVar9
>= mPos
) {
524 if (LoopVar9
> LoopVar11
) {
525 LoopVar11
= LoopVar9
;
528 mPosition
[LoopVar6
] = (NODE
) (LoopVar11
| WNDSIZ
);
529 LoopVar6
= mParent
[LoopVar6
];
530 LoopVar9
= mPosition
[LoopVar6
];
533 if (LoopVar6
< WNDSIZ
) {
534 if (LoopVar9
>= mPos
) {
538 if (LoopVar9
> LoopVar11
) {
539 LoopVar11
= LoopVar9
;
542 mPosition
[LoopVar6
] = (NODE
) (LoopVar11
| WNDSIZ
| PERC_FLAG
);
545 LoopVar11
= Child (LoopVar4
, mText
[LoopVar10
+ mLevel
[LoopVar4
]]);
546 LoopVar10
= mPrev
[LoopVar11
];
547 LoopVar9
= mNext
[LoopVar11
];
548 mNext
[LoopVar10
] = LoopVar9
;
549 mPrev
[LoopVar9
] = LoopVar10
;
550 LoopVar10
= mPrev
[LoopVar4
];
551 mNext
[LoopVar10
] = LoopVar11
;
552 mPrev
[LoopVar11
] = LoopVar10
;
553 LoopVar10
= mNext
[LoopVar4
];
554 mPrev
[LoopVar10
] = LoopVar11
;
555 mNext
[LoopVar11
] = LoopVar10
;
556 mParent
[LoopVar11
] = mParent
[LoopVar4
];
557 mParent
[LoopVar4
] = NIL
;
558 mNext
[LoopVar4
] = mAvail
;
565 @param[out] LoopVar7 The buffer to hold the data.
566 @param[in] LoopVar8 The number of bytes to read.
568 @return The number of bytes actually read.
578 for (LoopVar1
= 0; mSrc
< mSrcUpperLimit
&& LoopVar1
< LoopVar8
; LoopVar1
++) {
579 *LoopVar7
++ = *mSrc
++;
584 LoopVar7
-= LoopVar8
;
585 mOrigSize
+= LoopVar8
;
587 while (LoopVar1
>= 0) {
588 UPDATE_CRC (*LoopVar7
++);
596 Advance the current position (read in new data if needed).
597 Delete outdated string info. Find a match string for current position.
599 @retval TRUE The operation was successful.
600 @retval FALSE The operation failed due to insufficient memory.
612 if (mPos
== WNDSIZ
* 2) {
613 Temp
= AllocateZeroPool (WNDSIZ
+ MAXMATCH
);
617 CopyMem (Temp
, &mText
[WNDSIZ
], WNDSIZ
+ MAXMATCH
);
618 CopyMem (&mText
[0], Temp
, WNDSIZ
+ MAXMATCH
);
620 LoopVar8
= FreadCrc (&mText
[WNDSIZ
+ MAXMATCH
], WNDSIZ
);
621 mRemainder
+= LoopVar8
;
632 Send entry LoopVar1 down the queue.
634 @param[in] LoopVar1 The index of the item to move.
646 // priority queue: send i-th entry down heap
650 while (LoopVar1
<= mHeapSize
) {
651 if (LoopVar1
< mHeapSize
&& mFreq
[mHeap
[LoopVar1
]] > mFreq
[mHeap
[LoopVar1
+ 1]]) {
655 if (mFreq
[LoopVar2
] <= mFreq
[mHeap
[LoopVar1
]]) {
659 mHeap
[i
] = mHeap
[LoopVar1
];
664 mHeap
[i
] = (INT16
) LoopVar2
;
668 Count the number of each code length for a Huffman tree.
670 @param[in] LoopVar1 The top node.
677 if (LoopVar1
< mTempInt32
) {
678 mLenCnt
[(mHuffmanDepth
< 16) ? mHuffmanDepth
: 16]++;
681 CountLen (mLeft
[LoopVar1
]);
682 CountLen (mRight
[LoopVar1
]);
688 Create code length array for a Huffman tree.
690 @param[in] Root The root of the tree.
702 for (LoopVar1
= 0; LoopVar1
<= 16; LoopVar1
++) {
703 mLenCnt
[LoopVar1
] = 0;
709 // Adjust the length count array so that
710 // no code will be generated longer than its designated length
713 for (LoopVar1
= 16; LoopVar1
> 0; LoopVar1
--) {
714 Cum
+= mLenCnt
[LoopVar1
] << (16 - LoopVar1
);
717 while (Cum
!= (1U << 16)) {
719 for (LoopVar1
= 15; LoopVar1
> 0; LoopVar1
--) {
720 if (mLenCnt
[LoopVar1
] != 0) {
722 mLenCnt
[LoopVar1
+ 1] += 2;
730 for (LoopVar1
= 16; LoopVar1
> 0; LoopVar1
--) {
731 LoopVar2
= mLenCnt
[LoopVar1
];
733 while (LoopVar2
>= 0) {
734 mLen
[*mSortPtr
++] = (UINT8
) LoopVar1
;
741 Assign code to each symbol based on the code length array.
743 @param[in] LoopVar8 The number of symbols.
744 @param[in] Len The code length array.
745 @param[out] Code The stores codes for each symbol.
758 for (LoopVar1
= 1; LoopVar1
<= 16; LoopVar1
++) {
759 Start
[LoopVar1
+ 1] = (UINT16
) ((Start
[LoopVar1
] + mLenCnt
[LoopVar1
]) << 1);
762 for (LoopVar1
= 0; LoopVar1
< LoopVar8
; LoopVar1
++) {
763 Code
[LoopVar1
] = Start
[Len
[LoopVar1
]]++;
768 Generates Huffman codes given a frequency distribution of symbols.
770 @param[in] NParm The number of symbols.
771 @param[in] FreqParm The frequency of each symbol.
772 @param[out] LenParm The code length for each symbol.
773 @param[out] CodeParm The code for each symbol.
775 @return The root of the Huffman tree.
780 IN UINT16 FreqParm
[ ],
781 OUT UINT8 LenParm
[ ],
782 OUT UINT16 CodeParm
[ ]
794 // make tree, calculate len[], return root
802 for (LoopVar1
= 0; LoopVar1
< mTempInt32
; LoopVar1
++) {
804 if ((mFreq
[LoopVar1
]) != 0) {
806 mHeap
[mHeapSize
] = (INT16
) LoopVar1
;
811 CodeParm
[mHeap
[1]] = 0;
815 for (LoopVar1
= mHeapSize
/ 2; LoopVar1
>= 1; LoopVar1
--) {
817 // make priority queue
825 if (LoopVar1
< mTempInt32
) {
826 *mSortPtr
++ = (UINT16
) LoopVar1
;
829 mHeap
[1] = mHeap
[mHeapSize
--];
832 if (LoopVar2
< mTempInt32
) {
833 *mSortPtr
++ = (UINT16
) LoopVar2
;
837 mFreq
[LoopVar3
] = (UINT16
) (mFreq
[LoopVar1
] + mFreq
[LoopVar2
]);
838 mHeap
[1] = (INT16
) LoopVar3
;
840 mLeft
[LoopVar3
] = (UINT16
) LoopVar1
;
841 mRight
[LoopVar3
] = (UINT16
) LoopVar2
;
842 } while (mHeapSize
> 1);
846 MakeCode (NParm
, LenParm
, CodeParm
);
855 Outputs rightmost LoopVar8 bits of x
857 @param[in] LoopVar8 The rightmost LoopVar8 bits of the data is used.
858 @param[in] x The data.
868 if (LoopVar8
< mBitCount
) {
869 mSubBitBuf
|= x
<< (mBitCount
-= LoopVar8
);
872 Temp
= (UINT8
)(mSubBitBuf
| (x
>> (LoopVar8
-= mBitCount
)));
873 if (mDst
< mDstUpperLimit
) {
878 if (LoopVar8
< UINT8_BIT
) {
879 mSubBitBuf
= x
<< (mBitCount
= UINT8_BIT
- LoopVar8
);
882 Temp
= (UINT8
)(x
>> (LoopVar8
- UINT8_BIT
));
883 if (mDst
< mDstUpperLimit
) {
888 mSubBitBuf
= x
<< (mBitCount
= 2 * UINT8_BIT
- LoopVar8
);
894 Encode a signed 32 bit number.
896 @param[in] LoopVar5 The number to encode.
903 PutBits (mCLen
[LoopVar5
], mCCode
[LoopVar5
]);
907 Encode a unsigned 32 bit number.
909 @param[in] LoopVar7 The number to encode.
922 while (LoopVar6
!= 0) {
927 PutBits (mPTLen
[LoopVar5
], mPTCode
[LoopVar5
]);
929 PutBits(LoopVar5
- 1, LoopVar7
& (0xFFFFU
>> (17 - LoopVar5
)));
934 Count the frequencies for the Extra Set.
950 for (LoopVar1
= 0; LoopVar1
< NT
; LoopVar1
++) {
951 mTFreq
[LoopVar1
] = 0;
955 while (LoopVar8
> 0 && mCLen
[LoopVar8
- 1] == 0) {
960 while (LoopVar1
< LoopVar8
) {
961 LoopVar3
= mCLen
[LoopVar1
++];
964 while (LoopVar1
< LoopVar8
&& mCLen
[LoopVar1
] == 0) {
970 mTFreq
[0] = (UINT16
) (mTFreq
[0] + Count
);
971 } else if (Count
<= 18) {
973 } else if (Count
== 19) {
980 ASSERT((LoopVar3
+2)<(2 * NT
- 1));
981 mTFreq
[LoopVar3
+ 2]++;
987 Outputs the code length array for the Extra Set or the Position Set.
989 @param[in] LoopVar8 The number of symbols.
990 @param[in] nbit The number of bits needed to represent 'LoopVar8'.
991 @param[in] Special The special symbol that needs to be take care of.
1005 while (LoopVar8
> 0 && mPTLen
[LoopVar8
- 1] == 0) {
1009 PutBits (nbit
, LoopVar8
);
1011 while (LoopVar1
< LoopVar8
) {
1012 LoopVar3
= mPTLen
[LoopVar1
++];
1013 if (LoopVar3
<= 6) {
1014 PutBits (3, LoopVar3
);
1016 PutBits (LoopVar3
- 3, (1U << (LoopVar3
- 3)) - 2);
1019 if (LoopVar1
== Special
) {
1020 while (LoopVar1
< 6 && mPTLen
[LoopVar1
] == 0) {
1024 PutBits (2, (LoopVar1
- 3) & 3);
1030 Outputs the code length array for Char&Length Set.
1046 while (LoopVar8
> 0 && mCLen
[LoopVar8
- 1] == 0) {
1050 PutBits (CBIT
, LoopVar8
);
1052 while (LoopVar1
< LoopVar8
) {
1053 LoopVar3
= mCLen
[LoopVar1
++];
1054 if (LoopVar3
== 0) {
1056 while (LoopVar1
< LoopVar8
&& mCLen
[LoopVar1
] == 0) {
1062 for (LoopVar3
= 0; LoopVar3
< Count
; LoopVar3
++) {
1063 PutBits (mPTLen
[0], mPTCode
[0]);
1065 } else if (Count
<= 18) {
1066 PutBits (mPTLen
[1], mPTCode
[1]);
1067 PutBits (4, Count
- 3);
1068 } else if (Count
== 19) {
1069 PutBits (mPTLen
[0], mPTCode
[0]);
1070 PutBits (mPTLen
[1], mPTCode
[1]);
1073 PutBits (mPTLen
[2], mPTCode
[2]);
1074 PutBits (CBIT
, Count
- 20);
1077 ASSERT((LoopVar3
+2)<NPT
);
1078 PutBits (mPTLen
[LoopVar3
+ 2], mPTCode
[LoopVar3
+ 2]);
1084 Huffman code the block and output it.
1105 Root
= MakeTree (NC
, mCFreq
, mCLen
, mCCode
);
1106 Size
= mCFreq
[Root
];
1110 Root
= MakeTree (NT
, mTFreq
, mPTLen
, mPTCode
);
1112 WritePTLen (NT
, TBIT
, 3);
1115 PutBits (TBIT
, Root
);
1123 PutBits (CBIT
, Root
);
1126 Root
= MakeTree (NP
, mPFreq
, mPTLen
, mPTCode
);
1128 WritePTLen (NP
, PBIT
, -1);
1131 PutBits (PBIT
, Root
);
1135 for (LoopVar1
= 0; LoopVar1
< Size
; LoopVar1
++) {
1136 if (LoopVar1
% UINT8_BIT
== 0) {
1137 Flags
= mBuf
[Pos
++];
1141 if ((Flags
& (1U << (UINT8_BIT
- 1))) != 0){
1142 EncodeC(mBuf
[Pos
++] + (1U << UINT8_BIT
));
1143 LoopVar3
= mBuf
[Pos
++] << UINT8_BIT
;
1144 LoopVar3
+= mBuf
[Pos
++];
1148 EncodeC (mBuf
[Pos
++]);
1152 SetMem (mCFreq
, NC
* sizeof (UINT16
), 0);
1153 SetMem (mPFreq
, NP
* sizeof (UINT16
), 0);
1157 Start the huffman encoding.
1165 SetMem (mCFreq
, NC
* sizeof (UINT16
), 0);
1166 SetMem (mPFreq
, NP
* sizeof (UINT16
), 0);
1168 mOutputPos
= mOutputMask
= 0;
1170 mBitCount
= UINT8_BIT
;
1175 Outputs an Original Character or a Pointer.
1177 @param[in] LoopVar5 The original character or the 'String Length' element of
1179 @param[in] LoopVar7 The 'Position' field of a Pointer.
1189 if ((mOutputMask
>>= 1) == 0) {
1190 mOutputMask
= 1U << (UINT8_BIT
- 1);
1191 if (mOutputPos
>= mBufSiz
- 3 * UINT8_BIT
) {
1196 CPos
= mOutputPos
++;
1199 mBuf
[mOutputPos
++] = (UINT8
) LoopVar5
;
1201 if (LoopVar5
>= (1U << UINT8_BIT
)) {
1202 mBuf
[CPos
] = (UINT8
)(mBuf
[CPos
]|mOutputMask
);
1203 mBuf
[mOutputPos
++] = (UINT8
)(LoopVar7
>> UINT8_BIT
);
1204 mBuf
[mOutputPos
++] = (UINT8
) LoopVar7
;
1206 while (LoopVar7
!=0) {
1215 End the huffman encoding.
1226 // Flush remaining bits
1228 PutBits (UINT8_BIT
- 1, 0);
1232 The main controlling routine for compression process.
1234 @retval EFI_SUCCESS The compression is successful.
1235 @retval EFI_OUT_0F_RESOURCES Not enough memory for compression process.
1246 Status
= AllocateMemory ();
1247 if (EFI_ERROR (Status
)) {
1256 mRemainder
= FreadCrc (&mText
[WNDSIZ
], WNDSIZ
+ MAXMATCH
);
1261 if (mMatchLen
> mRemainder
) {
1262 mMatchLen
= mRemainder
;
1265 while (mRemainder
> 0) {
1266 LastMatchLen
= mMatchLen
;
1267 LastMatchPos
= mMatchPos
;
1268 if (!GetNextMatch ()) {
1269 Status
= EFI_OUT_OF_RESOURCES
;
1271 if (mMatchLen
> mRemainder
) {
1272 mMatchLen
= mRemainder
;
1275 if (mMatchLen
> LastMatchLen
|| LastMatchLen
< THRESHOLD
) {
1277 // Not enough benefits are gained by outputting a pointer,
1278 // so just output the original character
1280 CompressOutput(mText
[mPos
- 1], 0);
1283 // Outputting a pointer is beneficial enough, do it.
1286 CompressOutput(LastMatchLen
+ (UINT8_MAX
+ 1 - THRESHOLD
),
1287 (mPos
- LastMatchPos
- 2) & (WNDSIZ
- 1));
1289 while (LastMatchLen
> 0) {
1290 if (!GetNextMatch ()) {
1291 Status
= EFI_OUT_OF_RESOURCES
;
1296 if (mMatchLen
> mRemainder
) {
1297 mMatchLen
= mRemainder
;
1308 The compression routine.
1310 @param[in] SrcBuffer The buffer containing the source data.
1311 @param[in] SrcSize The number of bytes in SrcBuffer.
1312 @param[in] DstBuffer The buffer to put the compressed image in.
1313 @param[in, out] DstSize On input the size (in bytes) of DstBuffer, on
1314 return the number of bytes placed in DstBuffer.
1316 @retval EFI_SUCCESS The compression was sucessful.
1317 @retval EFI_BUFFER_TOO_SMALL The buffer was too small. DstSize is required.
1324 IN OUT UINT64
*DstSize
1343 mSrcUpperLimit
= mSrc
+ SrcSize
;
1345 mDstUpperLimit
= mDst
+*DstSize
;
1352 mOrigSize
= mCompSize
= 0;
1359 if (EFI_ERROR (Status
)) {
1360 return EFI_OUT_OF_RESOURCES
;
1363 // Null terminate the compressed data
1365 if (mDst
< mDstUpperLimit
) {
1369 // Fill in compressed size and original size
1372 PutDword (mCompSize
+ 1);
1373 PutDword (mOrigSize
);
1378 if (mCompSize
+ 1 + 8 > *DstSize
) {
1379 *DstSize
= mCompSize
+ 1 + 8;
1380 return EFI_BUFFER_TOO_SMALL
;
1382 *DstSize
= mCompSize
+ 1 + 8;