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 #include "oox/ole/axbinarywriter.hxx"
11 #include "oox/ole/olehelper.hxx"
16 // ============================================================================
20 const sal_uInt32 AX_STRING_SIZEMASK
= 0x7FFFFFFF;
21 const sal_uInt32 AX_STRING_COMPRESSED
= 0x80000000;
25 // ============================================================================
27 AxAlignedOutputStream::AxAlignedOutputStream( BinaryOutputStream
& rOutStrm
) :
28 BinaryStreamBase( false ),
29 mpOutStrm( &rOutStrm
),
31 mnStrmSize( rOutStrm
.getRemaining() ),
32 mnWrappedBeginPos( rOutStrm
.tell() )
34 mbEof
= mbEof
|| rOutStrm
.isEof();
37 sal_Int64
AxAlignedOutputStream::size() const
39 return mpOutStrm
? mnStrmSize
: -1;
42 sal_Int64
AxAlignedOutputStream::tell() const
44 return mpOutStrm
? mnStrmPos
: -1;
47 void AxAlignedOutputStream::seek( sal_Int64 nPos
)
52 mpOutStrm
->seek( static_cast< sal_Int32
>( mnWrappedBeginPos
+ nPos
) );
53 mnStrmPos
= mpOutStrm
->tell() - mnWrappedBeginPos
;
57 void AxAlignedOutputStream::close()
63 void AxAlignedOutputStream::writeData( const StreamDataSequence
& orData
, size_t nAtomSize
)
65 mpOutStrm
->writeData( orData
, nAtomSize
);
66 mnStrmPos
= mpOutStrm
->tell() - mnWrappedBeginPos
;
69 void AxAlignedOutputStream::writeMemory( const void* opMem
, sal_Int32 nBytes
, size_t nAtomSize
)
71 mpOutStrm
->writeMemory( opMem
, nBytes
, nAtomSize
);
72 mnStrmPos
= mpOutStrm
->tell() - mnWrappedBeginPos
;
75 void AxAlignedOutputStream::pad( sal_Int32 nBytes
, size_t nAtomSize
)
77 //PRESUMABELY we need to pad with 0's here as appropriate
78 com::sun::star::uno::Sequence
< sal_Int8
> aData( nBytes
);
79 // ok we could be padding with rubbish here, but really that shouldn't matter
80 // set to 0(s), easier to not get fooled by 0's when looking at
81 // binary content......
82 memset( static_cast<void*>( aData
.getArray() ), 0, nBytes
);
83 mpOutStrm
->writeData( aData
, nAtomSize
);
84 mnStrmPos
= mpOutStrm
->tell() - mnWrappedBeginPos
;
87 void AxAlignedOutputStream::align( size_t nSize
)
89 pad( static_cast< sal_Int32
>( (nSize
- (mnStrmPos
% nSize
)) % nSize
) );
92 // ============================================================================
96 void lclWriteString( AxAlignedOutputStream
& rOutStrm
, OUString
& rValue
, sal_uInt32 nSize
, bool bArrayString
)
98 bool bCompressed
= getFlag( nSize
, AX_STRING_COMPRESSED
);
99 rOutStrm
.writeCompressedUnicodeArray( rValue
, bCompressed
|| bArrayString
);
104 // ----------------------------------------------------------------------------
106 AxBinaryPropertyWriter::ComplexProperty::~ComplexProperty()
110 bool AxBinaryPropertyWriter::PairProperty::writeProperty( AxAlignedOutputStream
& rOutStrm
)
112 rOutStrm
<< mrPairData
.first
<< mrPairData
.second
;
116 bool AxBinaryPropertyWriter::StringProperty::writeProperty( AxAlignedOutputStream
& rOutStrm
)
118 lclWriteString( rOutStrm
, mrValue
, mnSize
, false );
122 // ----------------------------------------------------------------------------
124 AxBinaryPropertyWriter::AxBinaryPropertyWriter( BinaryOutputStream
& rOutStrm
, bool b64BitPropFlags
) :
125 maOutStrm( rOutStrm
),
128 mb64BitPropFlags( b64BitPropFlags
)
130 sal_uInt16
nId( 0x0200 );
132 mnBlockSize
= 0; // will be filled in the finalize method
135 mnPropFlagsStart
= maOutStrm
.tell();
137 if( mb64BitPropFlags
)
138 maOutStrm
<< mnPropFlags
;
140 maOutStrm
<< sal_uInt32( mnPropFlags
);
144 void AxBinaryPropertyWriter::writeBoolProperty( bool orbValue
, bool bReverse
)
146 // orbValue ^ bReverse true then we want to set the bit, e.g. don't skip
147 startNextProperty( !( ( orbValue
^ bReverse
) >= 1 ) );
150 void AxBinaryPropertyWriter::writePairProperty( AxPairData
& orPairData
)
152 if( startNextProperty() )
153 maLargeProps
.push_back( ComplexPropVector::value_type( new PairProperty( orPairData
) ) );
156 void AxBinaryPropertyWriter::writeStringProperty( OUString
& orValue
, bool bCompressed
)
158 sal_uInt32 nSize
= orValue
.getLength();
160 setFlag( nSize
, AX_STRING_COMPRESSED
);
163 maOutStrm
.writeAligned
< sal_uInt32
>( nSize
);
164 maLargeProps
.push_back( ComplexPropVector::value_type( new StringProperty( orValue
, nSize
) ) );
168 bool AxBinaryPropertyWriter::finalizeExport()
170 // write large properties
171 maOutStrm
.align( 4 );
172 if( !maLargeProps
.empty() )
174 for( ComplexPropVector::iterator aIt
= maLargeProps
.begin(), aEnd
= maLargeProps
.end(); ensureValid() && (aIt
!= aEnd
); ++aIt
)
176 (*aIt
)->writeProperty( maOutStrm
);
177 maOutStrm
.align( 4 );
181 mnBlockSize
= maOutStrm
.tell() - mnPropFlagsStart
;
183 // write stream properties (no stream alignment between properties!)
184 if( !maStreamProps
.empty() )
185 for( ComplexPropVector::iterator aIt
= maStreamProps
.begin(), aEnd
= maStreamProps
.end(); ensureValid() && (aIt
!= aEnd
); ++aIt
)
186 (*aIt
)->writeProperty( maOutStrm
);
188 sal_Int64 nPos
= maOutStrm
.tell();
189 maOutStrm
.seek( mnPropFlagsStart
- sizeof( mnBlockSize
) );
191 maOutStrm
<< mnBlockSize
;
193 if( mb64BitPropFlags
)
194 maOutStrm
<< mnPropFlags
;
196 maOutStrm
<< sal_uInt32( mnPropFlags
);
198 maOutStrm
.seek( nPos
);
202 bool AxBinaryPropertyWriter::ensureValid( bool bCondition
)
204 mbValid
= mbValid
&& bCondition
&& !maOutStrm
.isEof();
208 bool AxBinaryPropertyWriter::startNextProperty( bool bSkip
)
210 // if we are skipping then we clear the flag
211 setFlag( mnPropFlags
, mnNextProp
, !bSkip
);
216 // ============================================================================
221 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */