1 /*************************************************************************
3 * The Contents of this file are made available subject to the terms of
4 * either of the following licenses
6 * - GNU Lesser General Public License Version 2.1
7 * - Sun Industry Standards Source License Version 1.1
9 * Sun Microsystems Inc., October, 2000
11 * GNU Lesser General Public License Version 2.1
12 * =============================================
13 * Copyright 2000 by Sun Microsystems, Inc.
14 * 901 San Antonio Road, Palo Alto, CA 94303, USA
16 * This library is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU Lesser General Public
18 * License version 2.1, as published by the Free Software Foundation.
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Lesser General Public License for more details.
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
31 * Sun Industry Standards Source License Version 1.1
32 * =================================================
33 * The contents of this file are subject to the Sun Industry Standards
34 * Source License Version 1.1 (the "License"); You may not use this file
35 * except in compliance with the License. You may obtain a copy of the
36 * License at http://www.openoffice.org/license.html.
38 * Software provided under this License is provided on an "AS IS" basis,
39 * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
40 * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
41 * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
42 * See the License for the specific provisions governing your rights and
43 * obligations concerning the Software.
45 * The Initial Developer of the Original Code is: IBM Corporation
47 * Copyright: 2008 by IBM Corporation
49 * All Rights Reserved.
51 * Contributor(s): _______________________________________
54 ************************************************************************/
56 #include "explode.hxx"
58 const static char Tree1String
[][32] = {
77 const static char Tree2String
[][32] = {
144 Decompression::Decompression(SvStream
* pInStream
, SvStream
* pOutStream
):
145 m_pInStream(pInStream
), m_pOutStream(pOutStream
), m_pBuffer(m_Buffer
), m_nOutputBufferPos(0),
146 m_nBitsLeft(0), m_nBytesLeft(0), m_nCurrent4Byte(0)
148 if (!m_pInStream
|| !m_pOutStream
)
157 * @descr read specified bits from input stream
158 * @argument iCount - number of bits to be read, less than 31
159 * @argument nBits - bits read
160 * @return 0 - read OK, otherwise error
162 sal_uInt32
Decompression::ReadBits(sal_uInt16 iCount
, sal_uInt32
& nBits
)
164 if ( (iCount
== 0) || (iCount
> 32 ) )
169 sal_uInt32 val
= 0; /* bit accumulator */
171 /* load at least need bits into val */
172 val
= m_nCurrent4Byte
;
173 while (m_nBitsLeft
< iCount
)
175 if (m_nBytesLeft
== 0)
177 m_nBytesLeft
= m_pInStream
->Read(m_Buffer
, CHUNK
);
178 m_pBuffer
= m_Buffer
;
179 if (m_nBytesLeft
== 0) return 1;
181 val
|= (sal_uInt32
)(*m_pBuffer
++) << m_nBitsLeft
; /* load eight bits */
186 /* drop need bits and update buffer, always zero to seven bits left */
187 m_nCurrent4Byte
= val
>> iCount
;
188 m_nBitsLeft
-= iCount
;
190 /* return need bits, zeroing the bits above that */
191 nBits
= val
& ((1 << iCount
) - 1);
196 * @descr decompress input and write output
197 * @return 0 - read OK, otherwise error
199 sal_Int32
Decompression::explode()
201 /* The first 2 bytes are parameters */
203 if (0 != ReadBits(8, P1
))/* 0 or 1 */
206 /* I think this means 0=binary and 1=ascii file, but in RESOURCEs I saw always 0 */
207 if (P1
>= 1) // changed per 's review comments
211 if (0 != ReadBits(8, P2
))
214 /* must be 4,5 or 6 and it is a parameter for the decompression algorithm */
215 if (P2
< 4 || P2
> 6)
218 m_nOutputBufferPos
= 0;
219 /* Now, a bit stream follows, which is decoded as described below: */
220 /* The algorithm terminates as soon as it runs out of bits. */
223 // read 1 bit (take bits from the lowest value (LSB) to the MSB i.e. bit 0, bit 1 etc ...)
225 if (0 != ReadBits(1, iBit
))
227 if ( 0 == (iBit
& 0x01) )
229 //if the bit is 0 read 8 bits and write it to the output as it is.
231 if (0 != ReadBits(8, symbol
))
233 m_Output
[m_nOutputBufferPos
++] = (sal_uInt8
)symbol
;
234 if (m_nOutputBufferPos
== MAXWIN
)
236 m_pOutStream
->Write(m_Output
, m_nOutputBufferPos
);
237 m_nOutputBufferPos
= 0;
241 // if the bit is 1 we have here a length/distance pair:
242 // -decode a number with Hufmman Tree #1; variable bit length, result is 0x00 .. 0x0F -> L1
243 sal_uInt32 L1
= Decode(m_Tree1
);
254 // read more (L1-7) bits -> L2
255 // LENGTH = L2 + M[L1-7] + 2
257 if (0 != ReadBits((sal_uInt16
)(L1
- 7), L2
))
259 Length
= L2
+ 2 + m_iArrayOfM
[L1
-7];
263 // end of compressed data
267 // - decode another number with Hufmann Tree #2 giving result 0x00..0x3F -> D1
268 sal_uInt32 D1
= Decode(m_Tree2
);
276 if (0 != ReadBits(2, D2
))
282 // D1 = D1 << P2 // the parameter 2
283 // read P2 bits -> D2
285 if (0 != ReadBits((sal_uInt16
)P2
, D2
))
288 // DISTANCE = (D1 | D2) + 1
289 sal_uInt32 distance
= (D1
| D2
) + 1;
291 // - now copy LENGTH bytes from (output_ptr-DISTANCE) to output_ptr
292 // write current buffer to output
293 m_pOutStream
->Write(m_Output
, m_nOutputBufferPos
);
294 m_nOutputBufferPos
= 0;
296 // remember current position
297 sal_uInt32 nOutputPos
= m_pOutStream
->Tell();
298 if (distance
> nOutputPos
)
299 return -3; // format error
301 m_pOutStream
->Flush();
302 // point back to copy position and read bytes
303 m_pOutStream
->SeekRel((long)-distance
);
304 sal_uInt8 sTemp
[MAXWIN
];
305 sal_uInt32 nRead
= distance
> Length
? Length
:distance
;
306 m_pOutStream
->Read(sTemp
, nRead
);
309 // fill the buffer with read content repeatly until full
310 for (sal_uInt32 i
=nRead
; i
<Length
; i
++)
312 sTemp
[i
] = sTemp
[i
-nRead
];
316 // restore output stream position
317 m_pOutStream
->Seek(nOutputPos
);
319 // write current buffer to output
320 m_pOutStream
->Write(sTemp
, Length
);
325 * @descr bits to string
328 void Decompression::ToString(sal_uInt32 nBits
, sal_Char
*pChar
, sal_uInt32 nLen
)
331 for (sal_uInt32 i
=nLen
; i
> 0; i
--)
333 nBit
= (nBits
>> (i
-1) ) & 0x01;
334 pChar
[nLen
- i
] = nBit
? '1':'0';
341 * @descr decode tree 1 for length
342 * @return the decoded value
344 sal_uInt32
Decompression::Decode(HuffmanTreeNode
* pRoot
)
347 sal_uInt32 nRead
, nReadAlready
;
349 if( 0 != ReadBits(1, nReadAlready
))
350 return 0; // something wrong
352 for (sal_uInt16 i
=2; i
<= 8; i
++)
354 if ( 0 != ReadBits(1, nRead
))
355 return 0; // something wrong
357 nReadAlready
= (nReadAlready
<< 1) | (nRead
& 0x01);
360 ToString(nReadAlready
, sCode
, i
);
361 nRet
= pRoot
->QueryValue(sCode
);
362 if (nRet
!= 0xffffffff)
370 * @descr construct tree 1 for length
373 void Decompression::ConstructTree1()
375 // The first huffman tree (the Section called Decompression algorithm HUFFMAN) contains the length values. It is described by the following table:
376 // value (hex) code (binary)
393 m_Tree1
= new HuffmanTreeNode();
394 for (sal_uInt32 i
=0; i
< 16; i
++)
396 m_Tree1
->InsertNode(i
, Tree1String
[i
]);
399 m_Tree1->InsertNode(0, "101");
400 m_Tree1->InsertNode(1, "11");
401 m_Tree1->InsertNode(2, "100");
402 m_Tree1->InsertNode(3, "011");
403 m_Tree1->InsertNode(4, "0101");
404 m_Tree1->InsertNode(5, "0100");
405 m_Tree1->InsertNode(6, "0011");
406 m_Tree1->InsertNode(7, "00101");
407 m_Tree1->InsertNode(8, "00100");
408 m_Tree1->InsertNode(9, "00011");
409 m_Tree1->InsertNode(10, "00010");
410 m_Tree1->InsertNode(11, "000011");
411 m_Tree1->InsertNode(12, "000010");
412 m_Tree1->InsertNode(13, "000001");
413 m_Tree1->InsertNode(14, "0000001");
414 m_Tree1->InsertNode(15, "0000000");
418 * @descr construct tree 2 for distance
421 void Decompression::ConstructTree2()
424 m_Tree2
= new HuffmanTreeNode();
425 for (sal_uInt32 i
=0; i
< 64; i
++)
427 m_Tree2
->InsertNode(i
, Tree2String
[i
]);
430 m_Tree2
= new HuffmanTreeNode();
432 //The second huffman code tree contains the distance values. It can be built from the following table:
433 //value (hex) code (binary)
450 m_Tree2
->InsertNode(0x0, "11");
451 m_Tree2
->InsertNode(0x1, "1011");
452 m_Tree2
->InsertNode(0x2, "1010");
453 m_Tree2
->InsertNode(0x3, "10011");
454 m_Tree2
->InsertNode(0x4, "10010");
455 m_Tree2
->InsertNode(0x5, "10001");
456 m_Tree2
->InsertNode(0x6, "10000");
457 m_Tree2
->InsertNode(0x7, "011111");
458 m_Tree2
->InsertNode(0x8, "011110");
459 m_Tree2
->InsertNode(0x9, "011101");
460 m_Tree2
->InsertNode(0x0a, "011100");
461 m_Tree2
->InsertNode(0x0b, "011011");
462 m_Tree2
->InsertNode(0x0c, "011010");
463 m_Tree2
->InsertNode(0x0d, "011001");
464 m_Tree2
->InsertNode(0x0e, "011000");
465 m_Tree2
->InsertNode(0x0f, "010111");
482 m_Tree2
->InsertNode(0x10, "010110");
483 m_Tree2
->InsertNode(0x11, "010101");
484 m_Tree2
->InsertNode(0x12, "010100");
485 m_Tree2
->InsertNode(0x13, "010011");
486 m_Tree2
->InsertNode(0x14, "010010");
487 m_Tree2
->InsertNode(0x15, "010001");
488 m_Tree2
->InsertNode(0x16, "0100001");
489 m_Tree2
->InsertNode(0x17, "0100000");
490 m_Tree2
->InsertNode(0x18, "0011111");
491 m_Tree2
->InsertNode(0x19, "0011110");
492 m_Tree2
->InsertNode(0x1a, "0011101");
493 m_Tree2
->InsertNode(0x1b, "0011100");
494 m_Tree2
->InsertNode(0x1c, "0011011");
495 m_Tree2
->InsertNode(0x1d, "0011010");
496 m_Tree2
->InsertNode(0x1e, "0011001");
497 m_Tree2
->InsertNode(0x1f, "0011000");
514 m_Tree2
->InsertNode(0x20, "0010111");
515 m_Tree2
->InsertNode(0x21, "0010110");
516 m_Tree2
->InsertNode(0x22, "0010101");
517 m_Tree2
->InsertNode(0x23, "0010100");
518 m_Tree2
->InsertNode(0x24, "0010011");
519 m_Tree2
->InsertNode(0x25, "0010010");
520 m_Tree2
->InsertNode(0x26, "0010001");
521 m_Tree2
->InsertNode(0x27, "0010000");
522 m_Tree2
->InsertNode(0x28, "0001111");
523 m_Tree2
->InsertNode(0x29, "0001110");
524 m_Tree2
->InsertNode(0x2a, "0001101");
525 m_Tree2
->InsertNode(0x2b, "0001100");
526 m_Tree2
->InsertNode(0x2c, "0001011");
527 m_Tree2
->InsertNode(0x2d, "0001010");
528 m_Tree2
->InsertNode(0x2e, "0001001");
529 m_Tree2
->InsertNode(0x2f, "0001000");
546 m_Tree2
->InsertNode(0x30, "00001111");
547 m_Tree2
->InsertNode(0x31, "00001110");
548 m_Tree2
->InsertNode(0x32, "00001101");
549 m_Tree2
->InsertNode(0x33, "00001100");
550 m_Tree2
->InsertNode(0x34, "00001011");
551 m_Tree2
->InsertNode(0x35, "00001010");
552 m_Tree2
->InsertNode(0x36, "00001001");
553 m_Tree2
->InsertNode(0x37, "00001000");
554 m_Tree2
->InsertNode(0x38, "00000111");
555 m_Tree2
->InsertNode(0x39, "00000110");
556 m_Tree2
->InsertNode(0x3a, "00000101");
557 m_Tree2
->InsertNode(0x3b, "00000100");
558 m_Tree2
->InsertNode(0x3c, "00000011");
559 m_Tree2
->InsertNode(0x3d, "00000010");
560 m_Tree2
->InsertNode(0x3e, "00000001");
561 m_Tree2
->InsertNode(0x3f, "00000000");
563 //where bits should be read from the left to the right.
569 void Decompression::fillArray()
572 for (int i
=1; i
< 16; i
++)
575 m_iArrayOfM
[i
] = m_iArrayOfM
[i
- 1]+ (sal_uInt32
)pow(dR
, i
-1);//2
579 HuffmanTreeNode::HuffmanTreeNode(sal_uInt32 nValue
, HuffmanTreeNode
* pLeft
, HuffmanTreeNode
* pRight
)
585 HuffmanTreeNode::~HuffmanTreeNode()
599 HuffmanTreeNode
* HuffmanTreeNode::InsertNode(sal_uInt32 nValue
, const sal_Char
* pInCode
)
601 HuffmanTreeNode
*pNew
= new HuffmanTreeNode(nValue
);
603 strcpy(pCode
, pInCode
);
606 sal_Char cLast
= pCode
[strlen(pCode
) - 1];
607 pCode
[strlen(pCode
) - 1] = '\0';
608 HuffmanTreeNode
* pParent
= QueryNode(pCode
);
611 pParent
= InsertNode(0xffffffff, pCode
);
614 pParent
->left
= pNew
;
615 else // (cChar == '1')
616 pParent
->right
= pNew
;
620 HuffmanTreeNode
* HuffmanTreeNode::QueryNode(const sal_Char
* pCode
)
622 sal_uInt32 nLen
= strlen(pCode
);
624 HuffmanTreeNode
* pNode
= this; // this is the root
625 for(sal_uInt32 i
=0; i
<nLen
&& pNode
; i
++)
627 sal_Char cChar
= pCode
[i
];
632 else // (cChar == '1')
634 pNode
= pNode
->right
;
640 sal_uInt32
HuffmanTreeNode::QueryValue(const sal_Char
* pCode
)
642 HuffmanTreeNode
* pNode
=QueryNode(pCode
);