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 char Tree1String
[][32] = {
83 const 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 /* load at least need bits into val */
181 sal_uInt32 val
= m_nCurrent4Byte
; /* bit accumulator */
182 while (m_nBitsLeft
< iCount
)
184 if (m_nBytesLeft
== 0)
186 m_nBytesLeft
= m_pInStream
->ReadBytes(m_Buffer
, CHUNK
);
187 m_pBuffer
= m_Buffer
;
188 if (m_nBytesLeft
== 0) return 1;
190 val
|= static_cast<sal_uInt32
>(*m_pBuffer
++) << m_nBitsLeft
; /* load eight bits */
195 /* drop need bits and update buffer, always zero to seven bits left */
196 m_nCurrent4Byte
= val
>> iCount
;
197 m_nBitsLeft
-= iCount
;
199 /* return need bits, zeroing the bits above that */
200 nBits
= val
& ((1U << iCount
) - 1);
205 * @descr decompress input and write output
206 * @return 0 - read OK, otherwise error
208 sal_Int32
Decompression::explode()
210 /* The first 2 bytes are parameters */
212 if (0 != ReadBits(8, P1
))/* 0 or 1 */
215 /* I think this means 0=binary and 1=ascii file, but in RESOURCEs I saw always 0 */
216 if (P1
>= 1) // changed per 's review comments
220 if (0 != ReadBits(8, P2
))
223 /* must be 4,5 or 6 and it is a parameter for the decompression algorithm */
224 if (P2
< 4 || P2
> 6)
227 m_nOutputBufferPos
= 0;
228 /* Now, a bit stream follows, which is decoded as described below: */
229 /* The algorithm terminates as soon as it runs out of bits. */
232 // read 1 bit (take bits from the lowest value (LSB) to the MSB i.e. bit 0, bit 1 etc ...)
234 if (0 != ReadBits(1, iBit
))
236 if ( 0 == (iBit
& 0x01) )
238 //if the bit is 0 read 8 bits and write it to the output as it is.
240 if (0 != ReadBits(8, symbol
))
242 m_Output
[m_nOutputBufferPos
++] = static_cast<sal_uInt8
>(symbol
);
243 if (m_nOutputBufferPos
== MAXWIN
)
245 m_pOutStream
->WriteBytes(m_Output
, m_nOutputBufferPos
);
246 m_nOutputBufferPos
= 0;
250 // if the bit is 1 we have here a length/distance pair:
251 // -decode a number with Hufmman Tree #1; variable bit length, result is 0x00 .. 0x0F -> L1
252 sal_uInt32 L1
= Decode(m_Tree1
.get());
263 // read more (L1-7) bits -> L2
264 // LENGTH = L2 + M[L1-7] + 2
266 if (0 != ReadBits(static_cast<sal_uInt16
>(L1
- 7), L2
))
268 Length
= L2
+ 2 + m_iArrayOfM
[L1
-7];
272 // end of compressed data
276 // - decode another number with Hufmann Tree #2 giving result 0x00..0x3F -> D1
277 sal_uInt32 D1
= Decode(m_Tree2
.get());
285 if (0 != ReadBits(2, D2
))
291 // D1 = D1 << P2 // the parameter 2
292 // read P2 bits -> D2
294 if (0 != ReadBits(static_cast<sal_uInt16
>(P2
), D2
))
297 // DISTANCE = (D1 | D2) + 1
298 sal_uInt32 distance
= (D1
| D2
) + 1;
300 // - now copy LENGTH bytes from (output_ptr-DISTANCE) to output_ptr
301 // write current buffer to output
302 m_pOutStream
->WriteBytes(m_Output
, m_nOutputBufferPos
);
303 m_nOutputBufferPos
= 0;
305 // remember current position
306 sal_uInt32 nOutputPos
= m_pOutStream
->Tell();
307 if (distance
> nOutputPos
)
308 return -3; // format error
310 m_pOutStream
->FlushBuffer();
311 // point back to copy position and read bytes
312 m_pOutStream
->SeekRel(-static_cast<tools::Long
>(distance
));
313 sal_uInt8 sTemp
[MAXWIN
];
314 sal_uInt32 nRead
= std::min(distance
, Length
);
315 m_pOutStream
->ReadBytes(sTemp
, nRead
);
318 // fill the buffer with read content repeatedly until full
319 for (sal_uInt32 i
=nRead
; i
<Length
; i
++)
321 sTemp
[i
] = sTemp
[i
-nRead
];
325 // restore output stream position
326 m_pOutStream
->Seek(nOutputPos
);
328 // write current buffer to output
329 m_pOutStream
->WriteBytes(sTemp
, Length
);
334 * @descr bits to string
337 void Decompression::ToString(sal_uInt32 nBits
, char *pChar
, sal_uInt32 nLen
)
340 for (sal_uInt32 i
=nLen
; i
> 0; i
--)
342 nBit
= (nBits
>> (i
-1) ) & 0x01;
343 pChar
[nLen
- i
] = nBit
? '1':'0';
349 * @descr decode tree 1 for length
350 * @return the decoded value
352 sal_uInt32
Decompression::Decode(HuffmanTreeNode
* pRoot
)
355 sal_uInt32 nRead
, nReadAlready
;
357 if( 0 != ReadBits(1, nReadAlready
))
358 return 0; // something wrong
360 for (sal_uInt16 i
=2; i
<= 8; i
++)
362 if ( 0 != ReadBits(1, nRead
))
363 return 0; // something wrong
365 nReadAlready
= (nReadAlready
<< 1) | (nRead
& 0x01);
368 ToString(nReadAlready
, sCode
, i
);
369 nRet
= pRoot
->QueryValue(sCode
);
370 if (nRet
!= 0xffffffff)
378 * @descr construct tree 1 for length
381 void Decompression::ConstructTree1()
383 // The first huffman tree (the Section called Decompression algorithm HUFFMAN) contains the length values. It is described by the following table:
384 // value (hex) code (binary)
401 m_Tree1
.reset( new HuffmanTreeNode());
402 for (sal_uInt32 i
=0; i
< 16; i
++)
404 m_Tree1
->InsertNode(i
, Tree1String
[i
]);
407 m_Tree1->InsertNode(0, "101");
408 m_Tree1->InsertNode(1, "11");
409 m_Tree1->InsertNode(2, "100");
410 m_Tree1->InsertNode(3, "011");
411 m_Tree1->InsertNode(4, "0101");
412 m_Tree1->InsertNode(5, "0100");
413 m_Tree1->InsertNode(6, "0011");
414 m_Tree1->InsertNode(7, "00101");
415 m_Tree1->InsertNode(8, "00100");
416 m_Tree1->InsertNode(9, "00011");
417 m_Tree1->InsertNode(10, "00010");
418 m_Tree1->InsertNode(11, "000011");
419 m_Tree1->InsertNode(12, "000010");
420 m_Tree1->InsertNode(13, "000001");
421 m_Tree1->InsertNode(14, "0000001");
422 m_Tree1->InsertNode(15, "0000000");
426 * @descr construct tree 2 for distance
429 void Decompression::ConstructTree2()
432 m_Tree2
.reset(new HuffmanTreeNode());
433 for (sal_uInt32 i
=0; i
< 64; i
++)
435 m_Tree2
->InsertNode(i
, Tree2String
[i
]);
437 //where bits should be read from the left to the right.
443 void Decompression::fillArray()
446 for (int i
=1; i
< 16; i
++)
448 m_iArrayOfM
[i
] = m_iArrayOfM
[i
- 1]+ static_cast<sal_uInt32
>(pow(2.0, i
-1));//2
452 HuffmanTreeNode::HuffmanTreeNode(sal_uInt32 nValue
):value(nValue
)
455 HuffmanTreeNode::~HuffmanTreeNode()
459 HuffmanTreeNode
* HuffmanTreeNode::InsertNode(sal_uInt32 nValue
, const char * pInCode
)
461 HuffmanTreeNode
*pNew
= new HuffmanTreeNode(nValue
);
462 std::string
aCode(pInCode
);
465 const char cLast
= aCode
.back();
467 HuffmanTreeNode
* pParent
= QueryNode(aCode
.c_str());
470 pParent
= InsertNode(0xffffffff, aCode
.c_str());
473 pParent
->left
.reset(pNew
);
474 else // (cChar == '1')
475 pParent
->right
.reset(pNew
);
480 HuffmanTreeNode
* HuffmanTreeNode::QueryNode(const char * pCode
)
482 sal_uInt32 nLen
= strlen(pCode
);
484 HuffmanTreeNode
* pNode
= this; // this is the root
485 for(sal_uInt32 i
=0; i
<nLen
&& pNode
; i
++)
487 char cChar
= pCode
[i
];
490 pNode
= pNode
->left
.get();
492 else // (cChar == '1')
494 pNode
= pNode
->right
.get();
500 sal_uInt32
HuffmanTreeNode::QueryValue(const char * pCode
)
502 HuffmanTreeNode
* pNode
=QueryNode(pCode
);
509 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */