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