Update ooo320-m1
[ooovba.git] / oox / source / dump / dumperbase.cxx
blob81f63062b4ad85dff160c70c82724556093b142f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dumperbase.cxx,v $
10 * $Revision: 1.4.20.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "oox/dump/dumperbase.hxx"
33 #include <algorithm>
34 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
36 #include <com/sun/star/io/XActiveDataSink.hpp>
37 #include <com/sun/star/io/XActiveDataSource.hpp>
38 #include <com/sun/star/io/XTextInputStream.hpp>
39 #include <com/sun/star/io/XTextOutputStream.hpp>
40 #include <rtl/math.hxx>
41 #include <osl/file.hxx>
42 #include <comphelper/docpasswordhelper.hxx>
43 #include "oox/helper/binaryoutputstream.hxx"
44 #include "oox/core/filterbase.hxx"
45 #include "oox/xls/biffhelper.hxx"
47 #if OOX_INCLUDE_DUMPER
49 using ::rtl::OString;
50 using ::rtl::OStringBuffer;
51 using ::rtl::OStringToOUString;
52 using ::rtl::OUString;
53 using ::rtl::OUStringBuffer;
54 using ::rtl::OUStringToOString;
55 using ::com::sun::star::uno::Exception;
56 using ::com::sun::star::uno::Reference;
57 using ::com::sun::star::uno::UNO_QUERY_THROW;
58 using ::com::sun::star::util::DateTime;
59 using ::com::sun::star::lang::XMultiServiceFactory;
60 using ::com::sun::star::ucb::XSimpleFileAccess;
61 using ::com::sun::star::io::XActiveDataSink;
62 using ::com::sun::star::io::XActiveDataSource;
63 using ::com::sun::star::io::XInputStream;
64 using ::com::sun::star::io::XOutputStream;
65 using ::com::sun::star::io::XTextInputStream;
66 using ::com::sun::star::io::XTextOutputStream;
67 using ::comphelper::MediaDescriptor;
68 using ::oox::core::FilterBase;
70 namespace oox {
71 namespace dump {
73 const sal_Unicode OOX_DUMP_BOM = 0xFEFF;
74 const sal_Int32 OOX_DUMP_MAXSTRLEN = 80;
75 const sal_Int32 OOX_DUMP_INDENT = 2;
76 const sal_Unicode OOX_DUMP_BINDOT = '.';
77 const sal_Unicode OOX_DUMP_CFG_LISTSEP = ',';
78 const sal_Unicode OOX_DUMP_CFG_QUOTE = '\'';
79 const sal_Unicode OOX_DUMP_LF = '\n';
80 const sal_Unicode OOX_DUMP_ITEMSEP = '=';
81 const sal_Int32 OOX_DUMP_BYTESPERLINE = 16;
82 const sal_Int64 OOX_DUMP_MAXARRAY = 16;
84 // ============================================================================
85 // ============================================================================
87 // file names -----------------------------------------------------------------
89 OUString InputOutputHelper::convertFileNameToUrl( const OUString& rFileName )
91 OUString aFileUrl;
92 if( ::osl::FileBase::getFileURLFromSystemPath( rFileName, aFileUrl ) == ::osl::FileBase::E_None )
93 return aFileUrl;
94 return OUString();
97 sal_Int32 InputOutputHelper::getFileNamePos( const OUString& rFileUrl )
99 sal_Int32 nSepPos = rFileUrl.lastIndexOf( '/' );
100 return (nSepPos < 0) ? 0 : (nSepPos + 1);
103 OUString InputOutputHelper::getFileNameExtension( const OUString& rFileUrl )
105 sal_Int32 nNamePos = getFileNamePos( rFileUrl );
106 sal_Int32 nExtPos = rFileUrl.lastIndexOf( '.' );
107 if( nExtPos >= nNamePos )
108 return rFileUrl.copy( nExtPos + 1 );
109 return OUString();
112 // input streams --------------------------------------------------------------
114 Reference< XInputStream > InputOutputHelper::getXInputStream( BinaryInputStream& rStrm )
116 if( BinaryXInputStream* pXStrm = dynamic_cast< BinaryXInputStream* >( &rStrm ) )
117 return pXStrm->getXInputStream();
118 return 0;
121 Reference< XInputStream > InputOutputHelper::openInputStream(
122 const Reference< XMultiServiceFactory >& rxFactory, const OUString& rFileName )
124 Reference< XInputStream > xInStrm;
125 if( rxFactory.is() ) try
127 Reference< XSimpleFileAccess > xFileAccess( rxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY_THROW );
128 xInStrm = xFileAccess->openFileRead( rFileName );
130 catch( Exception& )
133 return xInStrm;
136 Reference< XTextInputStream > InputOutputHelper::openTextInputStream(
137 const Reference< XMultiServiceFactory >& rxFactory, const Reference< XInputStream >& rxInStrm, const OUString& rEncoding )
139 Reference< XTextInputStream > xTextInStrm;
140 if( rxFactory.is() && rxInStrm.is() ) try
142 Reference< XActiveDataSink > xDataSink( rxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TextInputStream" ) ), UNO_QUERY_THROW );
143 xDataSink->setInputStream( rxInStrm );
144 xTextInStrm.set( xDataSink, UNO_QUERY_THROW );
145 xTextInStrm->setEncoding( rEncoding );
147 catch( Exception& )
150 return xTextInStrm;
153 Reference< XTextInputStream > InputOutputHelper::openTextInputStream(
154 const Reference< XMultiServiceFactory >& rxFactory, const OUString& rFileName, const OUString& rEncoding )
156 return openTextInputStream( rxFactory, openInputStream( rxFactory, rFileName ), rEncoding );
159 // output streams -------------------------------------------------------------
161 Reference< XOutputStream > InputOutputHelper::openOutputStream(
162 const Reference< XMultiServiceFactory >& rxFactory, const OUString& rFileName )
164 Reference< XOutputStream > xOutStrm;
165 if( rxFactory.is() ) try
167 Reference< XSimpleFileAccess > xFileAccess( rxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY_THROW );
168 xOutStrm = xFileAccess->openFileWrite( rFileName );
170 catch( Exception& )
173 return xOutStrm;
176 Reference< XTextOutputStream > InputOutputHelper::openTextOutputStream(
177 const Reference< XMultiServiceFactory >& rxFactory, const Reference< XOutputStream >& rxOutStrm, const OUString& rEncoding )
179 Reference< XTextOutputStream > xTextOutStrm;
180 if( rxFactory.is() && rxOutStrm.is() ) try
182 Reference< XActiveDataSource > xDataSource( rxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TextOutputStream" ) ), UNO_QUERY_THROW );
183 xDataSource->setOutputStream( rxOutStrm );
184 xTextOutStrm.set( xDataSource, UNO_QUERY_THROW );
185 xTextOutStrm->setEncoding( rEncoding );
187 catch( Exception& )
190 return xTextOutStrm;
193 Reference< XTextOutputStream > InputOutputHelper::openTextOutputStream(
194 const Reference< XMultiServiceFactory >& rxFactory, const OUString& rFileName, const OUString& rEncoding )
196 return openTextOutputStream( rxFactory, openOutputStream( rxFactory, rFileName ), rEncoding );
199 // ============================================================================
200 // ============================================================================
202 ItemFormat::ItemFormat() :
203 meDataType( DATATYPE_VOID ),
204 meFmtType( FORMATTYPE_NONE )
208 void ItemFormat::set( DataType eDataType, FormatType eFmtType, const OUString& rItemName )
210 meDataType = eDataType;
211 meFmtType = eFmtType;
212 maItemName = rItemName;
213 maListName = OUString();
216 void ItemFormat::set( DataType eDataType, FormatType eFmtType, const OUString& rItemName, const OUString& rListName )
218 set( eDataType, eFmtType, rItemName );
219 maListName = rListName;
222 OUStringVector::const_iterator ItemFormat::parse( const OUStringVector& rFormatVec )
224 set( DATATYPE_VOID, FORMATTYPE_NONE, OUString() );
226 OUStringVector::const_iterator aIt = rFormatVec.begin(), aEnd = rFormatVec.end();
227 OUString aDataType, aFmtType;
228 if( aIt != aEnd ) aDataType = *aIt++;
229 if( aIt != aEnd ) aFmtType = *aIt++;
230 if( aIt != aEnd ) maItemName = *aIt++;
231 if( aIt != aEnd ) maListName = *aIt++;
233 meDataType = StringHelper::convertToDataType( aDataType );
234 meFmtType = StringHelper::convertToFormatType( aFmtType );
236 if( meFmtType == FORMATTYPE_NONE )
238 if( aFmtType.equalsAscii( "unused" ) )
239 set( meDataType, FORMATTYPE_HEX, CREATE_OUSTRING( OOX_DUMP_UNUSED ) );
240 else if( aFmtType.equalsAscii( "unknown" ) )
241 set( meDataType, FORMATTYPE_HEX, CREATE_OUSTRING( OOX_DUMP_UNKNOWN ) );
244 return aIt;
247 OUStringVector ItemFormat::parse( const OUString& rFormatStr )
249 OUStringVector aFormatVec;
250 StringHelper::convertStringToStringList( aFormatVec, rFormatStr, false );
251 OUStringVector::const_iterator aIt = parse( aFormatVec );
252 return OUStringVector( aIt, const_cast< const OUStringVector& >( aFormatVec ).end() );
255 // ============================================================================
256 // ============================================================================
258 // append string to string ----------------------------------------------------
260 void StringHelper::appendChar( OUStringBuffer& rStr, sal_Unicode cChar, sal_Int32 nCount )
262 for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
263 rStr.append( cChar );
266 void StringHelper::appendString( OUStringBuffer& rStr, const OUString& rData, sal_Int32 nWidth, sal_Unicode cFill )
268 appendChar( rStr, cFill, nWidth - rData.getLength() );
269 rStr.append( rData );
272 // append decimal -------------------------------------------------------------
274 void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt8 nData, sal_Int32 nWidth, sal_Unicode cFill )
276 appendString( rStr, OUString::valueOf( static_cast< sal_Int32 >( nData ) ), nWidth, cFill );
279 void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int8 nData, sal_Int32 nWidth, sal_Unicode cFill )
281 appendString( rStr, OUString::valueOf( static_cast< sal_Int32 >( nData ) ), nWidth, cFill );
284 void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt16 nData, sal_Int32 nWidth, sal_Unicode cFill )
286 appendString( rStr, OUString::valueOf( static_cast< sal_Int32 >( nData ) ), nWidth, cFill );
289 void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int16 nData, sal_Int32 nWidth, sal_Unicode cFill )
291 appendString( rStr, OUString::valueOf( static_cast< sal_Int32 >( nData ) ), nWidth, cFill );
294 void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt32 nData, sal_Int32 nWidth, sal_Unicode cFill )
296 appendString( rStr, OUString::valueOf( static_cast< sal_Int64 >( nData ) ), nWidth, cFill );
299 void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int32 nData, sal_Int32 nWidth, sal_Unicode cFill )
301 appendString( rStr, OUString::valueOf( nData ), nWidth, cFill );
304 void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt64 nData, sal_Int32 nWidth, sal_Unicode cFill )
306 /* Values greater than biggest signed 64bit integer will change to
307 negative when converting to sal_Int64. Therefore, the trailing digit
308 will be written separately. */
309 OUStringBuffer aBuffer;
310 if( nData > 9 )
311 aBuffer.append( OUString::valueOf( static_cast< sal_Int64 >( nData / 10 ) ) );
312 aBuffer.append( static_cast< sal_Unicode >( '0' + (nData % 10) ) );
313 appendString( rStr, aBuffer.makeStringAndClear(), nWidth, cFill );
316 void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int64 nData, sal_Int32 nWidth, sal_Unicode cFill )
318 appendString( rStr, OUString::valueOf( nData ), nWidth, cFill );
321 void StringHelper::appendDec( OUStringBuffer& rStr, double fData, sal_Int32 nWidth, sal_Unicode cFill )
323 appendString( rStr, ::rtl::math::doubleToUString( fData, rtl_math_StringFormat_G, 15, '.', true ), nWidth, cFill );
326 // append hexadecimal ---------------------------------------------------------
328 void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt8 nData, bool bPrefix )
330 static const sal_Unicode spcHexDigits[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
331 if( bPrefix )
332 rStr.appendAscii( "0x" );
333 rStr.append( spcHexDigits[ (nData >> 4) & 0x0F ] ).append( spcHexDigits[ nData & 0x0F ] );
336 void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int8 nData, bool bPrefix )
338 appendHex( rStr, static_cast< sal_uInt8 >( nData ), bPrefix );
341 void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt16 nData, bool bPrefix )
343 appendHex( rStr, static_cast< sal_uInt8 >( nData >> 8 ), bPrefix );
344 appendHex( rStr, static_cast< sal_uInt8 >( nData ), false );
347 void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int16 nData, bool bPrefix )
349 appendHex( rStr, static_cast< sal_uInt16 >( nData ), bPrefix );
352 void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt32 nData, bool bPrefix )
354 appendHex( rStr, static_cast< sal_uInt16 >( nData >> 16 ), bPrefix );
355 appendHex( rStr, static_cast< sal_uInt16 >( nData ), false );
358 void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int32 nData, bool bPrefix )
360 appendHex( rStr, static_cast< sal_uInt32 >( nData ), bPrefix );
363 void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt64 nData, bool bPrefix )
365 appendHex( rStr, static_cast< sal_uInt32 >( nData >> 32 ), bPrefix );
366 appendHex( rStr, static_cast< sal_uInt32 >( nData ), false );
369 void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int64 nData, bool bPrefix )
371 appendHex( rStr, static_cast< sal_uInt64 >( nData ), bPrefix );
374 void StringHelper::appendHex( OUStringBuffer& rStr, double fData, bool bPrefix )
376 appendHex( rStr, *reinterpret_cast< const sal_uInt64* >( &fData ), bPrefix );
379 // append shortened hexadecimal -----------------------------------------------
381 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt8 nData, bool bPrefix )
383 appendHex( rStr, nData, bPrefix );
386 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int8 nData, bool bPrefix )
388 appendHex( rStr, nData, bPrefix );
391 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt16 nData, bool bPrefix )
393 if( nData > SAL_MAX_UINT8 )
394 appendHex( rStr, nData, bPrefix );
395 else
396 appendHex( rStr, static_cast< sal_uInt8 >( nData ), bPrefix );
399 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int16 nData, bool bPrefix )
401 appendShortHex( rStr, static_cast< sal_uInt16 >( nData ), bPrefix );
404 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt32 nData, bool bPrefix )
406 if( nData > SAL_MAX_UINT16 )
407 appendHex( rStr, nData, bPrefix );
408 else
409 appendShortHex( rStr, static_cast< sal_uInt16 >( nData ), bPrefix );
412 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int32 nData, bool bPrefix )
414 appendShortHex( rStr, static_cast< sal_uInt32 >( nData ), bPrefix );
417 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt64 nData, bool bPrefix )
419 if( nData > SAL_MAX_UINT32 )
420 appendHex( rStr, nData, bPrefix );
421 else
422 appendShortHex( rStr, static_cast< sal_uInt32 >( nData ), bPrefix );
425 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int64 nData, bool bPrefix )
427 appendShortHex( rStr, static_cast< sal_uInt64 >( nData ), bPrefix );
430 void StringHelper::appendShortHex( OUStringBuffer& rStr, double fData, bool bPrefix )
432 appendHex( rStr, fData, bPrefix );
435 // append binary --------------------------------------------------------------
437 void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt8 nData, bool bDots )
439 for( sal_uInt8 nMask = 0x80; nMask != 0; (nMask >>= 1) &= 0x7F )
441 rStr.append( static_cast< sal_Unicode >( (nData & nMask) ? '1' : '0' ) );
442 if( bDots && (nMask == 0x10) )
443 rStr.append( OOX_DUMP_BINDOT );
447 void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int8 nData, bool bDots )
449 appendBin( rStr, static_cast< sal_uInt8 >( nData ), bDots );
452 void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt16 nData, bool bDots )
454 appendBin( rStr, static_cast< sal_uInt8 >( nData >> 8 ), bDots );
455 if( bDots )
456 rStr.append( OOX_DUMP_BINDOT );
457 appendBin( rStr, static_cast< sal_uInt8 >( nData ), bDots );
460 void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int16 nData, bool bDots )
462 appendBin( rStr, static_cast< sal_uInt16 >( nData ), bDots );
465 void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt32 nData, bool bDots )
467 appendBin( rStr, static_cast< sal_uInt16 >( nData >> 16 ), bDots );
468 if( bDots )
469 rStr.append( OOX_DUMP_BINDOT );
470 appendBin( rStr, static_cast< sal_uInt16 >( nData ), bDots );
473 void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int32 nData, bool bDots )
475 appendBin( rStr, static_cast< sal_uInt32 >( nData ), bDots );
478 void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt64 nData, bool bDots )
480 appendBin( rStr, static_cast< sal_uInt32 >( nData >> 32 ), bDots );
481 if( bDots )
482 rStr.append( OOX_DUMP_BINDOT );
483 appendBin( rStr, static_cast< sal_uInt32 >( nData ), bDots );
486 void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int64 nData, bool bDots )
488 appendBin( rStr, static_cast< sal_uInt64 >( nData ), bDots );
491 void StringHelper::appendBin( OUStringBuffer& rStr, double fData, bool bDots )
493 appendBin( rStr, *reinterpret_cast< const sal_uInt64* >( &fData ), bDots );
496 // append formatted value -----------------------------------------------------
498 void StringHelper::appendBool( OUStringBuffer& rStr, bool bData )
500 rStr.appendAscii( bData ? "true" : "false" );
503 // append columns, rows, addresses --------------------------------------------
505 void StringHelper::appendAddrCol( OUStringBuffer& rStr, sal_Int32 nCol, bool bRel )
507 if( !bRel ) rStr.append( OOX_DUMP_ADDRABS );
508 sal_Int32 nPos = rStr.getLength();
509 for( sal_Int32 nTemp = nCol; nTemp >= 0; (nTemp /= 26) -= 1 )
510 rStr.insert( nPos, static_cast< sal_Unicode >( 'A' + (nTemp % 26) ) );
513 void StringHelper::appendAddrRow( OUStringBuffer& rStr, sal_Int32 nRow, bool bRel )
515 if( !bRel ) rStr.append( OOX_DUMP_ADDRABS );
516 appendDec( rStr, nRow + 1 );
519 void StringHelper::appendAddrName( OUStringBuffer& rStr, sal_Unicode cPrefix, sal_Int32 nColRow, bool bRel )
521 rStr.append( cPrefix );
522 if( bRel && (nColRow != 0) )
524 rStr.append( OOX_DUMP_R1C1OPEN );
525 appendDec( rStr, nColRow );
526 rStr.append( OOX_DUMP_R1C1CLOSE );
528 else if( !bRel )
529 appendDec( rStr, nColRow + 1 );
532 void StringHelper::appendAddress( OUStringBuffer& rStr, const Address& rPos )
534 appendAddrCol( rStr, rPos.mnCol, true );
535 appendAddrRow( rStr, rPos.mnRow, true );
538 void StringHelper::appendRange( OUStringBuffer& rStr, const Range& rRange )
540 appendAddress( rStr, rRange.maFirst );
541 rStr.append( OOX_DUMP_RANGESEP );
542 appendAddress( rStr, rRange.maLast );
545 void StringHelper::appendRangeList( OUStringBuffer& rStr, const RangeList& rRanges )
547 OUStringBuffer aData;
548 for( RangeList::const_iterator aIt = rRanges.begin(), aEnd = rRanges.end(); aIt != aEnd; ++aIt )
550 OUStringBuffer aRange;
551 appendRange( aRange, *aIt );
552 appendToken( aData, aRange.makeStringAndClear(), OOX_DUMP_LISTSEP );
554 rStr.append( aData.makeStringAndClear() );
557 void StringHelper::appendAddress( OUStringBuffer& rStr, const TokenAddress& rPos, bool bR1C1 )
559 if( bR1C1 && (rPos.mbRelCol || rPos.mbRelRow) )
561 appendAddrName( rStr, OOX_DUMP_R1C1ROW, rPos.mnRow, rPos.mbRelRow );
562 appendAddrName( rStr, OOX_DUMP_R1C1COL, rPos.mnCol, rPos.mbRelCol );
564 else
566 appendAddrCol( rStr, rPos.mnCol, rPos.mbRelCol );
567 appendAddrRow( rStr, rPos.mnRow, rPos.mbRelRow );
571 void StringHelper::appendRange( OUStringBuffer& rStr, const TokenRange& rRange, bool bR1C1 )
573 appendAddress( rStr, rRange.maFirst, bR1C1 );
574 rStr.append( OOX_DUMP_RANGESEP );
575 appendAddress( rStr, rRange.maLast, bR1C1 );
578 // encoded text output --------------------------------------------------------
580 void StringHelper::appendCChar( OUStringBuffer& rStr, sal_Unicode cChar, bool bPrefix )
582 if( cChar > 0x00FF )
584 if( bPrefix )
585 rStr.appendAscii( "\\u" );
586 appendHex( rStr, static_cast< sal_uInt16 >( cChar ), false );
588 else
590 if( bPrefix )
591 rStr.appendAscii( "\\x" );
592 appendHex( rStr, static_cast< sal_uInt8 >( cChar ), false );
596 void StringHelper::appendEncChar( OUStringBuffer& rStr, sal_Unicode cChar, sal_Int32 nCount, bool bPrefix )
598 if( cChar < 0x0020 )
600 // C-style hex code
601 OUStringBuffer aCode;
602 appendCChar( aCode, cChar, bPrefix );
603 for( sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx )
604 rStr.append( aCode );
606 else
608 appendChar( rStr, cChar, nCount );
612 void StringHelper::appendEncString( OUStringBuffer& rStr, const OUString& rData, bool bPrefix )
614 sal_Int32 nBeg = 0;
615 sal_Int32 nIdx = 0;
616 sal_Int32 nEnd = rData.getLength();
617 while( nIdx < nEnd )
619 // find next character that needs encoding
620 while( (nIdx < nEnd) && (rData[ nIdx ] >= 0x20) ) ++nIdx;
621 // append portion
622 if( nBeg < nIdx )
624 if( (nBeg == 0) && (nIdx == nEnd) )
625 rStr.append( rData );
626 else
627 rStr.append( rData.copy( nBeg, nIdx - nBeg ) );
629 // append characters to be encoded
630 while( (nIdx < nEnd) && (rData[ nIdx ] < 0x20) )
632 appendCChar( rStr, rData[ nIdx ], bPrefix );
633 ++nIdx;
635 // adjust limits
636 nBeg = nIdx;
640 // token list -----------------------------------------------------------------
642 void StringHelper::appendToken( OUStringBuffer& rStr, const OUString& rToken, sal_Unicode cSep )
644 if( (rStr.getLength() > 0) && (rToken.getLength() > 0) )
645 rStr.append( cSep );
646 rStr.append( rToken );
649 void StringHelper::appendToken( OUStringBuffer& rStr, sal_Int64 nToken, sal_Unicode cSep )
651 OUStringBuffer aToken;
652 appendDec( aToken, nToken );
653 appendToken( rStr, aToken.makeStringAndClear(), cSep );
656 void StringHelper::prependToken( OUStringBuffer& rStr, const OUString& rToken, sal_Unicode cSep )
658 if( (rStr.getLength() > 0) && (rToken.getLength() > 0) )
659 rStr.insert( 0, cSep );
660 rStr.insert( 0, rToken );
663 void StringHelper::prependToken( OUStringBuffer& rStr, sal_Int64 nToken, sal_Unicode cSep )
665 OUStringBuffer aToken;
666 appendDec( aToken, nToken );
667 prependToken( rStr, aToken.makeStringAndClear(), cSep );
670 void StringHelper::appendIndex( OUStringBuffer& rStr, const OUString& rIdx )
672 rStr.append( sal_Unicode( '[' ) ).append( rIdx ).append( sal_Unicode( ']' ) );
675 void StringHelper::appendIndex( OUStringBuffer& rStr, sal_Int64 nIdx )
677 OUStringBuffer aToken;
678 appendDec( aToken, nIdx );
679 appendIndex( rStr, aToken.makeStringAndClear() );
682 void StringHelper::appendIndexedText( OUStringBuffer& rStr, const OUString& rData, const OUString& rIdx )
684 rStr.append( rData );
685 appendIndex( rStr, rIdx );
688 void StringHelper::appendIndexedText( OUStringBuffer& rStr, const OUString& rData, sal_Int64 nIdx )
690 rStr.append( rData );
691 appendIndex( rStr, nIdx );
694 OUString StringHelper::getToken( const OUString& rData, sal_Int32& rnPos, sal_Unicode cSep )
696 return trimSpaces( rData.getToken( 0, cSep, rnPos ) );
699 void StringHelper::enclose( OUStringBuffer& rStr, sal_Unicode cOpen, sal_Unicode cClose )
701 rStr.insert( 0, cOpen ).append( cClose ? cClose : cOpen );
704 // string conversion ----------------------------------------------------------
706 namespace {
708 sal_Int32 lclIndexOf( const OUString& rStr, sal_Unicode cChar, sal_Int32 nStartPos )
710 sal_Int32 nIndex = rStr.indexOf( cChar, nStartPos );
711 return (nIndex < 0) ? rStr.getLength() : nIndex;
714 OUString lclTrimQuotedStringList( const OUString& rStr )
716 OUStringBuffer aBuffer;
717 sal_Int32 nPos = 0;
718 sal_Int32 nLen = rStr.getLength();
719 while( nPos < nLen )
721 if( rStr[ nPos ] == OOX_DUMP_CFG_QUOTE )
723 // quoted string, skip leading quote character
724 ++nPos;
725 // process quoted text and ambedded literal quote characters
726 OUStringBuffer aToken;
729 // seek to next quote character and add text portion to token buffer
730 sal_Int32 nEnd = lclIndexOf( rStr, OOX_DUMP_CFG_QUOTE, nPos );
731 aToken.append( rStr.copy( nPos, nEnd - nPos ) );
732 // process literal quotes
733 while( (nEnd + 1 < nLen) && (rStr[ nEnd ] == OOX_DUMP_CFG_QUOTE) && (rStr[ nEnd + 1 ] == OOX_DUMP_CFG_QUOTE) )
735 aToken.append( OOX_DUMP_CFG_QUOTE );
736 nEnd += 2;
738 // nEnd is start of possible next text portion
739 nPos = nEnd;
741 while( (nPos < nLen) && (rStr[ nPos ] != OOX_DUMP_CFG_QUOTE) );
742 // add token, seek to list separator, ignore text following closing quote
743 aBuffer.append( aToken.makeStringAndClear() );
744 nPos = lclIndexOf( rStr, OOX_DUMP_CFG_LISTSEP, nPos );
745 if( nPos < nLen )
746 aBuffer.append( OOX_DUMP_LF );
747 // set current position behind list separator
748 ++nPos;
750 else
752 // find list separator, add token text to buffer
753 sal_Int32 nEnd = lclIndexOf( rStr, OOX_DUMP_CFG_LISTSEP, nPos );
754 aBuffer.append( rStr.copy( nPos, nEnd - nPos ) );
755 if( nEnd < nLen )
756 aBuffer.append( OOX_DUMP_LF );
757 // set current position behind list separator
758 nPos = nEnd + 1;
762 return aBuffer.makeStringAndClear();
765 } // namespace
767 OUString StringHelper::trimSpaces( const OUString& rStr )
769 sal_Int32 nBeg = 0;
770 while( (nBeg < rStr.getLength()) && ((rStr[ nBeg ] == ' ') || (rStr[ nBeg ] == '\t')) )
771 ++nBeg;
772 sal_Int32 nEnd = rStr.getLength();
773 while( (nEnd > nBeg) && ((rStr[ nEnd - 1 ] == ' ') || (rStr[ nEnd - 1 ] == '\t')) )
774 --nEnd;
775 return rStr.copy( nBeg, nEnd - nBeg );
778 OString StringHelper::convertToUtf8( const OUString& rStr )
780 return OUStringToOString( rStr, RTL_TEXTENCODING_UTF8 );
783 DataType StringHelper::convertToDataType( const OUString& rStr )
785 DataType eType = DATATYPE_VOID;
786 if( rStr.equalsAscii( "int8" ) )
787 eType = DATATYPE_INT8;
788 else if( rStr.equalsAscii( "uint8" ) )
789 eType = DATATYPE_UINT8;
790 else if( rStr.equalsAscii( "int16" ) )
791 eType = DATATYPE_INT16;
792 else if( rStr.equalsAscii( "uint16" ) )
793 eType = DATATYPE_UINT16;
794 else if( rStr.equalsAscii( "int32" ) )
795 eType = DATATYPE_INT32;
796 else if( rStr.equalsAscii( "uint32" ) )
797 eType = DATATYPE_UINT32;
798 else if( rStr.equalsAscii( "int64" ) )
799 eType = DATATYPE_INT64;
800 else if( rStr.equalsAscii( "uint64" ) )
801 eType = DATATYPE_UINT64;
802 else if( rStr.equalsAscii( "float" ) )
803 eType = DATATYPE_FLOAT;
804 else if( rStr.equalsAscii( "double" ) )
805 eType = DATATYPE_DOUBLE;
806 return eType;
809 FormatType StringHelper::convertToFormatType( const OUString& rStr )
811 FormatType eType = FORMATTYPE_NONE;
812 if( rStr.equalsAscii( "dec" ) )
813 eType = FORMATTYPE_DEC;
814 else if( rStr.equalsAscii( "hex" ) )
815 eType = FORMATTYPE_HEX;
816 else if( rStr.equalsAscii( "shorthex" ) )
817 eType = FORMATTYPE_SHORTHEX;
818 else if( rStr.equalsAscii( "bin" ) )
819 eType = FORMATTYPE_BIN;
820 else if( rStr.equalsAscii( "fix" ) )
821 eType = FORMATTYPE_FIX;
822 else if( rStr.equalsAscii( "bool" ) )
823 eType = FORMATTYPE_BOOL;
824 return eType;
827 bool StringHelper::convertFromDec( sal_Int64& ornData, const OUString& rData )
829 sal_Int32 nPos = 0;
830 sal_Int32 nLen = rData.getLength();
831 bool bNeg = false;
832 if( (nLen > 0) && (rData[ 0 ] == '-') )
834 bNeg = true;
835 ++nPos;
837 ornData = 0;
838 for( ; nPos < nLen; ++nPos )
840 sal_Unicode cChar = rData[ nPos ];
841 if( (cChar < '0') || (cChar > '9') )
842 return false;
843 (ornData *= 10) += (cChar - '0');
845 if( bNeg )
846 ornData *= -1;
847 return true;
850 bool StringHelper::convertFromHex( sal_Int64& ornData, const OUString& rData )
852 ornData = 0;
853 for( sal_Int32 nPos = 0, nLen = rData.getLength(); nPos < nLen; ++nPos )
855 sal_Unicode cChar = rData[ nPos ];
856 if( ('0' <= cChar) && (cChar <= '9') )
857 cChar -= '0';
858 else if( ('A' <= cChar) && (cChar <= 'F') )
859 cChar -= ('A' - 10);
860 else if( ('a' <= cChar) && (cChar <= 'f') )
861 cChar -= ('a' - 10);
862 else
863 return false;
864 (ornData <<= 4) += cChar;
866 return true;
869 bool StringHelper::convertStringToInt( sal_Int64& ornData, const OUString& rData )
871 if( (rData.getLength() > 2) && (rData[ 0 ] == '0') && ((rData[ 1 ] == 'X') || (rData[ 1 ] == 'x')) )
872 return convertFromHex( ornData, rData.copy( 2 ) );
873 return convertFromDec( ornData, rData );
876 bool StringHelper::convertStringToDouble( double& orfData, const OUString& rData )
878 rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
879 sal_Int32 nSize = 0;
880 orfData = rtl::math::stringToDouble( rData, '.', '\0', &eStatus, &nSize );
881 return (eStatus == rtl_math_ConversionStatus_Ok) && (nSize == rData.getLength());
884 bool StringHelper::convertStringToBool( const OUString& rData )
886 if( rData.equalsAscii( "true" ) )
887 return true;
888 if( rData.equalsAscii( "false" ) )
889 return false;
890 sal_Int64 nData;
891 return convertStringToInt( nData, rData ) && (nData != 0);
894 void StringHelper::convertStringToStringList( OUStringVector& orVec, const OUString& rData, bool bIgnoreEmpty )
896 orVec.clear();
897 OUString aUnquotedData = lclTrimQuotedStringList( rData );
898 sal_Int32 nPos = 0;
899 sal_Int32 nLen = aUnquotedData.getLength();
900 while( (0 <= nPos) && (nPos < nLen) )
902 OUString aToken = getToken( aUnquotedData, nPos, OOX_DUMP_LF );
903 if( !bIgnoreEmpty || (aToken.getLength() > 0) )
904 orVec.push_back( aToken );
908 void StringHelper::convertStringToIntList( Int64Vector& orVec, const OUString& rData, bool bIgnoreEmpty )
910 orVec.clear();
911 OUString aUnquotedData = lclTrimQuotedStringList( rData );
912 sal_Int32 nPos = 0;
913 sal_Int32 nLen = aUnquotedData.getLength();
914 sal_Int64 nData;
915 while( (0 <= nPos) && (nPos < nLen) )
917 bool bOk = convertStringToInt( nData, getToken( aUnquotedData, nPos, OOX_DUMP_LF ) );
918 if( !bIgnoreEmpty || bOk )
919 orVec.push_back( bOk ? nData : 0 );
923 // ============================================================================
924 // ============================================================================
926 FormulaStack::FormulaStack() :
927 mbError( false )
931 void FormulaStack::pushOperand( const String& rOp, const OUString& rTokClass )
933 maFmlaStack.push( rOp );
934 maClassStack.push( rTokClass );
937 void FormulaStack::pushOperand( const String& rOp )
939 pushOperand( rOp, OUString( OOX_DUMP_BASECLASS ) );
942 void FormulaStack::pushUnaryOp( const String& rLOp, const String& rROp )
944 pushUnaryOp( maFmlaStack, rLOp, rROp );
945 pushUnaryOp( maClassStack, rLOp, rROp );
948 void FormulaStack::pushBinaryOp( const String& rOp )
950 pushBinaryOp( maFmlaStack, rOp );
951 pushBinaryOp( maClassStack, rOp );
954 void FormulaStack::pushFuncOp( const String& rFunc, const OUString& rTokClass, sal_uInt8 nParamCount )
956 pushFuncOp( maFmlaStack, rFunc, nParamCount );
957 pushFuncOp( maClassStack, rTokClass, nParamCount );
960 void FormulaStack::replaceOnTop( const OUString& rOld, const OUString& rNew )
962 if( !maFmlaStack.empty() )
964 sal_Int32 nPos = maFmlaStack.top().indexOf( rOld );
965 if( nPos >= 0 )
966 maFmlaStack.top() = maFmlaStack.top().copy( 0, nPos ) + rNew + maFmlaStack.top().copy( nPos + rOld.getLength() );
970 const OUString& FormulaStack::getString( const StringStack& rStack ) const
972 static const OUString saStackError = OOX_DUMP_ERRSTRING( "stack" );
973 return (mbError || rStack.empty()) ? saStackError : rStack.top();
976 void FormulaStack::pushUnaryOp( StringStack& rStack, const OUString& rLOp, const OUString& rROp )
978 if( check( !rStack.empty() ) )
979 rStack.top() = rLOp + rStack.top() + rROp;
982 void FormulaStack::pushBinaryOp( StringStack& rStack, const OUString& rOp )
984 OUString aSecond;
985 if( check( !rStack.empty() ) )
987 aSecond = rStack.top();
988 rStack.pop();
990 if( check( !rStack.empty() ) )
991 rStack.top() = rStack.top() + rOp + aSecond;
994 void FormulaStack::pushFuncOp( StringStack& rStack, const OUString& rOp, sal_uInt8 nParamCount )
996 OUStringBuffer aFunc;
997 for( sal_uInt8 nParam = 0; (nParam < nParamCount) && check( !rStack.empty() ); ++nParam )
999 StringHelper::prependToken( aFunc, rStack.top(), OOX_DUMP_FUNCSEP );
1000 rStack.pop();
1002 StringHelper::enclose( aFunc, '(', ')' );
1003 aFunc.insert( 0, rOp );
1004 rStack.push( aFunc.makeStringAndClear() );
1007 // ============================================================================
1008 // ============================================================================
1010 Base::~Base()
1014 // ============================================================================
1015 // ============================================================================
1017 ConfigItemBase::~ConfigItemBase()
1021 void ConfigItemBase::readConfigBlock( const ConfigInputStreamRef& rxStrm )
1023 readConfigBlockContents( rxStrm );
1026 void ConfigItemBase::implProcessConfigItemStr(
1027 const ConfigInputStreamRef& /*rxStrm*/, const OUString& /*rKey*/, const OUString& /*rData*/ )
1031 void ConfigItemBase::implProcessConfigItemInt(
1032 const ConfigInputStreamRef& /*rxStrm*/, sal_Int64 /*nKey*/, const OUString& /*rData*/ )
1036 void ConfigItemBase::readConfigBlockContents( const ConfigInputStreamRef& rxStrm )
1038 bool bLoop = true;
1039 while( bLoop && !rxStrm->isEOF() )
1041 OUString aKey, aData;
1042 switch( readConfigLine( rxStrm, aKey, aData ) )
1044 case LINETYPE_DATA:
1045 processConfigItem( rxStrm, aKey, aData );
1046 break;
1047 case LINETYPE_END:
1048 bLoop = false;
1049 break;
1054 ConfigItemBase::LineType ConfigItemBase::readConfigLine(
1055 const ConfigInputStreamRef& rxStrm, OUString& orKey, OUString& orData ) const
1057 OUString aLine;
1058 while( !rxStrm->isEOF() && (aLine.getLength() == 0) )
1060 try { aLine = rxStrm->readLine(); } catch( Exception& ) { aLine = OUString(); }
1061 if( (aLine.getLength() > 0) && (aLine[ 0 ] == OOX_DUMP_BOM) )
1062 aLine = aLine.copy( 1 );
1063 aLine = StringHelper::trimSpaces( aLine );
1064 if( aLine.getLength() > 0 )
1066 // ignore comments (starting with hash or semicolon)
1067 sal_Unicode cChar = aLine[ 0 ];
1068 if( (cChar == '#') || (cChar == ';') )
1069 aLine = OUString();
1073 LineType eResult = LINETYPE_END;
1074 if( aLine.getLength() > 0 )
1076 sal_Int32 nEqPos = aLine.indexOf( '=' );
1077 if( nEqPos < 0 )
1079 orKey = aLine;
1081 else
1083 orKey = StringHelper::trimSpaces( aLine.copy( 0, nEqPos ) );
1084 orData = StringHelper::trimSpaces( aLine.copy( nEqPos + 1 ) );
1087 if( (orKey.getLength() > 0) && ((orData.getLength() > 0) || !orKey.equalsAscii( "end" )) )
1088 eResult = LINETYPE_DATA;
1091 return eResult;
1094 ConfigItemBase::LineType ConfigItemBase::readConfigLine( const ConfigInputStreamRef& rxStrm ) const
1096 OUString aKey, aData;
1097 return readConfigLine( rxStrm, aKey, aData );
1100 void ConfigItemBase::processConfigItem(
1101 const ConfigInputStreamRef& rxStrm, const OUString& rKey, const OUString& rData )
1103 sal_Int64 nKey;
1104 if( StringHelper::convertStringToInt( nKey, rKey ) )
1105 implProcessConfigItemInt( rxStrm, nKey, rData );
1106 else
1107 implProcessConfigItemStr( rxStrm, rKey, rData );
1110 // ============================================================================
1112 NameListBase::~NameListBase()
1116 void NameListBase::setName( sal_Int64 nKey, const String& rName )
1118 implSetName( nKey, rName );
1121 void NameListBase::includeList( const NameListRef& rxList )
1123 if( rxList.get() )
1125 for( const_iterator aIt = rxList->begin(), aEnd = rxList->end(); aIt != aEnd; ++aIt )
1126 maMap[ aIt->first ] = aIt->second;
1127 implIncludeList( *rxList );
1131 bool NameListBase::implIsValid() const
1133 return true;
1136 void NameListBase::implProcessConfigItemStr(
1137 const ConfigInputStreamRef& rxStrm, const OUString& rKey, const OUString& rData )
1139 if( rKey.equalsAscii( "include" ) )
1140 include( rData );
1141 else if( rKey.equalsAscii( "exclude" ) )
1142 exclude( rData );
1143 else
1144 ConfigItemBase::implProcessConfigItemStr( rxStrm, rKey, rData );
1147 void NameListBase::implProcessConfigItemInt(
1148 const ConfigInputStreamRef& /*rxStrm*/, sal_Int64 nKey, const OUString& rData )
1150 implSetName( nKey, rData );
1153 void NameListBase::insertRawName( sal_Int64 nKey, const OUString& rName )
1155 maMap[ nKey ] = rName;
1158 const OUString* NameListBase::findRawName( sal_Int64 nKey ) const
1160 const_iterator aIt = maMap.find( nKey );
1161 return (aIt == end()) ? 0 : &aIt->second;
1164 void NameListBase::include( const OUString& rListKeys )
1166 OUStringVector aVec;
1167 StringHelper::convertStringToStringList( aVec, rListKeys, true );
1168 for( OUStringVector::const_iterator aIt = aVec.begin(), aEnd = aVec.end(); aIt != aEnd; ++aIt )
1169 includeList( mrCfgData.getNameList( *aIt ) );
1172 void NameListBase::exclude( const OUString& rKeys )
1174 Int64Vector aVec;
1175 StringHelper::convertStringToIntList( aVec, rKeys, true );
1176 for( Int64Vector::const_iterator aIt = aVec.begin(), aEnd = aVec.end(); aIt != aEnd; ++aIt )
1177 maMap.erase( *aIt );
1180 // ============================================================================
1182 ConstList::ConstList( const SharedConfigData& rCfgData ) :
1183 NameListBase( rCfgData ),
1184 maDefName( OOX_DUMP_ERR_NONAME ),
1185 mbQuoteNames( false )
1189 void ConstList::implProcessConfigItemStr(
1190 const ConfigInputStreamRef& rxStrm, const OUString& rKey, const OUString& rData )
1192 if( rKey.equalsAscii( "default" ) )
1193 setDefaultName( rData );
1194 else if( rKey.equalsAscii( "quote-names" ) )
1195 setQuoteNames( StringHelper::convertStringToBool( rData ) );
1196 else
1197 NameListBase::implProcessConfigItemStr( rxStrm, rKey, rData );
1200 void ConstList::implSetName( sal_Int64 nKey, const OUString& rName )
1202 insertRawName( nKey, rName );
1205 OUString ConstList::implGetName( const Config& /*rCfg*/, sal_Int64 nKey ) const
1207 const OUString* pName = findRawName( nKey );
1208 OUString aName = pName ? *pName : maDefName;
1209 if( mbQuoteNames )
1211 OUStringBuffer aBuffer( aName );
1212 StringHelper::enclose( aBuffer, OOX_DUMP_STRQUOTE );
1213 aName = aBuffer.makeStringAndClear();
1215 return aName;
1218 OUString ConstList::implGetNameDbl( const Config& /*rCfg*/, double /*fValue*/ ) const
1220 return OUString();
1223 void ConstList::implIncludeList( const NameListBase& rList )
1225 if( const ConstList* pConstList = dynamic_cast< const ConstList* >( &rList ) )
1227 maDefName = pConstList->maDefName;
1228 mbQuoteNames = pConstList->mbQuoteNames;
1232 // ============================================================================
1234 MultiList::MultiList( const SharedConfigData& rCfgData ) :
1235 ConstList( rCfgData ),
1236 mbIgnoreEmpty( true )
1240 void MultiList::setNamesFromVec( sal_Int64 nStartKey, const OUStringVector& rNames )
1242 sal_Int64 nKey = nStartKey;
1243 for( OUStringVector::const_iterator aIt = rNames.begin(), aEnd = rNames.end(); aIt != aEnd; ++aIt, ++nKey )
1244 if( !mbIgnoreEmpty || (aIt->getLength() > 0) )
1245 insertRawName( nKey, *aIt );
1248 void MultiList::implProcessConfigItemStr(
1249 const ConfigInputStreamRef& rxStrm, const OUString& rKey, const OUString& rData )
1251 if( rKey.equalsAscii( "ignore-empty" ) )
1252 mbIgnoreEmpty = StringHelper::convertStringToBool( rData );
1253 else
1254 ConstList::implProcessConfigItemStr( rxStrm, rKey, rData );
1257 void MultiList::implSetName( sal_Int64 nKey, const OUString& rName )
1259 OUStringVector aNames;
1260 StringHelper::convertStringToStringList( aNames, rName, false );
1261 setNamesFromVec( nKey, aNames );
1264 // ============================================================================
1266 FlagsList::FlagsList( const SharedConfigData& rCfgData ) :
1267 NameListBase( rCfgData ),
1268 mnIgnore( 0 )
1272 void FlagsList::implProcessConfigItemStr(
1273 const ConfigInputStreamRef& rxStrm, const OUString& rKey, const OUString& rData )
1275 if( rKey.equalsAscii( "ignore" ) )
1277 sal_Int64 nIgnore;
1278 if( StringHelper::convertStringToInt( nIgnore, rData ) )
1279 setIgnoreFlags( nIgnore );
1281 else
1283 NameListBase::implProcessConfigItemStr( rxStrm, rKey, rData );
1287 void FlagsList::implSetName( sal_Int64 nKey, const OUString& rName )
1289 insertRawName( nKey, rName );
1292 OUString FlagsList::implGetName( const Config& /*rCfg*/, sal_Int64 nKey ) const
1294 sal_Int64 nFlags = nKey;
1295 setFlag( nFlags, mnIgnore, false );
1296 sal_Int64 nFound = 0;
1297 OUStringBuffer aName;
1298 // add known flags
1299 for( const_iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt )
1301 sal_Int64 nMask = aIt->first;
1302 const OUString& rFlagName = aIt->second;
1303 bool bNegated = (rFlagName.getLength() > 0) && (rFlagName[ 0 ] == '!');
1304 sal_Int32 nBothSep = bNegated ? rFlagName.indexOf( '!', 1 ) : -1;
1305 bool bFlag = getFlag( nFlags, nMask );
1306 if( bFlag )
1308 if( !bNegated )
1309 StringHelper::appendToken( aName, rFlagName );
1310 else if( nBothSep > 0 )
1311 StringHelper::appendToken( aName, rFlagName.copy( nBothSep + 1 ) );
1313 else if( bNegated )
1315 if( nBothSep > 0 )
1316 StringHelper::appendToken( aName, rFlagName.copy( 1, nBothSep - 1 ) );
1317 else
1318 StringHelper::appendToken( aName, rFlagName.copy( 1 ) );
1320 setFlag( nFound, nMask );
1322 // add unknown flags
1323 setFlag( nFlags, nFound, false );
1324 if( nFlags != 0 )
1326 OUStringBuffer aUnknown( CREATE_OUSTRING( OOX_DUMP_UNKNOWN ) );
1327 aUnknown.append( OOX_DUMP_ITEMSEP );
1328 StringHelper::appendShortHex( aUnknown, nFlags, true );
1329 StringHelper::enclose( aUnknown, '(', ')' );
1330 StringHelper::appendToken( aName, aUnknown.makeStringAndClear() );
1332 return aName.makeStringAndClear();
1335 OUString FlagsList::implGetNameDbl( const Config& /*rCfg*/, double /*fValue*/ ) const
1337 return OUString();
1340 void FlagsList::implIncludeList( const NameListBase& rList )
1342 if( const FlagsList* pFlagsList = dynamic_cast< const FlagsList* >( &rList ) )
1343 mnIgnore = pFlagsList->mnIgnore;
1346 // ============================================================================
1348 CombiList::CombiList( const SharedConfigData& rCfgData ) :
1349 FlagsList( rCfgData )
1353 void CombiList::implSetName( sal_Int64 nKey, const OUString& rName )
1355 if( (nKey & (nKey - 1)) != 0 ) // more than a single bit set?
1357 ExtItemFormat& rItemFmt = maFmtMap[ nKey ];
1358 OUStringVector aRemain = rItemFmt.parse( rName );
1359 rItemFmt.mbShiftValue = aRemain.empty() || !aRemain.front().equalsAscii( "noshift" );
1361 else
1363 FlagsList::implSetName( nKey, rName );
1367 OUString CombiList::implGetName( const Config& rCfg, sal_Int64 nKey ) const
1369 sal_Int64 nFlags = nKey;
1370 sal_Int64 nFound = 0;
1371 OUStringBuffer aName;
1372 // add known flag fields
1373 for( ExtItemFormatMap::const_iterator aIt = maFmtMap.begin(), aEnd = maFmtMap.end(); aIt != aEnd; ++aIt )
1375 sal_Int64 nMask = aIt->first;
1376 if( nMask != 0 )
1378 const ExtItemFormat& rItemFmt = aIt->second;
1380 sal_uInt64 nUFlags = static_cast< sal_uInt64 >( nFlags );
1381 sal_uInt64 nUMask = static_cast< sal_uInt64 >( nMask );
1382 if( rItemFmt.mbShiftValue )
1383 while( (nUMask & 1) == 0 ) { nUFlags >>= 1; nUMask >>= 1; }
1385 sal_uInt64 nUValue = nUFlags & nUMask;
1386 sal_Int64 nSValue = static_cast< sal_Int64 >( nUValue );
1387 if( getFlag< sal_uInt64 >( nUValue, (nUMask + 1) >> 1 ) )
1388 setFlag( nSValue, static_cast< sal_Int64 >( ~nUMask ) );
1390 OUStringBuffer aItem( rItemFmt.maItemName );
1391 OUStringBuffer aValue;
1392 switch( rItemFmt.meDataType )
1394 case DATATYPE_INT8: StringHelper::appendValue( aValue, static_cast< sal_Int8 >( nSValue ), rItemFmt.meFmtType ); break;
1395 case DATATYPE_UINT8: StringHelper::appendValue( aValue, static_cast< sal_uInt8 >( nUValue ), rItemFmt.meFmtType ); break;
1396 case DATATYPE_INT16: StringHelper::appendValue( aValue, static_cast< sal_Int16 >( nSValue ), rItemFmt.meFmtType ); break;
1397 case DATATYPE_UINT16: StringHelper::appendValue( aValue, static_cast< sal_uInt16 >( nUValue ), rItemFmt.meFmtType ); break;
1398 case DATATYPE_INT32: StringHelper::appendValue( aValue, static_cast< sal_Int32 >( nSValue ), rItemFmt.meFmtType ); break;
1399 case DATATYPE_UINT32: StringHelper::appendValue( aValue, static_cast< sal_uInt32 >( nUValue ), rItemFmt.meFmtType ); break;
1400 case DATATYPE_INT64: StringHelper::appendValue( aValue, nSValue, rItemFmt.meFmtType ); break;
1401 case DATATYPE_UINT64: StringHelper::appendValue( aValue, nUValue, rItemFmt.meFmtType ); break;
1402 case DATATYPE_FLOAT: StringHelper::appendValue( aValue, static_cast< float >( nSValue ), rItemFmt.meFmtType ); break;
1403 case DATATYPE_DOUBLE: StringHelper::appendValue( aValue, static_cast< double >( nSValue ), rItemFmt.meFmtType ); break;
1404 default:;
1406 StringHelper::appendToken( aItem, aValue.makeStringAndClear(), OOX_DUMP_ITEMSEP );
1407 if( rItemFmt.maListName.getLength() > 0 )
1409 OUString aValueName = rCfg.getName( rItemFmt.maListName, static_cast< sal_Int64 >( nUValue ) );
1410 StringHelper::appendToken( aItem, aValueName, OOX_DUMP_ITEMSEP );
1412 StringHelper::enclose( aItem, '(', ')' );
1413 StringHelper::appendToken( aName, aItem.makeStringAndClear() );
1414 setFlag( nFound, nMask );
1417 setFlag( nFlags, nFound, false );
1418 StringHelper::appendToken( aName, FlagsList::implGetName( rCfg, nFlags ) );
1419 return aName.makeStringAndClear();
1422 void CombiList::implIncludeList( const NameListBase& rList )
1424 if( const CombiList* pCombiList = dynamic_cast< const CombiList* >( &rList ) )
1425 maFmtMap = pCombiList->maFmtMap;
1426 FlagsList::implIncludeList( rList );
1429 // ============================================================================
1431 UnitConverter::UnitConverter( const SharedConfigData& rCfgData ) :
1432 NameListBase( rCfgData ),
1433 mfFactor( 1.0 )
1437 void UnitConverter::implSetName( sal_Int64 /*nKey*/, const OUString& /*rName*/ )
1439 // nothing to do
1442 OUString UnitConverter::implGetName( const Config& rCfg, sal_Int64 nKey ) const
1444 return implGetNameDbl( rCfg, static_cast< double >( nKey ) );
1447 OUString UnitConverter::implGetNameDbl( const Config& /*rCfg*/, double fValue ) const
1449 OUStringBuffer aValue;
1450 StringHelper::appendDec( aValue, mfFactor * fValue );
1451 aValue.append( maUnitName );
1452 return aValue.makeStringAndClear();
1455 void UnitConverter::implIncludeList( const NameListBase& /*rList*/ )
1459 // ============================================================================
1461 NameListRef NameListWrapper::getNameList( const Config& rCfg ) const
1463 return mxList.get() ? mxList : (mxList = rCfg.getNameList( maName ));
1466 // ============================================================================
1467 // ============================================================================
1469 SharedConfigData::SharedConfigData( const OUString& rFileName,
1470 const Reference< XMultiServiceFactory >& rxFactory, const StorageRef& rxRootStrg,
1471 const OUString& rSysFileName, MediaDescriptor& rMediaDesc ) :
1472 mxFactory( rxFactory ),
1473 mxRootStrg( rxRootStrg ),
1474 maSysFileName( rSysFileName ),
1475 mrMediaDesc( rMediaDesc ),
1476 mbLoaded( false ),
1477 mbPwCancelled( false )
1479 OUString aFileUrl = InputOutputHelper::convertFileNameToUrl( rFileName );
1480 if( aFileUrl.getLength() > 0 )
1482 sal_Int32 nNamePos = InputOutputHelper::getFileNamePos( aFileUrl );
1483 maConfigPath = aFileUrl.copy( 0, nNamePos );
1484 mbLoaded = readConfigFile( aFileUrl );
1488 SharedConfigData::~SharedConfigData()
1492 void SharedConfigData::setOption( const OUString& rKey, const OUString& rData )
1494 maConfigData[ rKey ] = rData;
1497 const OUString* SharedConfigData::getOption( const OUString& rKey ) const
1499 ConfigDataMap::const_iterator aIt = maConfigData.find( rKey );
1500 return (aIt == maConfigData.end()) ? 0 : &aIt->second;
1503 void SharedConfigData::setNameList( const OUString& rListName, const NameListRef& rxList )
1505 if( rListName.getLength() > 0 )
1506 maNameLists[ rListName ] = rxList;
1509 void SharedConfigData::eraseNameList( const OUString& rListName )
1511 maNameLists.erase( rListName );
1514 NameListRef SharedConfigData::getNameList( const OUString& rListName ) const
1516 NameListRef xList;
1517 NameListMap::const_iterator aIt = maNameLists.find( rListName );
1518 if( aIt != maNameLists.end() )
1519 xList = aIt->second;
1520 return xList;
1523 OUString SharedConfigData::requestPassword( ::comphelper::IDocPasswordVerifier& rVerifier )
1525 OUString aPassword;
1526 if( !mbPwCancelled )
1528 ::std::vector< OUString > aDefaultPasswords;
1529 aDefaultPasswords.push_back( CREATE_OUSTRING( "VelvetSweatshop" ) );
1530 aPassword = ::comphelper::DocPasswordHelper::requestAndVerifyDocPassword(
1531 rVerifier, mrMediaDesc, ::comphelper::DocPasswordRequestType_MS, &aDefaultPasswords );
1532 mbPwCancelled = aPassword.getLength() == 0;
1534 return aPassword;
1537 bool SharedConfigData::implIsValid() const
1539 return mbLoaded && mxFactory.is() && mxRootStrg.get() && (maSysFileName.getLength() > 0);
1542 void SharedConfigData::implProcessConfigItemStr(
1543 const ConfigInputStreamRef& rxStrm, const OUString& rKey, const OUString& rData )
1545 if( rKey.equalsAscii( "include-config-file" ) )
1546 readConfigFile( maConfigPath + rData );
1547 else if( rKey.equalsAscii( "constlist" ) )
1548 readNameList< ConstList >( rxStrm, rData );
1549 else if( rKey.equalsAscii( "multilist" ) )
1550 readNameList< MultiList >( rxStrm, rData );
1551 else if( rKey.equalsAscii( "flagslist" ) )
1552 readNameList< FlagsList >( rxStrm, rData );
1553 else if( rKey.equalsAscii( "combilist" ) )
1554 readNameList< CombiList >( rxStrm, rData );
1555 else if( rKey.equalsAscii( "shortlist" ) )
1556 createShortList( rData );
1557 else if( rKey.equalsAscii( "unitconverter" ) )
1558 createUnitConverter( rData );
1559 else
1560 setOption( rKey, rData );
1563 bool SharedConfigData::readConfigFile( const OUString& rFileUrl )
1565 bool bLoaded = maConfigFiles.count( rFileUrl ) > 0;
1566 if( !bLoaded )
1568 Reference< XTextInputStream > xTextInStrm =
1569 InputOutputHelper::openTextInputStream( mxFactory, rFileUrl, CREATE_OUSTRING( "UTF-8" ) );
1570 if( xTextInStrm.is() )
1572 maConfigFiles.insert( rFileUrl );
1573 readConfigBlockContents( xTextInStrm );
1574 bLoaded = true;
1577 return bLoaded;
1580 void SharedConfigData::createShortList( const OUString& rData )
1582 OUStringVector aDataVec;
1583 StringHelper::convertStringToStringList( aDataVec, rData, false );
1584 if( aDataVec.size() >= 3 )
1586 sal_Int64 nStartKey;
1587 if( StringHelper::convertStringToInt( nStartKey, aDataVec[ 1 ] ) )
1589 ::boost::shared_ptr< MultiList > xList = createNameList< MultiList >( aDataVec[ 0 ] );
1590 if( xList.get() )
1592 aDataVec.erase( aDataVec.begin(), aDataVec.begin() + 2 );
1593 xList->setNamesFromVec( nStartKey, aDataVec );
1599 void SharedConfigData::createUnitConverter( const OUString& rData )
1601 OUStringVector aDataVec;
1602 StringHelper::convertStringToStringList( aDataVec, rData, false );
1603 if( aDataVec.size() >= 2 )
1605 OUString aFactor = aDataVec[ 1 ];
1606 bool bRecip = (aFactor.getLength() > 0) && (aFactor[ 0 ] == '/');
1607 if( bRecip )
1608 aFactor = aFactor.copy( 1 );
1609 double fFactor;
1610 if( StringHelper::convertStringToDouble( fFactor, aFactor ) && (fFactor != 0.0) )
1612 ::boost::shared_ptr< UnitConverter > xList = createNameList< UnitConverter >( aDataVec[ 0 ] );
1613 if( xList.get() )
1615 xList->setFactor( bRecip ? (1.0 / fFactor) : fFactor );
1616 if( aDataVec.size() >= 3 )
1617 xList->setUnitName( aDataVec[ 2 ] );
1623 // ============================================================================
1625 Config::Config( const Config& rParent ) :
1626 Base() // c'tor needs to be called explicitly to avoid compiler warning
1628 construct( rParent );
1631 Config::Config( const sal_Char* pcEnvVar, const FilterBase& rFilter )
1633 construct( pcEnvVar, rFilter );
1636 Config::Config( const sal_Char* pcEnvVar, const Reference< XMultiServiceFactory >& rxFactory, const StorageRef& rxRootStrg, const OUString& rSysFileName, MediaDescriptor& rMediaDesc )
1638 construct( pcEnvVar, rxFactory, rxRootStrg, rSysFileName, rMediaDesc );
1641 Config::~Config()
1645 void Config::construct( const Config& rParent )
1647 *this = rParent;
1650 void Config::construct( const sal_Char* pcEnvVar, const FilterBase& rFilter )
1652 if( rFilter.getFileUrl().getLength() > 0 )
1653 construct( pcEnvVar, rFilter.getGlobalFactory(), rFilter.getStorage(), rFilter.getFileUrl(), rFilter.getMediaDescriptor() );
1656 void Config::construct( const sal_Char* pcEnvVar, const Reference< XMultiServiceFactory >& rxFactory, const StorageRef& rxRootStrg, const OUString& rSysFileName, MediaDescriptor& rMediaDesc )
1658 if( pcEnvVar && rxRootStrg.get() && (rSysFileName.getLength() > 0) )
1659 if( const sal_Char* pcFileName = ::getenv( pcEnvVar ) )
1660 mxCfgData.reset( new SharedConfigData( OUString::createFromAscii( pcFileName ), rxFactory, rxRootStrg, rSysFileName, rMediaDesc ) );
1663 void Config::setStringOption( const String& rKey, const String& rData )
1665 mxCfgData->setOption( rKey, rData );
1668 const OUString& Config::getStringOption( const String& rKey, const OUString& rDefault ) const
1670 const OUString* pData = implGetOption( rKey );
1671 return pData ? *pData : rDefault;
1674 bool Config::getBoolOption( const String& rKey, bool bDefault ) const
1676 const OUString* pData = implGetOption( rKey );
1677 return pData ? StringHelper::convertStringToBool( *pData ) : bDefault;
1680 bool Config::isDumperEnabled() const
1682 return getBoolOption( "enable-dumper", false );
1685 bool Config::isImportEnabled() const
1687 return getBoolOption( "enable-import", true );
1690 void Config::setNameList( const String& rListName, const NameListRef& rxList )
1692 mxCfgData->setNameList( rListName, rxList );
1695 void Config::eraseNameList( const String& rListName )
1697 mxCfgData->eraseNameList( rListName );
1700 NameListRef Config::getNameList( const String& rListName ) const
1702 return implGetNameList( rListName );
1705 OUString Config::requestPassword( ::comphelper::IDocPasswordVerifier& rVerifier )
1707 return mxCfgData->requestPassword( rVerifier );
1710 bool Config::isPasswordCancelled() const
1712 return mxCfgData->isPasswordCancelled();
1715 bool Config::implIsValid() const
1717 return isValid( mxCfgData );
1720 const OUString* Config::implGetOption( const OUString& rKey ) const
1722 return mxCfgData->getOption( rKey );
1725 NameListRef Config::implGetNameList( const OUString& rListName ) const
1727 return mxCfgData->getNameList( rListName );
1730 // ============================================================================
1731 // ============================================================================
1733 Output::Output( const Reference< XTextOutputStream >& rxStrm )
1735 construct( rxStrm );
1738 Output::Output( const Reference< XMultiServiceFactory >& rxFactory, const OUString& rFileName )
1740 construct( InputOutputHelper::openTextOutputStream( rxFactory, rFileName, CREATE_OUSTRING( "UTF-8" ) ) );
1743 // ----------------------------------------------------------------------------
1745 void Output::newLine()
1747 if( maLine.getLength() > 0 )
1749 mxStrm->writeString( maIndent );
1750 maLine.append( sal_Unicode( '\n' ) );
1751 mxStrm->writeString( maLine.makeStringAndClear() );
1752 mnCol = 0;
1753 mnLastItem = 0;
1757 void Output::emptyLine( size_t nCount )
1759 for( size_t nIdx = 0; nIdx < nCount; ++nIdx )
1760 mxStrm->writeString( OUString( sal_Unicode( '\n' ) ) );
1763 void Output::incIndent()
1765 OUStringBuffer aBuffer( maIndent );
1766 StringHelper::appendChar( aBuffer, ' ', OOX_DUMP_INDENT );
1767 maIndent = aBuffer.makeStringAndClear();
1770 void Output::decIndent()
1772 if( maIndent.getLength() >= OOX_DUMP_INDENT )
1773 maIndent = maIndent.copy( OOX_DUMP_INDENT );
1776 void Output::resetIndent()
1778 maIndent = OUString();
1781 void Output::startTable( sal_Int32 nW1 )
1783 startTable( 1, &nW1 );
1786 void Output::startTable( sal_Int32 nW1, sal_Int32 nW2 )
1788 sal_Int32 pnColWidths[ 2 ];
1789 pnColWidths[ 0 ] = nW1;
1790 pnColWidths[ 1 ] = nW2;
1791 startTable( 2, pnColWidths );
1794 void Output::startTable( sal_Int32 nW1, sal_Int32 nW2, sal_Int32 nW3 )
1796 sal_Int32 pnColWidths[ 3 ];
1797 pnColWidths[ 0 ] = nW1;
1798 pnColWidths[ 1 ] = nW2;
1799 pnColWidths[ 2 ] = nW3;
1800 startTable( 3, pnColWidths );
1803 void Output::startTable( sal_Int32 nW1, sal_Int32 nW2, sal_Int32 nW3, sal_Int32 nW4 )
1805 sal_Int32 pnColWidths[ 4 ];
1806 pnColWidths[ 0 ] = nW1;
1807 pnColWidths[ 1 ] = nW2;
1808 pnColWidths[ 2 ] = nW3;
1809 pnColWidths[ 3 ] = nW4;
1810 startTable( 4, pnColWidths );
1813 void Output::startTable( size_t nColCount, const sal_Int32* pnColWidths )
1815 maColPos.clear();
1816 maColPos.push_back( 0 );
1817 sal_Int32 nColPos = 0;
1818 for( size_t nCol = 0; nCol < nColCount; ++nCol )
1820 nColPos = nColPos + pnColWidths[ nCol ];
1821 maColPos.push_back( nColPos );
1825 void Output::tab()
1827 tab( mnCol + 1 );
1830 void Output::tab( size_t nCol )
1832 mnCol = nCol;
1833 if( mnCol < maColPos.size() )
1835 sal_Int32 nColPos = maColPos[ mnCol ];
1836 if( maLine.getLength() >= nColPos )
1837 maLine.setLength( ::std::max< sal_Int32 >( nColPos - 1, 0 ) );
1838 StringHelper::appendChar( maLine, ' ', nColPos - maLine.getLength() );
1840 else
1842 StringHelper::appendChar( maLine, ' ', 2 );
1846 void Output::endTable()
1848 maColPos.clear();
1851 void Output::resetItemIndex( sal_Int64 nIdx )
1853 mnItemIdx = nIdx;
1856 void Output::startItem( const String& rItemName )
1858 if( mnItemLevel == 0 )
1860 if( (mnMultiLevel > 0) && (maLine.getLength() > 0) )
1861 tab();
1862 if( rItemName.has() )
1864 writeItemName( rItemName );
1865 writeChar( OOX_DUMP_ITEMSEP );
1868 ++mnItemLevel;
1869 mnLastItem = maLine.getLength();
1872 void Output::contItem()
1874 if( mnItemLevel > 0 )
1876 if( (maLine.getLength() == 0) || (maLine[ maLine.getLength() - 1 ] != OOX_DUMP_ITEMSEP) )
1877 writeChar( OOX_DUMP_ITEMSEP );
1878 mnLastItem = maLine.getLength();
1882 void Output::endItem()
1884 if( mnItemLevel > 0 )
1886 maLastItem = OUString( maLine.getStr() + mnLastItem );
1887 if( (maLastItem.getLength() == 0) && (mnLastItem > 0) && (maLine[ mnLastItem - 1 ] == OOX_DUMP_ITEMSEP) )
1888 maLine.setLength( mnLastItem - 1 );
1889 --mnItemLevel;
1891 if( mnItemLevel == 0 )
1893 if( mnMultiLevel == 0 )
1894 newLine();
1896 else
1897 contItem();
1900 void Output::startMultiItems()
1902 ++mnMultiLevel;
1905 void Output::endMultiItems()
1907 if( mnMultiLevel > 0 )
1908 --mnMultiLevel;
1909 if( mnMultiLevel == 0 )
1910 newLine();
1913 // ----------------------------------------------------------------------------
1915 void Output::writeChar( sal_Unicode cChar, sal_Int32 nCount )
1917 StringHelper::appendEncChar( maLine, cChar, nCount );
1920 void Output::writeAscii( const sal_Char* pcStr )
1922 if( pcStr )
1923 maLine.appendAscii( pcStr );
1926 void Output::writeString( const OUString& rStr )
1928 StringHelper::appendEncString( maLine, rStr );
1931 void Output::writeArray( const sal_uInt8* pnData, sal_Size nSize, sal_Unicode cSep )
1933 const sal_uInt8* pnEnd = pnData ? (pnData + nSize) : 0;
1934 for( const sal_uInt8* pnByte = pnData; pnByte < pnEnd; ++pnByte )
1936 if( pnByte > pnData )
1937 writeChar( cSep );
1938 writeHex( *pnByte, false );
1942 void Output::writeBool( bool bData )
1944 StringHelper::appendBool( maLine, bData );
1947 void Output::writeColorABGR( sal_Int32 nColor )
1949 writeChar( 'a' );
1950 writeDec( static_cast< sal_uInt8 >( nColor >> 24 ) );
1951 writeAscii( ",r" );
1952 writeDec( static_cast< sal_uInt8 >( nColor ) );
1953 writeAscii( ",g" );
1954 writeDec( static_cast< sal_uInt8 >( nColor >> 8 ) );
1955 writeAscii( ",b" );
1956 writeDec( static_cast< sal_uInt8 >( nColor >> 16 ) );
1959 void Output::writeDateTime( const DateTime& rDateTime )
1961 writeDec( rDateTime.Year, 4, '0' );
1962 writeChar( '-' );
1963 writeDec( rDateTime.Month, 2, '0' );
1964 writeChar( '-' );
1965 writeDec( rDateTime.Day, 2, '0' );
1966 writeChar( 'T' );
1967 writeDec( rDateTime.Hours, 2, '0' );
1968 writeChar( ':' );
1969 writeDec( rDateTime.Minutes, 2, '0' );
1970 writeChar( ':' );
1971 writeDec( rDateTime.Seconds, 2, '0' );
1974 void Output::writeColIndex( sal_Int32 nCol )
1976 StringHelper::appendAddrCol( maLine, nCol, true );
1979 void Output::writeRowIndex( sal_Int32 nRow )
1981 StringHelper::appendAddrRow( maLine, nRow, true );
1984 void Output::writeColRowRange( sal_Int32 nColRow1, sal_Int32 nColRow2 )
1986 writeDec( nColRow1 );
1987 writeChar( OOX_DUMP_RANGESEP );
1988 writeDec( nColRow2 );
1991 void Output::writeColRange( sal_Int32 nCol1, sal_Int32 nCol2 )
1993 writeColIndex( nCol1 );
1994 writeChar( OOX_DUMP_RANGESEP );
1995 writeColIndex( nCol2 );
1998 void Output::writeRowRange( sal_Int32 nRow1, sal_Int32 nRow2 )
2000 writeRowIndex( nRow1 );
2001 writeChar( OOX_DUMP_RANGESEP );
2002 writeRowIndex( nRow2 );
2005 void Output::writeAddress( const Address& rPos )
2007 StringHelper::appendAddress( maLine, rPos );
2010 void Output::writeRange( const Range& rRange )
2012 StringHelper::appendRange( maLine, rRange );
2015 void Output::writeRangeList( const RangeList& rRanges )
2017 StringHelper::appendRangeList( maLine, rRanges );
2020 // ----------------------------------------------------------------------------
2022 void Output::construct( const Reference< XTextOutputStream >& rxStrm )
2024 mxStrm = rxStrm;
2025 mnCol = mnItemLevel = mnMultiLevel = 0;
2026 mnItemIdx = 0;
2027 mnLastItem = 0;
2028 if( mxStrm.is() )
2030 writeChar( OOX_DUMP_BOM );
2031 newLine();
2035 bool Output::implIsValid() const
2037 return mxStrm.is();
2040 void Output::writeItemName( const String& rItemName )
2042 if( rItemName.has() && (rItemName[ 0 ] == '#') )
2044 writeString( rItemName.copy( 1 ) );
2045 StringHelper::appendIndex( maLine, mnItemIdx++ );
2047 else
2048 writeString( rItemName );
2051 // ============================================================================
2053 StorageIterator::StorageIterator( const StorageRef& rxStrg ) :
2054 mxStrg( rxStrg )
2056 if( mxStrg.get() )
2057 mxStrg->getElementNames( maNames );
2058 maIt = maNames.begin();
2061 StorageIterator::~StorageIterator()
2065 size_t StorageIterator::getElementCount() const
2067 return maNames.size();
2070 StorageIterator& StorageIterator::operator++()
2072 if( maIt != maNames.end() )
2073 ++maIt;
2074 return *this;
2077 OUString StorageIterator::getName() const
2079 OUString aName;
2080 if( maIt != maNames.end() )
2081 aName = *maIt;
2082 return aName;
2085 bool StorageIterator::isStream() const
2087 return isValid() && mxStrg->openInputStream( *maIt ).is();
2090 bool StorageIterator::isStorage() const
2092 if( !isValid() )
2093 return false;
2094 StorageRef xStrg = mxStrg->openSubStorage( *maIt, false );
2095 return xStrg.get() && xStrg->isStorage();
2098 bool StorageIterator::implIsValid() const
2100 return mxStrg.get() && mxStrg->isStorage() && (maIt != maNames.end());
2103 // ============================================================================
2104 // ============================================================================
2106 ObjectBase::~ObjectBase()
2110 void ObjectBase::construct( const ConfigRef& rxConfig )
2112 mxConfig = rxConfig;
2115 void ObjectBase::construct( const ObjectBase& rParent )
2117 *this = rParent;
2120 void ObjectBase::dump()
2122 if( isValid() )
2123 implDump();
2126 bool ObjectBase::implIsValid() const
2128 return isValid( mxConfig );
2131 void ObjectBase::implDump()
2135 void ObjectBase::reconstructConfig( const ConfigRef& rxConfig )
2137 if( isValid( rxConfig ) )
2138 mxConfig = rxConfig;
2141 // ============================================================================
2142 // ============================================================================
2144 void StorageObjectBase::construct( const ObjectBase& rParent, const StorageRef& rxStrg, const OUString& rSysPath )
2146 ObjectBase::construct( rParent );
2147 mxStrg = rxStrg;
2148 maSysPath = rSysPath;
2151 void StorageObjectBase::construct( const ObjectBase& rParent )
2153 ObjectBase::construct( rParent );
2154 if( ObjectBase::implIsValid() )
2156 mxStrg = cfg().getRootStorage();
2157 maSysPath = cfg().getSysFileName();
2161 bool StorageObjectBase::implIsValid() const
2163 return mxStrg.get() && mxStrg->isStorage() && (maSysPath.getLength() > 0) && ObjectBase::implIsValid();
2166 void StorageObjectBase::implDump()
2170 Reference< XSimpleFileAccess > xFileAccess( getFactory()->createInstance( CREATE_OUSTRING( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY_THROW );
2171 xFileAccess->kill( maSysPath + OOX_DUMP_DUMPEXT );
2173 catch( Exception& )
2176 extractStorage( mxStrg, OUString(), maSysPath );
2179 void StorageObjectBase::implDumpStream( const BinaryInputStreamRef&, const OUString&, const OUString&, const OUString& )
2183 void StorageObjectBase::implDumpStorage( const StorageRef& rxStrg, const OUString& rStrgPath, const OUString& rSysPath )
2185 extractStorage( rxStrg, rStrgPath, rSysPath );
2188 void StorageObjectBase::addPreferredStream( const String& rStrmName )
2190 if( rStrmName.has() )
2191 maPreferred.push_back( PreferredItem( rStrmName, false ) );
2194 void StorageObjectBase::addPreferredStorage( const String& rStrgPath )
2196 if( rStrgPath.has() )
2197 maPreferred.push_back( PreferredItem( rStrgPath, true ) );
2200 OUString StorageObjectBase::getSysFileName( const OUString& rStrmName, const OUString& rSysOutPath )
2202 // encode all characters < 0x20
2203 OUStringBuffer aBuffer;
2204 StringHelper::appendEncString( aBuffer, rStrmName, false );
2206 // replace all characters reserved in file system
2207 OUString aFileName = aBuffer.makeStringAndClear();
2208 static const sal_Unicode spcReserved[] = { '/', '\\', ':', '*', '?', '<', '>', '|' };
2209 for( const sal_Unicode* pcChar = spcReserved; pcChar < STATIC_ARRAY_END( spcReserved ); ++pcChar )
2210 aFileName = aFileName.replace( *pcChar, '_' );
2212 // build full path
2213 return rSysOutPath + OUString( sal_Unicode( '/' ) ) + aFileName;
2216 void StorageObjectBase::extractStream( StorageBase& rStrg, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName )
2218 BinaryXInputStream aInStrm( rStrg.openInputStream( rStrmName ), true );
2219 if( !aInStrm.isEof() )
2221 BinaryXOutputStream aOutStrm( InputOutputHelper::openOutputStream( getFactory(), rSysFileName ), true );
2222 if( !aOutStrm.isEof() )
2223 aOutStrm.copyStream( aInStrm );
2225 BinaryXInputStreamRef xDumpStrm( new BinaryXInputStream( InputOutputHelper::openInputStream( getFactory(), rSysFileName ), true ) );
2226 if( !xDumpStrm->isEof() )
2227 implDumpStream( xDumpStrm, rStrgPath, rStrmName, rSysFileName );
2230 void StorageObjectBase::extractStorage( const StorageRef& rxStrg, const OUString& rStrgPath, const OUString& rSysPath )
2232 OUString aSysOutPath = rSysPath + OOX_DUMP_DUMPEXT;
2234 // create directory in file system
2235 ::osl::FileBase::RC eRes = ::osl::Directory::create( aSysOutPath );
2236 if( (eRes != ::osl::FileBase::E_None) && (eRes != ::osl::FileBase::E_EXIST) )
2237 return;
2239 // process preferred storages and streams in root storage first
2240 if( rStrgPath.getLength() == 0 )
2241 for( PreferredItemVector::iterator aIt = maPreferred.begin(), aEnd = maPreferred.end(); aIt != aEnd; ++aIt )
2242 extractItem( rxStrg, rStrgPath, aIt->maName, aSysOutPath, aIt->mbStorage, !aIt->mbStorage );
2244 // process children of the storage
2245 for( StorageIterator aIt( rxStrg ); aIt.isValid(); ++aIt )
2247 // skip processed preferred items
2248 OUString aItemName = aIt.getName();
2249 bool bFound = false;
2250 if( rStrgPath.getLength() == 0 )
2251 for( PreferredItemVector::iterator aIIt = maPreferred.begin(), aIEnd = maPreferred.end(); !bFound && (aIIt != aIEnd); ++aIIt )
2252 bFound = aIIt->maName == aItemName;
2253 if( !bFound )
2254 extractItem( rxStrg, rStrgPath, aItemName, aSysOutPath, aIt.isStorage(), aIt.isStream() );
2258 void StorageObjectBase::extractItem( const StorageRef& rxStrg, const OUString& rStrgPath, const OUString& rItemName, const OUString& rSysOutPath, bool bIsStrg, bool bIsStrm )
2260 OUString aSysFileName = getSysFileName( rItemName, rSysOutPath );
2261 if( bIsStrg )
2263 OUStringBuffer aStrgPath( rStrgPath );
2264 StringHelper::appendToken( aStrgPath, rItemName, '/' );
2265 implDumpStorage( rxStrg->openSubStorage( rItemName, false ), aStrgPath.makeStringAndClear(), aSysFileName );
2267 else if( bIsStrm )
2269 extractStream( *rxStrg, rStrgPath, rItemName, aSysFileName );
2273 // ============================================================================
2274 // ============================================================================
2276 OutputObjectBase::~OutputObjectBase()
2280 void OutputObjectBase::construct( const ObjectBase& rParent, const OUString& rSysFileName )
2282 ObjectBase::construct( rParent );
2283 if( ObjectBase::implIsValid() )
2284 mxOut.reset( new Output( getFactory(), rSysFileName + OOX_DUMP_DUMPEXT ) );
2287 void OutputObjectBase::construct( const ObjectBase& rParent, const OutputRef& rxOut )
2289 ObjectBase::construct( rParent );
2290 mxOut = rxOut;
2293 void OutputObjectBase::construct( const OutputObjectBase& rParent )
2295 *this = rParent;
2298 bool OutputObjectBase::implIsValid() const
2300 return isValid( mxOut ) && ObjectBase::implIsValid();
2303 void OutputObjectBase::writeEmptyItem( const String& rName )
2305 ItemGuard aItem( *mxOut, rName );
2308 void OutputObjectBase::writeInfoItem( const String& rName, const String& rData )
2310 ItemGuard aItem( *mxOut, rName );
2311 mxOut->writeString( rData );
2314 void OutputObjectBase::writeCharItem( const String& rName, sal_Unicode cData )
2316 ItemGuard aItem( *mxOut, rName );
2317 mxOut->writeChar( OOX_DUMP_STRQUOTE );
2318 mxOut->writeChar( cData );
2319 mxOut->writeChar( OOX_DUMP_STRQUOTE );
2322 void OutputObjectBase::writeStringItem( const String& rName, const OUString& rData )
2324 ItemGuard aItem( *mxOut, rName );
2325 mxOut->writeAscii( "(len=" );
2326 mxOut->writeDec( rData.getLength() );
2327 mxOut->writeAscii( ")," );
2328 OUStringBuffer aValue( rData.copy( 0, ::std::min( rData.getLength(), OOX_DUMP_MAXSTRLEN ) ) );
2329 StringHelper::enclose( aValue, OOX_DUMP_STRQUOTE );
2330 mxOut->writeString( aValue.makeStringAndClear() );
2331 if( rData.getLength() > OOX_DUMP_MAXSTRLEN )
2332 mxOut->writeAscii( ",cut" );
2335 void OutputObjectBase::writeArrayItem( const String& rName, const sal_uInt8* pnData, sal_Size nSize, sal_Unicode cSep )
2337 ItemGuard aItem( *mxOut, rName );
2338 mxOut->writeArray( pnData, nSize, cSep );
2341 void OutputObjectBase::writeBoolItem( const String& rName, bool bData )
2343 ItemGuard aItem( *mxOut, rName );
2344 mxOut->writeBool( bData );
2347 double OutputObjectBase::writeRkItem( const String& rName, sal_Int32 nRk )
2349 MultiItemsGuard aMultiGuard( out() );
2350 writeHexItem( rName, static_cast< sal_uInt32 >( nRk ), "RK-FLAGS" );
2351 double fValue = ::oox::xls::BiffHelper::calcDoubleFromRk( nRk );
2352 writeDecItem( "decoded", fValue );
2353 return fValue;
2356 void OutputObjectBase::writeColorABGRItem( const String& rName, sal_Int32 nColor )
2358 ItemGuard aItem( *mxOut, rName );
2359 writeHexItem( rName, nColor );
2360 mxOut->writeColorABGR( nColor );
2363 void OutputObjectBase::writeDateTimeItem( const String& rName, const DateTime& rDateTime )
2365 ItemGuard aItem( *mxOut, rName );
2366 mxOut->writeDateTime( rDateTime );
2369 void OutputObjectBase::writeGuidItem( const String& rName, const OUString& rGuid )
2371 ItemGuard aItem( *mxOut, rName );
2372 mxOut->writeString( rGuid );
2373 aItem.cont();
2374 mxOut->writeString( cfg().getStringOption( rGuid, OUString() ) );
2377 void OutputObjectBase::writeColIndexItem( const String& rName, sal_Int32 nCol )
2379 Output& rOut = out();
2380 ItemGuard aItem( rOut, rName );
2381 rOut.writeDec( nCol );
2382 aItem.cont();
2383 rOut.writeColIndex( nCol );
2386 void OutputObjectBase::writeRowIndexItem( const String& rName, sal_Int32 nRow )
2388 Output& rOut = out();
2389 ItemGuard aItem( rOut, rName );
2390 rOut.writeDec( nRow );
2391 aItem.cont();
2392 rOut.writeRowIndex( nRow );
2395 void OutputObjectBase::writeColRangeItem( const String& rName, sal_Int32 nCol1, sal_Int32 nCol2 )
2397 Output& rOut = out();
2398 ItemGuard aItem( rOut, rName );
2399 rOut.writeColRowRange( nCol1, nCol2 );
2400 aItem.cont();
2401 rOut.writeColRange( nCol1, nCol2 );
2404 void OutputObjectBase::writeRowRangeItem( const String& rName, sal_Int32 nRow1, sal_Int32 nRow2 )
2406 Output& rOut = out();
2407 ItemGuard aItem( rOut, rName );
2408 rOut.writeColRowRange( nRow1, nRow2 );
2409 aItem.cont();
2410 rOut.writeRowRange( nRow1, nRow2 );
2413 void OutputObjectBase::writeAddressItem( const String& rName, const Address& rPos )
2415 ItemGuard aItem( out(), rName );
2416 StringHelper::appendAddress( out().getLine(), rPos );
2419 void OutputObjectBase::writeRangeItem( const String& rName, const Range& rRange )
2421 ItemGuard aItem( out(), rName );
2422 StringHelper::appendRange( out().getLine(), rRange );
2425 void OutputObjectBase::writeRangeListItem( const String& rName, const RangeList& rRanges )
2427 MultiItemsGuard aMultiGuard( out() );
2428 writeEmptyItem( rName );
2429 writeDecItem( "count", static_cast< sal_uInt16 >( rRanges.size() ) );
2430 ItemGuard aItem( out(), "ranges" );
2431 StringHelper::appendRangeList( out().getLine(), rRanges );
2434 void OutputObjectBase::writeTokenAddressItem( const String& rName, const TokenAddress& rPos, bool bNameMode )
2436 ItemGuard aItem( out(), rName );
2437 StringHelper::appendAddress( out().getLine(), rPos, bNameMode );
2440 void OutputObjectBase::writeTokenAddress3dItem( const String& rName, const OUString& rRef, const TokenAddress& rPos, bool bNameMode )
2442 ItemGuard aItem( out(), rName );
2443 out().writeString( rRef );
2444 StringHelper::appendAddress( out().getLine(), rPos, bNameMode );
2447 void OutputObjectBase::writeTokenRangeItem( const String& rName, const TokenRange& rRange, bool bNameMode )
2449 ItemGuard aItem( out(), rName );
2450 StringHelper::appendRange( out().getLine(), rRange, bNameMode );
2453 void OutputObjectBase::writeTokenRange3dItem( const String& rName, const OUString& rRef, const TokenRange& rRange, bool bNameMode )
2455 ItemGuard aItem( out(), rName );
2456 out().writeString( rRef );
2457 StringHelper::appendRange( out().getLine(), rRange, bNameMode );
2460 // ============================================================================
2461 // ============================================================================
2463 InputObjectBase::~InputObjectBase()
2467 void InputObjectBase::construct( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName )
2469 OutputObjectBase::construct( rParent, rSysFileName );
2470 mxStrm = rxStrm;
2473 void InputObjectBase::construct( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, const OutputRef& rxOut )
2475 OutputObjectBase::construct( rParent, rxOut );
2476 mxStrm = rxStrm;
2479 void InputObjectBase::construct( const OutputObjectBase& rParent, const BinaryInputStreamRef& rxStrm )
2481 OutputObjectBase::construct( rParent );
2482 mxStrm = rxStrm;
2485 void InputObjectBase::construct( const InputObjectBase& rParent )
2487 *this = rParent;
2490 bool InputObjectBase::implIsValid() const
2492 return mxStrm.get() && OutputObjectBase::implIsValid();
2495 void InputObjectBase::skipBlock( sal_Int64 nBytes, bool bShowSize )
2497 sal_Int64 nEndPos = ::std::min< sal_Int64 >( mxStrm->tell() + nBytes, mxStrm->getLength() );
2498 if( mxStrm->tell() < nEndPos )
2500 if( bShowSize )
2501 writeDecItem( "skipped-data-size", static_cast< sal_uInt64 >( nEndPos - mxStrm->tell() ) );
2502 mxStrm->seek( nEndPos );
2506 void InputObjectBase::dumpRawBinary( sal_Int64 nBytes, bool bShowOffset, bool bStream )
2508 Output& rOut = out();
2509 TableGuard aTabGuard( rOut,
2510 bShowOffset ? 12 : 0,
2511 3 * OOX_DUMP_BYTESPERLINE / 2 + 1,
2512 3 * OOX_DUMP_BYTESPERLINE / 2 + 1,
2513 OOX_DUMP_BYTESPERLINE / 2 + 1 );
2515 sal_Int64 nMaxShowSize = cfg().getIntOption< sal_Int64 >(
2516 bStream ? "max-binary-stream-size" : "max-binary-data-size", SAL_MAX_INT64 );
2518 bool bSeekable = mxStrm->getLength() >= 0;
2519 sal_Int64 nEndPos = bSeekable ? ::std::min< sal_Int64 >( mxStrm->tell() + nBytes, mxStrm->getLength() ) : 0;
2520 sal_Int64 nDumpEnd = bSeekable ? ::std::min< sal_Int64 >( mxStrm->tell() + nMaxShowSize, nEndPos ) : nMaxShowSize;
2521 sal_Int64 nPos = bSeekable ? mxStrm->tell() : 0;
2522 bool bLoop = true;
2524 while( bLoop && (nPos < nDumpEnd) )
2526 rOut.writeHex( static_cast< sal_uInt32 >( nPos ) );
2527 rOut.tab();
2529 sal_uInt8 pnLineData[ OOX_DUMP_BYTESPERLINE ];
2530 sal_Int32 nLineSize = bSeekable ? ::std::min( static_cast< sal_Int32 >( nDumpEnd - mxStrm->tell() ), OOX_DUMP_BYTESPERLINE ) : OOX_DUMP_BYTESPERLINE;
2531 sal_Int32 nReadSize = mxStrm->readMemory( pnLineData, nLineSize );
2532 bLoop = nReadSize == nLineSize;
2533 nPos += nReadSize;
2535 if( nReadSize > 0 )
2537 const sal_uInt8* pnByte = 0;
2538 const sal_uInt8* pnEnd = 0;
2539 for( pnByte = pnLineData, pnEnd = pnLineData + nReadSize; pnByte != pnEnd; ++pnByte )
2541 if( (pnByte - pnLineData) == (OOX_DUMP_BYTESPERLINE / 2) ) rOut.tab();
2542 rOut.writeHex( *pnByte, false );
2543 rOut.writeChar( ' ' );
2546 aTabGuard.tab( 3 );
2547 for( pnByte = pnLineData, pnEnd = pnLineData + nReadSize; pnByte != pnEnd; ++pnByte )
2549 if( (pnByte - pnLineData) == (OOX_DUMP_BYTESPERLINE / 2) ) rOut.tab();
2550 rOut.writeChar( static_cast< sal_Unicode >( (*pnByte < 0x20) ? '.' : *pnByte ) );
2552 rOut.newLine();
2556 // skip undumped data
2557 if( bSeekable )
2558 skipBlock( nEndPos - mxStrm->tell() );
2561 void InputObjectBase::dumpBinary( const String& rName, sal_Int64 nBytes, bool bShowOffset )
2564 MultiItemsGuard aMultiGuard( out() );
2565 writeEmptyItem( rName );
2566 writeDecItem( "size", nBytes );
2568 IndentGuard aIndGuard( out() );
2569 dumpRawBinary( nBytes, bShowOffset );
2572 void InputObjectBase::dumpRemaining( sal_Int64 nBytes )
2574 if( nBytes > 0 )
2576 if( cfg().getBoolOption( "show-trailing-unknown", true ) )
2577 dumpBinary( "remaining-data", nBytes, false );
2578 else
2579 skipBlock( nBytes );
2583 void InputObjectBase::dumpRemainingTo( sal_Int64 nPos )
2585 if( mxStrm->isEof() )
2586 writeInfoItem( "stream-state", OOX_DUMP_ERR_STREAM );
2587 else
2588 dumpRemaining( nPos - mxStrm->tell() );
2589 mxStrm->seek( nPos );
2592 void InputObjectBase::dumpRemainingStream()
2594 dumpRemainingTo( mxStrm->getLength() );
2597 void InputObjectBase::dumpArray( const String& rName, sal_Int32 nBytes, sal_Unicode cSep )
2599 sal_Int32 nDumpSize = getLimitedValue< sal_Int32, sal_Int64 >( mxStrm->getLength() - mxStrm->tell(), 0, nBytes );
2600 if( nDumpSize > OOX_DUMP_MAXARRAY )
2602 dumpBinary( rName, nBytes, false );
2604 else if( nDumpSize > 1 )
2606 sal_uInt8 pnData[ OOX_DUMP_MAXARRAY ];
2607 mxStrm->readMemory( pnData, nDumpSize );
2608 writeArrayItem( rName, pnData, nDumpSize, cSep );
2610 else if( nDumpSize == 1 )
2611 dumpHex< sal_uInt8 >( rName );
2614 sal_Unicode InputObjectBase::dumpChar( const String& rName, rtl_TextEncoding eTextEnc )
2616 sal_uInt8 nChar;
2617 *mxStrm >> nChar;
2618 OUString aChar = OStringToOUString( OString( static_cast< sal_Char >( nChar ) ), eTextEnc );
2619 sal_Unicode cChar = (aChar.getLength() > 0) ? aChar[ 0 ] : 0;
2620 writeCharItem( rName( "char" ), cChar );
2621 return cChar;
2624 sal_Unicode InputObjectBase::dumpUnicode( const String& rName )
2626 sal_uInt16 nChar;
2627 *mxStrm >> nChar;
2628 sal_Unicode cChar = static_cast< sal_Unicode >( nChar );
2629 writeCharItem( rName( "char" ), cChar );
2630 return cChar;
2633 OUString InputObjectBase::dumpCharArray( const String& rName, sal_Int32 nLen, rtl_TextEncoding eTextEnc )
2635 sal_Int32 nDumpSize = getLimitedValue< sal_Int32, sal_Int64 >( mxStrm->getLength() - mxStrm->tell(), 0, nLen );
2636 OUString aString;
2637 if( nDumpSize > 0 )
2639 ::std::vector< sal_Char > aBuffer( static_cast< sal_Size >( nLen ) + 1 );
2640 sal_Int32 nCharsRead = mxStrm->readMemory( &aBuffer.front(), nLen );
2641 aBuffer[ nCharsRead ] = 0;
2642 aString = OStringToOUString( OString( &aBuffer.front() ), eTextEnc );
2644 writeStringItem( rName( "text" ), aString );
2645 return aString;
2648 OUString InputObjectBase::dumpUnicodeArray( const String& rName, sal_Int32 nLen )
2650 OUStringBuffer aBuffer;
2651 for( sal_Int32 nIndex = 0; !mxStrm->isEof() && (nIndex < nLen); ++nIndex )
2652 aBuffer.append( static_cast< sal_Unicode >( mxStrm->readuInt16() ) );
2653 OUString aString = aBuffer.makeStringAndClear();
2654 writeStringItem( rName( "text" ), aString );
2655 return aString;
2658 OUString InputObjectBase::dumpNullCharArray( const String& rName, rtl_TextEncoding eTextEnc )
2660 OStringBuffer aBuffer;
2661 sal_uInt8 nChar;
2662 for( *mxStrm >> nChar; !mxStrm->isEof() && (nChar > 0); *mxStrm >> nChar )
2663 aBuffer.append( static_cast< sal_Char >( nChar ) );
2664 OUString aString = OStringToOUString( aBuffer.makeStringAndClear(), eTextEnc );
2665 writeStringItem( rName( "text" ), aString );
2666 return aString;
2669 OUString InputObjectBase::dumpNullUnicodeArray( const String& rName )
2671 OUStringBuffer aBuffer;
2672 sal_uInt16 nChar;
2673 for( *mxStrm >> nChar; !mxStrm->isEof() && (nChar > 0); *mxStrm >> nChar )
2674 aBuffer.append( static_cast< sal_Unicode >( nChar ) );
2675 OUString aString = aBuffer.makeStringAndClear();
2676 writeStringItem( rName( "text" ), aString );
2677 return aString;
2680 double InputObjectBase::dumpRk( const String& rName )
2682 sal_Int32 nRk;
2683 *mxStrm >> nRk;
2684 return writeRkItem( rName( "rk-value" ), nRk );
2687 sal_Int32 InputObjectBase::dumpColorABGR( const String& rName )
2689 sal_Int32 nColor;
2690 *mxStrm >> nColor;
2691 writeColorABGRItem( rName( "color" ), nColor );
2692 return nColor;
2695 DateTime InputObjectBase::dumpFileTime( const String& rName )
2697 DateTime aDateTime;
2699 ItemGuard aItem( out(), rName( "file-time" ) );
2700 sal_Int64 nFileTime = dumpDec< sal_Int64 >( EMPTY_STRING );
2701 // file time is in 10^-7 seconds (100 nanoseconds), convert to 1/100 seconds
2702 nFileTime /= 100000;
2703 // entire days
2704 sal_Int64 nDays = nFileTime / sal_Int64( 360000 * 24 );
2705 // number of entire years
2706 sal_Int64 nYears = (nDays - (nDays / (4 * 365)) + (nDays / (100 * 365)) - (nDays / (400 * 365))) / 365;
2707 // remaining days in the year
2708 sal_Int64 nDaysInYear = nDays - (nYears * 365 + nYears / 4 - nYears / 100 + nYears / 400);
2709 // the year (file dates start from 1601-01-01)
2710 aDateTime.Year = static_cast< sal_uInt16 >( 1601 + nYears );
2711 // leap year?
2712 bool bLeap = ((aDateTime.Year % 4 == 0) && (aDateTime.Year % 100 != 0)) || (aDateTime.Year % 400 == 0);
2713 // static arrays with number of days in month
2714 static const sal_Int64 spnDaysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
2715 static const sal_Int64 spnDaysInMonthL[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
2716 const sal_Int64* pnDaysInMonth = bLeap ? spnDaysInMonthL : spnDaysInMonth;
2717 // the month
2718 aDateTime.Month = 1;
2719 while( nDaysInYear >= *pnDaysInMonth )
2721 nDaysInYear -= *pnDaysInMonth++;
2722 ++aDateTime.Month;
2724 // the day
2725 aDateTime.Day = static_cast< sal_uInt16 >( nDaysInYear + 1 );
2726 // number of 1/100 seconds in the day
2727 sal_Int64 nTimeInDay = nFileTime % sal_Int64( 360000 * 24 );
2728 // 1/100 seconds
2729 aDateTime.HundredthSeconds = static_cast< sal_uInt16 >( nTimeInDay % 100 );
2730 nTimeInDay /= 100;
2731 // seconds
2732 aDateTime.Seconds = static_cast< sal_uInt16 >( nTimeInDay % 60 );
2733 nTimeInDay /= 60;
2734 // minutes
2735 aDateTime.Minutes = static_cast< sal_uInt16 >( nTimeInDay % 60 );
2736 nTimeInDay /= 60;
2737 // hours
2738 aDateTime.Hours = static_cast< sal_uInt16 >( nTimeInDay );
2740 writeDateTimeItem( EMPTY_STRING, aDateTime );
2741 return aDateTime;
2744 OUString InputObjectBase::dumpGuid( const String& rName )
2746 OUStringBuffer aBuffer;
2747 sal_uInt32 nData32;
2748 sal_uInt16 nData16;
2749 sal_uInt8 nData8;
2751 *mxStrm >> nData32;
2752 StringHelper::appendHex( aBuffer, nData32, false );
2753 aBuffer.append( sal_Unicode( '-' ) );
2754 *mxStrm >> nData16;
2755 StringHelper::appendHex( aBuffer, nData16, false );
2756 aBuffer.append( sal_Unicode( '-' ) );
2757 *mxStrm >> nData16;
2758 StringHelper::appendHex( aBuffer, nData16, false );
2759 aBuffer.append( sal_Unicode( '-' ) );
2760 *mxStrm >> nData8;
2761 StringHelper::appendHex( aBuffer, nData8, false );
2762 *mxStrm >> nData8;
2763 StringHelper::appendHex( aBuffer, nData8, false );
2764 aBuffer.append( sal_Unicode( '-' ) );
2765 for( int nIndex = 0; nIndex < 6; ++nIndex )
2767 *mxStrm >> nData8;
2768 StringHelper::appendHex( aBuffer, nData8, false );
2770 StringHelper::enclose( aBuffer, '{', '}' );
2771 OUString aGuid = aBuffer.makeStringAndClear();
2772 writeGuidItem( rName( "guid" ), aGuid );
2773 return aGuid;
2776 void InputObjectBase::dumpItem( const ItemFormat& rItemFmt )
2778 switch( rItemFmt.meDataType )
2780 case DATATYPE_VOID: break;
2781 case DATATYPE_INT8: dumpValue< sal_Int8 >( rItemFmt ); break;
2782 case DATATYPE_UINT8: dumpValue< sal_uInt8 >( rItemFmt ); break;
2783 case DATATYPE_INT16: dumpValue< sal_Int16 >( rItemFmt ); break;
2784 case DATATYPE_UINT16: dumpValue< sal_uInt16 >( rItemFmt ); break;
2785 case DATATYPE_INT32: dumpValue< sal_Int32 >( rItemFmt ); break;
2786 case DATATYPE_UINT32: dumpValue< sal_uInt32 >( rItemFmt ); break;
2787 case DATATYPE_INT64: dumpValue< sal_Int64 >( rItemFmt ); break;
2788 case DATATYPE_UINT64: dumpValue< sal_uInt64 >( rItemFmt ); break;
2789 case DATATYPE_FLOAT: dumpValue< float >( rItemFmt ); break;
2790 case DATATYPE_DOUBLE: dumpValue< double >( rItemFmt ); break;
2791 default:;
2795 // ============================================================================
2796 // ============================================================================
2798 BinaryStreamObject::BinaryStreamObject( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName )
2800 InputObjectBase::construct( rParent, rxStrm, rSysFileName );
2803 BinaryStreamObject::BinaryStreamObject( const OutputObjectBase& rParent, const BinaryInputStreamRef& rxStrm )
2805 InputObjectBase::construct( rParent, rxStrm );
2808 void BinaryStreamObject::dumpBinaryStream( bool bShowOffset )
2810 in().seek( 0 );
2811 dumpRawBinary( in().getLength(), bShowOffset, true );
2812 out().emptyLine();
2815 void BinaryStreamObject::implDump()
2817 dumpBinaryStream();
2820 // ============================================================================
2822 namespace {
2824 bool lclIsEof( BinaryInputStream& rStrm )
2826 return rStrm.isEof() || (rStrm.isSeekable() && (rStrm.tell() >= rStrm.getLength()));
2829 template< typename BufferType, typename CharType >
2830 CharType lclAppendChar( BufferType& orBuffer, CharType cChar )
2832 if( (cChar == 0x0A) || (cChar == 0x0D) )
2833 return cChar;
2834 orBuffer.append( cChar );
2835 return 0;
2838 template< typename BufferType, typename CharType, typename StreamDataType >
2839 bool lclReadLine( BufferType& orBuffer, sal_Unicode& orcNextLineChar, BinaryInputStream& rStrm )
2841 CharType cLineEndChar = (orcNextLineChar == 0) ? 0 : lclAppendChar( orBuffer, static_cast< CharType >( orcNextLineChar ) );
2842 orcNextLineChar = 0;
2844 // read chars until EOF or line end character (LF or CR)
2845 bool bIsEof = lclIsEof( rStrm );
2846 while( !bIsEof && (cLineEndChar == 0) )
2848 CharType cChar = static_cast< CharType >( rStrm.readValue< StreamDataType >() );
2849 bIsEof = rStrm.isEof();
2850 cLineEndChar = bIsEof ? 0 : lclAppendChar( orBuffer, cChar );
2853 // try to skip LF following CR, or CR following LF
2854 if( !lclIsEof( rStrm ) && (cLineEndChar != 0) )
2856 CharType cChar = static_cast< CharType >( rStrm.readValue< StreamDataType >() );
2857 bool bLineEnd = ((cChar == 0x0A) || (cChar == 0x0D)) && (cChar != cLineEndChar);
2858 if( !rStrm.isEof() && !bLineEnd )
2859 orcNextLineChar = static_cast< sal_Unicode >( cChar );
2862 return (cLineEndChar != 0) || (orBuffer.getLength() > 0);
2865 } // namespace
2867 // ----------------------------------------------------------------------------
2869 TextStreamObject::TextStreamObject( const ObjectBase& rParent,
2870 const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc, const OUString& rSysFileName ) :
2871 meTextEnc( eTextEnc )
2873 InputObjectBase::construct( rParent, rxStrm, rSysFileName );
2876 TextStreamObject::TextStreamObject( const OutputObjectBase& rParent,
2877 const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc ) :
2878 meTextEnc( eTextEnc )
2880 InputObjectBase::construct( rParent, rxStrm );
2883 void TextStreamObject::implDump()
2885 OUString aLine;
2886 sal_Unicode cNextLineChar = 0;
2887 sal_uInt32 nLine = 0;
2888 while( readLine( aLine, cNextLineChar ) )
2889 implDumpLine( aLine, ++nLine );
2890 out().emptyLine();
2893 void TextStreamObject::implDumpLine( const OUString& rLine, sal_uInt32 nLine )
2895 Output& rOut = out();
2896 TableGuard aTabGuard( rOut, 8 );
2897 rOut.writeDec( nLine, 6 );
2898 rOut.tab();
2899 rOut.writeString( rLine );
2900 rOut.newLine();
2903 bool TextStreamObject::readCharLine( OUString& orLine, sal_Unicode& orcNextLineChar )
2905 OStringBuffer aBuffer;
2906 bool bHasData = lclReadLine< OStringBuffer, sal_Char, sal_uInt8 >( aBuffer, orcNextLineChar, in() );
2907 if( bHasData )
2908 orLine = OStringToOUString( aBuffer.makeStringAndClear(), meTextEnc );
2909 return bHasData;
2912 bool TextStreamObject::readUcs2Line( OUString& orLine, sal_Unicode& orcNextLineChar )
2914 OUStringBuffer aBuffer;
2915 bool bHasData = lclReadLine< OUStringBuffer, sal_Unicode, sal_uInt16 >( aBuffer, orcNextLineChar, in() );
2916 if( bHasData )
2917 orLine = aBuffer.makeStringAndClear();
2918 return bHasData;
2921 bool TextStreamObject::readLine( OUString& orLine, sal_Unicode& orcNextLineChar )
2923 return (meTextEnc == RTL_TEXTENCODING_UCS2) ?
2924 readUcs2Line( orLine, orcNextLineChar ) :
2925 readCharLine( orLine, orcNextLineChar );
2928 // ============================================================================
2930 XmlStreamObject::XmlStreamObject( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName ) :
2931 TextStreamObject( rParent, rxStrm, RTL_TEXTENCODING_UTF8, rSysFileName )
2935 void XmlStreamObject::implDump()
2937 maIncompleteLine = OUString();
2938 TextStreamObject::implDump();
2939 if( maIncompleteLine.getLength() > 0 )
2941 out().resetIndent();
2942 out().writeString( maIncompleteLine );
2943 out().emptyLine();
2944 writeInfoItem( "stream-state", OOX_DUMP_ERR_STREAM );
2948 void XmlStreamObject::implDumpLine( const OUString& rLine, sal_uInt32 )
2950 // build input line from cached incomplete element and new text data
2951 OUStringBuffer aLine;
2952 if( maIncompleteLine.getLength() > 0 )
2953 aLine.append( maIncompleteLine ).append( sal_Unicode( ' ' ) );
2954 aLine.append( rLine );
2955 maIncompleteLine = OUString();
2957 Output& rOut = out();
2958 if( aLine.getLength() == 0 )
2960 rOut.newLine();
2961 return;
2964 const sal_Unicode* pcPos = aLine.getStr();
2965 const sal_Unicode* pcEnd = pcPos + aLine.getLength();
2966 while( pcPos < pcEnd )
2968 OUStringBuffer aOutLine;
2969 bool bIsStartElement = false;
2970 bool bIsComplElement = false;
2971 bool bIsEndElement = false;
2973 /* check for start element at beginning of the line - pcEnd and thus (pcPos+1)
2974 are dereferenceable, because OUStringBuffer::getStr is null-terminated. */
2975 if( (*pcPos == '<') && (pcPos[ 1 ] != '/') )
2977 const sal_Unicode* pcElementEnd = ::std::find( pcPos, pcEnd, '>' );
2978 if( pcElementEnd == pcEnd )
2980 // incomplete start element
2981 maIncompleteLine = OUString( pcPos, static_cast< sal_Int32 >( pcEnd - pcPos ) );
2982 pcPos = pcEnd;
2984 else
2986 bIsComplElement = (pcPos[ 1 ] == '?') || (pcPos[ 1 ] == '!') || (pcElementEnd[ -1 ] == '/');
2987 bIsStartElement = !bIsComplElement;
2988 ++pcElementEnd;
2989 aOutLine.append( pcPos, static_cast< sal_Int32 >( pcElementEnd - pcPos ) );
2990 pcPos = pcElementEnd;
2994 // check for following element text
2995 if( !bIsComplElement && (pcPos < pcEnd) )
2997 const sal_Unicode* pcElementStart = ::std::find( pcPos, pcEnd, '<' );
2998 // append text between elements
2999 if( pcPos < pcElementStart )
3001 OUString aText( pcPos, static_cast< sal_Int32 >( pcElementStart - pcPos ) );
3002 if( aText.trim().getLength() > 0 )
3003 aOutLine.append( aText );
3004 pcPos = pcElementStart;
3008 // check for stand-alone or following end element
3009 if( !bIsComplElement && (pcPos < pcEnd) && (pcPos[ 1 ] == '/') )
3011 const sal_Unicode* pcElementEnd = ::std::find( pcPos, pcEnd, '>' );
3012 if( pcElementEnd == pcEnd )
3014 // incomplete end element
3015 aOutLine.append( pcPos, static_cast< sal_Int32 >( pcEnd - pcPos ) );
3016 maIncompleteLine = aOutLine.makeStringAndClear();
3017 pcPos = pcEnd;
3019 else
3021 bIsEndElement = true;
3022 ++pcElementEnd;
3023 aOutLine.append( pcPos, static_cast< sal_Int32 >( pcElementEnd - pcPos ) );
3024 pcPos = pcElementEnd;
3028 // flush output line
3029 if( maIncompleteLine.getLength() == 0 )
3031 if( !bIsStartElement && bIsEndElement ) rOut.decIndent();
3032 rOut.writeString( aOutLine.makeStringAndClear() );
3033 rOut.newLine();
3034 if( bIsStartElement && !bIsEndElement ) rOut.incIndent();
3039 // ============================================================================
3040 // ============================================================================
3042 void RecordObjectBase::construct( const ObjectBase& rParent,
3043 const BinaryInputStreamRef& rxBaseStrm, const OUString& rSysFileName,
3044 const BinaryInputStreamRef& rxRecStrm, const String& rRecNames, const String& rSimpleRecs )
3046 InputObjectBase::construct( rParent, rxRecStrm, rSysFileName );
3047 constructRecObjBase( rxBaseStrm, rRecNames, rSimpleRecs );
3050 void RecordObjectBase::construct( const OutputObjectBase& rParent, const BinaryInputStreamRef& rxBaseStrm,
3051 const BinaryInputStreamRef& rxRecStrm, const String& rRecNames, const String& rSimpleRecs )
3053 InputObjectBase::construct( rParent, rxRecStrm );
3054 constructRecObjBase( rxBaseStrm, rRecNames, rSimpleRecs );
3057 bool RecordObjectBase::implIsValid() const
3059 return mxBaseStrm.get() && InputObjectBase::implIsValid();
3062 void RecordObjectBase::implDump()
3064 NameListRef xRecNames = getRecNames();
3066 typedef ::std::map< sal_Int64, ItemFormat > ItemFormatMap;
3067 ItemFormatMap aSimpleRecs;
3068 if( NameListBase* pSimpleRecs = maSimpleRecs.getNameList( cfg() ).get() )
3069 for( NameListBase::const_iterator aIt = pSimpleRecs->begin(), aEnd = pSimpleRecs->end(); aIt != aEnd; ++aIt )
3070 aSimpleRecs[ aIt->first ].parse( aIt->second );
3072 while( implStartRecord( *mxBaseStrm, mnRecPos, mnRecId, mnRecSize ) )
3074 // record header
3075 out().emptyLine();
3076 writeHeader();
3077 implWriteExtHeader();
3078 IndentGuard aIndGuard( out() );
3079 sal_Int64 nRecPos = in().tell();
3081 // record body
3082 if( !mbBinaryOnly && cfg().hasName( xRecNames, mnRecId ) )
3084 ItemFormatMap::const_iterator aIt = aSimpleRecs.find( mnRecId );
3085 if( aIt != aSimpleRecs.end() )
3086 dumpItem( aIt->second );
3087 else
3088 implDumpRecordBody();
3091 // remaining undumped data
3092 if( !in().isEof() && (in().tell() == nRecPos) )
3093 dumpRawBinary( mnRecSize, false );
3094 else
3095 dumpRemainingTo( nRecPos + mnRecSize );
3099 void RecordObjectBase::implWriteExtHeader()
3103 void RecordObjectBase::implDumpRecordBody()
3107 void RecordObjectBase::constructRecObjBase( const BinaryInputStreamRef& rxBaseStrm, const String& rRecNames, const String& rSimpleRecs )
3109 mxBaseStrm = rxBaseStrm;
3110 maRecNames = rRecNames;
3111 maSimpleRecs = rSimpleRecs;
3112 mnRecPos = mnRecId = mnRecSize = 0;
3113 mbBinaryOnly = false;
3114 if( InputObjectBase::implIsValid() )
3115 mbShowRecPos = cfg().getBoolOption( "show-record-position", true );
3118 void RecordObjectBase::writeHeader()
3120 MultiItemsGuard aMultiGuard( out() );
3121 writeEmptyItem( "REC" );
3122 if( mbShowRecPos && mxBaseStrm->isSeekable() )
3123 writeShortHexItem( "pos", mnRecPos, "CONV-DEC" );
3124 writeShortHexItem( "size", mnRecSize, "CONV-DEC" );
3125 ItemGuard aItem( out(), "id" );
3126 out().writeShortHex( mnRecId );
3127 addNameToItem( mnRecId, "CONV-DEC" );
3128 addNameToItem( mnRecId, maRecNames );
3131 // ============================================================================
3133 void SequenceRecordObjectBase::construct(
3134 const ObjectBase& rParent, const BinaryInputStreamRef& rxBaseStrm, const ::rtl::OUString& rSysFileName,
3135 const BinaryInputStreamRef& rxRecStrm, const String& rRecNames, const String& rSimpleRecs )
3137 RecordObjectBase::construct( rParent, rxBaseStrm, rSysFileName, rxRecStrm, rRecNames, rSimpleRecs );
3140 void SequenceRecordObjectBase::construct( const OutputObjectBase& rParent,
3141 const BinaryInputStreamRef& rxBaseStrm, const BinaryInputStreamRef& rxRecStrm,
3142 const String& rRecNames, const String& rSimpleRecs )
3144 RecordObjectBase::construct( rParent, rxBaseStrm, rxRecStrm, rRecNames, rSimpleRecs );
3147 void SequenceRecordObjectBase::construct( const ObjectBase& rParent,
3148 const BinaryInputStreamRef& rxBaseStrm, const ::rtl::OUString& rSysFileName,
3149 const String& rRecNames, const String& rSimpleRecs )
3151 BinaryInputStreamRef xRecStrm( new SequenceInputStream( *mxRecData ) );
3152 RecordObjectBase::construct( rParent, rxBaseStrm, rSysFileName, xRecStrm, rRecNames, rSimpleRecs );
3155 void SequenceRecordObjectBase::construct( const OutputObjectBase& rParent,
3156 const BinaryInputStreamRef& rxBaseStrm, const String& rRecNames, const String& rSimpleRecs )
3158 BinaryInputStreamRef xRecStrm( new SequenceInputStream( *mxRecData ) );
3159 RecordObjectBase::construct( rParent, rxBaseStrm, xRecStrm, rRecNames, rSimpleRecs );
3162 bool SequenceRecordObjectBase::implStartRecord( BinaryInputStream& rBaseStrm, sal_Int64& ornRecPos, sal_Int64& ornRecId, sal_Int64& ornRecSize )
3164 bool bValid = true;
3165 if( rBaseStrm.isSeekable() )
3167 ornRecPos = rBaseStrm.tell();
3168 // do not try to overread seekable streams, may cause assertions
3169 bValid = ornRecPos < rBaseStrm.getLength();
3172 // read the record header
3173 if( bValid )
3174 bValid = implReadRecordHeader( rBaseStrm, ornRecId, ornRecSize ) && !rBaseStrm.isEof() && (0 <= ornRecSize) && (ornRecSize <= 0x00100000);
3176 // read record contents into data sequence
3177 if( bValid )
3179 sal_Int32 nRecSize = static_cast< sal_Int32 >( ornRecSize );
3180 mxRecData->realloc( nRecSize );
3181 bValid = (nRecSize == 0) || (rBaseStrm.readData( *mxRecData, nRecSize ) == nRecSize);
3182 in().seekToStart();
3184 return bValid;
3187 // ============================================================================
3188 // ============================================================================
3190 DumperBase::~DumperBase()
3194 bool DumperBase::isImportEnabled() const
3196 return !isValid() || cfg().isImportEnabled();
3199 bool DumperBase::isImportCancelled() const
3201 return isValid() && cfg().isPasswordCancelled();
3204 void DumperBase::construct( const ConfigRef& rxConfig )
3206 if( isValid( rxConfig ) && rxConfig->isDumperEnabled() )
3207 ObjectBase::construct( rxConfig );
3210 // ============================================================================
3211 // ============================================================================
3213 } // namespace dump
3214 } // namespace oox
3216 #endif