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( std::u16string_view 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, std::u16string_view rData, sal_Int32 nWidth, sal_Unicode cFill )
204{
205 appendChar( rStr, cFill, nWidth - rData.size() );
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( OUStringChar(spcHexDigits[ (nData >> 4) & 0x0F ] ) + OUStringChar( 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, std::u16string_view rData, bool bPrefix )
487{
488 size_t nBeg = 0;
489 size_t nIdx = 0;
490 size_t nEnd = rData.size();
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.substr(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( "[" + aToken + "]" );
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( std::u16string_view rStr, sal_Unicode cChar, sal_Int32 nStartPos )
545{
546 size_t nIndex = rStr.find( cChar, nStartPos );
547 return (nIndex == std::u16string_view::npos) ? rStr.size() : nIndex;
548}
549
550OUString lclTrimQuotedStringList( std::u16string_view rStr )
551{
552 OUStringBuffer aBuffer;
553 size_t nPos = 0;
554 size_t nLen = rStr.size();
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 size_t nEnd = lclIndexOf( rStr, OOX_DUMP_CFG_QUOTE, nPos );
567 aToken.append( rStr.substr(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 size_t nEnd = lclIndexOf( rStr, OOX_DUMP_CFG_LISTSEP, nPos );
590 aBuffer.append( rStr.substr(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, std::u16string_view 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, std::u16string_view 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( std::u16string_view rListKeys )
922{
923 OUStringVector aVec;
924 StringHelper::convertStringToStringList( aVec, rListKeys, true );
925 for (auto const& elem : aVec)
927}
928
929void NameListBase::exclude( std::u16string_view 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( OUString::Concat(OOX_DUMP_UNKNOWN) + OUStringChar(OOX_DUMP_ITEMSEP) );
1101 StringHelper::appendShortHex( aUnknown, nKey );
1102 StringHelper::enclose( aUnknown, '(', ')' );
1103 StringHelper::appendToken( aName, aUnknown );
1104 }
1105 return aName.makeStringAndClear();
1106}
1107
1108OUString FlagsList::implGetNameDbl( const Config& /*rCfg*/, double /*fValue*/ ) const
1109{
1110 return OUString();
1111}
1112
1115 if( const FlagsList* pFlagsList = dynamic_cast< const FlagsList* >( &rList ) )
1116 mnIgnore = pFlagsList->mnIgnore;
1117}
1118
1120{
1121 return (mnKey < rRight.mnKey) || ((mnKey == rRight.mnKey) && (maFilter < rRight.maFilter));
1122}
1123
1125 FlagsList( rCfgData )
1126{
1127}
1128
1129void CombiList::implSetName( sal_Int64 nKey, const OUString& rName )
1130{
1131 if( (nKey & (nKey - 1)) != 0 ) // more than a single bit set?
1132 {
1133 ::std::set< ExtItemFormatKey > aItemKeys;
1134 ExtItemFormat aItemFmt;
1135 OUStringVector aRemain = aItemFmt.parse( rName );
1136 for (auto const& elemRemain : aRemain)
1139 if ( aPair.first == "noshift" )
1140 {
1141 aItemFmt.mbShiftValue = StringHelper::convertStringToBool( aPair.second );
1142 }
1143 else if ( aPair.first == "filter" )
1144 {
1145 OUStringPair aFilter = StringHelper::convertStringToPair( aPair.second, '~' );
1146 ExtItemFormatKey aKey( nKey );
1147 if( !aFilter.first.isEmpty() && StringHelper::convertStringToInt( aKey.maFilter.first, aFilter.first ) &&
1148 !aFilter.second.isEmpty() && StringHelper::convertStringToInt( aKey.maFilter.second, aFilter.second ) )
1149 {
1150 if( aKey.maFilter.first == 0 )
1151 aKey.maFilter.second = 0;
1152 aItemKeys.insert( aKey );
1153 }
1154 }
1155 }
1156 if( aItemKeys.empty() )
1157 aItemKeys.insert( ExtItemFormatKey( nKey ) );
1158 for (auto const& itemKey : aItemKeys)
1159 maFmtMap[itemKey] = aItemFmt;
1160 }
1161 else
1162 {
1163 FlagsList::implSetName( nKey, rName );
1164 }
1165}
1166
1167OUString CombiList::implGetName( const Config& rCfg, sal_Int64 nKey ) const
1168{
1169 sal_Int64 nFound = 0;
1170 OUStringBuffer aName;
1171 // add known flag fields
1172 for (auto const& fmt : maFmtMap)
1173 {
1174 const ExtItemFormatKey& rMapKey = fmt.first;
1175 sal_Int64 nMask = rMapKey.mnKey;
1176 if( (nMask != 0) && ((nKey & rMapKey.maFilter.first) == rMapKey.maFilter.second) )
1177 {
1178 const ExtItemFormat& rItemFmt = fmt.second;
1179
1180 sal_uInt64 nUFlags = static_cast< sal_uInt64 >( nKey );
1181 sal_uInt64 nUMask = static_cast< sal_uInt64 >( nMask );
1182 if( rItemFmt.mbShiftValue )
1183 while( (nUMask & 1) == 0 ) { nUFlags >>= 1; nUMask >>= 1; }
1184
1185 sal_uInt64 nUValue = nUFlags & nUMask;
1186 sal_Int64 nSValue = static_cast< sal_Int64 >( nUValue );
1187 if( getFlag< sal_uInt64 >( nUValue, (nUMask + 1) >> 1 ) )
1188 setFlag( nSValue, static_cast< sal_Int64 >( ~nUMask ) );
1189
1190 OUStringBuffer aItem( rItemFmt.maItemName );
1191 OUStringBuffer aValue;
1192 switch( rItemFmt.meDataType )
1193 {
1194 case DATATYPE_INT8: StringHelper::appendValue( aValue, static_cast< sal_Int8 >( nSValue ), rItemFmt.meFmtType ); break;
1195 case DATATYPE_UINT8: StringHelper::appendValue( aValue, static_cast< sal_uInt8 >( nUValue ), rItemFmt.meFmtType ); break;
1196 case DATATYPE_INT16: StringHelper::appendValue( aValue, static_cast< sal_Int16 >( nSValue ), rItemFmt.meFmtType ); break;
1197 case DATATYPE_UINT16: StringHelper::appendValue( aValue, static_cast< sal_uInt16 >( nUValue ), rItemFmt.meFmtType ); break;
1198 case DATATYPE_INT32: StringHelper::appendValue( aValue, static_cast< sal_Int32 >( nSValue ), rItemFmt.meFmtType ); break;
1199 case DATATYPE_UINT32: StringHelper::appendValue( aValue, static_cast< sal_uInt32 >( nUValue ), rItemFmt.meFmtType ); break;
1200 case DATATYPE_INT64: StringHelper::appendValue( aValue, nSValue, rItemFmt.meFmtType ); break;
1201 case DATATYPE_UINT64: StringHelper::appendValue( aValue, nUValue, rItemFmt.meFmtType ); break;
1202 case DATATYPE_FLOAT: StringHelper::appendValue( aValue, static_cast< float >( nSValue ), rItemFmt.meFmtType ); break;
1203 case DATATYPE_DOUBLE: StringHelper::appendValue( aValue, static_cast< double >( nSValue ), rItemFmt.meFmtType ); break;
1204 default:;
1205 }
1206 StringHelper::appendToken( aItem, aValue, OOX_DUMP_ITEMSEP );
1207 if( !rItemFmt.maListName.isEmpty() )
1208 {
1209 OUString aValueName = rCfg.getName( rItemFmt.maListName, static_cast< sal_Int64 >( nUValue ) );
1210 StringHelper::appendToken( aItem, aValueName, OOX_DUMP_ITEMSEP );
1211 }
1212 StringHelper::enclose( aItem, '(', ')' );
1214 setFlag( nFound, nMask );
1215 }
1216 }
1217 setFlag( nKey, nFound, false );
1218 StringHelper::appendToken( aName, FlagsList::implGetName( rCfg, nKey ) );
1219 return aName.makeStringAndClear();
1220}
1221
1223{
1224 if( const CombiList* pCombiList = dynamic_cast< const CombiList* >( &rList ) )
1225 maFmtMap = pCombiList->maFmtMap;
1227}
1228
1230 NameListBase( rCfgData ),
1231 mfFactor( 1.0 )
1232{
1233}
1234
1235void UnitConverter::implSetName( sal_Int64 /*nKey*/, const OUString& /*rName*/ )
1236{
1237 // nothing to do
1238}
1239
1240OUString UnitConverter::implGetName( const Config& rCfg, sal_Int64 nKey ) const
1241{
1242 return implGetNameDbl( rCfg, static_cast< double >( nKey ) );
1243}
1244
1245OUString UnitConverter::implGetNameDbl( const Config& /*rCfg*/, double fValue ) const
1246{
1247 OUStringBuffer aValue;
1248 StringHelper::appendDec( aValue, mfFactor * fValue );
1249 aValue.append( maUnitName );
1250 return aValue.makeStringAndClear();
1251}
1252
1254{
1255}
1256
1258{
1259 if (!mxList)
1260 mxList = rCfg.getNameList( maName );
1261 return mxList;
1262}
1263
1264SharedConfigData::SharedConfigData( const OUString& rFileName,
1265 const Reference< XComponentContext >& rxContext, StorageRef xRootStrg,
1266 OUString aSysFileName ) :
1267 mxContext( rxContext ),
1268 mxRootStrg(std::move( xRootStrg )),
1269 maSysFileName(std::move( aSysFileName )),
1270 mbLoaded( false )
1271{
1272 OUString aFileUrl = InputOutputHelper::convertFileNameToUrl( rFileName );
1273 if( !aFileUrl.isEmpty() )
1274 {
1275 sal_Int32 nNamePos = InputOutputHelper::getFileNamePos( aFileUrl );
1276 maConfigPath = aFileUrl.copy( 0, nNamePos );
1277 mbLoaded = readConfigFile( aFileUrl );
1278 }
1279}
1280
1282{
1283}
1284
1285const OUString* SharedConfigData::getOption( const OUString& rKey ) const
1286{
1287 ConfigDataMap::const_iterator aIt = maConfigData.find( rKey );
1288 return (aIt == maConfigData.end()) ? nullptr : &aIt->second;
1289}
1290
1291void SharedConfigData::setNameList( const OUString& rListName, const NameListRef& rxList )
1292{
1293 if( !rListName.isEmpty() )
1294 maNameLists[ rListName ] = rxList;
1295}
1296
1297void SharedConfigData::eraseNameList( const OUString& rListName )
1298{
1299 maNameLists.erase( rListName );
1300}
1301
1302NameListRef SharedConfigData::getNameList( const OUString& rListName ) const
1303{
1304 NameListRef xList;
1305 NameListMap::const_iterator aIt = maNameLists.find( rListName );
1306 if( aIt != maNameLists.end() )
1307 xList = aIt->second;
1308 return xList;
1309}
1310
1312{
1313 return mbLoaded && mxContext.is() && mxRootStrg && !maSysFileName.isEmpty();
1314}
1315
1317 TextInputStream& rStrm, const OUString& rKey, const OUString& rData )
1318{
1319 if ( rKey == "include-config-file" )
1320 readConfigFile( maConfigPath + rData );
1321 else if ( rKey == "constlist" )
1322 readNameList< ConstList >( rStrm, rData );
1323 else if ( rKey == "multilist" )
1324 readNameList< MultiList >( rStrm, rData );
1325 else if ( rKey == "flagslist" )
1326 readNameList< FlagsList >( rStrm, rData );
1327 else if ( rKey == "combilist" )
1328 readNameList< CombiList >( rStrm, rData );
1329 else if ( rKey == "shortlist" )
1330 createShortList( rData );
1331 else if ( rKey == "unitconverter" )
1332 createUnitConverter( rData );
1333 else
1334 maConfigData[ rKey ] = rData;
1335}
1336
1337bool SharedConfigData::readConfigFile( const OUString& rFileUrl )
1338{
1339 bool bLoaded = maConfigFiles.count( rFileUrl ) > 0;
1340 if( !bLoaded )
1341 {
1342 Reference< XInputStream > xInStrm = InputOutputHelper::openInputStream( mxContext, rFileUrl );
1343 TextInputStream aTxtStrm( mxContext, xInStrm, RTL_TEXTENCODING_UTF8 );
1344 if( !aTxtStrm.isEof() )
1345 {
1346 maConfigFiles.insert( rFileUrl );
1347 readConfigBlockContents( aTxtStrm );
1348 bLoaded = true;
1349 }
1350 }
1351 return bLoaded;
1352}
1353
1354void SharedConfigData::createShortList( std::u16string_view rData )
1355{
1356 OUStringVector aDataVec;
1357 StringHelper::convertStringToStringList( aDataVec, rData, false );
1358 if( aDataVec.size() < 3 )
1359 return;
1360
1361 sal_Int64 nStartKey;
1362 if( StringHelper::convertStringToInt( nStartKey, aDataVec[ 1 ] ) )
1363 {
1364 std::shared_ptr< MultiList > xList = createNameList< MultiList >( aDataVec[ 0 ] );
1365 if( xList )
1366 {
1367 aDataVec.erase( aDataVec.begin(), aDataVec.begin() + 2 );
1368 xList->setNamesFromVec( nStartKey, aDataVec );
1369 }
1370 }
1371}
1372
1373void SharedConfigData::createUnitConverter( std::u16string_view rData )
1374{
1375 OUStringVector aDataVec;
1376 StringHelper::convertStringToStringList( aDataVec, rData, false );
1377 if( aDataVec.size() < 2 )
1378 return;
1379
1380 OUString aFactor = aDataVec[ 1 ];
1381 bool bRecip = aFactor.startsWith("/");
1382 if( bRecip )
1383 aFactor = aFactor.copy( 1 );
1384 double fFactor;
1385 if( StringHelper::convertStringToDouble( fFactor, aFactor ) && (fFactor != 0.0) )
1386 {
1387 std::shared_ptr< UnitConverter > xList = createNameList< UnitConverter >( aDataVec[ 0 ] );
1388 if( xList )
1389 {
1390 xList->setFactor( bRecip ? (1.0 / fFactor) : fFactor );
1391 if( aDataVec.size() >= 3 )
1392 xList->setUnitName( aDataVec[ 2 ] );
1393 }
1394 }
1395}
1396
1397Config::Config( const char* pcEnvVar, const FilterBase& rFilter )
1398{
1399 construct( pcEnvVar, rFilter );
1400}
1401
1402Config::Config( const char* pcEnvVar, const Reference< XComponentContext >& rxContext, const StorageRef& rxRootStrg, const OUString& rSysFileName )
1403{
1404 construct( pcEnvVar, rxContext, rxRootStrg, rSysFileName );
1405}
1406
1408{
1409}
1410
1411void Config::construct( const char* pcEnvVar, const FilterBase& rFilter )
1412{
1413 if( !rFilter.getFileUrl().isEmpty() )
1414 construct( pcEnvVar, rFilter.getComponentContext(), rFilter.getStorage(), rFilter.getFileUrl() );
1415}
1416
1417void Config::construct( const char* pcEnvVar, const Reference< XComponentContext >& rxContext, const StorageRef& rxRootStrg, const OUString& rSysFileName )
1418{
1419 if( pcEnvVar && rxRootStrg && !rSysFileName.isEmpty() )
1420 if( const char* pcFileName = ::getenv( pcEnvVar ) )
1421 mxCfgData = std::make_shared<SharedConfigData>( OUString::createFromAscii( pcFileName ), rxContext, rxRootStrg, rSysFileName );
1422}
1423
1424const OUString& Config::getStringOption( const String& rKey, const OUString& rDefault ) const
1425{
1426 const OUString* pData = implGetOption( rKey );
1427 return pData ? *pData : rDefault;
1428}
1429
1430bool Config::getBoolOption( const String& rKey, bool bDefault ) const
1431{
1432 const OUString* pData = implGetOption( rKey );
1433 return pData ? StringHelper::convertStringToBool( *pData ) : bDefault;
1434}
1435
1437{
1438 return getBoolOption( "enable-dumper", false );
1439}
1440
1442{
1443 return getBoolOption( "enable-import", true );
1444}
1445
1446void Config::eraseNameList( const String& rListName )
1447{
1448 mxCfgData->eraseNameList( rListName );
1449}
1450
1451NameListRef Config::getNameList( const String& rListName ) const
1452{
1453 return mxCfgData->getNameList( rListName );
1454}
1455
1457{
1458 return isValid( mxCfgData );
1459}
1460
1461const OUString* Config::implGetOption( const OUString& rKey ) const
1462{
1463 return mxCfgData->getOption( rKey );
1464}
1465
1466Output::Output( const Reference< XComponentContext >& rxContext, const OUString& rFileName ) :
1467 mxStrm( InputOutputHelper::openTextOutputStream( rxContext, rFileName, RTL_TEXTENCODING_UTF8 ) ),
1468 mnCol( 0 ),
1469 mnItemLevel( 0 ),
1470 mnMultiLevel( 0 ),
1471 mnItemIdx( 0 ),
1472 mnLastItem( 0 )
1473{
1474 if( mxStrm.is() )
1475 mxStrm->writeString( OUString( OOX_DUMP_BOM ) );
1476}
1477
1479{
1480 if( maLine.getLength() > 0 )
1481 {
1482 mxStrm->writeString( maIndent );
1483 maLine.append( '\n' );
1484 mxStrm->writeString( maLine.makeStringAndClear() );
1485 mnCol = 0;
1486 mnLastItem = 0;
1487 }
1488}
1489
1491{
1492 for( size_t nIdx = 0; nIdx < nCount; ++nIdx )
1493 mxStrm->writeString( OUString('\n') );
1494}
1495
1497{
1498 OUStringBuffer aBuffer( maIndent );
1499 StringHelper::appendChar( aBuffer, ' ', OOX_DUMP_INDENT );
1500 maIndent = aBuffer.makeStringAndClear();
1501}
1502
1504{
1505 if( maIndent.getLength() >= OOX_DUMP_INDENT )
1506 maIndent = maIndent.copy( OOX_DUMP_INDENT );
1507}
1508
1509void Output::startTable( sal_Int32 nW1 )
1510{
1511 startTable( 1, &nW1 );
1512}
1513
1514void Output::startTable( sal_Int32 nW1, sal_Int32 nW2 )
1515{
1516 sal_Int32 pnColWidths[ 2 ];
1517 pnColWidths[ 0 ] = nW1;
1518 pnColWidths[ 1 ] = nW2;
1519 startTable( 2, pnColWidths );
1520}
1521
1522void Output::startTable( sal_Int32 nW1, sal_Int32 nW2, sal_Int32 nW3, sal_Int32 nW4 )
1523{
1524 sal_Int32 pnColWidths[ 4 ];
1525 pnColWidths[ 0 ] = nW1;
1526 pnColWidths[ 1 ] = nW2;
1527 pnColWidths[ 2 ] = nW3;
1528 pnColWidths[ 3 ] = nW4;
1529 startTable( 4, pnColWidths );
1530}
1531
1532void Output::startTable( size_t nColCount, const sal_Int32* pnColWidths )
1533{
1534 maColPos.clear();
1535 maColPos.push_back( 0 );
1536 sal_Int32 nColPos = 0;
1537 for( size_t nCol = 0; nCol < nColCount; ++nCol )
1538 {
1539 nColPos = nColPos + pnColWidths[ nCol ];
1540 maColPos.push_back( nColPos );
1541 }
1542}
1543
1545{
1546 tab( mnCol + 1 );
1547}
1548
1549void Output::tab( size_t nCol )
1550{
1551 mnCol = nCol;
1552 if( mnCol < maColPos.size() )
1553 {
1554 sal_Int32 nColPos = maColPos[ mnCol ];
1555 if( maLine.getLength() >= nColPos )
1556 maLine.setLength( ::std::max< sal_Int32 >( nColPos - 1, 0 ) );
1557 StringHelper::appendChar( maLine, ' ', nColPos - maLine.getLength() );
1558 }
1559 else
1560 {
1562 }
1563}
1564
1566{
1567 maColPos.clear();
1568}
1569
1570void Output::resetItemIndex( sal_Int64 nIdx )
1571{
1572 mnItemIdx = nIdx;
1573}
1574
1575void Output::startItem( const String& rItemName )
1576{
1577 if( mnItemLevel == 0 )
1578 {
1579 if( (mnMultiLevel > 0) && (maLine.getLength() > 0) )
1580 tab();
1581 if( rItemName.has() )
1582 {
1583 writeItemName( rItemName );
1584 writeChar( OOX_DUMP_ITEMSEP );
1585 }
1586 }
1587 ++mnItemLevel;
1588 mnLastItem = maLine.getLength();
1589}
1590
1592{
1593 if( mnItemLevel > 0 )
1594 {
1595 if( (maLine.getLength() == 0) || (maLine[ maLine.getLength() - 1 ] != OOX_DUMP_ITEMSEP) )
1596 writeChar( OOX_DUMP_ITEMSEP );
1597 mnLastItem = maLine.getLength();
1598 }
1599}
1600
1602{
1603 if( mnItemLevel > 0 )
1604 {
1605 maLastItem = maLine.copy( mnLastItem ).makeStringAndClear();
1606 if( maLastItem.isEmpty() && mnLastItem > 0 && maLine[ mnLastItem - 1 ] == OOX_DUMP_ITEMSEP )
1607 maLine.setLength( mnLastItem - 1 );
1608 --mnItemLevel;
1609 }
1610 if( mnItemLevel == 0 )
1611 {
1612 if( mnMultiLevel == 0 )
1613 newLine();
1614 }
1615 else
1616 contItem();
1617}
1618
1620{
1621 ++mnMultiLevel;
1622}
1623
1625{
1626 if( mnMultiLevel > 0 )
1627 --mnMultiLevel;
1628 if( mnMultiLevel == 0 )
1629 newLine();
1630}
1631
1632void Output::writeChar( sal_Unicode cChar, sal_Int32 nCount )
1633{
1635}
1636
1637void Output::writeAscii( const char* pcStr )
1638{
1639 if( pcStr )
1640 maLine.appendAscii( pcStr );
1641}
1642
1643void Output::writeString( std::u16string_view rStr )
1644{
1647
1648void Output::writeArray( const sal_uInt8* pnData, std::size_t nSize, sal_Unicode cSep )
1649{
1650 const sal_uInt8* pnEnd = pnData ? (pnData + nSize) : nullptr;
1651 for( const sal_uInt8* pnByte = pnData; pnByte < pnEnd; ++pnByte )
1652 {
1653 if( pnByte > pnData )
1654 writeChar( cSep );
1655 writeHex( *pnByte, false );
1656 }
1657}
1658
1659void Output::writeBool( bool bData )
1660{
1662}
1663
1664void Output::writeDateTime( const util::DateTime& rDateTime )
1665{
1666 writeDec( rDateTime.Year, 4, '0' );
1667 writeChar( '-' );
1668 writeDec( rDateTime.Month, 2, '0' );
1669 writeChar( '-' );
1670 writeDec( rDateTime.Day, 2, '0' );
1671 writeChar( 'T' );
1672 writeDec( rDateTime.Hours, 2, '0' );
1673 writeChar( ':' );
1674 writeDec( rDateTime.Minutes, 2, '0' );
1675 writeChar( ':' );
1676 writeDec( rDateTime.Seconds, 2, '0' );
1677}
1678
1680{
1681 return mxStrm.is();
1682}
1683
1684void Output::writeItemName( const String& rItemName )
1685{
1686 if( rItemName.has() && (rItemName[ 0 ] == '#') )
1687 {
1688 writeString( rItemName.subView( 1 ) );
1691 else
1692 writeString( rItemName );
1693}
1694
1696 mxStrg(std::move( xStrg ))
1697{
1698 if( mxStrg )
1699 mxStrg->getElementNames( maNames );
1700 maIt = maNames.begin();
1701}
1702
1704{
1705}
1706
1708{
1709 if( maIt != maNames.end() )
1710 ++maIt;
1711 return *this;
1712}
1713
1715{
1716 OUString aName;
1717 if( maIt != maNames.end() )
1718 aName = *maIt;
1719 return aName;
1720}
1721
1723{
1724 return isValid() && mxStrg->openInputStream( *maIt ).is();
1725}
1726
1728{
1729 if( !isValid() )
1730 return false;
1731 StorageRef xStrg = mxStrg->openSubStorage( *maIt, false );
1732 return xStrg && xStrg->isStorage();
1733}
1734
1736{
1737 return mxStrg && mxStrg->isStorage() && (maIt != maNames.end());
1738}
1739
1741{
1742}
1743
1744void ObjectBase::construct( const ConfigRef& rxConfig )
1745{
1746 mxConfig = rxConfig;
1747}
1748
1749void ObjectBase::construct( const ObjectBase& rParent )
1750{
1751 *this = rParent;
1752}
1753
1755{
1756 if( isValid() )
1757 implDump();
1758}
1759
1761{
1762 return isValid( mxConfig );
1763}
1764
1766{
1767}
1768
1769void StorageObjectBase::construct( const ObjectBase& rParent, const StorageRef& rxStrg, const OUString& rSysPath )
1770{
1771 ObjectBase::construct( rParent );
1772 mxStrg = rxStrg;
1773 maSysPath = rSysPath;
1774}
1775
1777{
1778 ObjectBase::construct( rParent );
1780 {
1783 }
1784}
1785
1787{
1788 return mxStrg && !maSysPath.isEmpty() && ObjectBase::implIsValid();
1789}
1790
1792{
1793 bool bIsStrg = mxStrg->isStorage();
1794 bool bIsRoot = mxStrg->isRootStorage();
1795 Reference< XInputStream > xBaseStrm;
1796 if( !bIsStrg )
1797 xBaseStrm = mxStrg->openInputStream( OUString() );
1798
1799 OUString aSysOutPath = maSysPath;
1800 if( bIsRoot ) try
1801 {
1802 aSysOutPath += OOX_DUMP_DUMPEXT;
1803 Reference<XSimpleFileAccess3> xFileAccess(SimpleFileAccess::create(getContext()));
1804 xFileAccess->kill( aSysOutPath );
1805 }
1806 catch( Exception& )
1807 {
1808 }
1809
1810 if( bIsStrg )
1811 {
1812 extractStorage( mxStrg, OUString(), aSysOutPath );
1813 }
1814 else if( xBaseStrm.is() )
1815 {
1816 BinaryInputStreamRef xInStrm( std::make_shared<BinaryXInputStream>( xBaseStrm, false ) );
1817 xInStrm->seekToStart();
1818 implDumpBaseStream( xInStrm, aSysOutPath );
1819 }
1820}
1821
1822void StorageObjectBase::implDumpStream( const Reference< XInputStream >&, const OUString&, const OUString&, const OUString& )
1823{
1824}
1825
1826void StorageObjectBase::implDumpStorage( const StorageRef& rxStrg, const OUString& rStrgPath, const OUString& rSysPath )
1827{
1828 extractStorage( rxStrg, rStrgPath, rSysPath );
1829}
1830
1832{
1833}
1834
1836{
1837 if( rStrmName.has() )
1838 maPreferred.emplace_back( rStrmName, false );
1839}
1840
1842{
1843 if( rStrgPath.has() )
1844 maPreferred.emplace_back( rStrgPath, true );
1845}
1846
1848 std::u16string_view rStrmName, std::u16string_view rSysOutPath )
1849{
1850 // encode all characters < 0x20
1851 OUStringBuffer aBuffer;
1852 StringHelper::appendEncString( aBuffer, rStrmName, false );
1853
1854 // replace all characters reserved in file system
1855 OUString aFileName = aBuffer.makeStringAndClear();
1856 static const sal_Unicode spcReserved[] = { '/', '\\', ':', '*', '?', '<', '>', '|' };
1857 for(const sal_Unicode cChar : spcReserved)
1858 aFileName = aFileName.replace(cChar, '_');
1859
1860 // build full path
1861 return OUString::Concat(rSysOutPath) + "/" + aFileName;
1862}
1863
1864void StorageObjectBase::extractStream( StorageBase& rStrg, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName )
1865{
1866 BinaryXInputStream aInStrm( rStrg.openInputStream( rStrmName ), true );
1867 if( !aInStrm.isEof() )
1868 {
1869 BinaryXOutputStream aOutStrm( InputOutputHelper::openOutputStream( getContext(), rSysFileName ), true );
1870 if( !aOutStrm.isEof() )
1871 aInStrm.copyToStream( aOutStrm );
1872 }
1873 Reference< XInputStream > xDumpStrm = InputOutputHelper::openInputStream( getContext(), rSysFileName );
1874 if( xDumpStrm.is() )
1875 implDumpStream( xDumpStrm, rStrgPath, rStrmName, rSysFileName );
1876}
1877
1878void StorageObjectBase::extractStorage( const StorageRef& rxStrg, const OUString& rStrgPath, const OUString& rSysPath )
1879{
1880 // create directory in file system
1881 ::osl::FileBase::RC eRes = ::osl::Directory::create( rSysPath );
1882 if( (eRes != ::osl::FileBase::E_None) && (eRes != ::osl::FileBase::E_EXIST) )
1883 return;
1884
1885 // process preferred storages and streams in root storage first
1886 if( rStrgPath.isEmpty() )
1887 {
1888 for (auto const& elemPreferred : maPreferred)
1889 extractItem( rxStrg, rStrgPath, elemPreferred.maName, rSysPath, elemPreferred.mbStorage, !elemPreferred.mbStorage );
1890 }
1891
1892 // process children of the storage
1893 for( StorageIterator aIt( rxStrg ); aIt.isValid(); ++aIt )
1894 {
1895 // skip processed preferred items
1896 OUString aItemName = aIt.getName();
1897 bool bFound = false;
1898 if( rStrgPath.isEmpty() )
1899 {
1900 for (auto const& elemPreferred : maPreferred)
1901 {
1902 bFound = elemPreferred.maName == aItemName;
1903 if (bFound)
1904 break;
1905 }
1906 }
1907 if( !bFound )
1908 extractItem( rxStrg, rStrgPath, aItemName, rSysPath, aIt.isStorage(), aIt.isStream() );
1909 }
1910}
1911
1912void StorageObjectBase::extractItem( const StorageRef& rxStrg, const OUString& rStrgPath, const OUString& rItemName, std::u16string_view rSysPath, bool bIsStrg, bool bIsStrm )
1913{
1914 OUString aSysFileName = getSysFileName( rItemName, rSysPath );
1915 if( bIsStrg )
1916 {
1917 OUStringBuffer aStrgPath( rStrgPath );
1918 StringHelper::appendToken( aStrgPath, rItemName, '/' );
1919 implDumpStorage( rxStrg->openSubStorage( rItemName, false ), aStrgPath.makeStringAndClear(), aSysFileName );
1920 }
1921 else if( bIsStrm )
1922 {
1923 extractStream( *rxStrg, rStrgPath, rItemName, aSysFileName );
1924 }
1925}
1926
1928{
1929}
1930
1931void OutputObjectBase::construct( const ObjectBase& rParent, const OUString& rSysFileName )
1932{
1933 ObjectBase::construct( rParent );
1935 {
1936 maSysFileName = rSysFileName;
1937 mxOut = std::make_shared<Output>( getContext(), rSysFileName + OOX_DUMP_DUMPEXT );
1938 }
1939}
1940
1942{
1943 *this = rParent;
1944}
1945
1947{
1948 return isValid( mxOut ) && ObjectBase::implIsValid();
1949}
1950
1952{
1953 ItemGuard aItem( mxOut, rName );
1954}
1955
1956void OutputObjectBase::writeInfoItem( const String& rName, const String& rData )
1957{
1958 ItemGuard aItem( mxOut, rName );
1959 mxOut->writeString( rData );
1960}
1961
1963{
1964 ItemGuard aItem( mxOut, rName );
1965 mxOut->writeChar( OOX_DUMP_STRQUOTE );
1966 mxOut->writeChar( cData );
1967 mxOut->writeChar( OOX_DUMP_STRQUOTE );
1968}
1969
1970void OutputObjectBase::writeStringItem( const String& rName, std::u16string_view rData )
1971{
1972 ItemGuard aItem( mxOut, rName );
1973 mxOut->writeAscii( "(len=" );
1974 mxOut->writeDec( sal_Int32(rData.size()) );
1975 mxOut->writeAscii( ")," );
1976 OUStringBuffer aValue( rData.substr( 0, ::std::min( sal_Int32(rData.size()), OOX_DUMP_MAXSTRLEN ) ) );
1978 mxOut->writeString( aValue.makeStringAndClear() );
1979 if( rData.size() > OOX_DUMP_MAXSTRLEN )
1980 mxOut->writeAscii( ",cut" );
1981}
1982
1983void OutputObjectBase::writeArrayItem( const String& rName, const sal_uInt8* pnData, std::size_t nSize, sal_Unicode cSep )
1984{
1985 ItemGuard aItem( mxOut, rName );
1986 mxOut->writeArray( pnData, nSize, cSep );
1987}
1988
1989void OutputObjectBase::writeDateTimeItem( const String& rName, const util::DateTime& rDateTime )
1990{
1991 ItemGuard aItem( mxOut, rName );
1992 mxOut->writeDateTime( rDateTime );
1993}
1994
1995void OutputObjectBase::writeGuidItem( const String& rName, const OUString& rGuid )
1996{
1997 ItemGuard aItem( mxOut, rName );
1998 mxOut->writeString( rGuid );
1999 aItem.cont();
2000 mxOut->writeString( cfg().getStringOption( rGuid, OUString() ) );
2001}
2002
2004{
2005}
2006
2007void InputObjectBase::construct( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName )
2008{
2009 OutputObjectBase::construct( rParent, rSysFileName );
2010 mxStrm = rxStrm;
2011}
2012
2014{
2015 OutputObjectBase::construct( rParent );
2016 mxStrm = rxStrm;
2017}
2018
2020{
2021 *this = rParent;
2022}
2023
2025{
2027}
2028
2029void InputObjectBase::skipBlock( sal_Int64 nBytes, bool bShowSize )
2030{
2031 sal_Int64 nEndPos = ::std::min< sal_Int64 >( mxStrm->tell() + nBytes, mxStrm->size() );
2032 if( mxStrm->tell() < nEndPos )
2033 {
2034 if( bShowSize )
2035 writeDecItem( "skipped-data-size", static_cast< sal_uInt64 >( nEndPos - mxStrm->tell() ) );
2036 mxStrm->seek( nEndPos );
2037 }
2038}
2039
2040void InputObjectBase::dumpRawBinary( sal_Int64 nBytes, bool bShowOffset, bool bStream )
2041{
2042 TableGuard aTabGuard( mxOut,
2043 bShowOffset ? 12 : 0,
2044 3 * OOX_DUMP_BYTESPERLINE / 2 + 1,
2045 3 * OOX_DUMP_BYTESPERLINE / 2 + 1,
2046 OOX_DUMP_BYTESPERLINE / 2 + 1 );
2047
2048 sal_Int64 nMaxShowSize = cfg().getIntOption< sal_Int64 >(
2049 bStream ? "max-binary-stream-size" : "max-binary-data-size", SAL_MAX_INT64 );
2050
2051 bool bSeekable = mxStrm->size() >= 0;
2052 sal_Int64 nEndPos = bSeekable ? ::std::min< sal_Int64 >( mxStrm->tell() + nBytes, mxStrm->size() ) : 0;
2053 sal_Int64 nDumpEnd = bSeekable ? ::std::min< sal_Int64 >( mxStrm->tell() + nMaxShowSize, nEndPos ) : nMaxShowSize;
2054 sal_Int64 nPos = bSeekable ? mxStrm->tell() : 0;
2055 bool bLoop = true;
2056
2057 while( bLoop && (nPos < nDumpEnd) )
2058 {
2059 mxOut->writeHex( static_cast< sal_uInt32 >( nPos ) );
2060 mxOut->tab();
2061
2062 sal_uInt8 pnLineData[ OOX_DUMP_BYTESPERLINE ];
2063 sal_Int32 nLineSize = bSeekable ? ::std::min( static_cast< sal_Int32 >( nDumpEnd - mxStrm->tell() ), OOX_DUMP_BYTESPERLINE ) : OOX_DUMP_BYTESPERLINE;
2064 sal_Int32 nReadSize = mxStrm->readMemory( pnLineData, nLineSize );
2065 bLoop = nReadSize == nLineSize;
2066 nPos += nReadSize;
2067
2068 if( nReadSize > 0 )
2069 {
2070 const sal_uInt8* pnByte = nullptr;
2071 const sal_uInt8* pnEnd = nullptr;
2072 for( pnByte = pnLineData, pnEnd = pnLineData + nReadSize; pnByte != pnEnd; ++pnByte )
2073 {
2074 if( (pnByte - pnLineData) == (OOX_DUMP_BYTESPERLINE / 2) ) mxOut->tab();
2075 mxOut->writeHex( *pnByte, false );
2076 mxOut->writeChar( ' ' );
2077 }
2078
2079 aTabGuard.tab( 3 );
2080 for( pnByte = pnLineData, pnEnd = pnLineData + nReadSize; pnByte != pnEnd; ++pnByte )
2081 {
2082 if( (pnByte - pnLineData) == (OOX_DUMP_BYTESPERLINE / 2) ) mxOut->tab();
2083 mxOut->writeChar( static_cast< sal_Unicode >( (*pnByte < 0x20) ? '.' : *pnByte ) );
2084 }
2085 mxOut->newLine();
2086 }
2087 }
2088
2089 // skip undumped data
2090 if( bSeekable )
2091 skipBlock( nEndPos - mxStrm->tell() );
2092}
2093
2094void InputObjectBase::dumpBinary( const String& rName, sal_Int64 nBytes, bool bShowOffset )
2095{
2096 {
2097 MultiItemsGuard aMultiGuard( mxOut );
2098 writeEmptyItem( rName );
2099 writeDecItem( "size", nBytes );
2100 }
2101 IndentGuard aIndGuard( mxOut );
2102 dumpRawBinary( nBytes, bShowOffset );
2103}
2104
2105void InputObjectBase::dumpRemaining( sal_Int64 nBytes )
2106{
2107 if( nBytes > 0 )
2108 {
2109 if( cfg().getBoolOption( "show-trailing-unknown", true ) )
2110 dumpBinary( "remaining-data", nBytes, false );
2111 else
2112 skipBlock( nBytes );
2113 }
2114}
2115
2117{
2118 if( mxStrm->isEof() || (mxStrm->tell() > nPos) )
2119 writeInfoItem( "stream-state", OOX_DUMP_ERR_STREAM );
2120 else
2121 dumpRemaining( nPos - mxStrm->tell() );
2122 mxStrm->seek( nPos );
2123}
2124
2126{
2127 dumpRemainingTo( mxStrm->size() );
2128}
2129
2130void InputObjectBase::dumpArray( const String& rName, sal_Int32 nBytes, sal_Unicode cSep )
2131{
2132 sal_Int32 nDumpSize = getLimitedValue< sal_Int32, sal_Int64 >( mxStrm->size() - mxStrm->tell(), 0, nBytes );
2133 if( nDumpSize > OOX_DUMP_MAXARRAY )
2134 {
2135 dumpBinary( rName, nBytes, false );
2136 }
2137 else if( nDumpSize > 1 )
2138 {
2139 sal_uInt8 pnData[ OOX_DUMP_MAXARRAY ];
2140 mxStrm->readMemory( pnData, nDumpSize );
2141 writeArrayItem( rName, pnData, nDumpSize, cSep );
2142 }
2143 else if( nDumpSize == 1 )
2144 dumpHex< sal_uInt8 >( rName );
2145}
2146
2148{
2149 sal_uInt16 nChar = mxStrm->readuInt16();
2150 sal_Unicode cChar = static_cast< sal_Unicode >( nChar );
2151 writeCharItem( rName( "char" ), cChar );
2152 return cChar;
2153}
2154
2155OUString InputObjectBase::dumpCharArray( const String& rName, sal_Int32 nLen, rtl_TextEncoding eTextEnc, bool bHideTrailingNul )
2156{
2157 sal_Int32 nDumpSize = getLimitedValue< sal_Int32, sal_Int64 >( mxStrm->size() - mxStrm->tell(), 0, nLen );
2158 OUString aString;
2159 if( nDumpSize > 0 )
2160 {
2161 ::std::vector< char > aBuffer( static_cast< std::size_t >( nLen ) + 1 );
2162 sal_Int32 nCharsRead = mxStrm->readMemory(aBuffer.data(), nLen);
2163 aBuffer[ nCharsRead ] = 0;
2164 aString = OStringToOUString(std::string_view(aBuffer.data()), eTextEnc);
2165 }
2166 if( bHideTrailingNul )
2167 aString = StringHelper::trimTrailingNul( aString );
2168 writeStringItem( rName( "text" ), aString );
2169 return aString;
2170}
2171
2172OUString InputObjectBase::dumpUnicodeArray( const String& rName, sal_Int32 nLen, bool bHideTrailingNul )
2173{
2174 OUStringBuffer aBuffer;
2175 for( sal_Int32 nIndex = 0; !mxStrm->isEof() && (nIndex < nLen); ++nIndex )
2176 {
2177 aBuffer.append( static_cast< sal_Unicode >( mxStrm->readuInt16() ) );
2178 }
2179 OUString aString = aBuffer.makeStringAndClear();
2180 if( bHideTrailingNul )
2181 aString = StringHelper::trimTrailingNul( aString );
2182 writeStringItem( rName( "text" ), aString );
2183 return aString;
2184}
2185
2186util::DateTime InputObjectBase::dumpFileTime( const String& rName )
2187{
2188 util::DateTime aDateTime;
2189
2190 ItemGuard aItem( mxOut, rName( "file-time" ) );
2191 sal_Int64 nFileTime = dumpDec< sal_Int64 >( EMPTY_STRING );
2192 // file time is in 10^-7 seconds (100 nanoseconds), convert to nanoseconds
2193 nFileTime *= 100;
2194 // entire days
2195 sal_Int64 nDays = nFileTime / sal_Int64( ::tools::Time::nanoSecPerDay );
2196 // number of entire years
2197 sal_Int64 nYears = (nDays - (nDays / (4 * 365)) + (nDays / (100 * 365)) - (nDays / (400 * 365))) / 365;
2198 // remaining days in the year
2199 sal_Int64 nDaysInYear = nDays - (nYears * 365 + nYears / 4 - nYears / 100 + nYears / 400);
2200 // the year (file dates start from 1601-01-01)
2201 aDateTime.Year = static_cast< sal_uInt16 >( 1601 + nYears );
2202 // leap year?
2203 bool bLeap = ((aDateTime.Year % 4 == 0) && (aDateTime.Year % 100 != 0)) || (aDateTime.Year % 400 == 0);
2204 // static arrays with number of days in month
2205 static const sal_Int64 spnDaysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
2206 static const sal_Int64 spnDaysInMonthL[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
2207 const sal_Int64* pnDaysInMonth = bLeap ? spnDaysInMonthL : spnDaysInMonth;
2208 // the month
2209 aDateTime.Month = 1;
2210 while( nDaysInYear >= *pnDaysInMonth )
2211 {
2212 nDaysInYear -= *pnDaysInMonth++;
2213 ++aDateTime.Month;
2214 }
2215 // the day
2216 aDateTime.Day = static_cast< sal_uInt16 >( nDaysInYear + 1 );
2217 // number of nanoseconds in the day
2218 sal_Int64 nTimeInDay = nFileTime % sal_Int64( ::tools::Time::nanoSecPerDay );
2219 // nanoseconds
2220 aDateTime.NanoSeconds = static_cast< sal_uInt32 >( nTimeInDay % ::tools::Time::nanoSecPerSec );
2221 nTimeInDay /= ::tools::Time::nanoSecPerSec;
2222 // seconds
2223 aDateTime.Seconds = static_cast< sal_uInt16 >( nTimeInDay % ::tools::Time::secondPerMinute );
2224 nTimeInDay /= ::tools::Time::secondPerMinute;
2225 // minutes
2226 aDateTime.Minutes = static_cast< sal_uInt16 >( nTimeInDay % ::tools::Time::minutePerHour );
2227 nTimeInDay /= ::tools::Time::minutePerHour;
2228 // hours
2229 aDateTime.Hours = static_cast< sal_uInt16 >( nTimeInDay );
2230
2231 writeDateTimeItem( EMPTY_STRING, aDateTime );
2232 return aDateTime;
2233}
2234
2235OUString InputObjectBase::dumpGuid( const String& rName )
2236{
2237 OUStringBuffer aBuffer;
2238 sal_uInt32 nData32;
2239 sal_uInt16 nData16;
2240 sal_uInt8 nData8;
2241
2242 nData32 = mxStrm->readuInt32();
2243 StringHelper::appendHex( aBuffer, nData32, false );
2244 aBuffer.append( '-' );
2245 nData16 = mxStrm->readuInt16();
2246 StringHelper::appendHex( aBuffer, nData16, false );
2247 aBuffer.append( '-' );
2248 nData16 = mxStrm->readuInt16();
2249 StringHelper::appendHex( aBuffer, nData16, false );
2250 aBuffer.append( '-' );
2251 nData8 = mxStrm->readuChar();
2252 StringHelper::appendHex( aBuffer, nData8, false );
2253 nData8 = mxStrm->readuChar( );
2254 StringHelper::appendHex( aBuffer, nData8, false );
2255 aBuffer.append( '-' );
2256 for( int nIndex = 0; nIndex < 6; ++nIndex )
2257 {
2258 nData8 = mxStrm->readuChar( );
2259 StringHelper::appendHex( aBuffer, nData8, false );
2260 }
2261 StringHelper::enclose( aBuffer, '{', '}' );
2262 OUString aGuid = aBuffer.makeStringAndClear();
2263 writeGuidItem( rName( "guid" ), aGuid );
2264 return aGuid;
2265}
2266
2268{
2269 switch( rItemFmt.meDataType )
2270 {
2271 case DATATYPE_VOID: break;
2272 case DATATYPE_INT8: dumpValue< sal_Int8 >( rItemFmt ); break;
2273 case DATATYPE_UINT8: dumpValue< sal_uInt8 >( rItemFmt ); break;
2274 case DATATYPE_INT16: dumpValue< sal_Int16 >( rItemFmt ); break;
2275 case DATATYPE_UINT16: dumpValue< sal_uInt16 >( rItemFmt ); break;
2276 case DATATYPE_INT32: dumpValue< sal_Int32 >( rItemFmt ); break;
2277 case DATATYPE_UINT32: dumpValue< sal_uInt32 >( rItemFmt ); break;
2278 case DATATYPE_INT64: dumpValue< sal_Int64 >( rItemFmt ); break;
2279 case DATATYPE_UINT64: dumpValue< sal_uInt64 >( rItemFmt ); break;
2280 case DATATYPE_FLOAT: dumpValue< float >( rItemFmt ); break;
2281 case DATATYPE_DOUBLE: dumpValue< double >( rItemFmt ); break;
2282 default:;
2283 }
2284}
2285
2286BinaryStreamObject::BinaryStreamObject( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName )
2287{
2288 InputObjectBase::construct( rParent, rxStrm, rSysFileName );
2289}
2290
2292{
2293 mxStrm->seekToStart();
2294 dumpRawBinary( mxStrm->size(), bShowOffset, true );
2295 mxOut->emptyLine();
2296}
2297
2299{
2301}
2302
2304 const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc, const OUString& rSysFileName )
2305{
2306 InputObjectBase::construct( rParent, rxStrm, rSysFileName );
2307 constructTextStrmObj( eTextEnc );
2308}
2309
2311 const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc )
2312{
2313 InputObjectBase::construct( rParent, rxStrm );
2314 constructTextStrmObj( eTextEnc );
2315}
2316
2318{
2320}
2321
2323{
2325}
2326
2327void TextStreamObjectBase::constructTextStrmObj( rtl_TextEncoding eTextEnc )
2328{
2329 if( mxStrm )
2330 mxTextStrm = std::make_shared<TextInputStream>( getContext(), *mxStrm, eTextEnc );
2331}
2332
2334 const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc, const OUString& rSysFileName )
2335{
2336 TextStreamObjectBase::construct( rParent, rxStrm, eTextEnc, rSysFileName );
2337}
2338
2340 const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc )
2341{
2342 TextStreamObjectBase::construct( rParent, rxStrm, eTextEnc );
2343}
2344
2346{
2347 sal_uInt32 nLine = 0;
2348 while( !rTextStrm.isEof() )
2349 {
2350 OUString aLine = rTextStrm.readLine();
2351 if( !rTextStrm.isEof() || !aLine.isEmpty() )
2352 implDumpLine( aLine, ++nLine );
2353 }
2354}
2355
2356void TextLineStreamObject::implDumpLine( std::u16string_view rLine, sal_uInt32 nLine )
2357{
2358 TableGuard aTabGuard( mxOut, 8 );
2359 mxOut->writeDec( nLine, 6 );
2360 mxOut->tab();
2361 mxOut->writeString( rLine );
2362 mxOut->newLine();
2363}
2364
2366 const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName )
2367{
2368 TextStreamObjectBase::construct( rParent, rxStrm, RTL_TEXTENCODING_UTF8, rSysFileName );
2369}
2370
2372{
2373 /* Buffers a start element and the following element text. Needed to dump
2374 matching start/end elements and the element text on the same line. */
2375 OUStringBuffer aOldStartElem;
2376 // special handling for VML
2378
2379 while( !rTextStrm.isEof() )
2380 {
2381 // get the next element and the following element text from text stream
2382 OUString aElem = rTextStrm.readToChar( '>', true ).trim();
2383 OUString aText = rTextStrm.readToChar( '<', false );
2384
2385 // remove multiple whitespace from element
2386 sal_Int32 nPos = 0;
2387 while( nPos < aElem.getLength() )
2388 {
2389 while( (nPos < aElem.getLength()) && (aElem[ nPos ] >= 32) ) ++nPos;
2390 if( nPos < aElem.getLength() )
2391 aElem = aElem.subView( 0, nPos ) + OUStringChar(' ') + o3tl::trim(aElem.subView( nPos ));
2392 ++nPos;
2393 }
2394
2395 sal_Int32 nElemLen = aElem.getLength();
2396 if( (nElemLen >= 2) && (aElem[ 0 ] == '<') && (aElem[ nElemLen - 1 ] == '>') )
2397 {
2398 // determine type of the element
2399 bool bSimpleElem = (aElem[ 1 ] == '!') || (aElem[ 1 ] == '?') || (aElem[ nElemLen - 2 ] == '/') ||
2400 (bIsVml && (nElemLen == 4) && (aElem[ 1 ] == 'b') && (aElem[ 2 ] == 'r'));
2401 bool bStartElem = !bSimpleElem && (aElem[ 1 ] != '/');
2402 bool bEndElem = !bSimpleElem && !bStartElem;
2403
2404 /* Start element or simple element: flush old start element and
2405 its text from previous iteration, and start a new indentation
2406 level for the new element. Trim whitespace and line breaks from
2407 the text of the old start element. */
2408 if( (bSimpleElem || bStartElem) && (aOldStartElem.getLength() > 0) )
2409 {
2410 mxOut->writeString( o3tl::trim(aOldStartElem.makeStringAndClear()) );
2411 mxOut->newLine();
2412 mxOut->incIndent();
2413 }
2414
2415 /* Start element: remember it and its text, to be able to print the
2416 matching end element on the same line in the next iteration. */
2417 if( bStartElem )
2418 {
2419 aOldStartElem.append( aElem + aText );
2420 }
2421 else
2422 {
2423 /* End element: if a start element has been remembered in the
2424 previous iteration, write it out here untrimmed, to show
2425 all whitespace in the element text, and without trailing
2426 line break. Code below will add the end element right after
2427 it. Otherwise, return to previous indentation level. */
2428 if( bEndElem )
2429 {
2430 if( aOldStartElem.getLength() == 0 )
2431 mxOut->decIndent();
2432 else
2433 mxOut->writeString( aOldStartElem.makeStringAndClear() );
2434 }
2435
2436 /* Write the element. Write following element text in a new
2437 line, but only, if it does not contain of white space
2438 entirely. */
2439 mxOut->writeString( aElem );
2440 mxOut->newLine();
2441 if( !o3tl::trim(aText).empty() )
2442 {
2443 mxOut->writeString( aText );
2444 mxOut->newLine();
2445 }
2446 }
2447 }
2448 }
2449}
2450
2452 const BinaryInputStreamRef& rxBaseStrm, const OUString& rSysFileName,
2453 const BinaryInputStreamRef& rxRecStrm, const String& rRecNames, const String& rSimpleRecs )
2454{
2455 InputObjectBase::construct( rParent, rxRecStrm, rSysFileName );
2456 constructRecObjBase( rxBaseStrm, rRecNames, rSimpleRecs );
2457}
2458
2460{
2462}
2463
2465{
2466 NameListRef xRecNames = maRecNames.getNameList( cfg() );
2467 ItemFormatMap aSimpleRecs( maSimpleRecs.getNameList( cfg() ) );
2468
2470 {
2471 // record header
2472 mxOut->emptyLine();
2473 writeHeader();
2475 IndentGuard aIndGuard( mxOut );
2476 sal_Int64 nRecPos = mxStrm->tell();
2477
2478 // record body
2479 if( !mbBinaryOnly && cfg().hasName( xRecNames, mnRecId ) )
2480 {
2481 ::std::map< sal_Int64, ItemFormat >::const_iterator aIt = aSimpleRecs.find( mnRecId );
2482 if( aIt != aSimpleRecs.end() )
2483 dumpItem( aIt->second );
2484 else
2486 }
2487
2488 // remaining undumped data
2489 if( !mxStrm->isEof() && (mxStrm->tell() == nRecPos) )
2490 dumpRawBinary( mnRecSize, false );
2491 else
2492 dumpRemainingTo( nRecPos + mnRecSize );
2493 }
2494}
2495
2497{
2498}
2499
2501{
2502}
2503
2504void RecordObjectBase::constructRecObjBase( const BinaryInputStreamRef& rxBaseStrm, const String& rRecNames, const String& rSimpleRecs )
2505{
2506 mxBaseStrm = rxBaseStrm;
2507 maRecNames = rRecNames;
2508 maSimpleRecs = rSimpleRecs;
2509 mnRecPos = mnRecId = mnRecSize = 0;
2510 mbBinaryOnly = false;
2512 mbShowRecPos = cfg().getBoolOption( "show-record-position", true );
2513}
2514
2516{
2517 MultiItemsGuard aMultiGuard( mxOut );
2518 writeEmptyItem( "REC" );
2519 if( mbShowRecPos && mxBaseStrm->isSeekable() )
2520 writeShortHexItem( "pos", mnRecPos, "CONV-DEC" );
2521 writeShortHexItem( "size", mnRecSize, "CONV-DEC" );
2522 ItemGuard aItem( mxOut, "id" );
2523 mxOut->writeShortHex( mnRecId );
2524 addNameToItem( mnRecId, "CONV-DEC" );
2526}
2527
2529 const BinaryInputStreamRef& rxBaseStrm, const OUString& rSysFileName,
2530 const String& rRecNames, const String& rSimpleRecs )
2531{
2532 BinaryInputStreamRef xRecStrm( std::make_shared<SequenceInputStream>( *mxRecData ) );
2533 RecordObjectBase::construct( rParent, rxBaseStrm, rSysFileName, xRecStrm, rRecNames, rSimpleRecs );
2534}
2535
2536bool SequenceRecordObjectBase::implStartRecord( BinaryInputStream& rBaseStrm, sal_Int64& ornRecPos, sal_Int64& ornRecId, sal_Int64& ornRecSize )
2537{
2538 bool bValid = true;
2539 if( rBaseStrm.isSeekable() )
2540 {
2541 ornRecPos = rBaseStrm.tell();
2542 // do not try to overread seekable streams, may cause assertions
2543 bValid = ornRecPos < rBaseStrm.size();
2544 }
2545
2546 // read the record header
2547 if( bValid )
2548 bValid = implReadRecordHeader( rBaseStrm, ornRecId, ornRecSize ) && !rBaseStrm.isEof() && (0 <= ornRecSize) && (ornRecSize <= 0x00100000);
2549
2550 // read record contents into data sequence
2551 if( bValid )
2552 {
2553 sal_Int32 nRecSize = static_cast< sal_Int32 >( ornRecSize );
2554 mxRecData->realloc( nRecSize );
2555 bValid = (nRecSize == 0) || (rBaseStrm.readData( *mxRecData, nRecSize ) == nRecSize);
2556 mxStrm->seekToStart();
2557 }
2558 return bValid;
2559}
2560
2562{
2563}
2564
2566{
2567 return !isValid() || cfg().isImportEnabled();
2568}
2569
2570void DumperBase::construct( const ConfigRef& rxConfig )
2571{
2572 if( isValid( rxConfig ) && rxConfig->isDumperEnabled() )
2573 ObjectBase::construct( rxConfig );
2574}
2575
2576} // namespace oox
2577
2578#endif
2579
2580/* 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 exclude(std::u16string_view rKeys)
Excludes names from the list, given in a comma separated list of their keys.
Definition: dumperbase.cxx:929
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
void include(std::u16string_view rListKeys)
Includes name lists, given in a comma separated list of names of the lists.
Definition: dumperbase.cxx:921
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
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
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
void writeStringItem(const String &rName, std::u16string_view rData)
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)
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
::std::vector< sal_Int32 > maColPos
Definition: dumperbase.hxx:998
void writeAscii(const char *pcStr)
void resetItemIndex(sal_Int64 nIdx=0)
sal_Int32 mnLastItem
void writeString(std::u16string_view rStr)
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)
bool readConfigFile(const OUString &rFileUrl)
css::uno::Reference< css::uno::XComponentContext > mxContext
Definition: dumperbase.hxx:800
void createShortList(std::u16string_view rData)
virtual bool implIsValid() const override
void createUnitConverter(std::u16string_view rData)
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)
static OUString getSysFileName(std::u16string_view rStrmName, std::u16string_view rSysOutPath)
virtual void implDumpBaseStream(const BinaryInputStreamRef &rxStrm, const OUString &rSysFileName)
virtual bool implIsValid() const override
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 appendString(OUStringBuffer &rStr, std::u16string_view rData, sal_Int32 nWidth, sal_Unicode cFill=' ')
Definition: dumperbase.cxx:203
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 convertStringToStringList(OUStringVector &orVec, std::u16string_view rData, bool bIgnoreEmpty)
Definition: dumperbase.cxx:763
static void appendEncString(OUStringBuffer &rStr, std::u16string_view rData, bool bPrefix=true)
Definition: dumperbase.cxx:486
static void appendHex(OUStringBuffer &rStr, sal_uInt8 nData, bool bPrefix=true)
Definition: dumperbase.cxx:265
static DataType convertToDataType(std::u16string_view rStr)
Definition: dumperbase.cxx:627
static std::u16string_view getToken(std::u16string_view rData, sal_Int32 &rnPos, sal_Unicode cSep=OOX_DUMP_LISTSEP)
Definition: dumperbase.cxx:530
static void convertStringToIntList(Int64Vector &orVec, std::u16string_view rData, bool bIgnoreEmpty)
Definition: dumperbase.cxx:777
static void appendDec(OUStringBuffer &rStr, sal_uInt8 nData, sal_Int32 nWidth=0, sal_Unicode cFill=' ')
Definition: dumperbase.cxx:211
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)
TextLineStreamObject(const ObjectBase &rParent, const BinaryInputStreamRef &rxStrm, rtl_TextEncoding eTextEnc, const OUString &rSysFileName)
virtual void implDumpText(TextInputStream &rTextStrm) override
void implDumpLine(std::u16string_view rLine, sal_uInt32 nLine)
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
std::basic_string_view< charT, traits > trim(std::basic_string_view< charT, traits > str)
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)
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)
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