1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * The Contents of this file are made available subject to the terms of
5 * either of the following licenses
7 * - GNU Lesser General Public License Version 2.1
8 * - Sun Industry Standards Source License Version 1.1
10 * Sun Microsystems Inc., October, 2000
12 * GNU Lesser General Public License Version 2.1
13 * =============================================
14 * Copyright 2000 by Sun Microsystems, Inc.
15 * 901 San Antonio Road, Palo Alto, CA 94303, USA
17 * This library is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Lesser General Public
19 * License version 2.1, as published by the Free Software Foundation.
21 * This library is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * Lesser General Public License for more details.
26 * You should have received a copy of the GNU Lesser General Public
27 * License along with this library; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
32 * Sun Industry Standards Source License Version 1.1
33 * =================================================
34 * The contents of this file are subject to the Sun Industry Standards
35 * Source License Version 1.1 (the "License"); You may not use this file
36 * except in compliance with the License. You may obtain a copy of the
37 * License at http://www.openoffice.org/license.html.
39 * Software provided under this License is provided on an "AS IS" basis,
40 * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
41 * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
42 * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
43 * See the License for the specific provisions governing your rights and
44 * obligations concerning the Software.
46 * The Initial Developer of the Original Code is: IBM Corporation
48 * Copyright: 2008 by IBM Corporation
50 * All Rights Reserved.
52 * Contributor(s): _______________________________________
55 ************************************************************************/
57 #include "explode.hxx"
59 const static char Tree1String
[][32] = {
78 const static char Tree2String
[][32] = {
145 Decompression::Decompression(SvStream
* pInStream
, SvStream
* pOutStream
)
146 : m_pInStream(pInStream
)
147 , m_pOutStream(pOutStream
)
150 , m_pBuffer(m_Buffer
)
152 , m_nOutputBufferPos(0)
154 if (!m_pInStream
|| !m_pOutStream
)
163 * @descr read specified bits from input stream
164 * @argument iCount - number of bits to be read, less than 31
165 * @argument nBits - bits read
166 * @return 0 - read OK, otherwise error
168 sal_uInt32
Decompression::ReadBits(sal_uInt16 iCount
, sal_uInt32
& nBits
)
170 if ( (iCount
== 0) || (iCount
> 31 ) )
175 sal_uInt32 val
= 0; /* bit accumulator */
177 /* load at least need bits into val */
178 val
= m_nCurrent4Byte
;
179 while (m_nBitsLeft
< iCount
)
181 if (m_nBytesLeft
== 0)
183 m_nBytesLeft
= m_pInStream
->Read(m_Buffer
, CHUNK
);
184 m_pBuffer
= m_Buffer
;
185 if (m_nBytesLeft
== 0) return 1;
187 val
|= (sal_uInt32
)(*m_pBuffer
++) << m_nBitsLeft
; /* load eight bits */
192 /* drop need bits and update buffer, always zero to seven bits left */
193 m_nCurrent4Byte
= val
>> iCount
;
194 m_nBitsLeft
-= iCount
;
196 /* return need bits, zeroing the bits above that */
197 nBits
= val
& ((1 << iCount
) - 1);
202 * @descr decompress input and write output
203 * @return 0 - read OK, otherwise error
205 sal_Int32
Decompression::explode()
207 /* The first 2 bytes are parameters */
209 if (0 != ReadBits(8, P1
))/* 0 or 1 */
212 /* I think this means 0=binary and 1=ascii file, but in RESOURCEs I saw always 0 */
213 if (P1
>= 1) // changed per 's review comments
217 if (0 != ReadBits(8, P2
))
220 /* must be 4,5 or 6 and it is a parameter for the decompression algorithm */
221 if (P2
< 4 || P2
> 6)
224 m_nOutputBufferPos
= 0;
225 /* Now, a bit stream follows, which is decoded as described below: */
226 /* The algorithm terminates as soon as it runs out of bits. */
229 // read 1 bit (take bits from the lowest value (LSB) to the MSB i.e. bit 0, bit 1 etc ...)
231 if (0 != ReadBits(1, iBit
))
233 if ( 0 == (iBit
& 0x01) )
235 //if the bit is 0 read 8 bits and write it to the output as it is.
237 if (0 != ReadBits(8, symbol
))
239 m_Output
[m_nOutputBufferPos
++] = (sal_uInt8
)symbol
;
240 if (m_nOutputBufferPos
== MAXWIN
)
242 m_pOutStream
->Write(m_Output
, m_nOutputBufferPos
);
243 m_nOutputBufferPos
= 0;
247 // if the bit is 1 we have here a length/distance pair:
248 // -decode a number with Hufmman Tree #1; variable bit length, result is 0x00 .. 0x0F -> L1
249 sal_uInt32 L1
= Decode(m_Tree1
);
260 // read more (L1-7) bits -> L2
261 // LENGTH = L2 + M[L1-7] + 2
263 if (0 != ReadBits((sal_uInt16
)(L1
- 7), L2
))
265 Length
= L2
+ 2 + m_iArrayOfM
[L1
-7];
269 // end of compressed data
273 // - decode another number with Hufmann Tree #2 giving result 0x00..0x3F -> D1
274 sal_uInt32 D1
= Decode(m_Tree2
);
282 if (0 != ReadBits(2, D2
))
288 // D1 = D1 << P2 // the parameter 2
289 // read P2 bits -> D2
291 if (0 != ReadBits((sal_uInt16
)P2
, D2
))
294 // DISTANCE = (D1 | D2) + 1
295 sal_uInt32 distance
= (D1
| D2
) + 1;
297 // - now copy LENGTH bytes from (output_ptr-DISTANCE) to output_ptr
298 // write current buffer to output
299 m_pOutStream
->Write(m_Output
, m_nOutputBufferPos
);
300 m_nOutputBufferPos
= 0;
302 // remember current position
303 sal_uInt32 nOutputPos
= m_pOutStream
->Tell();
304 if (distance
> nOutputPos
)
305 return -3; // format error
307 m_pOutStream
->Flush();
308 // point back to copy position and read bytes
309 m_pOutStream
->SeekRel(-(long)distance
);
310 sal_uInt8 sTemp
[MAXWIN
];
311 sal_uInt32 nRead
= distance
> Length
? Length
:distance
;
312 m_pOutStream
->Read(sTemp
, nRead
);
315 // fill the buffer with read content repeatly until full
316 for (sal_uInt32 i
=nRead
; i
<Length
; i
++)
318 sTemp
[i
] = sTemp
[i
-nRead
];
322 // restore output stream position
323 m_pOutStream
->Seek(nOutputPos
);
325 // write current buffer to output
326 m_pOutStream
->Write(sTemp
, Length
);
331 * @descr bits to string
334 void Decompression::ToString(sal_uInt32 nBits
, sal_Char
*pChar
, sal_uInt32 nLen
)
337 for (sal_uInt32 i
=nLen
; i
> 0; i
--)
339 nBit
= (nBits
>> (i
-1) ) & 0x01;
340 pChar
[nLen
- i
] = nBit
? '1':'0';
347 * @descr decode tree 1 for length
348 * @return the decoded value
350 sal_uInt32
Decompression::Decode(HuffmanTreeNode
* pRoot
)
353 sal_uInt32 nRead
, nReadAlready
;
355 if( 0 != ReadBits(1, nReadAlready
))
356 return 0; // something wrong
358 for (sal_uInt16 i
=2; i
<= 8; i
++)
360 if ( 0 != ReadBits(1, nRead
))
361 return 0; // something wrong
363 nReadAlready
= (nReadAlready
<< 1) | (nRead
& 0x01);
366 ToString(nReadAlready
, sCode
, i
);
367 nRet
= pRoot
->QueryValue(sCode
);
368 if (nRet
!= 0xffffffff)
376 * @descr construct tree 1 for length
379 void Decompression::ConstructTree1()
381 // The first huffman tree (the Section called Decompression algorithm HUFFMAN) contains the length values. It is described by the following table:
382 // value (hex) code (binary)
399 m_Tree1
= new HuffmanTreeNode();
400 for (sal_uInt32 i
=0; i
< 16; i
++)
402 m_Tree1
->InsertNode(i
, Tree1String
[i
]);
405 m_Tree1->InsertNode(0, "101");
406 m_Tree1->InsertNode(1, "11");
407 m_Tree1->InsertNode(2, "100");
408 m_Tree1->InsertNode(3, "011");
409 m_Tree1->InsertNode(4, "0101");
410 m_Tree1->InsertNode(5, "0100");
411 m_Tree1->InsertNode(6, "0011");
412 m_Tree1->InsertNode(7, "00101");
413 m_Tree1->InsertNode(8, "00100");
414 m_Tree1->InsertNode(9, "00011");
415 m_Tree1->InsertNode(10, "00010");
416 m_Tree1->InsertNode(11, "000011");
417 m_Tree1->InsertNode(12, "000010");
418 m_Tree1->InsertNode(13, "000001");
419 m_Tree1->InsertNode(14, "0000001");
420 m_Tree1->InsertNode(15, "0000000");
424 * @descr construct tree 2 for distance
427 void Decompression::ConstructTree2()
430 m_Tree2
= new HuffmanTreeNode();
431 for (sal_uInt32 i
=0; i
< 64; i
++)
433 m_Tree2
->InsertNode(i
, Tree2String
[i
]);
435 //where bits should be read from the left to the right.
441 void Decompression::fillArray()
444 for (int i
=1; i
< 16; i
++)
447 m_iArrayOfM
[i
] = m_iArrayOfM
[i
- 1]+ (sal_uInt32
)pow(dR
, i
-1);//2
451 HuffmanTreeNode::HuffmanTreeNode(sal_uInt32 nValue
, HuffmanTreeNode
* pLeft
, HuffmanTreeNode
* pRight
)
457 HuffmanTreeNode::~HuffmanTreeNode()
471 HuffmanTreeNode
* HuffmanTreeNode::InsertNode(sal_uInt32 nValue
, const sal_Char
* pInCode
)
473 HuffmanTreeNode
*pNew
= new HuffmanTreeNode(nValue
);
475 strcpy(pCode
, pInCode
);
478 sal_Char cLast
= pCode
[strlen(pCode
) - 1];
479 pCode
[strlen(pCode
) - 1] = '\0';
480 HuffmanTreeNode
* pParent
= QueryNode(pCode
);
483 pParent
= InsertNode(0xffffffff, pCode
);
486 pParent
->left
= pNew
;
487 else // (cChar == '1')
488 pParent
->right
= pNew
;
492 HuffmanTreeNode
* HuffmanTreeNode::QueryNode(const sal_Char
* pCode
)
494 sal_uInt32 nLen
= strlen(pCode
);
496 HuffmanTreeNode
* pNode
= this; // this is the root
497 for(sal_uInt32 i
=0; i
<nLen
&& pNode
; i
++)
499 sal_Char cChar
= pCode
[i
];
504 else // (cChar == '1')
506 pNode
= pNode
->right
;
512 sal_uInt32
HuffmanTreeNode::QueryValue(const sal_Char
* pCode
)
514 HuffmanTreeNode
* pNode
=QueryNode(pCode
);
521 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */