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 
20 #include <oox/dump/dumperbase.hxx>
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>
31 #include <oox/core/filterbase.hxx>
34 #include <tools/time.hxx>
35 #include <o3tl/string_view.hxx>
36 
37 #ifdef DBG_UTIL
38 
39 namespace oox::dump {
40 
41 using namespace ::com::sun::star;
42 using namespace ::com::sun::star::beans;
43 using namespace ::com::sun::star::io;
44 using namespace ::com::sun::star::lang;
45 using namespace ::com::sun::star::ucb;
46 using namespace ::com::sun::star::uno;
47 
48 using ::oox::core::FilterBase;
49 
50 namespace {
51 
52 const sal_Unicode OOX_DUMP_BOM = 0xFEFF;
53 const sal_Int32 OOX_DUMP_MAXSTRLEN = 80;
54 const sal_Int32 OOX_DUMP_INDENT = 2;
55 const sal_Unicode OOX_DUMP_BINDOT = '.';
56 const sal_Unicode OOX_DUMP_CFG_LISTSEP = ',';
57 const sal_Unicode OOX_DUMP_CFG_QUOTE = '\'';
58 const sal_Unicode OOX_DUMP_LF = '\n';
59 const sal_Unicode OOX_DUMP_ITEMSEP = '=';
60 const sal_Int32 OOX_DUMP_BYTESPERLINE = 16;
61 const sal_Int64 OOX_DUMP_MAXARRAY = 16;
62 
63 } // namespace
64 
65 // file names -----------------------------------------------------------------
66 
67 OUString InputOutputHelper::convertFileNameToUrl( const OUString& rFileName )
68 {
69  OUString aFileUrl;
70  if( ::osl::FileBase::getFileURLFromSystemPath( rFileName, aFileUrl ) == ::osl::FileBase::E_None )
71  return aFileUrl;
72  return OUString();
73 }
74 
75 sal_Int32 InputOutputHelper::getFileNamePos( std::u16string_view rFileUrl )
76 {
77  size_t nSepPos = rFileUrl.find( '/' );
78  return (nSepPos == std::u16string_view::npos) ? 0 : (nSepPos + 1);
79 }
80 
81 std::u16string_view InputOutputHelper::getFileNameExtension( std::u16string_view rFileUrl )
82 {
83  sal_Int32 nNamePos = getFileNamePos( rFileUrl );
84  size_t nExtPos = rFileUrl.rfind( '.' );
85  if( nExtPos != std::u16string_view::npos && static_cast<sal_Int32>(nExtPos) >= nNamePos )
86  return rFileUrl.substr( nExtPos + 1 );
87  return std::u16string_view();
88 }
89 
90 // input streams --------------------------------------------------------------
91 
93  const Reference< XComponentContext >& rxContext, const OUString& rFileName )
94 {
96  if( rxContext.is() ) try
97  {
98  Reference<XSimpleFileAccess3> xFileAccess(SimpleFileAccess::create(rxContext));
99  xInStrm = xFileAccess->openFileRead( rFileName );
100  }
101  catch( Exception& )
102  {
103  }
104  return xInStrm;
105 }
106 
107 // output streams -------------------------------------------------------------
108 
109 Reference< XOutputStream > InputOutputHelper::openOutputStream(
110  const Reference< XComponentContext >& rxContext, const OUString& rFileName )
111 {
112  Reference< XOutputStream > xOutStrm;
113  if( rxContext.is() ) try
114  {
115  Reference<XSimpleFileAccess3> xFileAccess(SimpleFileAccess::create(rxContext));
116  xOutStrm = xFileAccess->openFileWrite( rFileName );
117  }
118  catch( Exception& )
119  {
120  }
121  return xOutStrm;
122 }
123 
124 Reference< XTextOutputStream2 > InputOutputHelper::openTextOutputStream(
125  const Reference< XComponentContext >& rxContext, const Reference< XOutputStream >& rxOutStrm, rtl_TextEncoding eTextEnc )
126 {
127  Reference< XTextOutputStream2 > xTextOutStrm;
128  const char* pcCharset = rtl_getMimeCharsetFromTextEncoding( eTextEnc );
129  if( rxContext.is() && rxOutStrm.is() && pcCharset ) try
130  {
131  xTextOutStrm = TextOutputStream::create(rxContext);
132  xTextOutStrm->setOutputStream( rxOutStrm );
133  xTextOutStrm->setEncoding( OUString::createFromAscii( pcCharset ) );
134  }
135  catch( Exception& )
136  {
137  }
138  return xTextOutStrm;
139 }
140 
141 Reference< XTextOutputStream2 > InputOutputHelper::openTextOutputStream(
142  const Reference< XComponentContext >& rxContext, const OUString& rFileName, rtl_TextEncoding eTextEnc )
143 {
144  return openTextOutputStream( rxContext, openOutputStream( rxContext, rFileName ), eTextEnc );
145 }
146 
148  meDataType( DATATYPE_VOID ),
149  meFmtType( FORMATTYPE_NONE )
150 {
151 }
152 
153 void ItemFormat::set( DataType eDataType, FormatType eFmtType, const OUString& rItemName )
154 {
155  meDataType = eDataType;
156  meFmtType = eFmtType;
157  maItemName = rItemName;
158  maListName.clear();
159 }
160 
161 OUStringVector::const_iterator ItemFormat::parse( const OUStringVector& rFormatVec )
162 {
163  set( DATATYPE_VOID, FORMATTYPE_NONE, OUString() );
164 
165  OUStringVector::const_iterator aIt = rFormatVec.begin(), aEnd = rFormatVec.end();
166  OUString aDataType, aFmtType;
167  if( aIt != aEnd ) aDataType = *aIt++;
168  if( aIt != aEnd ) aFmtType = *aIt++;
169  if( aIt != aEnd ) maItemName = *aIt++;
170  if( aIt != aEnd ) maListName = *aIt++;
171 
174 
175  if( meFmtType == FORMATTYPE_NONE )
176  {
177  if ( aFmtType == "unused" )
179  else if ( aFmtType == "unknown" )
181  }
182 
183  return aIt;
184 }
185 
186 OUStringVector ItemFormat::parse( const OUString& rFormatStr )
187 {
188  OUStringVector aFormatVec;
189  StringHelper::convertStringToStringList( aFormatVec, rFormatStr, false );
190  OUStringVector::const_iterator aIt = parse( aFormatVec );
191  return OUStringVector( aIt, const_cast< const OUStringVector& >( aFormatVec ).end() );
192 }
193 
194 // append string to string ----------------------------------------------------
195 
196 void StringHelper::appendChar( OUStringBuffer& rStr, sal_Unicode cChar, sal_Int32 nCount )
197 {
198  for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
199  rStr.append( cChar );
200 }
201 
202 void StringHelper::appendString( OUStringBuffer& rStr, const OUString& rData, sal_Int32 nWidth, sal_Unicode cFill )
203 {
204  appendChar( rStr, cFill, nWidth - rData.getLength() );
205  rStr.append( rData );
206 }
207 
208 // append decimal -------------------------------------------------------------
209 
210 void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt8 nData, sal_Int32 nWidth, sal_Unicode cFill )
211 {
212  appendString( rStr, OUString::number( nData ), nWidth, cFill );
213 }
214 
215 void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int8 nData, sal_Int32 nWidth, sal_Unicode cFill )
216 {
217  appendString( rStr, OUString::number( nData ), nWidth, cFill );
218 }
219 
220 void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt16 nData, sal_Int32 nWidth, sal_Unicode cFill )
221 {
222  appendString( rStr, OUString::number( nData ), nWidth, cFill );
223 }
224 
225 void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int16 nData, sal_Int32 nWidth, sal_Unicode cFill )
226 {
227  appendString( rStr, OUString::number( nData ), nWidth, cFill );
228 }
229 
230 void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt32 nData, sal_Int32 nWidth, sal_Unicode cFill )
231 {
232  appendString( rStr, OUString::number( nData ), nWidth, cFill );
233 }
234 
235 void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int32 nData, sal_Int32 nWidth, sal_Unicode cFill )
236 {
237  appendString( rStr, OUString::number( nData ), nWidth, cFill );
238 }
239 
240 void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt64 nData, sal_Int32 nWidth, sal_Unicode cFill )
241 {
242  /* Values greater than biggest signed 64bit integer will change to
243  negative when converting to sal_Int64. Therefore, the trailing digit
244  will be written separately. */
245  OUStringBuffer aBuffer;
246  if( nData > 9 )
247  aBuffer.append( static_cast<sal_Int64>(nData / 10 ) );
248  aBuffer.append( static_cast< sal_Unicode >( '0' + (nData % 10) ) );
249  appendString( rStr, aBuffer.makeStringAndClear(), nWidth, cFill );
250 }
251 
252 void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int64 nData, sal_Int32 nWidth, sal_Unicode cFill )
253 {
254  appendString( rStr, OUString::number( nData ), nWidth, cFill );
255 }
256 
257 void StringHelper::appendDec( OUStringBuffer& rStr, double fData, sal_Int32 nWidth, sal_Unicode cFill )
258 {
259  appendString( rStr, ::rtl::math::doubleToUString( fData, rtl_math_StringFormat_G, 15, '.', true ), nWidth, cFill );
260 }
261 
262 // append hexadecimal ---------------------------------------------------------
263 
264 void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt8 nData, bool bPrefix )
265 {
266  static const sal_Unicode spcHexDigits[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
267  if( bPrefix )
268  rStr.append( "0x" );
269  rStr.append( spcHexDigits[ (nData >> 4) & 0x0F ] ).append( spcHexDigits[ nData & 0x0F ] );
270 }
271 
272 void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int8 nData, bool bPrefix )
273 {
274  appendHex( rStr, static_cast< sal_uInt8 >( nData ), bPrefix );
275 }
276 
277 void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt16 nData, bool bPrefix )
278 {
279  appendHex( rStr, static_cast< sal_uInt8 >( nData >> 8 ), bPrefix );
280  appendHex( rStr, static_cast< sal_uInt8 >( nData ), false );
281 }
282 
283 void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int16 nData, bool bPrefix )
284 {
285  appendHex( rStr, static_cast< sal_uInt16 >( nData ), bPrefix );
286 }
287 
288 void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt32 nData, bool bPrefix )
289 {
290  appendHex( rStr, static_cast< sal_uInt16 >( nData >> 16 ), bPrefix );
291  appendHex( rStr, static_cast< sal_uInt16 >( nData ), false );
292 }
293 
294 void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int32 nData, bool bPrefix )
295 {
296  appendHex( rStr, static_cast< sal_uInt32 >( nData ), bPrefix );
297 }
298 
299 void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt64 nData, bool bPrefix )
300 {
301  appendHex( rStr, static_cast< sal_uInt32 >( nData >> 32 ), bPrefix );
302  appendHex( rStr, static_cast< sal_uInt32 >( nData ), false );
303 }
304 
305 void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int64 nData, bool bPrefix )
306 {
307  appendHex( rStr, static_cast< sal_uInt64 >( nData ), bPrefix );
308 }
309 
310 static sal_uInt64
311 lcl_ConvertDouble(double const f)
312 {
313  sal_uInt64 i = sal_uInt64();
314  for (size_t j = 0; j < sizeof(double); ++j)
315  { // hopefully both endian independent and strict aliasing safe
316  reinterpret_cast<char *>(&i)[j] = reinterpret_cast<char const *>(&f)[j];
317  }
318  return i;
319 }
320 
321 void StringHelper::appendHex( OUStringBuffer& rStr, double fData, bool bPrefix )
322 {
323  appendHex( rStr, lcl_ConvertDouble(fData), bPrefix );
324 }
325 
326 // append shortened hexadecimal -----------------------------------------------
327 
328 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt8 nData, bool bPrefix )
329 {
330  appendHex( rStr, nData, bPrefix );
331 }
332 
333 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int8 nData, bool bPrefix )
334 {
335  appendHex( rStr, nData, bPrefix );
336 }
337 
338 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt16 nData, bool bPrefix )
339 {
340  if( nData > SAL_MAX_UINT8 )
341  appendHex( rStr, nData, bPrefix );
342  else
343  appendHex( rStr, static_cast< sal_uInt8 >( nData ), bPrefix );
344 }
345 
346 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int16 nData, bool bPrefix )
347 {
348  appendShortHex( rStr, static_cast< sal_uInt16 >( nData ), bPrefix );
349 }
350 
351 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt32 nData, bool bPrefix )
352 {
353  if( nData > SAL_MAX_UINT16 )
354  appendHex( rStr, nData, bPrefix );
355  else
356  appendShortHex( rStr, static_cast< sal_uInt16 >( nData ), bPrefix );
357 }
358 
359 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int32 nData, bool bPrefix )
360 {
361  appendShortHex( rStr, static_cast< sal_uInt32 >( nData ), bPrefix );
362 }
363 
364 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt64 nData, bool bPrefix )
365 {
366  if( nData > SAL_MAX_UINT32 )
367  appendHex( rStr, nData, bPrefix );
368  else
369  appendShortHex( rStr, static_cast< sal_uInt32 >( nData ), bPrefix );
370 }
371 
372 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int64 nData, bool bPrefix )
373 {
374  appendShortHex( rStr, static_cast< sal_uInt64 >( nData ), bPrefix );
375 }
376 
377 void StringHelper::appendShortHex( OUStringBuffer& rStr, double fData, bool bPrefix )
378 {
379  appendHex( rStr, fData, bPrefix );
380 }
381 
382 // append binary --------------------------------------------------------------
383 
384 void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt8 nData, bool bDots )
385 {
386  for( sal_uInt8 nMask = 0x80; nMask != 0; (nMask >>= 1) &= 0x7F )
387  {
388  rStr.append( static_cast< sal_Unicode >( (nData & nMask) ? '1' : '0' ) );
389  if( bDots && (nMask == 0x10) )
390  rStr.append( OOX_DUMP_BINDOT );
391  }
392 }
393 
394 void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int8 nData, bool bDots )
395 {
396  appendBin( rStr, static_cast< sal_uInt8 >( nData ), bDots );
397 }
398 
399 void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt16 nData, bool bDots )
400 {
401  appendBin( rStr, static_cast< sal_uInt8 >( nData >> 8 ), bDots );
402  if( bDots )
403  rStr.append( OOX_DUMP_BINDOT );
404  appendBin( rStr, static_cast< sal_uInt8 >( nData ), bDots );
405 }
406 
407 void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int16 nData, bool bDots )
408 {
409  appendBin( rStr, static_cast< sal_uInt16 >( nData ), bDots );
410 }
411 
412 void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt32 nData, bool bDots )
413 {
414  appendBin( rStr, static_cast< sal_uInt16 >( nData >> 16 ), bDots );
415  if( bDots )
416  rStr.append( OOX_DUMP_BINDOT );
417  appendBin( rStr, static_cast< sal_uInt16 >( nData ), bDots );
418 }
419 
420 void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int32 nData, bool bDots )
421 {
422  appendBin( rStr, static_cast< sal_uInt32 >( nData ), bDots );
423 }
424 
425 void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt64 nData, bool bDots )
426 {
427  appendBin( rStr, static_cast< sal_uInt32 >( nData >> 32 ), bDots );
428  if( bDots )
429  rStr.append( OOX_DUMP_BINDOT );
430  appendBin( rStr, static_cast< sal_uInt32 >( nData ), bDots );
431 }
432 
433 void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int64 nData, bool bDots )
434 {
435  appendBin( rStr, static_cast< sal_uInt64 >( nData ), bDots );
436 }
437 
438 void StringHelper::appendBin( OUStringBuffer& rStr, double fData, bool bDots )
439 {
440  appendBin( rStr, lcl_ConvertDouble(fData), bDots );
441 }
442 
443 // append formatted value -----------------------------------------------------
444 
445 void StringHelper::appendBool( OUStringBuffer& rStr, bool bData )
446 {
447  rStr.appendAscii( bData ? "true" : "false" );
448 }
449 
450 // encoded text output --------------------------------------------------------
451 
452 void StringHelper::appendCChar( OUStringBuffer& rStr, sal_Unicode cChar, bool bPrefix )
453 {
454  if( cChar > 0x00FF )
455  {
456  if( bPrefix )
457  rStr.append( "\\u" );
458  appendHex( rStr, static_cast< sal_uInt16 >( cChar ), false );
459  }
460  else
461  {
462  if( bPrefix )
463  rStr.append( "\\x" );
464  appendHex( rStr, static_cast< sal_uInt8 >( cChar ), false );
465  }
466 }
467 
468 void StringHelper::appendEncChar( OUStringBuffer& rStr, sal_Unicode cChar, sal_Int32 nCount, bool bPrefix )
469 {
470  if( cChar < 0x0020 )
471  {
472  // C-style hex code
473  OUStringBuffer aCode;
474  appendCChar( aCode, cChar, bPrefix );
475  OUString aCodeStr = aCode.makeStringAndClear();
476  for( sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx )
477  rStr.append( aCodeStr );
478  }
479  else
480  {
481  appendChar( rStr, cChar, nCount );
482  }
483 }
484 
485 void StringHelper::appendEncString( OUStringBuffer& rStr, const OUString& rData, bool bPrefix )
486 {
487  sal_Int32 nBeg = 0;
488  sal_Int32 nIdx = 0;
489  sal_Int32 nEnd = rData.getLength();
490  while( nIdx < nEnd )
491  {
492  // find next character that needs encoding
493  while( (nIdx < nEnd) && (rData[ nIdx ] >= 0x20) ) ++nIdx;
494  // append portion
495  if( nBeg < nIdx )
496  {
497  if( (nBeg == 0) && (nIdx == nEnd) )
498  rStr.append( rData );
499  else
500  rStr.append( rData.subView(nBeg, nIdx - nBeg) );
501  }
502  // append characters to be encoded
503  while( (nIdx < nEnd) && (rData[ nIdx ] < 0x20) )
504  {
505  appendCChar( rStr, rData[ nIdx ], bPrefix );
506  ++nIdx;
507  }
508  // adjust limits
509  nBeg = nIdx;
510  }
511 }
512 
513 // token list -----------------------------------------------------------------
514 
515 void StringHelper::appendToken( OUStringBuffer& rStr, std::u16string_view rToken, sal_Unicode cSep )
516 {
517  if( (rStr.getLength() > 0) && (!rToken.empty()) )
518  rStr.append( cSep );
519  rStr.append( rToken );
520 }
521 
522 void StringHelper::appendIndex( OUStringBuffer& rStr, sal_Int64 nIdx )
523 {
524  OUStringBuffer aToken;
525  appendDec( aToken, nIdx );
526  rStr.append( '[' ).append( aToken.makeStringAndClear() ).append( ']' );
527 }
528 
529 std::u16string_view StringHelper::getToken( std::u16string_view rData, sal_Int32& rnPos, sal_Unicode cSep )
530 {
531  return trimSpaces( o3tl::getToken(rData, 0, cSep, rnPos ) );
532 }
533 
534 void StringHelper::enclose( OUStringBuffer& rStr, sal_Unicode cOpen, sal_Unicode cClose )
535 {
536  rStr.insert( 0, cOpen ).append( cClose ? cClose : cOpen );
537 }
538 
539 // string conversion ----------------------------------------------------------
540 
541 namespace {
542 
543 sal_Int32 lclIndexOf( const OUString& rStr, sal_Unicode cChar, sal_Int32 nStartPos )
544 {
545  sal_Int32 nIndex = rStr.indexOf( cChar, nStartPos );
546  return (nIndex < 0) ? rStr.getLength() : nIndex;
547 }
548 
549 OUString lclTrimQuotedStringList( const OUString& rStr )
550 {
551  OUStringBuffer aBuffer;
552  sal_Int32 nPos = 0;
553  sal_Int32 nLen = rStr.getLength();
554  while( nPos < nLen )
555  {
556  if( rStr[ nPos ] == OOX_DUMP_CFG_QUOTE )
557  {
558  // quoted string, skip leading quote character
559  ++nPos;
560  // process quoted text and embedded literal quote characters
561  OUStringBuffer aToken;
562  do
563  {
564  // seek to next quote character and add text portion to token buffer
565  sal_Int32 nEnd = lclIndexOf( rStr, OOX_DUMP_CFG_QUOTE, nPos );
566  aToken.append( rStr.subView(nPos, nEnd - nPos) );
567  // process literal quotes
568  while( (nEnd + 1 < nLen) && (rStr[ nEnd ] == OOX_DUMP_CFG_QUOTE) && (rStr[ nEnd + 1 ] == OOX_DUMP_CFG_QUOTE) )
569  {
570  aToken.append( OOX_DUMP_CFG_QUOTE );
571  nEnd += 2;
572  }
573  // nEnd is start of possible next text portion
574  nPos = nEnd;
575  }
576  while( (nPos < nLen) && (rStr[ nPos ] != OOX_DUMP_CFG_QUOTE) );
577  // add token, seek to list separator, ignore text following closing quote
578  aBuffer.append( aToken.makeStringAndClear() );
579  nPos = lclIndexOf( rStr, OOX_DUMP_CFG_LISTSEP, nPos );
580  if( nPos < nLen )
581  aBuffer.append( OOX_DUMP_LF );
582  // set current position behind list separator
583  ++nPos;
584  }
585  else
586  {
587  // find list separator, add token text to buffer
588  sal_Int32 nEnd = lclIndexOf( rStr, OOX_DUMP_CFG_LISTSEP, nPos );
589  aBuffer.append( rStr.subView(nPos, nEnd - nPos) );
590  if( nEnd < nLen )
591  aBuffer.append( OOX_DUMP_LF );
592  // set current position behind list separator
593  nPos = nEnd + 1;
594  }
595  }
596 
597  return aBuffer.makeStringAndClear();
598 }
599 
600 } // namespace
601 
602 std::u16string_view StringHelper::trimSpaces( std::u16string_view rStr )
603 {
604  size_t nBeg = 0;
605  while( (nBeg < rStr.size()) && ((rStr[ nBeg ] == ' ') || (rStr[ nBeg ] == '\t')) )
606  ++nBeg;
607  size_t nEnd = rStr.size();
608  while( (nEnd > nBeg) && ((rStr[ nEnd - 1 ] == ' ') || (rStr[ nEnd - 1 ] == '\t')) )
609  --nEnd;
610  return rStr.substr( nBeg, nEnd - nBeg );
611 }
612 
613 OUString StringHelper::trimTrailingNul( const OUString& rStr )
614 {
615  sal_Int32 nLastPos = rStr.getLength() - 1;
616  if( (nLastPos >= 0) && (rStr[ nLastPos ] == 0) )
617  return rStr.copy( 0, nLastPos );
618  return rStr;
619 }
620 
621 OString StringHelper::convertToUtf8( std::u16string_view rStr )
622 {
623  return OUStringToOString( rStr, RTL_TEXTENCODING_UTF8 );
624 }
625 
626 DataType StringHelper::convertToDataType( std::u16string_view rStr )
627 {
629  if ( rStr == u"int8" )
630  eType = DATATYPE_INT8;
631  else if ( rStr == u"uint8" )
632  eType = DATATYPE_UINT8;
633  else if ( rStr == u"int16" )
634  eType = DATATYPE_INT16;
635  else if ( rStr == u"uint16" )
636  eType = DATATYPE_UINT16;
637  else if ( rStr == u"int32" )
638  eType = DATATYPE_INT32;
639  else if ( rStr == u"uint32" )
640  eType = DATATYPE_UINT32;
641  else if ( rStr == u"int64" )
642  eType = DATATYPE_INT64;
643  else if ( rStr == u"uint64" )
644  eType = DATATYPE_UINT64;
645  else if ( rStr == u"float" )
646  eType = DATATYPE_FLOAT;
647  else if ( rStr == u"double" )
648  eType = DATATYPE_DOUBLE;
649  return eType;
650 }
651 
653 {
655  if ( rStr == u"dec" )
656  eType = FORMATTYPE_DEC;
657  else if ( rStr == u"hex" )
658  eType = FORMATTYPE_HEX;
659  else if ( rStr == u"shorthex" )
660  eType = FORMATTYPE_SHORTHEX;
661  else if ( rStr == u"bin" )
662  eType = FORMATTYPE_BIN;
663  else if ( rStr == u"fix" )
664  eType = FORMATTYPE_FIX;
665  else if ( rStr == u"bool" )
666  eType = FORMATTYPE_BOOL;
667  return eType;
668 }
669 
670 bool StringHelper::convertFromDec( sal_Int64& ornData, std::u16string_view rData )
671 {
672  size_t nPos = 0;
673  size_t nLen = rData.size();
674  bool bNeg = false;
675  if( (nLen > 0) && (rData[ 0 ] == '-') )
676  {
677  bNeg = true;
678  ++nPos;
679  }
680  ornData = 0;
681  for( ; nPos < nLen; ++nPos )
682  {
683  sal_Unicode cChar = rData[ nPos ];
684  if( (cChar < '0') || (cChar > '9') )
685  return false;
686  ornData = (ornData * 10) + (cChar - '0');
687  }
688  if( bNeg )
689  ornData *= -1;
690  return true;
691 }
692 
693 bool StringHelper::convertFromHex( sal_Int64& ornData, std::u16string_view rData )
694 {
695  ornData = 0;
696  for( size_t nPos = 0, nLen = rData.size(); nPos < nLen; ++nPos )
697  {
698  sal_Unicode cChar = rData[ nPos ];
699  if( ('0' <= cChar) && (cChar <= '9') )
700  cChar -= '0';
701  else if( ('A' <= cChar) && (cChar <= 'F') )
702  cChar -= ('A' - 10);
703  else if( ('a' <= cChar) && (cChar <= 'f') )
704  cChar -= ('a' - 10);
705  else
706  return false;
707  ornData = (ornData << 4) + cChar;
708  }
709  return true;
710 }
711 
712 bool StringHelper::convertStringToInt( sal_Int64& ornData, std::u16string_view rData )
713 {
714  if( (rData.size() > 2) && (rData[ 0 ] == '0') && ((rData[ 1 ] == 'X') || (rData[ 1 ] == 'x')) )
715  return convertFromHex( ornData, rData.substr( 2 ) );
716  return convertFromDec( ornData, rData );
717 }
718 
719 bool StringHelper::convertStringToDouble( double& orfData, std::u16string_view rData )
720 {
721  rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
722  sal_Int32 nSize = 0;
723  sal_Unicode const * pBegin = rData.data();
724  sal_Unicode const * pEnd;
725  orfData = rtl_math_uStringToDouble(pBegin,
726  pBegin + rData.size(),
727  '.', '\0',
728  &eStatus, &pEnd);
729  nSize = static_cast<sal_Int32>(pEnd - pBegin);
730  return (eStatus == rtl_math_ConversionStatus_Ok) && (nSize == static_cast<sal_Int32>(rData.size()));
731 }
732 
733 bool StringHelper::convertStringToBool( std::u16string_view rData )
734 {
735  if ( rData == u"true" )
736  return true;
737  if ( rData == u"false" )
738  return false;
739  sal_Int64 nData;
740  return convertStringToInt( nData, rData ) && (nData != 0);
741 }
742 
744 {
745  OUStringPair aPair;
746  if( !rString.isEmpty() )
747  {
748  sal_Int32 nEqPos = rString.indexOf( cSep );
749  if( nEqPos < 0 )
750  {
751  aPair.first = rString;
752  }
753  else
754  {
755  aPair.first = StringHelper::trimSpaces( rString.subView( 0, nEqPos ) );
756  aPair.second = StringHelper::trimSpaces( rString.subView( nEqPos + 1 ) );
757  }
758  }
759  return aPair;
760 }
761 
762 void StringHelper::convertStringToStringList( OUStringVector& orVec, const OUString& rData, bool bIgnoreEmpty )
763 {
764  orVec.clear();
765  OUString aUnquotedData = lclTrimQuotedStringList( rData );
766  sal_Int32 nPos = 0;
767  sal_Int32 nLen = aUnquotedData.getLength();
768  while( (0 <= nPos) && (nPos < nLen) )
769  {
770  std::u16string_view aToken = getToken( aUnquotedData, nPos, OOX_DUMP_LF );
771  if( !bIgnoreEmpty || !aToken.empty() )
772  orVec.push_back( OUString(aToken) );
773  }
774 }
775 
776 void StringHelper::convertStringToIntList( Int64Vector& orVec, const OUString& rData, bool bIgnoreEmpty )
777 {
778  orVec.clear();
779  OUString aUnquotedData = lclTrimQuotedStringList( rData );
780  sal_Int32 nPos = 0;
781  sal_Int32 nLen = aUnquotedData.getLength();
782  sal_Int64 nData;
783  while( (0 <= nPos) && (nPos < nLen) )
784  {
785  bool bOk = convertStringToInt( nData, getToken( aUnquotedData, nPos, OOX_DUMP_LF ) );
786  if( !bIgnoreEmpty || bOk )
787  orVec.push_back( bOk ? nData : 0 );
788  }
789 }
790 
792 {
793 }
794 
796 {
797 }
798 
800 {
801  readConfigBlockContents( rStrm );
802 }
803 
805  TextInputStream& /*rStrm*/, const OUString& /*rKey*/, const OUString& /*rData*/ )
806 {
807 }
808 
810  TextInputStream& /*rStrm*/, sal_Int64 /*nKey*/, const OUString& /*rData*/ )
811 {
812 }
813 
815 {
816  bool bLoop = true;
817  while( bLoop && !rStrm.isEof() )
818  {
819  OUString aKey, aData;
820  switch( readConfigLine( rStrm, aKey, aData ) )
821  {
822  case LINETYPE_DATA:
823  processConfigItem( rStrm, aKey, aData );
824  break;
825  case LINETYPE_END:
826  bLoop = false;
827  break;
828  }
829  }
830 }
831 
833  TextInputStream& rStrm, OUString& orKey, OUString& orData )
834 {
835  OUString aLine;
836  while( !rStrm.isEof() && aLine.isEmpty() )
837  {
838  aLine = rStrm.readLine();
839  if( !aLine.isEmpty() && (aLine[ 0 ] == OOX_DUMP_BOM) )
840  aLine = aLine.copy( 1 );
841  aLine = StringHelper::trimSpaces( aLine );
842  if( !aLine.isEmpty() )
843  {
844  // ignore comments (starting with hash or semicolon)
845  sal_Unicode cChar = aLine[ 0 ];
846  if( (cChar == '#') || (cChar == ';') )
847  aLine.clear();
848  }
849  }
850 
852  orKey = aPair.first;
853  orData = aPair.second;
854  return ( !orKey.isEmpty() && (!orData.isEmpty() || orKey != "end" )) ?
856 }
857 
859  TextInputStream& rStrm, const OUString& rKey, const OUString& rData )
860 {
861  sal_Int64 nKey;
862  if( StringHelper::convertStringToInt( nKey, rKey ) )
863  implProcessConfigItemInt( rStrm, nKey, rData );
864  else
865  implProcessConfigItemStr( rStrm, rKey, rData );
866 }
867 
869 {
870 }
871 
872 void NameListBase::setName( sal_Int64 nKey, const String& rName )
873 {
874  implSetName( nKey, rName );
875 }
876 
878 {
879  if( rxList )
880  {
881  for (auto const& elem : *rxList)
882  maMap[ elem.first ] = elem.second;
883  implIncludeList( *rxList );
884  }
885 }
886 
888 {
889  return true;
890 }
891 
893  TextInputStream& rStrm, const OUString& rKey, const OUString& rData )
894 {
895  if ( rKey == "include" )
896  include( rData );
897  else if ( rKey == "exclude" )
898  exclude( rData );
899  else
900  ConfigItemBase::implProcessConfigItemStr( rStrm, rKey, rData );
901 }
902 
904  TextInputStream& /*rStrm*/, sal_Int64 nKey, const OUString& rData )
905 {
906  implSetName( nKey, rData );
907 }
908 
909 void NameListBase::insertRawName( sal_Int64 nKey, const OUString& rName )
910 {
911  maMap[ nKey ] = rName;
912 }
913 
914 const OUString* NameListBase::findRawName( sal_Int64 nKey ) const
915 {
916  const_iterator aIt = maMap.find( nKey );
917  return (aIt == end()) ? nullptr : &aIt->second;
918 }
919 
920 void NameListBase::include( const OUString& rListKeys )
921 {
922  OUStringVector aVec;
923  StringHelper::convertStringToStringList( aVec, rListKeys, true );
924  for (auto const& elem : aVec)
926 }
927 
928 void NameListBase::exclude( const OUString& rKeys )
929 {
930  Int64Vector aVec;
931  StringHelper::convertStringToIntList( aVec, rKeys, true );
932  for (auto const& elem : aVec)
933  maMap.erase(elem);
934 }
935 
936 void ItemFormatMap::insertFormats( const NameListRef& rxNameList )
937 {
938  if( Base::isValid( rxNameList ) )
939  {
940  for (auto const& elemName : *rxNameList)
941  maMap[ elemName.first ].parse( elemName.second );
942  }
943 }
944 
946  NameListBase( rCfgData ),
947  maDefName( OOX_DUMP_ERR_NONAME ),
948  mbQuoteNames( false )
949 {
950 }
951 
953  TextInputStream& rStrm, const OUString& rKey, const OUString& rData )
954 {
955  if ( rKey == "default" )
956  maDefName = rData; // Sets a default name for unknown keys.
957  else if ( rKey == "quote-names" )
959  else
960  NameListBase::implProcessConfigItemStr( rStrm, rKey, rData );
961 }
962 
963 void ConstList::implSetName( sal_Int64 nKey, const OUString& rName )
964 {
965  insertRawName( nKey, rName );
966 }
967 
968 OUString ConstList::implGetName( const Config& /*rCfg*/, sal_Int64 nKey ) const
969 {
970  const OUString* pName = findRawName( nKey );
971  OUString aName = pName ? *pName : maDefName;
972  if( mbQuoteNames )
973  {
974  OUStringBuffer aBuffer( aName );
976  aName = aBuffer.makeStringAndClear();
977  }
978  return aName;
979 }
980 
981 OUString ConstList::implGetNameDbl( const Config& /*rCfg*/, double /*fValue*/ ) const
982 {
983  return OUString();
984 }
985 
987 {
988  if( const ConstList* pConstList = dynamic_cast< const ConstList* >( &rList ) )
989  {
990  maDefName = pConstList->maDefName;
991  mbQuoteNames = pConstList->mbQuoteNames;
992  }
993 }
994 
996  ConstList( rCfgData ),
997  mbIgnoreEmpty( true )
998 {
999 }
1000 
1001 void MultiList::setNamesFromVec( sal_Int64 nStartKey, const OUStringVector& rNames )
1002 {
1003  sal_Int64 nKey = nStartKey;
1004  for (auto const& name : rNames)
1005  {
1006  if( !mbIgnoreEmpty || !name.isEmpty() )
1007  insertRawName( nKey, name);
1008  ++nKey;
1009  }
1010 }
1011 
1013  TextInputStream& rStrm, const OUString& rKey, const OUString& rData )
1014 {
1015  if ( rKey == "ignore-empty" )
1017  else
1018  ConstList::implProcessConfigItemStr( rStrm, rKey, rData );
1019 }
1020 
1021 void MultiList::implSetName( sal_Int64 nKey, const OUString& rName )
1022 {
1023  OUStringVector aNames;
1024  StringHelper::convertStringToStringList( aNames, rName, false );
1025  setNamesFromVec( nKey, aNames );
1026 }
1027 
1029  NameListBase( rCfgData ),
1030  mnIgnore( 0 )
1031 {
1032 }
1033 
1035  TextInputStream& rStrm, const OUString& rKey, const OUString& rData )
1036 {
1037  if ( rKey == "ignore" )
1038  {
1039  sal_Int64 nIgnore;
1040  if( StringHelper::convertStringToInt( nIgnore, rData ) )
1041  setIgnoreFlags( nIgnore );
1042  }
1043  else
1044  {
1045  NameListBase::implProcessConfigItemStr( rStrm, rKey, rData );
1046  }
1047 }
1048 
1049 void FlagsList::implSetName( sal_Int64 nKey, const OUString& rName )
1050 {
1051  if( (nKey != 0) && ((nKey & (nKey - 1)) == 0) ) // only a single bit set?
1052  insertRawName( nKey, rName );
1053 }
1054 
1055 OUString FlagsList::implGetName( const Config& /*rCfg*/, sal_Int64 nKey ) const
1056 {
1057  sal_Int64 nFound = mnIgnore;
1058  OUStringBuffer aName;
1059  // add known flags
1060  for( const_iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt )
1061  {
1062  sal_Int64 nMask = aIt->first;
1063  setFlag( nFound, nMask );
1064  if( !getFlag( mnIgnore, nMask ) )
1065  {
1066  const OUString& rFlagName = aIt->second;
1067  bool bOnOff = rFlagName.startsWith(":");
1068  bool bFlag = getFlag( nKey, nMask );
1069  if( bOnOff )
1070  {
1071  StringHelper::appendToken( aName, rFlagName.subView( 1 ) );
1072  aName.appendAscii( bFlag ? ":on" : ":off" );
1073  }
1074  else
1075  {
1076  bool bNegated = rFlagName.startsWith("!");
1077  sal_Int32 nBothSep = bNegated ? rFlagName.indexOf( '!', 1 ) : -1;
1078  if( bFlag )
1079  {
1080  if( !bNegated )
1081  StringHelper::appendToken( aName, rFlagName );
1082  else if( nBothSep > 0 )
1083  StringHelper::appendToken( aName, rFlagName.subView( nBothSep + 1 ) );
1084  }
1085  else if( bNegated )
1086  {
1087  if( nBothSep > 0 )
1088  StringHelper::appendToken( aName, rFlagName.subView( 1, nBothSep - 1 ) );
1089  else
1090  StringHelper::appendToken( aName, rFlagName.subView( 1 ) );
1091  }
1092  }
1093  }
1094  }
1095  // add unknown flags
1096  setFlag( nKey, nFound, false );
1097  if( nKey != 0 )
1098  {
1099  OUStringBuffer aUnknown( OOX_DUMP_UNKNOWN );
1100  aUnknown.append( OOX_DUMP_ITEMSEP );
1101  StringHelper::appendShortHex( aUnknown, nKey );
1102  StringHelper::enclose( aUnknown, '(', ')' );
1103  StringHelper::appendToken( aName, aUnknown.makeStringAndClear() );
1104  }
1105  return aName.makeStringAndClear();
1106 }
1107 
1108 OUString FlagsList::implGetNameDbl( const Config& /*rCfg*/, double /*fValue*/ ) const
1109 {
1110  return OUString();
1111 }
1112 
1114 {
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 
1129 void 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)
1137  {
1138  OUStringPair aPair = StringHelper::convertStringToPair(elemRemain);
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 
1167 OUString 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.makeStringAndClear(), 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, '(', ')' );
1213  StringHelper::appendToken( aName, aItem.makeStringAndClear() );
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;
1226  FlagsList::implIncludeList( rList );
1227 }
1228 
1230  NameListBase( rCfgData ),
1231  mfFactor( 1.0 )
1232 {
1233 }
1234 
1235 void UnitConverter::implSetName( sal_Int64 /*nKey*/, const OUString& /*rName*/ )
1236 {
1237  // nothing to do
1238 }
1239 
1240 OUString UnitConverter::implGetName( const Config& rCfg, sal_Int64 nKey ) const
1241 {
1242  return implGetNameDbl( rCfg, static_cast< double >( nKey ) );
1243 }
1244 
1245 OUString 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 
1264 SharedConfigData::SharedConfigData( const OUString& rFileName,
1265  const Reference< XComponentContext >& rxContext, const StorageRef& rxRootStrg,
1266  const OUString& rSysFileName ) :
1267  mxContext( rxContext ),
1268  mxRootStrg( rxRootStrg ),
1269  maSysFileName( rSysFileName ),
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 
1285 const 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 
1291 void SharedConfigData::setNameList( const OUString& rListName, const NameListRef& rxList )
1292 {
1293  if( !rListName.isEmpty() )
1294  maNameLists[ rListName ] = rxList;
1295 }
1296 
1297 void SharedConfigData::eraseNameList( const OUString& rListName )
1298 {
1299  maNameLists.erase( rListName );
1300 }
1301 
1302 NameListRef 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 
1337 bool SharedConfigData::readConfigFile( const OUString& rFileUrl )
1338 {
1339  bool bLoaded = maConfigFiles.count( rFileUrl ) > 0;
1340  if( !bLoaded )
1341  {
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 
1354 void SharedConfigData::createShortList( const OUString& 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 
1373 void SharedConfigData::createUnitConverter( const OUString& 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 
1397 Config::Config( const char* pcEnvVar, const FilterBase& rFilter )
1398 {
1399  construct( pcEnvVar, rFilter );
1400 }
1401 
1402 Config::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 
1411 void 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 
1417 void 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 
1424 const OUString& Config::getStringOption( const String& rKey, const OUString& rDefault ) const
1425 {
1426  const OUString* pData = implGetOption( rKey );
1427  return pData ? *pData : rDefault;
1428 }
1429 
1430 bool 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 
1446 void Config::eraseNameList( const String& rListName )
1447 {
1448  mxCfgData->eraseNameList( rListName );
1449 }
1450 
1451 NameListRef Config::getNameList( const String& rListName ) const
1452 {
1453  return mxCfgData->getNameList( rListName );
1454 }
1455 
1457 {
1458  return isValid( mxCfgData );
1459 }
1460 
1461 const OUString* Config::implGetOption( const OUString& rKey ) const
1462 {
1463  return mxCfgData->getOption( rKey );
1464 }
1465 
1466 Output::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 
1509 void Output::startTable( sal_Int32 nW1 )
1510 {
1511  startTable( 1, &nW1 );
1512 }
1513 
1514 void 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 
1522 void 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 
1532 void 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 
1549 void 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  {
1561  StringHelper::appendChar( maLine, ' ', 2 );
1562  }
1563 }
1564 
1566 {
1567  maColPos.clear();
1568 }
1569 
1570 void Output::resetItemIndex( sal_Int64 nIdx )
1571 {
1572  mnItemIdx = nIdx;
1573 }
1574 
1575 void 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 
1632 void Output::writeChar( sal_Unicode cChar, sal_Int32 nCount )
1633 {
1634  StringHelper::appendEncChar( maLine, cChar, nCount );
1635 }
1636 
1637 void Output::writeAscii( const char* pcStr )
1638 {
1639  if( pcStr )
1640  maLine.appendAscii( pcStr );
1641 }
1642 
1643 void Output::writeString( const OUString& rStr )
1644 {
1646 }
1647 
1648 void 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 
1659 void Output::writeBool( bool bData )
1660 {
1661  StringHelper::appendBool( maLine, bData );
1662 }
1663 
1664 void 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 
1684 void Output::writeItemName( const String& rItemName )
1685 {
1686  if( rItemName.has() && (rItemName[ 0 ] == '#') )
1687  {
1688  writeString( rItemName.copy( 1 ) );
1690  }
1691  else
1692  writeString( rItemName );
1693 }
1694 
1696  mxStrg( rxStrg )
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 
1744 void ObjectBase::construct( const ConfigRef& rxConfig )
1745 {
1746  mxConfig = rxConfig;
1747 }
1748 
1749 void 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 
1769 void 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 );
1779  if( ObjectBase::implIsValid() )
1780  {
1781  mxStrg = cfg().getRootStorage();
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 
1822 void StorageObjectBase::implDumpStream( const Reference< XInputStream >&, const OUString&, const OUString&, const OUString& )
1823 {
1824 }
1825 
1826 void 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  const OUString& 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 
1864 void 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  }
1874  if( xDumpStrm.is() )
1875  implDumpStream( xDumpStrm, rStrgPath, rStrmName, rSysFileName );
1876 }
1877 
1878 void 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 
1912 void 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 
1931 void OutputObjectBase::construct( const ObjectBase& rParent, const OUString& rSysFileName )
1932 {
1933  ObjectBase::construct( rParent );
1934  if( ObjectBase::implIsValid() )
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 
1956 void 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 
1970 void OutputObjectBase::writeStringItem( const String& rName, const OUString& rData )
1971 {
1972  ItemGuard aItem( mxOut, rName );
1973  mxOut->writeAscii( "(len=" );
1974  mxOut->writeDec( rData.getLength() );
1975  mxOut->writeAscii( ")," );
1976  OUStringBuffer aValue( rData.subView( 0, ::std::min( rData.getLength(), OOX_DUMP_MAXSTRLEN ) ) );
1978  mxOut->writeString( aValue.makeStringAndClear() );
1979  if( rData.getLength() > OOX_DUMP_MAXSTRLEN )
1980  mxOut->writeAscii( ",cut" );
1981 }
1982 
1983 void 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 
1989 void OutputObjectBase::writeDateTimeItem( const String& rName, const util::DateTime& rDateTime )
1990 {
1991  ItemGuard aItem( mxOut, rName );
1992  mxOut->writeDateTime( rDateTime );
1993 }
1994 
1995 void 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 
2007 void 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 
2029 void 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 
2040 void 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 
2094 void 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 
2105 void 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 
2116 void InputObjectBase::dumpRemainingTo( sal_Int64 nPos )
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 
2130 void 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 
2155 OUString 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 
2172 OUString 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 
2186 util::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 
2235 OUString 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 
2267 void InputObjectBase::dumpItem( const ItemFormat& rItemFmt )
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 
2286 BinaryStreamObject::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 {
2300  dumpBinaryStream();
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 
2327 void 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 
2356 void TextLineStreamObject::implDumpLine( const OUString& 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( aOldStartElem.makeStringAndClear().trim() );
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( !aText.trim().isEmpty() )
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 
2504 void 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 
2536 bool 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 
2570 void 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: */
OUString maItemName
Name of the item.
Definition: dumperbase.hxx:207
virtual void implDumpText(TextInputStream &rTextStrm) override
Unsigned 32-bit integer.
Definition: dumperbase.hxx:162
virtual OUString implGetName(const Config &rCfg, sal_Int64 nKey) const override
Returns the name for the passed key.
virtual void implDumpBaseStream(const BinaryInputStreamRef &rxStrm, const OUString &rSysFileName)
static const sal_Int64 minutePerHour
bool getBoolOption(const String &rKey, bool bDefault) const
const_iterator end() const
Returns a map iterator pointing one past the last contained name.
Definition: dumperbase.hxx:542
XmlStreamObject(const ObjectBase &rParent, const BinaryInputStreamRef &rxStrm, const OUString &rSysFileName)
static LineType readConfigLine(TextInputStream &rStrm, OUString &orKey, OUString &orData)
Definition: dumperbase.cxx:832
void writeStringItem(const String &rName, const OUString &rData)
const OUString & getStringOption(const String &rKey, const OUString &rDefault) const
bool isImportEnabled() const
sal_Int32 nIndex
void writeItemName(const String &rItemName)
virtual void implProcessConfigItemInt(TextInputStream &rStrm, sal_Int64 nKey, const OUString &rData) override
Definition: dumperbase.cxx:903
static const sal_Int64 nanoSecPerSec
static const sal_Int64 secondPerMinute
const css::uno::Reference< css::uno::XComponentContext > & getContext() const
Wraps a UNO input stream and provides convenient access functions.
static void convertStringToStringList(OUStringVector &orVec, const OUString &rData, bool bIgnoreEmpty)
Definition: dumperbase.cxx:762
::std::map< sal_Int64, ItemFormat > maMap
Definition: dumperbase.hxx:742
Hexadecimal, as short as possible (no leading zeros).
Definition: dumperbase.hxx:176
void construct(const ConfigRef &rxConfig)
static std::u16string_view trimSpaces(std::u16string_view rStr)
Definition: dumperbase.cxx:602
static OUStringPair convertStringToPair(const OUString &rString, sal_Unicode cSep= '=')
Definition: dumperbase.cxx:743
void writeHex(Type nData, bool bPrefix=true)
Definition: dumperbase.hxx:967
void setNamesFromVec(sal_Int64 nStartKey, const OUStringVector &rNames)
bool readConfigFile(const OUString &rFileUrl)
PreferredItemVector maPreferred
UnitConverter(const SharedConfigData &rCfgData)
static std::u16string_view getToken(std::u16string_view rData, sal_Int32 &rnPos, sal_Unicode cSep=OOX_DUMP_LISTSEP)
Definition: dumperbase.cxx:529
virtual void implSetName(sal_Int64 nKey, const OUString &rName) override
Sets the name for the passed key.
static void appendBin(OUStringBuffer &rStr, sal_uInt8 nData, bool bDots=true)
Definition: dumperbase.cxx:384
signed char sal_Int8
virtual bool implIsValid() const override
virtual ~ObjectBase() override
Unsigned 64-bit integer.
Definition: dumperbase.hxx:164
Static helper functions for system file and stream access.
Definition: dumperbase.hxx:99
uno::Reference< uno::XComponentContext > mxContext
std::unique_ptr< sal_Int32[]> pData
OUString readToChar(sal_Unicode cChar, bool bIncludeChar)
Reads a text portion from the stream until the specified character is found.
static void appendDec(OUStringBuffer &rStr, sal_uInt8 nData, sal_Int32 nWidth=0, sal_Unicode cFill= ' ')
Definition: dumperbase.cxx:210
bool operator<(const ExtItemFormatKey &rRight) const
FormatType
Specifiers for the output format of values.
Definition: dumperbase.hxx:171
virtual void implIncludeList(const NameListBase &rList)=0
Derived classes insert all names and other settings from the passed list.
bool isDumperEnabled() const
bool isImportEnabled() const
void emptyLine(size_t nCount=1)
virtual ~NameListBase() override
Definition: dumperbase.cxx:868
void createUnitConverter(const OUString &rData)
sal_Int32 mnLastItem
static sal_uInt64 lcl_ConvertDouble(double const f)
Definition: dumperbase.cxx:311
void setNameList(const OUString &rListName, const NameListRef &rxList)
sal_Int32 mnCol
::std::vector< OUString > OUStringVector
Definition: dumperbase.hxx:94
void implDumpLine(const OUString &rLine, sal_uInt32 nLine)
void dumpArray(const String &rName, sal_Int32 nBytes, sal_Unicode cSep=OOX_DUMP_LISTSEP)
Boolean ('true' or 'false').
Definition: dumperbase.hxx:179
void addPreferredStream(const String &rStrmName)
const NameListRef & getNameList(const Config &rCfg) const
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
static bool convertStringToInt(sal_Int64 &ornData, std::u16string_view rData)
Definition: dumperbase.cxx:712
Type getIntOption(const String &rKey, Type nDefault) const
Definition: dumperbase.hxx:897
::std::pair< OUString, OUString > OUStringPair
Definition: dumperbase.hxx:92
OUString readLine()
Reads a text line from the stream.
virtual void implDump() override
virtual void implProcessConfigItemStr(TextInputStream &rStrm, const OUString &rKey, const OUString &rData) override
virtual bool implIsValid() const override
std::shared_ptr< StorageBase > StorageRef
Definition: storagebase.hxx:42
virtual void implDumpText(TextInputStream &rTextStrm) override
static void appendChar(OUStringBuffer &rStr, sal_Unicode cChar, sal_Int32 nCount)
Definition: dumperbase.cxx:196
OUString getName() const
void readConfigBlockContents(TextInputStream &rStrm)
Definition: dumperbase.cxx:814
virtual OUString implGetName(const Config &rCfg, sal_Int64 nKey) const override
Returns the converted value with appended unit name.
#define OOX_DUMP_ERR_STREAM
Definition: dumperbase.hxx:71
NameListWrapper maSimpleRecs
static void appendIndex(OUStringBuffer &rStr, sal_Int64 nIdx)
Definition: dumperbase.cxx:522
void writeArray(const sal_uInt8 *pnData, std::size_t nSize, sal_Unicode cSep=OOX_DUMP_LISTSEP)
Signed 8-bit integer.
Definition: dumperbase.hxx:157
virtual sal_Int64 size() const =0
Implementations return the size of the stream, if possible.
NameListRef getNameList(const String &rListName) const
Wraps a UNO output stream and provides convenient access functions.
virtual ~OutputObjectBase() override
virtual void implProcessConfigItemStr(TextInputStream &rStrm, const OUString &rKey, const OUString &rData)
Definition: dumperbase.cxx:804
#define SAL_MAX_UINT32
void dumpRemainingTo(sal_Int64 nPos)
void construct(const ObjectBase &rParent, const BinaryInputStreamRef &rxBaseStrm, const OUString &rSysFileName, const BinaryInputStreamRef &rxRecStrm, const String &rRecNames, const String &rSimpleRecs)
static OUString convertFileNameToUrl(const OUString &rFileName)
Definition: dumperbase.cxx:67
virtual void implDumpRecordBody()
void createShortList(const OUString &rData)
sal_uInt16 sal_Unicode
::std::vector< sal_Int64 > Int64Vector
Definition: dumperbase.hxx:95
bool has() const
Definition: dumperbase.hxx:383
Floating-point, double precision.
Definition: dumperbase.hxx:166
OUString dumpCharArray(const String &rName, sal_Int32 nLen, rtl_TextEncoding eTextEnc, bool bHideTrailingNul=false)
void eraseNameList(const OUString &rListName)
virtual bool implIsValid() const override
OUStringVector::const_iterator maIt
void dumpRawBinary(sal_Int64 nBytes, bool bShowOffset, bool bStream=false)
std::shared_ptr< SharedConfigData > mxCfgData
Definition: dumperbase.hxx:890
std::shared_ptr< TextInputStream > mxTextStrm
StorageIterator(const StorageRef &rxStrg)
OUStringBuffer maLine
Definition: dumperbase.hxx:995
DataType
Specifiers for atomic data types.
Definition: dumperbase.hxx:154
#define SAL_MAX_UINT16
Signed 16-bit integer.
Definition: dumperbase.hxx:159
int nCount
Output(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const OUString &rFileName)
void writeDateTimeItem(const String &rName, const css::util::DateTime &rDateTime)
void constructTextStrmObj(rtl_TextEncoding eTextEnc)
void construct(const ObjectBase &rParent, const BinaryInputStreamRef &rxStrm, rtl_TextEncoding eTextEnc, const OUString &rSysFileName)
virtual void implSetName(sal_Int64 nKey, const OUString &rName) override
Sets the name for the passed key.
const OUString & getSysFileName() const
Definition: dumperbase.hxx:853
void writeBool(bool bData)
void writeDec(Type nData, sal_Int32 nWidth=0, sal_Unicode cFill= ' ')
Definition: dumperbase.hxx:964
virtual OUString implGetNameDbl(const Config &rCfg, double fValue) const override
Returns the converted value with appended unit name.
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
void include(const OUString &rListKeys)
Includes name lists, given in a comma separated list of names of the lists.
Definition: dumperbase.cxx:920
static void appendValue(OUStringBuffer &rStr, Type nData, FormatType eFmtType)
Definition: dumperbase.hxx:360
virtual void implSetName(sal_Int64 nKey, const OUString &rName) override
Sets the name for the passed key.
virtual bool implIsValid() const override
virtual void implDumpText(TextInputStream &rTextStrm)=0
FormatType meFmtType
Output format for the value.
Definition: dumperbase.hxx:206
virtual OUString implGetName(const Config &rCfg, sal_Int64 nKey) const override
Returns the name for the passed key.
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:135
virtual void implProcessConfigItemStr(TextInputStream &rStrm, const OUString &rKey, const OUString &rData) override
const String EMPTY_STRING
Definition: dumperbase.hxx:387
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:968
void writeAscii(const char *pcStr)
virtual void implIncludeList(const NameListBase &rList) override
Inserts all flags from the passed list.
Signed 64-bit integer.
Definition: dumperbase.hxx:163
DocumentType eType
void construct(const ObjectBase &rParent, const StorageRef &rxStrg, const OUString &rSysPath)
OUString dumpUnicodeArray(const String &rName, sal_Int32 nLen, bool bHideTrailingNul=false)
Interface for binary input stream classes.
const SharedConfigData & mrCfgData
Definition: dumperbase.hxx:581
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:165
std::shared_ptr< StreamDataSequence > mxRecData
DataType meDataType
Data type of the item.
Definition: dumperbase.hxx:205
::std::pair< sal_Int64, sal_Int64 > maFilter
Definition: dumperbase.hxx:681
void writeGuidItem(const String &rName, const OUString &rGuid)
static bool convertStringToBool(std::u16string_view rData)
Definition: dumperbase.cxx:733
Base class for storage access implementations.
Definition: storagebase.hxx:51
css::uno::Reference< css::uno::XComponentContext > mxContext
Definition: dumperbase.hxx:800
void writeDecItem(const String &rName, Type nData, const NameListWrapper &rListWrp=NO_LIST)
virtual ~DumperBase() override
sal_uInt16 char * pName
void addNameToItem(Type nData, const NameListWrapper &rListWrp)
OUString dumpGuid(const String &rName=EMPTY_STRING)
void dumpBinary(const String &rName, sal_Int64 nBytes, bool bShowOffset=true)
void dumpItem(const ItemFormat &rItemFmt)
sal_Unicode dumpUnicode(const String &rName)
static bool convertFromDec(sal_Int64 &ornData, std::u16string_view rData)
Definition: dumperbase.cxx:670
css::util::DateTime dumpFileTime(const String &rName=EMPTY_STRING)
Describes the output format of a data item.
Definition: dumperbase.hxx:203
static void appendShortHex(OUStringBuffer &rStr, sal_uInt8 nData, bool bPrefix=true)
Definition: dumperbase.cxx:328
Unsigned 16-bit integer.
Definition: dumperbase.hxx:160
void construct(const ObjectBase &rParent, const BinaryInputStreamRef &rxBaseStrm, const OUString &rSysFileName, const String &rRecNames, const String &rSimpleRecs)
void processConfigItem(TextInputStream &rStrm, const OUString &rKey, const OUString &rData)
Definition: dumperbase.cxx:858
void construct(const ObjectBase &rParent, const BinaryInputStreamRef &rxStrm, const OUString &rSysFileName)
virtual void implProcessConfigItemStr(TextInputStream &rStrm, const OUString &rKey, const OUString &rData) override
Definition: dumperbase.cxx:952
void insertRawName(sal_Int64 nKey, const OUString &rName)
Inserts the passed name into the internal map.
Definition: dumperbase.cxx:909
constexpr OUStringLiteral OOX_DUMP_ERR_NONAME
Definition: dumperbase.hxx:70
virtual void implIncludeList(const NameListBase &rList) override
Inserts all flags from the passed list.
static css::uno::Reference< css::io::XInputStream > openInputStream(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const OUString &rFileName)
Definition: dumperbase.cxx:92
void constructRecObjBase(const BinaryInputStreamRef &rxBaseStrm, const String &rRecNames, const String &rSimpleRecs)
virtual bool implIsValid() const override
void skipBlock(sal_Int64 nBytes, bool bShowSize=true)
virtual bool implIsValid() const override
static sal_Int32 getFileNamePos(std::u16string_view rFileUrl)
Definition: dumperbase.cxx:75
SharedConfigData(const OUString &rFileName, const css::uno::Reference< css::uno::XComponentContext > &rxContext, const StorageRef &rxRootStrg, const OUString &rSysFileName)
void writeCharItem(const String &rName, sal_Unicode cData)
static FormatType convertToFormatType(std::u16string_view rStr)
Definition: dumperbase.cxx:652
void set(DataType eDataType, FormatType eFmtType, const OUString &rItemName)
Definition: dumperbase.cxx:153
ExtItemFormatMap maFmtMap
Definition: dumperbase.hxx:692
::std::vector< sal_Int32 > maColPos
Definition: dumperbase.hxx:998
float u
virtual bool implReadRecordHeader(BinaryInputStream &rBaseStrm, sal_Int64 &ornRecId, sal_Int64 &ornRecSize)=0
virtual void implSetName(sal_Int64 nKey, const OUString &rName) override
Sets the name for the passed key.
bool isValid() const
Definition: dumperbase.hxx:449
virtual bool implIsValid() const override
Definition: dumperbase.cxx:887
static bool convertStringToDouble(double &orfData, std::u16string_view rData)
Definition: dumperbase.cxx:719
virtual bool implIsValid() const override
static OString convertToUtf8(std::u16string_view rStr)
Definition: dumperbase.cxx:621
const OUString * implGetOption(const OUString &rKey) const
void setQuoteNames(bool bQuoteNames)
Enables or disables automatic quotation of returned names.
Definition: dumperbase.hxx:591
void construct(const ObjectBase &rParent, const OUString &rSysFileName)
Config & cfg() const
virtual sal_Int64 tell() const =0
Implementations return the current stream position, if possible.
FlagsList(const SharedConfigData &rCfgData)
static bool convertFromHex(sal_Int64 &ornData, std::u16string_view rData)
Definition: dumperbase.cxx:693
constexpr OUStringLiteral OOX_DUMP_UNKNOWN
Definition: dumperbase.hxx:65
void includeList(const NameListRef &rxList)
Include all names of the passed list.
Definition: dumperbase.cxx:877
virtual void implDumpStorage(const StorageRef &rxStrg, const OUString &rStrgPath, const OUString &rSysPath)
static void appendString(OUStringBuffer &rStr, const OUString &rData, sal_Int32 nWidth, sal_Unicode cFill= ' ')
Definition: dumperbase.cxx:202
static void appendCChar(OUStringBuffer &rStr, sal_Unicode cChar, bool bPrefix=true)
Definition: dumperbase.cxx:452
static OUString getSysFileName(const OUString &rStrmName, std::u16string_view rSysOutPath)
void extractStorage(const StorageRef &rxStrg, const OUString &rStrgPath, const OUString &rSysPath)
css::uno::Reference< css::io::XInputStream > openInputStream(const OUString &rStreamName)
Opens and returns the specified input stream from the storage.
void writeArrayItem(const String &rName, const sal_uInt8 *pnData, std::size_t nSize, sal_Unicode cSep=OOX_DUMP_LISTSEP)
void insertFormats(const NameListRef &rxNameList)
Definition: dumperbase.cxx:936
virtual bool implIsValid() const override
void setIgnoreFlags(sal_Int64 nIgnore)
Sets flags to be ignored on output.
Definition: dumperbase.hxx:642
void addPreferredStorage(const String &rStrgPath)
static void appendHex(OUStringBuffer &rStr, sal_uInt8 nData, bool bPrefix=true)
Definition: dumperbase.cxx:264
virtual ~SharedConfigData() override
virtual ~InputObjectBase() override
virtual void implDump() override
enumrange< T >::Iterator end(enumrange< T >)
void dumpBinaryStream(bool bShowOffset=true)
void writeChar(sal_Unicode cChar, sal_Int32 nCount=1)
void construct(const char *pcEnvVar, const ::oox::core::FilterBase &rFilter)
const sal_Unicode OOX_DUMP_STRQUOTE
Definition: dumperbase.hxx:75
OUStringVector::const_iterator parse(const OUStringVector &rFormatVec)
Initializes the struct from a vector of strings containing the item format.
Definition: dumperbase.cxx:161
virtual ~Base()
Definition: dumperbase.cxx:791
virtual ~Config() override
bool isEof() const
Returns true, if no more text is available in the stream.
static void convertStringToIntList(Int64Vector &orVec, const OUString &rData, bool bIgnoreEmpty)
Definition: dumperbase.cxx:776
virtual OUString implGetNameDbl(const Config &rCfg, double fValue) const override
Returns the name for the passed double value.
virtual bool implStartRecord(BinaryInputStream &rBaseStrm, sal_Int64 &ornRecPos, sal_Int64 &ornRecId, sal_Int64 &ornRecSize)=0
std::shared_ptr< NameListBase > NameListRef
Definition: dumperbase.hxx:499
#define OOX_DUMP_DUMPEXT
Definition: dumperbase.hxx:73
virtual void implDump()
virtual bool implIsValid() const override
std::unique_ptr< char[]> aBuffer
void writeString(const OUString &rStr)
void startTable(sal_Int32 nW1)
virtual void implSetName(sal_Int64 nKey, const OUString &rName)=0
Derived classes set the name for the passed key.
Base class of all classes providing names for specific values (name lists).
Definition: dumperbase.hxx:510
StorageIterator & operator++()
virtual void implSetName(sal_Int64 nKey, const OUString &rName) override
Sets the name for the passed key.
Definition: dumperbase.cxx:963
virtual ~StorageIterator() override
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
void writeDateTime(const css::util::DateTime &rDateTime)
unsigned char sal_uInt8
#define SAL_MAX_UINT8
OUString aName
void extractStream(StorageBase &rStrg, const OUString &rStrgPath, const OUString &rStrmName, const OUString &rSysFileName)
Signed 32-bit integer.
Definition: dumperbase.hxx:161
MultiList(const SharedConfigData &rCfgData)
Definition: dumperbase.cxx:995
std::u16string_view trim(std::u16string_view str)
void construct(const ConfigRef &rxConfig)
void resetItemIndex(sal_Int64 nIdx=0)
virtual void implProcessConfigItemStr(TextInputStream &rStrm, const OUString &rKey, const OUString &rData) override
Definition: dumperbase.cxx:892
bool isSeekable() const
Returns true, if the implementation supports the seek() operation.
void startItem(const String &rItemName)
NameListRef getNameList(const OUString &rListName) const
const char * name
static void appendEncString(OUStringBuffer &rStr, const OUString &rData, bool bPrefix=true)
Definition: dumperbase.cxx:485
OUString getName(const NameListWrapper &rListWrp, Type nKey) const
Returns the name for the passed key from the passed name list.
Definition: dumperbase.hxx:912
CombiList(const SharedConfigData &rCfgData)
static DataType convertToDataType(std::u16string_view rStr)
Definition: dumperbase.cxx:626
virtual void implDumpStream(const css::uno::Reference< css::io::XInputStream > &rxStrm, const OUString &rStrgPath, const OUString &rStrmName, const OUString &rSysFileName)
void readConfigBlock(TextInputStream &rStrm)
Definition: dumperbase.cxx:799
virtual bool implStartRecord(BinaryInputStream &rBaseStrm, sal_Int64 &ornRecPos, sal_Int64 &ornRecId, sal_Int64 &ornRecSize) override
const OUString * findRawName(sal_Int64 nKey) const
Returns the name for the passed key, or 0, if nothing found.
Definition: dumperbase.cxx:914
const OUString * getOption(const OUString &rKey) const
static const sal_Int64 nanoSecPerDay
virtual void implIncludeList(const NameListBase &rList) override
Inserts all names from the passed list.
Definition: dumperbase.cxx:986
void writeInfoItem(const String &rName, const String &rData)
virtual bool implIsValid() const override
static void appendEncChar(OUStringBuffer &rStr, sal_Unicode cChar, sal_Int32 nCount, bool bPrefix=true)
Definition: dumperbase.cxx:468
virtual sal_Int32 readData(StreamDataSequence &orData, sal_Int32 nBytes, size_t nAtomSize=1)=0
Derived classes implement reading nBytes bytes to the passed sequence.
std::shared_ptr< Config > ConfigRef
Definition: dumperbase.hxx:893
static void appendToken(OUStringBuffer &rStr, std::u16string_view rToken, sal_Unicode cSep=OOX_DUMP_LISTSEP)
Definition: dumperbase.cxx:515
void writeEmptyItem(const String &rName)
BinaryInputStreamRef mxBaseStrm
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)
virtual void implIncludeList(const NameListBase &rList) override
Empty implementation.
bool isEof() const
Returns true, if the stream position is invalid (EOF).
OUString maListName
Name of a name list to be used for this item.
Definition: dumperbase.hxx:208
virtual void implProcessConfigItemStr(TextInputStream &rStrm, const OUString &rKey, const OUString &rData) override
TextLineStreamObject(const ObjectBase &rParent, const BinaryInputStreamRef &rxStrm, rtl_TextEncoding eTextEnc, const OUString &rSysFileName)
const StorageRef & getRootStorage() const
Definition: dumperbase.hxx:852
Floating-point, single precision.
Definition: dumperbase.hxx:165
virtual void implProcessConfigItemInt(TextInputStream &rStrm, sal_Int64 nKey, const OUString &rData)
Definition: dumperbase.cxx:809
OUStringMap::const_iterator const_iterator
Definition: dumperbase.hxx:514
BinaryStreamObject(const ObjectBase &rParent, const BinaryInputStreamRef &rxStrm, const OUString &rSysFileName)
void setName(sal_Int64 nKey, const String &rName)
Sets a name for the specified key.
Definition: dumperbase.cxx:872
void tab(size_t nCol)
void dumpRemaining(sal_Int64 nBytes)
void eraseNameList(const String &rListName)
static void appendBool(OUStringBuffer &rStr, bool bData)
Definition: dumperbase.cxx:445
GUIDCNamePair aData
Definition: olehelper.cxx:98
void extractItem(const StorageRef &rxStrg, const OUString &rStrgPath, const OUString &rItemName, std::u16string_view rSysPath, bool bIsStrg, bool bIsStrm)
virtual OUString implGetNameDbl(const Config &rCfg, double fValue) const override
Returns the name for the passed double value.
Definition: dumperbase.cxx:981
virtual void implDump() override
No numeric format (e.g. show name only).
Definition: dumperbase.hxx:173
#define SAL_MAX_INT64
virtual void implWriteExtHeader()
static OUString trimTrailingNul(const OUString &rStr)
Definition: dumperbase.cxx:613
BinaryInputStreamRef mxStrm
void writeShortHexItem(const String &rName, Type nData, const NameListWrapper &rListWrp=NO_LIST)
sal_uInt16 nPos
void exclude(const OUString &rKeys)
Excludes names from the list, given in a comma separated list of their keys.
Definition: dumperbase.cxx:928
static css::uno::Reference< css::io::XOutputStream > openOutputStream(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const OUString &rFileName)
Definition: dumperbase.cxx:109
constexpr OUStringLiteral OOX_DUMP_UNUSED
Definition: dumperbase.hxx:64
static void enclose(OUStringBuffer &rStr, sal_Unicode cOpen, sal_Unicode cClose= '\0')
Encloses the passed string with the passed characters.
Definition: dumperbase.cxx:534
const_iterator begin() const
Returns a map iterator pointing to the first contained name.
Definition: dumperbase.hxx:540
bool m_bDetectedRangeSegmentation false
static std::u16string_view getFileNameExtension(std::u16string_view rFileUrl)
Definition: dumperbase.cxx:81
Unsigned 8-bit integer.
Definition: dumperbase.hxx:158
ConstList(const SharedConfigData &rCfgData)
Definition: dumperbase.cxx:945
virtual void implDump() override
css::uno::Reference< css::io::XTextOutputStream2 > mxStrm
Definition: dumperbase.hxx:993