LCOV - code coverage report
Current view: top level - sal/rtl - ustring.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 427 483 88.4 %
Date: 2014-11-03 Functions: 34 36 94.4 %
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 "sal/config.h"
      21             : 
      22             : #ifdef _MSC_VER
      23             : #pragma warning(disable:4738) // storing 32-bit float result in memory, possible loss of performance
      24             : #endif
      25             : 
      26             : #include <cassert>
      27             : #include <cstdlib>
      28             : 
      29             : #include <osl/diagnose.h>
      30             : #include <osl/interlck.h>
      31             : #include <rtl/alloc.h>
      32             : #include <osl/mutex.h>
      33             : #include <osl/doublecheckedlocking.h>
      34             : #include <rtl/tencinfo.h>
      35             : 
      36             : #include <string.h>
      37             : #include <sal/alloca.h>
      38             : #include <sal/log.hxx>
      39             : 
      40             : #include "hash.hxx"
      41             : #include "strimp.hxx"
      42             : #include "surrogates.hxx"
      43             : #include <rtl/ustring.h>
      44             : 
      45             : #include "rtl/math.h"
      46             : 
      47             : /* ======================================================================= */
      48             : 
      49             : /* static data to be referenced by all empty strings
      50             :  * the refCount is predefined to 1 and must never become 0 !
      51             :  */
      52             : static rtl_uString const aImplEmpty_rtl_uString =
      53             : {
      54             :     (sal_Int32) (SAL_STRING_INTERN_FLAG|SAL_STRING_STATIC_FLAG|1), /*sal_Int32    refCount; */
      55             :     0,                                               /*sal_Int32    length;   */
      56             :     { 0 }                                            /*sal_Unicode  buffer[1];*/
      57             : };
      58             : 
      59             : /* ======================================================================= */
      60             : /* These macros are for the "poor-man templates" included from
      61             :  * the strtmpl.cxx just below, used to share code between here and
      62             :  * string.cxx
      63             :  */
      64             : 
      65             : #define IMPL_RTL_STRCODE            sal_Unicode
      66             : #define IMPL_RTL_USTRCODE( c )      (c)
      67             : #define IMPL_RTL_STRNAME( n )       rtl_ustr_ ## n
      68             : 
      69             : #define IMPL_RTL_STRINGNAME( n )    rtl_uString_ ## n
      70             : #define IMPL_RTL_STRINGDATA         rtl_uString
      71             : #define IMPL_RTL_EMPTYSTRING        aImplEmpty_rtl_uString
      72             : #define IMPL_RTL_INTERN
      73             : static void internRelease (rtl_uString *pThis);
      74             : 
      75             : #if USE_SDT_PROBES
      76             : #define RTL_LOG_STRING_BITS         16
      77             : #endif
      78             : 
      79             : /* ======================================================================= */
      80             : 
      81             : /* Include String/UString template code */
      82             : 
      83             : #include "strtmpl.cxx"
      84             : 
      85     6544964 : sal_Int32 rtl_ustr_indexOfAscii_WithLength(
      86             :     sal_Unicode const * str, sal_Int32 len,
      87             :     char const * subStr, sal_Int32 subLen) SAL_THROW_EXTERN_C()
      88             : {
      89     6544964 :     if (subLen > 0 && subLen <= len) {
      90             :         sal_Int32 i;
      91    63684906 :         for (i = 0; i <= len - subLen; ++i) {
      92    60060997 :             if (rtl_ustr_asciil_reverseEquals_WithLength(
      93    60060997 :                     str + i, subStr, subLen))
      94             :             {
      95      295235 :                 return i;
      96             :             }
      97             :         }
      98             :     }
      99     6249729 :     return -1;
     100             : }
     101             : 
     102        5599 : sal_Int32 rtl_ustr_lastIndexOfAscii_WithLength(
     103             :     sal_Unicode const * str, sal_Int32 len,
     104             :     char const * subStr, sal_Int32 subLen) SAL_THROW_EXTERN_C()
     105             : {
     106        5599 :     if (subLen > 0 && subLen <= len) {
     107             :         sal_Int32 i;
     108        6389 :         for (i = len - subLen; i >= 0; --i) {
     109        6387 :             if (rtl_ustr_asciil_reverseEquals_WithLength(
     110        6387 :                     str + i, subStr, subLen))
     111             :             {
     112        5595 :                 return i;
     113             :             }
     114             :         }
     115             :     }
     116           4 :     return -1;
     117             : }
     118             : 
     119          82 : sal_Int32 SAL_CALL rtl_ustr_valueOfFloat(sal_Unicode * pStr, float f)
     120             :     SAL_THROW_EXTERN_C()
     121             : {
     122          82 :     rtl_uString * pResult = NULL;
     123             :     sal_Int32 nLen;
     124             :     rtl_math_doubleToUString(
     125             :         &pResult, 0, 0, f, rtl_math_StringFormat_G,
     126             :         RTL_USTR_MAX_VALUEOFFLOAT - RTL_CONSTASCII_LENGTH("-x.E-xxx"), '.', 0,
     127          82 :         0, sal_True);
     128          82 :     nLen = pResult->length;
     129             :     OSL_ASSERT(nLen < RTL_USTR_MAX_VALUEOFFLOAT);
     130          82 :     memcpy(pStr, pResult->buffer, (nLen + 1) * sizeof(sal_Unicode));
     131          82 :     rtl_uString_release(pResult);
     132          82 :     return nLen;
     133             : }
     134             : 
     135      198517 : sal_Int32 SAL_CALL rtl_ustr_valueOfDouble(sal_Unicode * pStr, double d)
     136             :     SAL_THROW_EXTERN_C()
     137             : {
     138      198517 :     rtl_uString * pResult = NULL;
     139             :     sal_Int32 nLen;
     140             :     rtl_math_doubleToUString(
     141             :         &pResult, 0, 0, d, rtl_math_StringFormat_G,
     142             :         RTL_USTR_MAX_VALUEOFDOUBLE - RTL_CONSTASCII_LENGTH("-x.E-xxx"), '.', 0,
     143      198517 :         0, sal_True);
     144      198517 :     nLen = pResult->length;
     145             :     OSL_ASSERT(nLen < RTL_USTR_MAX_VALUEOFDOUBLE);
     146      198517 :     memcpy(pStr, pResult->buffer, (nLen + 1) * sizeof(sal_Unicode));
     147      198517 :     rtl_uString_release(pResult);
     148      198517 :     return nLen;
     149             : }
     150             : 
     151             : namespace {
     152             : 
     153             : // Avoid -fsanitize=undefined warning e.g. "runtime error: value 1e+99 is
     154             : // outside the range of representable values of type 'float'":
     155         232 : float doubleToFloat(double x) {
     156             :     return
     157         232 :         x < -std::numeric_limits<float>::max()
     158           4 :         ? -std::numeric_limits<float>::infinity()
     159         228 :         : x > std::numeric_limits<float>::max()
     160             :         ? std::numeric_limits<float>::infinity()
     161         464 :         : static_cast<float>(x);
     162             : }
     163             : 
     164             : }
     165             : 
     166         232 : float SAL_CALL rtl_ustr_toFloat(sal_Unicode const * pStr) SAL_THROW_EXTERN_C()
     167             : {
     168             :     return doubleToFloat(rtl_math_uStringToDouble(pStr,
     169         232 :                                             pStr + rtl_ustr_getLength(pStr),
     170         232 :                                             '.', 0, 0, 0));
     171             : }
     172             : 
     173       42946 : double SAL_CALL rtl_ustr_toDouble(sal_Unicode const * pStr) SAL_THROW_EXTERN_C()
     174             : {
     175       42946 :     return rtl_math_uStringToDouble(pStr, pStr + rtl_ustr_getLength(pStr), '.',
     176       42946 :                                     0, 0, 0);
     177             : }
     178             : 
     179             : /* ======================================================================= */
     180             : 
     181       70555 : sal_Int32 SAL_CALL rtl_ustr_ascii_compare( const sal_Unicode* pStr1,
     182             :                                            const sal_Char* pStr2 )
     183             :     SAL_THROW_EXTERN_C()
     184             : {
     185             :     sal_Int32 nRet;
     186      857935 :     while ( ((nRet = ((sal_Int32)(*pStr1))-
     187      393690 :                      ((sal_Int32)((unsigned char)(*pStr2)))) == 0) &&
     188             :             *pStr2 )
     189             :     {
     190             :         /* Check ASCII range */
     191             :         SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
     192             :                     "rtl_ustr_ascii_compare - Found char > 127" );
     193      323135 :         pStr1++;
     194      323135 :         pStr2++;
     195             :     }
     196             : 
     197       70555 :     return nRet;
     198             : }
     199             : 
     200             : /* ----------------------------------------------------------------------- */
     201             : 
     202  1106415333 : sal_Int32 SAL_CALL rtl_ustr_ascii_compare_WithLength( const sal_Unicode* pStr1,
     203             :                                                       sal_Int32 nStr1Len,
     204             :                                                       const sal_Char* pStr2 )
     205             :     SAL_THROW_EXTERN_C()
     206             : {
     207  1106415333 :     sal_Int32 nRet = 0;
     208  5707889585 :     while( ((nRet = (nStr1Len ? (sal_Int32)(*pStr1) : 0)-
     209  1208362204 :                     ((sal_Int32)((unsigned char)(*pStr2)))) == 0) &&
     210  3495058921 :            nStr1Len && *pStr2 )
     211             :     {
     212             :         /* Check ASCII range */
     213             :         SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
     214             :                     "rtl_ustr_ascii_compare_WithLength - Found char > 127" );
     215  1194321793 :         pStr1++;
     216  1194321793 :         pStr2++;
     217  1194321793 :         nStr1Len--;
     218             :     }
     219             : 
     220  1106415333 :     return nRet;
     221             : }
     222             : 
     223             : /* ----------------------------------------------------------------------- */
     224             : 
     225     7614191 : sal_Int32 SAL_CALL rtl_ustr_ascii_shortenedCompare_WithLength( const sal_Unicode* pStr1,
     226             :                                                                sal_Int32 nStr1Len,
     227             :                                                                const sal_Char* pStr2,
     228             :                                                                sal_Int32 nShortenedLength )
     229             :     SAL_THROW_EXTERN_C()
     230             : {
     231     7614191 :     const sal_Unicode*  pStr1End = pStr1 + nStr1Len;
     232             :     sal_Int32           nRet;
     233    32812630 :     while ( (nShortenedLength > 0) &&
     234    22056254 :             (pStr1 < pStr1End) && *pStr2 )
     235             :     {
     236             :         /* Check ASCII range */
     237             :         SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
     238             :                     "rtl_ustr_ascii_shortenedCompare_WithLength - Found char > 127" );
     239             : 
     240    22056254 :         nRet = ((sal_Int32)*pStr1)-
     241    22056254 :                ((sal_Int32)(unsigned char)*pStr2);
     242    22056254 :         if ( nRet != 0 )
     243     4472006 :             return nRet;
     244             : 
     245    17584248 :         nShortenedLength--;
     246    17584248 :         pStr1++;
     247    17584248 :         pStr2++;
     248             :     }
     249             : 
     250     3142185 :     if ( nShortenedLength <= 0 )
     251     3127548 :         return 0;
     252             : 
     253       14637 :     if ( *pStr2 )
     254             :     {
     255             :         OSL_ENSURE( pStr1 == pStr1End, "pStr1 == pStr1End failed" );
     256             :         // first is a substring of the second string => less (negative value)
     257       14637 :         nRet = -1;
     258             :     }
     259             :     else
     260             :     {
     261             :         // greater or equal
     262           0 :         nRet = pStr1End - pStr1;
     263             :     }
     264             : 
     265       14637 :     return nRet;
     266             : }
     267             : 
     268             : /* ----------------------------------------------------------------------- */
     269             : 
     270        6666 : sal_Int32 SAL_CALL rtl_ustr_asciil_reverseCompare_WithLength( const sal_Unicode* pStr1,
     271             :                                                               sal_Int32 nStr1Len,
     272             :                                                               const sal_Char* pStr2,
     273             :                                                               sal_Int32 nStr2Len )
     274             :     SAL_THROW_EXTERN_C()
     275             : {
     276        6666 :     const sal_Unicode*  pStr1Run = pStr1+nStr1Len;
     277        6666 :     const sal_Char*     pStr2Run = pStr2+nStr2Len;
     278             :     sal_Int32           nRet;
     279       14174 :     while ( (pStr1 < pStr1Run) && (pStr2 < pStr2Run) )
     280             :     {
     281             :         /* Check ASCII range */
     282             :         SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
     283             :                     "rtl_ustr_asciil_reverseCompare_WithLength - Found char > 127" );
     284        7468 :         pStr1Run--;
     285        7468 :         pStr2Run--;
     286        7468 :         nRet = ((sal_Int32)*pStr1Run)-((sal_Int32)*pStr2Run);
     287        7468 :         if ( nRet )
     288        6626 :             return nRet;
     289             :     }
     290             : 
     291          40 :     return nStr1Len - nStr2Len;
     292             : }
     293             : 
     294             : /* ----------------------------------------------------------------------- */
     295             : 
     296   121493281 : sal_Bool SAL_CALL rtl_ustr_asciil_reverseEquals_WithLength( const sal_Unicode* pStr1,
     297             :                                                               const sal_Char* pStr2,
     298             :                                                               sal_Int32 nStrLen )
     299             :     SAL_THROW_EXTERN_C()
     300             : {
     301   121493281 :     const sal_Unicode*  pStr1Run = pStr1+nStrLen;
     302   121493281 :     const sal_Char*     pStr2Run = pStr2+nStrLen;
     303   655654199 :     while ( pStr1 < pStr1Run )
     304             :     {
     305             :         /* Check ASCII range */
     306             :         SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
     307             :                     "rtl_ustr_asciil_reverseEquals_WithLength - Found char > 127" );
     308   496429868 :         pStr1Run--;
     309   496429868 :         pStr2Run--;
     310   496429868 :         if( *pStr1Run != (sal_Unicode)*pStr2Run )
     311    83762231 :             return sal_False;
     312             :     }
     313             : 
     314    37731050 :     return sal_True;
     315             : }
     316             : 
     317             : /* ----------------------------------------------------------------------- */
     318             : 
     319           0 : sal_Int32 SAL_CALL rtl_ustr_ascii_compareIgnoreAsciiCase( const sal_Unicode* pStr1,
     320             :                                                           const sal_Char* pStr2 )
     321             :     SAL_THROW_EXTERN_C()
     322             : {
     323             :     sal_Int32   nRet;
     324             :     sal_Int32   c1;
     325             :     sal_Int32   c2;
     326           0 :     do
     327             :     {
     328             :         /* Check ASCII range */
     329             :         SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
     330             :                     "rtl_ustr_ascii_compareIgnoreAsciiCase - Found char > 127" );
     331             :         /* If character between 'A' and 'Z', than convert it to lowercase */
     332           0 :         c1 = (sal_Int32)*pStr1;
     333           0 :         c2 = (sal_Int32)((unsigned char)*pStr2);
     334           0 :         if ( (c1 >= 65) && (c1 <= 90) )
     335           0 :             c1 += 32;
     336           0 :         if ( (c2 >= 65) && (c2 <= 90) )
     337           0 :             c2 += 32;
     338           0 :         nRet = c1-c2;
     339           0 :         if ( nRet != 0 )
     340           0 :             return nRet;
     341             : 
     342           0 :         pStr1++;
     343           0 :         pStr2++;
     344             :     }
     345             :     while ( c2 );
     346             : 
     347           0 :     return 0;
     348             : }
     349             : 
     350             : /* ----------------------------------------------------------------------- */
     351             : 
     352   484099139 : sal_Int32 SAL_CALL rtl_ustr_ascii_compareIgnoreAsciiCase_WithLength( const sal_Unicode* pStr1,
     353             :                                                                      sal_Int32 nStr1Len,
     354             :                                                                      const sal_Char* pStr2 )
     355             :     SAL_THROW_EXTERN_C()
     356             : {
     357             :     sal_Int32   nRet;
     358             :     sal_Int32   c1;
     359             :     sal_Int32   c2;
     360    67270637 :     do
     361             :     {
     362             :         /* Check ASCII range */
     363             :         SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
     364             :                     "rtl_ustr_ascii_compareIgnoreAsciiCase_WithLength - Found char > 127" );
     365   484099139 :         if ( !nStr1Len )
     366     2066679 :             return *pStr2 == '\0' ? 0 : -1;
     367             : 
     368             :         /* If character between 'A' and 'Z', than convert it to lowercase */
     369   482032460 :         c1 = (sal_Int32)*pStr1;
     370   482032460 :         c2 = (sal_Int32)((unsigned char)*pStr2);
     371   482032460 :         if ( (c1 >= 65) && (c1 <= 90) )
     372   420304964 :             c1 += 32;
     373   482032460 :         if ( (c2 >= 65) && (c2 <= 90) )
     374   415887783 :             c2 += 32;
     375   482032460 :         nRet = c1-c2;
     376   482032460 :         if ( nRet != 0 )
     377   414761823 :             return nRet;
     378             : 
     379    67270637 :         pStr1++;
     380    67270637 :         pStr2++;
     381    67270637 :         nStr1Len--;
     382             :     }
     383             :     while( c2 );
     384             : 
     385           0 :     return 0;
     386             : }
     387             : 
     388    20199365 : sal_Int32 rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
     389             :     sal_Unicode const * first, sal_Int32 firstLen,
     390             :     char const * second, sal_Int32 secondLen) SAL_THROW_EXTERN_C()
     391             : {
     392             :     sal_Int32 i;
     393    20199365 :     sal_Int32 len = firstLen < secondLen ? firstLen : secondLen;
     394    22703940 :     for (i = 0; i < len; ++i) {
     395             :         /* Check ASCII range */
     396             :         SAL_WARN_IF( ((unsigned char)*second) > 127, "rtl.string",
     397             :                     "rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths - Found char > 127" );
     398    22594895 :         sal_Int32 c1 = *first++;
     399    22594895 :         sal_Int32 c2 = (unsigned char) *second++;
     400             :         sal_Int32 d;
     401    22594895 :         if (c1 >= 65 && c1 <= 90) {
     402     6081102 :             c1 += 32;
     403             :         }
     404    22594895 :         if (c2 >= 65 && c2 <= 90) {
     405      179198 :             c2 += 32;
     406             :         }
     407    22594895 :         d = c1 - c2;
     408    22594895 :         if (d != 0) {
     409    20090320 :             return d;
     410             :         }
     411             :     }
     412      109045 :     return firstLen - secondLen;
     413             : }
     414             : 
     415             : /* ----------------------------------------------------------------------- */
     416             : 
     417     3130811 : sal_Int32 SAL_CALL rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( const sal_Unicode* pStr1,
     418             :                                                                               sal_Int32 nStr1Len,
     419             :                                                                               const sal_Char* pStr2,
     420             :                                                                               sal_Int32 nShortenedLength )
     421             :     SAL_THROW_EXTERN_C()
     422             : {
     423     3130811 :     const sal_Unicode*  pStr1End = pStr1 + nStr1Len;
     424             :     sal_Int32           nRet;
     425             :     sal_Int32           c1;
     426             :     sal_Int32           c2;
     427     7736855 :     while ( (nShortenedLength > 0) &&
     428     4447088 :             (pStr1 < pStr1End) && *pStr2 )
     429             :     {
     430             :         /* Check ASCII range */
     431             :         SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
     432             :                     "rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength - Found char > 127" );
     433             : 
     434             :         /* If character between 'A' and 'Z', than convert it to lowercase */
     435     4447088 :         c1 = (sal_Int32)*pStr1;
     436     4447088 :         c2 = (sal_Int32)((unsigned char)*pStr2);
     437     4447088 :         if ( (c1 >= 65) && (c1 <= 90) )
     438      232276 :             c1 += 32;
     439     4447088 :         if ( (c2 >= 65) && (c2 <= 90) )
     440      232790 :             c2 += 32;
     441     4447088 :         nRet = c1-c2;
     442     4447088 :         if ( nRet != 0 )
     443     2971855 :             return nRet;
     444             : 
     445     1475233 :         nShortenedLength--;
     446     1475233 :         pStr1++;
     447     1475233 :         pStr2++;
     448             :     }
     449             : 
     450      158956 :     if ( nShortenedLength <= 0 )
     451      158854 :         return 0;
     452             : 
     453         102 :     if ( *pStr2 )
     454             :     {
     455             :         OSL_ENSURE( pStr1 == pStr1End, "pStr1 == pStr1End failed" );
     456             :         // first is a substring of the second string => less (negative value)
     457         102 :         nRet = -1;
     458             :     }
     459             :     else
     460             :     {
     461             :         // greater or equal
     462           0 :         nRet = pStr1End - pStr1;
     463             :     }
     464             : 
     465         102 :     return nRet;
     466             : }
     467             : 
     468             : /* ----------------------------------------------------------------------- */
     469             : 
     470    22452546 : void SAL_CALL rtl_uString_newFromAscii( rtl_uString** ppThis,
     471             :                                         const sal_Char* pCharStr )
     472             :     SAL_THROW_EXTERN_C()
     473             : {
     474             :     sal_Int32 nLen;
     475             : 
     476    22452546 :     if ( pCharStr )
     477             :     {
     478    22452232 :         const sal_Char* pTempStr = pCharStr;
     479   288157892 :         while( *pTempStr )
     480   243253428 :             pTempStr++;
     481    22452232 :         nLen = pTempStr-pCharStr;
     482             :     }
     483             :     else
     484         314 :         nLen = 0;
     485             : 
     486    22452546 :     if ( !nLen )
     487             :     {
     488      196934 :         rtl_uString_new( ppThis );
     489    22649480 :         return;
     490             :     }
     491             : 
     492    22255612 :     if ( *ppThis )
     493        9868 :         rtl_uString_release( *ppThis );
     494             : 
     495    22255612 :     *ppThis = rtl_uString_ImplAlloc( nLen );
     496             :     OSL_ASSERT(*ppThis != NULL);
     497    22255612 :     if ( (*ppThis) )
     498             :     {
     499    22255612 :         sal_Unicode* pBuffer = (*ppThis)->buffer;
     500   243253428 :         do
     501             :         {
     502             :             /* Check ASCII range */
     503             :             SAL_WARN_IF( ((unsigned char)*pCharStr) > 127, "rtl.string",
     504             :                         "rtl_uString_newFromAscii - Found char > 127" );
     505             : 
     506   243253428 :             *pBuffer = *pCharStr;
     507   243253428 :             pBuffer++;
     508   243253428 :             pCharStr++;
     509             :         }
     510             :         while ( *pCharStr );
     511             : 
     512             :         RTL_LOG_STRING_NEW( *ppThis );
     513             :     }
     514             : }
     515             : 
     516       13787 : void SAL_CALL rtl_uString_newFromCodePoints(
     517             :     rtl_uString ** newString, sal_uInt32 const * codePoints,
     518             :     sal_Int32 codePointCount) SAL_THROW_EXTERN_C()
     519             : {
     520             :     sal_Int32 n;
     521             :     sal_Int32 i;
     522             :     sal_Unicode * p;
     523             :     OSL_ASSERT(
     524             :         newString != NULL &&
     525             :         (codePoints != NULL || codePointCount == 0) &&
     526             :         codePointCount >= 0);
     527       13787 :     if (codePointCount == 0) {
     528        4254 :         rtl_uString_new(newString);
     529        4254 :         return;
     530             :     }
     531        9533 :     if (*newString != NULL) {
     532           0 :         rtl_uString_release(*newString);
     533             :     }
     534        9533 :     n = codePointCount;
     535       19462 :     for (i = 0; i < codePointCount; ++i) {
     536             :         OSL_ASSERT(codePoints[i] <= 0x10FFFF);
     537        9929 :         if (codePoints[i] >= 0x10000) {
     538           8 :             ++n;
     539             :         }
     540             :     }
     541             :     /* Builds on the assumption that sal_Int32 uses 32 bit two's complement
     542             :        representation with wrap around (the necessary number of UTF-16 code
     543             :        units will be no larger than 2 * SAL_MAX_INT32, represented as
     544             :        sal_Int32 -2): */
     545        9533 :     if (n < 0) {
     546           0 :         *newString = NULL;
     547           0 :         return;
     548             :     }
     549        9533 :     *newString = rtl_uString_ImplAlloc(n);
     550        9533 :     if (*newString == NULL) {
     551           0 :         return;
     552             :     }
     553        9533 :     p = (*newString)->buffer;
     554       19462 :     for (i = 0; i < codePointCount; ++i) {
     555        9929 :         sal_uInt32 c = codePoints[i];
     556        9929 :         if (c < 0x10000) {
     557        9921 :             *p++ = (sal_Unicode) c;
     558             :         } else {
     559           8 :             c -= 0x10000;
     560           8 :             *p++ = (sal_Unicode) ((c >> 10) | SAL_RTL_FIRST_HIGH_SURROGATE);
     561           8 :             *p++ = (sal_Unicode) ((c & 0x3FF) | SAL_RTL_FIRST_LOW_SURROGATE);
     562             :         }
     563             :     }
     564             :     RTL_LOG_STRING_NEW( *newString );
     565             : }
     566             : 
     567             : /* ======================================================================= */
     568             : 
     569    41459541 : static int rtl_ImplGetFastUTF8UnicodeLen( const sal_Char* pStr, sal_Int32 nLen, bool * ascii )
     570             : {
     571             :     int             n;
     572             :     unsigned char       c;
     573             :     const sal_Char* pEndStr;
     574             : 
     575    41459541 :     *ascii = true;
     576    41459541 :     n = 0;
     577    41459541 :     pEndStr  = pStr+nLen;
     578   684123326 :     while ( pStr < pEndStr )
     579             :     {
     580   601204244 :         c = (unsigned char)*pStr;
     581             : 
     582   601204244 :         if ( !(c & 0x80) )
     583   598186270 :             pStr++;
     584             :         else
     585             :         {
     586     3017974 :             if ( (c & 0xE0) == 0xC0 )
     587       53918 :                 pStr += 2;
     588     2964056 :             else if ( (c & 0xF0) == 0xE0 )
     589     2956918 :                 pStr += 3;
     590        7138 :             else if ( (c & 0xF8) == 0xF0 )
     591         438 :                 pStr += 4;
     592        6700 :             else if ( (c & 0xFC) == 0xF8 )
     593           0 :                 pStr += 5;
     594        6700 :             else if ( (c & 0xFE) == 0xFC )
     595          30 :                 pStr += 6;
     596             :             else
     597        6670 :                 pStr++;
     598     3017974 :             *ascii = false;
     599             :         }
     600             : 
     601   601204244 :         n++;
     602             :     }
     603             : 
     604    41459541 :     return n;
     605             : }
     606             : 
     607             : /* ----------------------------------------------------------------------- */
     608             : 
     609    61805236 : static void rtl_string2UString_status( rtl_uString** ppThis,
     610             :                                        const sal_Char* pStr,
     611             :                                        sal_Int32 nLen,
     612             :                                        rtl_TextEncoding eTextEncoding,
     613             :                                        sal_uInt32 nCvtFlags,
     614             :                                        sal_uInt32 *pInfo )
     615             : {
     616             :     OSL_ENSURE(nLen == 0 || rtl_isOctetTextEncoding(eTextEncoding),
     617             :                "rtl_string2UString_status() - Wrong TextEncoding" );
     618             : 
     619    61805236 :     if ( !nLen )
     620             :     {
     621     1252282 :         rtl_uString_new( ppThis );
     622     1252282 :         if (pInfo != NULL) {
     623      959591 :             *pInfo = 0;
     624             :         }
     625             :     }
     626             :     else
     627             :     {
     628    60552954 :         if ( *ppThis )
     629    14160513 :             rtl_uString_release( *ppThis );
     630             : 
     631             :         /* Optimization for US-ASCII */
     632    60552957 :         if ( eTextEncoding == RTL_TEXTENCODING_ASCII_US )
     633             :         {
     634             :             sal_Unicode* pBuffer;
     635    18872191 :             *ppThis = rtl_uString_ImplAlloc( nLen );
     636    18872191 :             if (*ppThis == NULL) {
     637           0 :                 if (pInfo != NULL) {
     638             :                     *pInfo = RTL_TEXTTOUNICODE_INFO_ERROR |
     639           0 :                         RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
     640             :                 }
     641           0 :                 return;
     642             :             }
     643    18872191 :             pBuffer = (*ppThis)->buffer;
     644   262317504 :             do
     645             :             {
     646             :                 /* Check ASCII range */
     647             :                 SAL_WARN_IF( ((unsigned char)*pStr) > 127, "rtl.string",
     648             :                             "rtl_string2UString_status() - Found char > 127 and RTL_TEXTENCODING_ASCII_US is specified" );
     649             : 
     650   262317504 :                 *pBuffer = *pStr;
     651   262317504 :                 pBuffer++;
     652   262317504 :                 pStr++;
     653   262317504 :                 nLen--;
     654             :             }
     655             :             while ( nLen );
     656    18872191 :             if (pInfo != NULL) {
     657    13571748 :                 *pInfo = 0;
     658             :             }
     659             :         }
     660             :         else
     661             :         {
     662             :             rtl_uString*                pTemp;
     663    41680766 :             rtl_uString*                pTemp2 = NULL;
     664             :             rtl_TextToUnicodeConverter  hConverter;
     665             :             sal_uInt32                  nInfo;
     666             :             sal_Size                    nSrcBytes;
     667             :             sal_Size                    nDestChars;
     668             :             sal_Size                    nNewLen;
     669             : 
     670             :             /* Optimization for UTF-8 - we try to calculate the exact length */
     671             :             /* For all other encoding we try the maximum - and reallocate
     672             :                the buffer if needed */
     673    41680766 :             if ( eTextEncoding == RTL_TEXTENCODING_UTF8 )
     674             :             {
     675             :                 bool ascii;
     676    41459541 :                 nNewLen = rtl_ImplGetFastUTF8UnicodeLen( pStr, nLen, &ascii );
     677             :                 /* Includes the string only ASCII, then we could copy
     678             :                    the buffer faster */
     679    41459542 :                 if ( ascii )
     680             :                 {
     681             :                     sal_Unicode* pBuffer;
     682    40684680 :                     *ppThis = rtl_uString_ImplAlloc( nLen );
     683    40684683 :                     if (*ppThis == NULL)
     684             :                     {
     685           0 :                         if (pInfo != NULL) {
     686             :                             *pInfo = RTL_TEXTTOUNICODE_INFO_ERROR |
     687           0 :                                 RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
     688             :                         }
     689    40684683 :                         return;
     690             :                     }
     691    40684683 :                     pBuffer = (*ppThis)->buffer;
     692   588783326 :                     do
     693             :                     {
     694             :                         /* Check ASCII range */
     695             :                         SAL_WARN_IF( ((unsigned char)*pStr) > 127, "rtl.string",
     696             :                                     "rtl_string2UString_status() - UTF8 test encoding is wrong" );
     697             : 
     698   588783326 :                         *pBuffer = *pStr;
     699   588783326 :                         pBuffer++;
     700   588783326 :                         pStr++;
     701   588783326 :                         nLen--;
     702             :                     }
     703             :                     while ( nLen );
     704    40684683 :                     if (pInfo != NULL) {
     705    20463161 :                         *pInfo = 0;
     706             :                     }
     707             :                     RTL_LOG_STRING_NEW( *ppThis );
     708    40684683 :                     return;
     709             :                 }
     710             :             }
     711             :             else
     712      221225 :                 nNewLen = nLen;
     713             : 
     714      996087 :             nCvtFlags |= RTL_TEXTTOUNICODE_FLAGS_FLUSH;
     715      996087 :             hConverter = rtl_createTextToUnicodeConverter( eTextEncoding );
     716             : 
     717      996087 :             pTemp = rtl_uString_ImplAlloc( nNewLen );
     718      996087 :             if (pTemp == NULL) {
     719           0 :                 if (pInfo != NULL) {
     720             :                     *pInfo = RTL_TEXTTOUNICODE_INFO_ERROR |
     721           0 :                         RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
     722             :                 }
     723           0 :                 return;
     724             :             }
     725             :             nDestChars = rtl_convertTextToUnicode( hConverter, 0,
     726             :                                                    pStr, nLen,
     727             :                                                    pTemp->buffer, nNewLen,
     728             :                                                    nCvtFlags,
     729      996087 :                                                    &nInfo, &nSrcBytes );
     730             : 
     731             :             /* Buffer not big enough, try again with enough space */
     732             :             /* Shouldn't be the case, but if we get textencoding which
     733             :                could results in more unicode characters we have this
     734             :                code here. Could be the case for apple encodings */
     735     1992532 :             while ( nInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL )
     736             :             {
     737         358 :                 rtl_freeMemory( pTemp );
     738         358 :                 nNewLen += 8;
     739         358 :                 pTemp = rtl_uString_ImplAlloc( nNewLen );
     740         358 :                 if (pTemp == NULL) {
     741           0 :                     if (pInfo != NULL) {
     742             :                         *pInfo = RTL_TEXTTOUNICODE_INFO_ERROR |
     743           0 :                             RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
     744             :                     }
     745           0 :                     return;
     746             :                 }
     747             :                 nDestChars = rtl_convertTextToUnicode( hConverter, 0,
     748             :                                                        pStr, nLen,
     749             :                                                        pTemp->buffer, nNewLen,
     750             :                                                        nCvtFlags,
     751         358 :                                                        &nInfo, &nSrcBytes );
     752             :             }
     753             : 
     754      996087 :             if (pInfo)
     755       54886 :                 *pInfo = nInfo;
     756             : 
     757             :             /* Set the buffer to the correct size or if there is too
     758             :                much overhead, reallocate to the correct size */
     759      996087 :             if ( nNewLen > nDestChars+8 )
     760             :             {
     761           4 :                 pTemp2 = rtl_uString_ImplAlloc( nDestChars );
     762             :             }
     763      996087 :             if (pTemp2 != NULL)
     764             :             {
     765           4 :                 rtl_str_ImplCopy(pTemp2->buffer, pTemp->buffer, nDestChars);
     766           4 :                 rtl_freeMemory(pTemp);
     767           4 :                 pTemp = pTemp2;
     768             :             }
     769             :             else
     770             :             {
     771      996083 :                 pTemp->length = nDestChars;
     772      996083 :                 pTemp->buffer[nDestChars] = 0;
     773             :             }
     774             : 
     775      996087 :             rtl_destroyTextToUnicodeConverter( hConverter );
     776      996087 :             *ppThis = pTemp;
     777             : 
     778             :             /* Results the conversion in an empty buffer -
     779             :                create an empty string */
     780      996087 :             if ( pTemp && !nDestChars )
     781          12 :                 rtl_uString_new( ppThis );
     782             :         }
     783             :     }
     784             :     RTL_LOG_STRING_NEW( *ppThis );
     785             : }
     786             : 
     787    25604648 : void SAL_CALL rtl_string2UString( rtl_uString** ppThis,
     788             :                                   const sal_Char* pStr,
     789             :                                   sal_Int32 nLen,
     790             :                                   rtl_TextEncoding eTextEncoding,
     791             :                                   sal_uInt32 nCvtFlags ) SAL_THROW_EXTERN_C()
     792             : {
     793             :     rtl_string2UString_status( ppThis, pStr, nLen, eTextEncoding,
     794    25604648 :                                nCvtFlags, NULL );
     795    25604648 : }
     796             : 
     797             : /* ----------------------------------------------------------------------- */
     798             : 
     799             : enum StrLifecycle {
     800             :     CANNOT_RETURN,
     801             :     CAN_RETURN = 1
     802             : };
     803             : 
     804             : static oslMutex
     805     2184547 : getInternMutex()
     806             : {
     807             :     static oslMutex pPoolGuard = NULL;
     808     2184547 :     if( !pPoolGuard )
     809             :     {
     810             :         oslMutex pGlobalGuard;
     811         243 :         pGlobalGuard = *osl_getGlobalMutex();
     812         243 :         osl_acquireMutex( pGlobalGuard );
     813         243 :         if( !pPoolGuard )
     814             :         {
     815         243 :             oslMutex p = osl_createMutex();
     816             :             OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
     817         243 :             pPoolGuard = p;
     818             :         }
     819         243 :         osl_releaseMutex( pGlobalGuard );
     820             :     }
     821             :     else
     822             :     {
     823             :         OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
     824             :     }
     825             : 
     826     2184547 :     return pPoolGuard;
     827             : }
     828             : 
     829             : /* returns true if we found a dup in the pool */
     830     1254763 : static void rtl_ustring_intern_internal( rtl_uString ** newStr,
     831             :                                          rtl_uString  * str,
     832             :                                          StrLifecycle   can_return )
     833             : {
     834             :     oslMutex pPoolMutex;
     835             : 
     836     1254763 :     pPoolMutex = getInternMutex();
     837             : 
     838     1254763 :     osl_acquireMutex( pPoolMutex );
     839             : 
     840     1254763 :     *newStr = rtl_str_hash_intern (str, can_return);
     841             : 
     842     1254763 :     osl_releaseMutex( pPoolMutex );
     843             : 
     844             :     RTL_LOG_STRING_INTERN_NEW(*newStr, str);
     845             : 
     846     1254763 :     if( can_return && *newStr != str )
     847             :     { /* we dupped, then found a match */
     848      283978 :         rtl_freeMemory( str );
     849             :     }
     850     1254763 : }
     851             : 
     852       83201 : void SAL_CALL rtl_uString_intern( rtl_uString ** newStr,
     853             :                                   rtl_uString  * str) SAL_THROW_EXTERN_C()
     854             : {
     855       83201 :     if (SAL_STRING_IS_INTERN(str))
     856             :     {
     857           2 :         IMPL_RTL_AQUIRE( str );
     858           2 :         *newStr = str;
     859             :     }
     860             :     else
     861             :     {
     862       83199 :         rtl_uString *pOrg = *newStr;
     863       83199 :         *newStr = NULL;
     864       83199 :         rtl_ustring_intern_internal( newStr, str, CANNOT_RETURN );
     865       83199 :         if (pOrg)
     866           0 :             rtl_uString_release (pOrg);
     867             :     }
     868       83201 : }
     869             : 
     870     1151216 : static int rtl_canGuessUOutputLength( int len, rtl_TextEncoding eTextEncoding )
     871             : {
     872             :     // FIXME: Maybe we should use a bit flag in the higher bits of the
     873             :     // eTextEncoding value itself to determine the encoding type.  But if we
     874             :     // do, be sure to mask the value in certain places that expect the values
     875             :     // to be numbered serially from 0 and up.  One such place is
     876             :     // Impl_getTextEncodingData().
     877             : 
     878     1151216 :     switch ( eTextEncoding )
     879             :     {
     880             :         // 1 to 1 (with no zero elements)
     881             :         case RTL_TEXTENCODING_IBM_437:
     882             :         case RTL_TEXTENCODING_IBM_850:
     883             :         case RTL_TEXTENCODING_IBM_860:
     884             :         case RTL_TEXTENCODING_IBM_861:
     885             :         case RTL_TEXTENCODING_IBM_863:
     886             :         case RTL_TEXTENCODING_IBM_865:
     887           0 :             return len;
     888             :         break;
     889             :     }
     890     1151216 :     return 0;
     891             : }
     892             : 
     893     1171564 : void SAL_CALL rtl_uString_internConvert( rtl_uString   ** newStr,
     894             :                                          const sal_Char * str,
     895             :                                          sal_Int32        len,
     896             :                                          rtl_TextEncoding eTextEncoding,
     897             :                                          sal_uInt32       convertFlags,
     898             :                                          sal_uInt32     * pInfo )
     899             :     SAL_THROW_EXTERN_C()
     900             : {
     901             :     rtl_uString *scratch;
     902             : 
     903     1171564 :     if (*newStr)
     904             :     {
     905           0 :         rtl_uString_release (*newStr);
     906           0 :         *newStr = NULL;
     907             :     }
     908             : 
     909     1171564 :     if ( len < 256 )
     910             :     { // try various optimisations
     911             :         sal_Int32 ulen;
     912     1171564 :         if ( len < 0 )
     913           0 :             len = strlen( str );
     914     1171564 :         if ( eTextEncoding == RTL_TEXTENCODING_ASCII_US )
     915             :         {
     916             :             int i;
     917             :             rtl_uString *pScratch;
     918             :             pScratch = static_cast< rtl_uString * >(
     919       20348 :                 alloca(sizeof (rtl_uString) + len * sizeof (sal_Unicode)));
     920      142480 :             for (i = 0; i < len; i++)
     921             :             {
     922             :                 /* Check ASCII range */
     923             :                 SAL_WARN_IF( ((unsigned char)str[i]) > 127, "rtl.string",
     924             :                             "rtl_ustring_internConvert() - Found char > 127 and RTL_TEXTENCODING_ASCII_US is specified" );
     925      122132 :                 pScratch->buffer[i] = str[i];
     926             :             }
     927       20348 :             pScratch->length = len;
     928       20348 :             rtl_ustring_intern_internal( newStr, pScratch, CANNOT_RETURN );
     929       40696 :             return;
     930             :         }
     931     1151216 :         else if ( (ulen = rtl_canGuessUOutputLength(len, eTextEncoding)) != 0 )
     932             :         {
     933             :             rtl_uString *pScratch;
     934             :             rtl_TextToUnicodeConverter hConverter;
     935             :             sal_Size nSrcBytes;
     936             :             sal_uInt32 nInfo;
     937             : 
     938             :             pScratch = static_cast< rtl_uString * >(
     939           0 :                 alloca(
     940           0 :                     sizeof (rtl_uString) + ulen * sizeof (sal_Unicode)));
     941             : 
     942           0 :             hConverter = rtl_createTextToUnicodeConverter( eTextEncoding );
     943             :             rtl_convertTextToUnicode(
     944           0 :                 hConverter, 0, str, len, pScratch->buffer, ulen, convertFlags, &nInfo, &nSrcBytes );
     945           0 :             rtl_destroyTextToUnicodeConverter( hConverter );
     946             : 
     947           0 :             if (pInfo)
     948           0 :                 *pInfo = nInfo;
     949             : 
     950           0 :             pScratch->length = ulen;
     951           0 :             rtl_ustring_intern_internal( newStr, pScratch, CANNOT_RETURN );
     952           0 :             return;
     953             :         }
     954             : 
     955             :         /* FIXME: we want a nice UTF-8 / alloca shortcut here */
     956             :     }
     957             : 
     958     1151216 :     scratch = NULL;
     959             :     rtl_string2UString_status( &scratch, str, len, eTextEncoding, convertFlags,
     960     1151216 :                                pInfo );
     961     1151216 :     if (!scratch) {
     962           0 :         return;
     963             :     }
     964     1151216 :     rtl_ustring_intern_internal( newStr, scratch, CAN_RETURN );
     965             : }
     966             : 
     967             : static void
     968    11795268 : internRelease (rtl_uString *pThis)
     969             : {
     970             :     oslMutex pPoolMutex;
     971             : 
     972    11795268 :     rtl_uString *pFree = NULL;
     973    11795268 :     if ( SAL_STRING_REFCOUNT(
     974             :              osl_atomic_decrement( &(pThis->refCount) ) ) == 0)
     975             :     {
     976             :         RTL_LOG_STRING_INTERN_DELETE(pThis);
     977      929784 :         pPoolMutex = getInternMutex();
     978      929784 :         osl_acquireMutex( pPoolMutex );
     979             : 
     980      929784 :         rtl_str_hash_remove (pThis);
     981             : 
     982             :         /* May have been separately acquired */
     983      929784 :         if ( SAL_STRING_REFCOUNT(
     984             :                  osl_atomic_increment( &(pThis->refCount) ) ) == 1 )
     985             :         {
     986             :             /* we got the last ref */
     987      929784 :             pFree = pThis;
     988             :         }
     989             :         else /* very unusual */
     990             :         {
     991           0 :             internRelease (pThis);
     992             :         }
     993             : 
     994      929784 :         osl_releaseMutex( pPoolMutex );
     995             :     }
     996    11795269 :     if (pFree)
     997      929784 :         rtl_freeMemory (pFree);
     998    11795269 : }
     999             : 
    1000    26731358 : sal_uInt32 SAL_CALL rtl_uString_iterateCodePoints(
    1001             :     rtl_uString const * string, sal_Int32 * indexUtf16,
    1002             :     sal_Int32 incrementCodePoints)
    1003             : {
    1004             :     sal_Int32 n;
    1005             :     sal_Unicode cu;
    1006             :     sal_uInt32 cp;
    1007             :     assert(string != NULL && indexUtf16 != NULL);
    1008    26731358 :     n = *indexUtf16;
    1009             :     assert(n >= 0 && n <= string->length);
    1010    53666356 :     while (incrementCodePoints < 0) {
    1011             :         assert(n > 0);
    1012      203640 :         cu = string->buffer[--n];
    1013      203648 :         if (isLowSurrogate(cu) && n != 0 &&
    1014           8 :             isHighSurrogate(string->buffer[n - 1]))
    1015             :         {
    1016           6 :             --n;
    1017             :         }
    1018      203640 :         ++incrementCodePoints;
    1019             :     }
    1020             :     assert(n >= 0 && n < string->length);
    1021    26731358 :     cu = string->buffer[n];
    1022    26731380 :     if (isHighSurrogate(cu) && string->length - n >= 2 &&
    1023          22 :         isLowSurrogate(string->buffer[n + 1]))
    1024             :     {
    1025          22 :         cp = combineSurrogates(cu, string->buffer[n + 1]);
    1026             :     } else {
    1027    26731336 :         cp = cu;
    1028             :     }
    1029    66193180 :     while (incrementCodePoints > 0) {
    1030             :         assert(n < string->length);
    1031    12730464 :         cu = string->buffer[n++];
    1032    12730480 :         if (isHighSurrogate(cu) && n != string->length &&
    1033          16 :             isLowSurrogate(string->buffer[n]))
    1034             :         {
    1035          16 :             ++n;
    1036             :         }
    1037    12730464 :         --incrementCodePoints;
    1038             :     }
    1039             :     assert(n >= 0 && n <= string->length);
    1040    26731358 :     *indexUtf16 = n;
    1041    26731358 :     return cp;
    1042             : }
    1043             : 
    1044    35049386 : sal_Bool rtl_convertStringToUString(
    1045             :     rtl_uString ** target, char const * source, sal_Int32 length,
    1046             :     rtl_TextEncoding encoding, sal_uInt32 flags) SAL_THROW_EXTERN_C()
    1047             : {
    1048             :     sal_uInt32 info;
    1049    35049386 :     rtl_string2UString_status(target, source, length, encoding, flags, &info);
    1050    35049385 :     return (info & RTL_TEXTTOUNICODE_INFO_ERROR) == 0;
    1051             : }
    1052             : 
    1053      293354 : void rtl_uString_newReplaceFirst(
    1054             :     rtl_uString ** newStr, rtl_uString * str, rtl_uString const * from,
    1055             :     rtl_uString const * to, sal_Int32 * index) SAL_THROW_EXTERN_C()
    1056             : {
    1057             :     assert(str != 0);
    1058             :     assert(index != 0);
    1059             :     assert(*index >= 0 && *index <= str->length);
    1060             :     assert(from != 0);
    1061             :     assert(to != 0);
    1062             :     sal_Int32 i = rtl_ustr_indexOfStr_WithLength(
    1063      293354 :         str->buffer + *index, str->length - *index, from->buffer, from->length);
    1064      293354 :     if (i == -1) {
    1065      248772 :         rtl_uString_assign(newStr, str);
    1066             :     } else {
    1067             :         assert(i <= str->length - *index);
    1068       44582 :         i += *index;
    1069             :         assert(from->length <= str->length);
    1070       44582 :         if (str->length - from->length > SAL_MAX_INT32 - to->length) {
    1071           0 :             std::abort();
    1072             :         }
    1073       44582 :         sal_Int32 n = str->length - from->length + to->length;
    1074       44582 :         rtl_uString_acquire(str); // in case *newStr == str
    1075       44582 :         rtl_uString_new_WithLength(newStr, n);
    1076       44582 :         if (n != 0) {
    1077       44580 :             (*newStr)->length = n;
    1078             :             assert(i >= 0 && i < str->length);
    1079             :             memcpy(
    1080       44580 :                 (*newStr)->buffer, str->buffer, i * sizeof (sal_Unicode));
    1081             :             memcpy(
    1082       44580 :                 (*newStr)->buffer + i, to->buffer,
    1083       89160 :                 to->length * sizeof (sal_Unicode));
    1084             :             memcpy(
    1085       44580 :                 (*newStr)->buffer + i + to->length,
    1086       44580 :                 str->buffer + i + from->length,
    1087       89160 :                 (str->length - i - from->length) * sizeof (sal_Unicode));
    1088             :         }
    1089       44582 :         rtl_uString_release(str);
    1090             :     }
    1091      293354 :     *index = i;
    1092      293354 : }
    1093             : 
    1094       55387 : void rtl_uString_newReplaceFirstAsciiL(
    1095             :     rtl_uString ** newStr, rtl_uString * str, char const * from,
    1096             :     sal_Int32 fromLength, rtl_uString const * to, sal_Int32 * index)
    1097             :     SAL_THROW_EXTERN_C()
    1098             : {
    1099             :     assert(str != 0);
    1100             :     assert(index != 0);
    1101             :     assert(*index >= 0 && *index <= str->length);
    1102             :     assert(fromLength >= 0);
    1103             :     assert(to != 0);
    1104             :     sal_Int32 i = rtl_ustr_indexOfAscii_WithLength(
    1105       55387 :         str->buffer + *index, str->length - *index, from, fromLength);
    1106       55387 :     if (i == -1) {
    1107       26404 :         rtl_uString_assign(newStr, str);
    1108             :     } else {
    1109             :         assert(i <= str->length - *index);
    1110       28983 :         i += *index;
    1111             :         assert(fromLength <= str->length);
    1112       28983 :         if (str->length - fromLength > SAL_MAX_INT32 - to->length) {
    1113           0 :             std::abort();
    1114             :         }
    1115       28983 :         sal_Int32 n = str->length - fromLength + to->length;
    1116       28983 :         rtl_uString_acquire(str); // in case *newStr == str
    1117       28983 :         if (n != 0) {
    1118       28983 :             rtl_uString_new_WithLength(newStr, n);
    1119       28983 :             (*newStr)->length = n;
    1120             :             assert(i >= 0 && i < str->length);
    1121             :             memcpy(
    1122       28983 :                 (*newStr)->buffer, str->buffer, i * sizeof (sal_Unicode));
    1123             :             memcpy(
    1124       28983 :                 (*newStr)->buffer + i, to->buffer,
    1125       57966 :                 to->length * sizeof (sal_Unicode));
    1126             :             memcpy(
    1127       28983 :                 (*newStr)->buffer + i + to->length,
    1128       28983 :                 str->buffer + i + fromLength,
    1129       57966 :                 (str->length - i - fromLength) * sizeof (sal_Unicode));
    1130             :         }
    1131       28983 :         rtl_uString_release(str);
    1132             :     }
    1133       55387 :     *index = i;
    1134       55387 : }
    1135             : 
    1136       57236 : void rtl_uString_newReplaceFirstAsciiLAsciiL(
    1137             :     rtl_uString ** newStr, rtl_uString * str, char const * from,
    1138             :     sal_Int32 fromLength, char const * to, sal_Int32 toLength,
    1139             :     sal_Int32 * index) SAL_THROW_EXTERN_C()
    1140             : {
    1141             :     assert(str != 0);
    1142             :     assert(index != 0);
    1143             :     assert(*index >= 0 && *index <= str->length);
    1144             :     assert(fromLength >= 0);
    1145             :     assert(to != 0);
    1146             :     assert(toLength >= 0);
    1147             :     sal_Int32 i = rtl_ustr_indexOfAscii_WithLength(
    1148       57236 :         str->buffer + *index, str->length - *index, from, fromLength);
    1149       57236 :     if (i == -1) {
    1150       18216 :         rtl_uString_assign(newStr, str);
    1151             :     } else {
    1152             :         assert(i <= str->length - *index);
    1153       39020 :         i += *index;
    1154             :         assert(fromLength <= str->length);
    1155       39020 :         if (str->length - fromLength > SAL_MAX_INT32 - toLength) {
    1156           0 :             std::abort();
    1157             :         }
    1158       39020 :         sal_Int32 n = str->length - fromLength + toLength;
    1159       39020 :         rtl_uString_acquire(str); // in case *newStr == str
    1160       39020 :         if (n != 0) {
    1161       39020 :             rtl_uString_new_WithLength(newStr, n);
    1162       39020 :             (*newStr)->length = n;
    1163             :             assert(i >= 0 && i < str->length);
    1164             :             memcpy(
    1165       39020 :                 (*newStr)->buffer, str->buffer, i * sizeof (sal_Unicode));
    1166      217278 :             for (sal_Int32 j = 0; j != toLength; ++j) {
    1167             :                 assert(static_cast< unsigned char >(to[j]) <= 0x7F);
    1168      178258 :                 (*newStr)->buffer[i + j] = to[j];
    1169             :             }
    1170             :             memcpy(
    1171       39020 :                 (*newStr)->buffer + i + toLength,
    1172       39020 :                 str->buffer + i + fromLength,
    1173       78040 :                 (str->length - i - fromLength) * sizeof (sal_Unicode));
    1174             :         }
    1175       39020 :         rtl_uString_release(str);
    1176             :     }
    1177       57236 :     *index = i;
    1178       57236 : }
    1179             : 
    1180           0 : void rtl_uString_newReplaceAll(
    1181             :     rtl_uString ** newStr, rtl_uString * str, rtl_uString const * from,
    1182             :     rtl_uString const * to) SAL_THROW_EXTERN_C()
    1183             : {
    1184           0 :     rtl_uString_newReplaceAllFromIndex( newStr, str, from, to, 0 );
    1185           0 : }
    1186             : 
    1187      247078 : void rtl_uString_newReplaceAllFromIndex(
    1188             :     rtl_uString ** newStr, rtl_uString * str, rtl_uString const * from,
    1189             :     rtl_uString const * to, sal_Int32 fromIndex) SAL_THROW_EXTERN_C()
    1190             : {
    1191             :     assert(to != 0);
    1192             :     assert(fromIndex >= 0 && fromIndex <= str->length);
    1193      247078 :     rtl_uString_assign(newStr, str);
    1194      290388 :     for (sal_Int32 i = fromIndex;; i += to->length) {
    1195      290388 :         rtl_uString_newReplaceFirst(newStr, *newStr, from, to, &i);
    1196      290388 :         if (i == -1) {
    1197      247078 :             break;
    1198             :         }
    1199       43310 :     }
    1200      247078 : }
    1201             : 
    1202       24652 : void rtl_uString_newReplaceAllAsciiL(
    1203             :     rtl_uString ** newStr, rtl_uString * str, char const * from,
    1204             :     sal_Int32 fromLength, rtl_uString const * to) SAL_THROW_EXTERN_C()
    1205             : {
    1206             :     assert(to != 0);
    1207       24652 :     rtl_uString_assign(newStr, str);
    1208       27998 :     for (sal_Int32 i = 0;; i += to->length) {
    1209             :         rtl_uString_newReplaceFirstAsciiL(
    1210       27998 :             newStr, *newStr, from, fromLength, to, &i);
    1211       27998 :         if (i == -1) {
    1212       24652 :             break;
    1213             :         }
    1214        3346 :     }
    1215       24652 : }
    1216             : 
    1217       18204 : void rtl_uString_newReplaceAllAsciiLAsciiL(
    1218             :     rtl_uString ** newStr, rtl_uString * str, char const * from,
    1219             :     sal_Int32 fromLength, char const * to, sal_Int32 toLength)
    1220             :     SAL_THROW_EXTERN_C()
    1221             : {
    1222             :     assert(toLength >= 0);
    1223       18204 :     rtl_uString_assign(newStr, str);
    1224       55992 :     for (sal_Int32 i = 0;; i += toLength) {
    1225             :         rtl_uString_newReplaceFirstAsciiLAsciiL(
    1226       55992 :             newStr, *newStr, from, fromLength, to, toLength, &i);
    1227       55992 :         if (i == -1) {
    1228       18204 :             break;
    1229             :         }
    1230       37788 :     }
    1231       18204 : }
    1232             : 
    1233             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10