LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/tools/source/string - tustring.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 241 305 79.0 %
Date: 2013-07-09 Functions: 29 34 85.3 %
Legend: Lines: hit not hit

          Line data    Source code
       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 <string.h>
      21             : 
      22             : #include "boost/static_assert.hpp"
      23             : 
      24             : #include <osl/interlck.h>
      25             : #include <rtl/alloc.h>
      26             : #include <rtl/tencinfo.h>
      27             : #include <rtl/instance.hxx>
      28             : #include <tools/string.hxx>
      29             : 
      30             : #include <impstrg.hxx>
      31             : 
      32             : #include <tools/debug.hxx>
      33             : 
      34             : DBG_NAME( UniString )
      35             : 
      36             : #define STRCODE         sal_Unicode
      37             : #define STRCODEU        sal_Unicode
      38             : #define STRING          UniString
      39             : #define STRINGDATA      UniStringData
      40             : #define STRING_TYPE     rtl_uString
      41             : #define STRING_ACQUIRE  rtl_uString_acquire
      42             : #define STRING_RELEASE  rtl_uString_release
      43             : #define STRING_NEW      rtl_uString_new
      44             : 
      45             : #if defined DBG_UTIL
      46             : #define DBGCHECKSTRING  DbgCheckUniString
      47             : #endif
      48             : 
      49             : #include <strimp.cxx>
      50             : #include <strucvt.cxx>
      51             : #include <strascii.cxx>
      52             : 
      53          10 : UniString::UniString(char c): mpData(ImplAllocData(1)) { mpData->maStr[0] = c; }
      54             : 
      55             : namespace { struct Empty : public rtl::Static< const UniString, Empty> {}; }
      56             : 
      57        1436 : const UniString& UniString::EmptyString()
      58             : {
      59        1436 :     return Empty::get();
      60             : }
      61             : 
      62       27027 : sal_Int32 UniString::ToInt32() const
      63             : {
      64             :     DBG_CHKTHIS( UniString, DbgCheckUniString );
      65             : 
      66       27027 :     return rtl_ustr_toInt32( mpData->maStr, 10 );
      67             : }
      68             : 
      69           0 : sal_Int64 UniString::ToInt64() const
      70             : {
      71             :     DBG_CHKTHIS( UniString, DbgCheckUniString );
      72             : 
      73           0 :     return rtl_ustr_toInt64( mpData->maStr, 10 );
      74             : }
      75             : 
      76       11532 : xub_StrLen STRING::SearchChar( const STRCODE* pChars, xub_StrLen nIndex ) const
      77             : {
      78             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
      79             : 
      80       11532 :     sal_Int32       nLen = mpData->mnLen;
      81       11532 :     const STRCODE*  pStr = mpData->maStr;
      82       11532 :     pStr += nIndex;
      83       63801 :     while ( nIndex < nLen )
      84             :     {
      85       40737 :         STRCODE         c = *pStr;
      86       40737 :         const STRCODE*  pCompStr = pChars;
      87      366109 :         while ( *pCompStr )
      88             :         {
      89      284635 :             if ( *pCompStr == c )
      90           0 :                 return nIndex;
      91      284635 :             ++pCompStr;
      92             :         }
      93             :         ++pStr,
      94       40737 :         ++nIndex;
      95             :     }
      96             : 
      97       11532 :     return STRING_NOTFOUND;
      98             : }
      99             : 
     100           0 : xub_StrLen STRING::SearchAndReplace( STRCODE c, STRCODE cRep, xub_StrLen nIndex )
     101             : {
     102             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     103             : 
     104           0 :     sal_Int32       nLen = mpData->mnLen;
     105           0 :     const STRCODE*  pStr = mpData->maStr;
     106           0 :     pStr += nIndex;
     107           0 :     while ( nIndex < nLen )
     108             :     {
     109           0 :         if ( *pStr == c )
     110             :         {
     111           0 :             ImplCopyData();
     112           0 :             mpData->maStr[nIndex] = cRep;
     113           0 :             return nIndex;
     114             :         }
     115             :         ++pStr,
     116           0 :         ++nIndex;
     117             :     }
     118             : 
     119           0 :     return STRING_NOTFOUND;
     120             : }
     121             : 
     122           0 : STRING& STRING::Insert( const STRING& rStr, xub_StrLen nPos, xub_StrLen nLen,
     123             :                         xub_StrLen nIndex )
     124             : {
     125             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     126             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     127             : 
     128             :     // Determine string length
     129           0 :     if ( nPos > rStr.mpData->mnLen )
     130           0 :         nLen = 0;
     131             :     else
     132             :     {
     133             :         // Correct length if necessary
     134           0 :         sal_Int32 nMaxLen = rStr.mpData->mnLen-nPos;
     135           0 :         if ( nLen > nMaxLen )
     136           0 :             nLen = static_cast< xub_StrLen >(nMaxLen);
     137             :     }
     138             : 
     139             :     // Detect overflow
     140           0 :     sal_Int32 nCopyLen = ImplGetCopyLen( mpData->mnLen, nLen );
     141             : 
     142           0 :     if ( !nCopyLen )
     143           0 :         return *this;
     144             : 
     145             :     // Correct index if necessary
     146           0 :     if ( nIndex > mpData->mnLen )
     147           0 :         nIndex = static_cast< xub_StrLen >(mpData->mnLen);
     148             : 
     149             :     // Determine new length and allocate string
     150           0 :     STRINGDATA* pNewData = ImplAllocData( mpData->mnLen+nCopyLen );
     151             : 
     152             :     // copy string to newdata
     153           0 :     memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
     154           0 :     memcpy( pNewData->maStr+nIndex, rStr.mpData->maStr+nPos, nCopyLen*sizeof( STRCODE ) );
     155           0 :     memcpy( pNewData->maStr+nIndex+nCopyLen, mpData->maStr+nIndex,
     156           0 :             (mpData->mnLen-nIndex)*sizeof( STRCODE ) );
     157             : 
     158             :     // release old data
     159           0 :     STRING_RELEASE((STRING_TYPE *)mpData);
     160           0 :     mpData = pNewData;
     161             : 
     162           0 :     return *this;
     163             : }
     164             : 
     165       75661 : static sal_Int32 ImplStringICompareWithoutZero( const STRCODE* pStr1, const STRCODE* pStr2,
     166             :                                                 sal_Int32 nCount )
     167             : {
     168       75661 :     sal_Int32   nRet = 0;
     169             :     STRCODE     c1;
     170             :     STRCODE     c2;
     171      427926 :     do
     172             :     {
     173      432550 :         if ( !nCount )
     174        4624 :             break;
     175             : 
     176             :         // convert if char is between 'A' and 'Z'
     177      427926 :         c1 = *pStr1;
     178      427926 :         c2 = *pStr2;
     179      427926 :         if ( (c1 >= 65) && (c1 <= 90) )
     180       75793 :             c1 += 32;
     181      427926 :         if ( (c2 >= 65) && (c2 <= 90) )
     182       75940 :             c2 += 32;
     183      427926 :         nRet = ((sal_Int32)((STRCODEU)c1))-((sal_Int32)((STRCODEU)c2));
     184             : 
     185             :         ++pStr1,
     186             :         ++pStr2,
     187      427926 :         --nCount;
     188             :     }
     189             :     while ( nRet == 0 );
     190             : 
     191       75661 :     return nRet;
     192             : }
     193             : 
     194          32 : sal_Bool STRING::EqualsIgnoreCaseAscii( const STRING& rStr, xub_StrLen nIndex, xub_StrLen nLen ) const
     195             : {
     196             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     197             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     198             : 
     199             :     // Are there enough codes for comparing?
     200          32 :     if ( nIndex > mpData->mnLen )
     201           0 :         return (rStr.mpData->mnLen == 0);
     202          32 :     sal_Int32 nMaxLen = mpData->mnLen-nIndex;
     203          32 :     if ( nMaxLen < nLen )
     204             :     {
     205           0 :         if ( rStr.mpData->mnLen != nMaxLen )
     206           0 :             return sal_False;
     207           0 :         nLen = static_cast< xub_StrLen >(nMaxLen);
     208             :     }
     209             : 
     210          32 :     return (ImplStringICompareWithoutZero( mpData->maStr+nIndex, rStr.mpData->maStr, nLen ) == 0);
     211             : }
     212             : 
     213       76814 : StringCompare STRING::CompareIgnoreCaseToAscii( const STRING& rStr,
     214             :                                                 xub_StrLen nLen ) const
     215             : {
     216             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     217             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     218             : 
     219       76814 :     if ( mpData == rStr.mpData )
     220        2462 :         return COMPARE_EQUAL;
     221             : 
     222             :     // determine maximal length
     223       74352 :     if ( mpData->mnLen < nLen )
     224       74352 :         nLen = static_cast< xub_StrLen >(mpData->mnLen+1);
     225       74352 :     if ( rStr.mpData->mnLen < nLen )
     226       59485 :         nLen = static_cast< xub_StrLen >(rStr.mpData->mnLen+1);
     227             : 
     228       74352 :     sal_Int32 nCompare = ImplStringICompareWithoutZero( mpData->maStr, rStr.mpData->maStr, nLen );
     229             : 
     230       74352 :     if ( nCompare == 0 )
     231        4420 :         return COMPARE_EQUAL;
     232       69932 :     else if ( nCompare < 0 )
     233       42209 :         return COMPARE_LESS;
     234             :     else
     235       27723 :         return COMPARE_GREATER;
     236             : }
     237             : 
     238        1921 : STRCODE* STRING::GetBufferAccess()
     239             : {
     240             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     241             : 
     242             :     // Copy data if necessary
     243        1921 :     if ( mpData->mnLen )
     244        1914 :         ImplCopyData();
     245             : 
     246             :     // return pointer to string data
     247        1921 :     return mpData->maStr;
     248             : }
     249             : 
     250         312 : void STRING::ReleaseBufferAccess( xub_StrLen nLen )
     251             : {
     252             :     // String not consinstent, thus no functionality test
     253             :     DBG_CHKTHIS( STRING, NULL );
     254             :     DBG_ASSERT( mpData->mnRefCount == 1, "String::ReleaseCharStr() called for String with RefCount" );
     255             : 
     256         312 :     if ( nLen > mpData->mnLen )
     257         312 :         nLen = ImplStringLen( mpData->maStr );
     258             :     OSL_ASSERT(nLen <= mpData->mnLen);
     259         312 :     if ( !nLen )
     260             :     {
     261           0 :         STRING_NEW((STRING_TYPE **)&mpData);
     262             :     }
     263             :     // shorten buffer is difference > 8 chars
     264         312 :     else if ( mpData->mnLen - nLen > 8 )
     265             :     {
     266           0 :         STRINGDATA* pNewData = ImplAllocData( nLen );
     267           0 :         memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
     268           0 :         STRING_RELEASE((STRING_TYPE *)mpData);
     269           0 :         mpData = pNewData;
     270             :     }
     271             :     else
     272         312 :         mpData->mnLen = nLen;
     273         312 : }
     274             : 
     275           0 : STRCODE* STRING::AllocBuffer( xub_StrLen nLen )
     276             : {
     277             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     278             : 
     279           0 :     STRING_RELEASE((STRING_TYPE *)mpData);
     280           0 :     if ( nLen )
     281           0 :         mpData = ImplAllocData( nLen );
     282             :     else
     283             :     {
     284           0 :         mpData = NULL;
     285           0 :         STRING_NEW((STRING_TYPE **)&mpData);
     286             :     }
     287             : 
     288           0 :     return mpData->maStr;
     289             : }
     290             : 
     291        4795 : STRING& STRING::Insert( STRCODE c, xub_StrLen nIndex )
     292             : {
     293             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     294             : 
     295             :     // Don't insert 0 char or string size is maximum
     296        4795 :     if ( !c || (mpData->mnLen == STRING_MAXLEN) )
     297           0 :         return *this;
     298             : 
     299             :     // Adjust string index
     300        4795 :     if ( nIndex > mpData->mnLen )
     301        2566 :         nIndex = static_cast< xub_StrLen >(mpData->mnLen);
     302             : 
     303             :     // allocate string of new size
     304        4795 :     STRINGDATA* pNewData = ImplAllocData( mpData->mnLen+1 );
     305             : 
     306             :     // copy string
     307        4795 :     memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
     308        4795 :     pNewData->maStr[nIndex] = c;
     309        4795 :     memcpy( pNewData->maStr+nIndex+1, mpData->maStr+nIndex,
     310        9590 :             (mpData->mnLen-nIndex)*sizeof( STRCODE ) );
     311             : 
     312             :     // free old data
     313        4795 :     STRING_RELEASE((STRING_TYPE *)mpData);
     314        4795 :     mpData = pNewData;
     315             : 
     316        4795 :     return *this;
     317             : }
     318             : 
     319        1316 : STRING& STRING::ToUpperAscii()
     320             : {
     321             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     322             : 
     323        1316 :     sal_Int32 nIndex = 0;
     324        1316 :     sal_Int32 nLen = mpData->mnLen;
     325        1316 :     STRCODE*    pStr = mpData->maStr;
     326        4092 :     while ( nIndex < nLen )
     327             :     {
     328             :         // convert char if between 'a' and 'z'
     329        1460 :         if ( (*pStr >= 97) && (*pStr <= 122) )
     330             :         {
     331             :             // allocate string of new size
     332          76 :             pStr = ImplCopyStringData( pStr );
     333          76 :             *pStr -= 32;
     334             :         }
     335             : 
     336             :         ++pStr,
     337        1460 :         ++nIndex;
     338             :     }
     339             : 
     340        1316 :     return *this;
     341             : }
     342             : 
     343       77098 : StringCompare STRING::CompareTo( const STRING& rStr, xub_StrLen nLen ) const
     344             : {
     345             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     346             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     347             : 
     348       77098 :     if ( mpData == rStr.mpData )
     349        5604 :         return COMPARE_EQUAL;
     350             : 
     351             :     // determine maximal length
     352       71494 :     if ( mpData->mnLen < nLen )
     353       70235 :         nLen = static_cast< xub_StrLen >(mpData->mnLen+1);
     354       71494 :     if ( rStr.mpData->mnLen < nLen )
     355       36179 :         nLen = static_cast< xub_StrLen >(rStr.mpData->mnLen+1);
     356             : 
     357       71494 :     sal_Int32 nCompare = ImplStringCompareWithoutZero( mpData->maStr, rStr.mpData->maStr, nLen );
     358             : 
     359       71494 :     if ( nCompare == 0 )
     360        2854 :         return COMPARE_EQUAL;
     361       68640 :     else if ( nCompare < 0 )
     362       55595 :         return COMPARE_LESS;
     363             :     else
     364       13045 :         return COMPARE_GREATER;
     365             : }
     366             : 
     367    18156388 : sal_Bool STRING::Equals( const STRING& rStr ) const
     368             : {
     369             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     370             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     371             : 
     372    18156388 :     if ( mpData == rStr.mpData )
     373     2308721 :         return sal_True;
     374             : 
     375    15847667 :     if ( mpData->mnLen != rStr.mpData->mnLen )
     376    13424132 :         return sal_False;
     377             : 
     378     2423535 :     return (ImplStringCompareWithoutZero( mpData->maStr, rStr.mpData->maStr, mpData->mnLen ) == 0);
     379             : }
     380             : 
     381        1680 : sal_Bool STRING::EqualsIgnoreCaseAscii( const STRING& rStr ) const
     382             : {
     383             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     384             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     385             : 
     386        1680 :     if ( mpData == rStr.mpData )
     387           2 :         return sal_True;
     388             : 
     389        1678 :     if ( mpData->mnLen != rStr.mpData->mnLen )
     390         401 :         return sal_False;
     391             : 
     392             :     // compare string while ignoring case
     393        1277 :     return (ImplStringICompareWithoutZero( mpData->maStr, rStr.mpData->maStr, mpData->mnLen ) == 0);
     394             : }
     395             : 
     396        1909 : sal_Bool STRING::Equals( const STRING& rStr, xub_StrLen nIndex, xub_StrLen nLen ) const
     397             : {
     398             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     399             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     400             : 
     401             :     // Are there enough codes for comparing?
     402        1909 :     if ( nIndex > mpData->mnLen )
     403           0 :         return (rStr.mpData->mnLen == 0);
     404        1909 :     sal_Int32 nMaxLen = mpData->mnLen-nIndex;
     405        1909 :     if ( nMaxLen < nLen )
     406             :     {
     407           0 :         if ( rStr.mpData->mnLen != nMaxLen )
     408           0 :             return sal_False;
     409           0 :         nLen = static_cast< xub_StrLen >(nMaxLen);
     410             :     }
     411             : 
     412        1909 :     return (ImplStringCompareWithoutZero( mpData->maStr+nIndex, rStr.mpData->maStr, nLen ) == 0);
     413             : }
     414             : 
     415           0 : sal_Bool STRING::Equals( const STRCODE* pCharStr, xub_StrLen nIndex, xub_StrLen nLen ) const
     416             : {
     417             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     418             : 
     419             :     // Are there enough codes for comparing?
     420           0 :     if ( nIndex > mpData->mnLen )
     421           0 :         return (*pCharStr == 0);
     422             : 
     423           0 :     return (ImplStringCompare( mpData->maStr+nIndex, pCharStr, nLen ) == 0);
     424             : }
     425             : 
     426       20836 : xub_StrLen STRING::Match( const STRING& rStr ) const
     427             : {
     428             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     429             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     430             : 
     431             :     // return if string is empty
     432       20836 :     if ( !mpData->mnLen )
     433          28 :         return STRING_MATCH;
     434             : 
     435             :     // Search the string for unmatching chars
     436       20808 :     const STRCODE*  pStr1 = mpData->maStr;
     437       20808 :     const STRCODE*  pStr2 = rStr.mpData->maStr;
     438       20808 :     xub_StrLen      i = 0;
     439       55094 :     while ( i < mpData->mnLen )
     440             :     {
     441             :         // Abort on the first unmatching char
     442       34286 :         if ( *pStr1 != *pStr2 )
     443       20808 :             return i;
     444             :         ++pStr1,
     445             :         ++pStr2,
     446       13478 :         ++i;
     447             :     }
     448             : 
     449           0 :     return STRING_MATCH;
     450             : }
     451             : 
     452         175 : xub_StrLen STRING::SearchBackward( STRCODE c, xub_StrLen nIndex ) const
     453             : {
     454             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     455             : 
     456         175 :     if ( nIndex > mpData->mnLen )
     457         175 :         nIndex = (xub_StrLen)mpData->mnLen;
     458             : 
     459         175 :     const STRCODE* pStr = mpData->maStr;
     460         175 :     pStr += nIndex;
     461             : 
     462        1889 :     while ( nIndex )
     463             :     {
     464        1714 :         nIndex--;
     465        1714 :         pStr--;
     466        1714 :         if ( *pStr == c )
     467         175 :             return nIndex;
     468             :     }
     469             : 
     470           0 :     return STRING_NOTFOUND;
     471             : }
     472             : 
     473        2032 : void STRING::SearchAndReplaceAll( const STRING& rStr, const STRING& rRepStr )
     474             : {
     475             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     476             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     477             :     DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING );
     478             : 
     479        2032 :     xub_StrLen nSPos = Search( rStr, 0 );
     480        4064 :     while ( nSPos != STRING_NOTFOUND )
     481             :     {
     482           0 :         Replace( nSPos, rStr.Len(), rRepStr );
     483           0 :         nSPos = nSPos + rRepStr.Len();
     484           0 :         nSPos = Search( rStr, nSPos );
     485             :     }
     486        2032 : }
     487             : 
     488           8 : void STRING::SetToken( xub_StrLen nToken, STRCODE cTok, const STRING& rStr,
     489             :                        xub_StrLen nIndex )
     490             : {
     491             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     492             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     493             : 
     494           8 :     const STRCODE*  pStr            = mpData->maStr;
     495           8 :     xub_StrLen      nLen            = (xub_StrLen)mpData->mnLen;
     496           8 :     xub_StrLen      nTok            = 0;
     497           8 :     xub_StrLen      nFirstChar      = nIndex;
     498           8 :     xub_StrLen      i               = nFirstChar;
     499             : 
     500             :     // Determine token position and length
     501           8 :     pStr += i;
     502          35 :     while ( i < nLen )
     503             :     {
     504             :         // Increase token count if match
     505          23 :         if ( *pStr == cTok )
     506             :         {
     507          14 :             ++nTok;
     508             : 
     509          14 :             if ( nTok == nToken )
     510           6 :                 nFirstChar = i+1;
     511             :             else
     512             :             {
     513           8 :                 if ( nTok > nToken )
     514           4 :                     break;
     515             :             }
     516             :         }
     517             : 
     518             :         ++pStr,
     519          19 :         ++i;
     520             :     }
     521             : 
     522           8 :     if ( nTok >= nToken )
     523           8 :         Replace( nFirstChar, i-nFirstChar, rStr );
     524           8 : }
     525             : 
     526       38390 : STRING STRING::GetToken( xub_StrLen nToken, STRCODE cTok, sal_Int32& rIndex ) const
     527             : {
     528             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     529             : 
     530       38390 :     const STRCODE*  pStr            = mpData->maStr;
     531       38390 :     xub_StrLen      nLen            = (xub_StrLen)mpData->mnLen;
     532       38390 :     xub_StrLen      nTok            = 0;
     533       38390 :     sal_Int32      nFirstChar      = rIndex;
     534       38390 :     xub_StrLen      i               = nFirstChar;
     535             : 
     536             :     // Determine token position and length
     537       38390 :     pStr += i;
     538      420632 :     while ( i < nLen )
     539             :     {
     540             :         // Increase token count if match
     541      368305 :         if ( *pStr == cTok )
     542             :         {
     543       47269 :             ++nTok;
     544             : 
     545       47269 :             if ( nTok == nToken )
     546       15905 :                 nFirstChar = i+1;
     547             :             else
     548             :             {
     549       31364 :                 if ( nTok > nToken )
     550       24453 :                     break;
     551             :             }
     552             :         }
     553             : 
     554             :         ++pStr,
     555      343852 :         ++i;
     556             :     }
     557             : 
     558       38390 :     if ( nTok >= nToken )
     559             :     {
     560       38379 :         if ( i < nLen )
     561       24453 :             rIndex = i+1;
     562             :         else
     563       13926 :             rIndex = -1;
     564       38379 :         return Copy( nFirstChar, i-nFirstChar );
     565             :     }
     566             :     else
     567             :     {
     568          11 :         rIndex = -1;
     569          11 :         return STRING();
     570             :     }
     571             : }
     572             : 
     573        4650 : STRING& STRING::Append( const STRCODE* pCharStr, xub_StrLen nCharLen )
     574             : {
     575             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     576             :     DBG_ASSERT( pCharStr, "String::Append() - pCharStr is NULL" );
     577             : 
     578        4650 :     if ( nCharLen == STRING_LEN )
     579           0 :         nCharLen = ImplStringLen( pCharStr );
     580             : 
     581             : #ifdef DBG_UTIL
     582             :     if ( DbgIsAssert() )
     583             :     {
     584             :         for ( xub_StrLen i = 0; i < nCharLen; i++ )
     585             :         {
     586             :             if ( !pCharStr[i] )
     587             :             {
     588             :                 OSL_FAIL( "String::Append() : nLen is wrong" );
     589             :             }
     590             :         }
     591             :     }
     592             : #endif
     593             : 
     594             :     // Catch overflow
     595        4650 :     sal_Int32 nLen = mpData->mnLen;
     596        4650 :     sal_Int32 nCopyLen = ImplGetCopyLen( nLen, nCharLen );
     597             : 
     598        4650 :     if ( nCopyLen )
     599             :     {
     600             :         // allocate string of new size
     601        4498 :         STRINGDATA* pNewData = ImplAllocData( nLen+nCopyLen );
     602             : 
     603             :         // copy string
     604        4498 :         memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
     605        4498 :         memcpy( pNewData->maStr+nLen, pCharStr, nCopyLen*sizeof( STRCODE ) );
     606             : 
     607             :         // free old string
     608        4498 :         STRING_RELEASE((STRING_TYPE *)mpData);
     609        4498 :         mpData = pNewData;
     610             :     }
     611             : 
     612        4650 :     return *this;
     613             : }
     614             : 
     615      100681 : STRING& STRING::Append( STRCODE c )
     616             : {
     617             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     618             : 
     619             :     // don't append null characters and keep string length < maxlen
     620      100681 :     sal_Int32 nLen = mpData->mnLen;
     621      100681 :     if ( c && (nLen < STRING_MAXLEN) )
     622             :     {
     623             :         // allocate string of new size
     624      100681 :         STRINGDATA* pNewData = ImplAllocData( nLen+1 );
     625             : 
     626             :         // copy string
     627      100681 :         memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
     628      100681 :         pNewData->maStr[nLen] = c;
     629             : 
     630             :         // free old string
     631      100681 :         STRING_RELEASE((STRING_TYPE *)mpData);
     632      100681 :         mpData = pNewData;
     633             :     }
     634             : 
     635      100681 :     return *this;
     636             : }
     637             : 
     638         108 : STRING& STRING::Assign( STRCODE c )
     639             : {
     640             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     641             :     DBG_ASSERT( c, "String::Assign() - c is 0" );
     642             : 
     643             :     // initialize maintenance data
     644         108 :     STRING_RELEASE((STRING_TYPE *)mpData);
     645         108 :     mpData = ImplAllocData( 1 );
     646         108 :     mpData->maStr[0] = c;
     647         108 :     return *this;
     648             : }
     649             : 
     650        7088 : xub_StrLen STRING::SearchAndReplace( const STRING& rStr, const STRING& rRepStr,
     651             :                                      xub_StrLen nIndex )
     652             : {
     653             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     654             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     655             :     DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING );
     656             : 
     657        7088 :     xub_StrLen nSPos = Search( rStr, nIndex );
     658        7088 :     if ( nSPos != STRING_NOTFOUND )
     659        6932 :         Replace( nSPos, rStr.Len(), rRepStr );
     660             : 
     661        7088 :     return nSPos;
     662             : }
     663             : 
     664         418 : static sal_Int32 ImplStringICompare( const STRCODE* pStr1, const STRCODE* pStr2 )
     665             : {
     666             :     sal_Int32   nRet;
     667             :     STRCODE     c1;
     668             :     STRCODE     c2;
     669         266 :     do
     670             :     {
     671             :         // Convert char if between 'A' and 'Z'
     672         418 :         c1 = *pStr1;
     673         418 :         c2 = *pStr2;
     674         418 :         if ( (c1 >= 65) && (c1 <= 90) )
     675         190 :             c1 += 32;
     676         418 :         if ( (c2 >= 65) && (c2 <= 90) )
     677         190 :             c2 += 32;
     678         418 :         nRet = ((sal_Int32)((STRCODEU)c1))-((sal_Int32)((STRCODEU)c2));
     679         418 :         if ( nRet != 0 )
     680         152 :             break;
     681             : 
     682             :         ++pStr1,
     683         266 :         ++pStr2;
     684             :     }
     685             :     while ( c2 );
     686             : 
     687         190 :     return nRet;
     688             : }
     689             : 
     690         190 : sal_Bool STRING::EqualsIgnoreCaseAscii( const STRCODE* pCharStr ) const
     691             : {
     692             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     693             : 
     694         190 :     return (ImplStringICompare( mpData->maStr, pCharStr ) == 0);
     695             : }
     696             : 
     697       77801 : STRING& STRING::Assign( const STRCODE* pCharStr )
     698             : {
     699             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     700             :     DBG_ASSERT( pCharStr, "String::Assign() - pCharStr is NULL" );
     701             : 
     702       77801 :     xub_StrLen nLen = ImplStringLen( pCharStr );
     703             : 
     704       77801 :     if ( !nLen )
     705             :     {
     706       36610 :         STRING_NEW((STRING_TYPE **)&mpData);
     707             :     }
     708             :     else
     709             :     {
     710             :         // copy without allocation if string length is identical
     711       41191 :         if ( (nLen == mpData->mnLen) && (mpData->mnRefCount == 1) )
     712          20 :             memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
     713             :         else
     714             :         {
     715             :             // free old string
     716       41171 :             STRING_RELEASE((STRING_TYPE *)mpData);
     717             : 
     718             :             // allocate string of new size and copy
     719       41171 :             mpData = ImplAllocData( nLen );
     720       41171 :             memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
     721             :         }
     722             :     }
     723             : 
     724       77801 :     return *this;
     725             : }
     726             : 
     727     4006082 : xub_StrLen ImplStringLen( const sal_Char* pStr )
     728             : {
     729     4006082 :     const sal_Char* pTempStr = pStr;
     730    28548294 :     while( *pTempStr )
     731    20536130 :         ++pTempStr;
     732     4006082 :     return (xub_StrLen)(pTempStr-pStr);
     733             : }
     734             : 
     735       87305 : xub_StrLen ImplStringLen( const sal_Unicode* pStr )
     736             : {
     737       87305 :     const sal_Unicode* pTempStr = pStr;
     738      943021 :     while( *pTempStr )
     739      768411 :         ++pTempStr;
     740       87305 :     return (xub_StrLen)(pTempStr-pStr);
     741             : }
     742             : 
     743             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10