LCOV - code coverage report
Current view: top level - libreoffice/tools/source/string - tustring.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 239 320 74.7 %
Date: 2012-12-17 Functions: 29 36 80.6 %
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 DBGCHECKSTRING  DbgCheckUniString
      41             : #define STRING_TYPE     rtl_uString
      42             : #define STRING_ACQUIRE  rtl_uString_acquire
      43             : #define STRING_RELEASE  rtl_uString_release
      44             : #define STRING_NEW      rtl_uString_new
      45             : 
      46             : #include <strimp.cxx>
      47             : #include <strucvt.cxx>
      48             : #include <strascii.cxx>
      49             : 
      50           0 : UniString::UniString(char c): mpData(ImplAllocData(1)) { mpData->maStr[0] = c; }
      51             : 
      52       42291 : UniString UniString::CreateFromInt32( sal_Int32 n, sal_Int16 nRadix )
      53             : {
      54       42291 :     return rtl::OUString::valueOf(n, nRadix);
      55             : }
      56             : 
      57             : namespace { struct Empty : public rtl::Static< const UniString, Empty> {}; }
      58             : 
      59         376 : const UniString& UniString::EmptyString()
      60             : {
      61         376 :     return Empty::get();
      62             : }
      63             : 
      64        6686 : sal_Int32 UniString::ToInt32() const
      65             : {
      66             :     DBG_CHKTHIS( UniString, DbgCheckUniString );
      67             : 
      68        6686 :     return rtl_ustr_toInt32( mpData->maStr, 10 );
      69             : }
      70             : 
      71           0 : sal_Int64 UniString::ToInt64() const
      72             : {
      73             :     DBG_CHKTHIS( UniString, DbgCheckUniString );
      74             : 
      75           0 :     return rtl_ustr_toInt64( mpData->maStr, 10 );
      76             : }
      77             : 
      78         469 : xub_StrLen STRING::SearchChar( const STRCODE* pChars, xub_StrLen nIndex ) const
      79             : {
      80             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
      81             : 
      82         469 :     sal_Int32       nLen = mpData->mnLen;
      83         469 :     const STRCODE*  pStr = mpData->maStr;
      84         469 :     pStr += nIndex;
      85        5662 :     while ( nIndex < nLen )
      86             :     {
      87        4762 :         STRCODE         c = *pStr;
      88        4762 :         const STRCODE*  pCompStr = pChars;
      89       23598 :         while ( *pCompStr )
      90             :         {
      91       14112 :             if ( *pCompStr == c )
      92          38 :                 return nIndex;
      93       14074 :             ++pCompStr;
      94             :         }
      95             :         ++pStr,
      96        4724 :         ++nIndex;
      97             :     }
      98             : 
      99         431 :     return STRING_NOTFOUND;
     100             : }
     101             : 
     102           0 : xub_StrLen STRING::SearchAndReplace( STRCODE c, STRCODE cRep, xub_StrLen nIndex )
     103             : {
     104             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     105             : 
     106           0 :     sal_Int32       nLen = mpData->mnLen;
     107           0 :     const STRCODE*  pStr = mpData->maStr;
     108           0 :     pStr += nIndex;
     109           0 :     while ( nIndex < nLen )
     110             :     {
     111           0 :         if ( *pStr == c )
     112             :         {
     113           0 :             ImplCopyData();
     114           0 :             mpData->maStr[nIndex] = cRep;
     115           0 :             return nIndex;
     116             :         }
     117             :         ++pStr,
     118           0 :         ++nIndex;
     119             :     }
     120             : 
     121           0 :     return STRING_NOTFOUND;
     122             : }
     123             : 
     124         522 : STRING& STRING::Insert( const STRING& rStr, xub_StrLen nPos, xub_StrLen nLen,
     125             :                         xub_StrLen nIndex )
     126             : {
     127             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     128             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     129             : 
     130             :     // Determine string length
     131         522 :     if ( nPos > rStr.mpData->mnLen )
     132           0 :         nLen = 0;
     133             :     else
     134             :     {
     135             :         // Correct length if necessary
     136         522 :         sal_Int32 nMaxLen = rStr.mpData->mnLen-nPos;
     137         522 :         if ( nLen > nMaxLen )
     138           0 :             nLen = static_cast< xub_StrLen >(nMaxLen);
     139             :     }
     140             : 
     141             :     // Detect overflow
     142         522 :     sal_Int32 nCopyLen = ImplGetCopyLen( mpData->mnLen, nLen );
     143             : 
     144         522 :     if ( !nCopyLen )
     145           0 :         return *this;
     146             : 
     147             :     // Correct index if necessary
     148         522 :     if ( nIndex > mpData->mnLen )
     149           0 :         nIndex = static_cast< xub_StrLen >(mpData->mnLen);
     150             : 
     151             :     // Determine new length and allocate string
     152         522 :     STRINGDATA* pNewData = ImplAllocData( mpData->mnLen+nCopyLen );
     153             : 
     154             :     // copy string to newdata
     155         522 :     memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
     156         522 :     memcpy( pNewData->maStr+nIndex, rStr.mpData->maStr+nPos, nCopyLen*sizeof( STRCODE ) );
     157         522 :     memcpy( pNewData->maStr+nIndex+nCopyLen, mpData->maStr+nIndex,
     158        1044 :             (mpData->mnLen-nIndex)*sizeof( STRCODE ) );
     159             : 
     160             :     // release old data
     161         522 :     STRING_RELEASE((STRING_TYPE *)mpData);
     162         522 :     mpData = pNewData;
     163             : 
     164         522 :     return *this;
     165             : }
     166             : 
     167      326235 : static sal_Int32 ImplStringICompareWithoutZero( const STRCODE* pStr1, const STRCODE* pStr2,
     168             :                                                 sal_Int32 nCount )
     169             : {
     170      326235 :     sal_Int32   nRet = 0;
     171             :     STRCODE     c1;
     172             :     STRCODE     c2;
     173      617916 :     do
     174             :     {
     175      625930 :         if ( !nCount )
     176        8014 :             break;
     177             : 
     178             :         // convert if char is between 'A' and 'Z'
     179      617916 :         c1 = *pStr1;
     180      617916 :         c2 = *pStr2;
     181      617916 :         if ( (c1 >= 65) && (c1 <= 90) )
     182      138362 :             c1 += 32;
     183      617916 :         if ( (c2 >= 65) && (c2 <= 90) )
     184      305306 :             c2 += 32;
     185      617916 :         nRet = ((sal_Int32)((STRCODEU)c1))-((sal_Int32)((STRCODEU)c2));
     186             : 
     187             :         ++pStr1,
     188             :         ++pStr2,
     189      617916 :         --nCount;
     190             :     }
     191             :     while ( nRet == 0 );
     192             : 
     193      326235 :     return nRet;
     194             : }
     195             : 
     196          64 : sal_Bool STRING::EqualsIgnoreCaseAscii( const STRING& rStr, xub_StrLen nIndex, xub_StrLen nLen ) const
     197             : {
     198             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     199             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     200             : 
     201             :     // Are there enough codes for comparing?
     202          64 :     if ( nIndex > mpData->mnLen )
     203           0 :         return (rStr.mpData->mnLen == 0);
     204          64 :     sal_Int32 nMaxLen = mpData->mnLen-nIndex;
     205          64 :     if ( nMaxLen < nLen )
     206             :     {
     207           0 :         if ( rStr.mpData->mnLen != nMaxLen )
     208           0 :             return sal_False;
     209           0 :         nLen = static_cast< xub_StrLen >(nMaxLen);
     210             :     }
     211             : 
     212          64 :     return (ImplStringICompareWithoutZero( mpData->maStr+nIndex, rStr.mpData->maStr, nLen ) == 0);
     213             : }
     214             : 
     215      224000 : StringCompare STRING::CompareIgnoreCaseToAscii( const STRING& rStr,
     216             :                                                 xub_StrLen nLen ) const
     217             : {
     218             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     219             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     220             : 
     221      224000 :     if ( mpData == rStr.mpData )
     222        2489 :         return COMPARE_EQUAL;
     223             : 
     224             :     // determine maximal length
     225      221511 :     if ( mpData->mnLen < nLen )
     226      221511 :         nLen = static_cast< xub_StrLen >(mpData->mnLen+1);
     227      221511 :     if ( rStr.mpData->mnLen < nLen )
     228      131636 :         nLen = static_cast< xub_StrLen >(rStr.mpData->mnLen+1);
     229             : 
     230      221511 :     sal_Int32 nCompare = ImplStringICompareWithoutZero( mpData->maStr, rStr.mpData->maStr, nLen );
     231             : 
     232      221511 :     if ( nCompare == 0 )
     233        3068 :         return COMPARE_EQUAL;
     234      218443 :     else if ( nCompare < 0 )
     235       98931 :         return COMPARE_LESS;
     236             :     else
     237      119512 :         return COMPARE_GREATER;
     238             : }
     239             : 
     240           0 : STRING& STRING::Fill( xub_StrLen nCount, STRCODE cFillChar )
     241             : {
     242             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     243             : 
     244           0 :     if ( !nCount )
     245           0 :         return *this;
     246             : 
     247             :     // extend string if fill length is larger
     248           0 :     if ( nCount > mpData->mnLen )
     249             :     {
     250             :         // allocate string of new length
     251           0 :         STRINGDATA* pNewData = ImplAllocData( nCount );
     252           0 :         STRING_RELEASE((STRING_TYPE *)mpData);
     253           0 :         mpData = pNewData;
     254             :     }
     255             :     else
     256           0 :         ImplCopyData();
     257             : 
     258           0 :     STRCODE* pStr = mpData->maStr;
     259           0 :     do
     260             :     {
     261           0 :         *pStr = cFillChar;
     262             :         ++pStr,
     263           0 :         --nCount;
     264             :     }
     265             :     while ( nCount );
     266             : 
     267           0 :     return *this;
     268             : }
     269             : 
     270         910 : STRCODE* STRING::GetBufferAccess()
     271             : {
     272             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     273             : 
     274             :     // Copy data if necessary
     275         910 :     if ( mpData->mnLen )
     276         910 :         ImplCopyData();
     277             : 
     278             :     // return pointer to string data
     279         910 :     return mpData->maStr;
     280             : }
     281             : 
     282         430 : void STRING::ReleaseBufferAccess( xub_StrLen nLen )
     283             : {
     284             :     // String not consinstent, thus no functionality test
     285             :     DBG_CHKTHIS( STRING, NULL );
     286             :     DBG_ASSERT( mpData->mnRefCount == 1, "String::ReleaseCharStr() called for String with RefCount" );
     287             : 
     288         430 :     if ( nLen > mpData->mnLen )
     289         430 :         nLen = ImplStringLen( mpData->maStr );
     290             :     OSL_ASSERT(nLen <= mpData->mnLen);
     291         430 :     if ( !nLen )
     292             :     {
     293           0 :         STRING_NEW((STRING_TYPE **)&mpData);
     294             :     }
     295             :     // shorten buffer is difference > 8 chars
     296         430 :     else if ( mpData->mnLen - nLen > 8 )
     297             :     {
     298           0 :         STRINGDATA* pNewData = ImplAllocData( nLen );
     299           0 :         memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
     300           0 :         STRING_RELEASE((STRING_TYPE *)mpData);
     301           0 :         mpData = pNewData;
     302             :     }
     303             :     else
     304         430 :         mpData->mnLen = nLen;
     305         430 : }
     306             : 
     307           0 : STRCODE* STRING::AllocBuffer( xub_StrLen nLen )
     308             : {
     309             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     310             : 
     311           0 :     STRING_RELEASE((STRING_TYPE *)mpData);
     312           0 :     if ( nLen )
     313           0 :         mpData = ImplAllocData( nLen );
     314             :     else
     315             :     {
     316           0 :         mpData = NULL;
     317           0 :         STRING_NEW((STRING_TYPE **)&mpData);
     318             :     }
     319             : 
     320           0 :     return mpData->maStr;
     321             : }
     322             : 
     323        2475 : STRING& STRING::Insert( STRCODE c, xub_StrLen nIndex )
     324             : {
     325             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     326             : 
     327             :     // Don't insert 0 char or string size is maximum
     328        2475 :     if ( !c || (mpData->mnLen == STRING_MAXLEN) )
     329           0 :         return *this;
     330             : 
     331             :     // Adjust string index
     332        2475 :     if ( nIndex > mpData->mnLen )
     333         231 :         nIndex = static_cast< xub_StrLen >(mpData->mnLen);
     334             : 
     335             :     // allocate string of new size
     336        2475 :     STRINGDATA* pNewData = ImplAllocData( mpData->mnLen+1 );
     337             : 
     338             :     // copy string
     339        2475 :     memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
     340        2475 :     pNewData->maStr[nIndex] = c;
     341        2475 :     memcpy( pNewData->maStr+nIndex+1, mpData->maStr+nIndex,
     342        4950 :             (mpData->mnLen-nIndex)*sizeof( STRCODE ) );
     343             : 
     344             :     // free old data
     345        2475 :     STRING_RELEASE((STRING_TYPE *)mpData);
     346        2475 :     mpData = pNewData;
     347             : 
     348        2475 :     return *this;
     349             : }
     350             : 
     351        2838 : STRING& STRING::ToUpperAscii()
     352             : {
     353             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     354             : 
     355        2838 :     sal_Int32 nIndex = 0;
     356        2838 :     sal_Int32 nLen = mpData->mnLen;
     357        2838 :     STRCODE*    pStr = mpData->maStr;
     358       10834 :     while ( nIndex < nLen )
     359             :     {
     360             :         // convert char if between 'a' and 'z'
     361        5158 :         if ( (*pStr >= 97) && (*pStr <= 122) )
     362             :         {
     363             :             // allocate string of new size
     364         504 :             pStr = ImplCopyStringData( pStr );
     365         504 :             *pStr -= 32;
     366             :         }
     367             : 
     368             :         ++pStr,
     369        5158 :         ++nIndex;
     370             :     }
     371             : 
     372        2838 :     return *this;
     373             : }
     374             : 
     375      375856 : StringCompare STRING::CompareTo( const STRING& rStr, xub_StrLen nLen ) const
     376             : {
     377             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     378             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     379             : 
     380      375856 :     if ( mpData == rStr.mpData )
     381        6412 :         return COMPARE_EQUAL;
     382             : 
     383             :     // determine maximal length
     384      369444 :     if ( mpData->mnLen < nLen )
     385      344512 :         nLen = static_cast< xub_StrLen >(mpData->mnLen+1);
     386      369444 :     if ( rStr.mpData->mnLen < nLen )
     387      192430 :         nLen = static_cast< xub_StrLen >(rStr.mpData->mnLen+1);
     388             : 
     389      369444 :     sal_Int32 nCompare = ImplStringCompareWithoutZero( mpData->maStr, rStr.mpData->maStr, nLen );
     390             : 
     391      369444 :     if ( nCompare == 0 )
     392       45414 :         return COMPARE_EQUAL;
     393      324030 :     else if ( nCompare < 0 )
     394      225880 :         return COMPARE_LESS;
     395             :     else
     396       98150 :         return COMPARE_GREATER;
     397             : }
     398             : 
     399     7455427 : sal_Bool STRING::Equals( const STRING& rStr ) const
     400             : {
     401             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     402             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     403             : 
     404     7455427 :     if ( mpData == rStr.mpData )
     405     1709223 :         return sal_True;
     406             : 
     407     5746204 :     if ( mpData->mnLen != rStr.mpData->mnLen )
     408     5038510 :         return sal_False;
     409             : 
     410      707694 :     return (ImplStringCompareWithoutZero( mpData->maStr, rStr.mpData->maStr, mpData->mnLen ) == 0);
     411             : }
     412             : 
     413      111710 : sal_Bool STRING::EqualsIgnoreCaseAscii( const STRING& rStr ) const
     414             : {
     415             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     416             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     417             : 
     418      111710 :     if ( mpData == rStr.mpData )
     419           0 :         return sal_True;
     420             : 
     421      111710 :     if ( mpData->mnLen != rStr.mpData->mnLen )
     422        7050 :         return sal_False;
     423             : 
     424             :     // compare string while ignoring case
     425      104660 :     return (ImplStringICompareWithoutZero( mpData->maStr, rStr.mpData->maStr, mpData->mnLen ) == 0);
     426             : }
     427             : 
     428       11916 : sal_Bool STRING::Equals( const STRING& rStr, xub_StrLen nIndex, xub_StrLen nLen ) const
     429             : {
     430             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     431             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     432             : 
     433             :     // Are there enough codes for comparing?
     434       11916 :     if ( nIndex > mpData->mnLen )
     435           0 :         return (rStr.mpData->mnLen == 0);
     436       11916 :     sal_Int32 nMaxLen = mpData->mnLen-nIndex;
     437       11916 :     if ( nMaxLen < nLen )
     438             :     {
     439           0 :         if ( rStr.mpData->mnLen != nMaxLen )
     440           0 :             return sal_False;
     441           0 :         nLen = static_cast< xub_StrLen >(nMaxLen);
     442             :     }
     443             : 
     444       11916 :     return (ImplStringCompareWithoutZero( mpData->maStr+nIndex, rStr.mpData->maStr, nLen ) == 0);
     445             : }
     446             : 
     447           0 : sal_Bool STRING::Equals( const STRCODE* pCharStr, xub_StrLen nIndex, xub_StrLen nLen ) const
     448             : {
     449             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     450             : 
     451             :     // Are there enough codes for comparing?
     452           0 :     if ( nIndex > mpData->mnLen )
     453           0 :         return (*pCharStr == 0);
     454             : 
     455           0 :     return (ImplStringCompare( mpData->maStr+nIndex, pCharStr, nLen ) == 0);
     456             : }
     457             : 
     458       28074 : xub_StrLen STRING::Match( const STRING& rStr ) const
     459             : {
     460             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     461             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     462             : 
     463             :     // return if string is empty
     464       28074 :     if ( !mpData->mnLen )
     465          48 :         return STRING_MATCH;
     466             : 
     467             :     // Search the string for unmatching chars
     468       28026 :     const STRCODE*  pStr1 = mpData->maStr;
     469       28026 :     const STRCODE*  pStr2 = rStr.mpData->maStr;
     470       28026 :     xub_StrLen      i = 0;
     471       59896 :     while ( i < mpData->mnLen )
     472             :     {
     473             :         // Abort on the first unmatching char
     474       31870 :         if ( *pStr1 != *pStr2 )
     475       28026 :             return i;
     476             :         ++pStr1,
     477             :         ++pStr2,
     478        3844 :         ++i;
     479             :     }
     480             : 
     481           0 :     return STRING_MATCH;
     482             : }
     483             : 
     484          54 : xub_StrLen STRING::SearchBackward( STRCODE c, xub_StrLen nIndex ) const
     485             : {
     486             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     487             : 
     488          54 :     if ( nIndex > mpData->mnLen )
     489          54 :         nIndex = (xub_StrLen)mpData->mnLen;
     490             : 
     491          54 :     const STRCODE* pStr = mpData->maStr;
     492          54 :     pStr += nIndex;
     493             : 
     494         607 :     while ( nIndex )
     495             :     {
     496         553 :         nIndex--;
     497         553 :         pStr--;
     498         553 :         if ( *pStr == c )
     499          54 :             return nIndex;
     500             :     }
     501             : 
     502           0 :     return STRING_NOTFOUND;
     503             : }
     504             : 
     505        4068 : void STRING::SearchAndReplaceAll( const STRING& rStr, const STRING& rRepStr )
     506             : {
     507             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     508             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     509             :     DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING );
     510             : 
     511        4068 :     xub_StrLen nSPos = Search( rStr, 0 );
     512        8136 :     while ( nSPos != STRING_NOTFOUND )
     513             :     {
     514           0 :         Replace( nSPos, rStr.Len(), rRepStr );
     515           0 :         nSPos = nSPos + rRepStr.Len();
     516           0 :         nSPos = Search( rStr, nSPos );
     517             :     }
     518        4068 : }
     519             : 
     520           0 : void STRING::SetToken( xub_StrLen nToken, STRCODE cTok, const STRING& rStr,
     521             :                        xub_StrLen nIndex )
     522             : {
     523             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     524             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     525             : 
     526           0 :     const STRCODE*  pStr            = mpData->maStr;
     527           0 :     xub_StrLen      nLen            = (xub_StrLen)mpData->mnLen;
     528           0 :     xub_StrLen      nTok            = 0;
     529           0 :     xub_StrLen      nFirstChar      = nIndex;
     530           0 :     xub_StrLen      i               = nFirstChar;
     531             : 
     532             :     // Determine token position and length
     533           0 :     pStr += i;
     534           0 :     while ( i < nLen )
     535             :     {
     536             :         // Increase token count if match
     537           0 :         if ( *pStr == cTok )
     538             :         {
     539           0 :             ++nTok;
     540             : 
     541           0 :             if ( nTok == nToken )
     542           0 :                 nFirstChar = i+1;
     543             :             else
     544             :             {
     545           0 :                 if ( nTok > nToken )
     546           0 :                     break;
     547             :             }
     548             :         }
     549             : 
     550             :         ++pStr,
     551           0 :         ++i;
     552             :     }
     553             : 
     554           0 :     if ( nTok >= nToken )
     555           0 :         Replace( nFirstChar, i-nFirstChar, rStr );
     556           0 : }
     557             : 
     558        7800 : STRING STRING::GetToken( xub_StrLen nToken, STRCODE cTok, xub_StrLen& rIndex ) const
     559             : {
     560             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     561             : 
     562        7800 :     const STRCODE*  pStr            = mpData->maStr;
     563        7800 :     xub_StrLen      nLen            = (xub_StrLen)mpData->mnLen;
     564        7800 :     xub_StrLen      nTok            = 0;
     565        7800 :     xub_StrLen      nFirstChar      = rIndex;
     566        7800 :     xub_StrLen      i               = nFirstChar;
     567             : 
     568             :     // Determine token position and length
     569        7800 :     pStr += i;
     570      111920 :     while ( i < nLen )
     571             :     {
     572             :         // Increase token count if match
     573       98666 :         if ( *pStr == cTok )
     574             :         {
     575        6594 :             ++nTok;
     576             : 
     577        6594 :             if ( nTok == nToken )
     578        2162 :                 nFirstChar = i+1;
     579             :             else
     580             :             {
     581        4432 :                 if ( nTok > nToken )
     582        2346 :                     break;
     583             :             }
     584             :         }
     585             : 
     586             :         ++pStr,
     587       96320 :         ++i;
     588             :     }
     589             : 
     590        7800 :     if ( nTok >= nToken )
     591             :     {
     592        5894 :         if ( i < nLen )
     593        2346 :             rIndex = i+1;
     594             :         else
     595        3548 :             rIndex = STRING_NOTFOUND;
     596        5894 :         return Copy( nFirstChar, i-nFirstChar );
     597             :     }
     598             :     else
     599             :     {
     600        1906 :         rIndex = STRING_NOTFOUND;
     601        1906 :         return STRING();
     602             :     }
     603             : }
     604             : 
     605        5350 : STRING& STRING::Append( const STRCODE* pCharStr, xub_StrLen nCharLen )
     606             : {
     607             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     608             :     DBG_ASSERT( pCharStr, "String::Append() - pCharStr is NULL" );
     609             : 
     610        5350 :     if ( nCharLen == STRING_LEN )
     611           0 :         nCharLen = ImplStringLen( pCharStr );
     612             : 
     613             : #ifdef DBG_UTIL
     614             :     if ( DbgIsAssert() )
     615             :     {
     616             :         for ( xub_StrLen i = 0; i < nCharLen; i++ )
     617             :         {
     618             :             if ( !pCharStr[i] )
     619             :             {
     620             :                 OSL_FAIL( "String::Append() : nLen is wrong" );
     621             :             }
     622             :         }
     623             :     }
     624             : #endif
     625             : 
     626             :     // Catch overflow
     627        5350 :     sal_Int32 nLen = mpData->mnLen;
     628        5350 :     sal_Int32 nCopyLen = ImplGetCopyLen( nLen, nCharLen );
     629             : 
     630        5350 :     if ( nCopyLen )
     631             :     {
     632             :         // allocate string of new size
     633        5034 :         STRINGDATA* pNewData = ImplAllocData( nLen+nCopyLen );
     634             : 
     635             :         // copy string
     636        5034 :         memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
     637        5034 :         memcpy( pNewData->maStr+nLen, pCharStr, nCopyLen*sizeof( STRCODE ) );
     638             : 
     639             :         // free old string
     640        5034 :         STRING_RELEASE((STRING_TYPE *)mpData);
     641        5034 :         mpData = pNewData;
     642             :     }
     643             : 
     644        5350 :     return *this;
     645             : }
     646             : 
     647       52806 : STRING& STRING::Append( STRCODE c )
     648             : {
     649             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     650             : 
     651             :     // don't append null characters and keep string length < maxlen
     652       52806 :     sal_Int32 nLen = mpData->mnLen;
     653       52806 :     if ( c && (nLen < STRING_MAXLEN) )
     654             :     {
     655             :         // allocate string of new size
     656       52806 :         STRINGDATA* pNewData = ImplAllocData( nLen+1 );
     657             : 
     658             :         // copy string
     659       52806 :         memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
     660       52806 :         pNewData->maStr[nLen] = c;
     661             : 
     662             :         // free old string
     663       52806 :         STRING_RELEASE((STRING_TYPE *)mpData);
     664       52806 :         mpData = pNewData;
     665             :     }
     666             : 
     667       52806 :     return *this;
     668             : }
     669             : 
     670         196 : STRING& STRING::Assign( STRCODE c )
     671             : {
     672             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     673             :     DBG_ASSERT( c, "String::Assign() - c is 0" );
     674             : 
     675             :     // initialize maintenance data
     676         196 :     STRING_RELEASE((STRING_TYPE *)mpData);
     677         196 :     mpData = ImplAllocData( 1 );
     678         196 :     mpData->maStr[0] = c;
     679         196 :     return *this;
     680             : }
     681             : 
     682        2696 : xub_StrLen STRING::SearchAndReplace( const STRING& rStr, const STRING& rRepStr,
     683             :                                      xub_StrLen nIndex )
     684             : {
     685             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     686             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     687             :     DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING );
     688             : 
     689        2696 :     xub_StrLen nSPos = Search( rStr, nIndex );
     690        2696 :     if ( nSPos != STRING_NOTFOUND )
     691        2670 :         Replace( nSPos, rStr.Len(), rRepStr );
     692             : 
     693        2696 :     return nSPos;
     694             : }
     695             : 
     696          22 : static sal_Int32 ImplStringICompare( const STRCODE* pStr1, const STRCODE* pStr2 )
     697             : {
     698             :     sal_Int32   nRet;
     699             :     STRCODE     c1;
     700             :     STRCODE     c2;
     701          14 :     do
     702             :     {
     703             :         // Convert char if between 'A' and 'Z'
     704          22 :         c1 = *pStr1;
     705          22 :         c2 = *pStr2;
     706          22 :         if ( (c1 >= 65) && (c1 <= 90) )
     707          10 :             c1 += 32;
     708          22 :         if ( (c2 >= 65) && (c2 <= 90) )
     709          10 :             c2 += 32;
     710          22 :         nRet = ((sal_Int32)((STRCODEU)c1))-((sal_Int32)((STRCODEU)c2));
     711          22 :         if ( nRet != 0 )
     712           8 :             break;
     713             : 
     714             :         ++pStr1,
     715          14 :         ++pStr2;
     716             :     }
     717             :     while ( c2 );
     718             : 
     719          10 :     return nRet;
     720             : }
     721             : 
     722          10 : sal_Bool STRING::EqualsIgnoreCaseAscii( const STRCODE* pCharStr ) const
     723             : {
     724             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     725             : 
     726          10 :     return (ImplStringICompare( mpData->maStr, pCharStr ) == 0);
     727             : }
     728             : 
     729       16790 : STRING& STRING::Assign( const STRCODE* pCharStr )
     730             : {
     731             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     732             :     DBG_ASSERT( pCharStr, "String::Assign() - pCharStr is NULL" );
     733             : 
     734       16790 :     xub_StrLen nLen = ImplStringLen( pCharStr );
     735             : 
     736       16790 :     if ( !nLen )
     737             :     {
     738        6422 :         STRING_NEW((STRING_TYPE **)&mpData);
     739             :     }
     740             :     else
     741             :     {
     742             :         // copy without allocation if string length is identical
     743       10368 :         if ( (nLen == mpData->mnLen) && (mpData->mnRefCount == 1) )
     744           2 :             memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
     745             :         else
     746             :         {
     747             :             // free old string
     748       10366 :             STRING_RELEASE((STRING_TYPE *)mpData);
     749             : 
     750             :             // allocate string of new size and copy
     751       10366 :             mpData = ImplAllocData( nLen );
     752       10366 :             memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
     753             :         }
     754             :     }
     755             : 
     756       16790 :     return *this;
     757             : }
     758             : 
     759     2042238 : xub_StrLen ImplStringLen( const sal_Char* pStr )
     760             : {
     761     2042238 :     const sal_Char* pTempStr = pStr;
     762    17881926 :     while( *pTempStr )
     763    13797450 :         ++pTempStr;
     764     2042238 :     return (xub_StrLen)(pTempStr-pStr);
     765             : }
     766             : 
     767       29316 : xub_StrLen ImplStringLen( const sal_Unicode* pStr )
     768             : {
     769       29316 :     const sal_Unicode* pTempStr = pStr;
     770      312876 :     while( *pTempStr )
     771      254244 :         ++pTempStr;
     772       29316 :     return (xub_StrLen)(pTempStr-pStr);
     773             : }
     774             : 
     775             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10