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"
27 // ============================================================================
31 const sal_uInt32 AX_STRING_SIZEMASK
= 0x7FFFFFFF;
32 const sal_uInt32 AX_STRING_COMPRESSED
= 0x80000000;
36 // ============================================================================
38 AxAlignedInputStream::AxAlignedInputStream( BinaryInputStream
& rInStrm
) :
39 BinaryStreamBase( false ),
42 mnStrmSize( rInStrm
.getRemaining() )
44 mbEof
= mbEof
|| rInStrm
.isEof();
47 sal_Int64
AxAlignedInputStream::size() const
49 return mpInStrm
? mnStrmSize
: -1;
52 sal_Int64
AxAlignedInputStream::tell() const
54 return mpInStrm
? mnStrmPos
: -1;
57 void AxAlignedInputStream::seek( sal_Int64 nPos
)
59 mbEof
= mbEof
|| (nPos
< mnStrmPos
);
61 skip( static_cast< sal_Int32
>( nPos
- mnStrmPos
) );
64 void AxAlignedInputStream::close()
70 sal_Int32
AxAlignedInputStream::readData( StreamDataSequence
& orData
, sal_Int32 nBytes
, size_t nAtomSize
)
72 sal_Int32 nReadSize
= 0;
75 nReadSize
= mpInStrm
->readData( orData
, nBytes
, nAtomSize
);
76 mnStrmPos
+= nReadSize
;
77 mbEof
= mpInStrm
->isEof();
82 sal_Int32
AxAlignedInputStream::readMemory( void* opMem
, sal_Int32 nBytes
, size_t nAtomSize
)
84 sal_Int32 nReadSize
= 0;
87 nReadSize
= mpInStrm
->readMemory( opMem
, nBytes
, nAtomSize
);
88 mnStrmPos
+= nReadSize
;
89 mbEof
= mpInStrm
->isEof();
94 void AxAlignedInputStream::skip( sal_Int32 nBytes
, size_t nAtomSize
)
98 mpInStrm
->skip( nBytes
, nAtomSize
);
100 mbEof
= mpInStrm
->isEof();
104 void AxAlignedInputStream::align( size_t nSize
)
106 skip( static_cast< sal_Int32
>( (nSize
- (mnStrmPos
% nSize
)) % nSize
) );
109 // ============================================================================
113 bool lclReadString( AxAlignedInputStream
& rInStrm
, OUString
& rValue
, sal_uInt32 nSize
, bool bArrayString
)
115 bool bCompressed
= getFlag( nSize
, AX_STRING_COMPRESSED
);
116 sal_uInt32 nBufSize
= nSize
& AX_STRING_SIZEMASK
;
117 // Unicode: simple strings store byte count, array strings store char count
118 sal_Int32 nChars
= static_cast< sal_Int32
>( nBufSize
/ ((bCompressed
|| bArrayString
) ? 1 : 2) );
119 bool bValidChars
= nChars
<= 65536;
120 OSL_ENSURE( bValidChars
, "lclReadString - string too long" );
121 sal_Int64 nEndPos
= rInStrm
.tell() + nChars
* (bCompressed
? 1 : 2);
122 nChars
= ::std::min
< sal_Int32
>( nChars
, 65536 );
123 rValue
= rInStrm
.readCompressedUnicodeArray( nChars
, bCompressed
);
124 rInStrm
.seek( nEndPos
);
130 // ----------------------------------------------------------------------------
132 AxBinaryPropertyReader::ComplexProperty::~ComplexProperty()
136 bool AxBinaryPropertyReader::PairProperty::readProperty( AxAlignedInputStream
& rInStrm
)
138 rInStrm
>> mrPairData
.first
>> mrPairData
.second
;
142 bool AxBinaryPropertyReader::StringProperty::readProperty( AxAlignedInputStream
& rInStrm
)
144 return lclReadString( rInStrm
, mrValue
, mnSize
, false );
147 bool AxBinaryPropertyReader::ArrayStringProperty::readProperty( AxAlignedInputStream
& rInStrm
)
149 sal_Int64 nEndPos
= rInStrm
.tell() + mnSize
;
150 while( rInStrm
.tell() < nEndPos
)
153 if( !lclReadString( rInStrm
, aString
, rInStrm
.readuInt32(), true ) )
155 mrArray
.push_back( aString
);
156 // every array string is aligned on 4 byte boundries
162 bool AxBinaryPropertyReader::GuidProperty::readProperty( AxAlignedInputStream
& rInStrm
)
164 mrGuid
= OleHelper::importGuid( rInStrm
);
168 bool AxBinaryPropertyReader::FontProperty::readProperty( AxAlignedInputStream
& rInStrm
)
170 return mrFontData
.importGuidAndFont( rInStrm
);
173 bool AxBinaryPropertyReader::PictureProperty::readProperty( AxAlignedInputStream
& rInStrm
)
175 return OleHelper::importStdPic( mrPicData
, rInStrm
, true );
178 // ----------------------------------------------------------------------------
180 AxBinaryPropertyReader::AxBinaryPropertyReader( BinaryInputStream
& rInStrm
, bool b64BitPropFlags
) :
184 // version and size of property block
186 sal_uInt16 nBlockSize
= maInStrm
.readValue
< sal_uInt16
>();
187 mnPropsEnd
= maInStrm
.tell() + nBlockSize
;
188 // flagfield containing existing properties
189 if( b64BitPropFlags
)
190 maInStrm
>> mnPropFlags
;
192 mnPropFlags
= maInStrm
.readuInt32();
196 void AxBinaryPropertyReader::readBoolProperty( bool& orbValue
, bool bReverse
)
198 // there is no data, the boolean value is equivalent to the property flag itself
199 orbValue
= startNextProperty() != bReverse
;
202 void AxBinaryPropertyReader::readPairProperty( AxPairData
& orPairData
)
204 if( startNextProperty() )
205 maLargeProps
.push_back( ComplexPropVector::value_type( new PairProperty( orPairData
) ) );
208 void AxBinaryPropertyReader::readStringProperty( OUString
& orValue
)
210 if( startNextProperty() )
212 sal_uInt32 nSize
= maInStrm
.readAligned
< sal_uInt32
>();
213 maLargeProps
.push_back( ComplexPropVector::value_type( new StringProperty( orValue
, nSize
) ) );
217 void AxBinaryPropertyReader::readArrayStringProperty( std::vector
<OUString
>& orValue
)
219 if( startNextProperty() )
221 sal_uInt32 nSize
= maInStrm
.readAligned
< sal_uInt32
>();
222 maLargeProps
.push_back( ComplexPropVector::value_type( new ArrayStringProperty( orValue
, nSize
) ) );
226 void AxBinaryPropertyReader::readGuidProperty( OUString
& orGuid
)
228 if( startNextProperty() )
229 maLargeProps
.push_back( ComplexPropVector::value_type( new GuidProperty( orGuid
) ) );
232 void AxBinaryPropertyReader::readFontProperty( AxFontData
& orFontData
)
234 if( startNextProperty() )
236 sal_Int16 nData
= maInStrm
.readAligned
< sal_Int16
>();
237 if( ensureValid( nData
== -1 ) )
238 maStreamProps
.push_back( ComplexPropVector::value_type( new FontProperty( orFontData
) ) );
242 void AxBinaryPropertyReader::readPictureProperty( StreamDataSequence
& orPicData
)
244 if( startNextProperty() )
246 sal_Int16 nData
= maInStrm
.readAligned
< sal_Int16
>();
247 if( ensureValid( nData
== -1 ) )
248 maStreamProps
.push_back( ComplexPropVector::value_type( new PictureProperty( orPicData
) ) );
252 bool AxBinaryPropertyReader::finalizeImport()
254 // read large properties
256 if( ensureValid( mnPropFlags
== 0 ) && !maLargeProps
.empty() )
258 for( ComplexPropVector::iterator aIt
= maLargeProps
.begin(), aEnd
= maLargeProps
.end(); ensureValid() && (aIt
!= aEnd
); ++aIt
)
260 ensureValid( (*aIt
)->readProperty( maInStrm
) );
264 maInStrm
.seek( mnPropsEnd
);
266 // read stream properties (no stream alignment between properties!)
267 if( ensureValid() && !maStreamProps
.empty() )
268 for( ComplexPropVector::iterator aIt
= maStreamProps
.begin(), aEnd
= maStreamProps
.end(); ensureValid() && (aIt
!= aEnd
); ++aIt
)
269 ensureValid( (*aIt
)->readProperty( maInStrm
) );
274 bool AxBinaryPropertyReader::ensureValid( bool bCondition
)
276 mbValid
= mbValid
&& bCondition
&& !maInStrm
.isEof();
280 bool AxBinaryPropertyReader::startNextProperty()
282 bool bHasProp
= getFlag( mnPropFlags
, mnNextProp
);
283 setFlag( mnPropFlags
, mnNextProp
, false );
285 return ensureValid() && bHasProp
;
288 // ============================================================================
293 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */