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