LibreOffice Module vcl (master)  1
decode.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include "decode.hxx"
21 
22 #include <cstdlib>
23 #include <cstring>
24 
26 {
30 };
31 
33  : pTable(new GIFLZWTableEntry[4098])
34  , pOutBufData(pOutBuf.data() + 4096)
35  , pBlockBuf(nullptr)
36  , nInputBitsBuf(0)
37  , bEOIFound(false)
38  , nDataSize(cDataSize)
39  , nBlockBufSize(0)
40  , nBlockBufPos(0)
41  , nClearCode(1 << nDataSize)
42  , nEOICode(nClearCode + 1)
43  , nTableSize(nEOICode + 1)
44  , nCodeSize(nDataSize + 1)
45  , nOldCode(0xffff)
46  , nOutBufDataLen(0)
47  , nInputBitsBufSize(0)
48 {
49  for (sal_uInt16 i = 0; i < nTableSize; ++i)
50  {
51  pTable[i].pPrev = nullptr;
52  pTable[i].pFirst = &pTable[i];
53  pTable[i].nData = static_cast<sal_uInt8>(i);
54  }
55 
56  memset(pTable.get() + nTableSize, 0, sizeof(GIFLZWTableEntry) * (4098 - nTableSize));
57 }
58 
60 {
61 }
62 
64  sal_uLong& rCount, bool& rEOI )
65 {
66  sal_uLong nTargetSize = 4096;
67  sal_uLong nCount = 0;
68  sal_uInt8* pTarget = static_cast<sal_uInt8*>(std::malloc( nTargetSize ));
69  sal_uInt8* pTmpTarget = pTarget;
70 
71  nBlockBufSize = cBufSize;
72  nBlockBufPos = 0;
73  pBlockBuf = pSrc;
74 
75  while (pTarget && ProcessOneCode())
76  {
77  nCount += nOutBufDataLen;
78 
79  if( nCount > nTargetSize )
80  {
81  sal_uLong nNewSize = nTargetSize << 1;
82  sal_uLong nOffset = pTmpTarget - pTarget;
83  if (auto p = static_cast<sal_uInt8*>(std::realloc(pTarget, nNewSize)))
84  pTarget = p;
85  else
86  {
87  free(pTarget);
88  pTarget = nullptr;
89  break;
90  }
91 
92  nTargetSize = nNewSize;
93  pTmpTarget = pTarget + nOffset;
94  }
95 
96  memcpy( pTmpTarget, pOutBufData, nOutBufDataLen );
97  pTmpTarget += nOutBufDataLen;
99  nOutBufDataLen = 0;
100 
101  if ( bEOIFound )
102  break;
103  }
104 
105  rCount = nCount;
106  rEOI = bEOIFound;
107 
108  return pTarget;
109 }
110 
111 bool GIFLZWDecompressor::AddToTable( sal_uInt16 nPrevCode, sal_uInt16 nCodeFirstData )
112 {
113  if( nTableSize < 4096 )
114  {
115  GIFLZWTableEntry* pE = pTable.get() + nTableSize;
116  pE->pPrev = pTable.get() + nPrevCode;
117  pE->pFirst = pE->pPrev->pFirst;
118  GIFLZWTableEntry *pEntry = pTable[nCodeFirstData].pFirst;
119  if (!pEntry)
120  return false;
121  pE->nData = pEntry->nData;
122  nTableSize++;
123 
124  if ( ( nTableSize == static_cast<sal_uInt16>(1 << nCodeSize) ) && ( nTableSize < 4096 ) )
125  nCodeSize++;
126  }
127  return true;
128 }
129 
131 {
132  sal_uInt16 nCode;
133  bool bRet = false;
134  bool bEndOfBlock = false;
135 
136  while( nInputBitsBufSize < nCodeSize )
137  {
138  if( nBlockBufPos >= nBlockBufSize )
139  {
140  bEndOfBlock = true;
141  break;
142  }
143 
145  nInputBitsBufSize += 8;
146  }
147 
148  if ( !bEndOfBlock )
149  {
150  // fetch code from input buffer
151  nCode = sal::static_int_cast< sal_uInt16 >(
152  static_cast<sal_uInt16>(nInputBitsBuf) & ( ~( 0xffff << nCodeSize ) ));
155 
156  if ( nCode < nClearCode )
157  {
158  bool bOk = true;
159  if ( nOldCode != 0xffff )
160  bOk = AddToTable(nOldCode, nCode);
161  if (!bOk)
162  return false;
163  }
164  else if ( ( nCode > nEOICode ) && ( nCode <= nTableSize ) )
165  {
166  if ( nOldCode != 0xffff )
167  {
168  bool bOk;
169  if ( nCode == nTableSize )
170  bOk = AddToTable( nOldCode, nOldCode );
171  else
172  bOk = AddToTable( nOldCode, nCode );
173  if (!bOk)
174  return false;
175  }
176  }
177  else
178  {
179  if ( nCode == nClearCode )
180  {
181  nTableSize = nEOICode + 1;
182  nCodeSize = nDataSize + 1;
183  nOldCode = 0xffff;
184  nOutBufDataLen = 0;
185  }
186  else
187  bEOIFound = true;
188 
189  return true;
190  }
191 
192  nOldCode = nCode;
193 
194  if (nCode >= 4096)
195  return false;
196 
197  // write character(/-sequence) of code nCode in the output buffer:
198  GIFLZWTableEntry* pE = pTable.get() + nCode;
199  do
200  {
201  if (pOutBufData == pOutBuf.data()) //can't go back past start
202  return false;
203  nOutBufDataLen++;
204  *(--pOutBufData) = pE->nData;
205  pE = pE->pPrev;
206  }
207  while( pE );
208 
209  bRet = true;
210  }
211 
212  return bRet;
213 }
214 
215 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt16 const nEOICode
Definition: decode.hxx:44
bool AddToTable(sal_uInt16 nPrevCode, sal_uInt16 nCodeFirstData)
Definition: decode.cxx:111
sal_uIntPtr sal_uLong
bool ProcessOneCode()
Definition: decode.cxx:130
GIFLZWTableEntry * pPrev
Definition: decode.cxx:27
std::array< sal_uInt8, 4096 > pOutBuf
Definition: decode.hxx:35
sal_uInt8 * pOutBufData
Definition: decode.hxx:36
sal_uInt16 nTableSize
Definition: decode.hxx:45
sal_uLong nInputBitsBuf
Definition: decode.hxx:38
GIFLZWTableEntry * pFirst
Definition: decode.cxx:28
sal_uInt8 nBlockBufPos
Definition: decode.hxx:42
Scanline DecompressBlock(sal_uInt8 *pSrc, sal_uInt8 cBufSize, sal_uLong &rCount, bool &rEOI)
Definition: decode.cxx:63
sal_uInt8 nData
Definition: decode.cxx:29
sal_uInt8 * Scanline
Definition: Scanline.hxx:25
int i
std::unique_ptr< GIFLZWTableEntry[]> pTable
Definition: decode.hxx:33
sal_uInt16 const nClearCode
Definition: decode.hxx:43
unsigned char sal_uInt8
sal_uInt8 * pBlockBuf
Definition: decode.hxx:37
sal_uInt16 nOutBufDataLen
Definition: decode.hxx:48
sal_uInt8 const nDataSize
Definition: decode.hxx:40
sal_uInt16 nOldCode
Definition: decode.hxx:47
GIFLZWDecompressor(const GIFLZWDecompressor &)=delete
sal_uInt8 nBlockBufSize
Definition: decode.hxx:41
sal_uInt16 nCodeSize
Definition: decode.hxx:46
sal_uInt16 nInputBitsBufSize
Definition: decode.hxx:49