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 2 : AxAlignedOutputStream::AxAlignedOutputStream( BinaryOutputStream& rOutStrm ) :
51 : BinaryStreamBase( false ),
52 : mpOutStrm( &rOutStrm ),
53 : mnStrmPos( 0 ),
54 2 : mnStrmSize( rOutStrm.getRemaining() ),
55 4 : mnWrappedBeginPos( rOutStrm.tell() )
56 : {
57 2 : mbEof = mbEof || rOutStrm.isEof();
58 2 : }
59 :
60 0 : sal_Int64 AxAlignedOutputStream::size() const
61 : {
62 0 : return mpOutStrm ? mnStrmSize : -1;
63 : }
64 :
65 6 : sal_Int64 AxAlignedOutputStream::tell() const
66 : {
67 6 : return mpOutStrm ? mnStrmPos : -1;
68 : }
69 :
70 4 : void AxAlignedOutputStream::seek( sal_Int64 nPos )
71 : {
72 4 : mbEof = (nPos < 0);
73 4 : if( !mbEof )
74 : {
75 4 : mpOutStrm->seek( static_cast< sal_Int32 >( mnWrappedBeginPos + nPos ) );
76 4 : mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
77 : }
78 4 : }
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 35 : void AxAlignedOutputStream::writeMemory( const void* opMem, sal_Int32 nBytes, size_t nAtomSize )
93 : {
94 35 : mpOutStrm->writeMemory( opMem, nBytes, nAtomSize );
95 35 : mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
96 35 : }
97 :
98 26 : void AxAlignedOutputStream::pad( sal_Int32 nBytes, size_t nAtomSize )
99 : {
100 : //PRESUMABELY we need to pad with 0's here as appropriate
101 26 : 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 26 : memset( static_cast<void*>( aData.getArray() ), 0, nBytes );
106 26 : mpOutStrm->writeData( aData, nAtomSize );
107 26 : mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
108 26 : }
109 :
110 26 : void AxAlignedOutputStream::align( size_t nSize )
111 : {
112 26 : pad( static_cast< sal_Int32 >( (nSize - (mnStrmPos % nSize)) % nSize ) );
113 26 : }
114 :
115 : // ============================================================================
116 :
117 : namespace {
118 :
119 4 : void lclWriteString( AxAlignedOutputStream& rOutStrm, OUString& rValue, sal_uInt32 nSize, bool bArrayString )
120 : {
121 4 : bool bCompressed = getFlag( nSize, AX_STRING_COMPRESSED );
122 4 : rOutStrm.writeCompressedUnicodeArray( rValue, bCompressed || bArrayString );
123 4 : }
124 :
125 : } // namespace
126 :
127 : // ----------------------------------------------------------------------------
128 :
129 5 : AxBinaryPropertyWriter::ComplexProperty::~ComplexProperty()
130 : {
131 5 : }
132 :
133 1 : bool AxBinaryPropertyWriter::PairProperty::writeProperty( AxAlignedOutputStream& rOutStrm )
134 : {
135 1 : rOutStrm << mrPairData.first << mrPairData.second;
136 1 : return true;
137 : }
138 :
139 4 : bool AxBinaryPropertyWriter::StringProperty::writeProperty( AxAlignedOutputStream& rOutStrm )
140 : {
141 4 : lclWriteString( rOutStrm, mrValue, mnSize, false );
142 4 : return true;
143 : }
144 :
145 : // ----------------------------------------------------------------------------
146 :
147 2 : AxBinaryPropertyWriter::AxBinaryPropertyWriter( BinaryOutputStream& rOutStrm, bool b64BitPropFlags ) :
148 : maOutStrm( rOutStrm ),
149 : mnPropFlags( 0x0 ),
150 : mbValid( true ),
151 2 : mb64BitPropFlags( b64BitPropFlags )
152 : {
153 2 : sal_uInt16 nId( 0x0200 );
154 2 : maOutStrm << nId;
155 2 : mnBlockSize = 0; // will be filled in the finalize method
156 :
157 2 : maOutStrm << nId;
158 2 : mnPropFlagsStart = maOutStrm.tell();
159 :
160 2 : if( mb64BitPropFlags )
161 1 : maOutStrm << mnPropFlags;
162 : else
163 1 : maOutStrm << sal_uInt32( mnPropFlags );
164 2 : mnNextProp = 1;
165 2 : }
166 :
167 1 : 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 1 : startNextProperty( !( ( orbValue ^ bReverse ) >= 1 ) );
171 1 : }
172 :
173 1 : void AxBinaryPropertyWriter::writePairProperty( AxPairData& orPairData )
174 : {
175 1 : if( startNextProperty() )
176 1 : maLargeProps.push_back( ComplexPropVector::value_type( new PairProperty( orPairData ) ) );
177 1 : }
178 :
179 4 : void AxBinaryPropertyWriter::writeStringProperty( OUString& orValue, bool bCompressed )
180 : {
181 4 : sal_uInt32 nSize = orValue.getLength();
182 4 : if ( bCompressed )
183 4 : setFlag( nSize, AX_STRING_COMPRESSED );
184 : else
185 0 : nSize *= 2;
186 4 : maOutStrm.writeAligned< sal_uInt32 >( nSize );
187 4 : maLargeProps.push_back( ComplexPropVector::value_type( new StringProperty( orValue, nSize ) ) );
188 4 : startNextProperty();
189 4 : }
190 :
191 2 : bool AxBinaryPropertyWriter::finalizeExport()
192 : {
193 : // write large properties
194 2 : maOutStrm.align( 4 );
195 2 : if( !maLargeProps.empty() )
196 : {
197 7 : for( ComplexPropVector::iterator aIt = maLargeProps.begin(), aEnd = maLargeProps.end(); ensureValid() && (aIt != aEnd); ++aIt )
198 : {
199 5 : (*aIt)->writeProperty( maOutStrm );
200 5 : maOutStrm.align( 4 );
201 : }
202 : }
203 :
204 2 : mnBlockSize = maOutStrm.tell() - mnPropFlagsStart;
205 :
206 : // write stream properties (no stream alignment between properties!)
207 2 : 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 2 : sal_Int64 nPos = maOutStrm.tell();
212 2 : maOutStrm.seek( mnPropFlagsStart - sizeof( mnBlockSize ) );
213 :
214 2 : maOutStrm << mnBlockSize;
215 :
216 2 : if( mb64BitPropFlags )
217 1 : maOutStrm << mnPropFlags;
218 : else
219 1 : maOutStrm << sal_uInt32( mnPropFlags );
220 :
221 2 : maOutStrm.seek( nPos );
222 2 : return true;
223 : }
224 :
225 7 : bool AxBinaryPropertyWriter::ensureValid( bool bCondition )
226 : {
227 7 : mbValid = mbValid && bCondition && !maOutStrm.isEof();
228 7 : return mbValid;
229 : }
230 :
231 41 : bool AxBinaryPropertyWriter::startNextProperty( bool bSkip )
232 : {
233 : // if we are skipping then we clear the flag
234 41 : setFlag( mnPropFlags, mnNextProp, !bSkip );
235 41 : mnNextProp <<= 1;
236 41 : return true;
237 : }
238 :
239 : // ============================================================================
240 :
241 : } // namespace exp
242 51 : } // namespace ole
243 :
244 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|