diff options
Diffstat (limited to 'oox/source/ole/axbinarywriter.cxx')
-rw-r--r-- | oox/source/ole/axbinarywriter.cxx | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/oox/source/ole/axbinarywriter.cxx b/oox/source/ole/axbinarywriter.cxx new file mode 100644 index 000000000..b9c4b66be --- /dev/null +++ b/oox/source/ole/axbinarywriter.cxx @@ -0,0 +1,201 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#include <oox/ole/axbinarywriter.hxx> + +namespace oox::ole { + +namespace { + +const sal_uInt32 AX_STRING_COMPRESSED = 0x80000000; + +} // namespace + +AxAlignedOutputStream::AxAlignedOutputStream( BinaryOutputStream& rOutStrm ) : + BinaryStreamBase( false ), + mpOutStrm( &rOutStrm ), + mnStrmPos( 0 ), + mnStrmSize( rOutStrm.getRemaining() ), + mnWrappedBeginPos( rOutStrm.tell() ) +{ + mbEof = mbEof || rOutStrm.isEof(); +} + +sal_Int64 AxAlignedOutputStream::size() const +{ + return mpOutStrm ? mnStrmSize : -1; +} + +sal_Int64 AxAlignedOutputStream::tell() const +{ + return mpOutStrm ? mnStrmPos : -1; +} + +void AxAlignedOutputStream::seek( sal_Int64 nPos ) +{ + mbEof = (nPos < 0); + if( !mbEof ) + { + mpOutStrm->seek( static_cast< sal_Int32 >( mnWrappedBeginPos + nPos ) ); + mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos; + } +} + +void AxAlignedOutputStream::close() +{ + mpOutStrm = nullptr; + mbEof = true; +} + +void AxAlignedOutputStream::writeData( const StreamDataSequence& orData, size_t nAtomSize ) +{ + mpOutStrm->writeData( orData, nAtomSize ); + mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos; +} + +void AxAlignedOutputStream::writeMemory( const void* opMem, sal_Int32 nBytes, size_t nAtomSize ) +{ + mpOutStrm->writeMemory( opMem, nBytes, nAtomSize ); + mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos; +} + +void AxAlignedOutputStream::pad( sal_Int32 nBytes ) +{ + //PRESUMABLY we need to pad with 0's here as appropriate + css::uno::Sequence< sal_Int8 > aData( nBytes ); + // ok we could be padding with rubbish here, but really that shouldn't matter + // set to 0(s), easier to not get fooled by 0's when looking at + // binary content... + memset( static_cast<void*>( aData.getArray() ), 0, nBytes ); + mpOutStrm->writeData( aData ); + mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos; +} + +void AxAlignedOutputStream::align( size_t nSize ) +{ + pad( static_cast< sal_Int32 >( (nSize - (mnStrmPos % nSize)) % nSize ) ); +} + +namespace { + +void lclWriteString( AxAlignedOutputStream& rOutStrm, OUString const & rValue, sal_uInt32 nSize ) +{ + bool bCompressed = getFlag( nSize, AX_STRING_COMPRESSED ); + rOutStrm.writeCompressedUnicodeArray( rValue, bCompressed ); +} + +} // namespace + +AxBinaryPropertyWriter::ComplexProperty::~ComplexProperty() +{ +} + +bool AxBinaryPropertyWriter::PairProperty::writeProperty( AxAlignedOutputStream& rOutStrm ) +{ + rOutStrm.WriteInt32(mrPairData.first).WriteInt32(mrPairData.second); + return true; +} + +bool AxBinaryPropertyWriter::StringProperty::writeProperty( AxAlignedOutputStream& rOutStrm ) +{ + lclWriteString( rOutStrm, mrValue, mnSize ); + return true; +} + +AxBinaryPropertyWriter::AxBinaryPropertyWriter( BinaryOutputStream& rOutStrm, bool b64BitPropFlags ) : + maOutStrm( rOutStrm ), + mnPropFlags( 0x0 ), + mbValid( true ), + mb64BitPropFlags( b64BitPropFlags ) +{ + sal_uInt16 nId( 0x0200 ); + maOutStrm.WriteUInt16(nId); + mnBlockSize = 0; // will be filled in the finalize method + + maOutStrm.WriteUInt16(nId); + mnPropFlagsStart = maOutStrm.tell(); + + if( mb64BitPropFlags ) + maOutStrm.WriteInt64( mnPropFlags ); + else + maOutStrm.WriteUInt32( mnPropFlags ); + mnNextProp = 1; +} + +void AxBinaryPropertyWriter::writeBoolProperty( bool orbValue ) +{ + // orbValue == bReverse false then we want to set the bit, e.g. don't skip + startNextProperty( !orbValue ); +} + +void AxBinaryPropertyWriter::writePairProperty( AxPairData& orPairData ) +{ + startNextProperty(); + maLargeProps.push_back( ComplexPropVector::value_type( std::make_shared<PairProperty>( orPairData ) ) ); +} + +void AxBinaryPropertyWriter::writeStringProperty( OUString& orValue ) +{ + sal_uInt32 nSize = orValue.getLength() * 2; + setFlag( nSize, AX_STRING_COMPRESSED, false ); + maOutStrm.writeAligned< sal_uInt32 >( nSize ); + maLargeProps.push_back( ComplexPropVector::value_type( std::make_shared<StringProperty>( orValue, nSize ) ) ); + startNextProperty(); +} + +void AxBinaryPropertyWriter::finalizeExport() +{ + // write large properties + maOutStrm.align( 4 ); + for (auto const& largeProp : maLargeProps) + { + if (!ensureValid()) + break; + largeProp->writeProperty( maOutStrm ); + maOutStrm.align( 4 ); + } + + mnBlockSize = maOutStrm.tell() - mnPropFlagsStart; + + // write stream properties (no stream alignment between properties!) + for (auto const& streamProp : maStreamProps) + { + if (!ensureValid()) + break; + streamProp->writeProperty( maOutStrm ); + } + + sal_Int64 nPos = maOutStrm.tell(); + maOutStrm.seek( mnPropFlagsStart - sizeof( mnBlockSize ) ); + + maOutStrm.WriteInt16( mnBlockSize ); + + if( mb64BitPropFlags ) + maOutStrm.WriteInt64( mnPropFlags ); + else + maOutStrm.WriteUInt32( mnPropFlags ); + + maOutStrm.seek( nPos ); +} + +bool AxBinaryPropertyWriter::ensureValid() +{ + mbValid = mbValid && !maOutStrm.isEof(); + return mbValid; +} + +void AxBinaryPropertyWriter::startNextProperty( bool bSkip ) +{ + // if we are skipping then we clear the flag + setFlag( mnPropFlags, mnNextProp, !bSkip ); + mnNextProp <<= 1; +} + +} // namespace oox::ole + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |