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"
58 #include <tools/stream.hxx>
64 const static char Tree1String
[][32] = {
83 const static char Tree2String
[][32] = {
150 Decompression::Decompression(SvStream
* pInStream
, SvStream
* pOutStream
)
151 : m_pInStream(pInStream
)
152 , m_pOutStream(pOutStream
)
155 , m_pBuffer(m_Buffer
)
157 , m_nOutputBufferPos(0)
159 if (!m_pInStream
|| !m_pOutStream
)
168 * @descr read specified bits from input stream
169 * @argument iCount - number of bits to be read, less than 31
170 * @argument nBits - bits read
171 * @return 0 - read OK, otherwise error
173 sal_uInt32
Decompression::ReadBits(sal_uInt16 iCount
, sal_uInt32
& nBits
)
175 if ( (iCount
== 0) || (iCount
> 31 ) )
180 sal_uInt32 val
= 0; /* bit accumulator */
182 /* load at least need bits into val */
183 val
= m_nCurrent4Byte
;
184 while (m_nBitsLeft
< iCount
)
186 if (m_nBytesLeft
== 0)
188 m_nBytesLeft
= m_pInStream
->ReadBytes(m_Buffer
, CHUNK
);
189 m_pBuffer
= m_Buffer
;
190 if (m_nBytesLeft
== 0) return 1;
192 val
|= static_cast<sal_uInt32
>(*m_pBuffer
++) << m_nBitsLeft
; /* load eight bits */
197 /* drop need bits and update buffer, always zero to seven bits left */
198 m_nCurrent4Byte
= val
>> iCount
;
199 m_nBitsLeft
-= iCount
;
201 /* return need bits, zeroing the bits above that */
202 nBits
= val
& ((1 << iCount
) - 1);
207 * @descr decompress input and write output
208 * @return 0 - read OK, otherwise error
210 sal_Int32
Decompression::explode()
212 /* The first 2 bytes are parameters */
214 if (0 != ReadBits(8, P1
))/* 0 or 1 */
217 /* I think this means 0=binary and 1=ascii file, but in RESOURCEs I saw always 0 */
218 if (P1
>= 1) // changed per 's review comments
222 if (0 != ReadBits(8, P2
))
225 /* must be 4,5 or 6 and it is a parameter for the decompression algorithm */
226 if (P2
< 4 || P2
> 6)
229 m_nOutputBufferPos
= 0;
230 /* Now, a bit stream follows, which is decoded as described below: */
231 /* The algorithm terminates as soon as it runs out of bits. */
234 // read 1 bit (take bits from the lowest value (LSB) to the MSB i.e. bit 0, bit 1 etc ...)
236 if (0 != ReadBits(1, iBit
))
238 if ( 0 == (iBit
& 0x01) )
240 //if the bit is 0 read 8 bits and write it to the output as it is.
242 if (0 != ReadBits(8, symbol
))
244 m_Output
[m_nOutputBufferPos
++] = static_cast<sal_uInt8
>(symbol
);
245 if (m_nOutputBufferPos
== MAXWIN
)
247 m_pOutStream
->WriteBytes(m_Output
, m_nOutputBufferPos
);
248 m_nOutputBufferPos
= 0;
252 // if the bit is 1 we have here a length/distance pair:
253 // -decode a number with Hufmman Tree #1; variable bit length, result is 0x00 .. 0x0F -> L1
254 sal_uInt32 L1
= Decode(m_Tree1
.get());
265 // read more (L1-7) bits -> L2
266 // LENGTH = L2 + M[L1-7] + 2
268 if (0 != ReadBits(static_cast<sal_uInt16
>(L1
- 7), L2
))
270 Length
= L2
+ 2 + m_iArrayOfM
[L1
-7];
274 // end of compressed data
278 // - decode another number with Hufmann Tree #2 giving result 0x00..0x3F -> D1
279 sal_uInt32 D1
= Decode(m_Tree2
.get());
287 if (0 != ReadBits(2, D2
))
293 // D1 = D1 << P2 // the parameter 2
294 // read P2 bits -> D2
296 if (0 != ReadBits(static_cast<sal_uInt16
>(P2
), D2
))
299 // DISTANCE = (D1 | D2) + 1
300 sal_uInt32 distance
= (D1
| D2
) + 1;
302 // - now copy LENGTH bytes from (output_ptr-DISTANCE) to output_ptr
303 // write current buffer to output
304 m_pOutStream
->WriteBytes(m_Output
, m_nOutputBufferPos
);
305 m_nOutputBufferPos
= 0;
307 // remember current position
308 sal_uInt32 nOutputPos
= m_pOutStream
->Tell();
309 if (distance
> nOutputPos
)
310 return -3; // format error
312 m_pOutStream
->Flush();
313 // point back to copy position and read bytes
314 m_pOutStream
->SeekRel(-static_cast<long>(distance
));
315 sal_uInt8 sTemp
[MAXWIN
];
316 sal_uInt32 nRead
= std::min(distance
, Length
);
317 m_pOutStream
->ReadBytes(sTemp
, nRead
);
320 // fill the buffer with read content repeatedly until full
321 for (sal_uInt32 i
=nRead
; i
<Length
; i
++)
323 sTemp
[i
] = sTemp
[i
-nRead
];
327 // restore output stream position
328 m_pOutStream
->Seek(nOutputPos
);
330 // write current buffer to output
331 m_pOutStream
->WriteBytes(sTemp
, Length
);
336 * @descr bits to string
339 void Decompression::ToString(sal_uInt32 nBits
, sal_Char
*pChar
, sal_uInt32 nLen
)
342 for (sal_uInt32 i
=nLen
; i
> 0; i
--)
344 nBit
= (nBits
>> (i
-1) ) & 0x01;
345 pChar
[nLen
- i
] = nBit
? '1':'0';
351 * @descr decode tree 1 for length
352 * @return the decoded value
354 sal_uInt32
Decompression::Decode(HuffmanTreeNode
* pRoot
)
357 sal_uInt32 nRead
, nReadAlready
;
359 if( 0 != ReadBits(1, nReadAlready
))
360 return 0; // something wrong
362 for (sal_uInt16 i
=2; i
<= 8; i
++)
364 if ( 0 != ReadBits(1, nRead
))
365 return 0; // something wrong
367 nReadAlready
= (nReadAlready
<< 1) | (nRead
& 0x01);
370 ToString(nReadAlready
, sCode
, i
);
371 nRet
= pRoot
->QueryValue(sCode
);
372 if (nRet
!= 0xffffffff)
380 * @descr construct tree 1 for length
383 void Decompression::ConstructTree1()
385 // The first huffman tree (the Section called Decompression algorithm HUFFMAN) contains the length values. It is described by the following table:
386 // value (hex) code (binary)
403 m_Tree1
.reset( new HuffmanTreeNode());
404 for (sal_uInt32 i
=0; i
< 16; i
++)
406 m_Tree1
->InsertNode(i
, Tree1String
[i
]);
409 m_Tree1->InsertNode(0, "101");
410 m_Tree1->InsertNode(1, "11");
411 m_Tree1->InsertNode(2, "100");
412 m_Tree1->InsertNode(3, "011");
413 m_Tree1->InsertNode(4, "0101");
414 m_Tree1->InsertNode(5, "0100");
415 m_Tree1->InsertNode(6, "0011");
416 m_Tree1->InsertNode(7, "00101");
417 m_Tree1->InsertNode(8, "00100");
418 m_Tree1->InsertNode(9, "00011");
419 m_Tree1->InsertNode(10, "00010");
420 m_Tree1->InsertNode(11, "000011");
421 m_Tree1->InsertNode(12, "000010");
422 m_Tree1->InsertNode(13, "000001");
423 m_Tree1->InsertNode(14, "0000001");
424 m_Tree1->InsertNode(15, "0000000");
428 * @descr construct tree 2 for distance
431 void Decompression::ConstructTree2()
434 m_Tree2
.reset(new HuffmanTreeNode());
435 for (sal_uInt32 i
=0; i
< 64; i
++)
437 m_Tree2
->InsertNode(i
, Tree2String
[i
]);
439 //where bits should be read from the left to the right.
445 void Decompression::fillArray()
448 for (int i
=1; i
< 16; i
++)
450 m_iArrayOfM
[i
] = m_iArrayOfM
[i
- 1]+ static_cast<sal_uInt32
>(pow(2.0, i
-1));//2
454 HuffmanTreeNode::HuffmanTreeNode(sal_uInt32 nValue
):value(nValue
)
457 HuffmanTreeNode::~HuffmanTreeNode()
461 HuffmanTreeNode
* HuffmanTreeNode::InsertNode(sal_uInt32 nValue
, const sal_Char
* pInCode
)
463 HuffmanTreeNode
*pNew
= new HuffmanTreeNode(nValue
);
464 std::string
aCode(pInCode
);
467 const sal_Char cLast
= aCode
.back();
469 HuffmanTreeNode
* pParent
= QueryNode(aCode
.c_str());
472 pParent
= InsertNode(0xffffffff, aCode
.c_str());
475 pParent
->left
.reset(pNew
);
476 else // (cChar == '1')
477 pParent
->right
.reset(pNew
);
482 HuffmanTreeNode
* HuffmanTreeNode::QueryNode(const sal_Char
* pCode
)
484 sal_uInt32 nLen
= strlen(pCode
);
486 HuffmanTreeNode
* pNode
= this; // this is the root
487 for(sal_uInt32 i
=0; i
<nLen
&& pNode
; i
++)
489 sal_Char cChar
= pCode
[i
];
492 pNode
= pNode
->left
.get();
494 else // (cChar == '1')
496 pNode
= pNode
->right
.get();
502 sal_uInt32
HuffmanTreeNode::QueryValue(const sal_Char
* pCode
)
504 HuffmanTreeNode
* pNode
=QueryNode(pCode
);
511 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */