Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * Version: MPL 1.1 / GPLv3+ / LGPLv3+
4 : : *
5 : : * The contents of this file are subject to the Mozilla Public License Version
6 : : * 1.1 (the "License"); you may not use this file except in compliance with
7 : : * the License or as specified alternatively below. You may obtain a copy of
8 : : * the License at http://www.mozilla.org/MPL/
9 : : *
10 : : * Software distributed under the License is distributed on an "AS IS" basis,
11 : : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : : * for the specific language governing rights and limitations under the
13 : : * License.
14 : : *
15 : : * Major Contributor(s):
16 : : * [ Copyright (C) 2011 Noel Power <noel.power@suse.com> (initial developer) ]
17 : : *
18 : : * All Rights Reserved.
19 : : *
20 : : * For minor contributions see the git repository.
21 : : *
22 : : * Alternatively, the contents of this file may be used under the terms of
23 : : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
24 : : * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
25 : : * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
26 : : * instead of those above.
27 : : */
28 : : #include "oox/ole/axbinarywriter.hxx"
29 : :
30 : : #include "oox/ole/olehelper.hxx"
31 : :
32 : : namespace oox {
33 : : namespace ole {
34 : :
35 : : // ============================================================================
36 : :
37 : : using ::rtl::OUString;
38 : :
39 : : // ============================================================================
40 : :
41 : : namespace {
42 : :
43 : : const sal_uInt32 AX_STRING_SIZEMASK = 0x7FFFFFFF;
44 : : const sal_uInt32 AX_STRING_COMPRESSED = 0x80000000;
45 : :
46 : : } // namespace
47 : :
48 : : // ============================================================================
49 : :
50 : 6 : AxAlignedOutputStream::AxAlignedOutputStream( BinaryOutputStream& rOutStrm ) :
51 : : BinaryStreamBase( false ),
52 : : mpOutStrm( &rOutStrm ),
53 : : mnStrmPos( 0 ),
54 [ + - ][ # # ]: 6 : mnStrmSize( rOutStrm.getRemaining() ),
55 [ + - ][ + - ]: 12 : mnWrappedBeginPos( rOutStrm.tell() )
[ # # ][ # # ]
56 : : {
57 [ + - ][ - + ]: 6 : mbEof = mbEof || rOutStrm.isEof();
[ # # ][ # # ]
58 : 6 : }
59 : :
60 : 0 : sal_Int64 AxAlignedOutputStream::size() const
61 : : {
62 [ # # ]: 0 : return mpOutStrm ? mnStrmSize : -1;
63 : : }
64 : :
65 : 18 : sal_Int64 AxAlignedOutputStream::tell() const
66 : : {
67 [ + - ]: 18 : return mpOutStrm ? mnStrmPos : -1;
68 : : }
69 : :
70 : 12 : void AxAlignedOutputStream::seek( sal_Int64 nPos )
71 : : {
72 : 12 : mbEof = (nPos < 0);
73 [ + - ]: 12 : if( !mbEof )
74 : : {
75 : 12 : mpOutStrm->seek( static_cast< sal_Int32 >( mnWrappedBeginPos + nPos ) );
76 : 12 : mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
77 : : }
78 : 12 : }
79 : :
80 : 0 : void AxAlignedOutputStream::close()
81 : : {
82 : 0 : mpOutStrm = 0;
83 : 0 : mbEof = true;
84 : 0 : }
85 : :
86 : 0 : void AxAlignedOutputStream::writeData( const StreamDataSequence& orData, size_t nAtomSize )
87 : : {
88 : 0 : mpOutStrm->writeData( orData, nAtomSize );
89 : 0 : mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
90 : 0 : }
91 : :
92 : 105 : void AxAlignedOutputStream::writeMemory( const void* opMem, sal_Int32 nBytes, size_t nAtomSize )
93 : : {
94 : 105 : mpOutStrm->writeMemory( opMem, nBytes, nAtomSize );
95 : 105 : mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
96 : 105 : }
97 : :
98 : 78 : void AxAlignedOutputStream::pad( sal_Int32 nBytes, size_t nAtomSize )
99 : : {
100 : : //PRESUMABELY we need to pad with 0's here as appropriate
101 [ + - ]: 78 : com::sun::star::uno::Sequence< sal_Int8 > aData( nBytes );
102 : : // ok we could be padding with rubbish here, but really that shouldn't matter
103 : : // set to 0(s), easier to not get fooled by 0's when looking at
104 : : // binary content......
105 [ + - ]: 78 : memset( static_cast<void*>( aData.getArray() ), 0, nBytes );
106 [ + - ]: 78 : mpOutStrm->writeData( aData, nAtomSize );
107 [ + - ][ + - ]: 78 : mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
108 : 78 : }
109 : :
110 : 78 : void AxAlignedOutputStream::align( size_t nSize )
111 : : {
112 : 78 : pad( static_cast< sal_Int32 >( (nSize - (mnStrmPos % nSize)) % nSize ) );
113 : 78 : }
114 : :
115 : : // ============================================================================
116 : :
117 : : namespace {
118 : :
119 : 12 : void lclWriteString( AxAlignedOutputStream& rOutStrm, OUString& rValue, sal_uInt32 nSize, bool bArrayString )
120 : : {
121 : 12 : bool bCompressed = getFlag( nSize, AX_STRING_COMPRESSED );
122 [ # # ][ - + ]: 12 : rOutStrm.writeCompressedUnicodeArray( rValue, bCompressed || bArrayString );
123 : 12 : }
124 : :
125 : : } // namespace
126 : :
127 : : // ----------------------------------------------------------------------------
128 : :
129 : 15 : AxBinaryPropertyWriter::ComplexProperty::~ComplexProperty()
130 : : {
131 [ - + ]: 15 : }
132 : :
133 : 3 : bool AxBinaryPropertyWriter::PairProperty::writeProperty( AxAlignedOutputStream& rOutStrm )
134 : : {
135 : 3 : rOutStrm << mrPairData.first << mrPairData.second;
136 : 3 : return true;
137 : : }
138 : :
139 : 12 : bool AxBinaryPropertyWriter::StringProperty::writeProperty( AxAlignedOutputStream& rOutStrm )
140 : : {
141 : 12 : lclWriteString( rOutStrm, mrValue, mnSize, false );
142 : 12 : return true;
143 : : }
144 : :
145 : : // ----------------------------------------------------------------------------
146 : :
147 : 6 : AxBinaryPropertyWriter::AxBinaryPropertyWriter( BinaryOutputStream& rOutStrm, bool b64BitPropFlags ) :
148 : : maOutStrm( rOutStrm ),
149 : : mnPropFlags( 0x0 ),
150 : : mbValid( true ),
151 [ + - ][ + - ]: 6 : mb64BitPropFlags( b64BitPropFlags )
[ + - ][ + - ]
152 : : {
153 : 6 : sal_uInt16 nId( 0x0200 );
154 [ + - ]: 6 : maOutStrm << nId;
155 : 6 : mnBlockSize = 0; // will be filled in the finalize method
156 : :
157 [ + - ]: 6 : maOutStrm << nId;
158 : 6 : mnPropFlagsStart = maOutStrm.tell();
159 : :
160 [ + + ]: 6 : if( mb64BitPropFlags )
161 [ + - ]: 3 : maOutStrm << mnPropFlags;
162 : : else
163 [ + - ]: 3 : maOutStrm << sal_uInt32( mnPropFlags );
164 : 6 : mnNextProp = 1;
165 : 6 : }
166 : :
167 : 3 : void AxBinaryPropertyWriter::writeBoolProperty( bool orbValue, bool bReverse )
168 : : {
169 : : // orbValue ^ bReverse true then we want to set the bit, e.g. don't skip
170 : 3 : startNextProperty( !( ( orbValue ^ bReverse ) >= 1 ) );
171 : 3 : }
172 : :
173 : 3 : void AxBinaryPropertyWriter::writePairProperty( AxPairData& orPairData )
174 : : {
175 [ + - ]: 3 : if( startNextProperty() )
176 [ + - ][ + - ]: 3 : maLargeProps.push_back( ComplexPropVector::value_type( new PairProperty( orPairData ) ) );
177 : 3 : }
178 : :
179 : 12 : void AxBinaryPropertyWriter::writeStringProperty( OUString& orValue, bool bCompressed )
180 : : {
181 : 12 : sal_uInt32 nSize = orValue.getLength();
182 [ + - ]: 12 : if ( bCompressed )
183 : 12 : setFlag( nSize, AX_STRING_COMPRESSED );
184 : : else
185 : 0 : nSize *= 2;
186 [ + - ]: 12 : maOutStrm.writeAligned< sal_uInt32 >( nSize );
187 [ + - ][ + - ]: 12 : maLargeProps.push_back( ComplexPropVector::value_type( new StringProperty( orValue, nSize ) ) );
[ + - ][ + - ]
[ + - ]
188 [ + - ]: 12 : startNextProperty();
189 : 12 : }
190 : :
191 : 6 : bool AxBinaryPropertyWriter::finalizeExport()
192 : : {
193 : : // write large properties
194 : 6 : maOutStrm.align( 4 );
195 [ + - ]: 6 : if( !maLargeProps.empty() )
196 : : {
197 [ + - ][ + - ]: 21 : for( ComplexPropVector::iterator aIt = maLargeProps.begin(), aEnd = maLargeProps.end(); ensureValid() && (aIt != aEnd); ++aIt )
[ + + ][ + + ]
198 : : {
199 [ + - ]: 15 : (*aIt)->writeProperty( maOutStrm );
200 [ + - ]: 15 : maOutStrm.align( 4 );
201 : : }
202 : : }
203 : :
204 : 6 : mnBlockSize = maOutStrm.tell() - mnPropFlagsStart;
205 : :
206 : : // write stream properties (no stream alignment between properties!)
207 [ - + ]: 6 : if( !maStreamProps.empty() )
208 [ # # ][ # # ]: 0 : for( ComplexPropVector::iterator aIt = maStreamProps.begin(), aEnd = maStreamProps.end(); ensureValid() && (aIt != aEnd); ++aIt )
[ # # ][ # # ]
209 [ # # ]: 0 : (*aIt)->writeProperty( maOutStrm );
210 : :
211 : 6 : sal_Int64 nPos = maOutStrm.tell();
212 : 6 : maOutStrm.seek( mnPropFlagsStart - sizeof( mnBlockSize ) );
213 : :
214 : 6 : maOutStrm << mnBlockSize;
215 : :
216 [ + + ]: 6 : if( mb64BitPropFlags )
217 : 3 : maOutStrm << mnPropFlags;
218 : : else
219 : 3 : maOutStrm << sal_uInt32( mnPropFlags );
220 : :
221 : 6 : maOutStrm.seek( nPos );
222 : 6 : return true;
223 : : }
224 : :
225 : 21 : bool AxBinaryPropertyWriter::ensureValid( bool bCondition )
226 : : {
227 [ + - ][ + - ]: 21 : mbValid = mbValid && bCondition && !maOutStrm.isEof();
[ + - ]
228 : 21 : return mbValid;
229 : : }
230 : :
231 : 123 : bool AxBinaryPropertyWriter::startNextProperty( bool bSkip )
232 : : {
233 : : // if we are skipping then we clear the flag
234 : 123 : setFlag( mnPropFlags, mnNextProp, !bSkip );
235 : 123 : mnNextProp <<= 1;
236 : 123 : return true;
237 : : }
238 : :
239 : : // ============================================================================
240 : :
241 : : } // namespace exp
242 [ + - ][ + - ]: 285 : } // namespace ole
243 : :
244 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|