Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / sc / source / filter / excel / xestring.cxx
blobcdb1601bb30fbef1ddcab53c10fab9c7feb974d8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <algorithm>
21 #include <cassert>
23 #include <osl/diagnose.h>
24 #include "xlstyle.hxx"
25 #include "xestyle.hxx"
26 #include "xestream.hxx"
27 #include "xestring.hxx"
29 using namespace ::oox;
31 namespace {
33 // compare vectors
35 /** Compares two vectors.
36 @return A negative value, if rLeft<rRight; or a positive value, if rLeft>rRight;
37 or 0, if rLeft==rRight. */
38 template< typename Type >
39 int lclCompareVectors( const ::std::vector< Type >& rLeft, const ::std::vector< Type >& rRight )
41 int nResult = 0;
43 // 1st: compare all elements of the vectors
44 typedef typename ::std::vector< Type >::const_iterator CIT;
45 CIT aEndL = rLeft.end(), aEndR = rRight.end();
46 for( CIT aItL = rLeft.begin(), aItR = rRight.begin(); !nResult && (aItL != aEndL) && (aItR != aEndR); ++aItL, ++aItR )
47 nResult = static_cast< int >( *aItL ) - static_cast< int >( *aItR );
49 // 2nd: no differences found so far -> compare the vector sizes. Shorter vector is less
50 if( !nResult )
51 nResult = static_cast< int >( rLeft.size() ) - static_cast< int >( rRight.size() );
53 return nResult;
56 // hashing helpers
58 /** Base class for value hashers.
59 @descr These function objects are used to hash any value to a sal_uInt32 value. */
60 template< typename Type >
61 struct XclHasher : public ::std::unary_function< Type, sal_uInt32 > {};
63 template< typename Type >
64 struct XclDirectHasher : public XclHasher< Type >
66 inline sal_uInt32 operator()( Type nVal ) const { return nVal; }
69 struct XclFormatRunHasher : public XclHasher< const XclFormatRun& >
71 inline sal_uInt32 operator()( const XclFormatRun& rRun ) const
72 { return (rRun.mnChar << 8) ^ rRun.mnFontIdx; }
75 /** Calculates a hash value from a vector.
76 @descr Uses the passed hasher function object to calculate hash values from
77 all vector elements. */
78 template< typename Type, typename ValueHasher >
79 sal_uInt16 lclHashVector( const ::std::vector< Type >& rVec, const ValueHasher& rHasher )
81 sal_uInt32 nHash = rVec.size();
82 typedef typename ::std::vector< Type >::const_iterator CIT;
83 for( CIT aIt = rVec.begin(), aEnd = rVec.end(); aIt != aEnd; ++aIt )
84 (nHash *= 31) += rHasher( *aIt );
85 return static_cast< sal_uInt16 >( nHash ^ (nHash >> 16) );
88 /** Calculates a hash value from a vector. Uses XclDirectHasher to hash the vector elements. */
89 template< typename Type >
90 inline sal_uInt16 lclHashVector( const ::std::vector< Type >& rVec )
92 return lclHashVector( rVec, XclDirectHasher< Type >() );
95 } // namespace
97 // constructors ---------------------------------------------------------------
99 XclExpString::XclExpString( XclStrFlags nFlags, sal_uInt16 nMaxLen )
101 Init( 0, nFlags, nMaxLen, true );
104 XclExpString::XclExpString( const OUString& rString, XclStrFlags nFlags, sal_uInt16 nMaxLen )
106 Assign( rString, nFlags, nMaxLen );
109 // assign ---------------------------------------------------------------------
111 void XclExpString::Assign( const OUString& rString, XclStrFlags nFlags, sal_uInt16 nMaxLen )
113 Build( rString.getStr(), rString.getLength(), nFlags, nMaxLen );
116 void XclExpString::Assign( sal_Unicode cChar )
118 Build( &cChar, 1, EXC_STR_DEFAULT, EXC_STR_MAXLEN );
121 void XclExpString::AssignByte(
122 const OUString& rString, rtl_TextEncoding eTextEnc, XclStrFlags nFlags, sal_uInt16 nMaxLen )
124 // length may differ from length of rString
125 OString aByteStr(OUStringToOString(rString, eTextEnc));
126 Build(aByteStr.getStr(), aByteStr.getLength(), nFlags, nMaxLen);
129 // append ---------------------------------------------------------------------
131 void XclExpString::Append( const OUString& rString )
133 BuildAppend( rString.getStr(), rString.getLength() );
136 void XclExpString::AppendByte( const OUString& rString, rtl_TextEncoding eTextEnc )
138 if (!rString.isEmpty())
140 // length may differ from length of rString
141 OString aByteStr(OUStringToOString(rString, eTextEnc));
142 BuildAppend(aByteStr.getStr(), aByteStr.getLength());
146 void XclExpString::AppendByte( sal_Unicode cChar, rtl_TextEncoding eTextEnc )
148 if( !cChar )
150 sal_Char cByteChar = 0;
151 BuildAppend( &cByteChar, 1 );
153 else
155 OString aByteStr( &cChar, 1, eTextEnc ); // length may be >1
156 BuildAppend( aByteStr.getStr(), aByteStr.getLength() );
160 // formatting runs ------------------------------------------------------------
162 void XclExpString::AppendFormat( sal_uInt16 nChar, sal_uInt16 nFontIdx, bool bDropDuplicate )
164 OSL_ENSURE( maFormats.empty() || (maFormats.back().mnChar < nChar), "XclExpString::AppendFormat - invalid char index" );
165 size_t nMaxSize = static_cast< size_t >( mbIsBiff8 ? EXC_STR_MAXLEN : EXC_STR_MAXLEN_8BIT );
166 if( maFormats.empty() || ((maFormats.size() < nMaxSize) && (!bDropDuplicate || (maFormats.back().mnFontIdx != nFontIdx))) )
167 maFormats.push_back( XclFormatRun( nChar, nFontIdx ) );
170 void XclExpString::AppendTrailingFormat( sal_uInt16 nFontIdx )
172 AppendFormat( mnLen, nFontIdx, false );
175 void XclExpString::LimitFormatCount( sal_uInt16 nMaxCount )
177 if( maFormats.size() > nMaxCount )
178 maFormats.erase( maFormats.begin() + nMaxCount, maFormats.end() );
181 sal_uInt16 XclExpString::GetLeadingFont()
183 sal_uInt16 nFontIdx = EXC_FONT_NOTFOUND;
184 if( !maFormats.empty() && (maFormats.front().mnChar == 0) )
186 nFontIdx = maFormats.front().mnFontIdx;
188 return nFontIdx;
191 sal_uInt16 XclExpString::RemoveLeadingFont()
193 sal_uInt16 nFontIdx = GetLeadingFont();
194 if( nFontIdx != EXC_FONT_NOTFOUND )
196 maFormats.erase( maFormats.begin() );
198 return nFontIdx;
201 bool XclExpString::IsEqual( const XclExpString& rCmp ) const
203 return
204 (mnLen == rCmp.mnLen) &&
205 (mbIsBiff8 == rCmp.mbIsBiff8) &&
206 (mbIsUnicode == rCmp.mbIsUnicode) &&
207 (mbWrapped == rCmp.mbWrapped) &&
209 ( mbIsBiff8 && (maUniBuffer == rCmp.maUniBuffer)) ||
210 (!mbIsBiff8 && (maCharBuffer == rCmp.maCharBuffer))
211 ) &&
212 (maFormats == rCmp.maFormats);
215 bool XclExpString::IsLessThan( const XclExpString& rCmp ) const
217 int nResult = mbIsBiff8 ?
218 lclCompareVectors( maUniBuffer, rCmp.maUniBuffer ) :
219 lclCompareVectors( maCharBuffer, rCmp.maCharBuffer );
220 return (nResult != 0) ? (nResult < 0) : (maFormats < rCmp.maFormats);
223 // get data -------------------------------------------------------------------
225 sal_uInt16 XclExpString::GetFormatsCount() const
227 return static_cast< sal_uInt16 >( maFormats.size() );
230 sal_uInt8 XclExpString::GetFlagField() const
232 return (mbIsUnicode ? EXC_STRF_16BIT : 0) | (IsWriteFormats() ? EXC_STRF_RICH : 0);
235 sal_uInt16 XclExpString::GetHeaderSize() const
237 return
238 (mb8BitLen ? 1 : 2) + // length field
239 (IsWriteFlags() ? 1 : 0) + // flag field
240 (IsWriteFormats() ? 2 : 0); // richtext formattting count
243 sal_Size XclExpString::GetBufferSize() const
245 return static_cast<sal_Size>(mnLen) * (mbIsUnicode ? 2 : 1);
248 sal_Size XclExpString::GetSize() const
250 return
251 GetHeaderSize() + // header
252 GetBufferSize() + // character buffer
253 (IsWriteFormats() ? (4 * GetFormatsCount()) : 0); // richtext formattting
256 sal_uInt16 XclExpString::GetChar( sal_uInt16 nCharIdx ) const
258 OSL_ENSURE( nCharIdx < Len(), "XclExpString::GetChar - invalid character index" );
259 return static_cast< sal_uInt16 >( mbIsBiff8 ? maUniBuffer[ nCharIdx ] : maCharBuffer[ nCharIdx ] );
262 sal_uInt16 XclExpString::GetHash() const
264 return
265 (mbIsBiff8 ? lclHashVector( maUniBuffer ) : lclHashVector( maCharBuffer )) ^
266 lclHashVector( maFormats, XclFormatRunHasher() );
269 // streaming ------------------------------------------------------------------
271 void XclExpString::WriteLenField( XclExpStream& rStrm ) const
273 if( mb8BitLen )
274 rStrm << static_cast< sal_uInt8 >( mnLen );
275 else
276 rStrm << mnLen;
279 void XclExpString::WriteFlagField( XclExpStream& rStrm ) const
281 if( mbIsBiff8 )
283 PrepareWrite( rStrm, 1 );
284 rStrm << GetFlagField();
285 rStrm.SetSliceSize( 0 );
289 void XclExpString::WriteHeader( XclExpStream& rStrm ) const
291 OSL_ENSURE( !mb8BitLen || (mnLen < 256), "XclExpString::WriteHeader - string too long" );
292 PrepareWrite( rStrm, GetHeaderSize() );
293 // length
294 WriteLenField( rStrm );
295 // flag field
296 if( IsWriteFlags() )
297 rStrm << GetFlagField();
298 // format run count
299 if( IsWriteFormats() )
300 rStrm << GetFormatsCount();
301 rStrm.SetSliceSize( 0 );
304 void XclExpString::WriteBuffer( XclExpStream& rStrm ) const
306 if( mbIsBiff8 )
307 rStrm.WriteUnicodeBuffer( maUniBuffer, GetFlagField() );
308 else
309 rStrm.WriteCharBuffer( maCharBuffer );
312 void XclExpString::WriteFormats( XclExpStream& rStrm, bool bWriteSize ) const
314 if( IsRich() )
316 XclFormatRunVec::const_iterator aIt = maFormats.begin(), aEnd = maFormats.end();
317 if( mbIsBiff8 )
319 if( bWriteSize )
320 rStrm << GetFormatsCount();
321 rStrm.SetSliceSize( 4 );
322 for( ; aIt != aEnd; ++aIt )
323 rStrm << aIt->mnChar << aIt->mnFontIdx;
325 else
327 if( bWriteSize )
328 rStrm << static_cast< sal_uInt8 >( GetFormatsCount() );
329 rStrm.SetSliceSize( 2 );
330 for( ; aIt != aEnd; ++aIt )
331 rStrm << static_cast< sal_uInt8 >( aIt->mnChar ) << static_cast< sal_uInt8 >( aIt->mnFontIdx );
333 rStrm.SetSliceSize( 0 );
337 void XclExpString::Write( XclExpStream& rStrm ) const
339 if (!mbSkipHeader)
340 WriteHeader( rStrm );
341 WriteBuffer( rStrm );
342 if( IsWriteFormats() ) // only in BIFF8 included in string
343 WriteFormats( rStrm );
346 void XclExpString::WriteHeaderToMem( sal_uInt8* pnMem ) const
348 assert(pnMem);
349 OSL_ENSURE( !mb8BitLen || (mnLen < 256), "XclExpString::WriteHeaderToMem - string too long" );
350 OSL_ENSURE( !IsWriteFormats(), "XclExpString::WriteHeaderToMem - formatted strings not supported" );
351 // length
352 if( mb8BitLen )
354 *pnMem = static_cast< sal_uInt8 >( mnLen );
355 ++pnMem;
357 else
359 ShortToSVBT16( mnLen, pnMem );
360 pnMem += 2;
362 // flag field
363 if( IsWriteFlags() )
364 *pnMem = GetFlagField();
367 void XclExpString::WriteBufferToMem( sal_uInt8* pnMem ) const
369 assert(pnMem);
370 if( !IsEmpty() )
372 if( mbIsBiff8 )
374 for( ScfUInt16Vec::const_iterator aIt = maUniBuffer.begin(), aEnd = maUniBuffer.end(); aIt != aEnd; ++aIt )
376 sal_uInt16 nChar = *aIt;
377 *pnMem = static_cast< sal_uInt8 >( nChar );
378 ++pnMem;
379 if( mbIsUnicode )
381 *pnMem = static_cast< sal_uInt8 >( nChar >> 8 );
382 ++pnMem;
386 else
387 memcpy( pnMem, &maCharBuffer[ 0 ], mnLen );
391 void XclExpString::WriteToMem( sal_uInt8* pnMem ) const
393 WriteHeaderToMem( pnMem );
394 WriteBufferToMem( pnMem + GetHeaderSize() );
397 static sal_uInt16 lcl_WriteRun( XclExpXmlStream& rStrm, const ScfUInt16Vec& rBuffer, sal_uInt16 nStart, sal_Int32 nLength, const XclExpFont* pFont )
399 if( nLength == 0 )
400 return nStart;
402 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
404 rWorksheet->startElement( XML_r, FSEND );
405 if( pFont )
407 const XclFontData& rFontData = pFont->GetFontData();
408 rWorksheet->startElement( XML_rPr, FSEND );
409 XclXmlUtils::WriteFontData( rWorksheet, rFontData, XML_rFont );
410 rWorksheet->endElement( XML_rPr );
412 rWorksheet->startElement( XML_t,
413 FSNS(XML_xml, XML_space), "preserve", FSEND );
414 rWorksheet->writeEscaped( XclXmlUtils::ToOUString( rBuffer, nStart, nLength ) );
415 rWorksheet->endElement( XML_t );
416 rWorksheet->endElement( XML_r );
417 return nStart + nLength;
420 void XclExpString::WriteXml( XclExpXmlStream& rStrm ) const
422 sax_fastparser::FSHelperPtr rWorksheet = rStrm.GetCurrentStream();
424 if( !IsWriteFormats() )
426 rWorksheet->startElement( XML_t,
427 FSNS(XML_xml, XML_space), "preserve", FSEND );
428 rWorksheet->writeEscaped( XclXmlUtils::ToOUString( *this ) );
429 rWorksheet->endElement( XML_t );
431 else
433 XclExpFontBuffer& rFonts = rStrm.GetRoot().GetFontBuffer();
434 XclFormatRunVec::const_iterator aIt = maFormats.begin(), aEnd = maFormats.end();
436 sal_uInt16 nStart = 0;
437 const XclExpFont* pFont = nullptr;
438 for ( ; aIt != aEnd; ++aIt )
440 nStart = lcl_WriteRun( rStrm, GetUnicodeBuffer(),
441 nStart, aIt->mnChar-nStart, pFont );
442 pFont = rFonts.GetFont( aIt->mnFontIdx );
444 lcl_WriteRun( rStrm, GetUnicodeBuffer(),
445 nStart, GetUnicodeBuffer().size() - nStart, pFont );
449 bool XclExpString::IsWriteFlags() const
451 return mbIsBiff8 && (!IsEmpty() || !mbSmartFlags);
454 bool XclExpString::IsWriteFormats() const
456 return mbIsBiff8 && !mbSkipFormats && IsRich();
459 void XclExpString::SetStrLen( sal_Int32 nNewLen )
461 sal_uInt16 nAllowedLen = (mb8BitLen && (mnMaxLen > 255)) ? 255 : mnMaxLen;
462 mnLen = limit_cast< sal_uInt16 >( nNewLen, 0, nAllowedLen );
465 void XclExpString::CharsToBuffer( const sal_Unicode* pcSource, sal_Int32 nBegin, sal_Int32 nLen )
467 OSL_ENSURE( maUniBuffer.size() >= static_cast< size_t >( nBegin + nLen ),
468 "XclExpString::CharsToBuffer - char buffer invalid" );
469 ScfUInt16Vec::iterator aBeg = maUniBuffer.begin() + nBegin;
470 ScfUInt16Vec::iterator aEnd = aBeg + nLen;
471 const sal_Unicode* pcSrcChar = pcSource;
472 for( ScfUInt16Vec::iterator aIt = aBeg; aIt != aEnd; ++aIt, ++pcSrcChar )
474 *aIt = static_cast< sal_uInt16 >( *pcSrcChar );
475 if( *aIt & 0xFF00 )
476 mbIsUnicode = true;
478 if( !mbWrapped )
479 mbWrapped = ::std::find( aBeg, aEnd, EXC_LF ) != aEnd;
482 void XclExpString::CharsToBuffer( const sal_Char* pcSource, sal_Int32 nBegin, sal_Int32 nLen )
484 OSL_ENSURE( maCharBuffer.size() >= static_cast< size_t >( nBegin + nLen ),
485 "XclExpString::CharsToBuffer - char buffer invalid" );
486 ScfUInt8Vec::iterator aBeg = maCharBuffer.begin() + nBegin;
487 ScfUInt8Vec::iterator aEnd = aBeg + nLen;
488 const sal_Char* pcSrcChar = pcSource;
489 for( ScfUInt8Vec::iterator aIt = aBeg; aIt != aEnd; ++aIt, ++pcSrcChar )
490 *aIt = static_cast< sal_uInt8 >( *pcSrcChar );
491 mbIsUnicode = false;
492 if( !mbWrapped )
493 mbWrapped = ::std::find( aBeg, aEnd, EXC_LF_C ) != aEnd;
496 void XclExpString::Init( sal_Int32 nCurrLen, XclStrFlags nFlags, sal_uInt16 nMaxLen, bool bBiff8 )
498 mbIsBiff8 = bBiff8;
499 mbIsUnicode = bBiff8 && ::get_flag( nFlags, EXC_STR_FORCEUNICODE );
500 mb8BitLen = ::get_flag( nFlags, EXC_STR_8BITLENGTH );
501 mbSmartFlags = bBiff8 && ::get_flag( nFlags, EXC_STR_SMARTFLAGS );
502 mbSkipFormats = ::get_flag( nFlags, EXC_STR_SEPARATEFORMATS );
503 mbWrapped = false;
504 mbSkipHeader = ::get_flag( nFlags, EXC_STR_NOHEADER );
505 mnMaxLen = nMaxLen;
506 SetStrLen( nCurrLen );
508 maFormats.clear();
509 if( mbIsBiff8 )
511 maCharBuffer.clear();
512 maUniBuffer.resize( mnLen );
514 else
516 maUniBuffer.clear();
517 maCharBuffer.resize( mnLen );
521 void XclExpString::Build( const sal_Unicode* pcSource, sal_Int32 nCurrLen, XclStrFlags nFlags, sal_uInt16 nMaxLen )
523 Init( nCurrLen, nFlags, nMaxLen, true );
524 CharsToBuffer( pcSource, 0, mnLen );
527 void XclExpString::Build( const sal_Char* pcSource, sal_Int32 nCurrLen, XclStrFlags nFlags, sal_uInt16 nMaxLen )
529 Init( nCurrLen, nFlags, nMaxLen, false );
530 CharsToBuffer( pcSource, 0, mnLen );
533 void XclExpString::InitAppend( sal_Int32 nAddLen )
535 SetStrLen( static_cast< sal_Int32 >( mnLen ) + nAddLen );
536 if( mbIsBiff8 )
537 maUniBuffer.resize( mnLen );
538 else
539 maCharBuffer.resize( mnLen );
542 void XclExpString::BuildAppend( const sal_Unicode* pcSource, sal_Int32 nAddLen )
544 OSL_ENSURE( mbIsBiff8, "XclExpString::BuildAppend - must not be called at byte strings" );
545 if( mbIsBiff8 )
547 sal_uInt16 nOldLen = mnLen;
548 InitAppend( nAddLen );
549 CharsToBuffer( pcSource, nOldLen, mnLen - nOldLen );
553 void XclExpString::BuildAppend( const sal_Char* pcSource, sal_Int32 nAddLen )
555 OSL_ENSURE( !mbIsBiff8, "XclExpString::BuildAppend - must not be called at unicode strings" );
556 if( !mbIsBiff8 )
558 sal_uInt16 nOldLen = mnLen;
559 InitAppend( nAddLen );
560 CharsToBuffer( pcSource, nOldLen, mnLen - nOldLen );
564 void XclExpString::PrepareWrite( XclExpStream& rStrm, sal_uInt16 nBytes ) const
566 rStrm.SetSliceSize( nBytes + (mbIsUnicode ? 2 : 1) );
569 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */