Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : */
9 : #include "oox/ole/axbinarywriter.hxx"
10 :
11 : #include "oox/ole/olehelper.hxx"
12 :
13 : namespace oox {
14 : namespace ole {
15 :
16 : namespace {
17 :
18 : const sal_uInt32 AX_STRING_COMPRESSED = 0x80000000;
19 :
20 : } // namespace
21 :
22 4 : AxAlignedOutputStream::AxAlignedOutputStream( BinaryOutputStream& rOutStrm ) :
23 : BinaryStreamBase( false ),
24 : mpOutStrm( &rOutStrm ),
25 : mnStrmPos( 0 ),
26 4 : mnStrmSize( rOutStrm.getRemaining() ),
27 8 : mnWrappedBeginPos( rOutStrm.tell() )
28 : {
29 4 : mbEof = mbEof || rOutStrm.isEof();
30 4 : }
31 :
32 0 : sal_Int64 AxAlignedOutputStream::size() const
33 : {
34 0 : return mpOutStrm ? mnStrmSize : -1;
35 : }
36 :
37 12 : sal_Int64 AxAlignedOutputStream::tell() const
38 : {
39 12 : return mpOutStrm ? mnStrmPos : -1;
40 : }
41 :
42 8 : void AxAlignedOutputStream::seek( sal_Int64 nPos )
43 : {
44 8 : mbEof = (nPos < 0);
45 8 : if( !mbEof )
46 : {
47 8 : mpOutStrm->seek( static_cast< sal_Int32 >( mnWrappedBeginPos + nPos ) );
48 8 : mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
49 : }
50 8 : }
51 :
52 0 : void AxAlignedOutputStream::close()
53 : {
54 0 : mpOutStrm = 0;
55 0 : mbEof = true;
56 0 : }
57 :
58 0 : void AxAlignedOutputStream::writeData( const StreamDataSequence& orData, size_t nAtomSize )
59 : {
60 0 : mpOutStrm->writeData( orData, nAtomSize );
61 0 : mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
62 0 : }
63 :
64 52 : void AxAlignedOutputStream::writeMemory( const void* opMem, sal_Int32 nBytes, size_t nAtomSize )
65 : {
66 52 : mpOutStrm->writeMemory( opMem, nBytes, nAtomSize );
67 52 : mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
68 52 : }
69 :
70 34 : void AxAlignedOutputStream::pad( sal_Int32 nBytes, size_t nAtomSize )
71 : {
72 : //PRESUMABELY we need to pad with 0's here as appropriate
73 34 : com::sun::star::uno::Sequence< sal_Int8 > aData( nBytes );
74 : // ok we could be padding with rubbish here, but really that shouldn't matter
75 : // set to 0(s), easier to not get fooled by 0's when looking at
76 : // binary content......
77 34 : memset( static_cast<void*>( aData.getArray() ), 0, nBytes );
78 34 : mpOutStrm->writeData( aData, nAtomSize );
79 34 : mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
80 34 : }
81 :
82 34 : void AxAlignedOutputStream::align( size_t nSize )
83 : {
84 34 : pad( static_cast< sal_Int32 >( (nSize - (mnStrmPos % nSize)) % nSize ) );
85 34 : }
86 :
87 : namespace {
88 :
89 4 : void lclWriteString( AxAlignedOutputStream& rOutStrm, OUString& rValue, sal_uInt32 nSize, bool bArrayString )
90 : {
91 4 : bool bCompressed = getFlag( nSize, AX_STRING_COMPRESSED );
92 4 : rOutStrm.writeCompressedUnicodeArray( rValue, bCompressed || bArrayString );
93 4 : }
94 :
95 : } // namespace
96 :
97 6 : AxBinaryPropertyWriter::ComplexProperty::~ComplexProperty()
98 : {
99 6 : }
100 :
101 2 : bool AxBinaryPropertyWriter::PairProperty::writeProperty( AxAlignedOutputStream& rOutStrm )
102 : {
103 2 : rOutStrm << mrPairData.first << mrPairData.second;
104 2 : return true;
105 : }
106 :
107 4 : bool AxBinaryPropertyWriter::StringProperty::writeProperty( AxAlignedOutputStream& rOutStrm )
108 : {
109 4 : lclWriteString( rOutStrm, mrValue, mnSize, false );
110 4 : return true;
111 : }
112 :
113 4 : AxBinaryPropertyWriter::AxBinaryPropertyWriter( BinaryOutputStream& rOutStrm, bool b64BitPropFlags ) :
114 : maOutStrm( rOutStrm ),
115 : mnPropFlags( 0x0 ),
116 : mbValid( true ),
117 4 : mb64BitPropFlags( b64BitPropFlags )
118 : {
119 4 : sal_uInt16 nId( 0x0200 );
120 4 : maOutStrm << nId;
121 4 : mnBlockSize = 0; // will be filled in the finalize method
122 :
123 4 : maOutStrm << nId;
124 4 : mnPropFlagsStart = maOutStrm.tell();
125 :
126 4 : if( mb64BitPropFlags )
127 2 : maOutStrm << mnPropFlags;
128 : else
129 2 : maOutStrm << sal_uInt32( mnPropFlags );
130 4 : mnNextProp = 1;
131 4 : }
132 :
133 2 : void AxBinaryPropertyWriter::writeBoolProperty( bool orbValue, bool bReverse )
134 : {
135 : // orbValue == bReverse false then we want to set the bit, e.g. don't skip
136 2 : startNextProperty( orbValue == bReverse );
137 2 : }
138 :
139 2 : void AxBinaryPropertyWriter::writePairProperty( AxPairData& orPairData )
140 : {
141 2 : if( startNextProperty() )
142 2 : maLargeProps.push_back( ComplexPropVector::value_type( new PairProperty( orPairData ) ) );
143 2 : }
144 :
145 4 : void AxBinaryPropertyWriter::writeStringProperty( OUString& orValue, bool bCompressed )
146 : {
147 4 : sal_uInt32 nSize = orValue.getLength();
148 4 : if ( bCompressed )
149 4 : setFlag( nSize, AX_STRING_COMPRESSED );
150 : else
151 0 : nSize *= 2;
152 4 : maOutStrm.writeAligned< sal_uInt32 >( nSize );
153 4 : maLargeProps.push_back( ComplexPropVector::value_type( new StringProperty( orValue, nSize ) ) );
154 4 : startNextProperty();
155 4 : }
156 :
157 4 : bool AxBinaryPropertyWriter::finalizeExport()
158 : {
159 : // write large properties
160 4 : maOutStrm.align( 4 );
161 4 : if( !maLargeProps.empty() )
162 : {
163 10 : for( ComplexPropVector::iterator aIt = maLargeProps.begin(), aEnd = maLargeProps.end(); ensureValid() && (aIt != aEnd); ++aIt )
164 : {
165 6 : (*aIt)->writeProperty( maOutStrm );
166 6 : maOutStrm.align( 4 );
167 : }
168 : }
169 :
170 4 : mnBlockSize = maOutStrm.tell() - mnPropFlagsStart;
171 :
172 : // write stream properties (no stream alignment between properties!)
173 4 : if( !maStreamProps.empty() )
174 0 : for( ComplexPropVector::iterator aIt = maStreamProps.begin(), aEnd = maStreamProps.end(); ensureValid() && (aIt != aEnd); ++aIt )
175 0 : (*aIt)->writeProperty( maOutStrm );
176 :
177 4 : sal_Int64 nPos = maOutStrm.tell();
178 4 : maOutStrm.seek( mnPropFlagsStart - sizeof( mnBlockSize ) );
179 :
180 4 : maOutStrm << mnBlockSize;
181 :
182 4 : if( mb64BitPropFlags )
183 2 : maOutStrm << mnPropFlags;
184 : else
185 2 : maOutStrm << sal_uInt32( mnPropFlags );
186 :
187 4 : maOutStrm.seek( nPos );
188 4 : return true;
189 : }
190 :
191 10 : bool AxBinaryPropertyWriter::ensureValid( bool bCondition )
192 : {
193 10 : mbValid = mbValid && bCondition && !maOutStrm.isEof();
194 10 : return mbValid;
195 : }
196 :
197 82 : bool AxBinaryPropertyWriter::startNextProperty( bool bSkip )
198 : {
199 : // if we are skipping then we clear the flag
200 82 : setFlag( mnPropFlags, mnNextProp, !bSkip );
201 82 : mnNextProp <<= 1;
202 82 : return true;
203 : }
204 :
205 : } // namespace exp
206 408 : } // namespace ole
207 :
208 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|