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
57 #include <lwpobjstrm.hxx>
58 #include <lwptools.hxx>
59
60 #include <osl/endian.h>
61 #include <sal/types.h>
62 #include <tools/solar.h>
63 #include <memory>
64
65 /**
66 * @descr ctor() from LwpSvStream
67 */
LwpObjectStream(LwpSvStream * pStrm,bool isCompressed,sal_uInt16 size)68 LwpObjectStream::LwpObjectStream(LwpSvStream *pStrm, bool isCompressed, sal_uInt16 size)
69 :m_pContentBuf(nullptr), m_nBufSize(size), m_nReadPos(0),
70 m_pStrm(pStrm), m_bCompressed(isCompressed)
71 {
72 if (size >= IO_BUFFERSIZE)
73 throw std::range_error("bad Object size");
74 // read object data from stream
75 if (m_nBufSize > 0)
76 Read2Buffer();
77 }
78
79 /**
80 * @descr read object data from stream to buffer
81 */
Read2Buffer()82 void LwpObjectStream::Read2Buffer()
83 {
84 ReleaseBuffer();
85
86 m_nReadPos = 0;
87
88 if( m_bCompressed )
89 {
90 std::unique_ptr<sal_uInt8[]> xCompressBuf(new sal_uInt8[m_nBufSize]);
91
92 sal_uInt8* pCompressBuffer = xCompressBuf.get();
93 memset(pCompressBuffer, 0, m_nBufSize);
94 m_nBufSize = m_pStrm->Read(pCompressBuffer, m_nBufSize);
95
96 sal_uInt8 pTempDst[IO_BUFFERSIZE];
97 m_nBufSize = DecompressBuffer(pTempDst, pCompressBuffer, m_nBufSize);
98 assert( m_nBufSize < IO_BUFFERSIZE);
99
100 m_pContentBuf = AllocBuffer(m_nBufSize);
101 memcpy(m_pContentBuf, pTempDst, m_nBufSize);
102 }
103 else
104 {
105 m_pContentBuf = AllocBuffer(m_nBufSize);
106 m_nBufSize = m_pStrm->Read(m_pContentBuf, m_nBufSize);
107 }
108 }
109 /**
110 * @descr alloc size of buffer
111 */
AllocBuffer(sal_uInt16 size)112 sal_uInt8* LwpObjectStream::AllocBuffer(sal_uInt16 size)
113 {
114 if (size<=100)
115 {
116 return m_SmallBuffer;
117 }
118 m_BigBuffer.resize(size);
119 return m_BigBuffer.data();
120 }
121 /**
122 * @descr signal complete to release object buffer
123 */
ReadComplete()124 void LwpObjectStream::ReadComplete()
125 {
126 ReleaseBuffer();
127 }
128
~LwpObjectStream()129 LwpObjectStream::~LwpObjectStream()
130 {
131 ReleaseBuffer();
132 }
133 /**
134 * @descr release object buffer
135 */
ReleaseBuffer()136 void LwpObjectStream::ReleaseBuffer()
137 {
138 m_BigBuffer.clear();
139 m_pContentBuf = nullptr;
140 }
141
remainingSize() const142 sal_uInt16 LwpObjectStream::remainingSize() const
143 {
144 return m_nBufSize - m_nReadPos;
145 }
146
147 /**
148 * @descr read len bytes from object stream to buffer
149 */
QuickRead(void * buf,sal_uInt16 len)150 sal_uInt16 LwpObjectStream::QuickRead(void* buf, sal_uInt16 len)
151 {
152 memset(buf, 0, len);
153 if( len > m_nBufSize - m_nReadPos )
154 {
155 len = m_nBufSize - m_nReadPos;
156 }
157 if( m_pContentBuf && len)
158 {
159 memcpy(buf, m_pContentBuf+m_nReadPos, len);
160 m_nReadPos += len;
161 }
162 return len;
163 }
164 /**
165 * @descr SeekRel pos in object stream/buffer
166 */
SeekRel(sal_uInt16 pos)167 void LwpObjectStream::SeekRel(sal_uInt16 pos)
168 {
169 if( pos > m_nBufSize - m_nReadPos)
170 pos = m_nBufSize - m_nReadPos;
171 m_nReadPos +=pos;
172 }
173 /**
174 * @descr Seek to pos in object buffer/buffer
175 */
Seek(sal_uInt16 pos)176 void LwpObjectStream::Seek( sal_uInt16 pos)
177 {
178 if (pos < m_nBufSize)
179 {
180 m_nReadPos = pos;
181 }
182 }
183
184 /**
185 * @descr Quick read sal_Bool
186 */
QuickReadBool()187 bool LwpObjectStream::QuickReadBool()
188 {
189 SVBT16 aValue = {0};
190 QuickRead(aValue, sizeof(aValue));
191 return static_cast<bool>(SVBT16ToUInt16(aValue));
192 }
193 /**
194 * @descr Quick read sal_uInt32
195 */
QuickReaduInt32(bool * pFailure)196 sal_uInt32 LwpObjectStream::QuickReaduInt32(bool *pFailure)
197 {
198 SVBT32 aValue = {0};
199 sal_uInt16 nRead = QuickRead(aValue, sizeof(aValue));
200 if (pFailure)
201 *pFailure = (nRead != sizeof(aValue));
202 return SVBT32ToUInt32(aValue);
203 }
204 /**
205 * @descr Quick read sal_uInt32
206 */
QuickReaduInt16(bool * pFailure)207 sal_uInt16 LwpObjectStream::QuickReaduInt16(bool *pFailure)
208 {
209 SVBT16 aValue = {0};
210 sal_uInt16 nRead = QuickRead(aValue, sizeof(aValue));
211 if (pFailure)
212 *pFailure = (nRead != sizeof(aValue));
213 return SVBT16ToUInt16(aValue);
214 }
215 /**
216 * @descr Quick read sal_Int32
217 */
QuickReadInt32()218 sal_Int32 LwpObjectStream::QuickReadInt32()
219 {
220 SVBT32 aValue = {0};
221 QuickRead(aValue, sizeof(aValue));
222 return static_cast<sal_Int32>(SVBT32ToUInt32(aValue));
223 }
224 /**
225 * @descr Quick read sal_Int16
226 */
QuickReadInt16()227 sal_Int16 LwpObjectStream::QuickReadInt16()
228 {
229 SVBT16 aValue = {0};
230 QuickRead(aValue, sizeof(aValue));
231
232 return static_cast<sal_Int16>(SVBT16ToUInt16(aValue));
233 }
234 /**
235 * @descr Quick read sal_uInt8
236 */
QuickReaduInt8(bool * pFailure)237 sal_uInt8 LwpObjectStream::QuickReaduInt8(bool *pFailure)
238 {
239 sal_uInt8 aValue = 0;
240 sal_uInt16 nRead = QuickRead(&aValue, sizeof(aValue));
241 if (pFailure)
242 *pFailure = (nRead != sizeof(aValue));
243 return aValue;
244 }
245 /**
246 * @descr Quick read double
247 */
QuickReadDouble()248 double LwpObjectStream::QuickReadDouble()
249 {
250 union
251 {
252 double d;
253 sal_uInt8 c[8];
254 } s;
255 memset(s.c, 0, sizeof(s.c));
256 QuickRead(s.c, sizeof(s.c));
257 #if defined(OSL_BIGENDIAN)
258 for (size_t i = 0; i < 4; ++i)
259 std::swap(s.c[i], s.c[7-i]);
260 #endif
261 return s.d;
262 }
263 /**
264 * @descr skip extra bytes
265 */
SkipExtra()266 void LwpObjectStream::SkipExtra()
267 {
268 sal_uInt16 extra = QuickReaduInt16();
269 while (extra != 0)
270 extra = QuickReaduInt16();
271 }
272 /**
273 * @descr check if extra bytes
274 */
CheckExtra()275 sal_uInt16 LwpObjectStream::CheckExtra()
276 {
277 return QuickReaduInt16();
278 }
279 /**
280 * @descr decompress data buffer from pSrc to pDst
281 * Refer to the CAmiPro40File::DecompressObject(~) in LWP
282 */
DecompressBuffer(sal_uInt8 * pDst,sal_uInt8 * pSrc,sal_uInt16 Size)283 sal_uInt16 LwpObjectStream::DecompressBuffer(sal_uInt8* pDst, sal_uInt8* pSrc, sal_uInt16 Size)
284 {
285 sal_uInt16 Cnt;
286 sal_uInt32 DstSize = 0;
287
288 while (Size)
289 {
290 switch (*pSrc & 0xC0)
291 {
292 case 0x00:
293 // 1 - 64 bytes of 0
294 // Code 00zzzzzz
295 // where zzzzzz is the count - 1 of compressed 0 bytes
296
297 Cnt = (*pSrc++ & 0x3F) + 1;
298 if (DstSize+Cnt >= IO_BUFFERSIZE)
299 throw BadDecompress();
300 memset(pDst, 0, Cnt);
301 pDst += Cnt;
302 DstSize += Cnt;
303 Size--;
304 break;
305
306 case 0x40:
307 // 1 - 8 zeros followed by 1 - 8 non-zero
308 // Code 01zzznnn binary
309 // where zzz is the count - 1 of compressed zero bytes
310 // and nnn is the count - 1 of following non-zero bytes
311
312 Cnt = ((*pSrc & 0x38) >> 3) + 1;
313 if (DstSize+Cnt >= IO_BUFFERSIZE)
314 throw BadDecompress();
315 memset(pDst, 0, Cnt);
316 pDst += Cnt;
317 DstSize += Cnt;
318 Cnt = (*pSrc++ & 0x07) + 1;
319 if (Size < Cnt + 1)
320 throw BadDecompress();
321 Size -= Cnt + 1;
322 if (DstSize+Cnt >= IO_BUFFERSIZE)
323 throw BadDecompress();
324 memcpy(pDst, pSrc, Cnt);
325 pDst += Cnt;
326 DstSize += Cnt;
327 pSrc += Cnt;
328 break;
329
330 case 0x80:
331 // 1 0 followed by 1 - 64 bytes of non-zero
332 // Code 0x80 (or 0x40 if 8 or less non-zero)
333 // Code 10nnnnnn binary
334 // where nnnnnn is the count - 1 of following non-zero bytes
335
336 *pDst++ = 0;
337 DstSize++;
338 [[fallthrough]];
339
340 case 0xC0:
341 // 1 - 64 bytes of non-zero
342 // Code = 11nnnnnn binary
343 // nnnnnn is the count less 1 of following non-zero bytes
344
345 Cnt = (*pSrc++ & 0x3F) + 1;
346 if (Size < Cnt + 1)
347 throw BadDecompress();
348 Size -= Cnt + 1;
349 if (DstSize+Cnt >= IO_BUFFERSIZE)
350 throw BadDecompress();
351 memcpy(pDst, pSrc, Cnt);
352 pDst += Cnt;
353 DstSize += Cnt;
354 pSrc += Cnt;
355 break;
356 }
357 assert(DstSize < IO_BUFFERSIZE);
358 if (DstSize >= IO_BUFFERSIZE)
359 throw BadDecompress();
360
361 }
362 return static_cast<sal_uInt16>(DstSize);
363 }
364 /**
365 * @descr quick read string with 1252
366 */
QuickReadStringPtr()367 OUString LwpObjectStream::QuickReadStringPtr()
368 {
369 sal_uInt16 diskSize;
370
371 diskSize = QuickReaduInt16();
372 QuickReaduInt16(); //len
373
374 OUString str;
375 if (diskSize < sizeof diskSize)
376 throw std::range_error("Too small size");
377 LwpTools::QuickReadUnicode(this, str, diskSize-sizeof(diskSize), RTL_TEXTENCODING_MS_1252);
378 return str;
379 }
380
381 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
382