LCOV - code coverage report
Current view: top level - lotuswordpro/source/filter - explode.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 0 150 0.0 %
Date: 2014-11-03 Functions: 0 13 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*************************************************************************
       3             :  *
       4             :  *  The Contents of this file are made available subject to the terms of
       5             :  *  either of the following licenses
       6             :  *
       7             :  *         - GNU Lesser General Public License Version 2.1
       8             :  *         - Sun Industry Standards Source License Version 1.1
       9             :  *
      10             :  *  Sun Microsystems Inc., October, 2000
      11             :  *
      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
      16             :  *
      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.
      20             :  *
      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.
      25             :  *
      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,
      29             :  *  MA  02111-1307  USA
      30             :  *
      31             :  *
      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.
      38             :  *
      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.
      45             :  *
      46             :  *  The Initial Developer of the Original Code is: IBM Corporation
      47             :  *
      48             :  *  Copyright: 2008 by IBM Corporation
      49             :  *
      50             :  *  All Rights Reserved.
      51             :  *
      52             :  *  Contributor(s): _______________________________________
      53             :  *
      54             :  *
      55             :  ************************************************************************/
      56             : #include <assert.h>
      57             : #include "explode.hxx"
      58             : #include <math.h>
      59             :     const static char Tree1String[][32] = {
      60             :         "101",
      61             :         "11",
      62             :            "100",
      63             :         "011",
      64             :         "0101",
      65             :         "0100",
      66             :         "0011",
      67             :         "00101",
      68             :         "00100",
      69             :         "00011",
      70             :         "00010",
      71             :         "000011",
      72             :         "000010",
      73             :         "000001",
      74             :         "0000001",
      75             :         "0000000",
      76             :     };
      77             : 
      78             :     const static char Tree2String[][32] = {
      79             :         "11"    ,
      80             :         "1011"  ,
      81             :            "1010"  ,
      82             :         "10011"  ,
      83             :         "10010"  ,
      84             :         "10001"  ,
      85             :         "10000"  ,
      86             :         "011111"  ,
      87             :         "011110"  ,
      88             :         "011101"  ,
      89             :         "011100"  ,
      90             :         "011011"  ,
      91             :         "011010"  ,
      92             :         "011001"  ,
      93             :         "011000"  ,
      94             :         "010111"  ,
      95             :         "010110" ,
      96             :         "010101" ,
      97             :         "010100" ,
      98             :         "010011" ,
      99             :         "010010" ,
     100             :         "010001" ,
     101             :         "0100001" ,
     102             :         "0100000" ,
     103             :         "0011111" ,
     104             :         "0011110" ,
     105             :         "0011101" ,
     106             :         "0011100" ,
     107             :         "0011011" ,
     108             :         "0011010" ,
     109             :         "0011001" ,
     110             :         "0011000" ,
     111             :         "0010111" ,
     112             :         "0010110" ,
     113             :         "0010101" ,
     114             :         "0010100" ,
     115             :         "0010011" ,
     116             :         "0010010" ,
     117             :         "0010001" ,
     118             :         "0010000" ,
     119             :         "0001111" ,
     120             :         "0001110" ,
     121             :         "0001101" ,
     122             :         "0001100" ,
     123             :         "0001011" ,
     124             :         "0001010" ,
     125             :         "0001001" ,
     126             :         "0001000" ,
     127             :         "00001111",
     128             :         "00001110",
     129             :         "00001101",
     130             :         "00001100",
     131             :         "00001011",
     132             :         "00001010",
     133             :         "00001001",
     134             :         "00001000",
     135             :         "00000111",
     136             :         "00000110",
     137             :         "00000101",
     138             :         "00000100",
     139             :         "00000011",
     140             :         "00000010",
     141             :         "00000001",
     142             :         "00000000",
     143             :     };
     144             : 
     145           0 : Decompression::Decompression(SvStream * pInStream, SvStream * pOutStream)
     146             :     : m_pInStream(pInStream)
     147             :     , m_pOutStream(pOutStream)
     148             :     , m_nCurrent4Byte(0)
     149             :     , m_nBitsLeft(0)
     150             :     , m_pBuffer(m_Buffer)
     151             :     , m_nBytesLeft(0)
     152           0 :     , m_nOutputBufferPos(0)
     153             : {
     154           0 :     if (!m_pInStream || !m_pOutStream )
     155             :     {
     156             :         assert(false);
     157             :     }
     158           0 :     ConstructTree1();
     159           0 :     ConstructTree2();
     160           0 :     fillArray();
     161           0 : }
     162             : /**
     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
     167             :  */
     168           0 : sal_uInt32 Decompression::ReadBits(sal_uInt16 iCount, sal_uInt32 & nBits)
     169             : {
     170           0 :     if ( (iCount == 0) || (iCount > 31 ) )
     171             :     {
     172           0 :         return 1;
     173             :     }
     174             : 
     175           0 :     sal_uInt32 val = 0;     /* bit accumulator */
     176             : 
     177             :     /* load at least need bits into val */
     178           0 :     val = m_nCurrent4Byte;
     179           0 :     while (m_nBitsLeft < iCount)
     180             :     {
     181           0 :         if (m_nBytesLeft == 0)
     182             :         {
     183           0 :             m_nBytesLeft = m_pInStream->Read(m_Buffer, CHUNK);
     184           0 :             m_pBuffer = m_Buffer;
     185           0 :             if (m_nBytesLeft == 0)  return 1;
     186             :             }
     187           0 :         val |= (sal_uInt32)(*m_pBuffer++) << m_nBitsLeft;       /* load eight bits */
     188           0 :         m_nBytesLeft --;
     189           0 :         m_nBitsLeft += 8;
     190             :     }
     191             : 
     192             :     /* drop need bits and update buffer, always zero to seven bits left */
     193           0 :     m_nCurrent4Byte = val >> iCount;
     194           0 :     m_nBitsLeft -= iCount;
     195             : 
     196             :     /* return need bits, zeroing the bits above that */
     197           0 :     nBits = val & ((1 << iCount) - 1);
     198             : 
     199           0 :     return 0;
     200             : }
     201             : /**
     202             :  * @descr   decompress input and write output
     203             :  * @return  0 - read OK, otherwise error
     204             :  */
     205           0 : sal_Int32 Decompression::explode()
     206             : {
     207             :     /* The first 2 bytes are parameters */
     208             :     sal_uInt32 P1;
     209           0 :     if (0 != ReadBits(8, P1))/* 0 or 1 */
     210           0 :         return -1;
     211             : 
     212             :     /* I think this means 0=binary and 1=ascii file, but in RESOURCEs I saw always 0 */
     213           0 :     if (P1 >= 1) // changed per 's review comments
     214           0 :         return -1;
     215             : 
     216             :     sal_uInt32 P2;
     217           0 :     if (0 != ReadBits(8, P2))
     218           0 :         return -1;
     219             : 
     220             :     /* must be 4,5 or 6 and it is a parameter for the decompression algorithm */
     221           0 :     if (P2 < 4 || P2 > 6)
     222           0 :         return -2;
     223             : 
     224           0 :     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. */
     227             :     while(true)
     228             :     {
     229             :         // read 1 bit (take bits from the lowest value (LSB) to the MSB i.e. bit 0, bit 1 etc ...)
     230             :         sal_uInt32 iBit;
     231           0 :         if (0 != ReadBits(1, iBit))
     232           0 :             break;
     233           0 :         if ( 0 == (iBit & 0x01) )
     234             :         {
     235             :             //if the bit is 0 read 8 bits and write it to the output as it is.
     236             :             sal_uInt32 symbol;
     237           0 :             if (0 != ReadBits(8, symbol))
     238           0 :                 break;
     239           0 :             m_Output[m_nOutputBufferPos++] = (sal_uInt8)symbol;
     240           0 :             if (m_nOutputBufferPos == MAXWIN)
     241             :             {
     242           0 :                 m_pOutStream->Write(m_Output, m_nOutputBufferPos);
     243           0 :                 m_nOutputBufferPos = 0;
     244             :             }
     245           0 :             continue;
     246             :         }
     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           0 :         sal_uInt32 L1 = Decode(m_Tree1);
     250             :         sal_uInt32 Length;
     251           0 :         if (L1 <= 7)
     252             :         {
     253             :             //if L1 <= 7:
     254             :             //           LENGTH = L1 + 2
     255           0 :             Length = L1 + 2;
     256             :         }
     257             :         else
     258             :         {
     259             :             // if L1 > 7
     260             :             //            read more (L1-7) bits -> L2
     261             :             //             LENGTH = L2 + M[L1-7] + 2
     262             :             sal_uInt32 L2;
     263           0 :             if (0 != ReadBits((sal_uInt16)(L1 - 7), L2))
     264           0 :                 break;
     265           0 :             Length = L2 + 2 + m_iArrayOfM[L1 -7];
     266             :         }
     267           0 :         if (Length == 519)
     268             :         {
     269             :             // end of compressed data
     270           0 :             break;
     271             :         }
     272             : 
     273             :         // - decode another number with Hufmann Tree #2 giving result 0x00..0x3F -> D1
     274           0 :         sal_uInt32 D1 = Decode(m_Tree2);
     275             :         sal_uInt32 D2;
     276           0 :         if (Length == 2)
     277             :         {
     278             :             //       if LENGTH == 2
     279             :             //              D1 = D1 << 2
     280             :             //              read 2 bits -> D2
     281           0 :             D1 = D1 << 2;
     282           0 :             if (0 != ReadBits(2, D2))
     283           0 :                 break;
     284             :         }
     285             :         else
     286             :         {
     287             :             //        else
     288             :             //               D1 = D1 << P2  // the parameter 2
     289             :             //               read P2 bits -> D2
     290           0 :             D1 = D1 << P2;
     291           0 :             if (0 != ReadBits((sal_uInt16)P2, D2))
     292           0 :                 break;
     293             :         }
     294             :         // DISTANCE = (D1 | D2) + 1
     295           0 :         sal_uInt32 distance = (D1 | D2) + 1;
     296             : 
     297             :             // - now copy LENGTH bytes from (output_ptr-DISTANCE) to output_ptr
     298             :             // write current buffer to output
     299           0 :         m_pOutStream->Write(m_Output, m_nOutputBufferPos);
     300           0 :         m_nOutputBufferPos = 0;
     301             : 
     302             :         // remember current position
     303           0 :         sal_uInt32 nOutputPos = m_pOutStream->Tell();
     304           0 :         if (distance > nOutputPos)
     305           0 :             return -3; // format error
     306             : 
     307           0 :         m_pOutStream->Flush();
     308             :         // point back to copy position and read bytes
     309           0 :         m_pOutStream->SeekRel(-(long)distance);
     310             :         sal_uInt8 sTemp[MAXWIN];
     311           0 :         sal_uInt32 nRead = distance > Length? Length:distance;
     312           0 :         m_pOutStream->Read(sTemp, nRead);
     313           0 :         if (nRead != Length)
     314             :         {
     315             :             // fill the buffer with read content repeatly until full
     316           0 :             for (sal_uInt32 i=nRead; i<Length; i++)
     317             :             {
     318           0 :                 sTemp[i] = sTemp[i-nRead];
     319             :             }
     320             :         }
     321             : 
     322             :         // restore output stream position
     323           0 :         m_pOutStream->Seek(nOutputPos);
     324             : 
     325             :            // write current buffer to output
     326           0 :         m_pOutStream->Write(sTemp, Length);
     327             :     }
     328           0 :     return 0;
     329             : }
     330             : /**
     331             :  * @descr   bits to string
     332             :  * @return
     333             :  */
     334           0 : void Decompression::ToString(sal_uInt32 nBits, sal_Char *pChar, sal_uInt32 nLen)
     335             : {
     336             :     sal_uInt32 nBit;
     337           0 :     for (sal_uInt32 i=nLen; i > 0; i--)
     338             :     {
     339           0 :         nBit = (nBits >> (i -1) ) & 0x01;
     340           0 :         pChar[nLen - i]  = nBit ? '1':'0';
     341             :     }
     342           0 :     pChar[nLen] = '\0';
     343           0 :     return;
     344             : }
     345             : 
     346             : /**
     347             :  * @descr   decode tree 1 for length
     348             :  * @return  the decoded value
     349             :  */
     350           0 : sal_uInt32 Decompression::Decode(HuffmanTreeNode * pRoot)
     351             : {
     352           0 :     sal_uInt32 nRet(0);
     353             :     sal_uInt32 nRead, nReadAlready;
     354             : 
     355           0 :     if( 0 != ReadBits(1, nReadAlready))
     356           0 :         return 0; // something wrong
     357             : 
     358           0 :     for (sal_uInt16 i=2; i <= 8; i++)
     359             :     {
     360           0 :         if ( 0 != ReadBits(1, nRead))
     361           0 :             return 0; // something wrong
     362             : 
     363           0 :         nReadAlready  = (nReadAlready << 1) | (nRead & 0x01);
     364             : 
     365             :         sal_Char sCode[16];
     366           0 :         ToString(nReadAlready, sCode, i);
     367           0 :         nRet = pRoot->QueryValue(sCode);
     368           0 :         if (nRet != 0xffffffff)
     369             :         {
     370           0 :             break;
     371             :         }
     372             :     }
     373           0 :     return nRet;
     374             : }
     375             : /**
     376             :  * @descr   construct tree 1 for length
     377             :  * @return
     378             :  */
     379           0 : void Decompression::ConstructTree1()
     380             : {   // Huffman Tree #1
     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)
     383             :     // 0    101
     384             :     // 1    11
     385             :     // 2    100
     386             :     // 3    011
     387             :     // 4    0101
     388             :     // 5    0100
     389             :     // 6    0011
     390             :     // 7    0010 1
     391             :     // 8    0010 0
     392             :     // 9    0001 1
     393             :     // a    0001 0
     394             :     // b    0000 11
     395             :     // c    0000 10
     396             :     // d    0000 01
     397             :     // e    0000 001
     398             :     // f    0000 000
     399           0 :     m_Tree1 = new HuffmanTreeNode();
     400           0 :     for (sal_uInt32 i=0; i< 16; i++)
     401             :     {
     402           0 :         m_Tree1->InsertNode(i, Tree1String[i]);
     403             :     }
     404             :     /*
     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");
     421             :     */
     422           0 : }
     423             : /**
     424             :  * @descr   construct tree 2 for distance
     425             :  * @return
     426             :  */
     427           0 : void Decompression::ConstructTree2()
     428             : {
     429             : 
     430           0 :     m_Tree2 = new HuffmanTreeNode();
     431           0 :     for (sal_uInt32 i=0; i< 64; i++)
     432             :     {
     433           0 :         m_Tree2->InsertNode(i, Tree2String[i]);
     434             :     }
     435             :     //where bits should be read from the left to the right.
     436           0 : }
     437             : /**
     438             :  * @descr
     439             :  * @return
     440             :  */
     441           0 : void Decompression::fillArray()
     442             : {
     443           0 :     m_iArrayOfM[0] = 7;
     444           0 :     for (int i=1; i < 16; i++)
     445             :     {
     446           0 :         double dR = 2.0;
     447           0 :         m_iArrayOfM[i]  = m_iArrayOfM[i - 1]+ (sal_uInt32)pow(dR, i-1);//2
     448             :     }
     449           0 : }
     450             : 
     451           0 : HuffmanTreeNode::HuffmanTreeNode(sal_uInt32 nValue , HuffmanTreeNode * pLeft , HuffmanTreeNode * pRight )
     452             : {
     453           0 :     value = nValue;
     454           0 :     left = pLeft;
     455           0 :     right = pRight;
     456           0 : }
     457           0 : HuffmanTreeNode::~HuffmanTreeNode()
     458             : {
     459           0 :     if (left)
     460             :     {
     461           0 :         delete left;
     462           0 :         left = NULL;
     463             :     }
     464           0 :     if (right)
     465             :     {
     466           0 :         delete right;
     467           0 :         right = NULL;
     468             :     }
     469           0 : }
     470             : 
     471           0 : HuffmanTreeNode * HuffmanTreeNode::InsertNode(sal_uInt32 nValue, const sal_Char * pInCode)
     472             : {
     473           0 :     HuffmanTreeNode *pNew = new HuffmanTreeNode(nValue);
     474             :     sal_Char pCode[32];
     475           0 :         strcpy(pCode, pInCode );
     476             : 
     477             :     // query its parents
     478           0 :     sal_Char cLast = pCode[strlen(pCode) - 1];
     479           0 :     pCode[strlen(pCode) - 1] = '\0';
     480           0 :     HuffmanTreeNode * pParent = QueryNode(pCode);
     481           0 :     if (!pParent)
     482             :     {
     483           0 :         pParent = InsertNode(0xffffffff, pCode);
     484             :     }
     485           0 :     if (cLast == '0')
     486           0 :         pParent->left = pNew;
     487             :     else // (cChar == '1')
     488           0 :         pParent->right = pNew;
     489             : 
     490           0 :     return pNew;
     491             : }
     492           0 : HuffmanTreeNode * HuffmanTreeNode::QueryNode(const sal_Char * pCode)
     493             : {
     494           0 :     sal_uInt32 nLen = strlen(pCode);
     495             : 
     496           0 :     HuffmanTreeNode * pNode = this; // this is the root
     497           0 :     for(sal_uInt32 i=0; i<nLen && pNode; i++)
     498             :     {
     499           0 :         sal_Char cChar= pCode[i];
     500           0 :         if (cChar == '0')
     501             :         {
     502           0 :             pNode = pNode->left;
     503             :         }
     504             :         else // (cChar == '1')
     505             :         {
     506           0 :             pNode = pNode->right;
     507             :         }
     508             :     }
     509           0 :     return pNode;
     510             : }
     511             : 
     512           0 : sal_uInt32 HuffmanTreeNode::QueryValue(const sal_Char * pCode)
     513             : {
     514           0 :     HuffmanTreeNode * pNode =QueryNode(pCode);
     515           0 :     if (pNode)
     516           0 :         return pNode->value;
     517             : 
     518           0 :     return 0xffffffff;
     519             : }
     520             : 
     521             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10