1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "oox/dump/dumperbase.hxx"
23 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
24 #include <com/sun/star/io/XActiveDataSource.hpp>
25 #include <com/sun/star/io/TextOutputStream.hpp>
26 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
27 #include <comphelper/docpasswordhelper.hxx>
28 #include <osl/file.hxx>
29 #include <rtl/math.hxx>
30 #include <rtl/tencinfo.h>
31 #include "oox/core/filterbase.hxx"
32 #include "oox/helper/binaryoutputstream.hxx"
33 #include "oox/helper/textinputstream.hxx"
34 #include <tools/time.hxx>
36 #if OOX_INCLUDE_DUMPER
41 // ============================================================================
43 using namespace ::com::sun::star
;
44 using namespace ::com::sun::star::beans
;
45 using namespace ::com::sun::star::io
;
46 using namespace ::com::sun::star::lang
;
47 using namespace ::com::sun::star::ucb
;
48 using namespace ::com::sun::star::uno
;
50 using ::comphelper::MediaDescriptor
;
51 using ::oox::core::FilterBase
;
55 const sal_Unicode OOX_DUMP_BOM
= 0xFEFF;
56 const sal_Int32 OOX_DUMP_MAXSTRLEN
= 80;
57 const sal_Int32 OOX_DUMP_INDENT
= 2;
58 const sal_Unicode OOX_DUMP_BINDOT
= '.';
59 const sal_Unicode OOX_DUMP_CFG_LISTSEP
= ',';
60 const sal_Unicode OOX_DUMP_CFG_QUOTE
= '\'';
61 const sal_Unicode OOX_DUMP_LF
= '\n';
62 const sal_Unicode OOX_DUMP_ITEMSEP
= '=';
63 const sal_Int32 OOX_DUMP_BYTESPERLINE
= 16;
64 const sal_Int64 OOX_DUMP_MAXARRAY
= 16;
68 // ============================================================================
69 // ============================================================================
71 // file names -----------------------------------------------------------------
73 OUString
InputOutputHelper::convertFileNameToUrl( const OUString
& rFileName
)
76 if( ::osl::FileBase::getFileURLFromSystemPath( rFileName
, aFileUrl
) == ::osl::FileBase::E_None
)
81 sal_Int32
InputOutputHelper::getFileNamePos( const OUString
& rFileUrl
)
83 sal_Int32 nSepPos
= rFileUrl
.lastIndexOf( '/' );
84 return (nSepPos
< 0) ? 0 : (nSepPos
+ 1);
87 OUString
InputOutputHelper::getFileNameExtension( const OUString
& rFileUrl
)
89 sal_Int32 nNamePos
= getFileNamePos( rFileUrl
);
90 sal_Int32 nExtPos
= rFileUrl
.lastIndexOf( '.' );
91 if( nExtPos
>= nNamePos
)
92 return rFileUrl
.copy( nExtPos
+ 1 );
96 // input streams --------------------------------------------------------------
98 Reference
< XInputStream
> InputOutputHelper::openInputStream(
99 const Reference
< XComponentContext
>& rxContext
, const OUString
& rFileName
)
101 Reference
< XInputStream
> xInStrm
;
102 if( rxContext
.is() ) try
104 Reference
<XSimpleFileAccess3
> xFileAccess(SimpleFileAccess::create(rxContext
));
105 xInStrm
= xFileAccess
->openFileRead( rFileName
);
113 // output streams -------------------------------------------------------------
115 Reference
< XOutputStream
> InputOutputHelper::openOutputStream(
116 const Reference
< XComponentContext
>& rxContext
, const OUString
& rFileName
)
118 Reference
< XOutputStream
> xOutStrm
;
119 if( rxContext
.is() ) try
121 Reference
<XSimpleFileAccess3
> xFileAccess(SimpleFileAccess::create(rxContext
));
122 xOutStrm
= xFileAccess
->openFileWrite( rFileName
);
130 Reference
< XTextOutputStream2
> InputOutputHelper::openTextOutputStream(
131 const Reference
< XComponentContext
>& rxContext
, const Reference
< XOutputStream
>& rxOutStrm
, rtl_TextEncoding eTextEnc
)
133 Reference
< XTextOutputStream2
> xTextOutStrm
;
134 const char* pcCharset
= rtl_getMimeCharsetFromTextEncoding( eTextEnc
);
135 if( rxContext
.is() && rxOutStrm
.is() && pcCharset
) try
137 xTextOutStrm
= TextOutputStream::create(rxContext
);
138 xTextOutStrm
->setOutputStream( rxOutStrm
);
139 xTextOutStrm
->setEncoding( OUString::createFromAscii( pcCharset
) );
147 Reference
< XTextOutputStream2
> InputOutputHelper::openTextOutputStream(
148 const Reference
< XComponentContext
>& rxContext
, const OUString
& rFileName
, rtl_TextEncoding eTextEnc
)
150 return openTextOutputStream( rxContext
, openOutputStream( rxContext
, rFileName
), eTextEnc
);
153 // ============================================================================
154 // ============================================================================
156 ItemFormat::ItemFormat() :
157 meDataType( DATATYPE_VOID
),
158 meFmtType( FORMATTYPE_NONE
)
162 void ItemFormat::set( DataType eDataType
, FormatType eFmtType
, const OUString
& rItemName
)
164 meDataType
= eDataType
;
165 meFmtType
= eFmtType
;
166 maItemName
= rItemName
;
167 maListName
= OUString();
170 OUStringVector::const_iterator
ItemFormat::parse( const OUStringVector
& rFormatVec
)
172 set( DATATYPE_VOID
, FORMATTYPE_NONE
, OUString() );
174 OUStringVector::const_iterator aIt
= rFormatVec
.begin(), aEnd
= rFormatVec
.end();
175 OUString aDataType
, aFmtType
;
176 if( aIt
!= aEnd
) aDataType
= *aIt
++;
177 if( aIt
!= aEnd
) aFmtType
= *aIt
++;
178 if( aIt
!= aEnd
) maItemName
= *aIt
++;
179 if( aIt
!= aEnd
) maListName
= *aIt
++;
181 meDataType
= StringHelper::convertToDataType( aDataType
);
182 meFmtType
= StringHelper::convertToFormatType( aFmtType
);
184 if( meFmtType
== FORMATTYPE_NONE
)
186 if ( aFmtType
== "unused" )
187 set( meDataType
, FORMATTYPE_HEX
, OOX_DUMP_UNUSED
);
188 else if ( aFmtType
== "unknown" )
189 set( meDataType
, FORMATTYPE_HEX
, OOX_DUMP_UNKNOWN
);
195 OUStringVector
ItemFormat::parse( const OUString
& rFormatStr
)
197 OUStringVector aFormatVec
;
198 StringHelper::convertStringToStringList( aFormatVec
, rFormatStr
, false );
199 OUStringVector::const_iterator aIt
= parse( aFormatVec
);
200 return OUStringVector( aIt
, const_cast< const OUStringVector
& >( aFormatVec
).end() );
203 // ============================================================================
204 // ============================================================================
206 // append string to string ----------------------------------------------------
208 void StringHelper::appendChar( OUStringBuffer
& rStr
, sal_Unicode cChar
, sal_Int32 nCount
)
210 for( sal_Int32 nIndex
= 0; nIndex
< nCount
; ++nIndex
)
211 rStr
.append( cChar
);
214 void StringHelper::appendString( OUStringBuffer
& rStr
, const OUString
& rData
, sal_Int32 nWidth
, sal_Unicode cFill
)
216 appendChar( rStr
, cFill
, nWidth
- rData
.getLength() );
217 rStr
.append( rData
);
220 // append decimal -------------------------------------------------------------
222 void StringHelper::appendDec( OUStringBuffer
& rStr
, sal_uInt8 nData
, sal_Int32 nWidth
, sal_Unicode cFill
)
224 appendString( rStr
, OUString::number( nData
), nWidth
, cFill
);
227 void StringHelper::appendDec( OUStringBuffer
& rStr
, sal_Int8 nData
, sal_Int32 nWidth
, sal_Unicode cFill
)
229 appendString( rStr
, OUString::number( nData
), nWidth
, cFill
);
232 void StringHelper::appendDec( OUStringBuffer
& rStr
, sal_uInt16 nData
, sal_Int32 nWidth
, sal_Unicode cFill
)
234 appendString( rStr
, OUString::number( nData
), nWidth
, cFill
);
237 void StringHelper::appendDec( OUStringBuffer
& rStr
, sal_Int16 nData
, sal_Int32 nWidth
, sal_Unicode cFill
)
239 appendString( rStr
, OUString::number( nData
), nWidth
, cFill
);
242 void StringHelper::appendDec( OUStringBuffer
& rStr
, sal_uInt32 nData
, sal_Int32 nWidth
, sal_Unicode cFill
)
244 appendString( rStr
, OUString::number( nData
), nWidth
, cFill
);
247 void StringHelper::appendDec( OUStringBuffer
& rStr
, sal_Int32 nData
, sal_Int32 nWidth
, sal_Unicode cFill
)
249 appendString( rStr
, OUString::valueOf( nData
), nWidth
, cFill
);
252 void StringHelper::appendDec( OUStringBuffer
& rStr
, sal_uInt64 nData
, sal_Int32 nWidth
, sal_Unicode cFill
)
254 /* Values greater than biggest signed 64bit integer will change to
255 negative when converting to sal_Int64. Therefore, the trailing digit
256 will be written separately. */
257 OUStringBuffer aBuffer
;
259 aBuffer
.append( OUString::valueOf( static_cast< sal_Int64
>( nData
/ 10 ) ) );
260 aBuffer
.append( static_cast< sal_Unicode
>( '0' + (nData
% 10) ) );
261 appendString( rStr
, aBuffer
.makeStringAndClear(), nWidth
, cFill
);
264 void StringHelper::appendDec( OUStringBuffer
& rStr
, sal_Int64 nData
, sal_Int32 nWidth
, sal_Unicode cFill
)
266 appendString( rStr
, OUString::valueOf( nData
), nWidth
, cFill
);
269 void StringHelper::appendDec( OUStringBuffer
& rStr
, double fData
, sal_Int32 nWidth
, sal_Unicode cFill
)
271 appendString( rStr
, ::rtl::math::doubleToUString( fData
, rtl_math_StringFormat_G
, 15, '.', true ), nWidth
, cFill
);
274 // append hexadecimal ---------------------------------------------------------
276 void StringHelper::appendHex( OUStringBuffer
& rStr
, sal_uInt8 nData
, bool bPrefix
)
278 static const sal_Unicode spcHexDigits
[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
280 rStr
.appendAscii( "0x" );
281 rStr
.append( spcHexDigits
[ (nData
>> 4) & 0x0F ] ).append( spcHexDigits
[ nData
& 0x0F ] );
284 void StringHelper::appendHex( OUStringBuffer
& rStr
, sal_Int8 nData
, bool bPrefix
)
286 appendHex( rStr
, static_cast< sal_uInt8
>( nData
), bPrefix
);
289 void StringHelper::appendHex( OUStringBuffer
& rStr
, sal_uInt16 nData
, bool bPrefix
)
291 appendHex( rStr
, static_cast< sal_uInt8
>( nData
>> 8 ), bPrefix
);
292 appendHex( rStr
, static_cast< sal_uInt8
>( nData
), false );
295 void StringHelper::appendHex( OUStringBuffer
& rStr
, sal_Int16 nData
, bool bPrefix
)
297 appendHex( rStr
, static_cast< sal_uInt16
>( nData
), bPrefix
);
300 void StringHelper::appendHex( OUStringBuffer
& rStr
, sal_uInt32 nData
, bool bPrefix
)
302 appendHex( rStr
, static_cast< sal_uInt16
>( nData
>> 16 ), bPrefix
);
303 appendHex( rStr
, static_cast< sal_uInt16
>( nData
), false );
306 void StringHelper::appendHex( OUStringBuffer
& rStr
, sal_Int32 nData
, bool bPrefix
)
308 appendHex( rStr
, static_cast< sal_uInt32
>( nData
), bPrefix
);
311 void StringHelper::appendHex( OUStringBuffer
& rStr
, sal_uInt64 nData
, bool bPrefix
)
313 appendHex( rStr
, static_cast< sal_uInt32
>( nData
>> 32 ), bPrefix
);
314 appendHex( rStr
, static_cast< sal_uInt32
>( nData
), false );
317 void StringHelper::appendHex( OUStringBuffer
& rStr
, sal_Int64 nData
, bool bPrefix
)
319 appendHex( rStr
, static_cast< sal_uInt64
>( nData
), bPrefix
);
323 lcl_ConvertDouble(double const f
)
325 sal_uInt64 i
= sal_uInt64();
326 for (size_t j
= 0; j
< sizeof(double); ++j
)
327 { // hopefully both endian independent and strict aliasing safe
328 reinterpret_cast<char *>(&i
)[j
] = reinterpret_cast<char const *>(&f
)[j
];
333 void StringHelper::appendHex( OUStringBuffer
& rStr
, double fData
, bool bPrefix
)
335 appendHex( rStr
, lcl_ConvertDouble(fData
), bPrefix
);
338 // append shortened hexadecimal -----------------------------------------------
340 void StringHelper::appendShortHex( OUStringBuffer
& rStr
, sal_uInt8 nData
, bool bPrefix
)
342 appendHex( rStr
, nData
, bPrefix
);
345 void StringHelper::appendShortHex( OUStringBuffer
& rStr
, sal_Int8 nData
, bool bPrefix
)
347 appendHex( rStr
, nData
, bPrefix
);
350 void StringHelper::appendShortHex( OUStringBuffer
& rStr
, sal_uInt16 nData
, bool bPrefix
)
352 if( nData
> SAL_MAX_UINT8
)
353 appendHex( rStr
, nData
, bPrefix
);
355 appendHex( rStr
, static_cast< sal_uInt8
>( nData
), bPrefix
);
358 void StringHelper::appendShortHex( OUStringBuffer
& rStr
, sal_Int16 nData
, bool bPrefix
)
360 appendShortHex( rStr
, static_cast< sal_uInt16
>( nData
), bPrefix
);
363 void StringHelper::appendShortHex( OUStringBuffer
& rStr
, sal_uInt32 nData
, bool bPrefix
)
365 if( nData
> SAL_MAX_UINT16
)
366 appendHex( rStr
, nData
, bPrefix
);
368 appendShortHex( rStr
, static_cast< sal_uInt16
>( nData
), bPrefix
);
371 void StringHelper::appendShortHex( OUStringBuffer
& rStr
, sal_Int32 nData
, bool bPrefix
)
373 appendShortHex( rStr
, static_cast< sal_uInt32
>( nData
), bPrefix
);
376 void StringHelper::appendShortHex( OUStringBuffer
& rStr
, sal_uInt64 nData
, bool bPrefix
)
378 if( nData
> SAL_MAX_UINT32
)
379 appendHex( rStr
, nData
, bPrefix
);
381 appendShortHex( rStr
, static_cast< sal_uInt32
>( nData
), bPrefix
);
384 void StringHelper::appendShortHex( OUStringBuffer
& rStr
, sal_Int64 nData
, bool bPrefix
)
386 appendShortHex( rStr
, static_cast< sal_uInt64
>( nData
), bPrefix
);
389 void StringHelper::appendShortHex( OUStringBuffer
& rStr
, double fData
, bool bPrefix
)
391 appendHex( rStr
, fData
, bPrefix
);
394 // append binary --------------------------------------------------------------
396 void StringHelper::appendBin( OUStringBuffer
& rStr
, sal_uInt8 nData
, bool bDots
)
398 for( sal_uInt8 nMask
= 0x80; nMask
!= 0; (nMask
>>= 1) &= 0x7F )
400 rStr
.append( static_cast< sal_Unicode
>( (nData
& nMask
) ? '1' : '0' ) );
401 if( bDots
&& (nMask
== 0x10) )
402 rStr
.append( OOX_DUMP_BINDOT
);
406 void StringHelper::appendBin( OUStringBuffer
& rStr
, sal_Int8 nData
, bool bDots
)
408 appendBin( rStr
, static_cast< sal_uInt8
>( nData
), bDots
);
411 void StringHelper::appendBin( OUStringBuffer
& rStr
, sal_uInt16 nData
, bool bDots
)
413 appendBin( rStr
, static_cast< sal_uInt8
>( nData
>> 8 ), bDots
);
415 rStr
.append( OOX_DUMP_BINDOT
);
416 appendBin( rStr
, static_cast< sal_uInt8
>( nData
), bDots
);
419 void StringHelper::appendBin( OUStringBuffer
& rStr
, sal_Int16 nData
, bool bDots
)
421 appendBin( rStr
, static_cast< sal_uInt16
>( nData
), bDots
);
424 void StringHelper::appendBin( OUStringBuffer
& rStr
, sal_uInt32 nData
, bool bDots
)
426 appendBin( rStr
, static_cast< sal_uInt16
>( nData
>> 16 ), bDots
);
428 rStr
.append( OOX_DUMP_BINDOT
);
429 appendBin( rStr
, static_cast< sal_uInt16
>( nData
), bDots
);
432 void StringHelper::appendBin( OUStringBuffer
& rStr
, sal_Int32 nData
, bool bDots
)
434 appendBin( rStr
, static_cast< sal_uInt32
>( nData
), bDots
);
437 void StringHelper::appendBin( OUStringBuffer
& rStr
, sal_uInt64 nData
, bool bDots
)
439 appendBin( rStr
, static_cast< sal_uInt32
>( nData
>> 32 ), bDots
);
441 rStr
.append( OOX_DUMP_BINDOT
);
442 appendBin( rStr
, static_cast< sal_uInt32
>( nData
), bDots
);
445 void StringHelper::appendBin( OUStringBuffer
& rStr
, sal_Int64 nData
, bool bDots
)
447 appendBin( rStr
, static_cast< sal_uInt64
>( nData
), bDots
);
450 void StringHelper::appendBin( OUStringBuffer
& rStr
, double fData
, bool bDots
)
452 appendBin( rStr
, lcl_ConvertDouble(fData
), bDots
);
455 // append formatted value -----------------------------------------------------
457 void StringHelper::appendBool( OUStringBuffer
& rStr
, bool bData
)
459 rStr
.appendAscii( bData
? "true" : "false" );
462 // encoded text output --------------------------------------------------------
464 void StringHelper::appendCChar( OUStringBuffer
& rStr
, sal_Unicode cChar
, bool bPrefix
)
469 rStr
.appendAscii( "\\u" );
470 appendHex( rStr
, static_cast< sal_uInt16
>( cChar
), false );
475 rStr
.appendAscii( "\\x" );
476 appendHex( rStr
, static_cast< sal_uInt8
>( cChar
), false );
480 void StringHelper::appendEncChar( OUStringBuffer
& rStr
, sal_Unicode cChar
, sal_Int32 nCount
, bool bPrefix
)
485 OUStringBuffer aCode
;
486 appendCChar( aCode
, cChar
, bPrefix
);
487 OUString aCodeStr
= aCode
.makeStringAndClear();
488 for( sal_Int32 nIdx
= 0; nIdx
< nCount
; ++nIdx
)
489 rStr
.append( aCodeStr
);
493 appendChar( rStr
, cChar
, nCount
);
497 void StringHelper::appendEncString( OUStringBuffer
& rStr
, const OUString
& rData
, bool bPrefix
)
501 sal_Int32 nEnd
= rData
.getLength();
504 // find next character that needs encoding
505 while( (nIdx
< nEnd
) && (rData
[ nIdx
] >= 0x20) ) ++nIdx
;
509 if( (nBeg
== 0) && (nIdx
== nEnd
) )
510 rStr
.append( rData
);
512 rStr
.append( rData
.copy( nBeg
, nIdx
- nBeg
) );
514 // append characters to be encoded
515 while( (nIdx
< nEnd
) && (rData
[ nIdx
] < 0x20) )
517 appendCChar( rStr
, rData
[ nIdx
], bPrefix
);
525 // token list -----------------------------------------------------------------
527 void StringHelper::appendToken( OUStringBuffer
& rStr
, const OUString
& rToken
, sal_Unicode cSep
)
529 if( (rStr
.getLength() > 0) && (!rToken
.isEmpty()) )
531 rStr
.append( rToken
);
534 void StringHelper::appendIndex( OUStringBuffer
& rStr
, const OUString
& rIdx
)
536 rStr
.append( sal_Unicode( '[' ) ).append( rIdx
).append( sal_Unicode( ']' ) );
539 void StringHelper::appendIndex( OUStringBuffer
& rStr
, sal_Int64 nIdx
)
541 OUStringBuffer aToken
;
542 appendDec( aToken
, nIdx
);
543 appendIndex( rStr
, aToken
.makeStringAndClear() );
546 OUString
StringHelper::getToken( const OUString
& rData
, sal_Int32
& rnPos
, sal_Unicode cSep
)
548 return trimSpaces( rData
.getToken( 0, cSep
, rnPos
) );
551 void StringHelper::enclose( OUStringBuffer
& rStr
, sal_Unicode cOpen
, sal_Unicode cClose
)
553 rStr
.insert( 0, cOpen
).append( cClose
? cClose
: cOpen
);
556 // string conversion ----------------------------------------------------------
560 sal_Int32
lclIndexOf( const OUString
& rStr
, sal_Unicode cChar
, sal_Int32 nStartPos
)
562 sal_Int32 nIndex
= rStr
.indexOf( cChar
, nStartPos
);
563 return (nIndex
< 0) ? rStr
.getLength() : nIndex
;
566 OUString
lclTrimQuotedStringList( const OUString
& rStr
)
568 OUStringBuffer aBuffer
;
570 sal_Int32 nLen
= rStr
.getLength();
573 if( rStr
[ nPos
] == OOX_DUMP_CFG_QUOTE
)
575 // quoted string, skip leading quote character
577 // process quoted text and ambedded literal quote characters
578 OUStringBuffer aToken
;
581 // seek to next quote character and add text portion to token buffer
582 sal_Int32 nEnd
= lclIndexOf( rStr
, OOX_DUMP_CFG_QUOTE
, nPos
);
583 aToken
.append( rStr
.copy( nPos
, nEnd
- nPos
) );
584 // process literal quotes
585 while( (nEnd
+ 1 < nLen
) && (rStr
[ nEnd
] == OOX_DUMP_CFG_QUOTE
) && (rStr
[ nEnd
+ 1 ] == OOX_DUMP_CFG_QUOTE
) )
587 aToken
.append( OOX_DUMP_CFG_QUOTE
);
590 // nEnd is start of possible next text portion
593 while( (nPos
< nLen
) && (rStr
[ nPos
] != OOX_DUMP_CFG_QUOTE
) );
594 // add token, seek to list separator, ignore text following closing quote
595 aBuffer
.append( aToken
.makeStringAndClear() );
596 nPos
= lclIndexOf( rStr
, OOX_DUMP_CFG_LISTSEP
, nPos
);
598 aBuffer
.append( OOX_DUMP_LF
);
599 // set current position behind list separator
604 // find list separator, add token text to buffer
605 sal_Int32 nEnd
= lclIndexOf( rStr
, OOX_DUMP_CFG_LISTSEP
, nPos
);
606 aBuffer
.append( rStr
.copy( nPos
, nEnd
- nPos
) );
608 aBuffer
.append( OOX_DUMP_LF
);
609 // set current position behind list separator
614 return aBuffer
.makeStringAndClear();
619 OUString
StringHelper::trimSpaces( const OUString
& rStr
)
622 while( (nBeg
< rStr
.getLength()) && ((rStr
[ nBeg
] == ' ') || (rStr
[ nBeg
] == '\t')) )
624 sal_Int32 nEnd
= rStr
.getLength();
625 while( (nEnd
> nBeg
) && ((rStr
[ nEnd
- 1 ] == ' ') || (rStr
[ nEnd
- 1 ] == '\t')) )
627 return rStr
.copy( nBeg
, nEnd
- nBeg
);
630 OUString
StringHelper::trimTrailingNul( const OUString
& rStr
)
632 sal_Int32 nLastPos
= rStr
.getLength() - 1;
633 if( (nLastPos
>= 0) && (rStr
[ nLastPos
] == 0) )
634 return rStr
.copy( 0, nLastPos
);
638 OString
StringHelper::convertToUtf8( const OUString
& rStr
)
640 return OUStringToOString( rStr
, RTL_TEXTENCODING_UTF8
);
643 DataType
StringHelper::convertToDataType( const OUString
& rStr
)
645 DataType eType
= DATATYPE_VOID
;
646 if ( rStr
== "int8" )
647 eType
= DATATYPE_INT8
;
648 else if ( rStr
== "uint8" )
649 eType
= DATATYPE_UINT8
;
650 else if ( rStr
== "int16" )
651 eType
= DATATYPE_INT16
;
652 else if ( rStr
== "uint16" )
653 eType
= DATATYPE_UINT16
;
654 else if ( rStr
== "int32" )
655 eType
= DATATYPE_INT32
;
656 else if ( rStr
== "uint32" )
657 eType
= DATATYPE_UINT32
;
658 else if ( rStr
== "int64" )
659 eType
= DATATYPE_INT64
;
660 else if ( rStr
== "uint64" )
661 eType
= DATATYPE_UINT64
;
662 else if ( rStr
== "float" )
663 eType
= DATATYPE_FLOAT
;
664 else if ( rStr
== "double" )
665 eType
= DATATYPE_DOUBLE
;
669 FormatType
StringHelper::convertToFormatType( const OUString
& rStr
)
671 FormatType eType
= FORMATTYPE_NONE
;
673 eType
= FORMATTYPE_DEC
;
674 else if ( rStr
== "hex" )
675 eType
= FORMATTYPE_HEX
;
676 else if ( rStr
== "shorthex" )
677 eType
= FORMATTYPE_SHORTHEX
;
678 else if ( rStr
== "bin" )
679 eType
= FORMATTYPE_BIN
;
680 else if ( rStr
== "fix" )
681 eType
= FORMATTYPE_FIX
;
682 else if ( rStr
== "bool" )
683 eType
= FORMATTYPE_BOOL
;
687 bool StringHelper::convertFromDec( sal_Int64
& ornData
, const OUString
& rData
)
690 sal_Int32 nLen
= rData
.getLength();
692 if( (nLen
> 0) && (rData
[ 0 ] == '-') )
698 for( ; nPos
< nLen
; ++nPos
)
700 sal_Unicode cChar
= rData
[ nPos
];
701 if( (cChar
< '0') || (cChar
> '9') )
703 (ornData
*= 10) += (cChar
- '0');
710 bool StringHelper::convertFromHex( sal_Int64
& ornData
, const OUString
& rData
)
713 for( sal_Int32 nPos
= 0, nLen
= rData
.getLength(); nPos
< nLen
; ++nPos
)
715 sal_Unicode cChar
= rData
[ nPos
];
716 if( ('0' <= cChar
) && (cChar
<= '9') )
718 else if( ('A' <= cChar
) && (cChar
<= 'F') )
720 else if( ('a' <= cChar
) && (cChar
<= 'f') )
724 (ornData
<<= 4) += cChar
;
729 bool StringHelper::convertStringToInt( sal_Int64
& ornData
, const OUString
& rData
)
731 if( (rData
.getLength() > 2) && (rData
[ 0 ] == '0') && ((rData
[ 1 ] == 'X') || (rData
[ 1 ] == 'x')) )
732 return convertFromHex( ornData
, rData
.copy( 2 ) );
733 return convertFromDec( ornData
, rData
);
736 bool StringHelper::convertStringToDouble( double& orfData
, const OUString
& rData
)
738 rtl_math_ConversionStatus eStatus
= rtl_math_ConversionStatus_Ok
;
740 orfData
= rtl::math::stringToDouble( rData
, '.', '\0', &eStatus
, &nSize
);
741 return (eStatus
== rtl_math_ConversionStatus_Ok
) && (nSize
== rData
.getLength());
744 bool StringHelper::convertStringToBool( const OUString
& rData
)
746 if ( rData
== "true" )
748 if ( rData
== "false" )
751 return convertStringToInt( nData
, rData
) && (nData
!= 0);
754 OUStringPair
StringHelper::convertStringToPair( const OUString
& rString
, sal_Unicode cSep
)
757 if( !rString
.isEmpty() )
759 sal_Int32 nEqPos
= rString
.indexOf( cSep
);
762 aPair
.first
= rString
;
766 aPair
.first
= StringHelper::trimSpaces( rString
.copy( 0, nEqPos
) );
767 aPair
.second
= StringHelper::trimSpaces( rString
.copy( nEqPos
+ 1 ) );
773 void StringHelper::convertStringToStringList( OUStringVector
& orVec
, const OUString
& rData
, bool bIgnoreEmpty
)
776 OUString aUnquotedData
= lclTrimQuotedStringList( rData
);
778 sal_Int32 nLen
= aUnquotedData
.getLength();
779 while( (0 <= nPos
) && (nPos
< nLen
) )
781 OUString aToken
= getToken( aUnquotedData
, nPos
, OOX_DUMP_LF
);
782 if( !bIgnoreEmpty
|| !aToken
.isEmpty() )
783 orVec
.push_back( aToken
);
787 void StringHelper::convertStringToIntList( Int64Vector
& orVec
, const OUString
& rData
, bool bIgnoreEmpty
)
790 OUString aUnquotedData
= lclTrimQuotedStringList( rData
);
792 sal_Int32 nLen
= aUnquotedData
.getLength();
794 while( (0 <= nPos
) && (nPos
< nLen
) )
796 bool bOk
= convertStringToInt( nData
, getToken( aUnquotedData
, nPos
, OOX_DUMP_LF
) );
797 if( !bIgnoreEmpty
|| bOk
)
798 orVec
.push_back( bOk
? nData
: 0 );
802 // ============================================================================
803 // ============================================================================
809 // ============================================================================
810 // ============================================================================
812 ConfigItemBase::~ConfigItemBase()
816 void ConfigItemBase::readConfigBlock( TextInputStream
& rStrm
)
818 readConfigBlockContents( rStrm
);
821 void ConfigItemBase::implProcessConfigItemStr(
822 TextInputStream
& /*rStrm*/, const OUString
& /*rKey*/, const OUString
& /*rData*/ )
826 void ConfigItemBase::implProcessConfigItemInt(
827 TextInputStream
& /*rStrm*/, sal_Int64
/*nKey*/, const OUString
& /*rData*/ )
831 void ConfigItemBase::readConfigBlockContents( TextInputStream
& rStrm
)
834 while( bLoop
&& !rStrm
.isEof() )
836 OUString aKey
, aData
;
837 switch( readConfigLine( rStrm
, aKey
, aData
) )
840 processConfigItem( rStrm
, aKey
, aData
);
849 ConfigItemBase::LineType
ConfigItemBase::readConfigLine(
850 TextInputStream
& rStrm
, OUString
& orKey
, OUString
& orData
) const
853 while( !rStrm
.isEof() && aLine
.isEmpty() )
855 aLine
= rStrm
.readLine();
856 if( !aLine
.isEmpty() && (aLine
[ 0 ] == OOX_DUMP_BOM
) )
857 aLine
= aLine
.copy( 1 );
858 aLine
= StringHelper::trimSpaces( aLine
);
859 if( !aLine
.isEmpty() )
861 // ignore comments (starting with hash or semicolon)
862 sal_Unicode cChar
= aLine
[ 0 ];
863 if( (cChar
== '#') || (cChar
== ';') )
868 OUStringPair aPair
= StringHelper::convertStringToPair( aLine
);
870 orData
= aPair
.second
;
871 return ( !orKey
.isEmpty() && (!orData
.isEmpty() || orKey
!= "end" )) ?
872 LINETYPE_DATA
: LINETYPE_END
;
875 void ConfigItemBase::processConfigItem(
876 TextInputStream
& rStrm
, const OUString
& rKey
, const OUString
& rData
)
879 if( StringHelper::convertStringToInt( nKey
, rKey
) )
880 implProcessConfigItemInt( rStrm
, nKey
, rData
);
882 implProcessConfigItemStr( rStrm
, rKey
, rData
);
885 // ============================================================================
887 NameListBase::~NameListBase()
891 void NameListBase::setName( sal_Int64 nKey
, const String
& rName
)
893 implSetName( nKey
, rName
);
896 void NameListBase::includeList( const NameListRef
& rxList
)
900 for( const_iterator aIt
= rxList
->begin(), aEnd
= rxList
->end(); aIt
!= aEnd
; ++aIt
)
901 maMap
[ aIt
->first
] = aIt
->second
;
902 implIncludeList( *rxList
);
906 bool NameListBase::implIsValid() const
911 void NameListBase::implProcessConfigItemStr(
912 TextInputStream
& rStrm
, const OUString
& rKey
, const OUString
& rData
)
914 if ( rKey
== "include" )
916 else if ( rKey
== "exclude" )
919 ConfigItemBase::implProcessConfigItemStr( rStrm
, rKey
, rData
);
922 void NameListBase::implProcessConfigItemInt(
923 TextInputStream
& /*rStrm*/, sal_Int64 nKey
, const OUString
& rData
)
925 implSetName( nKey
, rData
);
928 void NameListBase::insertRawName( sal_Int64 nKey
, const OUString
& rName
)
930 maMap
[ nKey
] = rName
;
933 const OUString
* NameListBase::findRawName( sal_Int64 nKey
) const
935 const_iterator aIt
= maMap
.find( nKey
);
936 return (aIt
== end()) ? 0 : &aIt
->second
;
939 void NameListBase::include( const OUString
& rListKeys
)
942 StringHelper::convertStringToStringList( aVec
, rListKeys
, true );
943 for( OUStringVector::const_iterator aIt
= aVec
.begin(), aEnd
= aVec
.end(); aIt
!= aEnd
; ++aIt
)
944 includeList( mrCfgData
.getNameList( *aIt
) );
947 void NameListBase::exclude( const OUString
& rKeys
)
950 StringHelper::convertStringToIntList( aVec
, rKeys
, true );
951 for( Int64Vector::const_iterator aIt
= aVec
.begin(), aEnd
= aVec
.end(); aIt
!= aEnd
; ++aIt
)
955 // ============================================================================
957 void ItemFormatMap::insertFormats( const NameListRef
& rxNameList
)
959 if( Base::isValid( rxNameList
) )
960 for( NameListBase::const_iterator aIt
= rxNameList
->begin(), aEnd
= rxNameList
->end(); aIt
!= aEnd
; ++aIt
)
961 (*this)[ aIt
->first
].parse( aIt
->second
);
964 // ============================================================================
966 ConstList::ConstList( const SharedConfigData
& rCfgData
) :
967 NameListBase( rCfgData
),
968 maDefName( OOX_DUMP_ERR_NONAME
),
969 mbQuoteNames( false )
973 void ConstList::implProcessConfigItemStr(
974 TextInputStream
& rStrm
, const OUString
& rKey
, const OUString
& rData
)
976 if ( rKey
== "default" )
977 setDefaultName( rData
);
978 else if ( rKey
== "quote-names" )
979 setQuoteNames( StringHelper::convertStringToBool( rData
) );
981 NameListBase::implProcessConfigItemStr( rStrm
, rKey
, rData
);
984 void ConstList::implSetName( sal_Int64 nKey
, const OUString
& rName
)
986 insertRawName( nKey
, rName
);
989 OUString
ConstList::implGetName( const Config
& /*rCfg*/, sal_Int64 nKey
) const
991 const OUString
* pName
= findRawName( nKey
);
992 OUString aName
= pName
? *pName
: maDefName
;
995 OUStringBuffer
aBuffer( aName
);
996 StringHelper::enclose( aBuffer
, OOX_DUMP_STRQUOTE
);
997 aName
= aBuffer
.makeStringAndClear();
1002 OUString
ConstList::implGetNameDbl( const Config
& /*rCfg*/, double /*fValue*/ ) const
1007 void ConstList::implIncludeList( const NameListBase
& rList
)
1009 if( const ConstList
* pConstList
= dynamic_cast< const ConstList
* >( &rList
) )
1011 maDefName
= pConstList
->maDefName
;
1012 mbQuoteNames
= pConstList
->mbQuoteNames
;
1016 // ============================================================================
1018 MultiList::MultiList( const SharedConfigData
& rCfgData
) :
1019 ConstList( rCfgData
),
1020 mbIgnoreEmpty( true )
1024 void MultiList::setNamesFromVec( sal_Int64 nStartKey
, const OUStringVector
& rNames
)
1026 sal_Int64 nKey
= nStartKey
;
1027 for( OUStringVector::const_iterator aIt
= rNames
.begin(), aEnd
= rNames
.end(); aIt
!= aEnd
; ++aIt
, ++nKey
)
1028 if( !mbIgnoreEmpty
|| !aIt
->isEmpty() )
1029 insertRawName( nKey
, *aIt
);
1032 void MultiList::implProcessConfigItemStr(
1033 TextInputStream
& rStrm
, const OUString
& rKey
, const OUString
& rData
)
1035 if ( rKey
== "ignore-empty" )
1036 mbIgnoreEmpty
= StringHelper::convertStringToBool( rData
);
1038 ConstList::implProcessConfigItemStr( rStrm
, rKey
, rData
);
1041 void MultiList::implSetName( sal_Int64 nKey
, const OUString
& rName
)
1043 OUStringVector aNames
;
1044 StringHelper::convertStringToStringList( aNames
, rName
, false );
1045 setNamesFromVec( nKey
, aNames
);
1048 // ============================================================================
1050 FlagsList::FlagsList( const SharedConfigData
& rCfgData
) :
1051 NameListBase( rCfgData
),
1056 void FlagsList::implProcessConfigItemStr(
1057 TextInputStream
& rStrm
, const OUString
& rKey
, const OUString
& rData
)
1059 if ( rKey
== "ignore" )
1062 if( StringHelper::convertStringToInt( nIgnore
, rData
) )
1063 setIgnoreFlags( nIgnore
);
1067 NameListBase::implProcessConfigItemStr( rStrm
, rKey
, rData
);
1071 void FlagsList::implSetName( sal_Int64 nKey
, const OUString
& rName
)
1073 if( (nKey
!= 0) && ((nKey
& (nKey
- 1)) == 0) ) // only a single bit set?
1074 insertRawName( nKey
, rName
);
1077 OUString
FlagsList::implGetName( const Config
& /*rCfg*/, sal_Int64 nKey
) const
1079 sal_Int64 nFound
= mnIgnore
;
1080 OUStringBuffer aName
;
1082 for( const_iterator aIt
= begin(), aEnd
= end(); aIt
!= aEnd
; ++aIt
)
1084 sal_Int64 nMask
= aIt
->first
;
1085 setFlag( nFound
, nMask
);
1086 if( !getFlag( mnIgnore
, nMask
) )
1088 const OUString
& rFlagName
= aIt
->second
;
1089 bool bOnOff
= !rFlagName
.isEmpty() && rFlagName
[ 0 ] == ':';
1090 bool bFlag
= getFlag( nKey
, nMask
);
1093 StringHelper::appendToken( aName
, rFlagName
.copy( 1 ) );
1094 aName
.appendAscii( bFlag
? ":on" : ":off" );
1098 bool bNegated
= !rFlagName
.isEmpty() && rFlagName
[ 0 ] == '!';
1099 sal_Int32 nBothSep
= bNegated
? rFlagName
.indexOf( '!', 1 ) : -1;
1103 StringHelper::appendToken( aName
, rFlagName
);
1104 else if( nBothSep
> 0 )
1105 StringHelper::appendToken( aName
, rFlagName
.copy( nBothSep
+ 1 ) );
1110 StringHelper::appendToken( aName
, rFlagName
.copy( 1, nBothSep
- 1 ) );
1112 StringHelper::appendToken( aName
, rFlagName
.copy( 1 ) );
1117 // add unknown flags
1118 setFlag( nKey
, nFound
, false );
1121 OUStringBuffer
aUnknown( OOX_DUMP_UNKNOWN
);
1122 aUnknown
.append( OOX_DUMP_ITEMSEP
);
1123 StringHelper::appendShortHex( aUnknown
, nKey
, true );
1124 StringHelper::enclose( aUnknown
, '(', ')' );
1125 StringHelper::appendToken( aName
, aUnknown
.makeStringAndClear() );
1127 return aName
.makeStringAndClear();
1130 OUString
FlagsList::implGetNameDbl( const Config
& /*rCfg*/, double /*fValue*/ ) const
1135 void FlagsList::implIncludeList( const NameListBase
& rList
)
1137 if( const FlagsList
* pFlagsList
= dynamic_cast< const FlagsList
* >( &rList
) )
1138 mnIgnore
= pFlagsList
->mnIgnore
;
1141 // ============================================================================
1143 bool CombiList::ExtItemFormatKey::operator<( const ExtItemFormatKey
& rRight
) const
1145 return (mnKey
< rRight
.mnKey
) || ((mnKey
== rRight
.mnKey
) && (maFilter
< rRight
.maFilter
));
1148 CombiList::CombiList( const SharedConfigData
& rCfgData
) :
1149 FlagsList( rCfgData
)
1153 void CombiList::implSetName( sal_Int64 nKey
, const OUString
& rName
)
1155 if( (nKey
& (nKey
- 1)) != 0 ) // more than a single bit set?
1157 typedef ::std::set
< ExtItemFormatKey
> ExtItemFormatKeySet
;
1158 ::std::set
< ExtItemFormatKey
> aItemKeys
;
1159 ExtItemFormat aItemFmt
;
1160 OUStringVector aRemain
= aItemFmt
.parse( rName
);
1161 for( OUStringVector::iterator aIt
= aRemain
.begin(), aEnd
= aRemain
.end(); aIt
!= aEnd
; ++aIt
)
1163 OUStringPair aPair
= StringHelper::convertStringToPair( *aIt
);
1164 if ( aPair
.first
== "noshift" )
1166 aItemFmt
.mbShiftValue
= StringHelper::convertStringToBool( aPair
.second
);
1168 else if ( aPair
.first
== "filter" )
1170 OUStringPair aFilter
= StringHelper::convertStringToPair( aPair
.second
, '~' );
1171 ExtItemFormatKey
aKey( nKey
);
1172 if( !aFilter
.first
.isEmpty() && StringHelper::convertStringToInt( aKey
.maFilter
.first
, aFilter
.first
) &&
1173 !aFilter
.second
.isEmpty() && StringHelper::convertStringToInt( aKey
.maFilter
.second
, aFilter
.second
) )
1175 if( aKey
.maFilter
.first
== 0 )
1176 aKey
.maFilter
.second
= 0;
1177 aItemKeys
.insert( aKey
);
1181 if( aItemKeys
.empty() )
1182 aItemKeys
.insert( ExtItemFormatKey( nKey
) );
1183 for( ExtItemFormatKeySet::iterator aIt
= aItemKeys
.begin(), aEnd
= aItemKeys
.end(); aIt
!= aEnd
; ++aIt
)
1184 maFmtMap
[ *aIt
] = aItemFmt
;
1188 FlagsList::implSetName( nKey
, rName
);
1192 OUString
CombiList::implGetName( const Config
& rCfg
, sal_Int64 nKey
) const
1194 sal_Int64 nFound
= 0;
1195 OUStringBuffer aName
;
1196 // add known flag fields
1197 for( ExtItemFormatMap::const_iterator aIt
= maFmtMap
.begin(), aEnd
= maFmtMap
.end(); aIt
!= aEnd
; ++aIt
)
1199 const ExtItemFormatKey
& rMapKey
= aIt
->first
;
1200 sal_Int64 nMask
= rMapKey
.mnKey
;
1201 if( (nMask
!= 0) && ((nKey
& rMapKey
.maFilter
.first
) == rMapKey
.maFilter
.second
) )
1203 const ExtItemFormat
& rItemFmt
= aIt
->second
;
1205 sal_uInt64 nUFlags
= static_cast< sal_uInt64
>( nKey
);
1206 sal_uInt64 nUMask
= static_cast< sal_uInt64
>( nMask
);
1207 if( rItemFmt
.mbShiftValue
)
1208 while( (nUMask
& 1) == 0 ) { nUFlags
>>= 1; nUMask
>>= 1; }
1210 sal_uInt64 nUValue
= nUFlags
& nUMask
;
1211 sal_Int64 nSValue
= static_cast< sal_Int64
>( nUValue
);
1212 if( getFlag
< sal_uInt64
>( nUValue
, (nUMask
+ 1) >> 1 ) )
1213 setFlag( nSValue
, static_cast< sal_Int64
>( ~nUMask
) );
1215 OUStringBuffer
aItem( rItemFmt
.maItemName
);
1216 OUStringBuffer aValue
;
1217 switch( rItemFmt
.meDataType
)
1219 case DATATYPE_INT8
: StringHelper::appendValue( aValue
, static_cast< sal_Int8
>( nSValue
), rItemFmt
.meFmtType
); break;
1220 case DATATYPE_UINT8
: StringHelper::appendValue( aValue
, static_cast< sal_uInt8
>( nUValue
), rItemFmt
.meFmtType
); break;
1221 case DATATYPE_INT16
: StringHelper::appendValue( aValue
, static_cast< sal_Int16
>( nSValue
), rItemFmt
.meFmtType
); break;
1222 case DATATYPE_UINT16
: StringHelper::appendValue( aValue
, static_cast< sal_uInt16
>( nUValue
), rItemFmt
.meFmtType
); break;
1223 case DATATYPE_INT32
: StringHelper::appendValue( aValue
, static_cast< sal_Int32
>( nSValue
), rItemFmt
.meFmtType
); break;
1224 case DATATYPE_UINT32
: StringHelper::appendValue( aValue
, static_cast< sal_uInt32
>( nUValue
), rItemFmt
.meFmtType
); break;
1225 case DATATYPE_INT64
: StringHelper::appendValue( aValue
, nSValue
, rItemFmt
.meFmtType
); break;
1226 case DATATYPE_UINT64
: StringHelper::appendValue( aValue
, nUValue
, rItemFmt
.meFmtType
); break;
1227 case DATATYPE_FLOAT
: StringHelper::appendValue( aValue
, static_cast< float >( nSValue
), rItemFmt
.meFmtType
); break;
1228 case DATATYPE_DOUBLE
: StringHelper::appendValue( aValue
, static_cast< double >( nSValue
), rItemFmt
.meFmtType
); break;
1231 StringHelper::appendToken( aItem
, aValue
.makeStringAndClear(), OOX_DUMP_ITEMSEP
);
1232 if( !rItemFmt
.maListName
.isEmpty() )
1234 OUString aValueName
= rCfg
.getName( rItemFmt
.maListName
, static_cast< sal_Int64
>( nUValue
) );
1235 StringHelper::appendToken( aItem
, aValueName
, OOX_DUMP_ITEMSEP
);
1237 StringHelper::enclose( aItem
, '(', ')' );
1238 StringHelper::appendToken( aName
, aItem
.makeStringAndClear() );
1239 setFlag( nFound
, nMask
);
1242 setFlag( nKey
, nFound
, false );
1243 StringHelper::appendToken( aName
, FlagsList::implGetName( rCfg
, nKey
) );
1244 return aName
.makeStringAndClear();
1247 void CombiList::implIncludeList( const NameListBase
& rList
)
1249 if( const CombiList
* pCombiList
= dynamic_cast< const CombiList
* >( &rList
) )
1250 maFmtMap
= pCombiList
->maFmtMap
;
1251 FlagsList::implIncludeList( rList
);
1254 // ============================================================================
1256 UnitConverter::UnitConverter( const SharedConfigData
& rCfgData
) :
1257 NameListBase( rCfgData
),
1262 void UnitConverter::implSetName( sal_Int64
/*nKey*/, const OUString
& /*rName*/ )
1267 OUString
UnitConverter::implGetName( const Config
& rCfg
, sal_Int64 nKey
) const
1269 return implGetNameDbl( rCfg
, static_cast< double >( nKey
) );
1272 OUString
UnitConverter::implGetNameDbl( const Config
& /*rCfg*/, double fValue
) const
1274 OUStringBuffer aValue
;
1275 StringHelper::appendDec( aValue
, mfFactor
* fValue
);
1276 aValue
.append( maUnitName
);
1277 return aValue
.makeStringAndClear();
1280 void UnitConverter::implIncludeList( const NameListBase
& /*rList*/ )
1284 // ============================================================================
1286 NameListRef
NameListWrapper::getNameList( const Config
& rCfg
) const
1288 return mxList
.get() ? mxList
: (mxList
= rCfg
.getNameList( maName
));
1291 // ============================================================================
1292 // ============================================================================
1294 SharedConfigData::SharedConfigData( const OUString
& rFileName
,
1295 const Reference
< XComponentContext
>& rxContext
, const StorageRef
& rxRootStrg
,
1296 const OUString
& rSysFileName
) :
1297 mxContext( rxContext
),
1298 mxRootStrg( rxRootStrg
),
1299 maSysFileName( rSysFileName
),
1301 mbPwCancelled( false )
1303 OUString aFileUrl
= InputOutputHelper::convertFileNameToUrl( rFileName
);
1304 if( !aFileUrl
.isEmpty() )
1306 sal_Int32 nNamePos
= InputOutputHelper::getFileNamePos( aFileUrl
);
1307 maConfigPath
= aFileUrl
.copy( 0, nNamePos
);
1308 mbLoaded
= readConfigFile( aFileUrl
);
1312 SharedConfigData::~SharedConfigData()
1316 void SharedConfigData::setOption( const OUString
& rKey
, const OUString
& rData
)
1318 maConfigData
[ rKey
] = rData
;
1321 const OUString
* SharedConfigData::getOption( const OUString
& rKey
) const
1323 ConfigDataMap::const_iterator aIt
= maConfigData
.find( rKey
);
1324 return (aIt
== maConfigData
.end()) ? 0 : &aIt
->second
;
1327 void SharedConfigData::setNameList( const OUString
& rListName
, const NameListRef
& rxList
)
1329 if( !rListName
.isEmpty() )
1330 maNameLists
[ rListName
] = rxList
;
1333 void SharedConfigData::eraseNameList( const OUString
& rListName
)
1335 maNameLists
.erase( rListName
);
1338 NameListRef
SharedConfigData::getNameList( const OUString
& rListName
) const
1341 NameListMap::const_iterator aIt
= maNameLists
.find( rListName
);
1342 if( aIt
!= maNameLists
.end() )
1343 xList
= aIt
->second
;
1347 bool SharedConfigData::implIsValid() const
1349 return mbLoaded
&& mxContext
.is() && mxRootStrg
.get() && !maSysFileName
.isEmpty();
1352 void SharedConfigData::implProcessConfigItemStr(
1353 TextInputStream
& rStrm
, const OUString
& rKey
, const OUString
& rData
)
1355 if ( rKey
== "include-config-file" )
1356 readConfigFile( maConfigPath
+ rData
);
1357 else if ( rKey
== "constlist" )
1358 readNameList
< ConstList
>( rStrm
, rData
);
1359 else if ( rKey
== "multilist" )
1360 readNameList
< MultiList
>( rStrm
, rData
);
1361 else if ( rKey
== "flagslist" )
1362 readNameList
< FlagsList
>( rStrm
, rData
);
1363 else if ( rKey
== "combilist" )
1364 readNameList
< CombiList
>( rStrm
, rData
);
1365 else if ( rKey
== "shortlist" )
1366 createShortList( rData
);
1367 else if ( rKey
== "unitconverter" )
1368 createUnitConverter( rData
);
1370 setOption( rKey
, rData
);
1373 bool SharedConfigData::readConfigFile( const OUString
& rFileUrl
)
1375 bool bLoaded
= maConfigFiles
.count( rFileUrl
) > 0;
1378 Reference
< XInputStream
> xInStrm
= InputOutputHelper::openInputStream( mxContext
, rFileUrl
);
1379 TextInputStream
aTxtStrm( mxContext
, xInStrm
, RTL_TEXTENCODING_UTF8
);
1380 if( !aTxtStrm
.isEof() )
1382 maConfigFiles
.insert( rFileUrl
);
1383 readConfigBlockContents( aTxtStrm
);
1390 void SharedConfigData::createShortList( const OUString
& rData
)
1392 OUStringVector aDataVec
;
1393 StringHelper::convertStringToStringList( aDataVec
, rData
, false );
1394 if( aDataVec
.size() >= 3 )
1396 sal_Int64 nStartKey
;
1397 if( StringHelper::convertStringToInt( nStartKey
, aDataVec
[ 1 ] ) )
1399 ::boost::shared_ptr
< MultiList
> xList
= createNameList
< MultiList
>( aDataVec
[ 0 ] );
1402 aDataVec
.erase( aDataVec
.begin(), aDataVec
.begin() + 2 );
1403 xList
->setNamesFromVec( nStartKey
, aDataVec
);
1409 void SharedConfigData::createUnitConverter( const OUString
& rData
)
1411 OUStringVector aDataVec
;
1412 StringHelper::convertStringToStringList( aDataVec
, rData
, false );
1413 if( aDataVec
.size() >= 2 )
1415 OUString aFactor
= aDataVec
[ 1 ];
1416 bool bRecip
= !aFactor
.isEmpty() && aFactor
[ 0 ] == '/';
1418 aFactor
= aFactor
.copy( 1 );
1420 if( StringHelper::convertStringToDouble( fFactor
, aFactor
) && (fFactor
!= 0.0) )
1422 ::boost::shared_ptr
< UnitConverter
> xList
= createNameList
< UnitConverter
>( aDataVec
[ 0 ] );
1425 xList
->setFactor( bRecip
? (1.0 / fFactor
) : fFactor
);
1426 if( aDataVec
.size() >= 3 )
1427 xList
->setUnitName( aDataVec
[ 2 ] );
1433 // ============================================================================
1435 Config::Config( const Config
& rParent
) :
1436 Base() // c'tor needs to be called explicitly to avoid compiler warning
1438 construct( rParent
);
1441 Config::Config( const sal_Char
* pcEnvVar
, const FilterBase
& rFilter
)
1443 construct( pcEnvVar
, rFilter
);
1446 Config::Config( const sal_Char
* pcEnvVar
, const Reference
< XComponentContext
>& rxContext
, const StorageRef
& rxRootStrg
, const OUString
& rSysFileName
)
1448 construct( pcEnvVar
, rxContext
, rxRootStrg
, rSysFileName
);
1455 void Config::construct( const Config
& rParent
)
1460 void Config::construct( const sal_Char
* pcEnvVar
, const FilterBase
& rFilter
)
1462 if( !rFilter
.getFileUrl().isEmpty() )
1463 construct( pcEnvVar
, rFilter
.getComponentContext(), rFilter
.getStorage(), rFilter
.getFileUrl() );
1466 void Config::construct( const sal_Char
* pcEnvVar
, const Reference
< XComponentContext
>& rxContext
, const StorageRef
& rxRootStrg
, const OUString
& rSysFileName
)
1468 if( pcEnvVar
&& rxRootStrg
.get() && !rSysFileName
.isEmpty() )
1469 if( const sal_Char
* pcFileName
= ::getenv( pcEnvVar
) )
1470 mxCfgData
.reset( new SharedConfigData( OUString::createFromAscii( pcFileName
), rxContext
, rxRootStrg
, rSysFileName
) );
1473 const OUString
& Config::getStringOption( const String
& rKey
, const OUString
& rDefault
) const
1475 const OUString
* pData
= implGetOption( rKey
);
1476 return pData
? *pData
: rDefault
;
1479 bool Config::getBoolOption( const String
& rKey
, bool bDefault
) const
1481 const OUString
* pData
= implGetOption( rKey
);
1482 return pData
? StringHelper::convertStringToBool( *pData
) : bDefault
;
1485 bool Config::isDumperEnabled() const
1487 return getBoolOption( "enable-dumper", false );
1490 bool Config::isImportEnabled() const
1492 return getBoolOption( "enable-import", true );
1495 void Config::eraseNameList( const String
& rListName
)
1497 mxCfgData
->eraseNameList( rListName
);
1500 NameListRef
Config::getNameList( const String
& rListName
) const
1502 return implGetNameList( rListName
);
1505 bool Config::isPasswordCancelled() const
1507 return mxCfgData
->isPasswordCancelled();
1510 bool Config::implIsValid() const
1512 return isValid( mxCfgData
);
1515 const OUString
* Config::implGetOption( const OUString
& rKey
) const
1517 return mxCfgData
->getOption( rKey
);
1520 NameListRef
Config::implGetNameList( const OUString
& rListName
) const
1522 return mxCfgData
->getNameList( rListName
);
1525 // ============================================================================
1526 // ============================================================================
1528 Output::Output( const Reference
< XComponentContext
>& rxContext
, const OUString
& rFileName
) :
1529 mxStrm( InputOutputHelper::openTextOutputStream( rxContext
, rFileName
, RTL_TEXTENCODING_UTF8
) ),
1537 mxStrm
->writeString( OUString( OOX_DUMP_BOM
) );
1540 // ----------------------------------------------------------------------------
1542 void Output::newLine()
1544 if( maLine
.getLength() > 0 )
1546 mxStrm
->writeString( maIndent
);
1547 maLine
.append( sal_Unicode( '\n' ) );
1548 mxStrm
->writeString( maLine
.makeStringAndClear() );
1554 void Output::emptyLine( size_t nCount
)
1556 for( size_t nIdx
= 0; nIdx
< nCount
; ++nIdx
)
1557 mxStrm
->writeString( OUString( sal_Unicode( '\n' ) ) );
1560 void Output::incIndent()
1562 OUStringBuffer
aBuffer( maIndent
);
1563 StringHelper::appendChar( aBuffer
, ' ', OOX_DUMP_INDENT
);
1564 maIndent
= aBuffer
.makeStringAndClear();
1567 void Output::decIndent()
1569 if( maIndent
.getLength() >= OOX_DUMP_INDENT
)
1570 maIndent
= maIndent
.copy( OOX_DUMP_INDENT
);
1573 void Output::startTable( sal_Int32 nW1
)
1575 startTable( 1, &nW1
);
1578 void Output::startTable( sal_Int32 nW1
, sal_Int32 nW2
)
1580 sal_Int32 pnColWidths
[ 2 ];
1581 pnColWidths
[ 0 ] = nW1
;
1582 pnColWidths
[ 1 ] = nW2
;
1583 startTable( 2, pnColWidths
);
1586 void Output::startTable( sal_Int32 nW1
, sal_Int32 nW2
, sal_Int32 nW3
, sal_Int32 nW4
)
1588 sal_Int32 pnColWidths
[ 4 ];
1589 pnColWidths
[ 0 ] = nW1
;
1590 pnColWidths
[ 1 ] = nW2
;
1591 pnColWidths
[ 2 ] = nW3
;
1592 pnColWidths
[ 3 ] = nW4
;
1593 startTable( 4, pnColWidths
);
1596 void Output::startTable( size_t nColCount
, const sal_Int32
* pnColWidths
)
1599 maColPos
.push_back( 0 );
1600 sal_Int32 nColPos
= 0;
1601 for( size_t nCol
= 0; nCol
< nColCount
; ++nCol
)
1603 nColPos
= nColPos
+ pnColWidths
[ nCol
];
1604 maColPos
.push_back( nColPos
);
1613 void Output::tab( size_t nCol
)
1616 if( mnCol
< maColPos
.size() )
1618 sal_Int32 nColPos
= maColPos
[ mnCol
];
1619 if( maLine
.getLength() >= nColPos
)
1620 maLine
.setLength( ::std::max
< sal_Int32
>( nColPos
- 1, 0 ) );
1621 StringHelper::appendChar( maLine
, ' ', nColPos
- maLine
.getLength() );
1625 StringHelper::appendChar( maLine
, ' ', 2 );
1629 void Output::endTable()
1634 void Output::resetItemIndex( sal_Int64 nIdx
)
1639 void Output::startItem( const String
& rItemName
)
1641 if( mnItemLevel
== 0 )
1643 if( (mnMultiLevel
> 0) && (maLine
.getLength() > 0) )
1645 if( rItemName
.has() )
1647 writeItemName( rItemName
);
1648 writeChar( OOX_DUMP_ITEMSEP
);
1652 mnLastItem
= maLine
.getLength();
1655 void Output::contItem()
1657 if( mnItemLevel
> 0 )
1659 if( (maLine
.getLength() == 0) || (maLine
[ maLine
.getLength() - 1 ] != OOX_DUMP_ITEMSEP
) )
1660 writeChar( OOX_DUMP_ITEMSEP
);
1661 mnLastItem
= maLine
.getLength();
1665 void Output::endItem()
1667 if( mnItemLevel
> 0 )
1669 maLastItem
= OUString( maLine
.getStr() + mnLastItem
);
1670 if( maLastItem
.isEmpty() && mnLastItem
> 0 && maLine
[ mnLastItem
- 1 ] == OOX_DUMP_ITEMSEP
)
1671 maLine
.setLength( mnLastItem
- 1 );
1674 if( mnItemLevel
== 0 )
1676 if( mnMultiLevel
== 0 )
1683 void Output::startMultiItems()
1688 void Output::endMultiItems()
1690 if( mnMultiLevel
> 0 )
1692 if( mnMultiLevel
== 0 )
1696 // ----------------------------------------------------------------------------
1698 void Output::writeChar( sal_Unicode cChar
, sal_Int32 nCount
)
1700 StringHelper::appendEncChar( maLine
, cChar
, nCount
);
1703 void Output::writeAscii( const sal_Char
* pcStr
)
1706 maLine
.appendAscii( pcStr
);
1709 void Output::writeString( const OUString
& rStr
)
1711 StringHelper::appendEncString( maLine
, rStr
);
1714 void Output::writeArray( const sal_uInt8
* pnData
, sal_Size nSize
, sal_Unicode cSep
)
1716 const sal_uInt8
* pnEnd
= pnData
? (pnData
+ nSize
) : 0;
1717 for( const sal_uInt8
* pnByte
= pnData
; pnByte
< pnEnd
; ++pnByte
)
1719 if( pnByte
> pnData
)
1721 writeHex( *pnByte
, false );
1725 void Output::writeBool( bool bData
)
1727 StringHelper::appendBool( maLine
, bData
);
1730 void Output::writeDateTime( const util::DateTime
& rDateTime
)
1732 writeDec( rDateTime
.Year
, 4, '0' );
1734 writeDec( rDateTime
.Month
, 2, '0' );
1736 writeDec( rDateTime
.Day
, 2, '0' );
1738 writeDec( rDateTime
.Hours
, 2, '0' );
1740 writeDec( rDateTime
.Minutes
, 2, '0' );
1742 writeDec( rDateTime
.Seconds
, 2, '0' );
1745 // ----------------------------------------------------------------------------
1747 bool Output::implIsValid() const
1752 void Output::writeItemName( const String
& rItemName
)
1754 if( rItemName
.has() && (rItemName
[ 0 ] == '#') )
1756 writeString( rItemName
.copy( 1 ) );
1757 StringHelper::appendIndex( maLine
, mnItemIdx
++ );
1760 writeString( rItemName
);
1763 // ============================================================================
1765 StorageIterator::StorageIterator( const StorageRef
& rxStrg
) :
1769 mxStrg
->getElementNames( maNames
);
1770 maIt
= maNames
.begin();
1773 StorageIterator::~StorageIterator()
1777 StorageIterator
& StorageIterator::operator++()
1779 if( maIt
!= maNames
.end() )
1784 OUString
StorageIterator::getName() const
1787 if( maIt
!= maNames
.end() )
1792 bool StorageIterator::isStream() const
1794 return isValid() && mxStrg
->openInputStream( *maIt
).is();
1797 bool StorageIterator::isStorage() const
1801 StorageRef xStrg
= mxStrg
->openSubStorage( *maIt
, false );
1802 return xStrg
.get() && xStrg
->isStorage();
1805 bool StorageIterator::implIsValid() const
1807 return mxStrg
.get() && mxStrg
->isStorage() && (maIt
!= maNames
.end());
1810 // ============================================================================
1811 // ============================================================================
1813 ObjectBase::~ObjectBase()
1817 void ObjectBase::construct( const ConfigRef
& rxConfig
)
1819 mxConfig
= rxConfig
;
1822 void ObjectBase::construct( const ObjectBase
& rParent
)
1827 void ObjectBase::dump()
1833 bool ObjectBase::implIsValid() const
1835 return isValid( mxConfig
);
1838 void ObjectBase::implDump()
1842 // ============================================================================
1843 // ============================================================================
1845 void StorageObjectBase::construct( const ObjectBase
& rParent
, const StorageRef
& rxStrg
, const OUString
& rSysPath
)
1847 ObjectBase::construct( rParent
);
1849 maSysPath
= rSysPath
;
1852 void StorageObjectBase::construct( const ObjectBase
& rParent
)
1854 ObjectBase::construct( rParent
);
1855 if( ObjectBase::implIsValid() )
1857 mxStrg
= cfg().getRootStorage();
1858 maSysPath
= cfg().getSysFileName();
1862 bool StorageObjectBase::implIsValid() const
1864 return mxStrg
.get() && !maSysPath
.isEmpty() && ObjectBase::implIsValid();
1867 void StorageObjectBase::implDump()
1869 bool bIsStrg
= mxStrg
->isStorage();
1870 bool bIsRoot
= mxStrg
->isRootStorage();
1871 Reference
< XInputStream
> xBaseStrm
;
1873 xBaseStrm
= mxStrg
->openInputStream( OUString() );
1875 OUString aSysOutPath
= maSysPath
;
1878 aSysOutPath
+= OOX_DUMP_DUMPEXT
;
1879 Reference
<XSimpleFileAccess3
> xFileAccess(SimpleFileAccess::create(getContext()));
1880 xFileAccess
->kill( aSysOutPath
);
1888 extractStorage( mxStrg
, OUString(), aSysOutPath
);
1890 else if( xBaseStrm
.is() )
1892 BinaryInputStreamRef
xInStrm( new BinaryXInputStream( xBaseStrm
, false ) );
1893 xInStrm
->seekToStart();
1894 implDumpBaseStream( xInStrm
, aSysOutPath
);
1898 void StorageObjectBase::implDumpStream( const Reference
< XInputStream
>&, const OUString
&, const OUString
&, const OUString
& )
1902 void StorageObjectBase::implDumpStorage( const StorageRef
& rxStrg
, const OUString
& rStrgPath
, const OUString
& rSysPath
)
1904 extractStorage( rxStrg
, rStrgPath
, rSysPath
);
1907 void StorageObjectBase::implDumpBaseStream( const BinaryInputStreamRef
&, const OUString
& )
1911 void StorageObjectBase::addPreferredStream( const String
& rStrmName
)
1913 if( rStrmName
.has() )
1914 maPreferred
.push_back( PreferredItem( rStrmName
, false ) );
1917 void StorageObjectBase::addPreferredStorage( const String
& rStrgPath
)
1919 if( rStrgPath
.has() )
1920 maPreferred
.push_back( PreferredItem( rStrgPath
, true ) );
1923 OUString
StorageObjectBase::getSysFileName( const OUString
& rStrmName
, const OUString
& rSysOutPath
)
1925 // encode all characters < 0x20
1926 OUStringBuffer aBuffer
;
1927 StringHelper::appendEncString( aBuffer
, rStrmName
, false );
1929 // replace all characters reserved in file system
1930 OUString aFileName
= aBuffer
.makeStringAndClear();
1931 static const sal_Unicode spcReserved
[] = { '/', '\\', ':', '*', '?', '<', '>', '|' };
1932 for( const sal_Unicode
* pcChar
= spcReserved
; pcChar
< STATIC_ARRAY_END( spcReserved
); ++pcChar
)
1933 aFileName
= aFileName
.replace( *pcChar
, '_' );
1936 return rSysOutPath
+ OUString( sal_Unicode( '/' ) ) + aFileName
;
1939 void StorageObjectBase::extractStream( StorageBase
& rStrg
, const OUString
& rStrgPath
, const OUString
& rStrmName
, const OUString
& rSysFileName
)
1941 BinaryXInputStream
aInStrm( rStrg
.openInputStream( rStrmName
), true );
1942 if( !aInStrm
.isEof() )
1944 BinaryXOutputStream
aOutStrm( InputOutputHelper::openOutputStream( getContext(), rSysFileName
), true );
1945 if( !aOutStrm
.isEof() )
1946 aInStrm
.copyToStream( aOutStrm
);
1948 Reference
< XInputStream
> xDumpStrm
= InputOutputHelper::openInputStream( getContext(), rSysFileName
);
1949 if( xDumpStrm
.is() )
1950 implDumpStream( xDumpStrm
, rStrgPath
, rStrmName
, rSysFileName
);
1953 void StorageObjectBase::extractStorage( const StorageRef
& rxStrg
, const OUString
& rStrgPath
, const OUString
& rSysPath
)
1955 // create directory in file system
1956 ::osl::FileBase::RC eRes
= ::osl::Directory::create( rSysPath
);
1957 if( (eRes
!= ::osl::FileBase::E_None
) && (eRes
!= ::osl::FileBase::E_EXIST
) )
1960 // process preferred storages and streams in root storage first
1961 if( rStrgPath
.isEmpty() )
1962 for( PreferredItemVector::iterator aIt
= maPreferred
.begin(), aEnd
= maPreferred
.end(); aIt
!= aEnd
; ++aIt
)
1963 extractItem( rxStrg
, rStrgPath
, aIt
->maName
, rSysPath
, aIt
->mbStorage
, !aIt
->mbStorage
);
1965 // process children of the storage
1966 for( StorageIterator
aIt( rxStrg
); aIt
.isValid(); ++aIt
)
1968 // skip processed preferred items
1969 OUString aItemName
= aIt
.getName();
1970 bool bFound
= false;
1971 if( rStrgPath
.isEmpty() )
1972 for( PreferredItemVector::iterator aIIt
= maPreferred
.begin(), aIEnd
= maPreferred
.end(); !bFound
&& (aIIt
!= aIEnd
); ++aIIt
)
1973 bFound
= aIIt
->maName
== aItemName
;
1975 extractItem( rxStrg
, rStrgPath
, aItemName
, rSysPath
, aIt
.isStorage(), aIt
.isStream() );
1979 void StorageObjectBase::extractItem( const StorageRef
& rxStrg
, const OUString
& rStrgPath
, const OUString
& rItemName
, const OUString
& rSysPath
, bool bIsStrg
, bool bIsStrm
)
1981 OUString aSysFileName
= getSysFileName( rItemName
, rSysPath
);
1984 OUStringBuffer
aStrgPath( rStrgPath
);
1985 StringHelper::appendToken( aStrgPath
, rItemName
, '/' );
1986 implDumpStorage( rxStrg
->openSubStorage( rItemName
, false ), aStrgPath
.makeStringAndClear(), aSysFileName
);
1990 extractStream( *rxStrg
, rStrgPath
, rItemName
, aSysFileName
);
1994 // ============================================================================
1995 // ============================================================================
1997 OutputObjectBase::~OutputObjectBase()
2001 void OutputObjectBase::construct( const ObjectBase
& rParent
, const OUString
& rSysFileName
)
2003 ObjectBase::construct( rParent
);
2004 if( ObjectBase::implIsValid() )
2006 maSysFileName
= rSysFileName
;
2007 mxOut
.reset( new Output( getContext(), rSysFileName
+ OOX_DUMP_DUMPEXT
) );
2011 void OutputObjectBase::construct( const OutputObjectBase
& rParent
)
2016 bool OutputObjectBase::implIsValid() const
2018 return isValid( mxOut
) && ObjectBase::implIsValid();
2021 void OutputObjectBase::writeEmptyItem( const String
& rName
)
2023 ItemGuard
aItem( mxOut
, rName
);
2026 void OutputObjectBase::writeInfoItem( const String
& rName
, const String
& rData
)
2028 ItemGuard
aItem( mxOut
, rName
);
2029 mxOut
->writeString( rData
);
2032 void OutputObjectBase::writeCharItem( const String
& rName
, sal_Unicode cData
)
2034 ItemGuard
aItem( mxOut
, rName
);
2035 mxOut
->writeChar( OOX_DUMP_STRQUOTE
);
2036 mxOut
->writeChar( cData
);
2037 mxOut
->writeChar( OOX_DUMP_STRQUOTE
);
2040 void OutputObjectBase::writeStringItem( const String
& rName
, const OUString
& rData
)
2042 ItemGuard
aItem( mxOut
, rName
);
2043 mxOut
->writeAscii( "(len=" );
2044 mxOut
->writeDec( rData
.getLength() );
2045 mxOut
->writeAscii( ")," );
2046 OUStringBuffer
aValue( rData
.copy( 0, ::std::min( rData
.getLength(), OOX_DUMP_MAXSTRLEN
) ) );
2047 StringHelper::enclose( aValue
, OOX_DUMP_STRQUOTE
);
2048 mxOut
->writeString( aValue
.makeStringAndClear() );
2049 if( rData
.getLength() > OOX_DUMP_MAXSTRLEN
)
2050 mxOut
->writeAscii( ",cut" );
2053 void OutputObjectBase::writeArrayItem( const String
& rName
, const sal_uInt8
* pnData
, sal_Size nSize
, sal_Unicode cSep
)
2055 ItemGuard
aItem( mxOut
, rName
);
2056 mxOut
->writeArray( pnData
, nSize
, cSep
);
2059 void OutputObjectBase::writeDateTimeItem( const String
& rName
, const util::DateTime
& rDateTime
)
2061 ItemGuard
aItem( mxOut
, rName
);
2062 mxOut
->writeDateTime( rDateTime
);
2065 void OutputObjectBase::writeGuidItem( const String
& rName
, const OUString
& rGuid
)
2067 ItemGuard
aItem( mxOut
, rName
);
2068 mxOut
->writeString( rGuid
);
2070 mxOut
->writeString( cfg().getStringOption( rGuid
, OUString() ) );
2073 // ============================================================================
2074 // ============================================================================
2076 InputObjectBase::~InputObjectBase()
2080 void InputObjectBase::construct( const ObjectBase
& rParent
, const BinaryInputStreamRef
& rxStrm
, const OUString
& rSysFileName
)
2082 OutputObjectBase::construct( rParent
, rSysFileName
);
2086 void InputObjectBase::construct( const OutputObjectBase
& rParent
, const BinaryInputStreamRef
& rxStrm
)
2088 OutputObjectBase::construct( rParent
);
2092 void InputObjectBase::construct( const InputObjectBase
& rParent
)
2097 bool InputObjectBase::implIsValid() const
2099 return mxStrm
.get() && OutputObjectBase::implIsValid();
2102 void InputObjectBase::skipBlock( sal_Int64 nBytes
, bool bShowSize
)
2104 sal_Int64 nEndPos
= ::std::min
< sal_Int64
>( mxStrm
->tell() + nBytes
, mxStrm
->size() );
2105 if( mxStrm
->tell() < nEndPos
)
2108 writeDecItem( "skipped-data-size", static_cast< sal_uInt64
>( nEndPos
- mxStrm
->tell() ) );
2109 mxStrm
->seek( nEndPos
);
2113 void InputObjectBase::dumpRawBinary( sal_Int64 nBytes
, bool bShowOffset
, bool bStream
)
2115 TableGuard
aTabGuard( mxOut
,
2116 bShowOffset
? 12 : 0,
2117 3 * OOX_DUMP_BYTESPERLINE
/ 2 + 1,
2118 3 * OOX_DUMP_BYTESPERLINE
/ 2 + 1,
2119 OOX_DUMP_BYTESPERLINE
/ 2 + 1 );
2121 sal_Int64 nMaxShowSize
= cfg().getIntOption
< sal_Int64
>(
2122 bStream
? "max-binary-stream-size" : "max-binary-data-size", SAL_MAX_INT64
);
2124 bool bSeekable
= mxStrm
->size() >= 0;
2125 sal_Int64 nEndPos
= bSeekable
? ::std::min
< sal_Int64
>( mxStrm
->tell() + nBytes
, mxStrm
->size() ) : 0;
2126 sal_Int64 nDumpEnd
= bSeekable
? ::std::min
< sal_Int64
>( mxStrm
->tell() + nMaxShowSize
, nEndPos
) : nMaxShowSize
;
2127 sal_Int64 nPos
= bSeekable
? mxStrm
->tell() : 0;
2130 while( bLoop
&& (nPos
< nDumpEnd
) )
2132 mxOut
->writeHex( static_cast< sal_uInt32
>( nPos
) );
2135 sal_uInt8 pnLineData
[ OOX_DUMP_BYTESPERLINE
];
2136 sal_Int32 nLineSize
= bSeekable
? ::std::min( static_cast< sal_Int32
>( nDumpEnd
- mxStrm
->tell() ), OOX_DUMP_BYTESPERLINE
) : OOX_DUMP_BYTESPERLINE
;
2137 sal_Int32 nReadSize
= mxStrm
->readMemory( pnLineData
, nLineSize
);
2138 bLoop
= nReadSize
== nLineSize
;
2143 const sal_uInt8
* pnByte
= 0;
2144 const sal_uInt8
* pnEnd
= 0;
2145 for( pnByte
= pnLineData
, pnEnd
= pnLineData
+ nReadSize
; pnByte
!= pnEnd
; ++pnByte
)
2147 if( (pnByte
- pnLineData
) == (OOX_DUMP_BYTESPERLINE
/ 2) ) mxOut
->tab();
2148 mxOut
->writeHex( *pnByte
, false );
2149 mxOut
->writeChar( ' ' );
2153 for( pnByte
= pnLineData
, pnEnd
= pnLineData
+ nReadSize
; pnByte
!= pnEnd
; ++pnByte
)
2155 if( (pnByte
- pnLineData
) == (OOX_DUMP_BYTESPERLINE
/ 2) ) mxOut
->tab();
2156 mxOut
->writeChar( static_cast< sal_Unicode
>( (*pnByte
< 0x20) ? '.' : *pnByte
) );
2162 // skip undumped data
2164 skipBlock( nEndPos
- mxStrm
->tell() );
2167 void InputObjectBase::dumpBinary( const String
& rName
, sal_Int64 nBytes
, bool bShowOffset
)
2170 MultiItemsGuard
aMultiGuard( mxOut
);
2171 writeEmptyItem( rName
);
2172 writeDecItem( "size", nBytes
);
2174 IndentGuard
aIndGuard( mxOut
);
2175 dumpRawBinary( nBytes
, bShowOffset
);
2178 void InputObjectBase::dumpRemaining( sal_Int64 nBytes
)
2182 if( cfg().getBoolOption( "show-trailing-unknown", true ) )
2183 dumpBinary( "remaining-data", nBytes
, false );
2185 skipBlock( nBytes
);
2189 void InputObjectBase::dumpRemainingTo( sal_Int64 nPos
)
2191 if( mxStrm
->isEof() || (mxStrm
->tell() > nPos
) )
2192 writeInfoItem( "stream-state", OOX_DUMP_ERR_STREAM
);
2194 dumpRemaining( nPos
- mxStrm
->tell() );
2195 mxStrm
->seek( nPos
);
2198 void InputObjectBase::dumpRemainingStream()
2200 dumpRemainingTo( mxStrm
->size() );
2203 void InputObjectBase::dumpArray( const String
& rName
, sal_Int32 nBytes
, sal_Unicode cSep
)
2205 sal_Int32 nDumpSize
= getLimitedValue
< sal_Int32
, sal_Int64
>( mxStrm
->size() - mxStrm
->tell(), 0, nBytes
);
2206 if( nDumpSize
> OOX_DUMP_MAXARRAY
)
2208 dumpBinary( rName
, nBytes
, false );
2210 else if( nDumpSize
> 1 )
2212 sal_uInt8 pnData
[ OOX_DUMP_MAXARRAY
];
2213 mxStrm
->readMemory( pnData
, nDumpSize
);
2214 writeArrayItem( rName
, pnData
, nDumpSize
, cSep
);
2216 else if( nDumpSize
== 1 )
2217 dumpHex
< sal_uInt8
>( rName
);
2220 sal_Unicode
InputObjectBase::dumpUnicode( const String
& rName
)
2224 sal_Unicode cChar
= static_cast< sal_Unicode
>( nChar
);
2225 writeCharItem( rName( "char" ), cChar
);
2229 OUString
InputObjectBase::dumpCharArray( const String
& rName
, sal_Int32 nLen
, rtl_TextEncoding eTextEnc
, bool bHideTrailingNul
)
2231 sal_Int32 nDumpSize
= getLimitedValue
< sal_Int32
, sal_Int64
>( mxStrm
->size() - mxStrm
->tell(), 0, nLen
);
2235 ::std::vector
< sal_Char
> aBuffer( static_cast< sal_Size
>( nLen
) + 1 );
2236 sal_Int32 nCharsRead
= mxStrm
->readMemory( &aBuffer
.front(), nLen
);
2237 aBuffer
[ nCharsRead
] = 0;
2238 aString
= OStringToOUString( OString( &aBuffer
.front() ), eTextEnc
);
2240 if( bHideTrailingNul
)
2241 aString
= StringHelper::trimTrailingNul( aString
);
2242 writeStringItem( rName( "text" ), aString
);
2246 OUString
InputObjectBase::dumpUnicodeArray( const String
& rName
, sal_Int32 nLen
, bool bHideTrailingNul
)
2248 OUStringBuffer aBuffer
;
2249 for( sal_Int32 nIndex
= 0; !mxStrm
->isEof() && (nIndex
< nLen
); ++nIndex
)
2250 aBuffer
.append( static_cast< sal_Unicode
>( mxStrm
->readuInt16() ) );
2251 OUString aString
= aBuffer
.makeStringAndClear();
2252 if( bHideTrailingNul
)
2253 aString
= StringHelper::trimTrailingNul( aString
);
2254 writeStringItem( rName( "text" ), aString
);
2258 util::DateTime
InputObjectBase::dumpFileTime( const String
& rName
)
2260 util::DateTime aDateTime
;
2262 ItemGuard
aItem( mxOut
, rName( "file-time" ) );
2263 sal_Int64 nFileTime
= dumpDec
< sal_Int64
>( EMPTY_STRING
);
2264 // file time is in 10^-7 seconds (100 nanoseconds), convert to nanoseconds
2267 sal_Int64 nDays
= nFileTime
/ sal_Int64( ::Time::nanoSecPerDay
);
2268 // number of entire years
2269 sal_Int64 nYears
= (nDays
- (nDays
/ (4 * 365)) + (nDays
/ (100 * 365)) - (nDays
/ (400 * 365))) / 365;
2270 // remaining days in the year
2271 sal_Int64 nDaysInYear
= nDays
- (nYears
* 365 + nYears
/ 4 - nYears
/ 100 + nYears
/ 400);
2272 // the year (file dates start from 1601-01-01)
2273 aDateTime
.Year
= static_cast< sal_uInt16
>( 1601 + nYears
);
2275 bool bLeap
= ((aDateTime
.Year
% 4 == 0) && (aDateTime
.Year
% 100 != 0)) || (aDateTime
.Year
% 400 == 0);
2276 // static arrays with number of days in month
2277 static const sal_Int64 spnDaysInMonth
[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
2278 static const sal_Int64 spnDaysInMonthL
[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
2279 const sal_Int64
* pnDaysInMonth
= bLeap
? spnDaysInMonthL
: spnDaysInMonth
;
2281 aDateTime
.Month
= 1;
2282 while( nDaysInYear
>= *pnDaysInMonth
)
2284 nDaysInYear
-= *pnDaysInMonth
++;
2288 aDateTime
.Day
= static_cast< sal_uInt16
>( nDaysInYear
+ 1 );
2289 // number of nanoseconds in the day
2290 sal_Int64 nTimeInDay
= nFileTime
% sal_Int64( ::Time::nanoSecPerDay
);
2292 aDateTime
.NanoSeconds
= static_cast< sal_uInt32
>( nTimeInDay
% ::Time::nanoSecPerSec
);
2293 nTimeInDay
/= ::Time::nanoSecPerSec
;
2295 aDateTime
.Seconds
= static_cast< sal_uInt16
>( nTimeInDay
% ::Time::secondPerMinute
);
2296 nTimeInDay
/= ::Time::secondPerMinute
;
2298 aDateTime
.Minutes
= static_cast< sal_uInt16
>( nTimeInDay
% ::Time::minutePerHour
);
2299 nTimeInDay
/= ::Time::minutePerHour
;
2301 aDateTime
.Hours
= static_cast< sal_uInt16
>( nTimeInDay
);
2303 writeDateTimeItem( EMPTY_STRING
, aDateTime
);
2307 OUString
InputObjectBase::dumpGuid( const String
& rName
)
2309 OUStringBuffer aBuffer
;
2315 StringHelper::appendHex( aBuffer
, nData32
, false );
2316 aBuffer
.append( sal_Unicode( '-' ) );
2318 StringHelper::appendHex( aBuffer
, nData16
, false );
2319 aBuffer
.append( sal_Unicode( '-' ) );
2321 StringHelper::appendHex( aBuffer
, nData16
, false );
2322 aBuffer
.append( sal_Unicode( '-' ) );
2324 StringHelper::appendHex( aBuffer
, nData8
, false );
2326 StringHelper::appendHex( aBuffer
, nData8
, false );
2327 aBuffer
.append( sal_Unicode( '-' ) );
2328 for( int nIndex
= 0; nIndex
< 6; ++nIndex
)
2331 StringHelper::appendHex( aBuffer
, nData8
, false );
2333 StringHelper::enclose( aBuffer
, '{', '}' );
2334 OUString aGuid
= aBuffer
.makeStringAndClear();
2335 writeGuidItem( rName( "guid" ), aGuid
);
2339 void InputObjectBase::dumpItem( const ItemFormat
& rItemFmt
)
2341 switch( rItemFmt
.meDataType
)
2343 case DATATYPE_VOID
: break;
2344 case DATATYPE_INT8
: dumpValue
< sal_Int8
>( rItemFmt
); break;
2345 case DATATYPE_UINT8
: dumpValue
< sal_uInt8
>( rItemFmt
); break;
2346 case DATATYPE_INT16
: dumpValue
< sal_Int16
>( rItemFmt
); break;
2347 case DATATYPE_UINT16
: dumpValue
< sal_uInt16
>( rItemFmt
); break;
2348 case DATATYPE_INT32
: dumpValue
< sal_Int32
>( rItemFmt
); break;
2349 case DATATYPE_UINT32
: dumpValue
< sal_uInt32
>( rItemFmt
); break;
2350 case DATATYPE_INT64
: dumpValue
< sal_Int64
>( rItemFmt
); break;
2351 case DATATYPE_UINT64
: dumpValue
< sal_uInt64
>( rItemFmt
); break;
2352 case DATATYPE_FLOAT
: dumpValue
< float >( rItemFmt
); break;
2353 case DATATYPE_DOUBLE
: dumpValue
< double >( rItemFmt
); break;
2358 // ============================================================================
2359 // ============================================================================
2361 BinaryStreamObject::BinaryStreamObject( const ObjectBase
& rParent
, const BinaryInputStreamRef
& rxStrm
, const OUString
& rSysFileName
)
2363 InputObjectBase::construct( rParent
, rxStrm
, rSysFileName
);
2366 void BinaryStreamObject::dumpBinaryStream( bool bShowOffset
)
2368 mxStrm
->seekToStart();
2369 dumpRawBinary( mxStrm
->size(), bShowOffset
, true );
2373 void BinaryStreamObject::implDump()
2378 // ============================================================================
2379 // ============================================================================
2381 void TextStreamObjectBase::construct( const ObjectBase
& rParent
,
2382 const BinaryInputStreamRef
& rxStrm
, rtl_TextEncoding eTextEnc
, const OUString
& rSysFileName
)
2384 InputObjectBase::construct( rParent
, rxStrm
, rSysFileName
);
2385 constructTextStrmObj( eTextEnc
);
2388 void TextStreamObjectBase::construct( const OutputObjectBase
& rParent
,
2389 const BinaryInputStreamRef
& rxStrm
, rtl_TextEncoding eTextEnc
)
2391 InputObjectBase::construct( rParent
, rxStrm
);
2392 constructTextStrmObj( eTextEnc
);
2395 bool TextStreamObjectBase::implIsValid() const
2397 return InputObjectBase::implIsValid() && mxTextStrm
.get();
2400 void TextStreamObjectBase::implDump()
2402 implDumpText( *mxTextStrm
);
2405 void TextStreamObjectBase::constructTextStrmObj( rtl_TextEncoding eTextEnc
)
2408 mxTextStrm
.reset( new TextInputStream( getContext(), *mxStrm
, eTextEnc
) );
2411 // ============================================================================
2413 TextLineStreamObject::TextLineStreamObject( const ObjectBase
& rParent
,
2414 const BinaryInputStreamRef
& rxStrm
, rtl_TextEncoding eTextEnc
, const OUString
& rSysFileName
)
2416 TextStreamObjectBase::construct( rParent
, rxStrm
, eTextEnc
, rSysFileName
);
2419 TextLineStreamObject::TextLineStreamObject( const OutputObjectBase
& rParent
,
2420 const BinaryInputStreamRef
& rxStrm
, rtl_TextEncoding eTextEnc
)
2422 TextStreamObjectBase::construct( rParent
, rxStrm
, eTextEnc
);
2425 void TextLineStreamObject::implDumpText( TextInputStream
& rTextStrm
)
2427 sal_uInt32 nLine
= 0;
2428 while( !rTextStrm
.isEof() )
2430 OUString aLine
= rTextStrm
.readLine();
2431 if( !rTextStrm
.isEof() || !aLine
.isEmpty() )
2432 implDumpLine( aLine
, ++nLine
);
2436 void TextLineStreamObject::implDumpLine( const OUString
& rLine
, sal_uInt32 nLine
)
2438 TableGuard
aTabGuard( mxOut
, 8 );
2439 mxOut
->writeDec( nLine
, 6 );
2441 mxOut
->writeString( rLine
);
2445 // ============================================================================
2447 XmlStreamObject::XmlStreamObject( const ObjectBase
& rParent
,
2448 const BinaryInputStreamRef
& rxStrm
, const OUString
& rSysFileName
)
2450 TextStreamObjectBase::construct( rParent
, rxStrm
, RTL_TEXTENCODING_UTF8
, rSysFileName
);
2453 void XmlStreamObject::implDumpText( TextInputStream
& rTextStrm
)
2455 /* Buffers a start element and the following element text. Needed to dump
2456 matching start/end elements and the element text on the same line. */
2457 OUStringBuffer aOldStartElem
;
2458 // special handling for VML
2459 bool bIsVml
= InputOutputHelper::getFileNameExtension( maSysFileName
).equalsIgnoreAsciiCase("vml");
2461 while( !rTextStrm
.isEof() )
2463 // get the next element and the following element text from text stream
2464 OUString aElem
= rTextStrm
.readToChar( '>', true ).trim();
2465 OUString aText
= rTextStrm
.readToChar( '<', false );
2467 // remove multiple whitespace from element
2469 while( nPos
< aElem
.getLength() )
2471 while( (nPos
< aElem
.getLength()) && (aElem
[ nPos
] >= 32) ) ++nPos
;
2472 if( nPos
< aElem
.getLength() )
2473 aElem
= OUStringBuffer( aElem
.copy( 0, nPos
) ).append( sal_Unicode( ' ' ) ).append( aElem
.copy( nPos
).trim() ).makeStringAndClear();
2477 sal_Int32 nElemLen
= aElem
.getLength();
2478 if( (nElemLen
>= 2) && (aElem
[ 0 ] == '<') && (aElem
[ nElemLen
- 1 ] == '>') )
2480 // determine type of the element
2481 bool bSimpleElem
= (aElem
[ 1 ] == '!') || (aElem
[ 1 ] == '?') || (aElem
[ nElemLen
- 2 ] == '/') ||
2482 (bIsVml
&& (nElemLen
== 4) && (aElem
[ 1 ] == 'b') && (aElem
[ 2 ] == 'r'));
2483 bool bStartElem
= !bSimpleElem
&& (aElem
[ 1 ] != '/');
2484 bool bEndElem
= !bSimpleElem
&& !bStartElem
;
2486 /* Start element or simple element: flush old start element and
2487 its text from previous iteration, and start a new indentation
2488 level for the new element. Trim whitespace and line breaks from
2489 the text of the old start element. */
2490 if( (bSimpleElem
|| bStartElem
) && (aOldStartElem
.getLength() > 0) )
2492 mxOut
->writeString( aOldStartElem
.makeStringAndClear().trim() );
2497 /* Start element: remember it and its text, to be able to print the
2498 matching end element on the same line in the next iteration. */
2501 aOldStartElem
.append( aElem
).append( aText
);
2505 /* End element: if a start element has been remembered in the
2506 previous iteration, write it out here untrimmed, to show
2507 all whitespace in the element text, and without trailing
2508 line break. Code below will add the end element right after
2509 it. Otherwise, return to previous indentation level. */
2512 if( aOldStartElem
.getLength() == 0 )
2515 mxOut
->writeString( aOldStartElem
.makeStringAndClear() );
2518 /* Write the element. Write following element text in a new
2519 line, but only, if it does not contain of white space
2521 mxOut
->writeString( aElem
);
2523 if( !aText
.trim().isEmpty() )
2525 mxOut
->writeString( aText
);
2533 // ============================================================================
2534 // ============================================================================
2536 void RecordObjectBase::construct( const ObjectBase
& rParent
,
2537 const BinaryInputStreamRef
& rxBaseStrm
, const OUString
& rSysFileName
,
2538 const BinaryInputStreamRef
& rxRecStrm
, const String
& rRecNames
, const String
& rSimpleRecs
)
2540 InputObjectBase::construct( rParent
, rxRecStrm
, rSysFileName
);
2541 constructRecObjBase( rxBaseStrm
, rRecNames
, rSimpleRecs
);
2544 bool RecordObjectBase::implIsValid() const
2546 return mxBaseStrm
.get() && InputObjectBase::implIsValid();
2549 void RecordObjectBase::implDump()
2551 NameListRef xRecNames
= getRecNames();
2552 ItemFormatMap
aSimpleRecs( maSimpleRecs
.getNameList( cfg() ) );
2554 while( implStartRecord( *mxBaseStrm
, mnRecPos
, mnRecId
, mnRecSize
) )
2559 implWriteExtHeader();
2560 IndentGuard
aIndGuard( mxOut
);
2561 sal_Int64 nRecPos
= mxStrm
->tell();
2564 if( !mbBinaryOnly
&& cfg().hasName( xRecNames
, mnRecId
) )
2566 ItemFormatMap::const_iterator aIt
= aSimpleRecs
.find( mnRecId
);
2567 if( aIt
!= aSimpleRecs
.end() )
2568 dumpItem( aIt
->second
);
2570 implDumpRecordBody();
2573 // remaining undumped data
2574 if( !mxStrm
->isEof() && (mxStrm
->tell() == nRecPos
) )
2575 dumpRawBinary( mnRecSize
, false );
2577 dumpRemainingTo( nRecPos
+ mnRecSize
);
2581 void RecordObjectBase::implWriteExtHeader()
2585 void RecordObjectBase::implDumpRecordBody()
2589 void RecordObjectBase::constructRecObjBase( const BinaryInputStreamRef
& rxBaseStrm
, const String
& rRecNames
, const String
& rSimpleRecs
)
2591 mxBaseStrm
= rxBaseStrm
;
2592 maRecNames
= rRecNames
;
2593 maSimpleRecs
= rSimpleRecs
;
2594 mnRecPos
= mnRecId
= mnRecSize
= 0;
2595 mbBinaryOnly
= false;
2596 if( InputObjectBase::implIsValid() )
2597 mbShowRecPos
= cfg().getBoolOption( "show-record-position", true );
2600 void RecordObjectBase::writeHeader()
2602 MultiItemsGuard
aMultiGuard( mxOut
);
2603 writeEmptyItem( "REC" );
2604 if( mbShowRecPos
&& mxBaseStrm
->isSeekable() )
2605 writeShortHexItem( "pos", mnRecPos
, "CONV-DEC" );
2606 writeShortHexItem( "size", mnRecSize
, "CONV-DEC" );
2607 ItemGuard
aItem( mxOut
, "id" );
2608 mxOut
->writeShortHex( mnRecId
);
2609 addNameToItem( mnRecId
, "CONV-DEC" );
2610 addNameToItem( mnRecId
, maRecNames
);
2613 // ============================================================================
2615 void SequenceRecordObjectBase::construct( const ObjectBase
& rParent
,
2616 const BinaryInputStreamRef
& rxBaseStrm
, const OUString
& rSysFileName
,
2617 const String
& rRecNames
, const String
& rSimpleRecs
)
2619 BinaryInputStreamRef
xRecStrm( new SequenceInputStream( *mxRecData
) );
2620 RecordObjectBase::construct( rParent
, rxBaseStrm
, rSysFileName
, xRecStrm
, rRecNames
, rSimpleRecs
);
2623 bool SequenceRecordObjectBase::implStartRecord( BinaryInputStream
& rBaseStrm
, sal_Int64
& ornRecPos
, sal_Int64
& ornRecId
, sal_Int64
& ornRecSize
)
2626 if( rBaseStrm
.isSeekable() )
2628 ornRecPos
= rBaseStrm
.tell();
2629 // do not try to overread seekable streams, may cause assertions
2630 bValid
= ornRecPos
< rBaseStrm
.size();
2633 // read the record header
2635 bValid
= implReadRecordHeader( rBaseStrm
, ornRecId
, ornRecSize
) && !rBaseStrm
.isEof() && (0 <= ornRecSize
) && (ornRecSize
<= 0x00100000);
2637 // read record contents into data sequence
2640 sal_Int32 nRecSize
= static_cast< sal_Int32
>( ornRecSize
);
2641 mxRecData
->realloc( nRecSize
);
2642 bValid
= (nRecSize
== 0) || (rBaseStrm
.readData( *mxRecData
, nRecSize
) == nRecSize
);
2643 mxStrm
->seekToStart();
2648 // ============================================================================
2649 // ============================================================================
2651 DumperBase::~DumperBase()
2655 bool DumperBase::isImportEnabled() const
2657 return !isValid() || cfg().isImportEnabled();
2660 bool DumperBase::isImportCancelled() const
2662 return isValid() && cfg().isPasswordCancelled();
2665 void DumperBase::construct( const ConfigRef
& rxConfig
)
2667 if( isValid( rxConfig
) && rxConfig
->isDumperEnabled() )
2668 ObjectBase::construct( rxConfig
);
2671 // ============================================================================
2672 // ============================================================================
2679 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */