LCOV - code coverage report
Current view: top level - libreoffice/tools/source/string - tustring.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 223 307 72.6 %
Date: 2012-12-27 Functions: 27 35 77.1 %
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       19323 : UniString UniString::CreateFromInt32( sal_Int32 n, sal_Int16 nRadix )
      53             : {
      54       19323 :     return rtl::OUString::valueOf(n, nRadix);
      55             : }
      56             : 
      57             : namespace { struct Empty : public rtl::Static< const UniString, Empty> {}; }
      58             : 
      59         126 : const UniString& UniString::EmptyString()
      60             : {
      61         126 :     return Empty::get();
      62             : }
      63             : 
      64        3752 : sal_Int32 UniString::ToInt32() const
      65             : {
      66             :     DBG_CHKTHIS( UniString, DbgCheckUniString );
      67             : 
      68        3752 :     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         221 : xub_StrLen STRING::SearchChar( const STRCODE* pChars, xub_StrLen nIndex ) const
      79             : {
      80             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
      81             : 
      82         221 :     sal_Int32       nLen = mpData->mnLen;
      83         221 :     const STRCODE*  pStr = mpData->maStr;
      84         221 :     pStr += nIndex;
      85        2710 :     while ( nIndex < nLen )
      86             :     {
      87        2286 :         STRCODE         c = *pStr;
      88        2286 :         const STRCODE*  pCompStr = pChars;
      89       11327 :         while ( *pCompStr )
      90             :         {
      91        6773 :             if ( *pCompStr == c )
      92          18 :                 return nIndex;
      93        6755 :             ++pCompStr;
      94             :         }
      95             :         ++pStr,
      96        2268 :         ++nIndex;
      97             :     }
      98             : 
      99         203 :     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         261 : 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         261 :     if ( nPos > rStr.mpData->mnLen )
     132           0 :         nLen = 0;
     133             :     else
     134             :     {
     135             :         // Correct length if necessary
     136         261 :         sal_Int32 nMaxLen = rStr.mpData->mnLen-nPos;
     137         261 :         if ( nLen > nMaxLen )
     138           0 :             nLen = static_cast< xub_StrLen >(nMaxLen);
     139             :     }
     140             : 
     141             :     // Detect overflow
     142         261 :     sal_Int32 nCopyLen = ImplGetCopyLen( mpData->mnLen, nLen );
     143             : 
     144         261 :     if ( !nCopyLen )
     145           0 :         return *this;
     146             : 
     147             :     // Correct index if necessary
     148         261 :     if ( nIndex > mpData->mnLen )
     149           0 :         nIndex = static_cast< xub_StrLen >(mpData->mnLen);
     150             : 
     151             :     // Determine new length and allocate string
     152         261 :     STRINGDATA* pNewData = ImplAllocData( mpData->mnLen+nCopyLen );
     153             : 
     154             :     // copy string to newdata
     155         261 :     memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
     156         261 :     memcpy( pNewData->maStr+nIndex, rStr.mpData->maStr+nPos, nCopyLen*sizeof( STRCODE ) );
     157         261 :     memcpy( pNewData->maStr+nIndex+nCopyLen, mpData->maStr+nIndex,
     158         522 :             (mpData->mnLen-nIndex)*sizeof( STRCODE ) );
     159             : 
     160             :     // release old data
     161         261 :     STRING_RELEASE((STRING_TYPE *)mpData);
     162         261 :     mpData = pNewData;
     163             : 
     164         261 :     return *this;
     165             : }
     166             : 
     167      143181 : static sal_Int32 ImplStringICompareWithoutZero( const STRCODE* pStr1, const STRCODE* pStr2,
     168             :                                                 sal_Int32 nCount )
     169             : {
     170      143181 :     sal_Int32   nRet = 0;
     171             :     STRCODE     c1;
     172             :     STRCODE     c2;
     173      276368 :     do
     174             :     {
     175      280339 :         if ( !nCount )
     176        3971 :             break;
     177             : 
     178             :         // convert if char is between 'A' and 'Z'
     179      276368 :         c1 = *pStr1;
     180      276368 :         c2 = *pStr2;
     181      276368 :         if ( (c1 >= 65) && (c1 <= 90) )
     182       58708 :             c1 += 32;
     183      276368 :         if ( (c2 >= 65) && (c2 <= 90) )
     184      137941 :             c2 += 32;
     185      276368 :         nRet = ((sal_Int32)((STRCODEU)c1))-((sal_Int32)((STRCODEU)c2));
     186             : 
     187             :         ++pStr1,
     188             :         ++pStr2,
     189      276368 :         --nCount;
     190             :     }
     191             :     while ( nRet == 0 );
     192             : 
     193      143181 :     return nRet;
     194             : }
     195             : 
     196          32 : 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          32 :     if ( nIndex > mpData->mnLen )
     203           0 :         return (rStr.mpData->mnLen == 0);
     204          32 :     sal_Int32 nMaxLen = mpData->mnLen-nIndex;
     205          32 :     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          32 :     return (ImplStringICompareWithoutZero( mpData->maStr+nIndex, rStr.mpData->maStr, nLen ) == 0);
     213             : }
     214             : 
     215       92227 : 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       92227 :     if ( mpData == rStr.mpData )
     222        1152 :         return COMPARE_EQUAL;
     223             : 
     224             :     // determine maximal length
     225       91075 :     if ( mpData->mnLen < nLen )
     226       91075 :         nLen = static_cast< xub_StrLen >(mpData->mnLen+1);
     227       91075 :     if ( rStr.mpData->mnLen < nLen )
     228       54894 :         nLen = static_cast< xub_StrLen >(rStr.mpData->mnLen+1);
     229             : 
     230       91075 :     sal_Int32 nCompare = ImplStringICompareWithoutZero( mpData->maStr, rStr.mpData->maStr, nLen );
     231             : 
     232       91075 :     if ( nCompare == 0 )
     233        1528 :         return COMPARE_EQUAL;
     234       89547 :     else if ( nCompare < 0 )
     235       40367 :         return COMPARE_LESS;
     236             :     else
     237       49180 :         return COMPARE_GREATER;
     238             : }
     239             : 
     240         339 : STRCODE* STRING::GetBufferAccess()
     241             : {
     242             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     243             : 
     244             :     // Copy data if necessary
     245         339 :     if ( mpData->mnLen )
     246         339 :         ImplCopyData();
     247             : 
     248             :     // return pointer to string data
     249         339 :     return mpData->maStr;
     250             : }
     251             : 
     252         163 : void STRING::ReleaseBufferAccess( xub_StrLen nLen )
     253             : {
     254             :     // String not consinstent, thus no functionality test
     255             :     DBG_CHKTHIS( STRING, NULL );
     256             :     DBG_ASSERT( mpData->mnRefCount == 1, "String::ReleaseCharStr() called for String with RefCount" );
     257             : 
     258         163 :     if ( nLen > mpData->mnLen )
     259         163 :         nLen = ImplStringLen( mpData->maStr );
     260             :     OSL_ASSERT(nLen <= mpData->mnLen);
     261         163 :     if ( !nLen )
     262             :     {
     263           0 :         STRING_NEW((STRING_TYPE **)&mpData);
     264             :     }
     265             :     // shorten buffer is difference > 8 chars
     266         163 :     else if ( mpData->mnLen - nLen > 8 )
     267             :     {
     268           0 :         STRINGDATA* pNewData = ImplAllocData( nLen );
     269           0 :         memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
     270           0 :         STRING_RELEASE((STRING_TYPE *)mpData);
     271           0 :         mpData = pNewData;
     272             :     }
     273             :     else
     274         163 :         mpData->mnLen = nLen;
     275         163 : }
     276             : 
     277           0 : STRCODE* STRING::AllocBuffer( xub_StrLen nLen )
     278             : {
     279             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     280             : 
     281           0 :     STRING_RELEASE((STRING_TYPE *)mpData);
     282           0 :     if ( nLen )
     283           0 :         mpData = ImplAllocData( nLen );
     284             :     else
     285             :     {
     286           0 :         mpData = NULL;
     287           0 :         STRING_NEW((STRING_TYPE **)&mpData);
     288             :     }
     289             : 
     290           0 :     return mpData->maStr;
     291             : }
     292             : 
     293        1113 : STRING& STRING::Insert( STRCODE c, xub_StrLen nIndex )
     294             : {
     295             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     296             : 
     297             :     // Don't insert 0 char or string size is maximum
     298        1113 :     if ( !c || (mpData->mnLen == STRING_MAXLEN) )
     299           0 :         return *this;
     300             : 
     301             :     // Adjust string index
     302        1113 :     if ( nIndex > mpData->mnLen )
     303          71 :         nIndex = static_cast< xub_StrLen >(mpData->mnLen);
     304             : 
     305             :     // allocate string of new size
     306        1113 :     STRINGDATA* pNewData = ImplAllocData( mpData->mnLen+1 );
     307             : 
     308             :     // copy string
     309        1113 :     memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
     310        1113 :     pNewData->maStr[nIndex] = c;
     311        1113 :     memcpy( pNewData->maStr+nIndex+1, mpData->maStr+nIndex,
     312        2226 :             (mpData->mnLen-nIndex)*sizeof( STRCODE ) );
     313             : 
     314             :     // free old data
     315        1113 :     STRING_RELEASE((STRING_TYPE *)mpData);
     316        1113 :     mpData = pNewData;
     317             : 
     318        1113 :     return *this;
     319             : }
     320             : 
     321          22 : STRING& STRING::ToUpperAscii()
     322             : {
     323             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     324             : 
     325          22 :     sal_Int32 nIndex = 0;
     326          22 :     sal_Int32 nLen = mpData->mnLen;
     327          22 :     STRCODE*    pStr = mpData->maStr;
     328         102 :     while ( nIndex < nLen )
     329             :     {
     330             :         // convert char if between 'a' and 'z'
     331          58 :         if ( (*pStr >= 97) && (*pStr <= 122) )
     332             :         {
     333             :             // allocate string of new size
     334          58 :             pStr = ImplCopyStringData( pStr );
     335          58 :             *pStr -= 32;
     336             :         }
     337             : 
     338             :         ++pStr,
     339          58 :         ++nIndex;
     340             :     }
     341             : 
     342          22 :     return *this;
     343             : }
     344             : 
     345      173936 : StringCompare STRING::CompareTo( const STRING& rStr, xub_StrLen nLen ) const
     346             : {
     347             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     348             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     349             : 
     350      173936 :     if ( mpData == rStr.mpData )
     351        2940 :         return COMPARE_EQUAL;
     352             : 
     353             :     // determine maximal length
     354      170996 :     if ( mpData->mnLen < nLen )
     355      158840 :         nLen = static_cast< xub_StrLen >(mpData->mnLen+1);
     356      170996 :     if ( rStr.mpData->mnLen < nLen )
     357       89081 :         nLen = static_cast< xub_StrLen >(rStr.mpData->mnLen+1);
     358             : 
     359      170996 :     sal_Int32 nCompare = ImplStringCompareWithoutZero( mpData->maStr, rStr.mpData->maStr, nLen );
     360             : 
     361      170996 :     if ( nCompare == 0 )
     362       21714 :         return COMPARE_EQUAL;
     363      149282 :     else if ( nCompare < 0 )
     364      103191 :         return COMPARE_LESS;
     365             :     else
     366       46091 :         return COMPARE_GREATER;
     367             : }
     368             : 
     369     3406779 : sal_Bool STRING::Equals( const STRING& rStr ) const
     370             : {
     371             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     372             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     373             : 
     374     3406779 :     if ( mpData == rStr.mpData )
     375      814179 :         return sal_True;
     376             : 
     377     2592600 :     if ( mpData->mnLen != rStr.mpData->mnLen )
     378     2203247 :         return sal_False;
     379             : 
     380      389353 :     return (ImplStringCompareWithoutZero( mpData->maStr, rStr.mpData->maStr, mpData->mnLen ) == 0);
     381             : }
     382             : 
     383       54907 : sal_Bool STRING::EqualsIgnoreCaseAscii( const STRING& rStr ) const
     384             : {
     385             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     386             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     387             : 
     388       54907 :     if ( mpData == rStr.mpData )
     389           0 :         return sal_True;
     390             : 
     391       54907 :     if ( mpData->mnLen != rStr.mpData->mnLen )
     392        2833 :         return sal_False;
     393             : 
     394             :     // compare string while ignoring case
     395       52074 :     return (ImplStringICompareWithoutZero( mpData->maStr, rStr.mpData->maStr, mpData->mnLen ) == 0);
     396             : }
     397             : 
     398        2173 : sal_Bool STRING::Equals( const STRING& rStr, xub_StrLen nIndex, xub_StrLen nLen ) const
     399             : {
     400             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     401             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     402             : 
     403             :     // Are there enough codes for comparing?
     404        2173 :     if ( nIndex > mpData->mnLen )
     405           0 :         return (rStr.mpData->mnLen == 0);
     406        2173 :     sal_Int32 nMaxLen = mpData->mnLen-nIndex;
     407        2173 :     if ( nMaxLen < nLen )
     408             :     {
     409           0 :         if ( rStr.mpData->mnLen != nMaxLen )
     410           0 :             return sal_False;
     411           0 :         nLen = static_cast< xub_StrLen >(nMaxLen);
     412             :     }
     413             : 
     414        2173 :     return (ImplStringCompareWithoutZero( mpData->maStr+nIndex, rStr.mpData->maStr, nLen ) == 0);
     415             : }
     416             : 
     417           0 : sal_Bool STRING::Equals( const STRCODE* pCharStr, xub_StrLen nIndex, xub_StrLen nLen ) const
     418             : {
     419             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     420             : 
     421             :     // Are there enough codes for comparing?
     422           0 :     if ( nIndex > mpData->mnLen )
     423           0 :         return (*pCharStr == 0);
     424             : 
     425           0 :     return (ImplStringCompare( mpData->maStr+nIndex, pCharStr, nLen ) == 0);
     426             : }
     427             : 
     428       13895 : xub_StrLen STRING::Match( const STRING& rStr ) const
     429             : {
     430             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     431             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     432             : 
     433             :     // return if string is empty
     434       13895 :     if ( !mpData->mnLen )
     435          24 :         return STRING_MATCH;
     436             : 
     437             :     // Search the string for unmatching chars
     438       13871 :     const STRCODE*  pStr1 = mpData->maStr;
     439       13871 :     const STRCODE*  pStr2 = rStr.mpData->maStr;
     440       13871 :     xub_StrLen      i = 0;
     441       29561 :     while ( i < mpData->mnLen )
     442             :     {
     443             :         // Abort on the first unmatching char
     444       15690 :         if ( *pStr1 != *pStr2 )
     445       13871 :             return i;
     446             :         ++pStr1,
     447             :         ++pStr2,
     448        1819 :         ++i;
     449             :     }
     450             : 
     451           0 :     return STRING_MATCH;
     452             : }
     453             : 
     454          21 : xub_StrLen STRING::SearchBackward( STRCODE c, xub_StrLen nIndex ) const
     455             : {
     456             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     457             : 
     458          21 :     if ( nIndex > mpData->mnLen )
     459          21 :         nIndex = (xub_StrLen)mpData->mnLen;
     460             : 
     461          21 :     const STRCODE* pStr = mpData->maStr;
     462          21 :     pStr += nIndex;
     463             : 
     464         245 :     while ( nIndex )
     465             :     {
     466         224 :         nIndex--;
     467         224 :         pStr--;
     468         224 :         if ( *pStr == c )
     469          21 :             return nIndex;
     470             :     }
     471             : 
     472           0 :     return STRING_NOTFOUND;
     473             : }
     474             : 
     475        1958 : void STRING::SearchAndReplaceAll( const STRING& rStr, const STRING& rRepStr )
     476             : {
     477             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     478             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     479             :     DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING );
     480             : 
     481        1958 :     xub_StrLen nSPos = Search( rStr, 0 );
     482        3916 :     while ( nSPos != STRING_NOTFOUND )
     483             :     {
     484           0 :         Replace( nSPos, rStr.Len(), rRepStr );
     485           0 :         nSPos = nSPos + rRepStr.Len();
     486           0 :         nSPos = Search( rStr, nSPos );
     487             :     }
     488        1958 : }
     489             : 
     490           0 : void STRING::SetToken( xub_StrLen nToken, STRCODE cTok, const STRING& rStr,
     491             :                        xub_StrLen nIndex )
     492             : {
     493             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     494             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     495             : 
     496           0 :     const STRCODE*  pStr            = mpData->maStr;
     497           0 :     xub_StrLen      nLen            = (xub_StrLen)mpData->mnLen;
     498           0 :     xub_StrLen      nTok            = 0;
     499           0 :     xub_StrLen      nFirstChar      = nIndex;
     500           0 :     xub_StrLen      i               = nFirstChar;
     501             : 
     502             :     // Determine token position and length
     503           0 :     pStr += i;
     504           0 :     while ( i < nLen )
     505             :     {
     506             :         // Increase token count if match
     507           0 :         if ( *pStr == cTok )
     508             :         {
     509           0 :             ++nTok;
     510             : 
     511           0 :             if ( nTok == nToken )
     512           0 :                 nFirstChar = i+1;
     513             :             else
     514             :             {
     515           0 :                 if ( nTok > nToken )
     516           0 :                     break;
     517             :             }
     518             :         }
     519             : 
     520             :         ++pStr,
     521           0 :         ++i;
     522             :     }
     523             : 
     524           0 :     if ( nTok >= nToken )
     525           0 :         Replace( nFirstChar, i-nFirstChar, rStr );
     526           0 : }
     527             : 
     528        3708 : STRING STRING::GetToken( xub_StrLen nToken, STRCODE cTok, xub_StrLen& rIndex ) const
     529             : {
     530             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     531             : 
     532        3708 :     const STRCODE*  pStr            = mpData->maStr;
     533        3708 :     xub_StrLen      nLen            = (xub_StrLen)mpData->mnLen;
     534        3708 :     xub_StrLen      nTok            = 0;
     535        3708 :     xub_StrLen      nFirstChar      = rIndex;
     536        3708 :     xub_StrLen      i               = nFirstChar;
     537             : 
     538             :     // Determine token position and length
     539        3708 :     pStr += i;
     540       52046 :     while ( i < nLen )
     541             :     {
     542             :         // Increase token count if match
     543       45842 :         if ( *pStr == cTok )
     544             :         {
     545        3770 :             ++nTok;
     546             : 
     547        3770 :             if ( nTok == nToken )
     548        1422 :                 nFirstChar = i+1;
     549             :             else
     550             :             {
     551        2348 :                 if ( nTok > nToken )
     552        1212 :                     break;
     553             :             }
     554             :         }
     555             : 
     556             :         ++pStr,
     557       44630 :         ++i;
     558             :     }
     559             : 
     560        3708 :     if ( nTok >= nToken )
     561             :     {
     562        2954 :         if ( i < nLen )
     563        1212 :             rIndex = i+1;
     564             :         else
     565        1742 :             rIndex = STRING_NOTFOUND;
     566        2954 :         return Copy( nFirstChar, i-nFirstChar );
     567             :     }
     568             :     else
     569             :     {
     570         754 :         rIndex = STRING_NOTFOUND;
     571         754 :         return STRING();
     572             :     }
     573             : }
     574             : 
     575        2489 : STRING& STRING::Append( const STRCODE* pCharStr, xub_StrLen nCharLen )
     576             : {
     577             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     578             :     DBG_ASSERT( pCharStr, "String::Append() - pCharStr is NULL" );
     579             : 
     580        2489 :     if ( nCharLen == STRING_LEN )
     581           0 :         nCharLen = ImplStringLen( pCharStr );
     582             : 
     583             : #ifdef DBG_UTIL
     584             :     if ( DbgIsAssert() )
     585             :     {
     586             :         for ( xub_StrLen i = 0; i < nCharLen; i++ )
     587             :         {
     588             :             if ( !pCharStr[i] )
     589             :             {
     590             :                 OSL_FAIL( "String::Append() : nLen is wrong" );
     591             :             }
     592             :         }
     593             :     }
     594             : #endif
     595             : 
     596             :     // Catch overflow
     597        2489 :     sal_Int32 nLen = mpData->mnLen;
     598        2489 :     sal_Int32 nCopyLen = ImplGetCopyLen( nLen, nCharLen );
     599             : 
     600        2489 :     if ( nCopyLen )
     601             :     {
     602             :         // allocate string of new size
     603        2331 :         STRINGDATA* pNewData = ImplAllocData( nLen+nCopyLen );
     604             : 
     605             :         // copy string
     606        2331 :         memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
     607        2331 :         memcpy( pNewData->maStr+nLen, pCharStr, nCopyLen*sizeof( STRCODE ) );
     608             : 
     609             :         // free old string
     610        2331 :         STRING_RELEASE((STRING_TYPE *)mpData);
     611        2331 :         mpData = pNewData;
     612             :     }
     613             : 
     614        2489 :     return *this;
     615             : }
     616             : 
     617       23732 : STRING& STRING::Append( STRCODE c )
     618             : {
     619             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     620             : 
     621             :     // don't append null characters and keep string length < maxlen
     622       23732 :     sal_Int32 nLen = mpData->mnLen;
     623       23732 :     if ( c && (nLen < STRING_MAXLEN) )
     624             :     {
     625             :         // allocate string of new size
     626       23732 :         STRINGDATA* pNewData = ImplAllocData( nLen+1 );
     627             : 
     628             :         // copy string
     629       23732 :         memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
     630       23732 :         pNewData->maStr[nLen] = c;
     631             : 
     632             :         // free old string
     633       23732 :         STRING_RELEASE((STRING_TYPE *)mpData);
     634       23732 :         mpData = pNewData;
     635             :     }
     636             : 
     637       23732 :     return *this;
     638             : }
     639             : 
     640          74 : STRING& STRING::Assign( STRCODE c )
     641             : {
     642             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     643             :     DBG_ASSERT( c, "String::Assign() - c is 0" );
     644             : 
     645             :     // initialize maintenance data
     646          74 :     STRING_RELEASE((STRING_TYPE *)mpData);
     647          74 :     mpData = ImplAllocData( 1 );
     648          74 :     mpData->maStr[0] = c;
     649          74 :     return *this;
     650             : }
     651             : 
     652        1069 : xub_StrLen STRING::SearchAndReplace( const STRING& rStr, const STRING& rRepStr,
     653             :                                      xub_StrLen nIndex )
     654             : {
     655             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     656             :     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
     657             :     DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING );
     658             : 
     659        1069 :     xub_StrLen nSPos = Search( rStr, nIndex );
     660        1069 :     if ( nSPos != STRING_NOTFOUND )
     661        1058 :         Replace( nSPos, rStr.Len(), rRepStr );
     662             : 
     663        1069 :     return nSPos;
     664             : }
     665             : 
     666           0 : static sal_Int32 ImplStringICompare( const STRCODE* pStr1, const STRCODE* pStr2 )
     667             : {
     668             :     sal_Int32   nRet;
     669             :     STRCODE     c1;
     670             :     STRCODE     c2;
     671           0 :     do
     672             :     {
     673             :         // Convert char if between 'A' and 'Z'
     674           0 :         c1 = *pStr1;
     675           0 :         c2 = *pStr2;
     676           0 :         if ( (c1 >= 65) && (c1 <= 90) )
     677           0 :             c1 += 32;
     678           0 :         if ( (c2 >= 65) && (c2 <= 90) )
     679           0 :             c2 += 32;
     680           0 :         nRet = ((sal_Int32)((STRCODEU)c1))-((sal_Int32)((STRCODEU)c2));
     681           0 :         if ( nRet != 0 )
     682           0 :             break;
     683             : 
     684             :         ++pStr1,
     685           0 :         ++pStr2;
     686             :     }
     687             :     while ( c2 );
     688             : 
     689           0 :     return nRet;
     690             : }
     691             : 
     692           0 : sal_Bool STRING::EqualsIgnoreCaseAscii( const STRCODE* pCharStr ) const
     693             : {
     694             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     695             : 
     696           0 :     return (ImplStringICompare( mpData->maStr, pCharStr ) == 0);
     697             : }
     698             : 
     699        8159 : STRING& STRING::Assign( const STRCODE* pCharStr )
     700             : {
     701             :     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
     702             :     DBG_ASSERT( pCharStr, "String::Assign() - pCharStr is NULL" );
     703             : 
     704        8159 :     xub_StrLen nLen = ImplStringLen( pCharStr );
     705             : 
     706        8159 :     if ( !nLen )
     707             :     {
     708        3114 :         STRING_NEW((STRING_TYPE **)&mpData);
     709             :     }
     710             :     else
     711             :     {
     712             :         // copy without allocation if string length is identical
     713        5045 :         if ( (nLen == mpData->mnLen) && (mpData->mnRefCount == 1) )
     714           0 :             memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
     715             :         else
     716             :         {
     717             :             // free old string
     718        5045 :             STRING_RELEASE((STRING_TYPE *)mpData);
     719             : 
     720             :             // allocate string of new size and copy
     721        5045 :             mpData = ImplAllocData( nLen );
     722        5045 :             memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
     723             :         }
     724             :     }
     725             : 
     726        8159 :     return *this;
     727             : }
     728             : 
     729      984825 : xub_StrLen ImplStringLen( const sal_Char* pStr )
     730             : {
     731      984825 :     const sal_Char* pTempStr = pStr;
     732     8618473 :     while( *pTempStr )
     733     6648823 :         ++pTempStr;
     734      984825 :     return (xub_StrLen)(pTempStr-pStr);
     735             : }
     736             : 
     737       14071 : xub_StrLen ImplStringLen( const sal_Unicode* pStr )
     738             : {
     739       14071 :     const sal_Unicode* pTempStr = pStr;
     740      149664 :     while( *pTempStr )
     741      121522 :         ++pTempStr;
     742       14071 :     return (xub_StrLen)(pTempStr-pStr);
     743             : }
     744             : 
     745             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10