LCOV - code coverage report
Current view: top level - libreoffice/sal/rtl/source - ustring.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 384 460 83.5 %
Date: 2012-12-17 Functions: 31 35 88.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "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             : #include "rtl/tencinfo.h"
      47             : 
      48             : /* ======================================================================= */
      49             : 
      50             : /* static data to be referenced by all empty strings
      51             :  * the refCount is predefined to 1 and must never become 0 !
      52             :  */
      53             : static rtl_uString const aImplEmpty_rtl_uString =
      54             : {
      55             :     (sal_Int32) (SAL_STRING_INTERN_FLAG|SAL_STRING_STATIC_FLAG|1), /*sal_Int32    refCount; */
      56             :     0,                                               /*sal_Int32    length;   */
      57             :     { 0 }                                            /*sal_Unicode  buffer[1];*/
      58             : };
      59             : 
      60             : /* ======================================================================= */
      61             : 
      62             : #define IMPL_RTL_STRCODE            sal_Unicode
      63             : #define IMPL_RTL_USTRCODE( c )      (c)
      64             : #define IMPL_RTL_STRNAME( n )       rtl_ustr_ ## n
      65             : 
      66             : #define IMPL_RTL_STRINGNAME( n )    rtl_uString_ ## n
      67             : #define IMPL_RTL_STRINGDATA         rtl_uString
      68             : #define IMPL_RTL_EMPTYSTRING        aImplEmpty_rtl_uString
      69             : #define IMPL_RTL_INTERN
      70             : static void internRelease (rtl_uString *pThis);
      71             : 
      72             : /* ======================================================================= */
      73             : 
      74             : /* Include String/UString template code */
      75             : 
      76             : #include "strtmpl.cxx"
      77             : 
      78       79625 : sal_Int32 rtl_ustr_indexOfAscii_WithLength(
      79             :     sal_Unicode const * str, sal_Int32 len,
      80             :     char const * subStr, sal_Int32 subLen) SAL_THROW_EXTERN_C()
      81             : {
      82       79625 :     if (subLen > 0 && subLen <= len) {
      83             :         sal_Int32 i;
      84      618318 :         for (i = 0; i <= len - subLen; ++i) {
      85      572484 :             if (rtl_ustr_asciil_reverseEquals_WithLength(
      86      572484 :                     str + i, subStr, subLen))
      87             :             {
      88       25175 :                 return i;
      89             :             }
      90             :         }
      91             :     }
      92       54450 :     return -1;
      93             : }
      94             : 
      95           2 : sal_Int32 rtl_ustr_lastIndexOfAscii_WithLength(
      96             :     sal_Unicode const * str, sal_Int32 len,
      97             :     char const * subStr, sal_Int32 subLen) SAL_THROW_EXTERN_C()
      98             : {
      99           2 :     if (subLen > 0 && subLen <= len) {
     100             :         sal_Int32 i;
     101           2 :         for (i = len - subLen; i >= 0; --i) {
     102           2 :             if (rtl_ustr_asciil_reverseEquals_WithLength(
     103           2 :                     str + i, subStr, subLen))
     104             :             {
     105           2 :                 return i;
     106             :             }
     107             :         }
     108             :     }
     109           0 :     return -1;
     110             : }
     111             : 
     112           0 : sal_Int32 SAL_CALL rtl_ustr_valueOfFloat(sal_Unicode * pStr, float f)
     113             :     SAL_THROW_EXTERN_C()
     114             : {
     115           0 :     rtl_uString * pResult = NULL;
     116             :     sal_Int32 nLen;
     117             :     rtl_math_doubleToUString(
     118             :         &pResult, 0, 0, f, rtl_math_StringFormat_G,
     119             :         RTL_USTR_MAX_VALUEOFFLOAT - RTL_CONSTASCII_LENGTH("-x.E-xxx"), '.', 0,
     120           0 :         0, sal_True);
     121           0 :     nLen = pResult->length;
     122             :     OSL_ASSERT(nLen < RTL_USTR_MAX_VALUEOFFLOAT);
     123           0 :     memcpy(pStr, pResult->buffer, (nLen + 1) * sizeof(sal_Unicode));
     124           0 :     rtl_uString_release(pResult);
     125           0 :     return nLen;
     126             : }
     127             : 
     128        8340 : sal_Int32 SAL_CALL rtl_ustr_valueOfDouble(sal_Unicode * pStr, double d)
     129             :     SAL_THROW_EXTERN_C()
     130             : {
     131        8340 :     rtl_uString * pResult = NULL;
     132             :     sal_Int32 nLen;
     133             :     rtl_math_doubleToUString(
     134             :         &pResult, 0, 0, d, rtl_math_StringFormat_G,
     135             :         RTL_USTR_MAX_VALUEOFDOUBLE - RTL_CONSTASCII_LENGTH("-x.E-xxx"), '.', 0,
     136        8340 :         0, sal_True);
     137        8340 :     nLen = pResult->length;
     138             :     OSL_ASSERT(nLen < RTL_USTR_MAX_VALUEOFDOUBLE);
     139        8340 :     memcpy(pStr, pResult->buffer, (nLen + 1) * sizeof(sal_Unicode));
     140        8340 :     rtl_uString_release(pResult);
     141        8340 :     return nLen;
     142             : }
     143             : 
     144           0 : float SAL_CALL rtl_ustr_toFloat(sal_Unicode const * pStr) SAL_THROW_EXTERN_C()
     145             : {
     146             :     return (float) rtl_math_uStringToDouble(pStr,
     147           0 :                                             pStr + rtl_ustr_getLength(pStr),
     148           0 :                                             '.', 0, 0, 0);
     149             : }
     150             : 
     151        2144 : double SAL_CALL rtl_ustr_toDouble(sal_Unicode const * pStr) SAL_THROW_EXTERN_C()
     152             : {
     153        2144 :     return rtl_math_uStringToDouble(pStr, pStr + rtl_ustr_getLength(pStr), '.',
     154        2144 :                                     0, 0, 0);
     155             : }
     156             : 
     157             : /* ======================================================================= */
     158             : 
     159       21604 : sal_Int32 SAL_CALL rtl_ustr_ascii_compare( const sal_Unicode* pStr1,
     160             :                                            const sal_Char* pStr2 )
     161             :     SAL_THROW_EXTERN_C()
     162             : {
     163             :     sal_Int32 nRet;
     164      122886 :     while ( ((nRet = ((sal_Int32)(*pStr1))-
     165             :                      ((sal_Int32)((unsigned char)(*pStr2)))) == 0) &&
     166             :             *pStr2 )
     167             :     {
     168             :         /* Check ASCII range */
     169             :         SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
     170             :                     "rtl_ustr_ascii_compare - Found char > 127" );
     171       79678 :         pStr1++;
     172       79678 :         pStr2++;
     173             :     }
     174             : 
     175       21604 :     return nRet;
     176             : }
     177             : 
     178             : /* ----------------------------------------------------------------------- */
     179             : 
     180     7660112 : sal_Int32 SAL_CALL rtl_ustr_ascii_compare_WithLength( const sal_Unicode* pStr1,
     181             :                                                       sal_Int32 nStr1Len,
     182             :                                                       const sal_Char* pStr2 )
     183             :     SAL_THROW_EXTERN_C()
     184             : {
     185     7660112 :     sal_Int32 nRet = 0;
     186    25764633 :     while( ((nRet = (nStr1Len ? (sal_Int32)(*pStr1) : 0)-
     187             :                     ((sal_Int32)((unsigned char)(*pStr2)))) == 0) &&
     188             :            nStr1Len && *pStr2 )
     189             :     {
     190             :         /* Check ASCII range */
     191             :         SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
     192             :                     "rtl_ustr_ascii_compare_WithLength - Found char > 127" );
     193    10444409 :         pStr1++;
     194    10444409 :         pStr2++;
     195    10444409 :         nStr1Len--;
     196             :     }
     197             : 
     198     7660112 :     return nRet;
     199             : }
     200             : 
     201             : /* ----------------------------------------------------------------------- */
     202             : 
     203     3364946 : sal_Int32 SAL_CALL rtl_ustr_ascii_shortenedCompare_WithLength( const sal_Unicode* pStr1,
     204             :                                                                sal_Int32 nStr1Len,
     205             :                                                                const sal_Char* pStr2,
     206             :                                                                sal_Int32 nShortenedLength )
     207             :     SAL_THROW_EXTERN_C()
     208             : {
     209     3364946 :     const sal_Unicode*  pStr1End = pStr1 + nStr1Len;
     210             :     sal_Int32           nRet;
     211    15439728 :     while ( (nShortenedLength > 0) &&
     212             :             (pStr1 < pStr1End) && *pStr2 )
     213             :     {
     214             :         /* Check ASCII range */
     215             :         SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
     216             :                     "rtl_ustr_ascii_shortenedCompare_WithLength - Found char > 127" );
     217             : 
     218             :         nRet = ((sal_Int32)*pStr1)-
     219    10494525 :                ((sal_Int32)(unsigned char)*pStr2);
     220    10494525 :         if ( nRet != 0 )
     221     1784689 :             return nRet;
     222             : 
     223     8709836 :         nShortenedLength--;
     224     8709836 :         pStr1++;
     225     8709836 :         pStr2++;
     226             :     }
     227             : 
     228     1580257 :     if ( nShortenedLength <= 0 )
     229     1566362 :         return 0;
     230             : 
     231       13895 :     if ( *pStr2 )
     232             :     {
     233             :         OSL_ENSURE( pStr1 == pStr1End, "pStr1 == pStr1End failed" );
     234             :         // first is a substring of the second string => less (negative value)
     235       13895 :         nRet = -1;
     236             :     }
     237             :     else
     238             :     {
     239             :         // greater or equal
     240           0 :         nRet = pStr1End - pStr1;
     241             :     }
     242             : 
     243       13895 :     return nRet;
     244             : }
     245             : 
     246             : /* ----------------------------------------------------------------------- */
     247             : 
     248       67661 : sal_Int32 SAL_CALL rtl_ustr_asciil_reverseCompare_WithLength( const sal_Unicode* pStr1,
     249             :                                                               sal_Int32 nStr1Len,
     250             :                                                               const sal_Char* pStr2,
     251             :                                                               sal_Int32 nStr2Len )
     252             :     SAL_THROW_EXTERN_C()
     253             : {
     254       67661 :     const sal_Unicode*  pStr1Run = pStr1+nStr1Len;
     255       67661 :     const sal_Char*     pStr2Run = pStr2+nStr2Len;
     256             :     sal_Int32           nRet;
     257      245921 :     while ( (pStr1 < pStr1Run) && (pStr2 < pStr2Run) )
     258             :     {
     259             :         /* Check ASCII range */
     260             :         SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
     261             :                     "rtl_ustr_asciil_reverseCompare_WithLength - Found char > 127" );
     262      176592 :         pStr1Run--;
     263      176592 :         pStr2Run--;
     264      176592 :         nRet = ((sal_Int32)*pStr1Run)-((sal_Int32)*pStr2Run);
     265      176592 :         if ( nRet )
     266       65993 :             return nRet;
     267             :     }
     268             : 
     269        1668 :     return nStr1Len - nStr2Len;
     270             : }
     271             : 
     272             : /* ----------------------------------------------------------------------- */
     273             : 
     274     4139382 : sal_Bool SAL_CALL rtl_ustr_asciil_reverseEquals_WithLength( const sal_Unicode* pStr1,
     275             :                                                               const sal_Char* pStr2,
     276             :                                                               sal_Int32 nStrLen )
     277             :     SAL_THROW_EXTERN_C()
     278             : {
     279     4139382 :     const sal_Unicode*  pStr1Run = pStr1+nStrLen;
     280     4139382 :     const sal_Char*     pStr2Run = pStr2+nStrLen;
     281    37610003 :     while ( pStr1 < pStr1Run )
     282             :     {
     283             :         /* Check ASCII range */
     284             :         SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
     285             :                     "rtl_ustr_asciil_reverseEquals_WithLength - Found char > 127" );
     286    30543410 :         pStr1Run--;
     287    30543410 :         pStr2Run--;
     288    30543410 :         if( *pStr1Run != (sal_Unicode)*pStr2Run )
     289     1212171 :             return sal_False;
     290             :     }
     291             : 
     292     2927211 :     return sal_True;
     293             : }
     294             : 
     295             : /* ----------------------------------------------------------------------- */
     296             : 
     297           0 : sal_Int32 SAL_CALL rtl_ustr_ascii_compareIgnoreAsciiCase( const sal_Unicode* pStr1,
     298             :                                                           const sal_Char* pStr2 )
     299             :     SAL_THROW_EXTERN_C()
     300             : {
     301             :     sal_Int32   nRet;
     302             :     sal_Int32   c1;
     303             :     sal_Int32   c2;
     304           0 :     do
     305             :     {
     306             :         /* Check ASCII range */
     307             :         SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
     308             :                     "rtl_ustr_ascii_compareIgnoreAsciiCase - Found char > 127" );
     309             :         /* If character between 'A' and 'Z', than convert it to lowercase */
     310           0 :         c1 = (sal_Int32)*pStr1;
     311           0 :         c2 = (sal_Int32)((unsigned char)*pStr2);
     312           0 :         if ( (c1 >= 65) && (c1 <= 90) )
     313           0 :             c1 += 32;
     314           0 :         if ( (c2 >= 65) && (c2 <= 90) )
     315           0 :             c2 += 32;
     316           0 :         nRet = c1-c2;
     317           0 :         if ( nRet != 0 )
     318           0 :             return nRet;
     319             : 
     320           0 :         pStr1++;
     321           0 :         pStr2++;
     322             :     }
     323             :     while ( c2 );
     324             : 
     325           0 :     return 0;
     326             : }
     327             : 
     328             : /* ----------------------------------------------------------------------- */
     329             : 
     330     1805996 : sal_Int32 SAL_CALL rtl_ustr_ascii_compareIgnoreAsciiCase_WithLength( const sal_Unicode* pStr1,
     331             :                                                                      sal_Int32 nStr1Len,
     332             :                                                                      const sal_Char* pStr2 )
     333             :     SAL_THROW_EXTERN_C()
     334             : {
     335             :     sal_Int32   nRet;
     336             :     sal_Int32   c1;
     337             :     sal_Int32   c2;
     338     1332579 :     do
     339             :     {
     340             :         /* Check ASCII range */
     341             :         SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
     342             :                     "rtl_ustr_ascii_compareIgnoreAsciiCase_WithLength - Found char > 127" );
     343     1805996 :         if ( !nStr1Len )
     344      145186 :             return *pStr2 == '\0' ? 0 : -1;
     345             : 
     346             :         /* If character between 'A' and 'Z', than convert it to lowercase */
     347     1660810 :         c1 = (sal_Int32)*pStr1;
     348     1660810 :         c2 = (sal_Int32)((unsigned char)*pStr2);
     349     1660810 :         if ( (c1 >= 65) && (c1 <= 90) )
     350      310712 :             c1 += 32;
     351     1660810 :         if ( (c2 >= 65) && (c2 <= 90) )
     352       68314 :             c2 += 32;
     353     1660810 :         nRet = c1-c2;
     354     1660810 :         if ( nRet != 0 )
     355      328231 :             return nRet;
     356             : 
     357     1332579 :         pStr1++;
     358     1332579 :         pStr2++;
     359     1332579 :         nStr1Len--;
     360             :     }
     361             :     while( c2 );
     362             : 
     363           0 :     return 0;
     364             : }
     365             : 
     366      192373 : sal_Int32 rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
     367             :     sal_Unicode const * first, sal_Int32 firstLen,
     368             :     char const * second, sal_Int32 secondLen) SAL_THROW_EXTERN_C()
     369             : {
     370             :     sal_Int32 i;
     371      192373 :     sal_Int32 len = firstLen < secondLen ? firstLen : secondLen;
     372      241207 :     for (i = 0; i < len; ++i) {
     373             :         /* Check ASCII range */
     374             :         SAL_WARN_IF( ((unsigned char)*second) > 127, "rtl.string",
     375             :                     "rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths - Found char > 127" );
     376      229253 :         sal_Int32 c1 = *first++;
     377      229253 :         sal_Int32 c2 = (unsigned char) *second++;
     378             :         sal_Int32 d;
     379      229253 :         if (c1 >= 65 && c1 <= 90) {
     380       22632 :             c1 += 32;
     381             :         }
     382      229253 :         if (c2 >= 65 && c2 <= 90) {
     383          12 :             c2 += 32;
     384             :         }
     385      229253 :         d = c1 - c2;
     386      229253 :         if (d != 0) {
     387      180419 :             return d;
     388             :         }
     389             :     }
     390       11954 :     return firstLen - secondLen;
     391             : }
     392             : 
     393             : /* ----------------------------------------------------------------------- */
     394             : 
     395         920 : sal_Int32 SAL_CALL rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( const sal_Unicode* pStr1,
     396             :                                                                               sal_Int32 nStr1Len,
     397             :                                                                               const sal_Char* pStr2,
     398             :                                                                               sal_Int32 nShortenedLength )
     399             :     SAL_THROW_EXTERN_C()
     400             : {
     401         920 :     const sal_Unicode*  pStr1End = pStr1 + nStr1Len;
     402             :     sal_Int32           nRet;
     403             :     sal_Int32           c1;
     404             :     sal_Int32           c2;
     405       10968 :     while ( (nShortenedLength > 0) &&
     406             :             (pStr1 < pStr1End) && *pStr2 )
     407             :     {
     408             :         /* Check ASCII range */
     409             :         SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
     410             :                     "rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength - Found char > 127" );
     411             : 
     412             :         /* If character between 'A' and 'Z', than convert it to lowercase */
     413        9693 :         c1 = (sal_Int32)*pStr1;
     414        9693 :         c2 = (sal_Int32)((unsigned char)*pStr2);
     415        9693 :         if ( (c1 >= 65) && (c1 <= 90) )
     416          34 :             c1 += 32;
     417        9693 :         if ( (c2 >= 65) && (c2 <= 90) )
     418          52 :             c2 += 32;
     419        9693 :         nRet = c1-c2;
     420        9693 :         if ( nRet != 0 )
     421         565 :             return nRet;
     422             : 
     423        9128 :         nShortenedLength--;
     424        9128 :         pStr1++;
     425        9128 :         pStr2++;
     426             :     }
     427             : 
     428         355 :     if ( nShortenedLength <= 0 )
     429         343 :         return 0;
     430             : 
     431          12 :     if ( *pStr2 )
     432             :     {
     433             :         OSL_ENSURE( pStr1 == pStr1End, "pStr1 == pStr1End failed" );
     434             :         // first is a substring of the second string => less (negative value)
     435          12 :         nRet = -1;
     436             :     }
     437             :     else
     438             :     {
     439             :         // greater or equal
     440           0 :         nRet = pStr1End - pStr1;
     441             :     }
     442             : 
     443          12 :     return nRet;
     444             : }
     445             : 
     446             : /* ----------------------------------------------------------------------- */
     447             : 
     448     1179023 : void SAL_CALL rtl_uString_newFromAscii( rtl_uString** ppThis,
     449             :                                         const sal_Char* pCharStr )
     450             :     SAL_THROW_EXTERN_C()
     451             : {
     452             :     sal_Int32 nLen;
     453             : 
     454     1179023 :     if ( pCharStr )
     455             :     {
     456     1179021 :         const sal_Char* pTempStr = pCharStr;
     457    17414068 :         while( *pTempStr )
     458    15056026 :             pTempStr++;
     459     1179021 :         nLen = pTempStr-pCharStr;
     460             :     }
     461             :     else
     462           2 :         nLen = 0;
     463             : 
     464     1179023 :     if ( !nLen )
     465             :     {
     466       15562 :         IMPL_RTL_STRINGNAME( new )( ppThis );
     467     1194585 :         return;
     468             :     }
     469             : 
     470     1163461 :     if ( *ppThis )
     471        2047 :         IMPL_RTL_STRINGNAME( release )( *ppThis );
     472             : 
     473     1163461 :     *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
     474             :     OSL_ASSERT(*ppThis != NULL);
     475     1163461 :     if ( (*ppThis) )
     476             :     {
     477     1163461 :         IMPL_RTL_STRCODE* pBuffer = (*ppThis)->buffer;
     478    15056026 :         do
     479             :         {
     480             :             /* Check ASCII range */
     481             :             SAL_WARN_IF( ((unsigned char)*pCharStr) > 127, "rtl.string",
     482             :                         "rtl_uString_newFromAscii - Found char > 127" );
     483             : 
     484    15056026 :             *pBuffer = *pCharStr;
     485    15056026 :             pBuffer++;
     486    15056026 :             pCharStr++;
     487             :         }
     488             :         while ( *pCharStr );
     489             :     }
     490             : 
     491             :     RTL_LOG_STRING_NEW( *ppThis );
     492             : }
     493             : 
     494        6952 : void SAL_CALL rtl_uString_newFromCodePoints(
     495             :     rtl_uString ** newString, sal_uInt32 const * codePoints,
     496             :     sal_Int32 codePointCount) SAL_THROW_EXTERN_C()
     497             : {
     498             :     sal_Int32 n;
     499             :     sal_Int32 i;
     500             :     sal_Unicode * p;
     501             :     OSL_ASSERT(
     502             :         newString != NULL &&
     503             :         (codePoints != NULL || codePointCount == 0) &&
     504             :         codePointCount >= 0);
     505        6952 :     if (codePointCount == 0) {
     506        6690 :         rtl_uString_new(newString);
     507        6690 :         return;
     508             :     }
     509         262 :     if (*newString != NULL) {
     510           0 :         rtl_uString_release(*newString);
     511             :     }
     512         262 :     n = codePointCount;
     513         526 :     for (i = 0; i < codePointCount; ++i) {
     514             :         OSL_ASSERT(codePoints[i] <= 0x10FFFF);
     515         264 :         if (codePoints[i] >= 0x10000) {
     516           4 :             ++n;
     517             :         }
     518             :     }
     519             :     /* Builds on the assumption that sal_Int32 uses 32 bit two's complement
     520             :        representation with wrap around (the necessary number of UTF-16 code
     521             :        units will be no larger than 2 * SAL_MAX_INT32, represented as
     522             :        sal_Int32 -2): */
     523         262 :     if (n < 0) {
     524           0 :         *newString = NULL;
     525           0 :         return;
     526             :     }
     527         262 :     *newString = rtl_uString_ImplAlloc(n);
     528         262 :     if (*newString == NULL) {
     529           0 :         return;
     530             :     }
     531         262 :     p = (*newString)->buffer;
     532         526 :     for (i = 0; i < codePointCount; ++i) {
     533         264 :         sal_uInt32 c = codePoints[i];
     534         264 :         if (c < 0x10000) {
     535         260 :             *p++ = (sal_Unicode) c;
     536             :         } else {
     537           4 :             c -= 0x10000;
     538           4 :             *p++ = (sal_Unicode) ((c >> 10) | SAL_RTL_FIRST_HIGH_SURROGATE);
     539           4 :             *p++ = (sal_Unicode) ((c & 0x3FF) | SAL_RTL_FIRST_LOW_SURROGATE);
     540             :         }
     541             :     }
     542             :     RTL_LOG_STRING_NEW( *newString );
     543             : }
     544             : 
     545             : /* ======================================================================= */
     546             : 
     547     7085486 : static int rtl_ImplGetFastUTF8UnicodeLen( const sal_Char* pStr, sal_Int32 nLen )
     548             : {
     549             :     int             n;
     550             :     sal_uChar       c;
     551             :     const sal_Char* pEndStr;
     552             : 
     553     7085486 :     n = 0;
     554     7085486 :     pEndStr  = pStr+nLen;
     555   115692121 :     while ( pStr < pEndStr )
     556             :     {
     557   101521149 :         c = (sal_uChar)*pStr;
     558             : 
     559   101521149 :         if ( !(c & 0x80) )
     560   101257579 :             pStr++;
     561      263570 :         else if ( (c & 0xE0) == 0xC0 )
     562       61630 :             pStr += 2;
     563      201940 :         else if ( (c & 0xF0) == 0xE0 )
     564      201940 :             pStr += 3;
     565           0 :         else if ( (c & 0xF8) == 0xF0 )
     566           0 :             pStr += 4;
     567           0 :         else if ( (c & 0xFC) == 0xF8 )
     568           0 :             pStr += 5;
     569           0 :         else if ( (c & 0xFE) == 0xFC )
     570           0 :             pStr += 6;
     571             :         else
     572           0 :             pStr++;
     573             : 
     574   101521149 :         n++;
     575             :     }
     576             : 
     577     7085486 :     return n;
     578             : }
     579             : 
     580             : /* ----------------------------------------------------------------------- */
     581             : 
     582    10731153 : static void rtl_string2UString_status( rtl_uString** ppThis,
     583             :                                        const sal_Char* pStr,
     584             :                                        sal_Int32 nLen,
     585             :                                        rtl_TextEncoding eTextEncoding,
     586             :                                        sal_uInt32 nCvtFlags,
     587             :                                        sal_uInt32 *pInfo )
     588             : {
     589             :     OSL_ENSURE(nLen == 0 || rtl_isOctetTextEncoding(eTextEncoding),
     590             :                "rtl_string2UString_status() - Wrong TextEncoding" );
     591             : 
     592    10731153 :     if ( !nLen )
     593             :     {
     594      193757 :         rtl_uString_new( ppThis );
     595      193757 :         if (pInfo != NULL) {
     596      107525 :             *pInfo = 0;
     597             :         }
     598             :     }
     599             :     else
     600             :     {
     601    10537396 :         if ( *ppThis )
     602       16413 :             IMPL_RTL_STRINGNAME( release )( *ppThis );
     603             : 
     604             :         /* Optimization for US-ASCII */
     605    10537396 :         if ( eTextEncoding == RTL_TEXTENCODING_ASCII_US )
     606             :         {
     607             :             IMPL_RTL_STRCODE* pBuffer;
     608     3417464 :             *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
     609     3417464 :             if (*ppThis == NULL) {
     610           0 :                 if (pInfo != NULL) {
     611             :                     *pInfo = RTL_TEXTTOUNICODE_INFO_ERROR |
     612           0 :                         RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
     613             :                 }
     614           0 :                 return;
     615             :             }
     616     3417464 :             pBuffer = (*ppThis)->buffer;
     617    44197417 :             do
     618             :             {
     619             :                 /* Check ASCII range */
     620             :                 SAL_WARN_IF( ((unsigned char)*pStr) > 127, "rtl.string",
     621             :                             "rtl_string2UString_status() - Found char > 127 and RTL_TEXTENCODING_ASCII_US is specified" );
     622             : 
     623    44197417 :                 *pBuffer = *pStr;
     624    44197417 :                 pBuffer++;
     625    44197417 :                 pStr++;
     626    44197417 :                 nLen--;
     627             :             }
     628             :             while ( nLen );
     629     3417464 :             if (pInfo != NULL) {
     630           0 :                 *pInfo = 0;
     631             :             }
     632             :         }
     633             :         else
     634             :         {
     635             :             rtl_uString*                pTemp;
     636     7119932 :             rtl_uString*                pTemp2 = NULL;
     637             :             rtl_TextToUnicodeConverter  hConverter;
     638             :             sal_uInt32                  nInfo;
     639             :             sal_Size                    nSrcBytes;
     640             :             sal_Size                    nDestChars;
     641             :             sal_Size                    nNewLen;
     642             : 
     643             :             /* Optimization for UTF-8 - we try to calculate the exact length */
     644             :             /* For all other encoding we try the maximum - and reallocate
     645             :                the buffer if needed */
     646     7119932 :             if ( eTextEncoding == RTL_TEXTENCODING_UTF8 )
     647             :             {
     648     7085486 :                 nNewLen = rtl_ImplGetFastUTF8UnicodeLen( pStr, nLen );
     649             :                 /* Includes the string only ASCII, then we could copy
     650             :                    the buffer faster */
     651     7085486 :                 if ( nNewLen == (sal_Size)nLen )
     652             :                 {
     653             :                     IMPL_RTL_STRCODE* pBuffer;
     654     7017239 :                     *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
     655     7017239 :                     if (*ppThis == NULL)
     656             :                     {
     657           0 :                         if (pInfo != NULL) {
     658             :                             *pInfo = RTL_TEXTTOUNICODE_INFO_ERROR |
     659           0 :                                 RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
     660             :                         }
     661             :                         return;
     662             :                     }
     663     7017239 :                     pBuffer = (*ppThis)->buffer;
     664    97520964 :                     do
     665             :                     {
     666             :                         /* Check ASCII range */
     667             :                         SAL_WARN_IF( ((unsigned char)*pStr) > 127, "rtl.string",
     668             :                                     "rtl_string2UString_status() - UTF8 test encoding is wrong" );
     669             : 
     670    97520964 :                         *pBuffer = *pStr;
     671    97520964 :                         pBuffer++;
     672    97520964 :                         pStr++;
     673    97520964 :                         nLen--;
     674             :                     }
     675             :                     while ( nLen );
     676     7017239 :                     if (pInfo != NULL) {
     677     5151897 :                         *pInfo = 0;
     678             :                     }
     679             :                     RTL_LOG_STRING_NEW( *ppThis );
     680             :                     return;
     681             :                 }
     682             :             }
     683             :             else
     684       34446 :                 nNewLen = nLen;
     685             : 
     686      102693 :             nCvtFlags |= RTL_TEXTTOUNICODE_FLAGS_FLUSH;
     687      102693 :             hConverter = rtl_createTextToUnicodeConverter( eTextEncoding );
     688             : 
     689      102693 :             pTemp = IMPL_RTL_STRINGNAME( ImplAlloc )( nNewLen );
     690      102693 :             if (pTemp == NULL) {
     691           0 :                 if (pInfo != NULL) {
     692             :                     *pInfo = RTL_TEXTTOUNICODE_INFO_ERROR |
     693           0 :                         RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
     694             :                 }
     695             :                 return;
     696             :             }
     697             :             nDestChars = rtl_convertTextToUnicode( hConverter, 0,
     698             :                                                    pStr, nLen,
     699             :                                                    pTemp->buffer, nNewLen,
     700             :                                                    nCvtFlags,
     701      102693 :                                                    &nInfo, &nSrcBytes );
     702             : 
     703             :             /* Buffer not big enough, try again with enough space */
     704             :             /* Shouldn't be the case, but if we get textencoding which
     705             :                could results in more unicode characters we have this
     706             :                code here. Could be the case for apple encodings */
     707      205498 :             while ( nInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL )
     708             :             {
     709         112 :                 rtl_freeMemory( pTemp );
     710         112 :                 nNewLen += 8;
     711         112 :                 pTemp = IMPL_RTL_STRINGNAME( ImplAlloc )( nNewLen );
     712         112 :                 if (pTemp == NULL) {
     713           0 :                     if (pInfo != NULL) {
     714             :                         *pInfo = RTL_TEXTTOUNICODE_INFO_ERROR |
     715           0 :                             RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
     716             :                     }
     717             :                     return;
     718             :                 }
     719             :                 nDestChars = rtl_convertTextToUnicode( hConverter, 0,
     720             :                                                        pStr, nLen,
     721             :                                                        pTemp->buffer, nNewLen,
     722             :                                                        nCvtFlags,
     723         112 :                                                        &nInfo, &nSrcBytes );
     724             :             }
     725             : 
     726      102693 :             if (pInfo)
     727       61508 :                 *pInfo = nInfo;
     728             : 
     729             :             /* Set the buffer to the correct size or if there is too
     730             :                much overhead, reallocate to the correct size */
     731      102693 :             if ( nNewLen > nDestChars+8 )
     732             :             {
     733           0 :                 pTemp2 = IMPL_RTL_STRINGNAME( ImplAlloc )( nDestChars );
     734             :             }
     735      102693 :             if (pTemp2 != NULL)
     736             :             {
     737           0 :                 rtl_str_ImplCopy(pTemp2->buffer, pTemp->buffer, nDestChars);
     738           0 :                 rtl_freeMemory(pTemp);
     739           0 :                 pTemp = pTemp2;
     740             :             }
     741             :             else
     742             :             {
     743      102693 :                 pTemp->length = nDestChars;
     744      102693 :                 pTemp->buffer[nDestChars] = 0;
     745             :             }
     746             : 
     747      102693 :             rtl_destroyTextToUnicodeConverter( hConverter );
     748      102693 :             *ppThis = pTemp;
     749             : 
     750             :             /* Results the conversion in an empty buffer -
     751             :                create an empty string */
     752      102693 :             if ( pTemp && !nDestChars )
     753           2 :                 rtl_uString_new( ppThis );
     754             :         }
     755             :     }
     756             :     RTL_LOG_STRING_NEW( *ppThis );
     757             : }
     758             : 
     759     5377640 : void SAL_CALL rtl_string2UString( rtl_uString** ppThis,
     760             :                                   const sal_Char* pStr,
     761             :                                   sal_Int32 nLen,
     762             :                                   rtl_TextEncoding eTextEncoding,
     763             :                                   sal_uInt32 nCvtFlags ) SAL_THROW_EXTERN_C()
     764             : {
     765             :     rtl_string2UString_status( ppThis, pStr, nLen, eTextEncoding,
     766     5377640 :                                nCvtFlags, NULL );
     767     5377640 : }
     768             : 
     769             : /* ----------------------------------------------------------------------- */
     770             : 
     771             : enum StrLifecycle {
     772             :     CANNOT_RETURN,
     773             :     CAN_RETURN = 1
     774             : };
     775             : 
     776             : static oslMutex
     777       99056 : getInternMutex()
     778             : {
     779             :     static oslMutex pPoolGuard = NULL;
     780       99056 :     if( !pPoolGuard )
     781             :     {
     782             :         oslMutex pGlobalGuard;
     783          74 :         pGlobalGuard = *osl_getGlobalMutex();
     784          74 :         osl_acquireMutex( pGlobalGuard );
     785          74 :         if( !pPoolGuard )
     786             :         {
     787          74 :             oslMutex p = osl_createMutex();
     788             :             OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
     789          74 :             pPoolGuard = p;
     790             :         }
     791          74 :         osl_releaseMutex( pGlobalGuard );
     792             :     }
     793             :     else
     794             :     {
     795             :         OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
     796             :     }
     797             : 
     798       99056 :     return pPoolGuard;
     799             : }
     800             : 
     801             : /* returns true if we found a dup in the pool */
     802       66987 : static void rtl_ustring_intern_internal( rtl_uString ** newStr,
     803             :                                          rtl_uString  * str,
     804             :                                          StrLifecycle   can_return )
     805             : {
     806             :     oslMutex pPoolMutex;
     807             : 
     808       66987 :     pPoolMutex = getInternMutex();
     809             : 
     810       66987 :     osl_acquireMutex( pPoolMutex );
     811             : 
     812       66987 :     *newStr = rtl_str_hash_intern (str, can_return);
     813             : 
     814       66987 :     osl_releaseMutex( pPoolMutex );
     815             : 
     816       66987 :     if( can_return && *newStr != str )
     817             :     { /* we dupped, then found a match */
     818       13183 :         rtl_freeMemory( str );
     819             :     }
     820       66987 : }
     821             : 
     822       26254 : void SAL_CALL rtl_uString_intern( rtl_uString ** newStr,
     823             :                                   rtl_uString  * str) SAL_THROW_EXTERN_C()
     824             : {
     825       26254 :     if (SAL_STRING_IS_INTERN(str))
     826             :     {
     827         344 :         IMPL_RTL_AQUIRE( str );
     828         344 :         *newStr = str;
     829             :     }
     830             :     else
     831             :     {
     832       25910 :         rtl_uString *pOrg = *newStr;
     833       25910 :         *newStr = NULL;
     834       25910 :         rtl_ustring_intern_internal( newStr, str, CANNOT_RETURN );
     835       25910 :         if (pOrg)
     836           0 :             rtl_uString_release (pOrg);
     837             :     }
     838       26254 : }
     839             : 
     840       32583 : static int rtl_canGuessUOutputLength( int len, rtl_TextEncoding eTextEncoding )
     841             : {
     842             :     // FIXME: Maybe we should use a bit flag in the higher bits of the
     843             :     // eTextEncoding value itself to determine the encoding type.  But if we
     844             :     // do, be sure to mask the value in certain places that expect the values
     845             :     // to be numbered serially from 0 and up.  One such place is
     846             :     // Impl_getTextEncodingData().
     847             : 
     848       32583 :     switch ( eTextEncoding )
     849             :     {
     850             :         // 1 to 1 (with no zero elements)
     851             :         case RTL_TEXTENCODING_IBM_437:
     852             :         case RTL_TEXTENCODING_IBM_850:
     853             :         case RTL_TEXTENCODING_IBM_860:
     854             :         case RTL_TEXTENCODING_IBM_861:
     855             :         case RTL_TEXTENCODING_IBM_863:
     856             :         case RTL_TEXTENCODING_IBM_865:
     857           0 :             return len;
     858             :         break;
     859             :     }
     860       32583 :     return 0;
     861             : }
     862             : 
     863       41077 : void SAL_CALL rtl_uString_internConvert( rtl_uString   ** newStr,
     864             :                                          const sal_Char * str,
     865             :                                          sal_Int32        len,
     866             :                                          rtl_TextEncoding eTextEncoding,
     867             :                                          sal_uInt32       convertFlags,
     868             :                                          sal_uInt32     * pInfo )
     869             :     SAL_THROW_EXTERN_C()
     870             : {
     871             :     rtl_uString *scratch;
     872             : 
     873       41077 :     if (*newStr)
     874             :     {
     875           0 :         rtl_uString_release (*newStr);
     876           0 :         *newStr = NULL;
     877             :     }
     878             : 
     879       41077 :     if ( len < 256 )
     880             :     { // try various optimisations
     881             :         sal_Int32 ulen;
     882       41077 :         if ( len < 0 )
     883           0 :             len = strlen( str );
     884       41077 :         if ( eTextEncoding == RTL_TEXTENCODING_ASCII_US )
     885             :         {
     886             :             int i;
     887             :             rtl_uString *pScratch;
     888             :             pScratch = static_cast< rtl_uString * >(
     889        8494 :                 alloca(sizeof (rtl_uString) + len * sizeof (IMPL_RTL_STRCODE)));
     890      246446 :             for (i = 0; i < len; i++)
     891             :             {
     892             :                 /* Check ASCII range */
     893             :                 SAL_WARN_IF( ((unsigned char)str[i]) > 127, "rtl.string",
     894             :                             "rtl_ustring_internConvert() - Found char > 127 and RTL_TEXTENCODING_ASCII_US is specified" );
     895      237952 :                 pScratch->buffer[i] = str[i];
     896             :             }
     897        8494 :             pScratch->length = len;
     898        8494 :             rtl_ustring_intern_internal( newStr, pScratch, CANNOT_RETURN );
     899             :             return;
     900             :         }
     901       32583 :         else if ( (ulen = rtl_canGuessUOutputLength(len, eTextEncoding)) != 0 )
     902             :         {
     903             :             rtl_uString *pScratch;
     904             :             rtl_TextToUnicodeConverter hConverter;
     905             :             sal_Size nSrcBytes;
     906             :             sal_uInt32 nInfo;
     907             : 
     908             :             pScratch = static_cast< rtl_uString * >(
     909           0 :                 alloca(
     910           0 :                     sizeof (rtl_uString) + ulen * sizeof (IMPL_RTL_STRCODE)));
     911             : 
     912           0 :             hConverter = rtl_createTextToUnicodeConverter( eTextEncoding );
     913             :             rtl_convertTextToUnicode(
     914           0 :                 hConverter, 0, str, len, pScratch->buffer, ulen, convertFlags, &nInfo, &nSrcBytes );
     915           0 :             rtl_destroyTextToUnicodeConverter( hConverter );
     916             : 
     917           0 :             if (pInfo)
     918           0 :                 *pInfo = nInfo;
     919             : 
     920           0 :             pScratch->length = ulen;
     921           0 :             rtl_ustring_intern_internal( newStr, pScratch, CANNOT_RETURN );
     922             :             return;
     923             :         }
     924             : 
     925             :         /* FIXME: we want a nice UTF-8 / alloca shortcut here */
     926             :     }
     927             : 
     928       32583 :     scratch = NULL;
     929             :     rtl_string2UString_status( &scratch, str, len, eTextEncoding, convertFlags,
     930       32583 :                                pInfo );
     931       32583 :     if (!scratch) {
     932             :         return;
     933             :     }
     934       32583 :     rtl_ustring_intern_internal( newStr, scratch, CAN_RETURN );
     935             : }
     936             : 
     937             : static void
     938      286807 : internRelease (rtl_uString *pThis)
     939             : {
     940             :     oslMutex pPoolMutex;
     941             : 
     942      286807 :     rtl_uString *pFree = NULL;
     943      286807 :     if ( SAL_STRING_REFCOUNT(
     944             :              osl_atomic_decrement( &(pThis->refCount) ) ) == 0)
     945             :     {
     946       32069 :         pPoolMutex = getInternMutex();
     947       32069 :         osl_acquireMutex( pPoolMutex );
     948             : 
     949       32069 :         rtl_str_hash_remove (pThis);
     950             : 
     951             :         /* May have been separately acquired */
     952       32069 :         if ( SAL_STRING_REFCOUNT(
     953             :                  osl_atomic_increment( &(pThis->refCount) ) ) == 1 )
     954             :         {
     955             :             /* we got the last ref */
     956       32069 :             pFree = pThis;
     957             :         }
     958             :         else /* very unusual */
     959             :         {
     960           0 :             internRelease (pThis);
     961             :         }
     962             : 
     963       32069 :         osl_releaseMutex( pPoolMutex );
     964             :     }
     965      286807 :     if (pFree)
     966       32069 :         rtl_freeMemory (pFree);
     967      286807 : }
     968             : 
     969     1262951 : sal_uInt32 SAL_CALL rtl_uString_iterateCodePoints(
     970             :     rtl_uString const * string, sal_Int32 * indexUtf16,
     971             :     sal_Int32 incrementCodePoints)
     972             : {
     973             :     sal_Int32 n;
     974             :     sal_Unicode cu;
     975             :     sal_uInt32 cp;
     976             :     OSL_ASSERT(string != NULL && indexUtf16 != NULL);
     977     1262951 :     n = *indexUtf16;
     978             :     OSL_ASSERT(n >= 0 && n <= string->length);
     979     2537468 :     while (incrementCodePoints < 0) {
     980             :         OSL_ASSERT(n > 0);
     981       11566 :         cu = string->buffer[--n];
     982       11566 :         if (SAL_RTL_IS_LOW_SURROGATE(cu) && n != 0 &&
     983           0 :             SAL_RTL_IS_HIGH_SURROGATE(string->buffer[n - 1]))
     984             :         {
     985           0 :             --n;
     986             :         }
     987       11566 :         ++incrementCodePoints;
     988             :     }
     989             :     OSL_ASSERT(n >= 0 && n < string->length);
     990     1262951 :     cu = string->buffer[n];
     991     1262959 :     if (SAL_RTL_IS_HIGH_SURROGATE(cu) && string->length - n >= 2 &&
     992           8 :         SAL_RTL_IS_LOW_SURROGATE(string->buffer[n + 1]))
     993             :     {
     994           4 :         cp = SAL_RTL_COMBINE_SURROGATES(cu, string->buffer[n + 1]);
     995             :     } else {
     996     1262947 :         cp = cu;
     997             :     }
     998     2830598 :     while (incrementCodePoints > 0) {
     999             :         OSL_ASSERT(n < string->length);
    1000      304696 :         cu = string->buffer[n++];
    1001      304704 :         if (SAL_RTL_IS_HIGH_SURROGATE(cu) && n != string->length &&
    1002           8 :             SAL_RTL_IS_LOW_SURROGATE(string->buffer[n]))
    1003             :         {
    1004           4 :             ++n;
    1005             :         }
    1006      304696 :         --incrementCodePoints;
    1007             :     }
    1008             :     OSL_ASSERT(n >= 0 && n <= string->length);
    1009     1262951 :     *indexUtf16 = n;
    1010     1262951 :     return cp;
    1011             : }
    1012             : 
    1013     5320930 : sal_Bool rtl_convertStringToUString(
    1014             :     rtl_uString ** target, char const * source, sal_Int32 length,
    1015             :     rtl_TextEncoding encoding, sal_uInt32 flags) SAL_THROW_EXTERN_C()
    1016             : {
    1017             :     sal_uInt32 info;
    1018     5320930 :     rtl_string2UString_status(target, source, length, encoding, flags, &info);
    1019     5320930 :     return (sal_Bool) ((info & RTL_TEXTTOUNICODE_INFO_ERROR) == 0);
    1020             : }
    1021             : 
    1022        4904 : void rtl_uString_newReplaceFirst(
    1023             :     rtl_uString ** newStr, rtl_uString * str, rtl_uString const * from,
    1024             :     rtl_uString const * to, sal_Int32 * index) SAL_THROW_EXTERN_C()
    1025             : {
    1026             :     assert(str != 0);
    1027             :     assert(index != 0);
    1028             :     assert(*index >= 0 && *index <= str->length);
    1029             :     assert(from != 0);
    1030             :     assert(to != 0);
    1031             :     sal_Int32 i = rtl_ustr_indexOfStr_WithLength(
    1032        4904 :         str->buffer + *index, str->length - *index, from->buffer, from->length);
    1033        4904 :     if (i == -1) {
    1034        4637 :         rtl_uString_assign(newStr, str);
    1035             :     } else {
    1036             :         assert(i <= str->length - *index);
    1037         267 :         i += *index;
    1038             :         assert(from->length <= str->length);
    1039         267 :         if (str->length - from->length > SAL_MAX_INT32 - to->length) {
    1040           0 :             std::abort();
    1041             :         }
    1042         267 :         sal_Int32 n = str->length - from->length + to->length;
    1043         267 :         rtl_uString_acquire(str); // in case *newStr == str
    1044         267 :         rtl_uString_new_WithLength(newStr, n);
    1045         267 :         if (n != 0) {
    1046         265 :             (*newStr)->length = n;
    1047             :             assert(i >= 0 && i < str->length);
    1048             :             memcpy(
    1049         265 :                 (*newStr)->buffer, str->buffer, i * sizeof (sal_Unicode));
    1050             :             memcpy(
    1051         265 :                 (*newStr)->buffer + i, to->buffer,
    1052         530 :                 to->length * sizeof (sal_Unicode));
    1053             :             memcpy(
    1054         265 :                 (*newStr)->buffer + i + to->length,
    1055         265 :                 str->buffer + i + from->length,
    1056         530 :                 (str->length - i - from->length) * sizeof (sal_Unicode));
    1057             :         }
    1058         267 :         rtl_uString_release(str);
    1059             :     }
    1060        4904 :     *index = i;
    1061        4904 : }
    1062             : 
    1063         213 : void rtl_uString_newReplaceFirstAsciiL(
    1064             :     rtl_uString ** newStr, rtl_uString * str, char const * from,
    1065             :     sal_Int32 fromLength, rtl_uString const * to, sal_Int32 * index)
    1066             :     SAL_THROW_EXTERN_C()
    1067             : {
    1068             :     assert(str != 0);
    1069             :     assert(index != 0);
    1070             :     assert(*index >= 0 && *index <= str->length);
    1071             :     assert(fromLength >= 0);
    1072             :     assert(to != 0);
    1073             :     sal_Int32 i = rtl_ustr_indexOfAscii_WithLength(
    1074         213 :         str->buffer + *index, str->length - *index, from, fromLength);
    1075         213 :     if (i == -1) {
    1076         140 :         rtl_uString_assign(newStr, str);
    1077             :     } else {
    1078             :         assert(i <= str->length - *index);
    1079          73 :         i += *index;
    1080             :         assert(fromLength <= str->length);
    1081          73 :         if (str->length - fromLength > SAL_MAX_INT32 - to->length) {
    1082           0 :             std::abort();
    1083             :         }
    1084          73 :         sal_Int32 n = str->length - fromLength + to->length;
    1085          73 :         rtl_uString_acquire(str); // in case *newStr == str
    1086          73 :         if (n != 0) {
    1087          73 :             rtl_uString_new_WithLength(newStr, n);
    1088          73 :             (*newStr)->length = n;
    1089             :             assert(i >= 0 && i < str->length);
    1090             :             memcpy(
    1091          73 :                 (*newStr)->buffer, str->buffer, i * sizeof (sal_Unicode));
    1092             :             memcpy(
    1093          73 :                 (*newStr)->buffer + i, to->buffer,
    1094         146 :                 to->length * sizeof (sal_Unicode));
    1095             :             memcpy(
    1096          73 :                 (*newStr)->buffer + i + to->length,
    1097          73 :                 str->buffer + i + fromLength,
    1098         146 :                 (str->length - i - fromLength) * sizeof (sal_Unicode));
    1099             :         }
    1100          73 :         rtl_uString_release(str);
    1101             :     }
    1102         213 :     *index = i;
    1103         213 : }
    1104             : 
    1105        8014 : void rtl_uString_newReplaceFirstAsciiLAsciiL(
    1106             :     rtl_uString ** newStr, rtl_uString * str, char const * from,
    1107             :     sal_Int32 fromLength, char const * to, sal_Int32 toLength,
    1108             :     sal_Int32 * index) SAL_THROW_EXTERN_C()
    1109             : {
    1110             :     assert(str != 0);
    1111             :     assert(index != 0);
    1112             :     assert(*index >= 0 && *index <= str->length);
    1113             :     assert(fromLength >= 0);
    1114             :     assert(to != 0);
    1115             :     assert(toLength >= 0);
    1116             :     sal_Int32 i = rtl_ustr_indexOfAscii_WithLength(
    1117        8014 :         str->buffer + *index, str->length - *index, from, fromLength);
    1118        8014 :     if (i == -1) {
    1119        5948 :         rtl_uString_assign(newStr, str);
    1120             :     } else {
    1121             :         assert(i <= str->length - *index);
    1122        2066 :         i += *index;
    1123             :         assert(fromLength <= str->length);
    1124        2066 :         if (str->length - fromLength > SAL_MAX_INT32 - toLength) {
    1125           0 :             std::abort();
    1126             :         }
    1127        2066 :         sal_Int32 n = str->length - fromLength + toLength;
    1128        2066 :         rtl_uString_acquire(str); // in case *newStr == str
    1129        2066 :         if (n != 0) {
    1130        2066 :             rtl_uString_new_WithLength(newStr, n);
    1131        2066 :             (*newStr)->length = n;
    1132             :             assert(i >= 0 && i < str->length);
    1133             :             memcpy(
    1134        2066 :                 (*newStr)->buffer, str->buffer, i * sizeof (sal_Unicode));
    1135        2312 :             for (sal_Int32 j = 0; j != toLength; ++j) {
    1136             :                 assert(static_cast< unsigned char >(to[j]) <= 0x7F);
    1137         246 :                 (*newStr)->buffer[i + j] = to[j];
    1138             :             }
    1139             :             memcpy(
    1140        2066 :                 (*newStr)->buffer + i + toLength,
    1141        2066 :                 str->buffer + i + fromLength,
    1142        4132 :                 (str->length - i - fromLength) * sizeof (sal_Unicode));
    1143             :         }
    1144        2066 :         rtl_uString_release(str);
    1145             :     }
    1146        8014 :     *index = i;
    1147        8014 : }
    1148             : 
    1149           0 : void rtl_uString_newReplaceAll(
    1150             :     rtl_uString ** newStr, rtl_uString * str, rtl_uString const * from,
    1151             :     rtl_uString const * to) SAL_THROW_EXTERN_C()
    1152             : {
    1153           0 :     rtl_uString_newReplaceAllFromIndex( newStr, str, from, to, 0 );
    1154           0 : }
    1155             : 
    1156        4633 : void rtl_uString_newReplaceAllFromIndex(
    1157             :     rtl_uString ** newStr, rtl_uString * str, rtl_uString const * from,
    1158             :     rtl_uString const * to, sal_Int32 fromIndex) SAL_THROW_EXTERN_C()
    1159             : {
    1160             :     assert(to != 0);
    1161             :     assert(fromIndex >= 0 && fromIndex <= str->length);
    1162        4633 :     rtl_uString_assign(newStr, str);
    1163        4888 :     for (sal_Int32 i = fromIndex;; i += to->length) {
    1164        4888 :         rtl_uString_newReplaceFirst(newStr, *newStr, from, to, &i);
    1165        4888 :         if (i == -1) {
    1166        4633 :             break;
    1167             :         }
    1168             :     }
    1169        4633 : }
    1170             : 
    1171         136 : void rtl_uString_newReplaceAllAsciiL(
    1172             :     rtl_uString ** newStr, rtl_uString * str, char const * from,
    1173             :     sal_Int32 fromLength, rtl_uString const * to) SAL_THROW_EXTERN_C()
    1174             : {
    1175             :     assert(to != 0);
    1176         136 :     rtl_uString_assign(newStr, str);
    1177         201 :     for (sal_Int32 i = 0;; i += to->length) {
    1178             :         rtl_uString_newReplaceFirstAsciiL(
    1179         201 :             newStr, *newStr, from, fromLength, to, &i);
    1180         201 :         if (i == -1) {
    1181         136 :             break;
    1182             :         }
    1183             :     }
    1184         136 : }
    1185             : 
    1186        5944 : void rtl_uString_newReplaceAllAsciiLAsciiL(
    1187             :     rtl_uString ** newStr, rtl_uString * str, char const * from,
    1188             :     sal_Int32 fromLength, char const * to, sal_Int32 toLength)
    1189             :     SAL_THROW_EXTERN_C()
    1190             : {
    1191             :     assert(toLength >= 0);
    1192        5944 :     rtl_uString_assign(newStr, str);
    1193        8002 :     for (sal_Int32 i = 0;; i += toLength) {
    1194             :         rtl_uString_newReplaceFirstAsciiLAsciiL(
    1195        8002 :             newStr, *newStr, from, fromLength, to, toLength, &i);
    1196        8002 :         if (i == -1) {
    1197        5944 :             break;
    1198             :         }
    1199             :     }
    1200        5944 : }
    1201             : 
    1202             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10