Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / oox / source / ole / axbinaryreader.cxx
blobcbd7051637a5707d9fa49b9923bef4bb87c7d978
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <oox/ole/axbinaryreader.hxx>
22 #include <oox/ole/axfontdata.hxx>
23 #include <oox/ole/olehelper.hxx>
25 #include <osl/diagnose.h>
27 namespace oox {
28 namespace ole {
30 namespace {
32 const sal_uInt32 AX_STRING_SIZEMASK = 0x7FFFFFFF;
33 const sal_uInt32 AX_STRING_COMPRESSED = 0x80000000;
35 } // namespace
37 AxAlignedInputStream::AxAlignedInputStream( BinaryInputStream& rInStrm ) :
38 BinaryStreamBase( false ),
39 mpInStrm( &rInStrm ),
40 mnStrmPos( 0 ),
41 mnStrmSize( rInStrm.getRemaining() )
43 mbEof = mbEof || rInStrm.isEof();
46 sal_Int64 AxAlignedInputStream::size() const
48 return mpInStrm ? mnStrmSize : -1;
51 sal_Int64 AxAlignedInputStream::tell() const
53 return mpInStrm ? mnStrmPos : -1;
56 void AxAlignedInputStream::seek( sal_Int64 nPos )
58 mbEof = mbEof || (nPos < mnStrmPos);
59 if( !mbEof )
60 skip( static_cast< sal_Int32 >( nPos - mnStrmPos ) );
63 void AxAlignedInputStream::close()
65 mpInStrm = nullptr;
66 mbEof = true;
69 sal_Int32 AxAlignedInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize )
71 sal_Int32 nReadSize = 0;
72 if( !mbEof )
74 nReadSize = mpInStrm->readData( orData, nBytes, nAtomSize );
75 mnStrmPos += nReadSize;
76 mbEof = mpInStrm->isEof();
78 return nReadSize;
81 sal_Int32 AxAlignedInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize )
83 sal_Int32 nReadSize = 0;
84 if( !mbEof )
86 nReadSize = mpInStrm->readMemory( opMem, nBytes, nAtomSize );
87 mnStrmPos += nReadSize;
88 mbEof = mpInStrm->isEof();
90 return nReadSize;
93 void AxAlignedInputStream::skip( sal_Int32 nBytes, size_t nAtomSize )
95 if( !mbEof )
97 mpInStrm->skip( nBytes, nAtomSize );
98 mnStrmPos += nBytes;
99 mbEof = mpInStrm->isEof();
103 void AxAlignedInputStream::align( size_t nSize )
105 skip( static_cast< sal_Int32 >( (nSize - (mnStrmPos % nSize)) % nSize ) );
108 namespace {
110 bool lclReadString( AxAlignedInputStream& rInStrm, OUString& rValue, sal_uInt32 nSize, bool bArrayString )
112 bool bCompressed = getFlag( nSize, AX_STRING_COMPRESSED );
113 sal_uInt32 nBufSize = nSize & AX_STRING_SIZEMASK;
114 // Unicode: simple strings store byte count, array strings store char count
115 sal_Int32 nChars = static_cast< sal_Int32 >( nBufSize / ((bCompressed || bArrayString) ? 1 : 2) );
116 bool bValidChars = nChars <= 65536;
117 OSL_ENSURE( bValidChars, "lclReadString - string too long" );
118 sal_Int64 nEndPos = rInStrm.tell() + nChars * (bCompressed ? 1 : 2);
119 nChars = ::std::min< sal_Int32 >( nChars, 65536 );
120 rValue = rInStrm.readCompressedUnicodeArray( nChars, bCompressed );
121 rInStrm.seek( nEndPos );
122 return bValidChars;
125 } // namespace
127 AxBinaryPropertyReader::ComplexProperty::~ComplexProperty()
131 bool AxBinaryPropertyReader::PairProperty::readProperty( AxAlignedInputStream& rInStrm )
133 mrPairData.first = rInStrm.readInt32();
134 mrPairData.second = rInStrm.readInt32();
135 return true;
138 bool AxBinaryPropertyReader::StringProperty::readProperty( AxAlignedInputStream& rInStrm )
140 return lclReadString( rInStrm, mrValue, mnSize, false );
143 bool AxBinaryPropertyReader::ArrayStringProperty::readProperty( AxAlignedInputStream& rInStrm )
145 sal_Int64 nEndPos = rInStrm.tell() + mnSize;
146 while( rInStrm.tell() < nEndPos )
148 OUString aString;
149 if( !lclReadString( rInStrm, aString, rInStrm.readuInt32(), true ) )
150 return false;
151 mrArray.push_back( aString );
152 // every array string is aligned on 4 byte boundaries
153 rInStrm.align( 4 );
155 return true;
158 bool AxBinaryPropertyReader::GuidProperty::readProperty( AxAlignedInputStream& rInStrm )
160 mrGuid = OleHelper::importGuid( rInStrm );
161 return true;
164 bool AxBinaryPropertyReader::FontProperty::readProperty( AxAlignedInputStream& rInStrm )
166 return mrFontData.importGuidAndFont( rInStrm );
169 bool AxBinaryPropertyReader::PictureProperty::readProperty( AxAlignedInputStream& rInStrm )
171 return OleHelper::importStdPic( mrPicData, rInStrm );
174 AxBinaryPropertyReader::AxBinaryPropertyReader( BinaryInputStream& rInStrm, bool b64BitPropFlags ) :
175 maInStrm( rInStrm ),
176 mbValid( true )
178 // version and size of property block
179 maInStrm.skip( 2 );
180 sal_uInt16 nBlockSize = maInStrm.readuInt16();
181 mnPropsEnd = maInStrm.tell() + nBlockSize;
182 // flagfield containing existing properties
183 if( b64BitPropFlags )
184 mnPropFlags = maInStrm.readInt64();
185 else
186 mnPropFlags = maInStrm.readuInt32();
187 mnNextProp = 1;
190 void AxBinaryPropertyReader::readBoolProperty( bool& orbValue, bool bReverse )
192 // there is no data, the boolean value is equivalent to the property flag itself
193 orbValue = startNextProperty() != bReverse;
196 void AxBinaryPropertyReader::readPairProperty( AxPairData& orPairData )
198 if( startNextProperty() )
199 maLargeProps.push_back( ComplexPropVector::value_type( new PairProperty( orPairData ) ) );
202 void AxBinaryPropertyReader::readStringProperty( OUString& orValue )
204 if( startNextProperty() )
206 sal_uInt32 nSize = maInStrm.readAligned< sal_uInt32 >();
207 maLargeProps.push_back( ComplexPropVector::value_type( new StringProperty( orValue, nSize ) ) );
211 void AxBinaryPropertyReader::readArrayStringProperty( std::vector<OUString>& orValue )
213 if( startNextProperty() )
215 sal_uInt32 nSize = maInStrm.readAligned< sal_uInt32 >();
216 maLargeProps.push_back( ComplexPropVector::value_type( new ArrayStringProperty( orValue, nSize ) ) );
220 void AxBinaryPropertyReader::readGuidProperty( OUString& orGuid )
222 if( startNextProperty() )
223 maLargeProps.push_back( ComplexPropVector::value_type( new GuidProperty( orGuid ) ) );
226 void AxBinaryPropertyReader::readFontProperty( AxFontData& orFontData )
228 if( startNextProperty() )
230 sal_Int16 nData = maInStrm.readAligned< sal_Int16 >();
231 if( ensureValid( nData == -1 ) )
232 maStreamProps.push_back( ComplexPropVector::value_type( new FontProperty( orFontData ) ) );
236 void AxBinaryPropertyReader::readPictureProperty( StreamDataSequence& orPicData )
238 if( startNextProperty() )
240 sal_Int16 nData = maInStrm.readAligned< sal_Int16 >();
241 if( ensureValid( nData == -1 ) )
242 maStreamProps.push_back( ComplexPropVector::value_type( new PictureProperty( orPicData ) ) );
246 bool AxBinaryPropertyReader::finalizeImport()
248 // read large properties
249 maInStrm.align( 4 );
250 if( ensureValid( mnPropFlags == 0 ) )
252 for (auto const& largeProp : maLargeProps)
254 if (!ensureValid())
255 break;
256 ensureValid( largeProp->readProperty( maInStrm ) );
257 maInStrm.align( 4 );
260 maInStrm.seek( mnPropsEnd );
262 // read stream properties (no stream alignment between properties!)
263 if( ensureValid() )
265 for (auto const& streamProp : maStreamProps)
267 if (!ensureValid())
268 break;
269 ensureValid( streamProp->readProperty( maInStrm ) );
273 return mbValid;
276 bool AxBinaryPropertyReader::ensureValid( bool bCondition )
278 mbValid = mbValid && bCondition && !maInStrm.isEof();
279 return mbValid;
282 bool AxBinaryPropertyReader::startNextProperty()
284 bool bHasProp = getFlag( mnPropFlags, mnNextProp );
285 setFlag( mnPropFlags, mnNextProp, false );
286 mnNextProp <<= 1;
287 return ensureValid() && bHasProp;
290 } // namespace ole
291 } // namespace oox
293 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */