1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include "oox/dump/dumperbase.hxx"
25
26 #include <algorithm>
27 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
28 #include <com/sun/star/io/XActiveDataSource.hpp>
29 #include <com/sun/star/io/XTextOutputStream.hpp>
30 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
31 #include <comphelper/docpasswordhelper.hxx>
32 #include <osl/file.hxx>
33 #include <rtl/math.hxx>
34 #include <rtl/tencinfo.h>
35 #include "oox/core/filterbase.hxx"
36 #include "oox/helper/binaryoutputstream.hxx"
37 #include "oox/helper/textinputstream.hxx"
38 #include "oox/xls/biffhelper.hxx"
39
40 #if OOX_INCLUDE_DUMPER
41
42 namespace oox {
43 namespace dump {
44
45 // ============================================================================
46
47 using namespace ::com::sun::star::beans;
48 using namespace ::com::sun::star::io;
49 using namespace ::com::sun::star::lang;
50 using namespace ::com::sun::star::ucb;
51 using namespace ::com::sun::star::uno;
52 using namespace ::com::sun::star::util;
53
54 using ::comphelper::MediaDescriptor;
55 using ::oox::core::FilterBase;
56 using ::rtl::OString;
57 using ::rtl::OStringBuffer;
58 using ::rtl::OStringToOUString;
59 using ::rtl::OUString;
60 using ::rtl::OUStringBuffer;
61 using ::rtl::OUStringToOString;
62
63 // ============================================================================
64
65 namespace {
66
67 const sal_Unicode OOX_DUMP_BOM = 0xFEFF;
68 const sal_Int32 OOX_DUMP_MAXSTRLEN = 80;
69 const sal_Int32 OOX_DUMP_INDENT = 2;
70 const sal_Unicode OOX_DUMP_BINDOT = '.';
71 const sal_Unicode OOX_DUMP_CFG_LISTSEP = ',';
72 const sal_Unicode OOX_DUMP_CFG_QUOTE = '\'';
73 const sal_Unicode OOX_DUMP_LF = '\n';
74 const sal_Unicode OOX_DUMP_ITEMSEP = '=';
75 const sal_Int32 OOX_DUMP_BYTESPERLINE = 16;
76 const sal_Int64 OOX_DUMP_MAXARRAY = 16;
77
78 } // namespace
79
80 // ============================================================================
81 // ============================================================================
82
83 // file names -----------------------------------------------------------------
84
convertFileNameToUrl(const OUString & rFileName)85 OUString InputOutputHelper::convertFileNameToUrl( const OUString& rFileName )
86 {
87 OUString aFileUrl;
88 if( ::osl::FileBase::getFileURLFromSystemPath( rFileName, aFileUrl ) == ::osl::FileBase::E_None )
89 return aFileUrl;
90 return OUString();
91 }
92
getFileNamePos(const OUString & rFileUrl)93 sal_Int32 InputOutputHelper::getFileNamePos( const OUString& rFileUrl )
94 {
95 sal_Int32 nSepPos = rFileUrl.lastIndexOf( '/' );
96 return (nSepPos < 0) ? 0 : (nSepPos + 1);
97 }
98
getFileNameExtension(const OUString & rFileUrl)99 OUString InputOutputHelper::getFileNameExtension( const OUString& rFileUrl )
100 {
101 sal_Int32 nNamePos = getFileNamePos( rFileUrl );
102 sal_Int32 nExtPos = rFileUrl.lastIndexOf( '.' );
103 if( nExtPos >= nNamePos )
104 return rFileUrl.copy( nExtPos + 1 );
105 return OUString();
106 }
107
108 // input streams --------------------------------------------------------------
109
openInputStream(const Reference<XComponentContext> & rxContext,const OUString & rFileName)110 Reference< XInputStream > InputOutputHelper::openInputStream(
111 const Reference< XComponentContext >& rxContext, const OUString& rFileName )
112 {
113 Reference< XInputStream > xInStrm;
114 if( rxContext.is() ) try
115 {
116 Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW );
117 Reference< XSimpleFileAccess > xFileAccess( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY_THROW );
118 xInStrm = xFileAccess->openFileRead( rFileName );
119 }
120 catch( Exception& )
121 {
122 }
123 return xInStrm;
124 }
125
126 // output streams -------------------------------------------------------------
127
openOutputStream(const Reference<XComponentContext> & rxContext,const OUString & rFileName)128 Reference< XOutputStream > InputOutputHelper::openOutputStream(
129 const Reference< XComponentContext >& rxContext, const OUString& rFileName )
130 {
131 Reference< XOutputStream > xOutStrm;
132 if( rxContext.is() ) try
133 {
134 Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW );
135 Reference< XSimpleFileAccess > xFileAccess( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY_THROW );
136 xOutStrm = xFileAccess->openFileWrite( rFileName );
137 }
138 catch( Exception& )
139 {
140 }
141 return xOutStrm;
142 }
143
openTextOutputStream(const Reference<XComponentContext> & rxContext,const Reference<XOutputStream> & rxOutStrm,rtl_TextEncoding eTextEnc)144 Reference< XTextOutputStream > InputOutputHelper::openTextOutputStream(
145 const Reference< XComponentContext >& rxContext, const Reference< XOutputStream >& rxOutStrm, rtl_TextEncoding eTextEnc )
146 {
147 Reference< XTextOutputStream > xTextOutStrm;
148 const char* pcCharset = rtl_getMimeCharsetFromTextEncoding( eTextEnc );
149 if( rxContext.is() && rxOutStrm.is() && pcCharset ) try
150 {
151 Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW );
152 Reference< XActiveDataSource > xDataSource( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TextOutputStream" ) ), UNO_QUERY_THROW );
153 xDataSource->setOutputStream( rxOutStrm );
154 xTextOutStrm.set( xDataSource, UNO_QUERY_THROW );
155 xTextOutStrm->setEncoding( OUString::createFromAscii( pcCharset ) );
156 }
157 catch( Exception& )
158 {
159 }
160 return xTextOutStrm;
161 }
162
openTextOutputStream(const Reference<XComponentContext> & rxContext,const OUString & rFileName,rtl_TextEncoding eTextEnc)163 Reference< XTextOutputStream > InputOutputHelper::openTextOutputStream(
164 const Reference< XComponentContext >& rxContext, const OUString& rFileName, rtl_TextEncoding eTextEnc )
165 {
166 return openTextOutputStream( rxContext, openOutputStream( rxContext, rFileName ), eTextEnc );
167 }
168
169 // ============================================================================
170 // ============================================================================
171
ItemFormat()172 ItemFormat::ItemFormat() :
173 meDataType( DATATYPE_VOID ),
174 meFmtType( FORMATTYPE_NONE )
175 {
176 }
177
set(DataType eDataType,FormatType eFmtType,const OUString & rItemName)178 void ItemFormat::set( DataType eDataType, FormatType eFmtType, const OUString& rItemName )
179 {
180 meDataType = eDataType;
181 meFmtType = eFmtType;
182 maItemName = rItemName;
183 maListName = OUString();
184 }
185
set(DataType eDataType,FormatType eFmtType,const OUString & rItemName,const OUString & rListName)186 void ItemFormat::set( DataType eDataType, FormatType eFmtType, const OUString& rItemName, const OUString& rListName )
187 {
188 set( eDataType, eFmtType, rItemName );
189 maListName = rListName;
190 }
191
parse(const OUStringVector & rFormatVec)192 OUStringVector::const_iterator ItemFormat::parse( const OUStringVector& rFormatVec )
193 {
194 set( DATATYPE_VOID, FORMATTYPE_NONE, OUString() );
195
196 OUStringVector::const_iterator aIt = rFormatVec.begin(), aEnd = rFormatVec.end();
197 OUString aDataType, aFmtType;
198 if( aIt != aEnd ) aDataType = *aIt++;
199 if( aIt != aEnd ) aFmtType = *aIt++;
200 if( aIt != aEnd ) maItemName = *aIt++;
201 if( aIt != aEnd ) maListName = *aIt++;
202
203 meDataType = StringHelper::convertToDataType( aDataType );
204 meFmtType = StringHelper::convertToFormatType( aFmtType );
205
206 if( meFmtType == FORMATTYPE_NONE )
207 {
208 if( aFmtType.equalsAscii( "unused" ) )
209 set( meDataType, FORMATTYPE_HEX, CREATE_OUSTRING( OOX_DUMP_UNUSED ) );
210 else if( aFmtType.equalsAscii( "unknown" ) )
211 set( meDataType, FORMATTYPE_HEX, CREATE_OUSTRING( OOX_DUMP_UNKNOWN ) );
212 }
213
214 return aIt;
215 }
216
parse(const OUString & rFormatStr)217 OUStringVector ItemFormat::parse( const OUString& rFormatStr )
218 {
219 OUStringVector aFormatVec;
220 StringHelper::convertStringToStringList( aFormatVec, rFormatStr, false );
221 OUStringVector::const_iterator aIt = parse( aFormatVec );
222 return OUStringVector( aIt, const_cast< const OUStringVector& >( aFormatVec ).end() );
223 }
224
225 // ============================================================================
226 // ============================================================================
227
228 // append string to string ----------------------------------------------------
229
appendChar(OUStringBuffer & rStr,sal_Unicode cChar,sal_Int32 nCount)230 void StringHelper::appendChar( OUStringBuffer& rStr, sal_Unicode cChar, sal_Int32 nCount )
231 {
232 for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
233 rStr.append( cChar );
234 }
235
appendString(OUStringBuffer & rStr,const OUString & rData,sal_Int32 nWidth,sal_Unicode cFill)236 void StringHelper::appendString( OUStringBuffer& rStr, const OUString& rData, sal_Int32 nWidth, sal_Unicode cFill )
237 {
238 appendChar( rStr, cFill, nWidth - rData.getLength() );
239 rStr.append( rData );
240 }
241
242 // append decimal -------------------------------------------------------------
243
appendDec(OUStringBuffer & rStr,sal_uInt8 nData,sal_Int32 nWidth,sal_Unicode cFill)244 void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt8 nData, sal_Int32 nWidth, sal_Unicode cFill )
245 {
246 appendString( rStr, OUString::valueOf( static_cast< sal_Int32 >( nData ) ), nWidth, cFill );
247 }
248
appendDec(OUStringBuffer & rStr,sal_Int8 nData,sal_Int32 nWidth,sal_Unicode cFill)249 void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int8 nData, sal_Int32 nWidth, sal_Unicode cFill )
250 {
251 appendString( rStr, OUString::valueOf( static_cast< sal_Int32 >( nData ) ), nWidth, cFill );
252 }
253
appendDec(OUStringBuffer & rStr,sal_uInt16 nData,sal_Int32 nWidth,sal_Unicode cFill)254 void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt16 nData, sal_Int32 nWidth, sal_Unicode cFill )
255 {
256 appendString( rStr, OUString::valueOf( static_cast< sal_Int32 >( nData ) ), nWidth, cFill );
257 }
258
appendDec(OUStringBuffer & rStr,sal_Int16 nData,sal_Int32 nWidth,sal_Unicode cFill)259 void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int16 nData, sal_Int32 nWidth, sal_Unicode cFill )
260 {
261 appendString( rStr, OUString::valueOf( static_cast< sal_Int32 >( nData ) ), nWidth, cFill );
262 }
263
appendDec(OUStringBuffer & rStr,sal_uInt32 nData,sal_Int32 nWidth,sal_Unicode cFill)264 void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt32 nData, sal_Int32 nWidth, sal_Unicode cFill )
265 {
266 appendString( rStr, OUString::valueOf( static_cast< sal_Int64 >( nData ) ), nWidth, cFill );
267 }
268
appendDec(OUStringBuffer & rStr,sal_Int32 nData,sal_Int32 nWidth,sal_Unicode cFill)269 void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int32 nData, sal_Int32 nWidth, sal_Unicode cFill )
270 {
271 appendString( rStr, OUString::valueOf( nData ), nWidth, cFill );
272 }
273
appendDec(OUStringBuffer & rStr,sal_uInt64 nData,sal_Int32 nWidth,sal_Unicode cFill)274 void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt64 nData, sal_Int32 nWidth, sal_Unicode cFill )
275 {
276 /* Values greater than biggest signed 64bit integer will change to
277 negative when converting to sal_Int64. Therefore, the trailing digit
278 will be written separately. */
279 OUStringBuffer aBuffer;
280 if( nData > 9 )
281 aBuffer.append( OUString::valueOf( static_cast< sal_Int64 >( nData / 10 ) ) );
282 aBuffer.append( static_cast< sal_Unicode >( '0' + (nData % 10) ) );
283 appendString( rStr, aBuffer.makeStringAndClear(), nWidth, cFill );
284 }
285
appendDec(OUStringBuffer & rStr,sal_Int64 nData,sal_Int32 nWidth,sal_Unicode cFill)286 void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int64 nData, sal_Int32 nWidth, sal_Unicode cFill )
287 {
288 appendString( rStr, OUString::valueOf( nData ), nWidth, cFill );
289 }
290
appendDec(OUStringBuffer & rStr,double fData,sal_Int32 nWidth,sal_Unicode cFill)291 void StringHelper::appendDec( OUStringBuffer& rStr, double fData, sal_Int32 nWidth, sal_Unicode cFill )
292 {
293 appendString( rStr, ::rtl::math::doubleToUString( fData, rtl_math_StringFormat_G, 15, '.', true ), nWidth, cFill );
294 }
295
296 // append hexadecimal ---------------------------------------------------------
297
appendHex(OUStringBuffer & rStr,sal_uInt8 nData,bool bPrefix)298 void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt8 nData, bool bPrefix )
299 {
300 static const sal_Unicode spcHexDigits[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
301 if( bPrefix )
302 rStr.appendAscii( "0x" );
303 rStr.append( spcHexDigits[ (nData >> 4) & 0x0F ] ).append( spcHexDigits[ nData & 0x0F ] );
304 }
305
appendHex(OUStringBuffer & rStr,sal_Int8 nData,bool bPrefix)306 void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int8 nData, bool bPrefix )
307 {
308 appendHex( rStr, static_cast< sal_uInt8 >( nData ), bPrefix );
309 }
310
appendHex(OUStringBuffer & rStr,sal_uInt16 nData,bool bPrefix)311 void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt16 nData, bool bPrefix )
312 {
313 appendHex( rStr, static_cast< sal_uInt8 >( nData >> 8 ), bPrefix );
314 appendHex( rStr, static_cast< sal_uInt8 >( nData ), false );
315 }
316
appendHex(OUStringBuffer & rStr,sal_Int16 nData,bool bPrefix)317 void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int16 nData, bool bPrefix )
318 {
319 appendHex( rStr, static_cast< sal_uInt16 >( nData ), bPrefix );
320 }
321
appendHex(OUStringBuffer & rStr,sal_uInt32 nData,bool bPrefix)322 void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt32 nData, bool bPrefix )
323 {
324 appendHex( rStr, static_cast< sal_uInt16 >( nData >> 16 ), bPrefix );
325 appendHex( rStr, static_cast< sal_uInt16 >( nData ), false );
326 }
327
appendHex(OUStringBuffer & rStr,sal_Int32 nData,bool bPrefix)328 void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int32 nData, bool bPrefix )
329 {
330 appendHex( rStr, static_cast< sal_uInt32 >( nData ), bPrefix );
331 }
332
appendHex(OUStringBuffer & rStr,sal_uInt64 nData,bool bPrefix)333 void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt64 nData, bool bPrefix )
334 {
335 appendHex( rStr, static_cast< sal_uInt32 >( nData >> 32 ), bPrefix );
336 appendHex( rStr, static_cast< sal_uInt32 >( nData ), false );
337 }
338
appendHex(OUStringBuffer & rStr,sal_Int64 nData,bool bPrefix)339 void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int64 nData, bool bPrefix )
340 {
341 appendHex( rStr, static_cast< sal_uInt64 >( nData ), bPrefix );
342 }
343
appendHex(OUStringBuffer & rStr,double fData,bool bPrefix)344 void StringHelper::appendHex( OUStringBuffer& rStr, double fData, bool bPrefix )
345 {
346 appendHex( rStr, *reinterpret_cast< const sal_uInt64* >( &fData ), bPrefix );
347 }
348
349 // append shortened hexadecimal -----------------------------------------------
350
appendShortHex(OUStringBuffer & rStr,sal_uInt8 nData,bool bPrefix)351 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt8 nData, bool bPrefix )
352 {
353 appendHex( rStr, nData, bPrefix );
354 }
355
appendShortHex(OUStringBuffer & rStr,sal_Int8 nData,bool bPrefix)356 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int8 nData, bool bPrefix )
357 {
358 appendHex( rStr, nData, bPrefix );
359 }
360
appendShortHex(OUStringBuffer & rStr,sal_uInt16 nData,bool bPrefix)361 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt16 nData, bool bPrefix )
362 {
363 if( nData > SAL_MAX_UINT8 )
364 appendHex( rStr, nData, bPrefix );
365 else
366 appendHex( rStr, static_cast< sal_uInt8 >( nData ), bPrefix );
367 }
368
appendShortHex(OUStringBuffer & rStr,sal_Int16 nData,bool bPrefix)369 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int16 nData, bool bPrefix )
370 {
371 appendShortHex( rStr, static_cast< sal_uInt16 >( nData ), bPrefix );
372 }
373
appendShortHex(OUStringBuffer & rStr,sal_uInt32 nData,bool bPrefix)374 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt32 nData, bool bPrefix )
375 {
376 if( nData > SAL_MAX_UINT16 )
377 appendHex( rStr, nData, bPrefix );
378 else
379 appendShortHex( rStr, static_cast< sal_uInt16 >( nData ), bPrefix );
380 }
381
appendShortHex(OUStringBuffer & rStr,sal_Int32 nData,bool bPrefix)382 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int32 nData, bool bPrefix )
383 {
384 appendShortHex( rStr, static_cast< sal_uInt32 >( nData ), bPrefix );
385 }
386
appendShortHex(OUStringBuffer & rStr,sal_uInt64 nData,bool bPrefix)387 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt64 nData, bool bPrefix )
388 {
389 if( nData > SAL_MAX_UINT32 )
390 appendHex( rStr, nData, bPrefix );
391 else
392 appendShortHex( rStr, static_cast< sal_uInt32 >( nData ), bPrefix );
393 }
394
appendShortHex(OUStringBuffer & rStr,sal_Int64 nData,bool bPrefix)395 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int64 nData, bool bPrefix )
396 {
397 appendShortHex( rStr, static_cast< sal_uInt64 >( nData ), bPrefix );
398 }
399
appendShortHex(OUStringBuffer & rStr,double fData,bool bPrefix)400 void StringHelper::appendShortHex( OUStringBuffer& rStr, double fData, bool bPrefix )
401 {
402 appendHex( rStr, fData, bPrefix );
403 }
404
405 // append binary --------------------------------------------------------------
406
appendBin(OUStringBuffer & rStr,sal_uInt8 nData,bool bDots)407 void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt8 nData, bool bDots )
408 {
409 for( sal_uInt8 nMask = 0x80; nMask != 0; (nMask >>= 1) &= 0x7F )
410 {
411 rStr.append( static_cast< sal_Unicode >( (nData & nMask) ? '1' : '0' ) );
412 if( bDots && (nMask == 0x10) )
413 rStr.append( OOX_DUMP_BINDOT );
414 }
415 }
416
appendBin(OUStringBuffer & rStr,sal_Int8 nData,bool bDots)417 void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int8 nData, bool bDots )
418 {
419 appendBin( rStr, static_cast< sal_uInt8 >( nData ), bDots );
420 }
421
appendBin(OUStringBuffer & rStr,sal_uInt16 nData,bool bDots)422 void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt16 nData, bool bDots )
423 {
424 appendBin( rStr, static_cast< sal_uInt8 >( nData >> 8 ), bDots );
425 if( bDots )
426 rStr.append( OOX_DUMP_BINDOT );
427 appendBin( rStr, static_cast< sal_uInt8 >( nData ), bDots );
428 }
429
appendBin(OUStringBuffer & rStr,sal_Int16 nData,bool bDots)430 void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int16 nData, bool bDots )
431 {
432 appendBin( rStr, static_cast< sal_uInt16 >( nData ), bDots );
433 }
434
appendBin(OUStringBuffer & rStr,sal_uInt32 nData,bool bDots)435 void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt32 nData, bool bDots )
436 {
437 appendBin( rStr, static_cast< sal_uInt16 >( nData >> 16 ), bDots );
438 if( bDots )
439 rStr.append( OOX_DUMP_BINDOT );
440 appendBin( rStr, static_cast< sal_uInt16 >( nData ), bDots );
441 }
442
appendBin(OUStringBuffer & rStr,sal_Int32 nData,bool bDots)443 void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int32 nData, bool bDots )
444 {
445 appendBin( rStr, static_cast< sal_uInt32 >( nData ), bDots );
446 }
447
appendBin(OUStringBuffer & rStr,sal_uInt64 nData,bool bDots)448 void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt64 nData, bool bDots )
449 {
450 appendBin( rStr, static_cast< sal_uInt32 >( nData >> 32 ), bDots );
451 if( bDots )
452 rStr.append( OOX_DUMP_BINDOT );
453 appendBin( rStr, static_cast< sal_uInt32 >( nData ), bDots );
454 }
455
appendBin(OUStringBuffer & rStr,sal_Int64 nData,bool bDots)456 void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int64 nData, bool bDots )
457 {
458 appendBin( rStr, static_cast< sal_uInt64 >( nData ), bDots );
459 }
460
appendBin(OUStringBuffer & rStr,double fData,bool bDots)461 void StringHelper::appendBin( OUStringBuffer& rStr, double fData, bool bDots )
462 {
463 appendBin( rStr, *reinterpret_cast< const sal_uInt64* >( &fData ), bDots );
464 }
465
466 // append formatted value -----------------------------------------------------
467
appendBool(OUStringBuffer & rStr,bool bData)468 void StringHelper::appendBool( OUStringBuffer& rStr, bool bData )
469 {
470 rStr.appendAscii( bData ? "true" : "false" );
471 }
472
473 // append columns, rows, addresses --------------------------------------------
474
appendAddrCol(OUStringBuffer & rStr,sal_Int32 nCol,bool bRel)475 void StringHelper::appendAddrCol( OUStringBuffer& rStr, sal_Int32 nCol, bool bRel )
476 {
477 if( !bRel ) rStr.append( OOX_DUMP_ADDRABS );
478 sal_Int32 nPos = rStr.getLength();
479 for( sal_Int32 nTemp = nCol; nTemp >= 0; (nTemp /= 26) -= 1 )
480 rStr.insert( nPos, static_cast< sal_Unicode >( 'A' + (nTemp % 26) ) );
481 }
482
appendAddrRow(OUStringBuffer & rStr,sal_Int32 nRow,bool bRel)483 void StringHelper::appendAddrRow( OUStringBuffer& rStr, sal_Int32 nRow, bool bRel )
484 {
485 if( !bRel ) rStr.append( OOX_DUMP_ADDRABS );
486 appendDec( rStr, nRow + 1 );
487 }
488
appendAddrName(OUStringBuffer & rStr,sal_Unicode cPrefix,sal_Int32 nColRow,bool bRel)489 void StringHelper::appendAddrName( OUStringBuffer& rStr, sal_Unicode cPrefix, sal_Int32 nColRow, bool bRel )
490 {
491 rStr.append( cPrefix );
492 if( bRel && (nColRow != 0) )
493 {
494 rStr.append( OOX_DUMP_R1C1OPEN );
495 appendDec( rStr, nColRow );
496 rStr.append( OOX_DUMP_R1C1CLOSE );
497 }
498 else if( !bRel )
499 appendDec( rStr, nColRow + 1 );
500 }
501
appendAddress(OUStringBuffer & rStr,const Address & rPos)502 void StringHelper::appendAddress( OUStringBuffer& rStr, const Address& rPos )
503 {
504 appendAddrCol( rStr, rPos.mnCol, true );
505 appendAddrRow( rStr, rPos.mnRow, true );
506 }
507
appendRange(OUStringBuffer & rStr,const Range & rRange)508 void StringHelper::appendRange( OUStringBuffer& rStr, const Range& rRange )
509 {
510 appendAddress( rStr, rRange.maFirst );
511 rStr.append( OOX_DUMP_RANGESEP );
512 appendAddress( rStr, rRange.maLast );
513 }
514
appendRangeList(OUStringBuffer & rStr,const RangeList & rRanges)515 void StringHelper::appendRangeList( OUStringBuffer& rStr, const RangeList& rRanges )
516 {
517 OUStringBuffer aData;
518 for( RangeList::const_iterator aIt = rRanges.begin(), aEnd = rRanges.end(); aIt != aEnd; ++aIt )
519 {
520 OUStringBuffer aRange;
521 appendRange( aRange, *aIt );
522 appendToken( aData, aRange.makeStringAndClear(), OOX_DUMP_LISTSEP );
523 }
524 rStr.append( aData.makeStringAndClear() );
525 }
526
appendAddress(OUStringBuffer & rStr,const TokenAddress & rPos,bool bR1C1)527 void StringHelper::appendAddress( OUStringBuffer& rStr, const TokenAddress& rPos, bool bR1C1 )
528 {
529 if( bR1C1 && (rPos.mbRelCol || rPos.mbRelRow) )
530 {
531 appendAddrName( rStr, OOX_DUMP_R1C1ROW, rPos.mnRow, rPos.mbRelRow );
532 appendAddrName( rStr, OOX_DUMP_R1C1COL, rPos.mnCol, rPos.mbRelCol );
533 }
534 else
535 {
536 appendAddrCol( rStr, rPos.mnCol, rPos.mbRelCol );
537 appendAddrRow( rStr, rPos.mnRow, rPos.mbRelRow );
538 }
539 }
540
appendRange(OUStringBuffer & rStr,const TokenRange & rRange,bool bR1C1)541 void StringHelper::appendRange( OUStringBuffer& rStr, const TokenRange& rRange, bool bR1C1 )
542 {
543 appendAddress( rStr, rRange.maFirst, bR1C1 );
544 rStr.append( OOX_DUMP_RANGESEP );
545 appendAddress( rStr, rRange.maLast, bR1C1 );
546 }
547
548 // encoded text output --------------------------------------------------------
549
appendCChar(OUStringBuffer & rStr,sal_Unicode cChar,bool bPrefix)550 void StringHelper::appendCChar( OUStringBuffer& rStr, sal_Unicode cChar, bool bPrefix )
551 {
552 if( cChar > 0x00FF )
553 {
554 if( bPrefix )
555 rStr.appendAscii( "\\u" );
556 appendHex( rStr, static_cast< sal_uInt16 >( cChar ), false );
557 }
558 else
559 {
560 if( bPrefix )
561 rStr.appendAscii( "\\x" );
562 appendHex( rStr, static_cast< sal_uInt8 >( cChar ), false );
563 }
564 }
565
appendEncChar(OUStringBuffer & rStr,sal_Unicode cChar,sal_Int32 nCount,bool bPrefix)566 void StringHelper::appendEncChar( OUStringBuffer& rStr, sal_Unicode cChar, sal_Int32 nCount, bool bPrefix )
567 {
568 if( cChar < 0x0020 )
569 {
570 // C-style hex code
571 OUStringBuffer aCode;
572 appendCChar( aCode, cChar, bPrefix );
573 for( sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx )
574 rStr.append( aCode );
575 }
576 else
577 {
578 appendChar( rStr, cChar, nCount );
579 }
580 }
581
appendEncString(OUStringBuffer & rStr,const OUString & rData,bool bPrefix)582 void StringHelper::appendEncString( OUStringBuffer& rStr, const OUString& rData, bool bPrefix )
583 {
584 sal_Int32 nBeg = 0;
585 sal_Int32 nIdx = 0;
586 sal_Int32 nEnd = rData.getLength();
587 while( nIdx < nEnd )
588 {
589 // find next character that needs encoding
590 while( (nIdx < nEnd) && (rData[ nIdx ] >= 0x20) ) ++nIdx;
591 // append portion
592 if( nBeg < nIdx )
593 {
594 if( (nBeg == 0) && (nIdx == nEnd) )
595 rStr.append( rData );
596 else
597 rStr.append( rData.copy( nBeg, nIdx - nBeg ) );
598 }
599 // append characters to be encoded
600 while( (nIdx < nEnd) && (rData[ nIdx ] < 0x20) )
601 {
602 appendCChar( rStr, rData[ nIdx ], bPrefix );
603 ++nIdx;
604 }
605 // adjust limits
606 nBeg = nIdx;
607 }
608 }
609
610 // token list -----------------------------------------------------------------
611
appendToken(OUStringBuffer & rStr,const OUString & rToken,sal_Unicode cSep)612 void StringHelper::appendToken( OUStringBuffer& rStr, const OUString& rToken, sal_Unicode cSep )
613 {
614 if( (rStr.getLength() > 0) && (rToken.getLength() > 0) )
615 rStr.append( cSep );
616 rStr.append( rToken );
617 }
618
appendToken(OUStringBuffer & rStr,sal_Int64 nToken,sal_Unicode cSep)619 void StringHelper::appendToken( OUStringBuffer& rStr, sal_Int64 nToken, sal_Unicode cSep )
620 {
621 OUStringBuffer aToken;
622 appendDec( aToken, nToken );
623 appendToken( rStr, aToken.makeStringAndClear(), cSep );
624 }
625
prependToken(OUStringBuffer & rStr,const OUString & rToken,sal_Unicode cSep)626 void StringHelper::prependToken( OUStringBuffer& rStr, const OUString& rToken, sal_Unicode cSep )
627 {
628 if( (rStr.getLength() > 0) && (rToken.getLength() > 0) )
629 rStr.insert( 0, cSep );
630 rStr.insert( 0, rToken );
631 }
632
prependToken(OUStringBuffer & rStr,sal_Int64 nToken,sal_Unicode cSep)633 void StringHelper::prependToken( OUStringBuffer& rStr, sal_Int64 nToken, sal_Unicode cSep )
634 {
635 OUStringBuffer aToken;
636 appendDec( aToken, nToken );
637 prependToken( rStr, aToken.makeStringAndClear(), cSep );
638 }
639
appendIndex(OUStringBuffer & rStr,const OUString & rIdx)640 void StringHelper::appendIndex( OUStringBuffer& rStr, const OUString& rIdx )
641 {
642 rStr.append( sal_Unicode( '[' ) ).append( rIdx ).append( sal_Unicode( ']' ) );
643 }
644
appendIndex(OUStringBuffer & rStr,sal_Int64 nIdx)645 void StringHelper::appendIndex( OUStringBuffer& rStr, sal_Int64 nIdx )
646 {
647 OUStringBuffer aToken;
648 appendDec( aToken, nIdx );
649 appendIndex( rStr, aToken.makeStringAndClear() );
650 }
651
appendIndexedText(OUStringBuffer & rStr,const OUString & rData,const OUString & rIdx)652 void StringHelper::appendIndexedText( OUStringBuffer& rStr, const OUString& rData, const OUString& rIdx )
653 {
654 rStr.append( rData );
655 appendIndex( rStr, rIdx );
656 }
657
appendIndexedText(OUStringBuffer & rStr,const OUString & rData,sal_Int64 nIdx)658 void StringHelper::appendIndexedText( OUStringBuffer& rStr, const OUString& rData, sal_Int64 nIdx )
659 {
660 rStr.append( rData );
661 appendIndex( rStr, nIdx );
662 }
663
getToken(const OUString & rData,sal_Int32 & rnPos,sal_Unicode cSep)664 OUString StringHelper::getToken( const OUString& rData, sal_Int32& rnPos, sal_Unicode cSep )
665 {
666 return trimSpaces( rData.getToken( 0, cSep, rnPos ) );
667 }
668
enclose(OUStringBuffer & rStr,sal_Unicode cOpen,sal_Unicode cClose)669 void StringHelper::enclose( OUStringBuffer& rStr, sal_Unicode cOpen, sal_Unicode cClose )
670 {
671 rStr.insert( 0, cOpen ).append( cClose ? cClose : cOpen );
672 }
673
674 // string conversion ----------------------------------------------------------
675
676 namespace {
677
lclIndexOf(const OUString & rStr,sal_Unicode cChar,sal_Int32 nStartPos)678 sal_Int32 lclIndexOf( const OUString& rStr, sal_Unicode cChar, sal_Int32 nStartPos )
679 {
680 sal_Int32 nIndex = rStr.indexOf( cChar, nStartPos );
681 return (nIndex < 0) ? rStr.getLength() : nIndex;
682 }
683
lclTrimQuotedStringList(const OUString & rStr)684 OUString lclTrimQuotedStringList( const OUString& rStr )
685 {
686 OUStringBuffer aBuffer;
687 sal_Int32 nPos = 0;
688 sal_Int32 nLen = rStr.getLength();
689 while( nPos < nLen )
690 {
691 if( rStr[ nPos ] == OOX_DUMP_CFG_QUOTE )
692 {
693 // quoted string, skip leading quote character
694 ++nPos;
695 // process quoted text and ambedded literal quote characters
696 OUStringBuffer aToken;
697 do
698 {
699 // seek to next quote character and add text portion to token buffer
700 sal_Int32 nEnd = lclIndexOf( rStr, OOX_DUMP_CFG_QUOTE, nPos );
701 aToken.append( rStr.copy( nPos, nEnd - nPos ) );
702 // process literal quotes
703 while( (nEnd + 1 < nLen) && (rStr[ nEnd ] == OOX_DUMP_CFG_QUOTE) && (rStr[ nEnd + 1 ] == OOX_DUMP_CFG_QUOTE) )
704 {
705 aToken.append( OOX_DUMP_CFG_QUOTE );
706 nEnd += 2;
707 }
708 // nEnd is start of possible next text portion
709 nPos = nEnd;
710 }
711 while( (nPos < nLen) && (rStr[ nPos ] != OOX_DUMP_CFG_QUOTE) );
712 // add token, seek to list separator, ignore text following closing quote
713 aBuffer.append( aToken.makeStringAndClear() );
714 nPos = lclIndexOf( rStr, OOX_DUMP_CFG_LISTSEP, nPos );
715 if( nPos < nLen )
716 aBuffer.append( OOX_DUMP_LF );
717 // set current position behind list separator
718 ++nPos;
719 }
720 else
721 {
722 // find list separator, add token text to buffer
723 sal_Int32 nEnd = lclIndexOf( rStr, OOX_DUMP_CFG_LISTSEP, nPos );
724 aBuffer.append( rStr.copy( nPos, nEnd - nPos ) );
725 if( nEnd < nLen )
726 aBuffer.append( OOX_DUMP_LF );
727 // set current position behind list separator
728 nPos = nEnd + 1;
729 }
730 }
731
732 return aBuffer.makeStringAndClear();
733 }
734
735 } // namespace
736
trimSpaces(const OUString & rStr)737 OUString StringHelper::trimSpaces( const OUString& rStr )
738 {
739 sal_Int32 nBeg = 0;
740 while( (nBeg < rStr.getLength()) && ((rStr[ nBeg ] == ' ') || (rStr[ nBeg ] == '\t')) )
741 ++nBeg;
742 sal_Int32 nEnd = rStr.getLength();
743 while( (nEnd > nBeg) && ((rStr[ nEnd - 1 ] == ' ') || (rStr[ nEnd - 1 ] == '\t')) )
744 --nEnd;
745 return rStr.copy( nBeg, nEnd - nBeg );
746 }
747
trimTrailingNul(const OUString & rStr)748 OUString StringHelper::trimTrailingNul( const OUString& rStr )
749 {
750 sal_Int32 nLastPos = rStr.getLength() - 1;
751 if( (nLastPos >= 0) && (rStr[ nLastPos ] == 0) )
752 return rStr.copy( 0, nLastPos );
753 return rStr;
754 }
755
convertToUtf8(const OUString & rStr)756 OString StringHelper::convertToUtf8( const OUString& rStr )
757 {
758 return OUStringToOString( rStr, RTL_TEXTENCODING_UTF8 );
759 }
760
convertToDataType(const OUString & rStr)761 DataType StringHelper::convertToDataType( const OUString& rStr )
762 {
763 DataType eType = DATATYPE_VOID;
764 if( rStr.equalsAscii( "int8" ) )
765 eType = DATATYPE_INT8;
766 else if( rStr.equalsAscii( "uint8" ) )
767 eType = DATATYPE_UINT8;
768 else if( rStr.equalsAscii( "int16" ) )
769 eType = DATATYPE_INT16;
770 else if( rStr.equalsAscii( "uint16" ) )
771 eType = DATATYPE_UINT16;
772 else if( rStr.equalsAscii( "int32" ) )
773 eType = DATATYPE_INT32;
774 else if( rStr.equalsAscii( "uint32" ) )
775 eType = DATATYPE_UINT32;
776 else if( rStr.equalsAscii( "int64" ) )
777 eType = DATATYPE_INT64;
778 else if( rStr.equalsAscii( "uint64" ) )
779 eType = DATATYPE_UINT64;
780 else if( rStr.equalsAscii( "float" ) )
781 eType = DATATYPE_FLOAT;
782 else if( rStr.equalsAscii( "double" ) )
783 eType = DATATYPE_DOUBLE;
784 return eType;
785 }
786
convertToFormatType(const OUString & rStr)787 FormatType StringHelper::convertToFormatType( const OUString& rStr )
788 {
789 FormatType eType = FORMATTYPE_NONE;
790 if( rStr.equalsAscii( "dec" ) )
791 eType = FORMATTYPE_DEC;
792 else if( rStr.equalsAscii( "hex" ) )
793 eType = FORMATTYPE_HEX;
794 else if( rStr.equalsAscii( "shorthex" ) )
795 eType = FORMATTYPE_SHORTHEX;
796 else if( rStr.equalsAscii( "bin" ) )
797 eType = FORMATTYPE_BIN;
798 else if( rStr.equalsAscii( "fix" ) )
799 eType = FORMATTYPE_FIX;
800 else if( rStr.equalsAscii( "bool" ) )
801 eType = FORMATTYPE_BOOL;
802 return eType;
803 }
804
convertFromDec(sal_Int64 & ornData,const OUString & rData)805 bool StringHelper::convertFromDec( sal_Int64& ornData, const OUString& rData )
806 {
807 sal_Int32 nPos = 0;
808 sal_Int32 nLen = rData.getLength();
809 bool bNeg = false;
810 if( (nLen > 0) && (rData[ 0 ] == '-') )
811 {
812 bNeg = true;
813 ++nPos;
814 }
815 ornData = 0;
816 for( ; nPos < nLen; ++nPos )
817 {
818 sal_Unicode cChar = rData[ nPos ];
819 if( (cChar < '0') || (cChar > '9') )
820 return false;
821 (ornData *= 10) += (cChar - '0');
822 }
823 if( bNeg )
824 ornData *= -1;
825 return true;
826 }
827
convertFromHex(sal_Int64 & ornData,const OUString & rData)828 bool StringHelper::convertFromHex( sal_Int64& ornData, const OUString& rData )
829 {
830 ornData = 0;
831 for( sal_Int32 nPos = 0, nLen = rData.getLength(); nPos < nLen; ++nPos )
832 {
833 sal_Unicode cChar = rData[ nPos ];
834 if( ('0' <= cChar) && (cChar <= '9') )
835 cChar -= '0';
836 else if( ('A' <= cChar) && (cChar <= 'F') )
837 cChar -= ('A' - 10);
838 else if( ('a' <= cChar) && (cChar <= 'f') )
839 cChar -= ('a' - 10);
840 else
841 return false;
842 (ornData <<= 4) += cChar;
843 }
844 return true;
845 }
846
convertStringToInt(sal_Int64 & ornData,const OUString & rData)847 bool StringHelper::convertStringToInt( sal_Int64& ornData, const OUString& rData )
848 {
849 if( (rData.getLength() > 2) && (rData[ 0 ] == '0') && ((rData[ 1 ] == 'X') || (rData[ 1 ] == 'x')) )
850 return convertFromHex( ornData, rData.copy( 2 ) );
851 return convertFromDec( ornData, rData );
852 }
853
convertStringToDouble(double & orfData,const OUString & rData)854 bool StringHelper::convertStringToDouble( double& orfData, const OUString& rData )
855 {
856 rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
857 sal_Int32 nSize = 0;
858 orfData = rtl::math::stringToDouble( rData, '.', '\0', &eStatus, &nSize );
859 return (eStatus == rtl_math_ConversionStatus_Ok) && (nSize == rData.getLength());
860 }
861
convertStringToBool(const OUString & rData)862 bool StringHelper::convertStringToBool( const OUString& rData )
863 {
864 if( rData.equalsAscii( "true" ) )
865 return true;
866 if( rData.equalsAscii( "false" ) )
867 return false;
868 sal_Int64 nData;
869 return convertStringToInt( nData, rData ) && (nData != 0);
870 }
871
convertStringToPair(const OUString & rString,sal_Unicode cSep)872 OUStringPair StringHelper::convertStringToPair( const OUString& rString, sal_Unicode cSep )
873 {
874 OUStringPair aPair;
875 if( rString.getLength() > 0 )
876 {
877 sal_Int32 nEqPos = rString.indexOf( cSep );
878 if( nEqPos < 0 )
879 {
880 aPair.first = rString;
881 }
882 else
883 {
884 aPair.first = StringHelper::trimSpaces( rString.copy( 0, nEqPos ) );
885 aPair.second = StringHelper::trimSpaces( rString.copy( nEqPos + 1 ) );
886 }
887 }
888 return aPair;
889 }
890
convertStringToStringList(OUStringVector & orVec,const OUString & rData,bool bIgnoreEmpty)891 void StringHelper::convertStringToStringList( OUStringVector& orVec, const OUString& rData, bool bIgnoreEmpty )
892 {
893 orVec.clear();
894 OUString aUnquotedData = lclTrimQuotedStringList( rData );
895 sal_Int32 nPos = 0;
896 sal_Int32 nLen = aUnquotedData.getLength();
897 while( (0 <= nPos) && (nPos < nLen) )
898 {
899 OUString aToken = getToken( aUnquotedData, nPos, OOX_DUMP_LF );
900 if( !bIgnoreEmpty || (aToken.getLength() > 0) )
901 orVec.push_back( aToken );
902 }
903 }
904
convertStringToIntList(Int64Vector & orVec,const OUString & rData,bool bIgnoreEmpty)905 void StringHelper::convertStringToIntList( Int64Vector& orVec, const OUString& rData, bool bIgnoreEmpty )
906 {
907 orVec.clear();
908 OUString aUnquotedData = lclTrimQuotedStringList( rData );
909 sal_Int32 nPos = 0;
910 sal_Int32 nLen = aUnquotedData.getLength();
911 sal_Int64 nData;
912 while( (0 <= nPos) && (nPos < nLen) )
913 {
914 bool bOk = convertStringToInt( nData, getToken( aUnquotedData, nPos, OOX_DUMP_LF ) );
915 if( !bIgnoreEmpty || bOk )
916 orVec.push_back( bOk ? nData : 0 );
917 }
918 }
919
920 // ============================================================================
921 // ============================================================================
922
FormulaStack()923 FormulaStack::FormulaStack() :
924 mbError( false )
925 {
926 }
927
pushOperand(const String & rOp,const OUString & rTokClass)928 void FormulaStack::pushOperand( const String& rOp, const OUString& rTokClass )
929 {
930 maFmlaStack.push( rOp );
931 maClassStack.push( rTokClass );
932 }
933
pushOperand(const String & rOp)934 void FormulaStack::pushOperand( const String& rOp )
935 {
936 pushOperand( rOp, OUString( OOX_DUMP_BASECLASS ) );
937 }
938
pushUnaryOp(const String & rLOp,const String & rROp)939 void FormulaStack::pushUnaryOp( const String& rLOp, const String& rROp )
940 {
941 pushUnaryOp( maFmlaStack, rLOp, rROp );
942 pushUnaryOp( maClassStack, rLOp, rROp );
943 }
944
pushBinaryOp(const String & rOp)945 void FormulaStack::pushBinaryOp( const String& rOp )
946 {
947 pushBinaryOp( maFmlaStack, rOp );
948 pushBinaryOp( maClassStack, rOp );
949 }
950
pushFuncOp(const String & rFunc,const OUString & rTokClass,sal_uInt8 nParamCount)951 void FormulaStack::pushFuncOp( const String& rFunc, const OUString& rTokClass, sal_uInt8 nParamCount )
952 {
953 pushFuncOp( maFmlaStack, rFunc, nParamCount );
954 pushFuncOp( maClassStack, rTokClass, nParamCount );
955 }
956
replaceOnTop(const OUString & rOld,const OUString & rNew)957 void FormulaStack::replaceOnTop( const OUString& rOld, const OUString& rNew )
958 {
959 if( !maFmlaStack.empty() )
960 {
961 sal_Int32 nPos = maFmlaStack.top().indexOf( rOld );
962 if( nPos >= 0 )
963 maFmlaStack.top() = maFmlaStack.top().copy( 0, nPos ) + rNew + maFmlaStack.top().copy( nPos + rOld.getLength() );
964 }
965 }
966
getString(const StringStack & rStack) const967 const OUString& FormulaStack::getString( const StringStack& rStack ) const
968 {
969 static const OUString saStackError = OOX_DUMP_ERRSTRING( "stack" );
970 return (mbError || rStack.empty()) ? saStackError : rStack.top();
971 }
972
pushUnaryOp(StringStack & rStack,const OUString & rLOp,const OUString & rROp)973 void FormulaStack::pushUnaryOp( StringStack& rStack, const OUString& rLOp, const OUString& rROp )
974 {
975 if( check( !rStack.empty() ) )
976 rStack.top() = rLOp + rStack.top() + rROp;
977 }
978
pushBinaryOp(StringStack & rStack,const OUString & rOp)979 void FormulaStack::pushBinaryOp( StringStack& rStack, const OUString& rOp )
980 {
981 OUString aSecond;
982 if( check( !rStack.empty() ) )
983 {
984 aSecond = rStack.top();
985 rStack.pop();
986 }
987 if( check( !rStack.empty() ) )
988 rStack.top() = rStack.top() + rOp + aSecond;
989 }
990
pushFuncOp(StringStack & rStack,const OUString & rOp,sal_uInt8 nParamCount)991 void FormulaStack::pushFuncOp( StringStack& rStack, const OUString& rOp, sal_uInt8 nParamCount )
992 {
993 OUStringBuffer aFunc;
994 for( sal_uInt8 nParam = 0; (nParam < nParamCount) && check( !rStack.empty() ); ++nParam )
995 {
996 StringHelper::prependToken( aFunc, rStack.top(), OOX_DUMP_FUNCSEP );
997 rStack.pop();
998 }
999 StringHelper::enclose( aFunc, '(', ')' );
1000 aFunc.insert( 0, rOp );
1001 rStack.push( aFunc.makeStringAndClear() );
1002 }
1003
1004 // ============================================================================
1005 // ============================================================================
1006
~Base()1007 Base::~Base()
1008 {
1009 }
1010
1011 // ============================================================================
1012 // ============================================================================
1013
~ConfigItemBase()1014 ConfigItemBase::~ConfigItemBase()
1015 {
1016 }
1017
readConfigBlock(TextInputStream & rStrm)1018 void ConfigItemBase::readConfigBlock( TextInputStream& rStrm )
1019 {
1020 readConfigBlockContents( rStrm );
1021 }
1022
implProcessConfigItemStr(TextInputStream &,const OUString &,const OUString &)1023 void ConfigItemBase::implProcessConfigItemStr(
1024 TextInputStream& /*rStrm*/, const OUString& /*rKey*/, const OUString& /*rData*/ )
1025 {
1026 }
1027
implProcessConfigItemInt(TextInputStream &,sal_Int64,const OUString &)1028 void ConfigItemBase::implProcessConfigItemInt(
1029 TextInputStream& /*rStrm*/, sal_Int64 /*nKey*/, const OUString& /*rData*/ )
1030 {
1031 }
1032
readConfigBlockContents(TextInputStream & rStrm)1033 void ConfigItemBase::readConfigBlockContents( TextInputStream& rStrm )
1034 {
1035 bool bLoop = true;
1036 while( bLoop && !rStrm.isEof() )
1037 {
1038 OUString aKey, aData;
1039 switch( readConfigLine( rStrm, aKey, aData ) )
1040 {
1041 case LINETYPE_DATA:
1042 processConfigItem( rStrm, aKey, aData );
1043 break;
1044 case LINETYPE_END:
1045 bLoop = false;
1046 break;
1047 }
1048 }
1049 }
1050
readConfigLine(TextInputStream & rStrm,OUString & orKey,OUString & orData) const1051 ConfigItemBase::LineType ConfigItemBase::readConfigLine(
1052 TextInputStream& rStrm, OUString& orKey, OUString& orData ) const
1053 {
1054 OUString aLine;
1055 while( !rStrm.isEof() && (aLine.getLength() == 0) )
1056 {
1057 aLine = rStrm.readLine();
1058 if( (aLine.getLength() > 0) && (aLine[ 0 ] == OOX_DUMP_BOM) )
1059 aLine = aLine.copy( 1 );
1060 aLine = StringHelper::trimSpaces( aLine );
1061 if( aLine.getLength() > 0 )
1062 {
1063 // ignore comments (starting with hash or semicolon)
1064 sal_Unicode cChar = aLine[ 0 ];
1065 if( (cChar == '#') || (cChar == ';') )
1066 aLine = OUString();
1067 }
1068 }
1069
1070 OUStringPair aPair = StringHelper::convertStringToPair( aLine );
1071 orKey = aPair.first;
1072 orData = aPair.second;
1073 return ((orKey.getLength() > 0) && ((orData.getLength() > 0) || !orKey.equalsAscii( "end" ))) ?
1074 LINETYPE_DATA : LINETYPE_END;
1075 }
1076
readConfigLine(TextInputStream & rStrm) const1077 ConfigItemBase::LineType ConfigItemBase::readConfigLine( TextInputStream& rStrm ) const
1078 {
1079 OUString aKey, aData;
1080 return readConfigLine( rStrm, aKey, aData );
1081 }
1082
processConfigItem(TextInputStream & rStrm,const OUString & rKey,const OUString & rData)1083 void ConfigItemBase::processConfigItem(
1084 TextInputStream& rStrm, const OUString& rKey, const OUString& rData )
1085 {
1086 sal_Int64 nKey;
1087 if( StringHelper::convertStringToInt( nKey, rKey ) )
1088 implProcessConfigItemInt( rStrm, nKey, rData );
1089 else
1090 implProcessConfigItemStr( rStrm, rKey, rData );
1091 }
1092
1093 // ============================================================================
1094
~NameListBase()1095 NameListBase::~NameListBase()
1096 {
1097 }
1098
setName(sal_Int64 nKey,const String & rName)1099 void NameListBase::setName( sal_Int64 nKey, const String& rName )
1100 {
1101 implSetName( nKey, rName );
1102 }
1103
includeList(const NameListRef & rxList)1104 void NameListBase::includeList( const NameListRef& rxList )
1105 {
1106 if( rxList.get() )
1107 {
1108 for( const_iterator aIt = rxList->begin(), aEnd = rxList->end(); aIt != aEnd; ++aIt )
1109 maMap[ aIt->first ] = aIt->second;
1110 implIncludeList( *rxList );
1111 }
1112 }
1113
implIsValid() const1114 bool NameListBase::implIsValid() const
1115 {
1116 return true;
1117 }
1118
implProcessConfigItemStr(TextInputStream & rStrm,const OUString & rKey,const OUString & rData)1119 void NameListBase::implProcessConfigItemStr(
1120 TextInputStream& rStrm, const OUString& rKey, const OUString& rData )
1121 {
1122 if( rKey.equalsAscii( "include" ) )
1123 include( rData );
1124 else if( rKey.equalsAscii( "exclude" ) )
1125 exclude( rData );
1126 else
1127 ConfigItemBase::implProcessConfigItemStr( rStrm, rKey, rData );
1128 }
1129
implProcessConfigItemInt(TextInputStream &,sal_Int64 nKey,const OUString & rData)1130 void NameListBase::implProcessConfigItemInt(
1131 TextInputStream& /*rStrm*/, sal_Int64 nKey, const OUString& rData )
1132 {
1133 implSetName( nKey, rData );
1134 }
1135
insertRawName(sal_Int64 nKey,const OUString & rName)1136 void NameListBase::insertRawName( sal_Int64 nKey, const OUString& rName )
1137 {
1138 maMap[ nKey ] = rName;
1139 }
1140
findRawName(sal_Int64 nKey) const1141 const OUString* NameListBase::findRawName( sal_Int64 nKey ) const
1142 {
1143 const_iterator aIt = maMap.find( nKey );
1144 return (aIt == end()) ? 0 : &aIt->second;
1145 }
1146
include(const OUString & rListKeys)1147 void NameListBase::include( const OUString& rListKeys )
1148 {
1149 OUStringVector aVec;
1150 StringHelper::convertStringToStringList( aVec, rListKeys, true );
1151 for( OUStringVector::const_iterator aIt = aVec.begin(), aEnd = aVec.end(); aIt != aEnd; ++aIt )
1152 includeList( mrCfgData.getNameList( *aIt ) );
1153 }
1154
exclude(const OUString & rKeys)1155 void NameListBase::exclude( const OUString& rKeys )
1156 {
1157 Int64Vector aVec;
1158 StringHelper::convertStringToIntList( aVec, rKeys, true );
1159 for( Int64Vector::const_iterator aIt = aVec.begin(), aEnd = aVec.end(); aIt != aEnd; ++aIt )
1160 maMap.erase( *aIt );
1161 }
1162
1163 // ============================================================================
1164
insertFormats(const NameListRef & rxNameList)1165 void ItemFormatMap::insertFormats( const NameListRef& rxNameList )
1166 {
1167 if( Base::isValid( rxNameList ) )
1168 for( NameListBase::const_iterator aIt = rxNameList->begin(), aEnd = rxNameList->end(); aIt != aEnd; ++aIt )
1169 (*this)[ aIt->first ].parse( aIt->second );
1170 }
1171
1172 // ============================================================================
1173
ConstList(const SharedConfigData & rCfgData)1174 ConstList::ConstList( const SharedConfigData& rCfgData ) :
1175 NameListBase( rCfgData ),
1176 maDefName( OOX_DUMP_ERR_NONAME ),
1177 mbQuoteNames( false )
1178 {
1179 }
1180
implProcessConfigItemStr(TextInputStream & rStrm,const OUString & rKey,const OUString & rData)1181 void ConstList::implProcessConfigItemStr(
1182 TextInputStream& rStrm, const OUString& rKey, const OUString& rData )
1183 {
1184 if( rKey.equalsAscii( "default" ) )
1185 setDefaultName( rData );
1186 else if( rKey.equalsAscii( "quote-names" ) )
1187 setQuoteNames( StringHelper::convertStringToBool( rData ) );
1188 else
1189 NameListBase::implProcessConfigItemStr( rStrm, rKey, rData );
1190 }
1191
implSetName(sal_Int64 nKey,const OUString & rName)1192 void ConstList::implSetName( sal_Int64 nKey, const OUString& rName )
1193 {
1194 insertRawName( nKey, rName );
1195 }
1196
implGetName(const Config &,sal_Int64 nKey) const1197 OUString ConstList::implGetName( const Config& /*rCfg*/, sal_Int64 nKey ) const
1198 {
1199 const OUString* pName = findRawName( nKey );
1200 OUString aName = pName ? *pName : maDefName;
1201 if( mbQuoteNames )
1202 {
1203 OUStringBuffer aBuffer( aName );
1204 StringHelper::enclose( aBuffer, OOX_DUMP_STRQUOTE );
1205 aName = aBuffer.makeStringAndClear();
1206 }
1207 return aName;
1208 }
1209
implGetNameDbl(const Config &,double) const1210 OUString ConstList::implGetNameDbl( const Config& /*rCfg*/, double /*fValue*/ ) const
1211 {
1212 return OUString();
1213 }
1214
implIncludeList(const NameListBase & rList)1215 void ConstList::implIncludeList( const NameListBase& rList )
1216 {
1217 if( const ConstList* pConstList = dynamic_cast< const ConstList* >( &rList ) )
1218 {
1219 maDefName = pConstList->maDefName;
1220 mbQuoteNames = pConstList->mbQuoteNames;
1221 }
1222 }
1223
1224 // ============================================================================
1225
MultiList(const SharedConfigData & rCfgData)1226 MultiList::MultiList( const SharedConfigData& rCfgData ) :
1227 ConstList( rCfgData ),
1228 mbIgnoreEmpty( true )
1229 {
1230 }
1231
setNamesFromVec(sal_Int64 nStartKey,const OUStringVector & rNames)1232 void MultiList::setNamesFromVec( sal_Int64 nStartKey, const OUStringVector& rNames )
1233 {
1234 sal_Int64 nKey = nStartKey;
1235 for( OUStringVector::const_iterator aIt = rNames.begin(), aEnd = rNames.end(); aIt != aEnd; ++aIt, ++nKey )
1236 if( !mbIgnoreEmpty || (aIt->getLength() > 0) )
1237 insertRawName( nKey, *aIt );
1238 }
1239
implProcessConfigItemStr(TextInputStream & rStrm,const OUString & rKey,const OUString & rData)1240 void MultiList::implProcessConfigItemStr(
1241 TextInputStream& rStrm, const OUString& rKey, const OUString& rData )
1242 {
1243 if( rKey.equalsAscii( "ignore-empty" ) )
1244 mbIgnoreEmpty = StringHelper::convertStringToBool( rData );
1245 else
1246 ConstList::implProcessConfigItemStr( rStrm, rKey, rData );
1247 }
1248
implSetName(sal_Int64 nKey,const OUString & rName)1249 void MultiList::implSetName( sal_Int64 nKey, const OUString& rName )
1250 {
1251 OUStringVector aNames;
1252 StringHelper::convertStringToStringList( aNames, rName, false );
1253 setNamesFromVec( nKey, aNames );
1254 }
1255
1256 // ============================================================================
1257
FlagsList(const SharedConfigData & rCfgData)1258 FlagsList::FlagsList( const SharedConfigData& rCfgData ) :
1259 NameListBase( rCfgData ),
1260 mnIgnore( 0 )
1261 {
1262 }
1263
implProcessConfigItemStr(TextInputStream & rStrm,const OUString & rKey,const OUString & rData)1264 void FlagsList::implProcessConfigItemStr(
1265 TextInputStream& rStrm, const OUString& rKey, const OUString& rData )
1266 {
1267 if( rKey.equalsAscii( "ignore" ) )
1268 {
1269 sal_Int64 nIgnore;
1270 if( StringHelper::convertStringToInt( nIgnore, rData ) )
1271 setIgnoreFlags( nIgnore );
1272 }
1273 else
1274 {
1275 NameListBase::implProcessConfigItemStr( rStrm, rKey, rData );
1276 }
1277 }
1278
implSetName(sal_Int64 nKey,const OUString & rName)1279 void FlagsList::implSetName( sal_Int64 nKey, const OUString& rName )
1280 {
1281 if( (nKey != 0) && ((nKey & (nKey - 1)) == 0) ) // only a single bit set?
1282 insertRawName( nKey, rName );
1283 }
1284
implGetName(const Config &,sal_Int64 nKey) const1285 OUString FlagsList::implGetName( const Config& /*rCfg*/, sal_Int64 nKey ) const
1286 {
1287 sal_Int64 nFound = mnIgnore;
1288 OUStringBuffer aName;
1289 // add known flags
1290 for( const_iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt )
1291 {
1292 sal_Int64 nMask = aIt->first;
1293 setFlag( nFound, nMask );
1294 if( !getFlag( mnIgnore, nMask ) )
1295 {
1296 const OUString& rFlagName = aIt->second;
1297 bool bOnOff = (rFlagName.getLength() > 0) && (rFlagName[ 0 ] == ':');
1298 bool bFlag = getFlag( nKey, nMask );
1299 if( bOnOff )
1300 {
1301 StringHelper::appendToken( aName, rFlagName.copy( 1 ) );
1302 aName.appendAscii( bFlag ? ":on" : ":off" );
1303 }
1304 else
1305 {
1306 bool bNegated = (rFlagName.getLength() > 0) && (rFlagName[ 0 ] == '!');
1307 sal_Int32 nBothSep = bNegated ? rFlagName.indexOf( '!', 1 ) : -1;
1308 if( bFlag )
1309 {
1310 if( !bNegated )
1311 StringHelper::appendToken( aName, rFlagName );
1312 else if( nBothSep > 0 )
1313 StringHelper::appendToken( aName, rFlagName.copy( nBothSep + 1 ) );
1314 }
1315 else if( bNegated )
1316 {
1317 if( nBothSep > 0 )
1318 StringHelper::appendToken( aName, rFlagName.copy( 1, nBothSep - 1 ) );
1319 else
1320 StringHelper::appendToken( aName, rFlagName.copy( 1 ) );
1321 }
1322 }
1323 }
1324 }
1325 // add unknown flags
1326 setFlag( nKey, nFound, false );
1327 if( nKey != 0 )
1328 {
1329 OUStringBuffer aUnknown( CREATE_OUSTRING( OOX_DUMP_UNKNOWN ) );
1330 aUnknown.append( OOX_DUMP_ITEMSEP );
1331 StringHelper::appendShortHex( aUnknown, nKey, true );
1332 StringHelper::enclose( aUnknown, '(', ')' );
1333 StringHelper::appendToken( aName, aUnknown.makeStringAndClear() );
1334 }
1335 return aName.makeStringAndClear();
1336 }
1337
implGetNameDbl(const Config &,double) const1338 OUString FlagsList::implGetNameDbl( const Config& /*rCfg*/, double /*fValue*/ ) const
1339 {
1340 return OUString();
1341 }
1342
implIncludeList(const NameListBase & rList)1343 void FlagsList::implIncludeList( const NameListBase& rList )
1344 {
1345 if( const FlagsList* pFlagsList = dynamic_cast< const FlagsList* >( &rList ) )
1346 mnIgnore = pFlagsList->mnIgnore;
1347 }
1348
1349 // ============================================================================
1350
operator <(const ExtItemFormatKey & rRight) const1351 bool CombiList::ExtItemFormatKey::operator<( const ExtItemFormatKey& rRight ) const
1352 {
1353 return (mnKey < rRight.mnKey) || ((mnKey == rRight.mnKey) && (maFilter < rRight.maFilter));
1354 }
1355
CombiList(const SharedConfigData & rCfgData)1356 CombiList::CombiList( const SharedConfigData& rCfgData ) :
1357 FlagsList( rCfgData )
1358 {
1359 }
1360
implSetName(sal_Int64 nKey,const OUString & rName)1361 void CombiList::implSetName( sal_Int64 nKey, const OUString& rName )
1362 {
1363 if( (nKey & (nKey - 1)) != 0 ) // more than a single bit set?
1364 {
1365 typedef ::std::set< ExtItemFormatKey > ExtItemFormatKeySet;
1366 ::std::set< ExtItemFormatKey > aItemKeys;
1367 ExtItemFormat aItemFmt;
1368 OUStringVector aRemain = aItemFmt.parse( rName );
1369 for( OUStringVector::iterator aIt = aRemain.begin(), aEnd = aRemain.end(); aIt != aEnd; ++aIt )
1370 {
1371 OUStringPair aPair = StringHelper::convertStringToPair( *aIt );
1372 if( aPair.first.equalsAscii( "noshift" ) )
1373 {
1374 aItemFmt.mbShiftValue = StringHelper::convertStringToBool( aPair.second );
1375 }
1376 else if( aPair.first.equalsAscii( "filter" ) )
1377 {
1378 OUStringPair aFilter = StringHelper::convertStringToPair( aPair.second, '~' );
1379 ExtItemFormatKey aKey( nKey );
1380 if( (aFilter.first.getLength() > 0) && StringHelper::convertStringToInt( aKey.maFilter.first, aFilter.first ) &&
1381 (aFilter.second.getLength() > 0) && StringHelper::convertStringToInt( aKey.maFilter.second, aFilter.second ) )
1382 {
1383 if( aKey.maFilter.first == 0 )
1384 aKey.maFilter.second = 0;
1385 aItemKeys.insert( aKey );
1386 }
1387 }
1388 }
1389 if( aItemKeys.empty() )
1390 aItemKeys.insert( ExtItemFormatKey( nKey ) );
1391 for( ExtItemFormatKeySet::iterator aIt = aItemKeys.begin(), aEnd = aItemKeys.end(); aIt != aEnd; ++aIt )
1392 maFmtMap[ *aIt ] = aItemFmt;
1393 }
1394 else
1395 {
1396 FlagsList::implSetName( nKey, rName );
1397 }
1398 }
1399
implGetName(const Config & rCfg,sal_Int64 nKey) const1400 OUString CombiList::implGetName( const Config& rCfg, sal_Int64 nKey ) const
1401 {
1402 sal_Int64 nFound = 0;
1403 OUStringBuffer aName;
1404 // add known flag fields
1405 for( ExtItemFormatMap::const_iterator aIt = maFmtMap.begin(), aEnd = maFmtMap.end(); aIt != aEnd; ++aIt )
1406 {
1407 const ExtItemFormatKey& rMapKey = aIt->first;
1408 sal_Int64 nMask = rMapKey.mnKey;
1409 if( (nMask != 0) && ((nKey & rMapKey.maFilter.first) == rMapKey.maFilter.second) )
1410 {
1411 const ExtItemFormat& rItemFmt = aIt->second;
1412
1413 sal_uInt64 nUFlags = static_cast< sal_uInt64 >( nKey );
1414 sal_uInt64 nUMask = static_cast< sal_uInt64 >( nMask );
1415 if( rItemFmt.mbShiftValue )
1416 while( (nUMask & 1) == 0 ) { nUFlags >>= 1; nUMask >>= 1; }
1417
1418 sal_uInt64 nUValue = nUFlags & nUMask;
1419 sal_Int64 nSValue = static_cast< sal_Int64 >( nUValue );
1420 if( getFlag< sal_uInt64 >( nUValue, (nUMask + 1) >> 1 ) )
1421 setFlag( nSValue, static_cast< sal_Int64 >( ~nUMask ) );
1422
1423 OUStringBuffer aItem( rItemFmt.maItemName );
1424 OUStringBuffer aValue;
1425 switch( rItemFmt.meDataType )
1426 {
1427 case DATATYPE_INT8: StringHelper::appendValue( aValue, static_cast< sal_Int8 >( nSValue ), rItemFmt.meFmtType ); break;
1428 case DATATYPE_UINT8: StringHelper::appendValue( aValue, static_cast< sal_uInt8 >( nUValue ), rItemFmt.meFmtType ); break;
1429 case DATATYPE_INT16: StringHelper::appendValue( aValue, static_cast< sal_Int16 >( nSValue ), rItemFmt.meFmtType ); break;
1430 case DATATYPE_UINT16: StringHelper::appendValue( aValue, static_cast< sal_uInt16 >( nUValue ), rItemFmt.meFmtType ); break;
1431 case DATATYPE_INT32: StringHelper::appendValue( aValue, static_cast< sal_Int32 >( nSValue ), rItemFmt.meFmtType ); break;
1432 case DATATYPE_UINT32: StringHelper::appendValue( aValue, static_cast< sal_uInt32 >( nUValue ), rItemFmt.meFmtType ); break;
1433 case DATATYPE_INT64: StringHelper::appendValue( aValue, nSValue, rItemFmt.meFmtType ); break;
1434 case DATATYPE_UINT64: StringHelper::appendValue( aValue, nUValue, rItemFmt.meFmtType ); break;
1435 case DATATYPE_FLOAT: StringHelper::appendValue( aValue, static_cast< float >( nSValue ), rItemFmt.meFmtType ); break;
1436 case DATATYPE_DOUBLE: StringHelper::appendValue( aValue, static_cast< double >( nSValue ), rItemFmt.meFmtType ); break;
1437 default:;
1438 }
1439 StringHelper::appendToken( aItem, aValue.makeStringAndClear(), OOX_DUMP_ITEMSEP );
1440 if( rItemFmt.maListName.getLength() > 0 )
1441 {
1442 OUString aValueName = rCfg.getName( rItemFmt.maListName, static_cast< sal_Int64 >( nUValue ) );
1443 StringHelper::appendToken( aItem, aValueName, OOX_DUMP_ITEMSEP );
1444 }
1445 StringHelper::enclose( aItem, '(', ')' );
1446 StringHelper::appendToken( aName, aItem.makeStringAndClear() );
1447 setFlag( nFound, nMask );
1448 }
1449 }
1450 setFlag( nKey, nFound, false );
1451 StringHelper::appendToken( aName, FlagsList::implGetName( rCfg, nKey ) );
1452 return aName.makeStringAndClear();
1453 }
1454
implIncludeList(const NameListBase & rList)1455 void CombiList::implIncludeList( const NameListBase& rList )
1456 {
1457 if( const CombiList* pCombiList = dynamic_cast< const CombiList* >( &rList ) )
1458 maFmtMap = pCombiList->maFmtMap;
1459 FlagsList::implIncludeList( rList );
1460 }
1461
1462 // ============================================================================
1463
UnitConverter(const SharedConfigData & rCfgData)1464 UnitConverter::UnitConverter( const SharedConfigData& rCfgData ) :
1465 NameListBase( rCfgData ),
1466 mfFactor( 1.0 )
1467 {
1468 }
1469
implSetName(sal_Int64,const OUString &)1470 void UnitConverter::implSetName( sal_Int64 /*nKey*/, const OUString& /*rName*/ )
1471 {
1472 // nothing to do
1473 }
1474
implGetName(const Config & rCfg,sal_Int64 nKey) const1475 OUString UnitConverter::implGetName( const Config& rCfg, sal_Int64 nKey ) const
1476 {
1477 return implGetNameDbl( rCfg, static_cast< double >( nKey ) );
1478 }
1479
implGetNameDbl(const Config &,double fValue) const1480 OUString UnitConverter::implGetNameDbl( const Config& /*rCfg*/, double fValue ) const
1481 {
1482 OUStringBuffer aValue;
1483 StringHelper::appendDec( aValue, mfFactor * fValue );
1484 aValue.append( maUnitName );
1485 return aValue.makeStringAndClear();
1486 }
1487
implIncludeList(const NameListBase &)1488 void UnitConverter::implIncludeList( const NameListBase& /*rList*/ )
1489 {
1490 }
1491
1492 // ============================================================================
1493
getNameList(const Config & rCfg) const1494 NameListRef NameListWrapper::getNameList( const Config& rCfg ) const
1495 {
1496 return mxList.get() ? mxList : (mxList = rCfg.getNameList( maName ));
1497 }
1498
1499 // ============================================================================
1500 // ============================================================================
1501
SharedConfigData(const OUString & rFileName,const Reference<XComponentContext> & rxContext,const StorageRef & rxRootStrg,const OUString & rSysFileName,MediaDescriptor & rMediaDesc)1502 SharedConfigData::SharedConfigData( const OUString& rFileName,
1503 const Reference< XComponentContext >& rxContext, const StorageRef& rxRootStrg,
1504 const OUString& rSysFileName, MediaDescriptor& rMediaDesc ) :
1505 mxContext( rxContext ),
1506 mxRootStrg( rxRootStrg ),
1507 maSysFileName( rSysFileName ),
1508 mrMediaDesc( rMediaDesc ),
1509 mbLoaded( false ),
1510 mbPwCancelled( false )
1511 {
1512 OUString aFileUrl = InputOutputHelper::convertFileNameToUrl( rFileName );
1513 if( aFileUrl.getLength() > 0 )
1514 {
1515 sal_Int32 nNamePos = InputOutputHelper::getFileNamePos( aFileUrl );
1516 maConfigPath = aFileUrl.copy( 0, nNamePos );
1517 mbLoaded = readConfigFile( aFileUrl );
1518 }
1519 }
1520
~SharedConfigData()1521 SharedConfigData::~SharedConfigData()
1522 {
1523 }
1524
setOption(const OUString & rKey,const OUString & rData)1525 void SharedConfigData::setOption( const OUString& rKey, const OUString& rData )
1526 {
1527 maConfigData[ rKey ] = rData;
1528 }
1529
getOption(const OUString & rKey) const1530 const OUString* SharedConfigData::getOption( const OUString& rKey ) const
1531 {
1532 ConfigDataMap::const_iterator aIt = maConfigData.find( rKey );
1533 return (aIt == maConfigData.end()) ? 0 : &aIt->second;
1534 }
1535
setNameList(const OUString & rListName,const NameListRef & rxList)1536 void SharedConfigData::setNameList( const OUString& rListName, const NameListRef& rxList )
1537 {
1538 if( rListName.getLength() > 0 )
1539 maNameLists[ rListName ] = rxList;
1540 }
1541
eraseNameList(const OUString & rListName)1542 void SharedConfigData::eraseNameList( const OUString& rListName )
1543 {
1544 maNameLists.erase( rListName );
1545 }
1546
getNameList(const OUString & rListName) const1547 NameListRef SharedConfigData::getNameList( const OUString& rListName ) const
1548 {
1549 NameListRef xList;
1550 NameListMap::const_iterator aIt = maNameLists.find( rListName );
1551 if( aIt != maNameLists.end() )
1552 xList = aIt->second;
1553 return xList;
1554 }
1555
requestEncryptionData(::comphelper::IDocPasswordVerifier & rVerifier)1556 Sequence< NamedValue > SharedConfigData::requestEncryptionData( ::comphelper::IDocPasswordVerifier& rVerifier )
1557 {
1558 Sequence< NamedValue > aEncryptionData;
1559 if( !mbPwCancelled )
1560 {
1561 ::std::vector< OUString > aDefaultPasswords;
1562 aDefaultPasswords.push_back( CREATE_OUSTRING( "VelvetSweatshop" ) );
1563 aEncryptionData = ::comphelper::DocPasswordHelper::requestAndVerifyDocPassword(
1564 rVerifier, mrMediaDesc, ::comphelper::DocPasswordRequestType_MS, &aDefaultPasswords );
1565 mbPwCancelled = !aEncryptionData.hasElements();
1566 }
1567 return aEncryptionData;
1568 }
1569
implIsValid() const1570 bool SharedConfigData::implIsValid() const
1571 {
1572 return mbLoaded && mxContext.is() && mxRootStrg.get() && (maSysFileName.getLength() > 0);
1573 }
1574
implProcessConfigItemStr(TextInputStream & rStrm,const OUString & rKey,const OUString & rData)1575 void SharedConfigData::implProcessConfigItemStr(
1576 TextInputStream& rStrm, const OUString& rKey, const OUString& rData )
1577 {
1578 if( rKey.equalsAscii( "include-config-file" ) )
1579 readConfigFile( maConfigPath + rData );
1580 else if( rKey.equalsAscii( "constlist" ) )
1581 readNameList< ConstList >( rStrm, rData );
1582 else if( rKey.equalsAscii( "multilist" ) )
1583 readNameList< MultiList >( rStrm, rData );
1584 else if( rKey.equalsAscii( "flagslist" ) )
1585 readNameList< FlagsList >( rStrm, rData );
1586 else if( rKey.equalsAscii( "combilist" ) )
1587 readNameList< CombiList >( rStrm, rData );
1588 else if( rKey.equalsAscii( "shortlist" ) )
1589 createShortList( rData );
1590 else if( rKey.equalsAscii( "unitconverter" ) )
1591 createUnitConverter( rData );
1592 else
1593 setOption( rKey, rData );
1594 }
1595
readConfigFile(const OUString & rFileUrl)1596 bool SharedConfigData::readConfigFile( const OUString& rFileUrl )
1597 {
1598 bool bLoaded = maConfigFiles.count( rFileUrl ) > 0;
1599 if( !bLoaded )
1600 {
1601 Reference< XInputStream > xInStrm = InputOutputHelper::openInputStream( mxContext, rFileUrl );
1602 TextInputStream aTxtStrm( mxContext, xInStrm, RTL_TEXTENCODING_UTF8 );
1603 if( !aTxtStrm.isEof() )
1604 {
1605 maConfigFiles.insert( rFileUrl );
1606 readConfigBlockContents( aTxtStrm );
1607 bLoaded = true;
1608 }
1609 }
1610 return bLoaded;
1611 }
1612
createShortList(const OUString & rData)1613 void SharedConfigData::createShortList( const OUString& rData )
1614 {
1615 OUStringVector aDataVec;
1616 StringHelper::convertStringToStringList( aDataVec, rData, false );
1617 if( aDataVec.size() >= 3 )
1618 {
1619 sal_Int64 nStartKey;
1620 if( StringHelper::convertStringToInt( nStartKey, aDataVec[ 1 ] ) )
1621 {
1622 ::boost::shared_ptr< MultiList > xList = createNameList< MultiList >( aDataVec[ 0 ] );
1623 if( xList.get() )
1624 {
1625 aDataVec.erase( aDataVec.begin(), aDataVec.begin() + 2 );
1626 xList->setNamesFromVec( nStartKey, aDataVec );
1627 }
1628 }
1629 }
1630 }
1631
createUnitConverter(const OUString & rData)1632 void SharedConfigData::createUnitConverter( const OUString& rData )
1633 {
1634 OUStringVector aDataVec;
1635 StringHelper::convertStringToStringList( aDataVec, rData, false );
1636 if( aDataVec.size() >= 2 )
1637 {
1638 OUString aFactor = aDataVec[ 1 ];
1639 bool bRecip = (aFactor.getLength() > 0) && (aFactor[ 0 ] == '/');
1640 if( bRecip )
1641 aFactor = aFactor.copy( 1 );
1642 double fFactor;
1643 if( StringHelper::convertStringToDouble( fFactor, aFactor ) && (fFactor != 0.0) )
1644 {
1645 ::boost::shared_ptr< UnitConverter > xList = createNameList< UnitConverter >( aDataVec[ 0 ] );
1646 if( xList.get() )
1647 {
1648 xList->setFactor( bRecip ? (1.0 / fFactor) : fFactor );
1649 if( aDataVec.size() >= 3 )
1650 xList->setUnitName( aDataVec[ 2 ] );
1651 }
1652 }
1653 }
1654 }
1655
1656 // ============================================================================
1657
Config(const Config & rParent)1658 Config::Config( const Config& rParent ) :
1659 Base() // c'tor needs to be called explicitly to avoid compiler warning
1660 {
1661 construct( rParent );
1662 }
1663
Config(const sal_Char * pcEnvVar,const FilterBase & rFilter)1664 Config::Config( const sal_Char* pcEnvVar, const FilterBase& rFilter )
1665 {
1666 construct( pcEnvVar, rFilter );
1667 }
1668
Config(const sal_Char * pcEnvVar,const Reference<XComponentContext> & rxContext,const StorageRef & rxRootStrg,const OUString & rSysFileName,MediaDescriptor & rMediaDesc)1669 Config::Config( const sal_Char* pcEnvVar, const Reference< XComponentContext >& rxContext, const StorageRef& rxRootStrg, const OUString& rSysFileName, MediaDescriptor& rMediaDesc )
1670 {
1671 construct( pcEnvVar, rxContext, rxRootStrg, rSysFileName, rMediaDesc );
1672 }
1673
~Config()1674 Config::~Config()
1675 {
1676 }
1677
construct(const Config & rParent)1678 void Config::construct( const Config& rParent )
1679 {
1680 *this = rParent;
1681 }
1682
construct(const sal_Char * pcEnvVar,const FilterBase & rFilter)1683 void Config::construct( const sal_Char* pcEnvVar, const FilterBase& rFilter )
1684 {
1685 if( rFilter.getFileUrl().getLength() > 0 )
1686 construct( pcEnvVar, rFilter.getComponentContext(), rFilter.getStorage(), rFilter.getFileUrl(), rFilter.getMediaDescriptor() );
1687 }
1688
construct(const sal_Char * pcEnvVar,const Reference<XComponentContext> & rxContext,const StorageRef & rxRootStrg,const OUString & rSysFileName,MediaDescriptor & rMediaDesc)1689 void Config::construct( const sal_Char* pcEnvVar, const Reference< XComponentContext >& rxContext, const StorageRef& rxRootStrg, const OUString& rSysFileName, MediaDescriptor& rMediaDesc )
1690 {
1691 if( pcEnvVar && rxRootStrg.get() && (rSysFileName.getLength() > 0) )
1692 if( const sal_Char* pcFileName = ::getenv( pcEnvVar ) )
1693 mxCfgData.reset( new SharedConfigData( OUString::createFromAscii( pcFileName ), rxContext, rxRootStrg, rSysFileName, rMediaDesc ) );
1694 }
1695
setStringOption(const String & rKey,const String & rData)1696 void Config::setStringOption( const String& rKey, const String& rData )
1697 {
1698 mxCfgData->setOption( rKey, rData );
1699 }
1700
getStringOption(const String & rKey,const OUString & rDefault) const1701 const OUString& Config::getStringOption( const String& rKey, const OUString& rDefault ) const
1702 {
1703 const OUString* pData = implGetOption( rKey );
1704 return pData ? *pData : rDefault;
1705 }
1706
getBoolOption(const String & rKey,bool bDefault) const1707 bool Config::getBoolOption( const String& rKey, bool bDefault ) const
1708 {
1709 const OUString* pData = implGetOption( rKey );
1710 return pData ? StringHelper::convertStringToBool( *pData ) : bDefault;
1711 }
1712
isDumperEnabled() const1713 bool Config::isDumperEnabled() const
1714 {
1715 return getBoolOption( "enable-dumper", false );
1716 }
1717
isImportEnabled() const1718 bool Config::isImportEnabled() const
1719 {
1720 return getBoolOption( "enable-import", true );
1721 }
1722
setNameList(const String & rListName,const NameListRef & rxList)1723 void Config::setNameList( const String& rListName, const NameListRef& rxList )
1724 {
1725 mxCfgData->setNameList( rListName, rxList );
1726 }
1727
eraseNameList(const String & rListName)1728 void Config::eraseNameList( const String& rListName )
1729 {
1730 mxCfgData->eraseNameList( rListName );
1731 }
1732
getNameList(const String & rListName) const1733 NameListRef Config::getNameList( const String& rListName ) const
1734 {
1735 return implGetNameList( rListName );
1736 }
1737
requestEncryptionData(::comphelper::IDocPasswordVerifier & rVerifier)1738 Sequence< NamedValue > Config::requestEncryptionData( ::comphelper::IDocPasswordVerifier& rVerifier )
1739 {
1740 return mxCfgData->requestEncryptionData( rVerifier );
1741 }
1742
isPasswordCancelled() const1743 bool Config::isPasswordCancelled() const
1744 {
1745 return mxCfgData->isPasswordCancelled();
1746 }
1747
implIsValid() const1748 bool Config::implIsValid() const
1749 {
1750 return isValid( mxCfgData );
1751 }
1752
implGetOption(const OUString & rKey) const1753 const OUString* Config::implGetOption( const OUString& rKey ) const
1754 {
1755 return mxCfgData->getOption( rKey );
1756 }
1757
implGetNameList(const OUString & rListName) const1758 NameListRef Config::implGetNameList( const OUString& rListName ) const
1759 {
1760 return mxCfgData->getNameList( rListName );
1761 }
1762
1763 // ============================================================================
1764 // ============================================================================
1765
Output(const Reference<XComponentContext> & rxContext,const OUString & rFileName)1766 Output::Output( const Reference< XComponentContext >& rxContext, const OUString& rFileName ) :
1767 mxStrm( InputOutputHelper::openTextOutputStream( rxContext, rFileName, RTL_TEXTENCODING_UTF8 ) ),
1768 mnCol( 0 ),
1769 mnItemLevel( 0 ),
1770 mnMultiLevel( 0 ),
1771 mnItemIdx( 0 ),
1772 mnLastItem( 0 )
1773 {
1774 if( mxStrm.is() )
1775 mxStrm->writeString( OUString( OOX_DUMP_BOM ) );
1776 }
1777
1778 // ----------------------------------------------------------------------------
1779
newLine()1780 void Output::newLine()
1781 {
1782 if( maLine.getLength() > 0 )
1783 {
1784 mxStrm->writeString( maIndent );
1785 maLine.append( sal_Unicode( '\n' ) );
1786 mxStrm->writeString( maLine.makeStringAndClear() );
1787 mnCol = 0;
1788 mnLastItem = 0;
1789 }
1790 }
1791
emptyLine(size_t nCount)1792 void Output::emptyLine( size_t nCount )
1793 {
1794 for( size_t nIdx = 0; nIdx < nCount; ++nIdx )
1795 mxStrm->writeString( OUString( sal_Unicode( '\n' ) ) );
1796 }
1797
incIndent()1798 void Output::incIndent()
1799 {
1800 OUStringBuffer aBuffer( maIndent );
1801 StringHelper::appendChar( aBuffer, ' ', OOX_DUMP_INDENT );
1802 maIndent = aBuffer.makeStringAndClear();
1803 }
1804
decIndent()1805 void Output::decIndent()
1806 {
1807 if( maIndent.getLength() >= OOX_DUMP_INDENT )
1808 maIndent = maIndent.copy( OOX_DUMP_INDENT );
1809 }
1810
resetIndent()1811 void Output::resetIndent()
1812 {
1813 maIndent = OUString();
1814 }
1815
startTable(sal_Int32 nW1)1816 void Output::startTable( sal_Int32 nW1 )
1817 {
1818 startTable( 1, &nW1 );
1819 }
1820
startTable(sal_Int32 nW1,sal_Int32 nW2)1821 void Output::startTable( sal_Int32 nW1, sal_Int32 nW2 )
1822 {
1823 sal_Int32 pnColWidths[ 2 ];
1824 pnColWidths[ 0 ] = nW1;
1825 pnColWidths[ 1 ] = nW2;
1826 startTable( 2, pnColWidths );
1827 }
1828
startTable(sal_Int32 nW1,sal_Int32 nW2,sal_Int32 nW3)1829 void Output::startTable( sal_Int32 nW1, sal_Int32 nW2, sal_Int32 nW3 )
1830 {
1831 sal_Int32 pnColWidths[ 3 ];
1832 pnColWidths[ 0 ] = nW1;
1833 pnColWidths[ 1 ] = nW2;
1834 pnColWidths[ 2 ] = nW3;
1835 startTable( 3, pnColWidths );
1836 }
1837
startTable(sal_Int32 nW1,sal_Int32 nW2,sal_Int32 nW3,sal_Int32 nW4)1838 void Output::startTable( sal_Int32 nW1, sal_Int32 nW2, sal_Int32 nW3, sal_Int32 nW4 )
1839 {
1840 sal_Int32 pnColWidths[ 4 ];
1841 pnColWidths[ 0 ] = nW1;
1842 pnColWidths[ 1 ] = nW2;
1843 pnColWidths[ 2 ] = nW3;
1844 pnColWidths[ 3 ] = nW4;
1845 startTable( 4, pnColWidths );
1846 }
1847
startTable(size_t nColCount,const sal_Int32 * pnColWidths)1848 void Output::startTable( size_t nColCount, const sal_Int32* pnColWidths )
1849 {
1850 maColPos.clear();
1851 maColPos.push_back( 0 );
1852 sal_Int32 nColPos = 0;
1853 for( size_t nCol = 0; nCol < nColCount; ++nCol )
1854 {
1855 nColPos = nColPos + pnColWidths[ nCol ];
1856 maColPos.push_back( nColPos );
1857 }
1858 }
1859
tab()1860 void Output::tab()
1861 {
1862 tab( mnCol + 1 );
1863 }
1864
tab(size_t nCol)1865 void Output::tab( size_t nCol )
1866 {
1867 mnCol = nCol;
1868 if( mnCol < maColPos.size() )
1869 {
1870 sal_Int32 nColPos = maColPos[ mnCol ];
1871 if( maLine.getLength() >= nColPos )
1872 maLine.setLength( ::std::max< sal_Int32 >( nColPos - 1, 0 ) );
1873 StringHelper::appendChar( maLine, ' ', nColPos - maLine.getLength() );
1874 }
1875 else
1876 {
1877 StringHelper::appendChar( maLine, ' ', 2 );
1878 }
1879 }
1880
endTable()1881 void Output::endTable()
1882 {
1883 maColPos.clear();
1884 }
1885
resetItemIndex(sal_Int64 nIdx)1886 void Output::resetItemIndex( sal_Int64 nIdx )
1887 {
1888 mnItemIdx = nIdx;
1889 }
1890
startItem(const String & rItemName)1891 void Output::startItem( const String& rItemName )
1892 {
1893 if( mnItemLevel == 0 )
1894 {
1895 if( (mnMultiLevel > 0) && (maLine.getLength() > 0) )
1896 tab();
1897 if( rItemName.has() )
1898 {
1899 writeItemName( rItemName );
1900 writeChar( OOX_DUMP_ITEMSEP );
1901 }
1902 }
1903 ++mnItemLevel;
1904 mnLastItem = maLine.getLength();
1905 }
1906
contItem()1907 void Output::contItem()
1908 {
1909 if( mnItemLevel > 0 )
1910 {
1911 if( (maLine.getLength() == 0) || (maLine[ maLine.getLength() - 1 ] != OOX_DUMP_ITEMSEP) )
1912 writeChar( OOX_DUMP_ITEMSEP );
1913 mnLastItem = maLine.getLength();
1914 }
1915 }
1916
endItem()1917 void Output::endItem()
1918 {
1919 if( mnItemLevel > 0 )
1920 {
1921 maLastItem = OUString( maLine.getStr() + mnLastItem );
1922 if( (maLastItem.getLength() == 0) && (mnLastItem > 0) && (maLine[ mnLastItem - 1 ] == OOX_DUMP_ITEMSEP) )
1923 maLine.setLength( mnLastItem - 1 );
1924 --mnItemLevel;
1925 }
1926 if( mnItemLevel == 0 )
1927 {
1928 if( mnMultiLevel == 0 )
1929 newLine();
1930 }
1931 else
1932 contItem();
1933 }
1934
startMultiItems()1935 void Output::startMultiItems()
1936 {
1937 ++mnMultiLevel;
1938 }
1939
endMultiItems()1940 void Output::endMultiItems()
1941 {
1942 if( mnMultiLevel > 0 )
1943 --mnMultiLevel;
1944 if( mnMultiLevel == 0 )
1945 newLine();
1946 }
1947
1948 // ----------------------------------------------------------------------------
1949
writeChar(sal_Unicode cChar,sal_Int32 nCount)1950 void Output::writeChar( sal_Unicode cChar, sal_Int32 nCount )
1951 {
1952 StringHelper::appendEncChar( maLine, cChar, nCount );
1953 }
1954
writeAscii(const sal_Char * pcStr)1955 void Output::writeAscii( const sal_Char* pcStr )
1956 {
1957 if( pcStr )
1958 maLine.appendAscii( pcStr );
1959 }
1960
writeString(const OUString & rStr)1961 void Output::writeString( const OUString& rStr )
1962 {
1963 StringHelper::appendEncString( maLine, rStr );
1964 }
1965
writeArray(const sal_uInt8 * pnData,sal_Size nSize,sal_Unicode cSep)1966 void Output::writeArray( const sal_uInt8* pnData, sal_Size nSize, sal_Unicode cSep )
1967 {
1968 const sal_uInt8* pnEnd = pnData ? (pnData + nSize) : 0;
1969 for( const sal_uInt8* pnByte = pnData; pnByte < pnEnd; ++pnByte )
1970 {
1971 if( pnByte > pnData )
1972 writeChar( cSep );
1973 writeHex( *pnByte, false );
1974 }
1975 }
1976
writeBool(bool bData)1977 void Output::writeBool( bool bData )
1978 {
1979 StringHelper::appendBool( maLine, bData );
1980 }
1981
writeColorABGR(sal_Int32 nColor)1982 void Output::writeColorABGR( sal_Int32 nColor )
1983 {
1984 writeChar( 'a' );
1985 writeDec( static_cast< sal_uInt8 >( nColor >> 24 ) );
1986 writeAscii( ",r" );
1987 writeDec( static_cast< sal_uInt8 >( nColor ) );
1988 writeAscii( ",g" );
1989 writeDec( static_cast< sal_uInt8 >( nColor >> 8 ) );
1990 writeAscii( ",b" );
1991 writeDec( static_cast< sal_uInt8 >( nColor >> 16 ) );
1992 }
1993
writeDateTime(const DateTime & rDateTime)1994 void Output::writeDateTime( const DateTime& rDateTime )
1995 {
1996 writeDec( rDateTime.Year, 4, '0' );
1997 writeChar( '-' );
1998 writeDec( rDateTime.Month, 2, '0' );
1999 writeChar( '-' );
2000 writeDec( rDateTime.Day, 2, '0' );
2001 writeChar( 'T' );
2002 writeDec( rDateTime.Hours, 2, '0' );
2003 writeChar( ':' );
2004 writeDec( rDateTime.Minutes, 2, '0' );
2005 writeChar( ':' );
2006 writeDec( rDateTime.Seconds, 2, '0' );
2007 }
2008
writeColIndex(sal_Int32 nCol)2009 void Output::writeColIndex( sal_Int32 nCol )
2010 {
2011 StringHelper::appendAddrCol( maLine, nCol, true );
2012 }
2013
writeRowIndex(sal_Int32 nRow)2014 void Output::writeRowIndex( sal_Int32 nRow )
2015 {
2016 StringHelper::appendAddrRow( maLine, nRow, true );
2017 }
2018
writeColRowRange(sal_Int32 nColRow1,sal_Int32 nColRow2)2019 void Output::writeColRowRange( sal_Int32 nColRow1, sal_Int32 nColRow2 )
2020 {
2021 writeDec( nColRow1 );
2022 writeChar( OOX_DUMP_RANGESEP );
2023 writeDec( nColRow2 );
2024 }
2025
writeColRange(sal_Int32 nCol1,sal_Int32 nCol2)2026 void Output::writeColRange( sal_Int32 nCol1, sal_Int32 nCol2 )
2027 {
2028 writeColIndex( nCol1 );
2029 writeChar( OOX_DUMP_RANGESEP );
2030 writeColIndex( nCol2 );
2031 }
2032
writeRowRange(sal_Int32 nRow1,sal_Int32 nRow2)2033 void Output::writeRowRange( sal_Int32 nRow1, sal_Int32 nRow2 )
2034 {
2035 writeRowIndex( nRow1 );
2036 writeChar( OOX_DUMP_RANGESEP );
2037 writeRowIndex( nRow2 );
2038 }
2039
writeAddress(const Address & rPos)2040 void Output::writeAddress( const Address& rPos )
2041 {
2042 StringHelper::appendAddress( maLine, rPos );
2043 }
2044
writeRange(const Range & rRange)2045 void Output::writeRange( const Range& rRange )
2046 {
2047 StringHelper::appendRange( maLine, rRange );
2048 }
2049
writeRangeList(const RangeList & rRanges)2050 void Output::writeRangeList( const RangeList& rRanges )
2051 {
2052 StringHelper::appendRangeList( maLine, rRanges );
2053 }
2054
2055 // ----------------------------------------------------------------------------
2056
implIsValid() const2057 bool Output::implIsValid() const
2058 {
2059 return mxStrm.is();
2060 }
2061
writeItemName(const String & rItemName)2062 void Output::writeItemName( const String& rItemName )
2063 {
2064 if( rItemName.has() && (rItemName[ 0 ] == '#') )
2065 {
2066 writeString( rItemName.copy( 1 ) );
2067 StringHelper::appendIndex( maLine, mnItemIdx++ );
2068 }
2069 else
2070 writeString( rItemName );
2071 }
2072
2073 // ============================================================================
2074
StorageIterator(const StorageRef & rxStrg)2075 StorageIterator::StorageIterator( const StorageRef& rxStrg ) :
2076 mxStrg( rxStrg )
2077 {
2078 if( mxStrg.get() )
2079 mxStrg->getElementNames( maNames );
2080 maIt = maNames.begin();
2081 }
2082
~StorageIterator()2083 StorageIterator::~StorageIterator()
2084 {
2085 }
2086
getElementCount() const2087 size_t StorageIterator::getElementCount() const
2088 {
2089 return maNames.size();
2090 }
2091
operator ++()2092 StorageIterator& StorageIterator::operator++()
2093 {
2094 if( maIt != maNames.end() )
2095 ++maIt;
2096 return *this;
2097 }
2098
getName() const2099 OUString StorageIterator::getName() const
2100 {
2101 OUString aName;
2102 if( maIt != maNames.end() )
2103 aName = *maIt;
2104 return aName;
2105 }
2106
isStream() const2107 bool StorageIterator::isStream() const
2108 {
2109 return isValid() && mxStrg->openInputStream( *maIt ).is();
2110 }
2111
isStorage() const2112 bool StorageIterator::isStorage() const
2113 {
2114 if( !isValid() )
2115 return false;
2116 StorageRef xStrg = mxStrg->openSubStorage( *maIt, false );
2117 return xStrg.get() && xStrg->isStorage();
2118 }
2119
implIsValid() const2120 bool StorageIterator::implIsValid() const
2121 {
2122 return mxStrg.get() && mxStrg->isStorage() && (maIt != maNames.end());
2123 }
2124
2125 // ============================================================================
2126 // ============================================================================
2127
~ObjectBase()2128 ObjectBase::~ObjectBase()
2129 {
2130 }
2131
construct(const ConfigRef & rxConfig)2132 void ObjectBase::construct( const ConfigRef& rxConfig )
2133 {
2134 mxConfig = rxConfig;
2135 }
2136
construct(const ObjectBase & rParent)2137 void ObjectBase::construct( const ObjectBase& rParent )
2138 {
2139 *this = rParent;
2140 }
2141
dump()2142 void ObjectBase::dump()
2143 {
2144 if( isValid() )
2145 implDump();
2146 }
2147
implIsValid() const2148 bool ObjectBase::implIsValid() const
2149 {
2150 return isValid( mxConfig );
2151 }
2152
implDump()2153 void ObjectBase::implDump()
2154 {
2155 }
2156
reconstructConfig(const ConfigRef & rxConfig)2157 void ObjectBase::reconstructConfig( const ConfigRef& rxConfig )
2158 {
2159 if( isValid( rxConfig ) )
2160 mxConfig = rxConfig;
2161 }
2162
2163 // ============================================================================
2164 // ============================================================================
2165
construct(const ObjectBase & rParent,const StorageRef & rxStrg,const OUString & rSysPath)2166 void StorageObjectBase::construct( const ObjectBase& rParent, const StorageRef& rxStrg, const OUString& rSysPath )
2167 {
2168 ObjectBase::construct( rParent );
2169 mxStrg = rxStrg;
2170 maSysPath = rSysPath;
2171 }
2172
construct(const ObjectBase & rParent)2173 void StorageObjectBase::construct( const ObjectBase& rParent )
2174 {
2175 ObjectBase::construct( rParent );
2176 if( ObjectBase::implIsValid() )
2177 {
2178 mxStrg = cfg().getRootStorage();
2179 maSysPath = cfg().getSysFileName();
2180 }
2181 }
2182
implIsValid() const2183 bool StorageObjectBase::implIsValid() const
2184 {
2185 return mxStrg.get() && (maSysPath.getLength() > 0) && ObjectBase::implIsValid();
2186 }
2187
implDump()2188 void StorageObjectBase::implDump()
2189 {
2190 bool bIsStrg = mxStrg->isStorage();
2191 bool bIsRoot = mxStrg->isRootStorage();
2192 Reference< XInputStream > xBaseStrm;
2193 if( !bIsStrg )
2194 xBaseStrm = mxStrg->openInputStream( OUString() );
2195
2196 OUString aSysOutPath = maSysPath;
2197 if( bIsRoot ) try
2198 {
2199 aSysOutPath += OOX_DUMP_DUMPEXT;
2200 Reference< XMultiServiceFactory > xFactory( getContext()->getServiceManager(), UNO_QUERY_THROW );
2201 Reference< XSimpleFileAccess > xFileAccess( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY_THROW );
2202 xFileAccess->kill( aSysOutPath );
2203 }
2204 catch( Exception& )
2205 {
2206 }
2207
2208 if( bIsStrg )
2209 {
2210 extractStorage( mxStrg, OUString(), aSysOutPath );
2211 }
2212 else if( xBaseStrm.is() )
2213 {
2214 BinaryInputStreamRef xInStrm( new BinaryXInputStream( xBaseStrm, false ) );
2215 xInStrm->seekToStart();
2216 implDumpBaseStream( xInStrm, aSysOutPath );
2217 }
2218 }
2219
implDumpStream(const Reference<XInputStream> &,const OUString &,const OUString &,const OUString &)2220 void StorageObjectBase::implDumpStream( const Reference< XInputStream >&, const OUString&, const OUString&, const OUString& )
2221 {
2222 }
2223
implDumpStorage(const StorageRef & rxStrg,const OUString & rStrgPath,const OUString & rSysPath)2224 void StorageObjectBase::implDumpStorage( const StorageRef& rxStrg, const OUString& rStrgPath, const OUString& rSysPath )
2225 {
2226 extractStorage( rxStrg, rStrgPath, rSysPath );
2227 }
2228
implDumpBaseStream(const BinaryInputStreamRef &,const OUString &)2229 void StorageObjectBase::implDumpBaseStream( const BinaryInputStreamRef&, const OUString& )
2230 {
2231 }
2232
addPreferredStream(const String & rStrmName)2233 void StorageObjectBase::addPreferredStream( const String& rStrmName )
2234 {
2235 if( rStrmName.has() )
2236 maPreferred.push_back( PreferredItem( rStrmName, false ) );
2237 }
2238
addPreferredStorage(const String & rStrgPath)2239 void StorageObjectBase::addPreferredStorage( const String& rStrgPath )
2240 {
2241 if( rStrgPath.has() )
2242 maPreferred.push_back( PreferredItem( rStrgPath, true ) );
2243 }
2244
getSysFileName(const OUString & rStrmName,const OUString & rSysOutPath)2245 OUString StorageObjectBase::getSysFileName( const OUString& rStrmName, const OUString& rSysOutPath )
2246 {
2247 // encode all characters < 0x20
2248 OUStringBuffer aBuffer;
2249 StringHelper::appendEncString( aBuffer, rStrmName, false );
2250
2251 // replace all characters reserved in file system
2252 OUString aFileName = aBuffer.makeStringAndClear();
2253 static const sal_Unicode spcReserved[] = { '/', '\\', ':', '*', '?', '<', '>', '|' };
2254 for( const sal_Unicode* pcChar = spcReserved; pcChar < STATIC_ARRAY_END( spcReserved ); ++pcChar )
2255 aFileName = aFileName.replace( *pcChar, '_' );
2256
2257 // build full path
2258 return rSysOutPath + OUString( sal_Unicode( '/' ) ) + aFileName;
2259 }
2260
extractStream(StorageBase & rStrg,const OUString & rStrgPath,const OUString & rStrmName,const OUString & rSysFileName)2261 void StorageObjectBase::extractStream( StorageBase& rStrg, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName )
2262 {
2263 BinaryXInputStream aInStrm( rStrg.openInputStream( rStrmName ), true );
2264 if( !aInStrm.isEof() )
2265 {
2266 BinaryXOutputStream aOutStrm( InputOutputHelper::openOutputStream( getContext(), rSysFileName ), true );
2267 if( !aOutStrm.isEof() )
2268 aInStrm.copyToStream( aOutStrm );
2269 }
2270 Reference< XInputStream > xDumpStrm = InputOutputHelper::openInputStream( getContext(), rSysFileName );
2271 if( xDumpStrm.is() )
2272 implDumpStream( xDumpStrm, rStrgPath, rStrmName, rSysFileName );
2273 }
2274
extractStorage(const StorageRef & rxStrg,const OUString & rStrgPath,const OUString & rSysPath)2275 void StorageObjectBase::extractStorage( const StorageRef& rxStrg, const OUString& rStrgPath, const OUString& rSysPath )
2276 {
2277 // create directory in file system
2278 ::osl::FileBase::RC eRes = ::osl::Directory::create( rSysPath );
2279 if( (eRes != ::osl::FileBase::E_None) && (eRes != ::osl::FileBase::E_EXIST) )
2280 return;
2281
2282 // process preferred storages and streams in root storage first
2283 if( rStrgPath.getLength() == 0 )
2284 for( PreferredItemVector::iterator aIt = maPreferred.begin(), aEnd = maPreferred.end(); aIt != aEnd; ++aIt )
2285 extractItem( rxStrg, rStrgPath, aIt->maName, rSysPath, aIt->mbStorage, !aIt->mbStorage );
2286
2287 // process children of the storage
2288 for( StorageIterator aIt( rxStrg ); aIt.isValid(); ++aIt )
2289 {
2290 // skip processed preferred items
2291 OUString aItemName = aIt.getName();
2292 bool bFound = false;
2293 if( rStrgPath.getLength() == 0 )
2294 for( PreferredItemVector::iterator aIIt = maPreferred.begin(), aIEnd = maPreferred.end(); !bFound && (aIIt != aIEnd); ++aIIt )
2295 bFound = aIIt->maName == aItemName;
2296 if( !bFound )
2297 extractItem( rxStrg, rStrgPath, aItemName, rSysPath, aIt.isStorage(), aIt.isStream() );
2298 }
2299 }
2300
extractItem(const StorageRef & rxStrg,const OUString & rStrgPath,const OUString & rItemName,const OUString & rSysPath,bool bIsStrg,bool bIsStrm)2301 void StorageObjectBase::extractItem( const StorageRef& rxStrg, const OUString& rStrgPath, const OUString& rItemName, const OUString& rSysPath, bool bIsStrg, bool bIsStrm )
2302 {
2303 OUString aSysFileName = getSysFileName( rItemName, rSysPath );
2304 if( bIsStrg )
2305 {
2306 OUStringBuffer aStrgPath( rStrgPath );
2307 StringHelper::appendToken( aStrgPath, rItemName, '/' );
2308 implDumpStorage( rxStrg->openSubStorage( rItemName, false ), aStrgPath.makeStringAndClear(), aSysFileName );
2309 }
2310 else if( bIsStrm )
2311 {
2312 extractStream( *rxStrg, rStrgPath, rItemName, aSysFileName );
2313 }
2314 }
2315
2316 // ============================================================================
2317 // ============================================================================
2318
~OutputObjectBase()2319 OutputObjectBase::~OutputObjectBase()
2320 {
2321 }
2322
construct(const ObjectBase & rParent,const OUString & rSysFileName)2323 void OutputObjectBase::construct( const ObjectBase& rParent, const OUString& rSysFileName )
2324 {
2325 ObjectBase::construct( rParent );
2326 if( ObjectBase::implIsValid() )
2327 {
2328 maSysFileName = rSysFileName;
2329 mxOut.reset( new Output( getContext(), rSysFileName + OOX_DUMP_DUMPEXT ) );
2330 }
2331 }
2332
construct(const OutputObjectBase & rParent)2333 void OutputObjectBase::construct( const OutputObjectBase& rParent )
2334 {
2335 *this = rParent;
2336 }
2337
implIsValid() const2338 bool OutputObjectBase::implIsValid() const
2339 {
2340 return isValid( mxOut ) && ObjectBase::implIsValid();
2341 }
2342
writeEmptyItem(const String & rName)2343 void OutputObjectBase::writeEmptyItem( const String& rName )
2344 {
2345 ItemGuard aItem( mxOut, rName );
2346 }
2347
writeInfoItem(const String & rName,const String & rData)2348 void OutputObjectBase::writeInfoItem( const String& rName, const String& rData )
2349 {
2350 ItemGuard aItem( mxOut, rName );
2351 mxOut->writeString( rData );
2352 }
2353
writeCharItem(const String & rName,sal_Unicode cData)2354 void OutputObjectBase::writeCharItem( const String& rName, sal_Unicode cData )
2355 {
2356 ItemGuard aItem( mxOut, rName );
2357 mxOut->writeChar( OOX_DUMP_STRQUOTE );
2358 mxOut->writeChar( cData );
2359 mxOut->writeChar( OOX_DUMP_STRQUOTE );
2360 }
2361
writeStringItem(const String & rName,const OUString & rData)2362 void OutputObjectBase::writeStringItem( const String& rName, const OUString& rData )
2363 {
2364 ItemGuard aItem( mxOut, rName );
2365 mxOut->writeAscii( "(len=" );
2366 mxOut->writeDec( rData.getLength() );
2367 mxOut->writeAscii( ")," );
2368 OUStringBuffer aValue( rData.copy( 0, ::std::min( rData.getLength(), OOX_DUMP_MAXSTRLEN ) ) );
2369 StringHelper::enclose( aValue, OOX_DUMP_STRQUOTE );
2370 mxOut->writeString( aValue.makeStringAndClear() );
2371 if( rData.getLength() > OOX_DUMP_MAXSTRLEN )
2372 mxOut->writeAscii( ",cut" );
2373 }
2374
writeArrayItem(const String & rName,const sal_uInt8 * pnData,sal_Size nSize,sal_Unicode cSep)2375 void OutputObjectBase::writeArrayItem( const String& rName, const sal_uInt8* pnData, sal_Size nSize, sal_Unicode cSep )
2376 {
2377 ItemGuard aItem( mxOut, rName );
2378 mxOut->writeArray( pnData, nSize, cSep );
2379 }
2380
writeBoolItem(const String & rName,bool bData)2381 void OutputObjectBase::writeBoolItem( const String& rName, bool bData )
2382 {
2383 ItemGuard aItem( mxOut, rName );
2384 mxOut->writeBool( bData );
2385 }
2386
writeRkItem(const String & rName,sal_Int32 nRk)2387 double OutputObjectBase::writeRkItem( const String& rName, sal_Int32 nRk )
2388 {
2389 MultiItemsGuard aMultiGuard( mxOut );
2390 writeHexItem( rName, static_cast< sal_uInt32 >( nRk ), "RK-FLAGS" );
2391 double fValue = ::oox::xls::BiffHelper::calcDoubleFromRk( nRk );
2392 writeDecItem( "decoded", fValue );
2393 return fValue;
2394 }
2395
writeColorABGRItem(const String & rName,sal_Int32 nColor)2396 void OutputObjectBase::writeColorABGRItem( const String& rName, sal_Int32 nColor )
2397 {
2398 ItemGuard aItem( mxOut, rName );
2399 writeHexItem( rName, nColor );
2400 mxOut->writeColorABGR( nColor );
2401 }
2402
writeDateTimeItem(const String & rName,const DateTime & rDateTime)2403 void OutputObjectBase::writeDateTimeItem( const String& rName, const DateTime& rDateTime )
2404 {
2405 ItemGuard aItem( mxOut, rName );
2406 mxOut->writeDateTime( rDateTime );
2407 }
2408
writeGuidItem(const String & rName,const OUString & rGuid)2409 void OutputObjectBase::writeGuidItem( const String& rName, const OUString& rGuid )
2410 {
2411 ItemGuard aItem( mxOut, rName );
2412 mxOut->writeString( rGuid );
2413 aItem.cont();
2414 mxOut->writeString( cfg().getStringOption( rGuid, OUString() ) );
2415 }
2416
writeColIndexItem(const String & rName,sal_Int32 nCol)2417 void OutputObjectBase::writeColIndexItem( const String& rName, sal_Int32 nCol )
2418 {
2419 ItemGuard aItem( mxOut, rName );
2420 mxOut->writeDec( nCol );
2421 aItem.cont();
2422 mxOut->writeColIndex( nCol );
2423 }
2424
writeRowIndexItem(const String & rName,sal_Int32 nRow)2425 void OutputObjectBase::writeRowIndexItem( const String& rName, sal_Int32 nRow )
2426 {
2427 ItemGuard aItem( mxOut, rName );
2428 mxOut->writeDec( nRow );
2429 aItem.cont();
2430 mxOut->writeRowIndex( nRow );
2431 }
2432
writeColRangeItem(const String & rName,sal_Int32 nCol1,sal_Int32 nCol2)2433 void OutputObjectBase::writeColRangeItem( const String& rName, sal_Int32 nCol1, sal_Int32 nCol2 )
2434 {
2435 ItemGuard aItem( mxOut, rName );
2436 mxOut->writeColRowRange( nCol1, nCol2 );
2437 aItem.cont();
2438 mxOut->writeColRange( nCol1, nCol2 );
2439 }
2440
writeRowRangeItem(const String & rName,sal_Int32 nRow1,sal_Int32 nRow2)2441 void OutputObjectBase::writeRowRangeItem( const String& rName, sal_Int32 nRow1, sal_Int32 nRow2 )
2442 {
2443 ItemGuard aItem( mxOut, rName );
2444 mxOut->writeColRowRange( nRow1, nRow2 );
2445 aItem.cont();
2446 mxOut->writeRowRange( nRow1, nRow2 );
2447 }
2448
writeAddressItem(const String & rName,const Address & rPos)2449 void OutputObjectBase::writeAddressItem( const String& rName, const Address& rPos )
2450 {
2451 ItemGuard aItem( mxOut, rName );
2452 StringHelper::appendAddress( mxOut->getLine(), rPos );
2453 }
2454
writeRangeItem(const String & rName,const Range & rRange)2455 void OutputObjectBase::writeRangeItem( const String& rName, const Range& rRange )
2456 {
2457 ItemGuard aItem( mxOut, rName );
2458 StringHelper::appendRange( mxOut->getLine(), rRange );
2459 }
2460
writeRangeListItem(const String & rName,const RangeList & rRanges)2461 void OutputObjectBase::writeRangeListItem( const String& rName, const RangeList& rRanges )
2462 {
2463 MultiItemsGuard aMultiGuard( mxOut );
2464 writeEmptyItem( rName );
2465 writeDecItem( "count", static_cast< sal_uInt16 >( rRanges.size() ) );
2466 ItemGuard aItem( mxOut, "ranges" );
2467 StringHelper::appendRangeList( mxOut->getLine(), rRanges );
2468 }
2469
writeTokenAddressItem(const String & rName,const TokenAddress & rPos,bool bNameMode)2470 void OutputObjectBase::writeTokenAddressItem( const String& rName, const TokenAddress& rPos, bool bNameMode )
2471 {
2472 ItemGuard aItem( mxOut, rName );
2473 StringHelper::appendAddress( mxOut->getLine(), rPos, bNameMode );
2474 }
2475
writeTokenAddress3dItem(const String & rName,const OUString & rRef,const TokenAddress & rPos,bool bNameMode)2476 void OutputObjectBase::writeTokenAddress3dItem( const String& rName, const OUString& rRef, const TokenAddress& rPos, bool bNameMode )
2477 {
2478 ItemGuard aItem( mxOut, rName );
2479 mxOut->writeString( rRef );
2480 StringHelper::appendAddress( mxOut->getLine(), rPos, bNameMode );
2481 }
2482
writeTokenRangeItem(const String & rName,const TokenRange & rRange,bool bNameMode)2483 void OutputObjectBase::writeTokenRangeItem( const String& rName, const TokenRange& rRange, bool bNameMode )
2484 {
2485 ItemGuard aItem( mxOut, rName );
2486 StringHelper::appendRange( mxOut->getLine(), rRange, bNameMode );
2487 }
2488
writeTokenRange3dItem(const String & rName,const OUString & rRef,const TokenRange & rRange,bool bNameMode)2489 void OutputObjectBase::writeTokenRange3dItem( const String& rName, const OUString& rRef, const TokenRange& rRange, bool bNameMode )
2490 {
2491 ItemGuard aItem( mxOut, rName );
2492 mxOut->writeString( rRef );
2493 StringHelper::appendRange( mxOut->getLine(), rRange, bNameMode );
2494 }
2495
2496 // ============================================================================
2497 // ============================================================================
2498
~InputObjectBase()2499 InputObjectBase::~InputObjectBase()
2500 {
2501 }
2502
construct(const ObjectBase & rParent,const BinaryInputStreamRef & rxStrm,const OUString & rSysFileName)2503 void InputObjectBase::construct( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName )
2504 {
2505 OutputObjectBase::construct( rParent, rSysFileName );
2506 mxStrm = rxStrm;
2507 }
2508
construct(const OutputObjectBase & rParent,const BinaryInputStreamRef & rxStrm)2509 void InputObjectBase::construct( const OutputObjectBase& rParent, const BinaryInputStreamRef& rxStrm )
2510 {
2511 OutputObjectBase::construct( rParent );
2512 mxStrm = rxStrm;
2513 }
2514
construct(const InputObjectBase & rParent)2515 void InputObjectBase::construct( const InputObjectBase& rParent )
2516 {
2517 *this = rParent;
2518 }
2519
implIsValid() const2520 bool InputObjectBase::implIsValid() const
2521 {
2522 return mxStrm.get() && OutputObjectBase::implIsValid();
2523 }
2524
skipBlock(sal_Int64 nBytes,bool bShowSize)2525 void InputObjectBase::skipBlock( sal_Int64 nBytes, bool bShowSize )
2526 {
2527 sal_Int64 nEndPos = ::std::min< sal_Int64 >( mxStrm->tell() + nBytes, mxStrm->size() );
2528 if( mxStrm->tell() < nEndPos )
2529 {
2530 if( bShowSize )
2531 writeDecItem( "skipped-data-size", static_cast< sal_uInt64 >( nEndPos - mxStrm->tell() ) );
2532 mxStrm->seek( nEndPos );
2533 }
2534 }
2535
dumpRawBinary(sal_Int64 nBytes,bool bShowOffset,bool bStream)2536 void InputObjectBase::dumpRawBinary( sal_Int64 nBytes, bool bShowOffset, bool bStream )
2537 {
2538 TableGuard aTabGuard( mxOut,
2539 bShowOffset ? 12 : 0,
2540 3 * OOX_DUMP_BYTESPERLINE / 2 + 1,
2541 3 * OOX_DUMP_BYTESPERLINE / 2 + 1,
2542 OOX_DUMP_BYTESPERLINE / 2 + 1 );
2543
2544 sal_Int64 nMaxShowSize = cfg().getIntOption< sal_Int64 >(
2545 bStream ? "max-binary-stream-size" : "max-binary-data-size", SAL_MAX_INT64 );
2546
2547 bool bSeekable = mxStrm->size() >= 0;
2548 sal_Int64 nEndPos = bSeekable ? ::std::min< sal_Int64 >( mxStrm->tell() + nBytes, mxStrm->size() ) : 0;
2549 sal_Int64 nDumpEnd = bSeekable ? ::std::min< sal_Int64 >( mxStrm->tell() + nMaxShowSize, nEndPos ) : nMaxShowSize;
2550 sal_Int64 nPos = bSeekable ? mxStrm->tell() : 0;
2551 bool bLoop = true;
2552
2553 while( bLoop && (nPos < nDumpEnd) )
2554 {
2555 mxOut->writeHex( static_cast< sal_uInt32 >( nPos ) );
2556 mxOut->tab();
2557
2558 sal_uInt8 pnLineData[ OOX_DUMP_BYTESPERLINE ];
2559 sal_Int32 nLineSize = bSeekable ? ::std::min( static_cast< sal_Int32 >( nDumpEnd - mxStrm->tell() ), OOX_DUMP_BYTESPERLINE ) : OOX_DUMP_BYTESPERLINE;
2560 sal_Int32 nReadSize = mxStrm->readMemory( pnLineData, nLineSize );
2561 bLoop = nReadSize == nLineSize;
2562 nPos += nReadSize;
2563
2564 if( nReadSize > 0 )
2565 {
2566 const sal_uInt8* pnByte = 0;
2567 const sal_uInt8* pnEnd = 0;
2568 for( pnByte = pnLineData, pnEnd = pnLineData + nReadSize; pnByte != pnEnd; ++pnByte )
2569 {
2570 if( (pnByte - pnLineData) == (OOX_DUMP_BYTESPERLINE / 2) ) mxOut->tab();
2571 mxOut->writeHex( *pnByte, false );
2572 mxOut->writeChar( ' ' );
2573 }
2574
2575 aTabGuard.tab( 3 );
2576 for( pnByte = pnLineData, pnEnd = pnLineData + nReadSize; pnByte != pnEnd; ++pnByte )
2577 {
2578 if( (pnByte - pnLineData) == (OOX_DUMP_BYTESPERLINE / 2) ) mxOut->tab();
2579 mxOut->writeChar( static_cast< sal_Unicode >( (*pnByte < 0x20) ? '.' : *pnByte ) );
2580 }
2581 mxOut->newLine();
2582 }
2583 }
2584
2585 // skip undumped data
2586 if( bSeekable )
2587 skipBlock( nEndPos - mxStrm->tell() );
2588 }
2589
dumpBinary(const String & rName,sal_Int64 nBytes,bool bShowOffset)2590 void InputObjectBase::dumpBinary( const String& rName, sal_Int64 nBytes, bool bShowOffset )
2591 {
2592 {
2593 MultiItemsGuard aMultiGuard( mxOut );
2594 writeEmptyItem( rName );
2595 writeDecItem( "size", nBytes );
2596 }
2597 IndentGuard aIndGuard( mxOut );
2598 dumpRawBinary( nBytes, bShowOffset );
2599 }
2600
dumpRemaining(sal_Int64 nBytes)2601 void InputObjectBase::dumpRemaining( sal_Int64 nBytes )
2602 {
2603 if( nBytes > 0 )
2604 {
2605 if( cfg().getBoolOption( "show-trailing-unknown", true ) )
2606 dumpBinary( "remaining-data", nBytes, false );
2607 else
2608 skipBlock( nBytes );
2609 }
2610 }
2611
dumpRemainingTo(sal_Int64 nPos)2612 void InputObjectBase::dumpRemainingTo( sal_Int64 nPos )
2613 {
2614 if( mxStrm->isEof() || (mxStrm->tell() > nPos) )
2615 writeInfoItem( "stream-state", OOX_DUMP_ERR_STREAM );
2616 else
2617 dumpRemaining( nPos - mxStrm->tell() );
2618 mxStrm->seek( nPos );
2619 }
2620
dumpRemainingStream()2621 void InputObjectBase::dumpRemainingStream()
2622 {
2623 dumpRemainingTo( mxStrm->size() );
2624 }
2625
dumpArray(const String & rName,sal_Int32 nBytes,sal_Unicode cSep)2626 void InputObjectBase::dumpArray( const String& rName, sal_Int32 nBytes, sal_Unicode cSep )
2627 {
2628 sal_Int32 nDumpSize = getLimitedValue< sal_Int32, sal_Int64 >( mxStrm->size() - mxStrm->tell(), 0, nBytes );
2629 if( nDumpSize > OOX_DUMP_MAXARRAY )
2630 {
2631 dumpBinary( rName, nBytes, false );
2632 }
2633 else if( nDumpSize > 1 )
2634 {
2635 sal_uInt8 pnData[ OOX_DUMP_MAXARRAY ];
2636 mxStrm->readMemory( pnData, nDumpSize );
2637 writeArrayItem( rName, pnData, nDumpSize, cSep );
2638 }
2639 else if( nDumpSize == 1 )
2640 dumpHex< sal_uInt8 >( rName );
2641 }
2642
dumpChar(const String & rName,rtl_TextEncoding eTextEnc)2643 sal_Unicode InputObjectBase::dumpChar( const String& rName, rtl_TextEncoding eTextEnc )
2644 {
2645 sal_uInt8 nChar;
2646 *mxStrm >> nChar;
2647 OUString aChar = OStringToOUString( OString( static_cast< sal_Char >( nChar ) ), eTextEnc );
2648 sal_Unicode cChar = (aChar.getLength() > 0) ? aChar[ 0 ] : 0;
2649 writeCharItem( rName( "char" ), cChar );
2650 return cChar;
2651 }
2652
dumpUnicode(const String & rName)2653 sal_Unicode InputObjectBase::dumpUnicode( const String& rName )
2654 {
2655 sal_uInt16 nChar;
2656 *mxStrm >> nChar;
2657 sal_Unicode cChar = static_cast< sal_Unicode >( nChar );
2658 writeCharItem( rName( "char" ), cChar );
2659 return cChar;
2660 }
2661
dumpCharArray(const String & rName,sal_Int32 nLen,rtl_TextEncoding eTextEnc,bool bHideTrailingNul)2662 OUString InputObjectBase::dumpCharArray( const String& rName, sal_Int32 nLen, rtl_TextEncoding eTextEnc, bool bHideTrailingNul )
2663 {
2664 sal_Int32 nDumpSize = getLimitedValue< sal_Int32, sal_Int64 >( mxStrm->size() - mxStrm->tell(), 0, nLen );
2665 OUString aString;
2666 if( nDumpSize > 0 )
2667 {
2668 ::std::vector< sal_Char > aBuffer( static_cast< sal_Size >( nLen ) + 1 );
2669 sal_Int32 nCharsRead = mxStrm->readMemory( &aBuffer.front(), nLen );
2670 aBuffer[ nCharsRead ] = 0;
2671 aString = OStringToOUString( OString( &aBuffer.front() ), eTextEnc );
2672 }
2673 if( bHideTrailingNul )
2674 aString = StringHelper::trimTrailingNul( aString );
2675 writeStringItem( rName( "text" ), aString );
2676 return aString;
2677 }
2678
dumpUnicodeArray(const String & rName,sal_Int32 nLen,bool bHideTrailingNul)2679 OUString InputObjectBase::dumpUnicodeArray( const String& rName, sal_Int32 nLen, bool bHideTrailingNul )
2680 {
2681 OUStringBuffer aBuffer;
2682 for( sal_Int32 nIndex = 0; !mxStrm->isEof() && (nIndex < nLen); ++nIndex )
2683 aBuffer.append( static_cast< sal_Unicode >( mxStrm->readuInt16() ) );
2684 OUString aString = aBuffer.makeStringAndClear();
2685 if( bHideTrailingNul )
2686 aString = StringHelper::trimTrailingNul( aString );
2687 writeStringItem( rName( "text" ), aString );
2688 return aString;
2689 }
2690
dumpNullCharArray(const String & rName,rtl_TextEncoding eTextEnc)2691 OUString InputObjectBase::dumpNullCharArray( const String& rName, rtl_TextEncoding eTextEnc )
2692 {
2693 OStringBuffer aBuffer;
2694 sal_uInt8 nChar;
2695 for( *mxStrm >> nChar; !mxStrm->isEof() && (nChar > 0); *mxStrm >> nChar )
2696 aBuffer.append( static_cast< sal_Char >( nChar ) );
2697 OUString aString = OStringToOUString( aBuffer.makeStringAndClear(), eTextEnc );
2698 writeStringItem( rName( "text" ), aString );
2699 return aString;
2700 }
2701
dumpNullUnicodeArray(const String & rName)2702 OUString InputObjectBase::dumpNullUnicodeArray( const String& rName )
2703 {
2704 OUStringBuffer aBuffer;
2705 sal_uInt16 nChar;
2706 for( *mxStrm >> nChar; !mxStrm->isEof() && (nChar > 0); *mxStrm >> nChar )
2707 aBuffer.append( static_cast< sal_Unicode >( nChar ) );
2708 OUString aString = aBuffer.makeStringAndClear();
2709 writeStringItem( rName( "text" ), aString );
2710 return aString;
2711 }
2712
dumpRk(const String & rName)2713 double InputObjectBase::dumpRk( const String& rName )
2714 {
2715 sal_Int32 nRk;
2716 *mxStrm >> nRk;
2717 return writeRkItem( rName( "rk-value" ), nRk );
2718 }
2719
dumpColorABGR(const String & rName)2720 sal_Int32 InputObjectBase::dumpColorABGR( const String& rName )
2721 {
2722 sal_Int32 nColor;
2723 *mxStrm >> nColor;
2724 writeColorABGRItem( rName( "color" ), nColor );
2725 return nColor;
2726 }
2727
dumpFileTime(const String & rName)2728 DateTime InputObjectBase::dumpFileTime( const String& rName )
2729 {
2730 DateTime aDateTime;
2731
2732 ItemGuard aItem( mxOut, rName( "file-time" ) );
2733 sal_Int64 nFileTime = dumpDec< sal_Int64 >( EMPTY_STRING );
2734 // file time is in 10^-7 seconds (100 nanoseconds), convert to 1/100 seconds
2735 nFileTime /= 100000;
2736 // entire days
2737 sal_Int64 nDays = nFileTime / sal_Int64( 360000 * 24 );
2738 // number of entire years
2739 sal_Int64 nYears = (nDays - (nDays / (4 * 365)) + (nDays / (100 * 365)) - (nDays / (400 * 365))) / 365;
2740 // remaining days in the year
2741 sal_Int64 nDaysInYear = nDays - (nYears * 365 + nYears / 4 - nYears / 100 + nYears / 400);
2742 // the year (file dates start from 1601-01-01)
2743 aDateTime.Year = static_cast< sal_uInt16 >( 1601 + nYears );
2744 // leap year?
2745 bool bLeap = ((aDateTime.Year % 4 == 0) && (aDateTime.Year % 100 != 0)) || (aDateTime.Year % 400 == 0);
2746 // static arrays with number of days in month
2747 static const sal_Int64 spnDaysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
2748 static const sal_Int64 spnDaysInMonthL[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
2749 const sal_Int64* pnDaysInMonth = bLeap ? spnDaysInMonthL : spnDaysInMonth;
2750 // the month
2751 aDateTime.Month = 1;
2752 while( nDaysInYear >= *pnDaysInMonth )
2753 {
2754 nDaysInYear -= *pnDaysInMonth++;
2755 ++aDateTime.Month;
2756 }
2757 // the day
2758 aDateTime.Day = static_cast< sal_uInt16 >( nDaysInYear + 1 );
2759 // number of 1/100 seconds in the day
2760 sal_Int64 nTimeInDay = nFileTime % sal_Int64( 360000 * 24 );
2761 // 1/100 seconds
2762 aDateTime.HundredthSeconds = static_cast< sal_uInt16 >( nTimeInDay % 100 );
2763 nTimeInDay /= 100;
2764 // seconds
2765 aDateTime.Seconds = static_cast< sal_uInt16 >( nTimeInDay % 60 );
2766 nTimeInDay /= 60;
2767 // minutes
2768 aDateTime.Minutes = static_cast< sal_uInt16 >( nTimeInDay % 60 );
2769 nTimeInDay /= 60;
2770 // hours
2771 aDateTime.Hours = static_cast< sal_uInt16 >( nTimeInDay );
2772
2773 writeDateTimeItem( EMPTY_STRING, aDateTime );
2774 return aDateTime;
2775 }
2776
dumpGuid(const String & rName)2777 OUString InputObjectBase::dumpGuid( const String& rName )
2778 {
2779 OUStringBuffer aBuffer;
2780 sal_uInt32 nData32;
2781 sal_uInt16 nData16;
2782 sal_uInt8 nData8;
2783
2784 *mxStrm >> nData32;
2785 StringHelper::appendHex( aBuffer, nData32, false );
2786 aBuffer.append( sal_Unicode( '-' ) );
2787 *mxStrm >> nData16;
2788 StringHelper::appendHex( aBuffer, nData16, false );
2789 aBuffer.append( sal_Unicode( '-' ) );
2790 *mxStrm >> nData16;
2791 StringHelper::appendHex( aBuffer, nData16, false );
2792 aBuffer.append( sal_Unicode( '-' ) );
2793 *mxStrm >> nData8;
2794 StringHelper::appendHex( aBuffer, nData8, false );
2795 *mxStrm >> nData8;
2796 StringHelper::appendHex( aBuffer, nData8, false );
2797 aBuffer.append( sal_Unicode( '-' ) );
2798 for( int nIndex = 0; nIndex < 6; ++nIndex )
2799 {
2800 *mxStrm >> nData8;
2801 StringHelper::appendHex( aBuffer, nData8, false );
2802 }
2803 StringHelper::enclose( aBuffer, '{', '}' );
2804 OUString aGuid = aBuffer.makeStringAndClear();
2805 writeGuidItem( rName( "guid" ), aGuid );
2806 return aGuid;
2807 }
2808
dumpItem(const ItemFormat & rItemFmt)2809 void InputObjectBase::dumpItem( const ItemFormat& rItemFmt )
2810 {
2811 switch( rItemFmt.meDataType )
2812 {
2813 case DATATYPE_VOID: break;
2814 case DATATYPE_INT8: dumpValue< sal_Int8 >( rItemFmt ); break;
2815 case DATATYPE_UINT8: dumpValue< sal_uInt8 >( rItemFmt ); break;
2816 case DATATYPE_INT16: dumpValue< sal_Int16 >( rItemFmt ); break;
2817 case DATATYPE_UINT16: dumpValue< sal_uInt16 >( rItemFmt ); break;
2818 case DATATYPE_INT32: dumpValue< sal_Int32 >( rItemFmt ); break;
2819 case DATATYPE_UINT32: dumpValue< sal_uInt32 >( rItemFmt ); break;
2820 case DATATYPE_INT64: dumpValue< sal_Int64 >( rItemFmt ); break;
2821 case DATATYPE_UINT64: dumpValue< sal_uInt64 >( rItemFmt ); break;
2822 case DATATYPE_FLOAT: dumpValue< float >( rItemFmt ); break;
2823 case DATATYPE_DOUBLE: dumpValue< double >( rItemFmt ); break;
2824 default:;
2825 }
2826 }
2827
2828 // ============================================================================
2829 // ============================================================================
2830
BinaryStreamObject(const ObjectBase & rParent,const BinaryInputStreamRef & rxStrm,const OUString & rSysFileName)2831 BinaryStreamObject::BinaryStreamObject( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName )
2832 {
2833 InputObjectBase::construct( rParent, rxStrm, rSysFileName );
2834 }
2835
BinaryStreamObject(const OutputObjectBase & rParent,const BinaryInputStreamRef & rxStrm)2836 BinaryStreamObject::BinaryStreamObject( const OutputObjectBase& rParent, const BinaryInputStreamRef& rxStrm )
2837 {
2838 InputObjectBase::construct( rParent, rxStrm );
2839 }
2840
dumpBinaryStream(bool bShowOffset)2841 void BinaryStreamObject::dumpBinaryStream( bool bShowOffset )
2842 {
2843 mxStrm->seekToStart();
2844 dumpRawBinary( mxStrm->size(), bShowOffset, true );
2845 mxOut->emptyLine();
2846 }
2847
implDump()2848 void BinaryStreamObject::implDump()
2849 {
2850 dumpBinaryStream();
2851 }
2852
2853 // ============================================================================
2854 // ============================================================================
2855
construct(const ObjectBase & rParent,const BinaryInputStreamRef & rxStrm,rtl_TextEncoding eTextEnc,const OUString & rSysFileName)2856 void TextStreamObjectBase::construct( const ObjectBase& rParent,
2857 const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc, const OUString& rSysFileName )
2858 {
2859 InputObjectBase::construct( rParent, rxStrm, rSysFileName );
2860 constructTextStrmObj( eTextEnc );
2861 }
2862
construct(const OutputObjectBase & rParent,const BinaryInputStreamRef & rxStrm,rtl_TextEncoding eTextEnc)2863 void TextStreamObjectBase::construct( const OutputObjectBase& rParent,
2864 const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc )
2865 {
2866 InputObjectBase::construct( rParent, rxStrm );
2867 constructTextStrmObj( eTextEnc );
2868 }
2869
construct(const InputObjectBase & rParent,rtl_TextEncoding eTextEnc)2870 void TextStreamObjectBase::construct( const InputObjectBase& rParent, rtl_TextEncoding eTextEnc )
2871 {
2872 InputObjectBase::construct( rParent );
2873 constructTextStrmObj( eTextEnc );
2874 }
2875
implIsValid() const2876 bool TextStreamObjectBase::implIsValid() const
2877 {
2878 return InputObjectBase::implIsValid() && mxTextStrm.get();
2879 }
2880
implDump()2881 void TextStreamObjectBase::implDump()
2882 {
2883 implDumpText( *mxTextStrm );
2884 }
2885
constructTextStrmObj(rtl_TextEncoding eTextEnc)2886 void TextStreamObjectBase::constructTextStrmObj( rtl_TextEncoding eTextEnc )
2887 {
2888 if( mxStrm.get() )
2889 mxTextStrm.reset( new TextInputStream( getContext(), *mxStrm, eTextEnc ) );
2890 }
2891
2892 // ============================================================================
2893
TextLineStreamObject(const ObjectBase & rParent,const BinaryInputStreamRef & rxStrm,rtl_TextEncoding eTextEnc,const OUString & rSysFileName)2894 TextLineStreamObject::TextLineStreamObject( const ObjectBase& rParent,
2895 const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc, const OUString& rSysFileName )
2896 {
2897 TextStreamObjectBase::construct( rParent, rxStrm, eTextEnc, rSysFileName );
2898 }
2899
TextLineStreamObject(const OutputObjectBase & rParent,const BinaryInputStreamRef & rxStrm,rtl_TextEncoding eTextEnc)2900 TextLineStreamObject::TextLineStreamObject( const OutputObjectBase& rParent,
2901 const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc )
2902 {
2903 TextStreamObjectBase::construct( rParent, rxStrm, eTextEnc );
2904 }
2905
implDumpText(TextInputStream & rTextStrm)2906 void TextLineStreamObject::implDumpText( TextInputStream& rTextStrm )
2907 {
2908 sal_uInt32 nLine = 0;
2909 while( !rTextStrm.isEof() )
2910 {
2911 OUString aLine = rTextStrm.readLine();
2912 if( !rTextStrm.isEof() || (aLine.getLength() > 0) )
2913 implDumpLine( aLine, ++nLine );
2914 }
2915 }
2916
implDumpLine(const OUString & rLine,sal_uInt32 nLine)2917 void TextLineStreamObject::implDumpLine( const OUString& rLine, sal_uInt32 nLine )
2918 {
2919 TableGuard aTabGuard( mxOut, 8 );
2920 mxOut->writeDec( nLine, 6 );
2921 mxOut->tab();
2922 mxOut->writeString( rLine );
2923 mxOut->newLine();
2924 }
2925
2926 // ============================================================================
2927
XmlStreamObject(const ObjectBase & rParent,const BinaryInputStreamRef & rxStrm,const OUString & rSysFileName)2928 XmlStreamObject::XmlStreamObject( const ObjectBase& rParent,
2929 const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName )
2930 {
2931 TextStreamObjectBase::construct( rParent, rxStrm, RTL_TEXTENCODING_UTF8, rSysFileName );
2932 }
2933
XmlStreamObject(const OutputObjectBase & rParent,const BinaryInputStreamRef & rxStrm)2934 XmlStreamObject::XmlStreamObject( const OutputObjectBase& rParent, const BinaryInputStreamRef& rxStrm )
2935 {
2936 TextStreamObjectBase::construct( rParent, rxStrm, RTL_TEXTENCODING_UTF8 );
2937 }
2938
implDumpText(TextInputStream & rTextStrm)2939 void XmlStreamObject::implDumpText( TextInputStream& rTextStrm )
2940 {
2941 /* Buffers a start element and the following element text. Needed to dump
2942 matching start/end elements and the element text on the same line. */
2943 OUStringBuffer aOldStartElem;
2944 // special handling for VML
2945 bool bIsVml = InputOutputHelper::getFileNameExtension( maSysFileName ).equalsIgnoreAsciiCaseAscii( "vml" );
2946
2947 while( !rTextStrm.isEof() )
2948 {
2949 // get the next element and the following element text from text stream
2950 OUString aElem = rTextStrm.readToChar( '>', true ).trim();
2951 OUString aText = rTextStrm.readToChar( '<', false );
2952
2953 // remove multiple whitespace from element
2954 sal_Int32 nPos = 0;
2955 while( nPos < aElem.getLength() )
2956 {
2957 while( (nPos < aElem.getLength()) && (aElem[ nPos ] >= 32) ) ++nPos;
2958 if( nPos < aElem.getLength() )
2959 aElem = OUStringBuffer( aElem.copy( 0, nPos ) ).append( sal_Unicode( ' ' ) ).append( aElem.copy( nPos ).trim() ).makeStringAndClear();
2960 ++nPos;
2961 }
2962
2963 sal_Int32 nElemLen = aElem.getLength();
2964 if( (nElemLen >= 2) && (aElem[ 0 ] == '<') && (aElem[ nElemLen - 1 ] == '>') )
2965 {
2966 // determine type of the element
2967 bool bSimpleElem = (aElem[ 1 ] == '!') || (aElem[ 1 ] == '?') || (aElem[ nElemLen - 2 ] == '/') ||
2968 (bIsVml && (nElemLen == 4) && (aElem[ 1 ] == 'b') && (aElem[ 2 ] == 'r'));
2969 bool bStartElem = !bSimpleElem && (aElem[ 1 ] != '/');
2970 bool bEndElem = !bSimpleElem && !bStartElem;
2971
2972 /* Start element or simple element: flush old start element and
2973 its text from previous iteration, and start a new indentation
2974 level for the new element. Trim whitespace and line breaks from
2975 the text of the old start element. */
2976 if( (bSimpleElem || bStartElem) && (aOldStartElem.getLength() > 0) )
2977 {
2978 mxOut->writeString( aOldStartElem.makeStringAndClear().trim() );
2979 mxOut->newLine();
2980 mxOut->incIndent();
2981 }
2982
2983 /* Start element: remember it and its text, to be able to print the
2984 matching end element on the same line in the next iteration. */
2985 if( bStartElem )
2986 {
2987 aOldStartElem.append( aElem ).append( aText );
2988 }
2989 else
2990 {
2991 /* End element: if a start element has been remembered in the
2992 previous iteration, write it out here untrimmed, to show
2993 all whitespace in the element text, and without trailing
2994 line break. Code below will add the end element right after
2995 it. Otherwise, return to previous indentation level. */
2996 if( bEndElem )
2997 {
2998 if( aOldStartElem.getLength() == 0 )
2999 mxOut->decIndent();
3000 else
3001 mxOut->writeString( aOldStartElem.makeStringAndClear() );
3002 }
3003
3004 /* Write the element. Write following element text in a new
3005 line, but only, if it does not contain of white space
3006 entirely. */
3007 mxOut->writeString( aElem );
3008 mxOut->newLine();
3009 if( aText.trim().getLength() > 0 )
3010 {
3011 mxOut->writeString( aText );
3012 mxOut->newLine();
3013 }
3014 }
3015 }
3016 }
3017 }
3018
3019 // ============================================================================
3020 // ============================================================================
3021
construct(const ObjectBase & rParent,const BinaryInputStreamRef & rxBaseStrm,const OUString & rSysFileName,const BinaryInputStreamRef & rxRecStrm,const String & rRecNames,const String & rSimpleRecs)3022 void RecordObjectBase::construct( const ObjectBase& rParent,
3023 const BinaryInputStreamRef& rxBaseStrm, const OUString& rSysFileName,
3024 const BinaryInputStreamRef& rxRecStrm, const String& rRecNames, const String& rSimpleRecs )
3025 {
3026 InputObjectBase::construct( rParent, rxRecStrm, rSysFileName );
3027 constructRecObjBase( rxBaseStrm, rRecNames, rSimpleRecs );
3028 }
3029
construct(const OutputObjectBase & rParent,const BinaryInputStreamRef & rxBaseStrm,const BinaryInputStreamRef & rxRecStrm,const String & rRecNames,const String & rSimpleRecs)3030 void RecordObjectBase::construct( const OutputObjectBase& rParent, const BinaryInputStreamRef& rxBaseStrm,
3031 const BinaryInputStreamRef& rxRecStrm, const String& rRecNames, const String& rSimpleRecs )
3032 {
3033 InputObjectBase::construct( rParent, rxRecStrm );
3034 constructRecObjBase( rxBaseStrm, rRecNames, rSimpleRecs );
3035 }
3036
implIsValid() const3037 bool RecordObjectBase::implIsValid() const
3038 {
3039 return mxBaseStrm.get() && InputObjectBase::implIsValid();
3040 }
3041
implDump()3042 void RecordObjectBase::implDump()
3043 {
3044 NameListRef xRecNames = getRecNames();
3045 ItemFormatMap aSimpleRecs( maSimpleRecs.getNameList( cfg() ) );
3046
3047 while( implStartRecord( *mxBaseStrm, mnRecPos, mnRecId, mnRecSize ) )
3048 {
3049 // record header
3050 mxOut->emptyLine();
3051 writeHeader();
3052 implWriteExtHeader();
3053 IndentGuard aIndGuard( mxOut );
3054 sal_Int64 nRecPos = mxStrm->tell();
3055
3056 // record body
3057 if( !mbBinaryOnly && cfg().hasName( xRecNames, mnRecId ) )
3058 {
3059 ItemFormatMap::const_iterator aIt = aSimpleRecs.find( mnRecId );
3060 if( aIt != aSimpleRecs.end() )
3061 dumpItem( aIt->second );
3062 else
3063 implDumpRecordBody();
3064 }
3065
3066 // remaining undumped data
3067 if( !mxStrm->isEof() && (mxStrm->tell() == nRecPos) )
3068 dumpRawBinary( mnRecSize, false );
3069 else
3070 dumpRemainingTo( nRecPos + mnRecSize );
3071 }
3072 }
3073
implWriteExtHeader()3074 void RecordObjectBase::implWriteExtHeader()
3075 {
3076 }
3077
implDumpRecordBody()3078 void RecordObjectBase::implDumpRecordBody()
3079 {
3080 }
3081
constructRecObjBase(const BinaryInputStreamRef & rxBaseStrm,const String & rRecNames,const String & rSimpleRecs)3082 void RecordObjectBase::constructRecObjBase( const BinaryInputStreamRef& rxBaseStrm, const String& rRecNames, const String& rSimpleRecs )
3083 {
3084 mxBaseStrm = rxBaseStrm;
3085 maRecNames = rRecNames;
3086 maSimpleRecs = rSimpleRecs;
3087 mnRecPos = mnRecId = mnRecSize = 0;
3088 mbBinaryOnly = false;
3089 if( InputObjectBase::implIsValid() )
3090 mbShowRecPos = cfg().getBoolOption( "show-record-position", true );
3091 }
3092
writeHeader()3093 void RecordObjectBase::writeHeader()
3094 {
3095 MultiItemsGuard aMultiGuard( mxOut );
3096 writeEmptyItem( "REC" );
3097 if( mbShowRecPos && mxBaseStrm->isSeekable() )
3098 writeShortHexItem( "pos", mnRecPos, "CONV-DEC" );
3099 writeShortHexItem( "size", mnRecSize, "CONV-DEC" );
3100 ItemGuard aItem( mxOut, "id" );
3101 mxOut->writeShortHex( mnRecId );
3102 addNameToItem( mnRecId, "CONV-DEC" );
3103 addNameToItem( mnRecId, maRecNames );
3104 }
3105
3106 // ============================================================================
3107
construct(const ObjectBase & rParent,const BinaryInputStreamRef & rxBaseStrm,const::rtl::OUString & rSysFileName,const String & rRecNames,const String & rSimpleRecs)3108 void SequenceRecordObjectBase::construct( const ObjectBase& rParent,
3109 const BinaryInputStreamRef& rxBaseStrm, const ::rtl::OUString& rSysFileName,
3110 const String& rRecNames, const String& rSimpleRecs )
3111 {
3112 BinaryInputStreamRef xRecStrm( new SequenceInputStream( *mxRecData ) );
3113 RecordObjectBase::construct( rParent, rxBaseStrm, rSysFileName, xRecStrm, rRecNames, rSimpleRecs );
3114 }
3115
construct(const OutputObjectBase & rParent,const BinaryInputStreamRef & rxBaseStrm,const String & rRecNames,const String & rSimpleRecs)3116 void SequenceRecordObjectBase::construct( const OutputObjectBase& rParent,
3117 const BinaryInputStreamRef& rxBaseStrm, const String& rRecNames, const String& rSimpleRecs )
3118 {
3119 BinaryInputStreamRef xRecStrm( new SequenceInputStream( *mxRecData ) );
3120 RecordObjectBase::construct( rParent, rxBaseStrm, xRecStrm, rRecNames, rSimpleRecs );
3121 }
3122
implStartRecord(BinaryInputStream & rBaseStrm,sal_Int64 & ornRecPos,sal_Int64 & ornRecId,sal_Int64 & ornRecSize)3123 bool SequenceRecordObjectBase::implStartRecord( BinaryInputStream& rBaseStrm, sal_Int64& ornRecPos, sal_Int64& ornRecId, sal_Int64& ornRecSize )
3124 {
3125 bool bValid = true;
3126 if( rBaseStrm.isSeekable() )
3127 {
3128 ornRecPos = rBaseStrm.tell();
3129 // do not try to overread seekable streams, may cause assertions
3130 bValid = ornRecPos < rBaseStrm.size();
3131 }
3132
3133 // read the record header
3134 if( bValid )
3135 bValid = implReadRecordHeader( rBaseStrm, ornRecId, ornRecSize ) && !rBaseStrm.isEof() && (0 <= ornRecSize) && (ornRecSize <= 0x00100000);
3136
3137 // read record contents into data sequence
3138 if( bValid )
3139 {
3140 sal_Int32 nRecSize = static_cast< sal_Int32 >( ornRecSize );
3141 mxRecData->realloc( nRecSize );
3142 bValid = (nRecSize == 0) || (rBaseStrm.readData( *mxRecData, nRecSize ) == nRecSize);
3143 mxStrm->seekToStart();
3144 }
3145 return bValid;
3146 }
3147
3148 // ============================================================================
3149 // ============================================================================
3150
~DumperBase()3151 DumperBase::~DumperBase()
3152 {
3153 }
3154
isImportEnabled() const3155 bool DumperBase::isImportEnabled() const
3156 {
3157 return !isValid() || cfg().isImportEnabled();
3158 }
3159
isImportCancelled() const3160 bool DumperBase::isImportCancelled() const
3161 {
3162 return isValid() && cfg().isPasswordCancelled();
3163 }
3164
construct(const ConfigRef & rxConfig)3165 void DumperBase::construct( const ConfigRef& rxConfig )
3166 {
3167 if( isValid( rxConfig ) && rxConfig->isDumperEnabled() )
3168 ObjectBase::construct( rxConfig );
3169 }
3170
3171 // ============================================================================
3172 // ============================================================================
3173
3174 } // namespace dump
3175 } // namespace oox
3176
3177 #endif
3178