1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/olehelper.hxx"
24 #include <osl/diagnose.h>
31 const sal_uInt32 AX_STRING_SIZEMASK
= 0x7FFFFFFF;
32 const sal_uInt32 AX_STRING_COMPRESSED
= 0x80000000;
36 AxAlignedInputStream::AxAlignedInputStream( BinaryInputStream
& rInStrm
) :
37 BinaryStreamBase( false ),
40 mnStrmSize( rInStrm
.getRemaining() )
42 mbEof
= mbEof
|| rInStrm
.isEof();
45 sal_Int64
AxAlignedInputStream::size() const
47 return mpInStrm
? mnStrmSize
: -1;
50 sal_Int64
AxAlignedInputStream::tell() const
52 return mpInStrm
? mnStrmPos
: -1;
55 void AxAlignedInputStream::seek( sal_Int64 nPos
)
57 mbEof
= mbEof
|| (nPos
< mnStrmPos
);
59 skip( static_cast< sal_Int32
>( nPos
- mnStrmPos
) );
62 void AxAlignedInputStream::close()
68 sal_Int32
AxAlignedInputStream::readData( StreamDataSequence
& orData
, sal_Int32 nBytes
, size_t nAtomSize
)
70 sal_Int32 nReadSize
= 0;
73 nReadSize
= mpInStrm
->readData( orData
, nBytes
, nAtomSize
);
74 mnStrmPos
+= nReadSize
;
75 mbEof
= mpInStrm
->isEof();
80 sal_Int32
AxAlignedInputStream::readMemory( void* opMem
, sal_Int32 nBytes
, size_t nAtomSize
)
82 sal_Int32 nReadSize
= 0;
85 nReadSize
= mpInStrm
->readMemory( opMem
, nBytes
, nAtomSize
);
86 mnStrmPos
+= nReadSize
;
87 mbEof
= mpInStrm
->isEof();
92 void AxAlignedInputStream::skip( sal_Int32 nBytes
, size_t nAtomSize
)
96 mpInStrm
->skip( nBytes
, nAtomSize
);
98 mbEof
= mpInStrm
->isEof();
102 void AxAlignedInputStream::align( size_t nSize
)
104 skip( static_cast< sal_Int32
>( (nSize
- (mnStrmPos
% nSize
)) % nSize
) );
109 bool lclReadString( AxAlignedInputStream
& rInStrm
, OUString
& rValue
, sal_uInt32 nSize
, bool bArrayString
)
111 bool bCompressed
= getFlag( nSize
, AX_STRING_COMPRESSED
);
112 sal_uInt32 nBufSize
= nSize
& AX_STRING_SIZEMASK
;
113 // Unicode: simple strings store byte count, array strings store char count
114 sal_Int32 nChars
= static_cast< sal_Int32
>( nBufSize
/ ((bCompressed
|| bArrayString
) ? 1 : 2) );
115 bool bValidChars
= nChars
<= 65536;
116 OSL_ENSURE( bValidChars
, "lclReadString - string too long" );
117 sal_Int64 nEndPos
= rInStrm
.tell() + nChars
* (bCompressed
? 1 : 2);
118 nChars
= ::std::min
< sal_Int32
>( nChars
, 65536 );
119 rValue
= rInStrm
.readCompressedUnicodeArray( nChars
, bCompressed
);
120 rInStrm
.seek( nEndPos
);
126 AxBinaryPropertyReader::ComplexProperty::~ComplexProperty()
130 bool AxBinaryPropertyReader::PairProperty::readProperty( AxAlignedInputStream
& rInStrm
)
132 mrPairData
.first
= rInStrm
.readInt32();
133 mrPairData
.second
= rInStrm
.readInt32();
137 bool AxBinaryPropertyReader::StringProperty::readProperty( AxAlignedInputStream
& rInStrm
)
139 return lclReadString( rInStrm
, mrValue
, mnSize
, false );
142 bool AxBinaryPropertyReader::ArrayStringProperty::readProperty( AxAlignedInputStream
& rInStrm
)
144 sal_Int64 nEndPos
= rInStrm
.tell() + mnSize
;
145 while( rInStrm
.tell() < nEndPos
)
148 if( !lclReadString( rInStrm
, aString
, rInStrm
.readuInt32(), true ) )
150 mrArray
.push_back( aString
);
151 // every array string is aligned on 4 byte boundries
157 bool AxBinaryPropertyReader::GuidProperty::readProperty( AxAlignedInputStream
& rInStrm
)
159 mrGuid
= OleHelper::importGuid( rInStrm
);
163 bool AxBinaryPropertyReader::FontProperty::readProperty( AxAlignedInputStream
& rInStrm
)
165 return mrFontData
.importGuidAndFont( rInStrm
);
168 bool AxBinaryPropertyReader::PictureProperty::readProperty( AxAlignedInputStream
& rInStrm
)
170 return OleHelper::importStdPic( mrPicData
, rInStrm
, true );
173 AxBinaryPropertyReader::AxBinaryPropertyReader( BinaryInputStream
& rInStrm
, bool b64BitPropFlags
) :
177 // version and size of property block
179 sal_uInt16 nBlockSize
= maInStrm
.readuInt16();
180 mnPropsEnd
= maInStrm
.tell() + nBlockSize
;
181 // flagfield containing existing properties
182 if( b64BitPropFlags
)
183 mnPropFlags
= maInStrm
.readInt64();
185 mnPropFlags
= maInStrm
.readuInt32();
189 void AxBinaryPropertyReader::readBoolProperty( bool& orbValue
, bool bReverse
)
191 // there is no data, the boolean value is equivalent to the property flag itself
192 orbValue
= startNextProperty() != bReverse
;
195 void AxBinaryPropertyReader::readPairProperty( AxPairData
& orPairData
)
197 if( startNextProperty() )
198 maLargeProps
.push_back( ComplexPropVector::value_type( new PairProperty( orPairData
) ) );
201 void AxBinaryPropertyReader::readStringProperty( OUString
& orValue
)
203 if( startNextProperty() )
205 sal_uInt32 nSize
= maInStrm
.readAligned
< sal_uInt32
>();
206 maLargeProps
.push_back( ComplexPropVector::value_type( new StringProperty( orValue
, nSize
) ) );
210 void AxBinaryPropertyReader::readArrayStringProperty( std::vector
<OUString
>& orValue
)
212 if( startNextProperty() )
214 sal_uInt32 nSize
= maInStrm
.readAligned
< sal_uInt32
>();
215 maLargeProps
.push_back( ComplexPropVector::value_type( new ArrayStringProperty( orValue
, nSize
) ) );
219 void AxBinaryPropertyReader::readGuidProperty( OUString
& orGuid
)
221 if( startNextProperty() )
222 maLargeProps
.push_back( ComplexPropVector::value_type( new GuidProperty( orGuid
) ) );
225 void AxBinaryPropertyReader::readFontProperty( AxFontData
& orFontData
)
227 if( startNextProperty() )
229 sal_Int16 nData
= maInStrm
.readAligned
< sal_Int16
>();
230 if( ensureValid( nData
== -1 ) )
231 maStreamProps
.push_back( ComplexPropVector::value_type( new FontProperty( orFontData
) ) );
235 void AxBinaryPropertyReader::readPictureProperty( StreamDataSequence
& orPicData
)
237 if( startNextProperty() )
239 sal_Int16 nData
= maInStrm
.readAligned
< sal_Int16
>();
240 if( ensureValid( nData
== -1 ) )
241 maStreamProps
.push_back( ComplexPropVector::value_type( new PictureProperty( orPicData
) ) );
245 bool AxBinaryPropertyReader::finalizeImport()
247 // read large properties
249 if( ensureValid( mnPropFlags
== 0 ) && !maLargeProps
.empty() )
251 for( ComplexPropVector::iterator aIt
= maLargeProps
.begin(), aEnd
= maLargeProps
.end(); ensureValid() && (aIt
!= aEnd
); ++aIt
)
253 ensureValid( (*aIt
)->readProperty( maInStrm
) );
257 maInStrm
.seek( mnPropsEnd
);
259 // read stream properties (no stream alignment between properties!)
260 if( ensureValid() && !maStreamProps
.empty() )
261 for( ComplexPropVector::iterator aIt
= maStreamProps
.begin(), aEnd
= maStreamProps
.end(); ensureValid() && (aIt
!= aEnd
); ++aIt
)
262 ensureValid( (*aIt
)->readProperty( maInStrm
) );
267 bool AxBinaryPropertyReader::ensureValid( bool bCondition
)
269 mbValid
= mbValid
&& bCondition
&& !maInStrm
.isEof();
273 bool AxBinaryPropertyReader::startNextProperty()
275 bool bHasProp
= getFlag( mnPropFlags
, mnNextProp
);
276 setFlag( mnPropFlags
, mnNextProp
, false );
278 return ensureValid() && bHasProp
;
284 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */