LibreOffice Module oox (master) 1
dumperbase.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
21
22#include <algorithm>
23#include <string_view>
24
25#include <com/sun/star/lang/XMultiServiceFactory.hpp>
26#include <com/sun/star/io/TextOutputStream.hpp>
27#include <com/sun/star/ucb/SimpleFileAccess.hpp>
28#include <osl/file.hxx>
29#include <rtl/math.hxx>
30#include <rtl/tencinfo.h>
34#include <tools/time.hxx>
35#include <o3tl/string_view.hxx>
36#include <utility>
37
38#ifdef DBG_UTIL
39
40namespace oox::dump {
41
42using namespace ::com::sun::star;
43using namespace ::com::sun::star::beans;
44using namespace ::com::sun::star::io;
45using namespace ::com::sun::star::lang;
46using namespace ::com::sun::star::ucb;
47using namespace ::com::sun::star::uno;
48
49using ::oox::core::FilterBase;
50
51namespace {
52
53const sal_Unicode OOX_DUMP_BOM = 0xFEFF;
54const sal_Int32 OOX_DUMP_MAXSTRLEN = 80;
55const sal_Int32 OOX_DUMP_INDENT = 2;
56const sal_Unicode OOX_DUMP_BINDOT = '.';
57const sal_Unicode OOX_DUMP_CFG_LISTSEP = ',';
58const sal_Unicode OOX_DUMP_CFG_QUOTE = '\'';
59const sal_Unicode OOX_DUMP_LF = '\n';
60const sal_Unicode OOX_DUMP_ITEMSEP = '=';
61const sal_Int32 OOX_DUMP_BYTESPERLINE = 16;
62const sal_Int64 OOX_DUMP_MAXARRAY = 16;
63
64} // namespace
65
66// file names -----------------------------------------------------------------
67
68OUString InputOutputHelper::convertFileNameToUrl( const OUString& rFileName )
69{
70 OUString aFileUrl;
71 if( ::osl::FileBase::getFileURLFromSystemPath( rFileName, aFileUrl ) == ::osl::FileBase::E_None )
72 return aFileUrl;
73 return OUString();
74}
75
76sal_Int32 InputOutputHelper::getFileNamePos( std::u16string_view rFileUrl )
77{
78 size_t nSepPos = rFileUrl.find( '/' );
79 return (nSepPos == std::u16string_view::npos) ? 0 : (nSepPos + 1);
80}
81
82std::u16string_view InputOutputHelper::getFileNameExtension( std::u16string_view rFileUrl )
83{
84 sal_Int32 nNamePos = getFileNamePos( rFileUrl );
85 size_t nExtPos = rFileUrl.rfind( '.' );
86 if( nExtPos != std::u16string_view::npos && static_cast<sal_Int32>(nExtPos) >= nNamePos )
87 return rFileUrl.substr( nExtPos + 1 );
88 return std::u16string_view();
89}
90
91// input streams --------------------------------------------------------------
92
93Reference< XInputStream > InputOutputHelper::openInputStream(
94 const Reference< XComponentContext >& rxContext, const OUString& rFileName )
95{
96 Reference< XInputStream > xInStrm;
97 if( rxContext.is() ) try
98 {
99 Reference<XSimpleFileAccess3> xFileAccess(SimpleFileAccess::create(rxContext));
100 xInStrm = xFileAccess->openFileRead( rFileName );
101 }
102 catch( Exception& )
103 {
104 }
105 return xInStrm;
106}
107
108// output streams -------------------------------------------------------------
109
110Reference< XOutputStream > InputOutputHelper::openOutputStream(
111 const Reference< XComponentContext >& rxContext, const OUString& rFileName )
112{
113 Reference< XOutputStream > xOutStrm;
114 if( rxContext.is() ) try
115 {
116 Reference<XSimpleFileAccess3> xFileAccess(SimpleFileAccess::create(rxContext));
117 xOutStrm = xFileAccess->openFileWrite( rFileName );
118 }
119 catch( Exception& )
120 {
121 }
122 return xOutStrm;
123}
124
125Reference< XTextOutputStream2 > InputOutputHelper::openTextOutputStream(
126 const Reference< XComponentContext >& rxContext, const Reference< XOutputStream >& rxOutStrm, rtl_TextEncoding eTextEnc )
127{
128 Reference< XTextOutputStream2 > xTextOutStrm;
129 const char* pcCharset = rtl_getMimeCharsetFromTextEncoding( eTextEnc );
130 if( rxContext.is() && rxOutStrm.is() && pcCharset ) try
131 {
132 xTextOutStrm = TextOutputStream::create(rxContext);
133 xTextOutStrm->setOutputStream( rxOutStrm );
134 xTextOutStrm->setEncoding( OUString::createFromAscii( pcCharset ) );
135 }
136 catch( Exception& )
137 {
138 }
139 return xTextOutStrm;
140}
141
142Reference< XTextOutputStream2 > InputOutputHelper::openTextOutputStream(
143 const Reference< XComponentContext >& rxContext, const OUString& rFileName, rtl_TextEncoding eTextEnc )
144{
145 return openTextOutputStream( rxContext, openOutputStream( rxContext, rFileName ), eTextEnc );
146}
147
149 meDataType( DATATYPE_VOID ),
150 meFmtType( FORMATTYPE_NONE )
151{
152}
153
154void ItemFormat::set( DataType eDataType, FormatType eFmtType, const OUString& rItemName )
155{
156 meDataType = eDataType;
157 meFmtType = eFmtType;
158 maItemName = rItemName;
159 maListName.clear();
160}
161
162OUStringVector::const_iterator ItemFormat::parse( const OUStringVector& rFormatVec )
163{
164 set( DATATYPE_VOID, FORMATTYPE_NONE, OUString() );
165
166 OUStringVector::const_iterator aIt = rFormatVec.begin(), aEnd = rFormatVec.end();
167 OUString aDataType, aFmtType;
168 if( aIt != aEnd ) aDataType = *aIt++;
169 if( aIt != aEnd ) aFmtType = *aIt++;
170 if( aIt != aEnd ) maItemName = *aIt++;
171 if( aIt != aEnd ) maListName = *aIt++;
172
175
177 {
178 if ( aFmtType == "unused" )
180 else if ( aFmtType == "unknown" )
182 }
183
184 return aIt;
185}
186
187OUStringVector ItemFormat::parse( const OUString& rFormatStr )
188{
189 OUStringVector aFormatVec;
190 StringHelper::convertStringToStringList( aFormatVec, rFormatStr, false );
191 OUStringVector::const_iterator aIt = parse( aFormatVec );
192 return OUStringVector( aIt, const_cast< const OUStringVector& >( aFormatVec ).end() );
193}
194
195// append string to string ----------------------------------------------------
196
197void StringHelper::appendChar( OUStringBuffer& rStr, sal_Unicode cChar, sal_Int32 nCount )
198{
199 for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
200 rStr.append( cChar );
201}
202
203void StringHelper::appendString( OUStringBuffer& rStr, const OUString& rData, sal_Int32 nWidth, sal_Unicode cFill )
204{
205 appendChar( rStr, cFill, nWidth - rData.getLength() );
206 rStr.append( rData );
207}
208
209// append decimal -------------------------------------------------------------
210
211void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt8 nData, sal_Int32 nWidth, sal_Unicode cFill )
212{
213 appendString( rStr, OUString::number( nData ), nWidth, cFill );
214}
215
216void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int8 nData, sal_Int32 nWidth, sal_Unicode cFill )
217{
218 appendString( rStr, OUString::number( nData ), nWidth, cFill );
219}
220
221void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt16 nData, sal_Int32 nWidth, sal_Unicode cFill )
222{
223 appendString( rStr, OUString::number( nData ), nWidth, cFill );
224}
225
226void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int16 nData, sal_Int32 nWidth, sal_Unicode cFill )
227{
228 appendString( rStr, OUString::number( nData ), nWidth, cFill );
229}
230
231void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt32 nData, sal_Int32 nWidth, sal_Unicode cFill )
232{
233 appendString( rStr, OUString::number( nData ), nWidth, cFill );
234}
235
236void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int32 nData, sal_Int32 nWidth, sal_Unicode cFill )
237{
238 appendString( rStr, OUString::number( nData ), nWidth, cFill );
239}
240
241void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt64 nData, sal_Int32 nWidth, sal_Unicode cFill )
242{
243 /* Values greater than biggest signed 64bit integer will change to
244 negative when converting to sal_Int64. Therefore, the trailing digit
245 will be written separately. */
246 OUStringBuffer aBuffer;
247 if( nData > 9 )
248 aBuffer.append( static_cast<sal_Int64>(nData / 10 ) );
249 aBuffer.append( static_cast< sal_Unicode >( '0' + (nData % 10) ) );
250 appendString( rStr, aBuffer.makeStringAndClear(), nWidth, cFill );
251}
252
253void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int64 nData, sal_Int32 nWidth, sal_Unicode cFill )
254{
255 appendString( rStr, OUString::number( nData ), nWidth, cFill );
256}
257
258void StringHelper::appendDec( OUStringBuffer& rStr, double fData, sal_Int32 nWidth, sal_Unicode cFill )
259{
260 appendString( rStr, ::rtl::math::doubleToUString( fData, rtl_math_StringFormat_G, 15, '.', true ), nWidth, cFill );
261}
262
263// append hexadecimal ---------------------------------------------------------
264
265void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt8 nData, bool bPrefix )
266{
267 static const sal_Unicode spcHexDigits[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
268 if( bPrefix )
269 rStr.append( "0x" );
270 rStr.append( spcHexDigits[ (nData >> 4) & 0x0F ] ).append( spcHexDigits[ nData & 0x0F ] );
271}
272
273void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int8 nData, bool bPrefix )
274{
275 appendHex( rStr, static_cast< sal_uInt8 >( nData ), bPrefix );
276}
277
278void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt16 nData, bool bPrefix )
279{
280 appendHex( rStr, static_cast< sal_uInt8 >( nData >> 8 ), bPrefix );
281 appendHex( rStr, static_cast< sal_uInt8 >( nData ), false );
282}
283
284void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int16 nData, bool bPrefix )
285{
286 appendHex( rStr, static_cast< sal_uInt16 >( nData ), bPrefix );
287}
288
289void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt32 nData, bool bPrefix )
290{
291 appendHex( rStr, static_cast< sal_uInt16 >( nData >> 16 ), bPrefix );
292 appendHex( rStr, static_cast< sal_uInt16 >( nData ), false );
293}
294
295void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int32 nData, bool bPrefix )
296{
297 appendHex( rStr, static_cast< sal_uInt32 >( nData ), bPrefix );
298}
299
300void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt64 nData, bool bPrefix )
301{
302 appendHex( rStr, static_cast< sal_uInt32 >( nData >> 32 ), bPrefix );
303 appendHex( rStr, static_cast< sal_uInt32 >( nData ), false );
304}
305
306void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int64 nData, bool bPrefix )
307{
308 appendHex( rStr, static_cast< sal_uInt64 >( nData ), bPrefix );
309}
310
311static sal_uInt64
312lcl_ConvertDouble(double const f)
313{
314 sal_uInt64 i = sal_uInt64();
315 for (size_t j = 0; j < sizeof(double); ++j)
316 { // hopefully both endian independent and strict aliasing safe
317 reinterpret_cast<char *>(&i)[j] = reinterpret_cast<char const *>(&f)[j];
318 }
319 return i;
320}
321
322void StringHelper::appendHex( OUStringBuffer& rStr, double fData, bool bPrefix )
323{
324 appendHex( rStr, lcl_ConvertDouble(fData), bPrefix );
325}
326
327// append shortened hexadecimal -----------------------------------------------
328
329void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt8 nData, bool bPrefix )
330{
331 appendHex( rStr, nData, bPrefix );
332}
333
334void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int8 nData, bool bPrefix )
335{
336 appendHex( rStr, nData, bPrefix );
337}
338
339void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt16 nData, bool bPrefix )
340{
341 if( nData > SAL_MAX_UINT8 )
342 appendHex( rStr, nData, bPrefix );
343 else
344 appendHex( rStr, static_cast< sal_uInt8 >( nData ), bPrefix );
345}
346
347void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int16 nData, bool bPrefix )
348{
349 appendShortHex( rStr, static_cast< sal_uInt16 >( nData ), bPrefix );
350}
351
352void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt32 nData, bool bPrefix )
353{
354 if( nData > SAL_MAX_UINT16 )
355 appendHex( rStr, nData, bPrefix );
356 else
357 appendShortHex( rStr, static_cast< sal_uInt16 >( nData ), bPrefix );
358}
359
360void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int32 nData, bool bPrefix )
361{
362 appendShortHex( rStr, static_cast< sal_uInt32 >( nData ), bPrefix );
363}
364
365void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt64 nData, bool bPrefix )
366{
367 if( nData > SAL_MAX_UINT32 )
368 appendHex( rStr, nData, bPrefix );
369 else
370 appendShortHex( rStr, static_cast< sal_uInt32 >( nData ), bPrefix );
371}
372
373void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int64 nData, bool bPrefix )
374{
375 appendShortHex( rStr, static_cast< sal_uInt64 >( nData ), bPrefix );
376}
377
378void StringHelper::appendShortHex( OUStringBuffer& rStr, double fData, bool bPrefix )
379{
380 appendHex( rStr, fData, bPrefix );
381}
382
383// append binary --------------------------------------------------------------
384
385void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt8 nData, bool bDots )
386{
387 for( sal_uInt8 nMask = 0x80; nMask != 0; (nMask >>= 1) &= 0x7F )
388 {
389 rStr.append( static_cast< sal_Unicode >( (nData & nMask) ? '1' : '0' ) );
390 if( bDots && (nMask == 0x10) )
391 rStr.append( OOX_DUMP_BINDOT );
392 }
393}
394
395void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int8 nData, bool bDots )
396{
397 appendBin( rStr, static_cast< sal_uInt8 >( nData ), bDots );
398}
399
400void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt16 nData, bool bDots )
401{
402 appendBin( rStr, static_cast< sal_uInt8 >( nData >> 8 ), bDots );
403 if( bDots )
404 rStr.append( OOX_DUMP_BINDOT );
405 appendBin( rStr, static_cast< sal_uInt8 >( nData ), bDots );
406}
407
408void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int16 nData, bool bDots )
409{
410 appendBin( rStr, static_cast< sal_uInt16 >( nData ), bDots );
411}
412
413void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt32 nData, bool bDots )
414{
415 appendBin( rStr, static_cast< sal_uInt16 >( nData >> 16 ), bDots );
416 if( bDots )
417 rStr.append( OOX_DUMP_BINDOT );
418 appendBin( rStr, static_cast< sal_uInt16 >( nData ), bDots );
419}
420
421void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int32 nData, bool bDots )
422{
423 appendBin( rStr, static_cast< sal_uInt32 >( nData ), bDots );
424}
425
426void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt64 nData, bool bDots )
427{
428 appendBin( rStr, static_cast< sal_uInt32 >( nData >> 32 ), bDots );
429 if( bDots )
430 rStr.append( OOX_DUMP_BINDOT );
431 appendBin( rStr, static_cast< sal_uInt32 >( nData ), bDots );
432}
433
434void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int64 nData, bool bDots )
435{
436 appendBin( rStr, static_cast< sal_uInt64 >( nData ), bDots );
437}
438
439void StringHelper::appendBin( OUStringBuffer& rStr, double fData, bool bDots )
440{
441 appendBin( rStr, lcl_ConvertDouble(fData), bDots );
442}
443
444// append formatted value -----------------------------------------------------
445
446void StringHelper::appendBool( OUStringBuffer& rStr, bool bData )
447{
448 rStr.appendAscii( bData ? "true" : "false" );
449}
450
451// encoded text output --------------------------------------------------------
452
453void StringHelper::appendCChar( OUStringBuffer& rStr, sal_Unicode cChar, bool bPrefix )
454{
455 if( cChar > 0x00FF )
456 {
457 if( bPrefix )
458 rStr.append( "\\u" );
459 appendHex( rStr, static_cast< sal_uInt16 >( cChar ), false );
460 }
461 else
462 {
463 if( bPrefix )
464 rStr.append( "\\x" );
465 appendHex( rStr, static_cast< sal_uInt8 >( cChar ), false );
466 }
467}
468
469void StringHelper::appendEncChar( OUStringBuffer& rStr, sal_Unicode cChar, sal_Int32 nCount, bool bPrefix )
470{
471 if( cChar < 0x0020 )
472 {
473 // C-style hex code
474 OUStringBuffer aCode;
475 appendCChar( aCode, cChar, bPrefix );
476 OUString aCodeStr = aCode.makeStringAndClear();
477 for( sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx )
478 rStr.append( aCodeStr );
479 }
480 else
481 {
482 appendChar( rStr, cChar, nCount );
483 }
484}
485
486void StringHelper::appendEncString( OUStringBuffer& rStr, const OUString& rData, bool bPrefix )
487{
488 sal_Int32 nBeg = 0;
489 sal_Int32 nIdx = 0;
490 sal_Int32 nEnd = rData.getLength();
491 while( nIdx < nEnd )
492 {
493 // find next character that needs encoding
494 while( (nIdx < nEnd) && (rData[ nIdx ] >= 0x20) ) ++nIdx;
495 // append portion
496 if( nBeg < nIdx )
497 {
498 if( (nBeg == 0) && (nIdx == nEnd) )
499 rStr.append( rData );
500 else
501 rStr.append( rData.subView(nBeg, nIdx - nBeg) );
502 }
503 // append characters to be encoded
504 while( (nIdx < nEnd) && (rData[ nIdx ] < 0x20) )
505 {
506 appendCChar( rStr, rData[ nIdx ], bPrefix );
507 ++nIdx;
508 }
509 // adjust limits
510 nBeg = nIdx;
511 }
512}
513
514// token list -----------------------------------------------------------------
515
516void StringHelper::appendToken( OUStringBuffer& rStr, std::u16string_view rToken, sal_Unicode cSep )
517{
518 if( (rStr.getLength() > 0) && (!rToken.empty()) )
519 rStr.append( cSep );
520 rStr.append( rToken );
521}
522
523void StringHelper::appendIndex( OUStringBuffer& rStr, sal_Int64 nIdx )
524{
525 OUStringBuffer aToken;
526 appendDec( aToken, nIdx );
527 rStr.append( '[' ).append( aToken ).append( ']' );
528}
529
530std::u16string_view StringHelper::getToken( std::u16string_view rData, sal_Int32& rnPos, sal_Unicode cSep )
531{
532 return trimSpaces( o3tl::getToken(rData, 0, cSep, rnPos ) );
533}
534
535void StringHelper::enclose( OUStringBuffer& rStr, sal_Unicode cOpen, sal_Unicode cClose )
536{
537 rStr.insert( 0, cOpen ).append( cClose ? cClose : cOpen );
538}
539
540// string conversion ----------------------------------------------------------
541
542namespace {
543
544sal_Int32 lclIndexOf( const OUString& rStr, sal_Unicode cChar, sal_Int32 nStartPos )
545{
546 sal_Int32 nIndex = rStr.indexOf( cChar, nStartPos );
547 return (nIndex < 0) ? rStr.getLength() : nIndex;
548}
549
550OUString lclTrimQuotedStringList( const OUString& rStr )
551{
552 OUStringBuffer aBuffer;
553 sal_Int32 nPos = 0;
554 sal_Int32 nLen = rStr.getLength();
555 while( nPos < nLen )
556 {
557 if( rStr[ nPos ] == OOX_DUMP_CFG_QUOTE )
558 {
559 // quoted string, skip leading quote character
560 ++nPos;
561 // process quoted text and embedded literal quote characters
562 OUStringBuffer aToken;
563 do
564 {
565 // seek to next quote character and add text portion to token buffer
566 sal_Int32 nEnd = lclIndexOf( rStr, OOX_DUMP_CFG_QUOTE, nPos );
567 aToken.append( rStr.subView(nPos, nEnd - nPos) );
568 // process literal quotes
569 while( (nEnd + 1 < nLen) && (rStr[ nEnd ] == OOX_DUMP_CFG_QUOTE) && (rStr[ nEnd + 1 ] == OOX_DUMP_CFG_QUOTE) )
570 {
571 aToken.append( OOX_DUMP_CFG_QUOTE );
572 nEnd += 2;
573 }
574 // nEnd is start of possible next text portion
575 nPos = nEnd;
576 }
577 while( (nPos < nLen) && (rStr[ nPos ] != OOX_DUMP_CFG_QUOTE) );
578 // add token, seek to list separator, ignore text following closing quote
579 aBuffer.append( aToken );
580 nPos = lclIndexOf( rStr, OOX_DUMP_CFG_LISTSEP, nPos );
581 if( nPos < nLen )
582 aBuffer.append( OOX_DUMP_LF );
583 // set current position behind list separator
584 ++nPos;
585 }
586 else
587 {
588 // find list separator, add token text to buffer
589 sal_Int32 nEnd = lclIndexOf( rStr, OOX_DUMP_CFG_LISTSEP, nPos );
590 aBuffer.append( rStr.subView(nPos, nEnd - nPos) );
591 if( nEnd < nLen )
592 aBuffer.append( OOX_DUMP_LF );
593 // set current position behind list separator
594 nPos = nEnd + 1;
595 }
596 }
597
598 return aBuffer.makeStringAndClear();
599}
600
601} // namespace
602
603std::u16string_view StringHelper::trimSpaces( std::u16string_view rStr )
604{
605 size_t nBeg = 0;
606 while( (nBeg < rStr.size()) && ((rStr[ nBeg ] == ' ') || (rStr[ nBeg ] == '\t')) )
607 ++nBeg;
608 size_t nEnd = rStr.size();
609 while( (nEnd > nBeg) && ((rStr[ nEnd - 1 ] == ' ') || (rStr[ nEnd - 1 ] == '\t')) )
610 --nEnd;
611 return rStr.substr( nBeg, nEnd - nBeg );
612}
613
614OUString StringHelper::trimTrailingNul( const OUString& rStr )
615{
616 sal_Int32 nLastPos = rStr.getLength() - 1;
617 if( (nLastPos >= 0) && (rStr[ nLastPos ] == 0) )
618 return rStr.copy( 0, nLastPos );
619 return rStr;
620}
621
622OString StringHelper::convertToUtf8( std::u16string_view rStr )
623{
624 return OUStringToOString( rStr, RTL_TEXTENCODING_UTF8 );
625}
626
627DataType StringHelper::convertToDataType( std::u16string_view rStr )
628{
630 if ( rStr == u"int8" )
632 else if ( rStr == u"uint8" )
634 else if ( rStr == u"int16" )
636 else if ( rStr == u"uint16" )
638 else if ( rStr == u"int32" )
640 else if ( rStr == u"uint32" )
642 else if ( rStr == u"int64" )
644 else if ( rStr == u"uint64" )
646 else if ( rStr == u"float" )
648 else if ( rStr == u"double" )
650 return eType;
651}
652
654{
656 if ( rStr == u"dec" )
658 else if ( rStr == u"hex" )
660 else if ( rStr == u"shorthex" )
662 else if ( rStr == u"bin" )
664 else if ( rStr == u"fix" )
666 else if ( rStr == u"bool" )
668 return eType;
669}
670
671bool StringHelper::convertFromDec( sal_Int64& ornData, std::u16string_view rData )
672{
673 size_t nPos = 0;
674 size_t nLen = rData.size();
675 bool bNeg = false;
676 if( (nLen > 0) && (rData[ 0 ] == '-') )
677 {
678 bNeg = true;
679 ++nPos;
680 }
681 ornData = 0;
682 for( ; nPos < nLen; ++nPos )
683 {
684 sal_Unicode cChar = rData[ nPos ];
685 if( (cChar < '0') || (cChar > '9') )
686 return false;
687 ornData = (ornData * 10) + (cChar - '0');
688 }
689 if( bNeg )
690 ornData *= -1;
691 return true;
692}
693
694bool StringHelper::convertFromHex( sal_Int64& ornData, std::u16string_view rData )
695{
696 ornData = 0;
697 for( size_t nPos = 0, nLen = rData.size(); nPos < nLen; ++nPos )
698 {
699 sal_Unicode cChar = rData[ nPos ];
700 if( ('0' <= cChar) && (cChar <= '9') )
701 cChar -= '0';
702 else if( ('A' <= cChar) && (cChar <= 'F') )
703 cChar -= ('A' - 10);
704 else if( ('a' <= cChar) && (cChar <= 'f') )
705 cChar -= ('a' - 10);
706 else
707 return false;
708 ornData = (ornData << 4) + cChar;
709 }
710 return true;
711}
712
713bool StringHelper::convertStringToInt( sal_Int64& ornData, std::u16string_view rData )
714{
715 if( (rData.size() > 2) && (rData[ 0 ] == '0') && ((rData[ 1 ] == 'X') || (rData[ 1 ] == 'x')) )
716 return convertFromHex( ornData, rData.substr( 2 ) );
717 return convertFromDec( ornData, rData );
718}
719
720bool StringHelper::convertStringToDouble( double& orfData, std::u16string_view rData )
721{
722 rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
723 sal_Int32 nSize = 0;
724 sal_Unicode const * pBegin = rData.data();
725 sal_Unicode const * pEnd;
726 orfData = rtl_math_uStringToDouble(pBegin,
727 pBegin + rData.size(),
728 '.', '\0',
729 &eStatus, &pEnd);
730 nSize = static_cast<sal_Int32>(pEnd - pBegin);
731 return (eStatus == rtl_math_ConversionStatus_Ok) && (nSize == static_cast<sal_Int32>(rData.size()));
732}
733
734bool StringHelper::convertStringToBool( std::u16string_view rData )
735{
736 if ( rData == u"true" )
737 return true;
738 if ( rData == u"false" )
739 return false;
740 sal_Int64 nData;
741 return convertStringToInt( nData, rData ) && (nData != 0);
742}
743
745{
746 OUStringPair aPair;
747 if( !rString.isEmpty() )
748 {
749 sal_Int32 nEqPos = rString.indexOf( cSep );
750 if( nEqPos < 0 )
751 {
752 aPair.first = rString;
753 }
754 else
755 {
756 aPair.first = StringHelper::trimSpaces( rString.subView( 0, nEqPos ) );
757 aPair.second = StringHelper::trimSpaces( rString.subView( nEqPos + 1 ) );
758 }
759 }
760 return aPair;
761}
762
763void StringHelper::convertStringToStringList( OUStringVector& orVec, const OUString& rData, bool bIgnoreEmpty )
764{
765 orVec.clear();
766 OUString aUnquotedData = lclTrimQuotedStringList( rData );
767 sal_Int32 nPos = 0;
768 sal_Int32 nLen = aUnquotedData.getLength();
769 while( (0 <= nPos) && (nPos < nLen) )
770 {
771 std::u16string_view aToken = getToken( aUnquotedData, nPos, OOX_DUMP_LF );
772 if( !bIgnoreEmpty || !aToken.empty() )
773 orVec.push_back( OUString(aToken) );
774 }
775}
776
777void StringHelper::convertStringToIntList( Int64Vector& orVec, const OUString& rData, bool bIgnoreEmpty )
778{
779 orVec.clear();
780 OUString aUnquotedData = lclTrimQuotedStringList( rData );
781 sal_Int32 nPos = 0;
782 sal_Int32 nLen = aUnquotedData.getLength();
783 sal_Int64 nData;
784 while( (0 <= nPos) && (nPos < nLen) )
785 {
786 bool bOk = convertStringToInt( nData, getToken( aUnquotedData, nPos, OOX_DUMP_LF ) );
787 if( !bIgnoreEmpty || bOk )
788 orVec.push_back( bOk ? nData : 0 );
789 }
790}
791
793{
794}
795
797{
798}
799
801{
803}
804
806 TextInputStream& /*rStrm*/, const OUString& /*rKey*/, const OUString& /*rData*/ )
807{
808}
809
811 TextInputStream& /*rStrm*/, sal_Int64 /*nKey*/, const OUString& /*rData*/ )
812{
813}
814
816{
817 bool bLoop = true;
818 while( bLoop && !rStrm.isEof() )
819 {
820 OUString aKey, aData;
821 switch( readConfigLine( rStrm, aKey, aData ) )
822 {
823 case LINETYPE_DATA:
824 processConfigItem( rStrm, aKey, aData );
825 break;
826 case LINETYPE_END:
827 bLoop = false;
828 break;
829 }
830 }
831}
832
834 TextInputStream& rStrm, OUString& orKey, OUString& orData )
835{
836 OUString aLine;
837 while( !rStrm.isEof() && aLine.isEmpty() )
838 {
839 aLine = rStrm.readLine();
840 if( !aLine.isEmpty() && (aLine[ 0 ] == OOX_DUMP_BOM) )
841 aLine = aLine.copy( 1 );
842 aLine = StringHelper::trimSpaces( aLine );
843 if( !aLine.isEmpty() )
844 {
845 // ignore comments (starting with hash or semicolon)
846 sal_Unicode cChar = aLine[ 0 ];
847 if( (cChar == '#') || (cChar == ';') )
848 aLine.clear();
849 }
850 }
851
853 orKey = aPair.first;
854 orData = aPair.second;
855 return ( !orKey.isEmpty() && (!orData.isEmpty() || orKey != "end" )) ?
857}
858
860 TextInputStream& rStrm, const OUString& rKey, const OUString& rData )
861{
862 sal_Int64 nKey;
863 if( StringHelper::convertStringToInt( nKey, rKey ) )
864 implProcessConfigItemInt( rStrm, nKey, rData );
865 else
866 implProcessConfigItemStr( rStrm, rKey, rData );
867}
868
870{
871}
872
873void NameListBase::setName( sal_Int64 nKey, const String& rName )
874{
875 implSetName( nKey, rName );
876}
877
879{
880 if( rxList )
881 {
882 for (auto const& elem : *rxList)
883 maMap[ elem.first ] = elem.second;
884 implIncludeList( *rxList );
885 }
886}
887
889{
890 return true;
891}
892
894 TextInputStream& rStrm, const OUString& rKey, const OUString& rData )
895{
896 if ( rKey == "include" )
897 include( rData );
898 else if ( rKey == "exclude" )
899 exclude( rData );
900 else
902}
903
905 TextInputStream& /*rStrm*/, sal_Int64 nKey, const OUString& rData )
906{
907 implSetName( nKey, rData );
908}
909
910void NameListBase::insertRawName( sal_Int64 nKey, const OUString& rName )
911{
912 maMap[ nKey ] = rName;
913}
914
915const OUString* NameListBase::findRawName( sal_Int64 nKey ) const
916{
917 const_iterator aIt = maMap.find( nKey );
918 return (aIt == end()) ? nullptr : &aIt->second;
919}
920
921void NameListBase::include( const OUString& rListKeys )
922{
923 OUStringVector aVec;
924 StringHelper::convertStringToStringList( aVec, rListKeys, true );
925 for (auto const& elem : aVec)
927}
928
929void NameListBase::exclude( const OUString& rKeys )
930{
931 Int64Vector aVec;
932 StringHelper::convertStringToIntList( aVec, rKeys, true );
933 for (auto const& elem : aVec)
934 maMap.erase(elem);
935}
936
938{
939 if( Base::isValid( rxNameList ) )
940 {
941 for (auto const& elemName : *rxNameList)
942 maMap[ elemName.first ].parse( elemName.second );
943 }
944}
945
947 NameListBase( rCfgData ),
948 maDefName( OOX_DUMP_ERR_NONAME ),
949 mbQuoteNames( false )
950{
951}
952
954 TextInputStream& rStrm, const OUString& rKey, const OUString& rData )
955{
956 if ( rKey == "default" )
957 maDefName = rData; // Sets a default name for unknown keys.
958 else if ( rKey == "quote-names" )
960 else
962}
963
964void ConstList::implSetName( sal_Int64 nKey, const OUString& rName )
965{
966 insertRawName( nKey, rName );
967}
968
969OUString ConstList::implGetName( const Config& /*rCfg*/, sal_Int64 nKey ) const
970{
971 const OUString* pName = findRawName( nKey );
972 OUString aName = pName ? *pName : maDefName;
973 if( mbQuoteNames )
974 {
975 OUStringBuffer aBuffer( aName );
977 aName = aBuffer.makeStringAndClear();
978 }
979 return aName;
980}
981
982OUString ConstList::implGetNameDbl( const Config& /*rCfg*/, double /*fValue*/ ) const
983{
984 return OUString();
985}
986
988{
989 if( const ConstList* pConstList = dynamic_cast< const ConstList* >( &rList ) )
990 {
991 maDefName = pConstList->maDefName;
992 mbQuoteNames = pConstList->mbQuoteNames;
993 }
994}
995
997 ConstList( rCfgData ),
998 mbIgnoreEmpty( true )
999{
1000}
1001
1002void MultiList::setNamesFromVec( sal_Int64 nStartKey, const OUStringVector& rNames )
1003{
1004 sal_Int64 nKey = nStartKey;
1005 for (auto const& name : rNames)
1006 {
1007 if( !mbIgnoreEmpty || !name.isEmpty() )
1008 insertRawName( nKey, name);
1009 ++nKey;
1010 }
1011}
1012
1014 TextInputStream& rStrm, const OUString& rKey, const OUString& rData )
1015{
1016 if ( rKey == "ignore-empty" )
1018 else
1020}
1021
1022void MultiList::implSetName( sal_Int64 nKey, const OUString& rName )
1023{
1024 OUStringVector aNames;
1025 StringHelper::convertStringToStringList( aNames, rName, false );
1026 setNamesFromVec( nKey, aNames );
1027}
1028
1030 NameListBase( rCfgData ),
1031 mnIgnore( 0 )
1032{
1033}
1034
1036 TextInputStream& rStrm, const OUString& rKey, const OUString& rData )
1037{
1038 if ( rKey == "ignore" )
1039 {
1040 sal_Int64 nIgnore;
1041 if( StringHelper::convertStringToInt( nIgnore, rData ) )
1042 setIgnoreFlags( nIgnore );
1043 }
1044 else
1045 {
1047 }
1048}
1049
1050void FlagsList::implSetName( sal_Int64 nKey, const OUString& rName )
1051{
1052 if( (nKey != 0) && ((nKey & (nKey - 1)) == 0) ) // only a single bit set?
1053 insertRawName( nKey, rName );
1054}
1055
1056OUString FlagsList::implGetName( const Config& /*rCfg*/, sal_Int64 nKey ) const
1057{
1058 sal_Int64 nFound = mnIgnore;
1059 OUStringBuffer aName;
1060 // add known flags
1061 for( const_iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt )
1062 {
1063 sal_Int64 nMask = aIt->first;
1064 setFlag( nFound, nMask );
1065 if( !getFlag( mnIgnore, nMask ) )
1066 {
1067 const OUString& rFlagName = aIt->second;
1068 bool bOnOff = rFlagName.startsWith(":");
1069 bool bFlag = getFlag( nKey, nMask );
1070 if( bOnOff )
1071 {
1072 StringHelper::appendToken( aName, rFlagName.subView( 1 ) );
1073 aName.appendAscii( bFlag ? ":on" : ":off" );
1074 }
1075 else
1076 {
1077 bool bNegated = rFlagName.startsWith("!");
1078 sal_Int32 nBothSep = bNegated ? rFlagName.indexOf( '!', 1 ) : -1;
1079 if( bFlag )
1080 {
1081 if( !bNegated )
1082 StringHelper::appendToken( aName, rFlagName );
1083 else if( nBothSep > 0 )
1084 StringHelper::appendToken( aName, rFlagName.subView( nBothSep + 1 ) );
1085 }
1086 else if( bNegated )
1087 {
1088 if( nBothSep > 0 )
1089 StringHelper::appendToken( aName, rFlagName.subView( 1, nBothSep - 1 ) );
1090 else
1091 StringHelper::appendToken( aName, rFlagName.subView( 1 ) );
1092 }
1093 }
1094 }
1095 }
1096 // add unknown flags
1097 setFlag( nKey, nFound, false );
1098 if( nKey != 0 )
1099 {
1100 OUStringBuffer aUnknown( OOX_DUMP_UNKNOWN );
1101 aUnknown.append( OOX_DUMP_ITEMSEP );
1102 StringHelper::appendShortHex( aUnknown, nKey );
1103 StringHelper::enclose( aUnknown, '(', ')' );
1104 StringHelper::appendToken( aName, aUnknown );
1105 }
1106 return aName.makeStringAndClear();
1107}
1108
1109OUString FlagsList::implGetNameDbl( const Config& /*rCfg*/, double /*fValue*/ ) const
1110{
1111 return OUString();
1112}
1115{
1116 if( const FlagsList* pFlagsList = dynamic_cast< const FlagsList* >( &rList ) )
1117 mnIgnore = pFlagsList->mnIgnore;
1118}
1119
1121{
1122 return (mnKey < rRight.mnKey) || ((mnKey == rRight.mnKey) && (maFilter < rRight.maFilter));
1123}
1124
1126 FlagsList( rCfgData )
1127{
1128}
1129
1130void CombiList::implSetName( sal_Int64 nKey, const OUString& rName )
1131{
1132 if( (nKey & (nKey - 1)) != 0 ) // more than a single bit set?
1133 {
1134 ::std::set< ExtItemFormatKey > aItemKeys;
1135 ExtItemFormat aItemFmt;
1136 OUStringVector aRemain = aItemFmt.parse( rName );
1137 for (auto const& elemRemain : aRemain)
1138 {
1140 if ( aPair.first == "noshift" )
1141 {
1142 aItemFmt.mbShiftValue = StringHelper::convertStringToBool( aPair.second );
1143 }
1144 else if ( aPair.first == "filter" )
1145 {
1146 OUStringPair aFilter = StringHelper::convertStringToPair( aPair.second, '~' );
1147 ExtItemFormatKey aKey( nKey );
1148 if( !aFilter.first.isEmpty() && StringHelper::convertStringToInt( aKey.maFilter.first, aFilter.first ) &&
1149 !aFilter.second.isEmpty() && StringHelper::convertStringToInt( aKey.maFilter.second, aFilter.second ) )
1150 {
1151 if( aKey.maFilter.first == 0 )
1152 aKey.maFilter.second = 0;
1153 aItemKeys.insert( aKey );
1154 }
1155 }
1156 }
1157 if( aItemKeys.empty() )
1158 aItemKeys.insert( ExtItemFormatKey( nKey ) );
1159 for (auto const& itemKey : aItemKeys)
1160 maFmtMap[itemKey] = aItemFmt;
1161 }
1162 else
1163 {
1164 FlagsList::implSetName( nKey, rName );
1165 }
1166}
1167
1168OUString CombiList::implGetName( const Config& rCfg, sal_Int64 nKey ) const
1169{
1170 sal_Int64 nFound = 0;
1171 OUStringBuffer aName;
1172 // add known flag fields
1173 for (auto const& fmt : maFmtMap)
1174 {
1175 const ExtItemFormatKey& rMapKey = fmt.first;
1176 sal_Int64 nMask = rMapKey.mnKey;
1177 if( (nMask != 0) && ((nKey & rMapKey.maFilter.first) == rMapKey.maFilter.second) )
1178 {
1179 const ExtItemFormat& rItemFmt = fmt.second;
1180
1181 sal_uInt64 nUFlags = static_cast< sal_uInt64 >( nKey );
1182 sal_uInt64 nUMask = static_cast< sal_uInt64 >( nMask );
1183 if( rItemFmt.mbShiftValue )
1184 while( (nUMask & 1) == 0 ) { nUFlags >>= 1; nUMask >>= 1; }
1185
1186 sal_uInt64 nUValue = nUFlags & nUMask;
1187 sal_Int64 nSValue = static_cast< sal_Int64 >( nUValue );
1188 if( getFlag< sal_uInt64 >( nUValue, (nUMask + 1) >> 1 ) )
1189 setFlag( nSValue, static_cast< sal_Int64 >( ~nUMask ) );
1190
1191 OUStringBuffer aItem( rItemFmt.maItemName );
1192 OUStringBuffer aValue;
1193 switch( rItemFmt.meDataType )
1194 {
1195 case DATATYPE_INT8: StringHelper::appendValue( aValue, static_cast< sal_Int8 >( nSValue ), rItemFmt.meFmtType ); break;
1196 case DATATYPE_UINT8: StringHelper::appendValue( aValue, static_cast< sal_uInt8 >( nUValue ), rItemFmt.meFmtType ); break;
1197 case DATATYPE_INT16: StringHelper::appendValue( aValue, static_cast< sal_Int16 >( nSValue ), rItemFmt.meFmtType ); break;
1198 case DATATYPE_UINT16: StringHelper::appendValue( aValue, static_cast< sal_uInt16 >( nUValue ), rItemFmt.meFmtType ); break;
1199 case DATATYPE_INT32: StringHelper::appendValue( aValue, static_cast< sal_Int32 >( nSValue ), rItemFmt.meFmtType ); break;
1200 case DATATYPE_UINT32: StringHelper::appendValue( aValue, static_cast< sal_uInt32 >( nUValue ), rItemFmt.meFmtType ); break;
1201 case DATATYPE_INT64: StringHelper::appendValue( aValue, nSValue, rItemFmt.meFmtType ); break;
1202 case DATATYPE_UINT64: StringHelper::appendValue( aValue, nUValue, rItemFmt.meFmtType ); break;
1203 case DATATYPE_FLOAT: StringHelper::appendValue( aValue, static_cast< float >( nSValue ), rItemFmt.meFmtType ); break;
1204 case DATATYPE_DOUBLE: StringHelper::appendValue( aValue, static_cast< double >( nSValue ), rItemFmt.meFmtType ); break;
1205 default:;
1206 }
1207 StringHelper::appendToken( aItem, aValue, OOX_DUMP_ITEMSEP );
1208 if( !rItemFmt.maListName.isEmpty() )
1209 {
1210 OUString aValueName = rCfg.getName( rItemFmt.maListName, static_cast< sal_Int64 >( nUValue ) );
1211 StringHelper::appendToken( aItem, aValueName, OOX_DUMP_ITEMSEP );
1213 StringHelper::enclose( aItem, '(', ')' );
1215 setFlag( nFound, nMask );
1216 }
1217 }
1218 setFlag( nKey, nFound, false );
1219 StringHelper::appendToken( aName, FlagsList::implGetName( rCfg, nKey ) );
1220 return aName.makeStringAndClear();
1221}
1222
1224{
1225 if( const CombiList* pCombiList = dynamic_cast< const CombiList* >( &rList ) )
1226 maFmtMap = pCombiList->maFmtMap;
1228}
1229
1231 NameListBase( rCfgData ),
1232 mfFactor( 1.0 )
1233{
1234}
1235
1236void UnitConverter::implSetName( sal_Int64 /*nKey*/, const OUString& /*rName*/ )
1237{
1238 // nothing to do
1239}
1240
1241OUString UnitConverter::implGetName( const Config& rCfg, sal_Int64 nKey ) const
1242{
1243 return implGetNameDbl( rCfg, static_cast< double >( nKey ) );
1244}
1245
1246OUString UnitConverter::implGetNameDbl( const Config& /*rCfg*/, double fValue ) const
1247{
1248 OUStringBuffer aValue;
1249 StringHelper::appendDec( aValue, mfFactor * fValue );
1250 aValue.append( maUnitName );
1251 return aValue.makeStringAndClear();
1252}
1253
1255{
1256}
1257
1259{
1260 if (!mxList)
1261 mxList = rCfg.getNameList( maName );
1262 return mxList;
1263}
1264
1265SharedConfigData::SharedConfigData( const OUString& rFileName,
1266 const Reference< XComponentContext >& rxContext, StorageRef xRootStrg,
1267 OUString aSysFileName ) :
1268 mxContext( rxContext ),
1269 mxRootStrg(std::move( xRootStrg )),
1270 maSysFileName(std::move( aSysFileName )),
1271 mbLoaded( false )
1272{
1273 OUString aFileUrl = InputOutputHelper::convertFileNameToUrl( rFileName );
1274 if( !aFileUrl.isEmpty() )
1275 {
1276 sal_Int32 nNamePos = InputOutputHelper::getFileNamePos( aFileUrl );
1277 maConfigPath = aFileUrl.copy( 0, nNamePos );
1278 mbLoaded = readConfigFile( aFileUrl );
1279 }
1280}
1281
1283{
1284}
1285
1286const OUString* SharedConfigData::getOption( const OUString& rKey ) const
1287{
1288 ConfigDataMap::const_iterator aIt = maConfigData.find( rKey );
1289 return (aIt == maConfigData.end()) ? nullptr : &aIt->second;
1290}
1291
1292void SharedConfigData::setNameList( const OUString& rListName, const NameListRef& rxList )
1293{
1294 if( !rListName.isEmpty() )
1295 maNameLists[ rListName ] = rxList;
1296}
1297
1298void SharedConfigData::eraseNameList( const OUString& rListName )
1299{
1300 maNameLists.erase( rListName );
1301}
1302
1303NameListRef SharedConfigData::getNameList( const OUString& rListName ) const
1304{
1305 NameListRef xList;
1306 NameListMap::const_iterator aIt = maNameLists.find( rListName );
1307 if( aIt != maNameLists.end() )
1308 xList = aIt->second;
1309 return xList;
1310}
1311
1313{
1314 return mbLoaded && mxContext.is() && mxRootStrg && !maSysFileName.isEmpty();
1315}
1316
1318 TextInputStream& rStrm, const OUString& rKey, const OUString& rData )
1319{
1320 if ( rKey == "include-config-file" )
1321 readConfigFile( maConfigPath + rData );
1322 else if ( rKey == "constlist" )
1323 readNameList< ConstList >( rStrm, rData );
1324 else if ( rKey == "multilist" )
1325 readNameList< MultiList >( rStrm, rData );
1326 else if ( rKey == "flagslist" )
1327 readNameList< FlagsList >( rStrm, rData );
1328 else if ( rKey == "combilist" )
1329 readNameList< CombiList >( rStrm, rData );
1330 else if ( rKey == "shortlist" )
1331 createShortList( rData );
1332 else if ( rKey == "unitconverter" )
1333 createUnitConverter( rData );
1334 else
1335 maConfigData[ rKey ] = rData;
1336}
1337
1338bool SharedConfigData::readConfigFile( const OUString& rFileUrl )
1339{
1340 bool bLoaded = maConfigFiles.count( rFileUrl ) > 0;
1341 if( !bLoaded )
1342 {
1343 Reference< XInputStream > xInStrm = InputOutputHelper::openInputStream( mxContext, rFileUrl );
1344 TextInputStream aTxtStrm( mxContext, xInStrm, RTL_TEXTENCODING_UTF8 );
1345 if( !aTxtStrm.isEof() )
1346 {
1347 maConfigFiles.insert( rFileUrl );
1348 readConfigBlockContents( aTxtStrm );
1349 bLoaded = true;
1350 }
1351 }
1352 return bLoaded;
1353}
1354
1355void SharedConfigData::createShortList( const OUString& rData )
1356{
1357 OUStringVector aDataVec;
1358 StringHelper::convertStringToStringList( aDataVec, rData, false );
1359 if( aDataVec.size() < 3 )
1360 return;
1361
1362 sal_Int64 nStartKey;
1363 if( StringHelper::convertStringToInt( nStartKey, aDataVec[ 1 ] ) )
1364 {
1365 std::shared_ptr< MultiList > xList = createNameList< MultiList >( aDataVec[ 0 ] );
1366 if( xList )
1367 {
1368 aDataVec.erase( aDataVec.begin(), aDataVec.begin() + 2 );
1369 xList->setNamesFromVec( nStartKey, aDataVec );
1370 }
1371 }
1372}
1373
1374void SharedConfigData::createUnitConverter( const OUString& rData )
1375{
1376 OUStringVector aDataVec;
1377 StringHelper::convertStringToStringList( aDataVec, rData, false );
1378 if( aDataVec.size() < 2 )
1379 return;
1381 OUString aFactor = aDataVec[ 1 ];
1382 bool bRecip = aFactor.startsWith("/");
1383 if( bRecip )
1384 aFactor = aFactor.copy( 1 );
1385 double fFactor;
1386 if( StringHelper::convertStringToDouble( fFactor, aFactor ) && (fFactor != 0.0) )
1387 {
1388 std::shared_ptr< UnitConverter > xList = createNameList< UnitConverter >( aDataVec[ 0 ] );
1389 if( xList )
1390 {
1391 xList->setFactor( bRecip ? (1.0 / fFactor) : fFactor );
1392 if( aDataVec.size() >= 3 )
1393 xList->setUnitName( aDataVec[ 2 ] );
1394 }
1395 }
1396}
1397
1398Config::Config( const char* pcEnvVar, const FilterBase& rFilter )
1399{
1400 construct( pcEnvVar, rFilter );
1401}
1402
1403Config::Config( const char* pcEnvVar, const Reference< XComponentContext >& rxContext, const StorageRef& rxRootStrg, const OUString& rSysFileName )
1404{
1405 construct( pcEnvVar, rxContext, rxRootStrg, rSysFileName );
1406}
1407
1409{
1410}
1411
1412void Config::construct( const char* pcEnvVar, const FilterBase& rFilter )
1413{
1414 if( !rFilter.getFileUrl().isEmpty() )
1415 construct( pcEnvVar, rFilter.getComponentContext(), rFilter.getStorage(), rFilter.getFileUrl() );
1416}
1417
1418void Config::construct( const char* pcEnvVar, const Reference< XComponentContext >& rxContext, const StorageRef& rxRootStrg, const OUString& rSysFileName )
1419{
1420 if( pcEnvVar && rxRootStrg && !rSysFileName.isEmpty() )
1421 if( const char* pcFileName = ::getenv( pcEnvVar ) )
1422 mxCfgData = std::make_shared<SharedConfigData>( OUString::createFromAscii( pcFileName ), rxContext, rxRootStrg, rSysFileName );
1423}
1424
1425const OUString& Config::getStringOption( const String& rKey, const OUString& rDefault ) const
1426{
1427 const OUString* pData = implGetOption( rKey );
1428 return pData ? *pData : rDefault;
1429}
1430
1431bool Config::getBoolOption( const String& rKey, bool bDefault ) const
1432{
1433 const OUString* pData = implGetOption( rKey );
1434 return pData ? StringHelper::convertStringToBool( *pData ) : bDefault;
1435}
1436
1438{
1439 return getBoolOption( "enable-dumper", false );
1440}
1441
1443{
1444 return getBoolOption( "enable-import", true );
1445}
1446
1447void Config::eraseNameList( const String& rListName )
1448{
1449 mxCfgData->eraseNameList( rListName );
1450}
1451
1452NameListRef Config::getNameList( const String& rListName ) const
1453{
1454 return mxCfgData->getNameList( rListName );
1455}
1456
1458{
1459 return isValid( mxCfgData );
1460}
1461
1462const OUString* Config::implGetOption( const OUString& rKey ) const
1463{
1464 return mxCfgData->getOption( rKey );
1465}
1466
1467Output::Output( const Reference< XComponentContext >& rxContext, const OUString& rFileName ) :
1468 mxStrm( InputOutputHelper::openTextOutputStream( rxContext, rFileName, RTL_TEXTENCODING_UTF8 ) ),
1469 mnCol( 0 ),
1470 mnItemLevel( 0 ),
1471 mnMultiLevel( 0 ),
1472 mnItemIdx( 0 ),
1473 mnLastItem( 0 )
1474{
1475 if( mxStrm.is() )
1476 mxStrm->writeString( OUString( OOX_DUMP_BOM ) );
1477}
1478
1480{
1481 if( maLine.getLength() > 0 )
1482 {
1483 mxStrm->writeString( maIndent );
1484 maLine.append( '\n' );
1485 mxStrm->writeString( maLine.makeStringAndClear() );
1486 mnCol = 0;
1487 mnLastItem = 0;
1488 }
1489}
1490
1492{
1493 for( size_t nIdx = 0; nIdx < nCount; ++nIdx )
1494 mxStrm->writeString( OUString('\n') );
1495}
1496
1498{
1499 OUStringBuffer aBuffer( maIndent );
1500 StringHelper::appendChar( aBuffer, ' ', OOX_DUMP_INDENT );
1501 maIndent = aBuffer.makeStringAndClear();
1502}
1503
1505{
1506 if( maIndent.getLength() >= OOX_DUMP_INDENT )
1507 maIndent = maIndent.copy( OOX_DUMP_INDENT );
1508}
1509
1510void Output::startTable( sal_Int32 nW1 )
1511{
1512 startTable( 1, &nW1 );
1513}
1514
1515void Output::startTable( sal_Int32 nW1, sal_Int32 nW2 )
1516{
1517 sal_Int32 pnColWidths[ 2 ];
1518 pnColWidths[ 0 ] = nW1;
1519 pnColWidths[ 1 ] = nW2;
1520 startTable( 2, pnColWidths );
1521}
1522
1523void Output::startTable( sal_Int32 nW1, sal_Int32 nW2, sal_Int32 nW3, sal_Int32 nW4 )
1524{
1525 sal_Int32 pnColWidths[ 4 ];
1526 pnColWidths[ 0 ] = nW1;
1527 pnColWidths[ 1 ] = nW2;
1528 pnColWidths[ 2 ] = nW3;
1529 pnColWidths[ 3 ] = nW4;
1530 startTable( 4, pnColWidths );
1531}
1532
1533void Output::startTable( size_t nColCount, const sal_Int32* pnColWidths )
1534{
1535 maColPos.clear();
1536 maColPos.push_back( 0 );
1537 sal_Int32 nColPos = 0;
1538 for( size_t nCol = 0; nCol < nColCount; ++nCol )
1539 {
1540 nColPos = nColPos + pnColWidths[ nCol ];
1541 maColPos.push_back( nColPos );
1542 }
1543}
1544
1546{
1547 tab( mnCol + 1 );
1548}
1549
1550void Output::tab( size_t nCol )
1551{
1552 mnCol = nCol;
1553 if( mnCol < maColPos.size() )
1554 {
1555 sal_Int32 nColPos = maColPos[ mnCol ];
1556 if( maLine.getLength() >= nColPos )
1557 maLine.setLength( ::std::max< sal_Int32 >( nColPos - 1, 0 ) );
1558 StringHelper::appendChar( maLine, ' ', nColPos - maLine.getLength() );
1559 }
1560 else
1561 {
1563 }
1564}
1565
1567{
1568 maColPos.clear();
1569}
1570
1571void Output::resetItemIndex( sal_Int64 nIdx )
1572{
1573 mnItemIdx = nIdx;
1574}
1575
1576void Output::startItem( const String& rItemName )
1577{
1578 if( mnItemLevel == 0 )
1579 {
1580 if( (mnMultiLevel > 0) && (maLine.getLength() > 0) )
1581 tab();
1582 if( rItemName.has() )
1583 {
1584 writeItemName( rItemName );
1585 writeChar( OOX_DUMP_ITEMSEP );
1586 }
1587 }
1588 ++mnItemLevel;
1589 mnLastItem = maLine.getLength();
1590}
1591
1593{
1594 if( mnItemLevel > 0 )
1595 {
1596 if( (maLine.getLength() == 0) || (maLine[ maLine.getLength() - 1 ] != OOX_DUMP_ITEMSEP) )
1597 writeChar( OOX_DUMP_ITEMSEP );
1598 mnLastItem = maLine.getLength();
1599 }
1600}
1601
1603{
1604 if( mnItemLevel > 0 )
1605 {
1606 maLastItem = maLine.copy( mnLastItem ).makeStringAndClear();
1607 if( maLastItem.isEmpty() && mnLastItem > 0 && maLine[ mnLastItem - 1 ] == OOX_DUMP_ITEMSEP )
1608 maLine.setLength( mnLastItem - 1 );
1609 --mnItemLevel;
1610 }
1611 if( mnItemLevel == 0 )
1612 {
1613 if( mnMultiLevel == 0 )
1614 newLine();
1615 }
1616 else
1617 contItem();
1618}
1619
1621{
1622 ++mnMultiLevel;
1623}
1624
1626{
1627 if( mnMultiLevel > 0 )
1628 --mnMultiLevel;
1629 if( mnMultiLevel == 0 )
1630 newLine();
1631}
1632
1633void Output::writeChar( sal_Unicode cChar, sal_Int32 nCount )
1634{
1636}
1637
1638void Output::writeAscii( const char* pcStr )
1639{
1640 if( pcStr )
1641 maLine.appendAscii( pcStr );
1642}
1643
1644void Output::writeString( const OUString& rStr )
1647}
1648
1649void Output::writeArray( const sal_uInt8* pnData, std::size_t nSize, sal_Unicode cSep )
1650{
1651 const sal_uInt8* pnEnd = pnData ? (pnData + nSize) : nullptr;
1652 for( const sal_uInt8* pnByte = pnData; pnByte < pnEnd; ++pnByte )
1653 {
1654 if( pnByte > pnData )
1655 writeChar( cSep );
1656 writeHex( *pnByte, false );
1657 }
1658}
1659
1660void Output::writeBool( bool bData )
1661{
1663}
1664
1665void Output::writeDateTime( const util::DateTime& rDateTime )
1666{
1667 writeDec( rDateTime.Year, 4, '0' );
1668 writeChar( '-' );
1669 writeDec( rDateTime.Month, 2, '0' );
1670 writeChar( '-' );
1671 writeDec( rDateTime.Day, 2, '0' );
1672 writeChar( 'T' );
1673 writeDec( rDateTime.Hours, 2, '0' );
1674 writeChar( ':' );
1675 writeDec( rDateTime.Minutes, 2, '0' );
1676 writeChar( ':' );
1677 writeDec( rDateTime.Seconds, 2, '0' );
1678}
1679
1681{
1682 return mxStrm.is();
1683}
1684
1685void Output::writeItemName( const String& rItemName )
1686{
1687 if( rItemName.has() && (rItemName[ 0 ] == '#') )
1688 {
1689 writeString( rItemName.copy( 1 ) );
1691 }
1692 else
1693 writeString( rItemName );
1694}
1695
1697 mxStrg(std::move( xStrg ))
1698{
1699 if( mxStrg )
1700 mxStrg->getElementNames( maNames );
1701 maIt = maNames.begin();
1702}
1703
1705{
1706}
1707
1709{
1710 if( maIt != maNames.end() )
1711 ++maIt;
1712 return *this;
1713}
1714
1716{
1717 OUString aName;
1718 if( maIt != maNames.end() )
1719 aName = *maIt;
1720 return aName;
1721}
1722
1724{
1725 return isValid() && mxStrg->openInputStream( *maIt ).is();
1726}
1727
1729{
1730 if( !isValid() )
1731 return false;
1732 StorageRef xStrg = mxStrg->openSubStorage( *maIt, false );
1733 return xStrg && xStrg->isStorage();
1734}
1735
1737{
1738 return mxStrg && mxStrg->isStorage() && (maIt != maNames.end());
1739}
1740
1742{
1743}
1744
1745void ObjectBase::construct( const ConfigRef& rxConfig )
1746{
1747 mxConfig = rxConfig;
1748}
1749
1750void ObjectBase::construct( const ObjectBase& rParent )
1751{
1752 *this = rParent;
1753}
1754
1756{
1757 if( isValid() )
1758 implDump();
1759}
1760
1762{
1763 return isValid( mxConfig );
1764}
1765
1767{
1768}
1769
1770void StorageObjectBase::construct( const ObjectBase& rParent, const StorageRef& rxStrg, const OUString& rSysPath )
1771{
1772 ObjectBase::construct( rParent );
1773 mxStrg = rxStrg;
1774 maSysPath = rSysPath;
1775}
1776
1778{
1779 ObjectBase::construct( rParent );
1781 {
1784 }
1785}
1786
1788{
1789 return mxStrg && !maSysPath.isEmpty() && ObjectBase::implIsValid();
1790}
1791
1793{
1794 bool bIsStrg = mxStrg->isStorage();
1795 bool bIsRoot = mxStrg->isRootStorage();
1796 Reference< XInputStream > xBaseStrm;
1797 if( !bIsStrg )
1798 xBaseStrm = mxStrg->openInputStream( OUString() );
1799
1800 OUString aSysOutPath = maSysPath;
1801 if( bIsRoot ) try
1802 {
1803 aSysOutPath += OOX_DUMP_DUMPEXT;
1804 Reference<XSimpleFileAccess3> xFileAccess(SimpleFileAccess::create(getContext()));
1805 xFileAccess->kill( aSysOutPath );
1806 }
1807 catch( Exception& )
1808 {
1809 }
1810
1811 if( bIsStrg )
1812 {
1813 extractStorage( mxStrg, OUString(), aSysOutPath );
1814 }
1815 else if( xBaseStrm.is() )
1816 {
1817 BinaryInputStreamRef xInStrm( std::make_shared<BinaryXInputStream>( xBaseStrm, false ) );
1818 xInStrm->seekToStart();
1819 implDumpBaseStream( xInStrm, aSysOutPath );
1820 }
1821}
1822
1823void StorageObjectBase::implDumpStream( const Reference< XInputStream >&, const OUString&, const OUString&, const OUString& )
1824{
1825}
1826
1827void StorageObjectBase::implDumpStorage( const StorageRef& rxStrg, const OUString& rStrgPath, const OUString& rSysPath )
1828{
1829 extractStorage( rxStrg, rStrgPath, rSysPath );
1830}
1831
1833{
1834}
1835
1837{
1838 if( rStrmName.has() )
1839 maPreferred.emplace_back( rStrmName, false );
1840}
1841
1843{
1844 if( rStrgPath.has() )
1845 maPreferred.emplace_back( rStrgPath, true );
1846}
1847
1849 const OUString& rStrmName, std::u16string_view rSysOutPath )
1850{
1851 // encode all characters < 0x20
1852 OUStringBuffer aBuffer;
1853 StringHelper::appendEncString( aBuffer, rStrmName, false );
1854
1855 // replace all characters reserved in file system
1856 OUString aFileName = aBuffer.makeStringAndClear();
1857 static const sal_Unicode spcReserved[] = { '/', '\\', ':', '*', '?', '<', '>', '|' };
1858 for(const sal_Unicode cChar : spcReserved)
1859 aFileName = aFileName.replace(cChar, '_');
1860
1861 // build full path
1862 return OUString::Concat(rSysOutPath) + "/" + aFileName;
1863}
1864
1865void StorageObjectBase::extractStream( StorageBase& rStrg, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName )
1866{
1867 BinaryXInputStream aInStrm( rStrg.openInputStream( rStrmName ), true );
1868 if( !aInStrm.isEof() )
1869 {
1870 BinaryXOutputStream aOutStrm( InputOutputHelper::openOutputStream( getContext(), rSysFileName ), true );
1871 if( !aOutStrm.isEof() )
1872 aInStrm.copyToStream( aOutStrm );
1873 }
1874 Reference< XInputStream > xDumpStrm = InputOutputHelper::openInputStream( getContext(), rSysFileName );
1875 if( xDumpStrm.is() )
1876 implDumpStream( xDumpStrm, rStrgPath, rStrmName, rSysFileName );
1877}
1878
1879void StorageObjectBase::extractStorage( const StorageRef& rxStrg, const OUString& rStrgPath, const OUString& rSysPath )
1880{
1881 // create directory in file system
1882 ::osl::FileBase::RC eRes = ::osl::Directory::create( rSysPath );
1883 if( (eRes != ::osl::FileBase::E_None) && (eRes != ::osl::FileBase::E_EXIST) )
1884 return;
1885
1886 // process preferred storages and streams in root storage first
1887 if( rStrgPath.isEmpty() )
1888 {
1889 for (auto const& elemPreferred : maPreferred)
1890 extractItem( rxStrg, rStrgPath, elemPreferred.maName, rSysPath, elemPreferred.mbStorage, !elemPreferred.mbStorage );
1891 }
1892
1893 // process children of the storage
1894 for( StorageIterator aIt( rxStrg ); aIt.isValid(); ++aIt )
1895 {
1896 // skip processed preferred items
1897 OUString aItemName = aIt.getName();
1898 bool bFound = false;
1899 if( rStrgPath.isEmpty() )
1900 {
1901 for (auto const& elemPreferred : maPreferred)
1902 {
1903 bFound = elemPreferred.maName == aItemName;
1904 if (bFound)
1905 break;
1906 }
1907 }
1908 if( !bFound )
1909 extractItem( rxStrg, rStrgPath, aItemName, rSysPath, aIt.isStorage(), aIt.isStream() );
1910 }
1911}
1912
1913void StorageObjectBase::extractItem( const StorageRef& rxStrg, const OUString& rStrgPath, const OUString& rItemName, std::u16string_view rSysPath, bool bIsStrg, bool bIsStrm )
1914{
1915 OUString aSysFileName = getSysFileName( rItemName, rSysPath );
1916 if( bIsStrg )
1917 {
1918 OUStringBuffer aStrgPath( rStrgPath );
1919 StringHelper::appendToken( aStrgPath, rItemName, '/' );
1920 implDumpStorage( rxStrg->openSubStorage( rItemName, false ), aStrgPath.makeStringAndClear(), aSysFileName );
1921 }
1922 else if( bIsStrm )
1923 {
1924 extractStream( *rxStrg, rStrgPath, rItemName, aSysFileName );
1925 }
1926}
1927
1929{
1930}
1931
1932void OutputObjectBase::construct( const ObjectBase& rParent, const OUString& rSysFileName )
1933{
1934 ObjectBase::construct( rParent );
1936 {
1937 maSysFileName = rSysFileName;
1938 mxOut = std::make_shared<Output>( getContext(), rSysFileName + OOX_DUMP_DUMPEXT );
1939 }
1940}
1941
1943{
1944 *this = rParent;
1945}
1946
1948{
1949 return isValid( mxOut ) && ObjectBase::implIsValid();
1950}
1951
1953{
1954 ItemGuard aItem( mxOut, rName );
1955}
1956
1957void OutputObjectBase::writeInfoItem( const String& rName, const String& rData )
1958{
1959 ItemGuard aItem( mxOut, rName );
1960 mxOut->writeString( rData );
1961}
1962
1964{
1965 ItemGuard aItem( mxOut, rName );
1966 mxOut->writeChar( OOX_DUMP_STRQUOTE );
1967 mxOut->writeChar( cData );
1968 mxOut->writeChar( OOX_DUMP_STRQUOTE );
1969}
1970
1971void OutputObjectBase::writeStringItem( const String& rName, const OUString& rData )
1972{
1973 ItemGuard aItem( mxOut, rName );
1974 mxOut->writeAscii( "(len=" );
1975 mxOut->writeDec( rData.getLength() );
1976 mxOut->writeAscii( ")," );
1977 OUStringBuffer aValue( rData.subView( 0, ::std::min( rData.getLength(), OOX_DUMP_MAXSTRLEN ) ) );
1979 mxOut->writeString( aValue.makeStringAndClear() );
1980 if( rData.getLength() > OOX_DUMP_MAXSTRLEN )
1981 mxOut->writeAscii( ",cut" );
1982}
1983
1984void OutputObjectBase::writeArrayItem( const String& rName, const sal_uInt8* pnData, std::size_t nSize, sal_Unicode cSep )
1985{
1986 ItemGuard aItem( mxOut, rName );
1987 mxOut->writeArray( pnData, nSize, cSep );
1988}
1989
1990void OutputObjectBase::writeDateTimeItem( const String& rName, const util::DateTime& rDateTime )
1991{
1992 ItemGuard aItem( mxOut, rName );
1993 mxOut->writeDateTime( rDateTime );
1994}
1995
1996void OutputObjectBase::writeGuidItem( const String& rName, const OUString& rGuid )
1997{
1998 ItemGuard aItem( mxOut, rName );
1999 mxOut->writeString( rGuid );
2000 aItem.cont();
2001 mxOut->writeString( cfg().getStringOption( rGuid, OUString() ) );
2002}
2003
2005{
2006}
2007
2008void InputObjectBase::construct( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName )
2009{
2010 OutputObjectBase::construct( rParent, rSysFileName );
2011 mxStrm = rxStrm;
2012}
2013
2015{
2016 OutputObjectBase::construct( rParent );
2017 mxStrm = rxStrm;
2018}
2019
2021{
2022 *this = rParent;
2023}
2024
2026{
2028}
2029
2030void InputObjectBase::skipBlock( sal_Int64 nBytes, bool bShowSize )
2031{
2032 sal_Int64 nEndPos = ::std::min< sal_Int64 >( mxStrm->tell() + nBytes, mxStrm->size() );
2033 if( mxStrm->tell() < nEndPos )
2034 {
2035 if( bShowSize )
2036 writeDecItem( "skipped-data-size", static_cast< sal_uInt64 >( nEndPos - mxStrm->tell() ) );
2037 mxStrm->seek( nEndPos );
2038 }
2039}
2040
2041void InputObjectBase::dumpRawBinary( sal_Int64 nBytes, bool bShowOffset, bool bStream )
2042{
2043 TableGuard aTabGuard( mxOut,
2044 bShowOffset ? 12 : 0,
2045 3 * OOX_DUMP_BYTESPERLINE / 2 + 1,
2046 3 * OOX_DUMP_BYTESPERLINE / 2 + 1,
2047 OOX_DUMP_BYTESPERLINE / 2 + 1 );
2048
2049 sal_Int64 nMaxShowSize = cfg().getIntOption< sal_Int64 >(
2050 bStream ? "max-binary-stream-size" : "max-binary-data-size", SAL_MAX_INT64 );
2051
2052 bool bSeekable = mxStrm->size() >= 0;
2053 sal_Int64 nEndPos = bSeekable ? ::std::min< sal_Int64 >( mxStrm->tell() + nBytes, mxStrm->size() ) : 0;
2054 sal_Int64 nDumpEnd = bSeekable ? ::std::min< sal_Int64 >( mxStrm->tell() + nMaxShowSize, nEndPos ) : nMaxShowSize;
2055 sal_Int64 nPos = bSeekable ? mxStrm->tell() : 0;
2056 bool bLoop = true;
2057
2058 while( bLoop && (nPos < nDumpEnd) )
2059 {
2060 mxOut->writeHex( static_cast< sal_uInt32 >( nPos ) );
2061 mxOut->tab();
2062
2063 sal_uInt8 pnLineData[ OOX_DUMP_BYTESPERLINE ];
2064 sal_Int32 nLineSize = bSeekable ? ::std::min( static_cast< sal_Int32 >( nDumpEnd - mxStrm->tell() ), OOX_DUMP_BYTESPERLINE ) : OOX_DUMP_BYTESPERLINE;
2065 sal_Int32 nReadSize = mxStrm->readMemory( pnLineData, nLineSize );
2066 bLoop = nReadSize == nLineSize;
2067 nPos += nReadSize;
2068
2069 if( nReadSize > 0 )
2070 {
2071 const sal_uInt8* pnByte = nullptr;
2072 const sal_uInt8* pnEnd = nullptr;
2073 for( pnByte = pnLineData, pnEnd = pnLineData + nReadSize; pnByte != pnEnd; ++pnByte )
2074 {
2075 if( (pnByte - pnLineData) == (OOX_DUMP_BYTESPERLINE / 2) ) mxOut->tab();
2076 mxOut->writeHex( *pnByte, false );
2077 mxOut->writeChar( ' ' );
2078 }
2079
2080 aTabGuard.tab( 3 );
2081 for( pnByte = pnLineData, pnEnd = pnLineData + nReadSize; pnByte != pnEnd; ++pnByte )
2082 {
2083 if( (pnByte - pnLineData) == (OOX_DUMP_BYTESPERLINE / 2) ) mxOut->tab();
2084 mxOut->writeChar( static_cast< sal_Unicode >( (*pnByte < 0x20) ? '.' : *pnByte ) );
2085 }
2086 mxOut->newLine();
2087 }
2088 }
2089
2090 // skip undumped data
2091 if( bSeekable )
2092 skipBlock( nEndPos - mxStrm->tell() );
2093}
2094
2095void InputObjectBase::dumpBinary( const String& rName, sal_Int64 nBytes, bool bShowOffset )
2096{
2097 {
2098 MultiItemsGuard aMultiGuard( mxOut );
2099 writeEmptyItem( rName );
2100 writeDecItem( "size", nBytes );
2101 }
2102 IndentGuard aIndGuard( mxOut );
2103 dumpRawBinary( nBytes, bShowOffset );
2104}
2105
2106void InputObjectBase::dumpRemaining( sal_Int64 nBytes )
2107{
2108 if( nBytes > 0 )
2109 {
2110 if( cfg().getBoolOption( "show-trailing-unknown", true ) )
2111 dumpBinary( "remaining-data", nBytes, false );
2112 else
2113 skipBlock( nBytes );
2114 }
2115}
2116
2118{
2119 if( mxStrm->isEof() || (mxStrm->tell() > nPos) )
2120 writeInfoItem( "stream-state", OOX_DUMP_ERR_STREAM );
2121 else
2122 dumpRemaining( nPos - mxStrm->tell() );
2123 mxStrm->seek( nPos );
2124}
2125
2127{
2128 dumpRemainingTo( mxStrm->size() );
2129}
2130
2131void InputObjectBase::dumpArray( const String& rName, sal_Int32 nBytes, sal_Unicode cSep )
2132{
2133 sal_Int32 nDumpSize = getLimitedValue< sal_Int32, sal_Int64 >( mxStrm->size() - mxStrm->tell(), 0, nBytes );
2134 if( nDumpSize > OOX_DUMP_MAXARRAY )
2135 {
2136 dumpBinary( rName, nBytes, false );
2137 }
2138 else if( nDumpSize > 1 )
2139 {
2140 sal_uInt8 pnData[ OOX_DUMP_MAXARRAY ];
2141 mxStrm->readMemory( pnData, nDumpSize );
2142 writeArrayItem( rName, pnData, nDumpSize, cSep );
2143 }
2144 else if( nDumpSize == 1 )
2145 dumpHex< sal_uInt8 >( rName );
2146}
2147
2149{
2150 sal_uInt16 nChar = mxStrm->readuInt16();
2151 sal_Unicode cChar = static_cast< sal_Unicode >( nChar );
2152 writeCharItem( rName( "char" ), cChar );
2153 return cChar;
2154}
2155
2156OUString InputObjectBase::dumpCharArray( const String& rName, sal_Int32 nLen, rtl_TextEncoding eTextEnc, bool bHideTrailingNul )
2157{
2158 sal_Int32 nDumpSize = getLimitedValue< sal_Int32, sal_Int64 >( mxStrm->size() - mxStrm->tell(), 0, nLen );
2159 OUString aString;
2160 if( nDumpSize > 0 )
2161 {
2162 ::std::vector< char > aBuffer( static_cast< std::size_t >( nLen ) + 1 );
2163 sal_Int32 nCharsRead = mxStrm->readMemory(aBuffer.data(), nLen);
2164 aBuffer[ nCharsRead ] = 0;
2165 aString = OStringToOUString(std::string_view(aBuffer.data()), eTextEnc);
2166 }
2167 if( bHideTrailingNul )
2168 aString = StringHelper::trimTrailingNul( aString );
2169 writeStringItem( rName( "text" ), aString );
2170 return aString;
2171}
2172
2173OUString InputObjectBase::dumpUnicodeArray( const String& rName, sal_Int32 nLen, bool bHideTrailingNul )
2174{
2175 OUStringBuffer aBuffer;
2176 for( sal_Int32 nIndex = 0; !mxStrm->isEof() && (nIndex < nLen); ++nIndex )
2177 {
2178 aBuffer.append( static_cast< sal_Unicode >( mxStrm->readuInt16() ) );
2179 }
2180 OUString aString = aBuffer.makeStringAndClear();
2181 if( bHideTrailingNul )
2182 aString = StringHelper::trimTrailingNul( aString );
2183 writeStringItem( rName( "text" ), aString );
2184 return aString;
2185}
2186
2187util::DateTime InputObjectBase::dumpFileTime( const String& rName )
2188{
2189 util::DateTime aDateTime;
2190
2191 ItemGuard aItem( mxOut, rName( "file-time" ) );
2192 sal_Int64 nFileTime = dumpDec< sal_Int64 >( EMPTY_STRING );
2193 // file time is in 10^-7 seconds (100 nanoseconds), convert to nanoseconds
2194 nFileTime *= 100;
2195 // entire days
2196 sal_Int64 nDays = nFileTime / sal_Int64( ::tools::Time::nanoSecPerDay );
2197 // number of entire years
2198 sal_Int64 nYears = (nDays - (nDays / (4 * 365)) + (nDays / (100 * 365)) - (nDays / (400 * 365))) / 365;
2199 // remaining days in the year
2200 sal_Int64 nDaysInYear = nDays - (nYears * 365 + nYears / 4 - nYears / 100 + nYears / 400);
2201 // the year (file dates start from 1601-01-01)
2202 aDateTime.Year = static_cast< sal_uInt16 >( 1601 + nYears );
2203 // leap year?
2204 bool bLeap = ((aDateTime.Year % 4 == 0) && (aDateTime.Year % 100 != 0)) || (aDateTime.Year % 400 == 0);
2205 // static arrays with number of days in month
2206 static const sal_Int64 spnDaysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
2207 static const sal_Int64 spnDaysInMonthL[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
2208 const sal_Int64* pnDaysInMonth = bLeap ? spnDaysInMonthL : spnDaysInMonth;
2209 // the month
2210 aDateTime.Month = 1;
2211 while( nDaysInYear >= *pnDaysInMonth )
2212 {
2213 nDaysInYear -= *pnDaysInMonth++;
2214 ++aDateTime.Month;
2215 }
2216 // the day
2217 aDateTime.Day = static_cast< sal_uInt16 >( nDaysInYear + 1 );
2218 // number of nanoseconds in the day
2219 sal_Int64 nTimeInDay = nFileTime % sal_Int64( ::tools::Time::nanoSecPerDay );
2220 // nanoseconds
2221 aDateTime.NanoSeconds = static_cast< sal_uInt32 >( nTimeInDay % ::tools::Time::nanoSecPerSec );
2222 nTimeInDay /= ::tools::Time::nanoSecPerSec;
2223 // seconds
2224 aDateTime.Seconds = static_cast< sal_uInt16 >( nTimeInDay % ::tools::Time::secondPerMinute );
2225 nTimeInDay /= ::tools::Time::secondPerMinute;
2226 // minutes
2227 aDateTime.Minutes = static_cast< sal_uInt16 >( nTimeInDay % ::tools::Time::minutePerHour );
2228 nTimeInDay /= ::tools::Time::minutePerHour;
2229 // hours
2230 aDateTime.Hours = static_cast< sal_uInt16 >( nTimeInDay );
2231
2232 writeDateTimeItem( EMPTY_STRING, aDateTime );
2233 return aDateTime;
2234}
2235
2236OUString InputObjectBase::dumpGuid( const String& rName )
2237{
2238 OUStringBuffer aBuffer;
2239 sal_uInt32 nData32;
2240 sal_uInt16 nData16;
2241 sal_uInt8 nData8;
2242
2243 nData32 = mxStrm->readuInt32();
2244 StringHelper::appendHex( aBuffer, nData32, false );
2245 aBuffer.append( '-' );
2246 nData16 = mxStrm->readuInt16();
2247 StringHelper::appendHex( aBuffer, nData16, false );
2248 aBuffer.append( '-' );
2249 nData16 = mxStrm->readuInt16();
2250 StringHelper::appendHex( aBuffer, nData16, false );
2251 aBuffer.append( '-' );
2252 nData8 = mxStrm->readuChar();
2253 StringHelper::appendHex( aBuffer, nData8, false );
2254 nData8 = mxStrm->readuChar( );
2255 StringHelper::appendHex( aBuffer, nData8, false );
2256 aBuffer.append( '-' );
2257 for( int nIndex = 0; nIndex < 6; ++nIndex )
2258 {
2259 nData8 = mxStrm->readuChar( );
2260 StringHelper::appendHex( aBuffer, nData8, false );
2261 }
2262 StringHelper::enclose( aBuffer, '{', '}' );
2263 OUString aGuid = aBuffer.makeStringAndClear();
2264 writeGuidItem( rName( "guid" ), aGuid );
2265 return aGuid;
2266}
2267
2269{
2270 switch( rItemFmt.meDataType )
2271 {
2272 case DATATYPE_VOID: break;
2273 case DATATYPE_INT8: dumpValue< sal_Int8 >( rItemFmt ); break;
2274 case DATATYPE_UINT8: dumpValue< sal_uInt8 >( rItemFmt ); break;
2275 case DATATYPE_INT16: dumpValue< sal_Int16 >( rItemFmt ); break;
2276 case DATATYPE_UINT16: dumpValue< sal_uInt16 >( rItemFmt ); break;
2277 case DATATYPE_INT32: dumpValue< sal_Int32 >( rItemFmt ); break;
2278 case DATATYPE_UINT32: dumpValue< sal_uInt32 >( rItemFmt ); break;
2279 case DATATYPE_INT64: dumpValue< sal_Int64 >( rItemFmt ); break;
2280 case DATATYPE_UINT64: dumpValue< sal_uInt64 >( rItemFmt ); break;
2281 case DATATYPE_FLOAT: dumpValue< float >( rItemFmt ); break;
2282 case DATATYPE_DOUBLE: dumpValue< double >( rItemFmt ); break;
2283 default:;
2284 }
2285}
2286
2287BinaryStreamObject::BinaryStreamObject( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName )
2288{
2289 InputObjectBase::construct( rParent, rxStrm, rSysFileName );
2290}
2291
2293{
2294 mxStrm->seekToStart();
2295 dumpRawBinary( mxStrm->size(), bShowOffset, true );
2296 mxOut->emptyLine();
2297}
2298
2300{
2302}
2303
2305 const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc, const OUString& rSysFileName )
2306{
2307 InputObjectBase::construct( rParent, rxStrm, rSysFileName );
2308 constructTextStrmObj( eTextEnc );
2309}
2310
2312 const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc )
2313{
2314 InputObjectBase::construct( rParent, rxStrm );
2315 constructTextStrmObj( eTextEnc );
2316}
2317
2319{
2321}
2322
2324{
2326}
2327
2328void TextStreamObjectBase::constructTextStrmObj( rtl_TextEncoding eTextEnc )
2329{
2330 if( mxStrm )
2331 mxTextStrm = std::make_shared<TextInputStream>( getContext(), *mxStrm, eTextEnc );
2332}
2333
2335 const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc, const OUString& rSysFileName )
2336{
2337 TextStreamObjectBase::construct( rParent, rxStrm, eTextEnc, rSysFileName );
2338}
2339
2341 const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc )
2342{
2343 TextStreamObjectBase::construct( rParent, rxStrm, eTextEnc );
2344}
2345
2347{
2348 sal_uInt32 nLine = 0;
2349 while( !rTextStrm.isEof() )
2350 {
2351 OUString aLine = rTextStrm.readLine();
2352 if( !rTextStrm.isEof() || !aLine.isEmpty() )
2353 implDumpLine( aLine, ++nLine );
2354 }
2355}
2356
2357void TextLineStreamObject::implDumpLine( const OUString& rLine, sal_uInt32 nLine )
2358{
2359 TableGuard aTabGuard( mxOut, 8 );
2360 mxOut->writeDec( nLine, 6 );
2361 mxOut->tab();
2362 mxOut->writeString( rLine );
2363 mxOut->newLine();
2364}
2365
2367 const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName )
2368{
2369 TextStreamObjectBase::construct( rParent, rxStrm, RTL_TEXTENCODING_UTF8, rSysFileName );
2370}
2371
2373{
2374 /* Buffers a start element and the following element text. Needed to dump
2375 matching start/end elements and the element text on the same line. */
2376 OUStringBuffer aOldStartElem;
2377 // special handling for VML
2379
2380 while( !rTextStrm.isEof() )
2381 {
2382 // get the next element and the following element text from text stream
2383 OUString aElem = rTextStrm.readToChar( '>', true ).trim();
2384 OUString aText = rTextStrm.readToChar( '<', false );
2385
2386 // remove multiple whitespace from element
2387 sal_Int32 nPos = 0;
2388 while( nPos < aElem.getLength() )
2389 {
2390 while( (nPos < aElem.getLength()) && (aElem[ nPos ] >= 32) ) ++nPos;
2391 if( nPos < aElem.getLength() )
2392 aElem = aElem.subView( 0, nPos ) + OUStringChar(' ') + o3tl::trim(aElem.subView( nPos ));
2393 ++nPos;
2394 }
2395
2396 sal_Int32 nElemLen = aElem.getLength();
2397 if( (nElemLen >= 2) && (aElem[ 0 ] == '<') && (aElem[ nElemLen - 1 ] == '>') )
2398 {
2399 // determine type of the element
2400 bool bSimpleElem = (aElem[ 1 ] == '!') || (aElem[ 1 ] == '?') || (aElem[ nElemLen - 2 ] == '/') ||
2401 (bIsVml && (nElemLen == 4) && (aElem[ 1 ] == 'b') && (aElem[ 2 ] == 'r'));
2402 bool bStartElem = !bSimpleElem && (aElem[ 1 ] != '/');
2403 bool bEndElem = !bSimpleElem && !bStartElem;
2404
2405 /* Start element or simple element: flush old start element and
2406 its text from previous iteration, and start a new indentation
2407 level for the new element. Trim whitespace and line breaks from
2408 the text of the old start element. */
2409 if( (bSimpleElem || bStartElem) && (aOldStartElem.getLength() > 0) )
2410 {
2411 mxOut->writeString( aOldStartElem.makeStringAndClear().trim() );
2412 mxOut->newLine();
2413 mxOut->incIndent();
2414 }
2415
2416 /* Start element: remember it and its text, to be able to print the
2417 matching end element on the same line in the next iteration. */
2418 if( bStartElem )
2419 {
2420 aOldStartElem.append( aElem + aText );
2421 }
2422 else
2423 {
2424 /* End element: if a start element has been remembered in the
2425 previous iteration, write it out here untrimmed, to show
2426 all whitespace in the element text, and without trailing
2427 line break. Code below will add the end element right after
2428 it. Otherwise, return to previous indentation level. */
2429 if( bEndElem )
2430 {
2431 if( aOldStartElem.getLength() == 0 )
2432 mxOut->decIndent();
2433 else
2434 mxOut->writeString( aOldStartElem.makeStringAndClear() );
2435 }
2436
2437 /* Write the element. Write following element text in a new
2438 line, but only, if it does not contain of white space
2439 entirely. */
2440 mxOut->writeString( aElem );
2441 mxOut->newLine();
2442 if( !aText.trim().isEmpty() )
2443 {
2444 mxOut->writeString( aText );
2445 mxOut->newLine();
2446 }
2447 }
2448 }
2449 }
2450}
2451
2453 const BinaryInputStreamRef& rxBaseStrm, const OUString& rSysFileName,
2454 const BinaryInputStreamRef& rxRecStrm, const String& rRecNames, const String& rSimpleRecs )
2455{
2456 InputObjectBase::construct( rParent, rxRecStrm, rSysFileName );
2457 constructRecObjBase( rxBaseStrm, rRecNames, rSimpleRecs );
2458}
2459
2461{
2463}
2464
2466{
2467 NameListRef xRecNames = maRecNames.getNameList( cfg() );
2468 ItemFormatMap aSimpleRecs( maSimpleRecs.getNameList( cfg() ) );
2469
2471 {
2472 // record header
2473 mxOut->emptyLine();
2474 writeHeader();
2476 IndentGuard aIndGuard( mxOut );
2477 sal_Int64 nRecPos = mxStrm->tell();
2478
2479 // record body
2480 if( !mbBinaryOnly && cfg().hasName( xRecNames, mnRecId ) )
2481 {
2482 ::std::map< sal_Int64, ItemFormat >::const_iterator aIt = aSimpleRecs.find( mnRecId );
2483 if( aIt != aSimpleRecs.end() )
2484 dumpItem( aIt->second );
2485 else
2487 }
2488
2489 // remaining undumped data
2490 if( !mxStrm->isEof() && (mxStrm->tell() == nRecPos) )
2491 dumpRawBinary( mnRecSize, false );
2492 else
2493 dumpRemainingTo( nRecPos + mnRecSize );
2494 }
2495}
2496
2498{
2499}
2500
2502{
2503}
2504
2505void RecordObjectBase::constructRecObjBase( const BinaryInputStreamRef& rxBaseStrm, const String& rRecNames, const String& rSimpleRecs )
2506{
2507 mxBaseStrm = rxBaseStrm;
2508 maRecNames = rRecNames;
2509 maSimpleRecs = rSimpleRecs;
2510 mnRecPos = mnRecId = mnRecSize = 0;
2511 mbBinaryOnly = false;
2513 mbShowRecPos = cfg().getBoolOption( "show-record-position", true );
2514}
2515
2517{
2518 MultiItemsGuard aMultiGuard( mxOut );
2519 writeEmptyItem( "REC" );
2520 if( mbShowRecPos && mxBaseStrm->isSeekable() )
2521 writeShortHexItem( "pos", mnRecPos, "CONV-DEC" );
2522 writeShortHexItem( "size", mnRecSize, "CONV-DEC" );
2523 ItemGuard aItem( mxOut, "id" );
2524 mxOut->writeShortHex( mnRecId );
2525 addNameToItem( mnRecId, "CONV-DEC" );
2527}
2528
2530 const BinaryInputStreamRef& rxBaseStrm, const OUString& rSysFileName,
2531 const String& rRecNames, const String& rSimpleRecs )
2532{
2533 BinaryInputStreamRef xRecStrm( std::make_shared<SequenceInputStream>( *mxRecData ) );
2534 RecordObjectBase::construct( rParent, rxBaseStrm, rSysFileName, xRecStrm, rRecNames, rSimpleRecs );
2535}
2536
2537bool SequenceRecordObjectBase::implStartRecord( BinaryInputStream& rBaseStrm, sal_Int64& ornRecPos, sal_Int64& ornRecId, sal_Int64& ornRecSize )
2538{
2539 bool bValid = true;
2540 if( rBaseStrm.isSeekable() )
2541 {
2542 ornRecPos = rBaseStrm.tell();
2543 // do not try to overread seekable streams, may cause assertions
2544 bValid = ornRecPos < rBaseStrm.size();
2545 }
2546
2547 // read the record header
2548 if( bValid )
2549 bValid = implReadRecordHeader( rBaseStrm, ornRecId, ornRecSize ) && !rBaseStrm.isEof() && (0 <= ornRecSize) && (ornRecSize <= 0x00100000);
2550
2551 // read record contents into data sequence
2552 if( bValid )
2553 {
2554 sal_Int32 nRecSize = static_cast< sal_Int32 >( ornRecSize );
2555 mxRecData->realloc( nRecSize );
2556 bValid = (nRecSize == 0) || (rBaseStrm.readData( *mxRecData, nRecSize ) == nRecSize);
2557 mxStrm->seekToStart();
2558 }
2559 return bValid;
2560}
2561
2563{
2564}
2565
2567{
2568 return !isValid() || cfg().isImportEnabled();
2569}
2570
2571void DumperBase::construct( const ConfigRef& rxConfig )
2572{
2573 if( isValid( rxConfig ) && rxConfig->isDumperEnabled() )
2574 ObjectBase::construct( rxConfig );
2575}
2576
2577} // namespace oox
2578
2579#endif
2580
2581/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const char * pName
Interface for binary input stream classes.
virtual sal_Int32 readData(StreamDataSequence &orData, sal_Int32 nBytes, size_t nAtomSize=1)=0
Derived classes implement reading nBytes bytes to the passed sequence.
void copyToStream(BinaryOutputStream &rOutStrm)
Copies bytes from the current position to the passed output stream.
bool isSeekable() const
Returns true, if the implementation supports the seek() operation.
virtual sal_Int64 size() const =0
Implementations return the size of the stream, if possible.
bool isEof() const
Returns true, if the stream position is invalid (EOF).
virtual sal_Int64 tell() const =0
Implementations return the current stream position, if possible.
Wraps a UNO input stream and provides convenient access functions.
Wraps a UNO output stream and provides convenient access functions.
Base class for storage access implementations.
Definition: storagebase.hxx:52
css::uno::Reference< css::io::XInputStream > openInputStream(const OUString &rStreamName)
Opens and returns the specified input stream from the storage.
bool isEof() const
Returns true, if no more text is available in the stream.
OUString readLine()
Reads a text line from the stream.
OUString readToChar(sal_Unicode cChar, bool bIncludeChar)
Reads a text portion from the stream until the specified character is found.
virtual ~Base()
Definition: dumperbase.cxx:792
bool isValid() const
Definition: dumperbase.hxx:449
void dumpBinaryStream(bool bShowOffset=true)
virtual void implDump() override
BinaryStreamObject(const ObjectBase &rParent, const BinaryInputStreamRef &rxStrm, const OUString &rSysFileName)
virtual void implSetName(sal_Int64 nKey, const OUString &rName) override
Sets the name for the passed key.
ExtItemFormatMap maFmtMap
Definition: dumperbase.hxx:692
CombiList(const SharedConfigData &rCfgData)
virtual OUString implGetName(const Config &rCfg, sal_Int64 nKey) const override
Returns the name for the passed key.
virtual void implIncludeList(const NameListBase &rList) override
Inserts all flags from the passed list.
void readConfigBlock(TextInputStream &rStrm)
Definition: dumperbase.cxx:800
void processConfigItem(TextInputStream &rStrm, const OUString &rKey, const OUString &rData)
Definition: dumperbase.cxx:859
virtual void implProcessConfigItemInt(TextInputStream &rStrm, sal_Int64 nKey, const OUString &rData)
Definition: dumperbase.cxx:810
void readConfigBlockContents(TextInputStream &rStrm)
Definition: dumperbase.cxx:815
virtual void implProcessConfigItemStr(TextInputStream &rStrm, const OUString &rKey, const OUString &rData)
Definition: dumperbase.cxx:805
static LineType readConfigLine(TextInputStream &rStrm, OUString &orKey, OUString &orData)
Definition: dumperbase.cxx:833
const OUString & getStringOption(const String &rKey, const OUString &rDefault) const
const StorageRef & getRootStorage() const
Definition: dumperbase.hxx:852
virtual ~Config() override
const OUString & getSysFileName() const
Definition: dumperbase.hxx:853
Type getIntOption(const String &rKey, Type nDefault) const
Definition: dumperbase.hxx:897
bool isDumperEnabled() const
bool isImportEnabled() const
NameListRef getNameList(const String &rListName) const
void eraseNameList(const String &rListName)
OUString getName(const NameListWrapper &rListWrp, Type nKey) const
Returns the name for the passed key from the passed name list.
Definition: dumperbase.hxx:912
std::shared_ptr< SharedConfigData > mxCfgData
Definition: dumperbase.hxx:890
bool getBoolOption(const String &rKey, bool bDefault) const
void construct(const char *pcEnvVar, const ::oox::core::FilterBase &rFilter)
const OUString * implGetOption(const OUString &rKey) const
virtual bool implIsValid() const override
virtual void implSetName(sal_Int64 nKey, const OUString &rName) override
Sets the name for the passed key.
Definition: dumperbase.cxx:964
virtual void implProcessConfigItemStr(TextInputStream &rStrm, const OUString &rKey, const OUString &rData) override
Definition: dumperbase.cxx:953
virtual void implIncludeList(const NameListBase &rList) override
Inserts all names from the passed list.
Definition: dumperbase.cxx:987
virtual OUString implGetNameDbl(const Config &rCfg, double fValue) const override
Returns the name for the passed double value.
Definition: dumperbase.cxx:982
void setQuoteNames(bool bQuoteNames)
Enables or disables automatic quotation of returned names.
Definition: dumperbase.hxx:591
virtual OUString implGetName(const Config &rCfg, sal_Int64 nKey) const override
Returns the name for the passed key, or the default name, if key is not contained.
Definition: dumperbase.cxx:969
ConstList(const SharedConfigData &rCfgData)
Definition: dumperbase.cxx:946
virtual ~DumperBase() override
void construct(const ConfigRef &rxConfig)
bool isImportEnabled() const
virtual void implSetName(sal_Int64 nKey, const OUString &rName) override
Sets the name for the passed key.
virtual void implProcessConfigItemStr(TextInputStream &rStrm, const OUString &rKey, const OUString &rData) override
virtual OUString implGetNameDbl(const Config &rCfg, double fValue) const override
Returns the name for the passed double value.
FlagsList(const SharedConfigData &rCfgData)
virtual void implIncludeList(const NameListBase &rList) override
Inserts all flags from the passed list.
void setIgnoreFlags(sal_Int64 nIgnore)
Sets flags to be ignored on output.
Definition: dumperbase.hxx:642
virtual OUString implGetName(const Config &rCfg, sal_Int64 nKey) const override
Returns the name for the passed key.
void dumpRemainingTo(sal_Int64 nPos)
void construct(const ObjectBase &rParent, const BinaryInputStreamRef &rxStrm, const OUString &rSysFileName)
css::util::DateTime dumpFileTime(const String &rName=EMPTY_STRING)
void skipBlock(sal_Int64 nBytes, bool bShowSize=true)
sal_Unicode dumpUnicode(const String &rName)
OUString dumpCharArray(const String &rName, sal_Int32 nLen, rtl_TextEncoding eTextEnc, bool bHideTrailingNul=false)
OUString dumpUnicodeArray(const String &rName, sal_Int32 nLen, bool bHideTrailingNul=false)
void dumpBinary(const String &rName, sal_Int64 nBytes, bool bShowOffset=true)
void dumpRemaining(sal_Int64 nBytes)
virtual ~InputObjectBase() override
void dumpItem(const ItemFormat &rItemFmt)
OUString dumpGuid(const String &rName=EMPTY_STRING)
virtual bool implIsValid() const override
BinaryInputStreamRef mxStrm
void dumpArray(const String &rName, sal_Int32 nBytes, sal_Unicode cSep=OOX_DUMP_LISTSEP)
void dumpRawBinary(sal_Int64 nBytes, bool bShowOffset, bool bStream=false)
Static helper functions for system file and stream access.
Definition: dumperbase.hxx:100
static css::uno::Reference< css::io::XOutputStream > openOutputStream(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const OUString &rFileName)
Definition: dumperbase.cxx:110
static std::u16string_view getFileNameExtension(std::u16string_view rFileUrl)
Definition: dumperbase.cxx:82
static OUString convertFileNameToUrl(const OUString &rFileName)
Definition: dumperbase.cxx:68
static css::uno::Reference< css::io::XTextOutputStream2 > openTextOutputStream(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const css::uno::Reference< css::io::XOutputStream > &rxOutStrm, rtl_TextEncoding eTextEnc)
static sal_Int32 getFileNamePos(std::u16string_view rFileUrl)
Definition: dumperbase.cxx:76
static css::uno::Reference< css::io::XInputStream > openInputStream(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const OUString &rFileName)
Definition: dumperbase.cxx:93
::std::map< sal_Int64, ItemFormat > maMap
Definition: dumperbase.hxx:742
void insertFormats(const NameListRef &rxNameList)
Definition: dumperbase.cxx:937
::std::map< sal_Int64, ItemFormat >::const_iterator end() const
Definition: dumperbase.hxx:748
::std::map< sal_Int64, ItemFormat >::const_iterator find(sal_Int64 nId) const
Definition: dumperbase.hxx:749
virtual void implProcessConfigItemStr(TextInputStream &rStrm, const OUString &rKey, const OUString &rData) override
MultiList(const SharedConfigData &rCfgData)
Definition: dumperbase.cxx:996
void setNamesFromVec(sal_Int64 nStartKey, const OUStringVector &rNames)
virtual void implSetName(sal_Int64 nKey, const OUString &rName) override
Sets the name for the passed key.
Base class of all classes providing names for specific values (name lists).
Definition: dumperbase.hxx:511
void insertRawName(sal_Int64 nKey, const OUString &rName)
Inserts the passed name into the internal map.
Definition: dumperbase.cxx:910
virtual void implProcessConfigItemInt(TextInputStream &rStrm, sal_Int64 nKey, const OUString &rData) override
Definition: dumperbase.cxx:904
virtual void implProcessConfigItemStr(TextInputStream &rStrm, const OUString &rKey, const OUString &rData) override
Definition: dumperbase.cxx:893
const OUString * findRawName(sal_Int64 nKey) const
Returns the name for the passed key, or 0, if nothing found.
Definition: dumperbase.cxx:915
virtual void implSetName(sal_Int64 nKey, const OUString &rName)=0
Derived classes set the name for the passed key.
void includeList(const NameListRef &rxList)
Include all names of the passed list.
Definition: dumperbase.cxx:878
void include(const OUString &rListKeys)
Includes name lists, given in a comma separated list of names of the lists.
Definition: dumperbase.cxx:921
const_iterator end() const
Returns a map iterator pointing one past the last contained name.
Definition: dumperbase.hxx:542
const_iterator begin() const
Returns a map iterator pointing to the first contained name.
Definition: dumperbase.hxx:540
virtual void implIncludeList(const NameListBase &rList)=0
Derived classes insert all names and other settings from the passed list.
const SharedConfigData & mrCfgData
Definition: dumperbase.hxx:581
virtual bool implIsValid() const override
Definition: dumperbase.cxx:888
void exclude(const OUString &rKeys)
Excludes names from the list, given in a comma separated list of their keys.
Definition: dumperbase.cxx:929
virtual ~NameListBase() override
Definition: dumperbase.cxx:869
void setName(sal_Int64 nKey, const String &rName)
Sets a name for the specified key.
Definition: dumperbase.cxx:873
OUStringMap::const_iterator const_iterator
Definition: dumperbase.hxx:514
const NameListRef & getNameList(const Config &rCfg) const
virtual ~ObjectBase() override
Config & cfg() const
virtual bool implIsValid() const override
virtual void implDump()
void construct(const ConfigRef &rxConfig)
const css::uno::Reference< css::uno::XComponentContext > & getContext() const
void writeShortHexItem(const String &rName, Type nData, const NameListWrapper &rListWrp=NO_LIST)
void writeEmptyItem(const String &rName)
void writeGuidItem(const String &rName, const OUString &rGuid)
void addNameToItem(Type nData, const NameListWrapper &rListWrp)
void writeCharItem(const String &rName, sal_Unicode cData)
void writeDecItem(const String &rName, Type nData, const NameListWrapper &rListWrp=NO_LIST)
virtual bool implIsValid() const override
virtual ~OutputObjectBase() override
void writeDateTimeItem(const String &rName, const css::util::DateTime &rDateTime)
void construct(const ObjectBase &rParent, const OUString &rSysFileName)
void writeInfoItem(const String &rName, const String &rData)
void writeArrayItem(const String &rName, const sal_uInt8 *pnData, std::size_t nSize, sal_Unicode cSep=OOX_DUMP_LISTSEP)
void writeStringItem(const String &rName, const OUString &rData)
virtual bool implIsValid() const override
OUStringBuffer maLine
Definition: dumperbase.hxx:995
css::uno::Reference< css::io::XTextOutputStream2 > mxStrm
Definition: dumperbase.hxx:993
void writeHex(Type nData, bool bPrefix=true)
Definition: dumperbase.hxx:967
void writeArray(const sal_uInt8 *pnData, std::size_t nSize, sal_Unicode cSep=OOX_DUMP_LISTSEP)
void writeDec(Type nData, sal_Int32 nWidth=0, sal_Unicode cFill=' ')
Definition: dumperbase.hxx:964
void writeString(const OUString &rStr)
::std::vector< sal_Int32 > maColPos
Definition: dumperbase.hxx:998
void writeAscii(const char *pcStr)
void resetItemIndex(sal_Int64 nIdx=0)
sal_Int32 mnLastItem
void writeItemName(const String &rItemName)
void writeBool(bool bData)
void startTable(sal_Int32 nW1)
void writeDateTime(const css::util::DateTime &rDateTime)
void emptyLine(size_t nCount=1)
Output(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const OUString &rFileName)
void startItem(const String &rItemName)
void writeChar(sal_Unicode cChar, sal_Int32 nCount=1)
BinaryInputStreamRef mxBaseStrm
virtual void implDump() override
virtual bool implStartRecord(BinaryInputStream &rBaseStrm, sal_Int64 &ornRecPos, sal_Int64 &ornRecId, sal_Int64 &ornRecSize)=0
void construct(const ObjectBase &rParent, const BinaryInputStreamRef &rxBaseStrm, const OUString &rSysFileName, const BinaryInputStreamRef &rxRecStrm, const String &rRecNames, const String &rSimpleRecs)
virtual void implWriteExtHeader()
virtual bool implIsValid() const override
void constructRecObjBase(const BinaryInputStreamRef &rxBaseStrm, const String &rRecNames, const String &rSimpleRecs)
NameListWrapper maSimpleRecs
virtual void implDumpRecordBody()
std::shared_ptr< StreamDataSequence > mxRecData
virtual bool implStartRecord(BinaryInputStream &rBaseStrm, sal_Int64 &ornRecPos, sal_Int64 &ornRecId, sal_Int64 &ornRecSize) override
void construct(const ObjectBase &rParent, const BinaryInputStreamRef &rxBaseStrm, const OUString &rSysFileName, const String &rRecNames, const String &rSimpleRecs)
virtual bool implReadRecordHeader(BinaryInputStream &rBaseStrm, sal_Int64 &ornRecId, sal_Int64 &ornRecSize)=0
void eraseNameList(const OUString &rListName)
const OUString * getOption(const OUString &rKey) const
NameListRef getNameList(const OUString &rListName) const
virtual ~SharedConfigData() override
virtual void implProcessConfigItemStr(TextInputStream &rStrm, const OUString &rKey, const OUString &rData) override
SharedConfigData(const OUString &rFileName, const css::uno::Reference< css::uno::XComponentContext > &rxContext, StorageRef xRootStrg, OUString aSysFileName)
void setNameList(const OUString &rListName, const NameListRef &rxList)
void createUnitConverter(const OUString &rData)
void createShortList(const OUString &rData)
bool readConfigFile(const OUString &rFileUrl)
css::uno::Reference< css::uno::XComponentContext > mxContext
Definition: dumperbase.hxx:800
virtual bool implIsValid() const override
virtual ~StorageIterator() override
virtual bool implIsValid() const override
StorageIterator(StorageRef xStrg)
StorageIterator & operator++()
OUStringVector::const_iterator maIt
OUString getName() const
void extractItem(const StorageRef &rxStrg, const OUString &rStrgPath, const OUString &rItemName, std::u16string_view rSysPath, bool bIsStrg, bool bIsStrm)
void construct(const ObjectBase &rParent, const StorageRef &rxStrg, const OUString &rSysPath)
PreferredItemVector maPreferred
void extractStorage(const StorageRef &rxStrg, const OUString &rStrgPath, const OUString &rSysPath)
virtual void implDumpBaseStream(const BinaryInputStreamRef &rxStrm, const OUString &rSysFileName)
virtual bool implIsValid() const override
static OUString getSysFileName(const OUString &rStrmName, std::u16string_view rSysOutPath)
virtual void implDumpStream(const css::uno::Reference< css::io::XInputStream > &rxStrm, const OUString &rStrgPath, const OUString &rStrmName, const OUString &rSysFileName)
void addPreferredStorage(const String &rStrgPath)
void addPreferredStream(const String &rStrmName)
virtual void implDump() override
virtual void implDumpStorage(const StorageRef &rxStrg, const OUString &rStrgPath, const OUString &rSysPath)
void extractStream(StorageBase &rStrg, const OUString &rStrgPath, const OUString &rStrmName, const OUString &rSysFileName)
static void appendShortHex(OUStringBuffer &rStr, sal_uInt8 nData, bool bPrefix=true)
Definition: dumperbase.cxx:329
static void appendIndex(OUStringBuffer &rStr, sal_Int64 nIdx)
Definition: dumperbase.cxx:523
static bool convertStringToInt(sal_Int64 &ornData, std::u16string_view rData)
Definition: dumperbase.cxx:713
static bool convertFromDec(sal_Int64 &ornData, std::u16string_view rData)
Definition: dumperbase.cxx:671
static bool convertStringToBool(std::u16string_view rData)
Definition: dumperbase.cxx:734
static void appendCChar(OUStringBuffer &rStr, sal_Unicode cChar, bool bPrefix=true)
Definition: dumperbase.cxx:453
static FormatType convertToFormatType(std::u16string_view rStr)
Definition: dumperbase.cxx:653
static void appendEncChar(OUStringBuffer &rStr, sal_Unicode cChar, sal_Int32 nCount, bool bPrefix=true)
Definition: dumperbase.cxx:469
static void enclose(OUStringBuffer &rStr, sal_Unicode cOpen, sal_Unicode cClose='\0')
Encloses the passed string with the passed characters.
Definition: dumperbase.cxx:535
static bool convertFromHex(sal_Int64 &ornData, std::u16string_view rData)
Definition: dumperbase.cxx:694
static void appendValue(OUStringBuffer &rStr, Type nData, FormatType eFmtType)
Definition: dumperbase.hxx:360
static OString convertToUtf8(std::u16string_view rStr)
Definition: dumperbase.cxx:622
static void appendToken(OUStringBuffer &rStr, std::u16string_view rToken, sal_Unicode cSep=OOX_DUMP_LISTSEP)
Definition: dumperbase.cxx:516
static void appendBool(OUStringBuffer &rStr, bool bData)
Definition: dumperbase.cxx:446
static void appendBin(OUStringBuffer &rStr, sal_uInt8 nData, bool bDots=true)
Definition: dumperbase.cxx:385
static OUStringPair convertStringToPair(const OUString &rString, sal_Unicode cSep='=')
Definition: dumperbase.cxx:744
static OUString trimTrailingNul(const OUString &rStr)
Definition: dumperbase.cxx:614
static std::u16string_view trimSpaces(std::u16string_view rStr)
Definition: dumperbase.cxx:603
static void appendChar(OUStringBuffer &rStr, sal_Unicode cChar, sal_Int32 nCount)
Definition: dumperbase.cxx:197
static void appendString(OUStringBuffer &rStr, const OUString &rData, sal_Int32 nWidth, sal_Unicode cFill=' ')
Definition: dumperbase.cxx:203
static void appendHex(OUStringBuffer &rStr, sal_uInt8 nData, bool bPrefix=true)
Definition: dumperbase.cxx:265
static void convertStringToStringList(OUStringVector &orVec, const OUString &rData, bool bIgnoreEmpty)
Definition: dumperbase.cxx:763
static DataType convertToDataType(std::u16string_view rStr)
Definition: dumperbase.cxx:627
static void appendEncString(OUStringBuffer &rStr, const OUString &rData, bool bPrefix=true)
Definition: dumperbase.cxx:486
static std::u16string_view getToken(std::u16string_view rData, sal_Int32 &rnPos, sal_Unicode cSep=OOX_DUMP_LISTSEP)
Definition: dumperbase.cxx:530
static void appendDec(OUStringBuffer &rStr, sal_uInt8 nData, sal_Int32 nWidth=0, sal_Unicode cFill=' ')
Definition: dumperbase.cxx:211
static void convertStringToIntList(Int64Vector &orVec, const OUString &rData, bool bIgnoreEmpty)
Definition: dumperbase.cxx:777
static bool convertStringToDouble(double &orfData, std::u16string_view rData)
Definition: dumperbase.cxx:720
bool has() const
Definition: dumperbase.hxx:383
void tab(size_t nCol)
void implDumpLine(const OUString &rLine, sal_uInt32 nLine)
TextLineStreamObject(const ObjectBase &rParent, const BinaryInputStreamRef &rxStrm, rtl_TextEncoding eTextEnc, const OUString &rSysFileName)
virtual void implDumpText(TextInputStream &rTextStrm) override
std::shared_ptr< TextInputStream > mxTextStrm
virtual void implDump() override
void construct(const ObjectBase &rParent, const BinaryInputStreamRef &rxStrm, rtl_TextEncoding eTextEnc, const OUString &rSysFileName)
virtual bool implIsValid() const override
virtual void implDumpText(TextInputStream &rTextStrm)=0
void constructTextStrmObj(rtl_TextEncoding eTextEnc)
virtual void implIncludeList(const NameListBase &rList) override
Empty implementation.
virtual OUString implGetNameDbl(const Config &rCfg, double fValue) const override
Returns the converted value with appended unit name.
UnitConverter(const SharedConfigData &rCfgData)
virtual OUString implGetName(const Config &rCfg, sal_Int64 nKey) const override
Returns the converted value with appended unit name.
virtual void implSetName(sal_Int64 nKey, const OUString &rName) override
Sets the name for the passed key.
virtual void implDumpText(TextInputStream &rTextStrm) override
XmlStreamObject(const ObjectBase &rParent, const BinaryInputStreamRef &rxStrm, const OUString &rSysFileName)
static const sal_Int64 minutePerHour
static const sal_Int64 nanoSecPerDay
static const sal_Int64 nanoSecPerSec
static const sal_Int64 secondPerMinute
int nCount
uno::Reference< uno::XComponentContext > mxContext
sal_Int32 mnCol
#define OOX_DUMP_DUMPEXT
Definition: dumperbase.hxx:73
#define OOX_DUMP_ERR_STREAM
Definition: dumperbase.hxx:71
float u
DocumentType eType
const char * name
sal_Int32 nIndex
OUString aName
sal_uInt16 nPos
std::unique_ptr< sal_Int32[]> pData
@ Exception
void SvStream & rStrm
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
std::u16string_view trim(std::u16string_view str)
static sal_uInt64 lcl_ConvertDouble(double const f)
Definition: dumperbase.cxx:312
::std::pair< OUString, OUString > OUStringPair
Definition: dumperbase.hxx:92
::std::vector< OUString > OUStringVector
Definition: dumperbase.hxx:94
std::shared_ptr< Config > ConfigRef
Definition: dumperbase.hxx:893
constexpr OUStringLiteral OOX_DUMP_UNKNOWN
Definition: dumperbase.hxx:65
FormatType
Specifiers for the output format of values.
Definition: dumperbase.hxx:172
@ FORMATTYPE_BIN
Binary.
Definition: dumperbase.hxx:177
@ FORMATTYPE_HEX
Hexadecimal.
Definition: dumperbase.hxx:175
@ FORMATTYPE_DEC
Decimal.
Definition: dumperbase.hxx:174
@ FORMATTYPE_SHORTHEX
Hexadecimal, as short as possible (no leading zeros).
Definition: dumperbase.hxx:176
@ FORMATTYPE_FIX
Fixed-point.
Definition: dumperbase.hxx:178
@ FORMATTYPE_NONE
No numeric format (e.g. show name only).
Definition: dumperbase.hxx:173
@ FORMATTYPE_BOOL
Boolean ('true' or 'false').
Definition: dumperbase.hxx:179
constexpr OUStringLiteral OOX_DUMP_UNUSED
Definition: dumperbase.hxx:64
const String EMPTY_STRING
Definition: dumperbase.hxx:387
std::shared_ptr< NameListBase > NameListRef
Definition: dumperbase.hxx:499
::std::vector< sal_Int64 > Int64Vector
Definition: dumperbase.hxx:95
DataType
Specifiers for atomic data types.
Definition: dumperbase.hxx:155
@ DATATYPE_UINT64
Unsigned 64-bit integer.
Definition: dumperbase.hxx:164
@ DATATYPE_VOID
No data type.
Definition: dumperbase.hxx:156
@ DATATYPE_FLOAT
Floating-point, single precision.
Definition: dumperbase.hxx:165
@ DATATYPE_INT32
Signed 32-bit integer.
Definition: dumperbase.hxx:161
@ DATATYPE_UINT32
Unsigned 32-bit integer.
Definition: dumperbase.hxx:162
@ DATATYPE_INT16
Signed 16-bit integer.
Definition: dumperbase.hxx:159
@ DATATYPE_INT8
Signed 8-bit integer.
Definition: dumperbase.hxx:157
@ DATATYPE_INT64
Signed 64-bit integer.
Definition: dumperbase.hxx:163
@ DATATYPE_UINT8
Unsigned 8-bit integer.
Definition: dumperbase.hxx:158
@ DATATYPE_DOUBLE
Floating-point, double precision.
Definition: dumperbase.hxx:166
@ DATATYPE_UINT16
Unsigned 16-bit integer.
Definition: dumperbase.hxx:160
const sal_Unicode OOX_DUMP_STRQUOTE
Definition: dumperbase.hxx:75
constexpr OUStringLiteral OOX_DUMP_ERR_NONAME
Definition: dumperbase.hxx:70
void setFlag(Type &ornBitField, Type nMask, bool bSet=true)
Sets or clears (according to bSet) all set bits of nMask in ornBitField.
Definition: helper.hxx:167
std::shared_ptr< StorageBase > StorageRef
Definition: storagebase.hxx:42
bool getFlag(Type nBitField, Type nMask)
Returns true, if at least one of the bits set in nMask is set in nBitField.
Definition: helper.hxx:137
end
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
void(* f)(TrueTypeTable *)
GUIDCNamePair aData
Definition: olehelper.cxx:99
bool operator<(const ExtItemFormatKey &rRight) const
::std::pair< sal_Int64, sal_Int64 > maFilter
Definition: dumperbase.hxx:681
Describes the output format of a data item.
Definition: dumperbase.hxx:204
OUString maItemName
Name of the item.
Definition: dumperbase.hxx:207
OUStringVector::const_iterator parse(const OUStringVector &rFormatVec)
Initializes the struct from a vector of strings containing the item format.
Definition: dumperbase.cxx:162
DataType meDataType
Data type of the item.
Definition: dumperbase.hxx:205
void set(DataType eDataType, FormatType eFmtType, const OUString &rItemName)
Definition: dumperbase.cxx:154
FormatType meFmtType
Output format for the value.
Definition: dumperbase.hxx:206
OUString maListName
Name of a name list to be used for this item.
Definition: dumperbase.hxx:208
#define SAL_MAX_INT64
#define SAL_MAX_UINT8
unsigned char sal_uInt8
#define SAL_MAX_UINT16
sal_uInt16 sal_Unicode
signed char sal_Int8
#define SAL_MAX_UINT32
std::unique_ptr< char[]> aBuffer