bump product version to 4.1.6.2
[LibreOffice.git] / sc / source / filter / excel / xestring.cxx
blobb1cc1af1e1578269d645049230123fc49467f97d
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 .
21 #include <algorithm>
22 #include <stdio.h>
23 #include "xlstyle.hxx"
24 #include "xestyle.hxx"
25 #include "xestream.hxx"
26 #include "xestring.hxx"
28 using namespace ::oox;
31 // ============================================================================
33 namespace {
35 // compare vectors
37 /** Compares two vectors.
38 @return A negative value, if rLeft<rRight; or a positive value, if rLeft>rRight;
39 or 0, if rLeft==rRight. */
40 template< typename Type >
41 int lclCompareVectors( const ::std::vector< Type >& rLeft, const ::std::vector< Type >& rRight )
43 int nResult = 0;
45 // 1st: compare all elements of the vectors
46 typedef typename ::std::vector< Type >::const_iterator CIT;
47 CIT aEndL = rLeft.end(), aEndR = rRight.end();
48 for( CIT aItL = rLeft.begin(), aItR = rRight.begin(); !nResult && (aItL != aEndL) && (aItR != aEndR); ++aItL, ++aItR )
49 nResult = static_cast< int >( *aItL ) - static_cast< int >( *aItR );
51 // 2nd: no differences found so far -> compare the vector sizes. Shorter vector is less
52 if( !nResult )
53 nResult = static_cast< int >( rLeft.size() ) - static_cast< int >( rRight.size() );
55 return nResult;
58 // hashing helpers
60 /** Base class for value hashers.
61 @descr These function objects are used to hash any value to a sal_uInt32 value. */
62 template< typename Type >
63 struct XclHasher : public ::std::unary_function< Type, sal_uInt32 > {};
65 template< typename Type >
66 struct XclDirectHasher : public XclHasher< Type >
68 inline sal_uInt32 operator()( Type nVal ) const { return nVal; }
71 struct XclFormatRunHasher : public XclHasher< const XclFormatRun& >
73 inline sal_uInt32 operator()( const XclFormatRun& rRun ) const
74 { return (rRun.mnChar << 8) ^ rRun.mnFontIdx; }
77 /** Calculates a hash value from a vector.
78 @descr Uses the passed hasher function object to calculate hash values from
79 all vector elements. */
80 template< typename Type, typename ValueHasher >
81 sal_uInt16 lclHashVector( const ::std::vector< Type >& rVec, const ValueHasher& rHasher )
83 sal_uInt32 nHash = rVec.size();
84 typedef typename ::std::vector< Type >::const_iterator CIT;
85 for( CIT aIt = rVec.begin(), aEnd = rVec.end(); aIt != aEnd; ++aIt )
86 (nHash *= 31) += rHasher( *aIt );
87 return static_cast< sal_uInt16 >( nHash ^ (nHash >> 16) );
90 /** Calculates a hash value from a vector. Uses XclDirectHasher to hash the vector elements. */
91 template< typename Type >
92 inline sal_uInt16 lclHashVector( const ::std::vector< Type >& rVec )
94 return lclHashVector( rVec, XclDirectHasher< Type >() );
97 } // namespace
99 // constructors ---------------------------------------------------------------
101 XclExpString::XclExpString( XclStrFlags nFlags, sal_uInt16 nMaxLen )
103 Init( 0, nFlags, nMaxLen, true );
106 XclExpString::XclExpString( const String& rString, XclStrFlags nFlags, sal_uInt16 nMaxLen )
108 Assign( rString, nFlags, nMaxLen );
111 XclExpString::XclExpString( const OUString& rString, XclStrFlags nFlags, sal_uInt16 nMaxLen )
113 Assign( rString, nFlags, nMaxLen );
116 // assign ---------------------------------------------------------------------
118 void XclExpString::Assign( const String& rString, XclStrFlags nFlags, sal_uInt16 nMaxLen )
120 Build( rString.GetBuffer(), rString.Len(), nFlags, nMaxLen );
123 void XclExpString::Assign( const OUString& rString, XclStrFlags nFlags, sal_uInt16 nMaxLen )
125 Build( rString.getStr(), rString.getLength(), nFlags, nMaxLen );
128 void XclExpString::Assign( sal_Unicode cChar, XclStrFlags nFlags, sal_uInt16 nMaxLen )
130 Build( &cChar, 1, nFlags, nMaxLen );
133 void XclExpString::AssignByte(
134 const String& rString, rtl_TextEncoding eTextEnc, XclStrFlags nFlags, sal_uInt16 nMaxLen )
136 // length may differ from length of rString
137 OString aByteStr(OUStringToOString(rString, eTextEnc));
138 Build(aByteStr.getStr(), aByteStr.getLength(), nFlags, nMaxLen);
141 // append ---------------------------------------------------------------------
143 void XclExpString::Append( const String& rString )
145 BuildAppend( rString.GetBuffer(), rString.Len() );
148 void XclExpString::AppendByte( const String& rString, rtl_TextEncoding eTextEnc )
150 if( rString.Len() > 0 )
152 // length may differ from length of rString
153 OString aByteStr(OUStringToOString(rString, eTextEnc));
154 BuildAppend(aByteStr.getStr(), aByteStr.getLength());
158 void XclExpString::AppendByte( sal_Unicode cChar, rtl_TextEncoding eTextEnc )
160 if( !cChar )
162 sal_Char cByteChar = 0;
163 BuildAppend( &cByteChar, 1 );
165 else
167 OString aByteStr( &cChar, 1, eTextEnc ); // length may be >1
168 BuildAppend( aByteStr.getStr(), aByteStr.getLength() );
172 // formatting runs ------------------------------------------------------------
174 void XclExpString::AppendFormat( sal_uInt16 nChar, sal_uInt16 nFontIdx, bool bDropDuplicate )
176 OSL_ENSURE( maFormats.empty() || (maFormats.back().mnChar < nChar), "XclExpString::AppendFormat - invalid char index" );
177 size_t nMaxSize = static_cast< size_t >( mbIsBiff8 ? EXC_STR_MAXLEN : EXC_STR_MAXLEN_8BIT );
178 if( maFormats.empty() || ((maFormats.size() < nMaxSize) && (!bDropDuplicate || (maFormats.back().mnFontIdx != nFontIdx))) )
179 maFormats.push_back( XclFormatRun( nChar, nFontIdx ) );
182 void XclExpString::AppendTrailingFormat( sal_uInt16 nFontIdx )
184 AppendFormat( mnLen, nFontIdx, false );
187 void XclExpString::LimitFormatCount( sal_uInt16 nMaxCount )
189 if( maFormats.size() > nMaxCount )
190 maFormats.erase( maFormats.begin() + nMaxCount, maFormats.end() );
193 sal_uInt16 XclExpString::RemoveLeadingFont()
195 sal_uInt16 nFontIdx = EXC_FONT_NOTFOUND;
196 if( !maFormats.empty() && (maFormats.front().mnChar == 0) )
198 nFontIdx = maFormats.front().mnFontIdx;
199 maFormats.erase( maFormats.begin() );
201 return nFontIdx;
204 bool XclExpString::IsEqual( const XclExpString& rCmp ) const
206 return
207 (mnLen == rCmp.mnLen) &&
208 (mbIsBiff8 == rCmp.mbIsBiff8) &&
209 (mbIsUnicode == rCmp.mbIsUnicode) &&
210 (mbWrapped == rCmp.mbWrapped) &&
212 ( mbIsBiff8 && (maUniBuffer == rCmp.maUniBuffer)) ||
213 (!mbIsBiff8 && (maCharBuffer == rCmp.maCharBuffer))
214 ) &&
215 (maFormats == rCmp.maFormats);
218 bool XclExpString::IsLessThan( const XclExpString& rCmp ) const
220 int nResult = mbIsBiff8 ?
221 lclCompareVectors( maUniBuffer, rCmp.maUniBuffer ) :
222 lclCompareVectors( maCharBuffer, rCmp.maCharBuffer );
223 return (nResult != 0) ? (nResult < 0) : (maFormats < rCmp.maFormats);
226 // get data -------------------------------------------------------------------
228 sal_uInt16 XclExpString::GetFormatsCount() const
230 return static_cast< sal_uInt16 >( maFormats.size() );
233 sal_uInt8 XclExpString::GetFlagField() const
235 return (mbIsUnicode ? EXC_STRF_16BIT : 0) | (IsWriteFormats() ? EXC_STRF_RICH : 0);
238 sal_uInt16 XclExpString::GetHeaderSize() const
240 return
241 (mb8BitLen ? 1 : 2) + // length field
242 (IsWriteFlags() ? 1 : 0) + // flag field
243 (IsWriteFormats() ? 2 : 0); // richtext formattting count
246 sal_Size XclExpString::GetBufferSize() const
248 return mnLen * (mbIsUnicode ? 2 : 1);
251 sal_Size XclExpString::GetSize() const
253 return
254 GetHeaderSize() + // header
255 GetBufferSize() + // character buffer
256 (IsWriteFormats() ? (4 * GetFormatsCount()) : 0); // richtext formattting
259 sal_uInt16 XclExpString::GetChar( sal_uInt16 nCharIdx ) const
261 OSL_ENSURE( nCharIdx < Len(), "XclExpString::GetChar - invalid character index" );
262 return static_cast< sal_uInt16 >( mbIsBiff8 ? maUniBuffer[ nCharIdx ] : maCharBuffer[ nCharIdx ] );
265 sal_uInt16 XclExpString::GetHash() const
267 return
268 (mbIsBiff8 ? lclHashVector( maUniBuffer ) : lclHashVector( maCharBuffer )) ^
269 lclHashVector( maFormats, XclFormatRunHasher() );
272 // streaming ------------------------------------------------------------------
274 void XclExpString::WriteLenField( XclExpStream& rStrm ) const
276 if( mb8BitLen )
277 rStrm << static_cast< sal_uInt8 >( mnLen );
278 else
279 rStrm << mnLen;
282 void XclExpString::WriteFlagField( XclExpStream& rStrm ) const
284 if( mbIsBiff8 )
286 PrepareWrite( rStrm, 1 );
287 rStrm << GetFlagField();
288 rStrm.SetSliceSize( 0 );
292 void XclExpString::WriteHeader( XclExpStream& rStrm ) const
294 OSL_ENSURE( !mb8BitLen || (mnLen < 256), "XclExpString::WriteHeader - string too long" );
295 PrepareWrite( rStrm, GetHeaderSize() );
296 // length
297 WriteLenField( rStrm );
298 // flag field
299 if( IsWriteFlags() )
300 rStrm << GetFlagField();
301 // format run count
302 if( IsWriteFormats() )
303 rStrm << GetFormatsCount();
304 rStrm.SetSliceSize( 0 );
307 void XclExpString::WriteBuffer( XclExpStream& rStrm ) const
309 if( mbIsBiff8 )
310 rStrm.WriteUnicodeBuffer( maUniBuffer, GetFlagField() );
311 else
312 rStrm.WriteCharBuffer( maCharBuffer );
315 void XclExpString::WriteFormats( XclExpStream& rStrm, bool bWriteSize ) const
317 if( IsRich() )
319 XclFormatRunVec::const_iterator aIt = maFormats.begin(), aEnd = maFormats.end();
320 if( mbIsBiff8 )
322 if( bWriteSize )
323 rStrm << GetFormatsCount();
324 rStrm.SetSliceSize( 4 );
325 for( ; aIt != aEnd; ++aIt )
326 rStrm << aIt->mnChar << aIt->mnFontIdx;
328 else
330 if( bWriteSize )
331 rStrm << static_cast< sal_uInt8 >( GetFormatsCount() );
332 rStrm.SetSliceSize( 2 );
333 for( ; aIt != aEnd; ++aIt )
334 rStrm << static_cast< sal_uInt8 >( aIt->mnChar ) << static_cast< sal_uInt8 >( aIt->mnFontIdx );
336 rStrm.SetSliceSize( 0 );
340 void XclExpString::Write( XclExpStream& rStrm ) const
342 if (!mbSkipHeader)
343 WriteHeader( rStrm );
344 WriteBuffer( rStrm );
345 if( IsWriteFormats() ) // only in BIFF8 included in string
346 WriteFormats( rStrm );
349 void XclExpString::WriteHeaderToMem( sal_uInt8* pnMem ) const
351 OSL_ENSURE( pnMem, "XclExpString::WriteHeaderToMem - no memory to write to" );
352 OSL_ENSURE( !mb8BitLen || (mnLen < 256), "XclExpString::WriteHeaderToMem - string too long" );
353 OSL_ENSURE( !IsWriteFormats(), "XclExpString::WriteHeaderToMem - formatted strings not supported" );
354 // length
355 if( mb8BitLen )
357 *pnMem = static_cast< sal_uInt8 >( mnLen );
358 ++pnMem;
360 else
362 ShortToSVBT16( mnLen, pnMem );
363 pnMem += 2;
365 // flag field
366 if( IsWriteFlags() )
367 *pnMem = GetFlagField();
370 void XclExpString::WriteBufferToMem( sal_uInt8* pnMem ) const
372 OSL_ENSURE( pnMem, "XclExpString::WriteBufferToMem - no memory to write to" );
373 if( !IsEmpty() )
375 if( mbIsBiff8 )
377 for( ScfUInt16Vec::const_iterator aIt = maUniBuffer.begin(), aEnd = maUniBuffer.end(); aIt != aEnd; ++aIt )
379 sal_uInt16 nChar = *aIt;
380 *pnMem = static_cast< sal_uInt8 >( nChar );
381 ++pnMem;
382 if( mbIsUnicode )
384 *pnMem = static_cast< sal_uInt8 >( nChar >> 8 );
385 ++pnMem;
389 else
390 memcpy( pnMem, &maCharBuffer[ 0 ], mnLen );
394 void XclExpString::WriteToMem( sal_uInt8* pnMem ) const
396 WriteHeaderToMem( pnMem );
397 WriteBufferToMem( pnMem + GetHeaderSize() );
400 static sal_uInt16 lcl_WriteRun( XclExpXmlStream& rStrm, const ScfUInt16Vec& rBuffer, sal_uInt16 nStart, sal_Int32 nLength, const XclExpFont* pFont )
402 if( nLength == 0 )
403 return nStart;
405 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
407 rWorksheet->startElement( XML_r, FSEND );
408 if( pFont )
410 const XclFontData& rFontData = pFont->GetFontData();
411 rWorksheet->startElement( XML_rPr, FSEND );
412 XclXmlUtils::WriteFontData( rWorksheet, rFontData, XML_rFont );
413 rWorksheet->endElement( XML_rPr );
415 rWorksheet->startElement( XML_t,
416 FSNS( XML_xml, XML_space ), "preserve",
417 FSEND );
418 rWorksheet->writeEscaped( XclXmlUtils::ToOUString( rBuffer, nStart, nLength ) );
419 rWorksheet->endElement( XML_t );
420 rWorksheet->endElement( XML_r );
421 return nStart + nLength;
424 void XclExpString::WriteXml( XclExpXmlStream& rStrm ) const
426 sax_fastparser::FSHelperPtr rWorksheet = rStrm.GetCurrentStream();
428 if( !IsWriteFormats() )
430 rWorksheet->startElement( XML_t, FSEND );
431 rWorksheet->writeEscaped( XclXmlUtils::ToOUString( *this ) );
432 rWorksheet->endElement( XML_t );
434 else
436 XclExpFontBuffer& rFonts = rStrm.GetRoot().GetFontBuffer();
437 XclFormatRunVec::const_iterator aIt = maFormats.begin(), aEnd = maFormats.end();
439 sal_uInt16 nStart = 0;
440 const XclExpFont* pFont = NULL;
441 for ( ; aIt != aEnd; ++aIt )
443 nStart = lcl_WriteRun( rStrm, GetUnicodeBuffer(),
444 nStart, aIt->mnChar-nStart, pFont );
445 pFont = rFonts.GetFont( aIt->mnFontIdx );
447 lcl_WriteRun( rStrm, GetUnicodeBuffer(),
448 nStart, GetUnicodeBuffer().size() - nStart, pFont );
452 // ----------------------------------------------------------------------------
454 bool XclExpString::IsWriteFlags() const
456 return mbIsBiff8 && (!IsEmpty() || !mbSmartFlags);
459 bool XclExpString::IsWriteFormats() const
461 return mbIsBiff8 && !mbSkipFormats && IsRich();
464 void XclExpString::SetStrLen( sal_Int32 nNewLen )
466 sal_uInt16 nAllowedLen = (mb8BitLen && (mnMaxLen > 255)) ? 255 : mnMaxLen;
467 mnLen = limit_cast< sal_uInt16 >( nNewLen, 0, nAllowedLen );
470 void XclExpString::CharsToBuffer( const sal_Unicode* pcSource, sal_Int32 nBegin, sal_Int32 nLen )
472 OSL_ENSURE( maUniBuffer.size() >= static_cast< size_t >( nBegin + nLen ),
473 "XclExpString::CharsToBuffer - char buffer invalid" );
474 ScfUInt16Vec::iterator aBeg = maUniBuffer.begin() + nBegin;
475 ScfUInt16Vec::iterator aEnd = aBeg + nLen;
476 const sal_Unicode* pcSrcChar = pcSource;
477 for( ScfUInt16Vec::iterator aIt = aBeg; aIt != aEnd; ++aIt, ++pcSrcChar )
479 *aIt = static_cast< sal_uInt16 >( *pcSrcChar );
480 if( *aIt & 0xFF00 )
481 mbIsUnicode = true;
483 if( !mbWrapped )
484 mbWrapped = ::std::find( aBeg, aEnd, EXC_LF ) != aEnd;
487 void XclExpString::CharsToBuffer( const sal_Char* pcSource, sal_Int32 nBegin, sal_Int32 nLen )
489 OSL_ENSURE( maCharBuffer.size() >= static_cast< size_t >( nBegin + nLen ),
490 "XclExpString::CharsToBuffer - char buffer invalid" );
491 ScfUInt8Vec::iterator aBeg = maCharBuffer.begin() + nBegin;
492 ScfUInt8Vec::iterator aEnd = aBeg + nLen;
493 const sal_Char* pcSrcChar = pcSource;
494 for( ScfUInt8Vec::iterator aIt = aBeg; aIt != aEnd; ++aIt, ++pcSrcChar )
495 *aIt = static_cast< sal_uInt8 >( *pcSrcChar );
496 mbIsUnicode = false;
497 if( !mbWrapped )
498 mbWrapped = ::std::find( aBeg, aEnd, EXC_LF_C ) != aEnd;
501 void XclExpString::Init( sal_Int32 nCurrLen, XclStrFlags nFlags, sal_uInt16 nMaxLen, bool bBiff8 )
503 mbIsBiff8 = bBiff8;
504 mbIsUnicode = bBiff8 && ::get_flag( nFlags, EXC_STR_FORCEUNICODE );
505 mb8BitLen = ::get_flag( nFlags, EXC_STR_8BITLENGTH );
506 mbSmartFlags = bBiff8 && ::get_flag( nFlags, EXC_STR_SMARTFLAGS );
507 mbSkipFormats = ::get_flag( nFlags, EXC_STR_SEPARATEFORMATS );
508 mbWrapped = false;
509 mbSkipHeader = ::get_flag( nFlags, EXC_STR_NOHEADER );
510 mnMaxLen = nMaxLen;
511 SetStrLen( nCurrLen );
513 maFormats.clear();
514 if( mbIsBiff8 )
516 maCharBuffer.clear();
517 maUniBuffer.resize( mnLen );
519 else
521 maUniBuffer.clear();
522 maCharBuffer.resize( mnLen );
526 void XclExpString::Build( const sal_Unicode* pcSource, sal_Int32 nCurrLen, XclStrFlags nFlags, sal_uInt16 nMaxLen )
528 Init( nCurrLen, nFlags, nMaxLen, true );
529 CharsToBuffer( pcSource, 0, mnLen );
532 void XclExpString::Build( const sal_Char* pcSource, sal_Int32 nCurrLen, XclStrFlags nFlags, sal_uInt16 nMaxLen )
534 Init( nCurrLen, nFlags, nMaxLen, false );
535 CharsToBuffer( pcSource, 0, mnLen );
538 void XclExpString::InitAppend( sal_Int32 nAddLen )
540 SetStrLen( static_cast< sal_Int32 >( mnLen ) + nAddLen );
541 if( mbIsBiff8 )
542 maUniBuffer.resize( mnLen );
543 else
544 maCharBuffer.resize( mnLen );
547 void XclExpString::BuildAppend( const sal_Unicode* pcSource, sal_Int32 nAddLen )
549 OSL_ENSURE( mbIsBiff8, "XclExpString::BuildAppend - must not be called at byte strings" );
550 if( mbIsBiff8 )
552 sal_uInt16 nOldLen = mnLen;
553 InitAppend( nAddLen );
554 CharsToBuffer( pcSource, nOldLen, mnLen - nOldLen );
558 void XclExpString::BuildAppend( const sal_Char* pcSource, sal_Int32 nAddLen )
560 OSL_ENSURE( !mbIsBiff8, "XclExpString::BuildAppend - must not be called at unicode strings" );
561 if( !mbIsBiff8 )
563 sal_uInt16 nOldLen = mnLen;
564 InitAppend( nAddLen );
565 CharsToBuffer( pcSource, nOldLen, mnLen - nOldLen );
569 void XclExpString::PrepareWrite( XclExpStream& rStrm, sal_uInt16 nBytes ) const
571 rStrm.SetSliceSize( nBytes + (mbIsUnicode ? 2 : 1) );
574 // ============================================================================
576 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */