1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
28 #include <osl/diagnose.h>
29 #include <osl/interlck.h>
30 #include <rtl/alloc.h>
31 #include <osl/mutex.h>
32 #include <rtl/tencinfo.h>
35 #include <sal/alloca.h>
36 #include <sal/log.hxx>
40 #include <rtl/character.hxx>
41 #include <rtl/ustring.h>
45 /* ======================================================================= */
47 /* static data to be referenced by all empty strings
48 * the refCount is predefined to 1 and must never become 0 !
50 rtl_uString
const aImplEmpty_rtl_uString
=
52 sal_Int32(SAL_STRING_INTERN_FLAG
|SAL_STRING_STATIC_FLAG
|1), /*sal_Int32 refCount; */
53 0, /*sal_Int32 length; */
54 { 0 } /*sal_Unicode buffer[1];*/
57 /* ======================================================================= */
58 /* These macros are for the "poor-man templates" included from
59 * the strtmpl.cxx just below, used to share code between here and
63 #define IMPL_RTL_IS_USTRING 1
65 #define IMPL_RTL_STRCODE sal_Unicode
66 #define IMPL_RTL_USTRCODE( c ) (c)
67 #define IMPL_RTL_STRNAME( n ) rtl_ustr_ ## n
69 #define IMPL_RTL_STRINGNAME( n ) rtl_uString_ ## n
70 #define IMPL_RTL_STRINGDATA rtl_uString
71 #define IMPL_RTL_EMPTYSTRING aImplEmpty_rtl_uString
73 static void internRelease (rtl_uString
*pThis
);
76 #define RTL_LOG_STRING_BITS 16
79 /* ======================================================================= */
81 /* Include String/UString template code */
83 #include "strtmpl.cxx"
85 #undef IMPL_RTL_EMPTYSTRING
86 #undef IMPL_RTL_IS_USTRING
87 #undef IMPL_RTL_STRCODE
88 #undef IMPL_RTL_STRINGDATA
89 #undef IMPL_RTL_STRINGNAME
90 #undef IMPL_RTL_STRNAME
91 #undef IMPL_RTL_USTRCODE
92 #undef RTL_LOG_STRING_BITS
94 sal_Int32
rtl_ustr_indexOfAscii_WithLength(
95 sal_Unicode
const * str
, sal_Int32 len
,
96 char const * subStr
, sal_Int32 subLen
) SAL_THROW_EXTERN_C()
100 if (subLen
> 0 && subLen
<= len
)
102 sal_Unicode
const* end
= str
+ len
;
103 sal_Unicode
const* cursor
= str
;
107 cursor
= std::char_traits
<sal_Unicode
>::find(cursor
, end
- cursor
, *subStr
);
108 if(!cursor
|| (end
- cursor
< subLen
))
110 /* no enough left to actually have a match */
113 /* now it is worth trying a full match */
114 if (rtl_ustr_asciil_reverseEquals_WithLength(cursor
, subStr
, subLen
))
124 sal_Int32
rtl_ustr_lastIndexOfAscii_WithLength(
125 sal_Unicode
const * str
, sal_Int32 len
,
126 char const * subStr
, sal_Int32 subLen
) SAL_THROW_EXTERN_C()
130 if (subLen
> 0 && subLen
<= len
) {
132 for (i
= len
- subLen
; i
>= 0; --i
) {
133 if (rtl_ustr_asciil_reverseEquals_WithLength(
134 str
+ i
, subStr
, subLen
))
143 sal_Int32 SAL_CALL
rtl_ustr_valueOfFloat(sal_Unicode
* pStr
, float f
)
147 rtl_uString
* pResult
= nullptr;
149 rtl_math_doubleToUString(
150 &pResult
, nullptr, 0, f
, rtl_math_StringFormat_G
,
151 RTL_USTR_MAX_VALUEOFFLOAT
- RTL_CONSTASCII_LENGTH("-x.E-xxx"), '.', nullptr,
153 nLen
= pResult
->length
;
154 OSL_ASSERT(nLen
< RTL_USTR_MAX_VALUEOFFLOAT
);
155 memcpy(pStr
, pResult
->buffer
, (nLen
+ 1) * sizeof(sal_Unicode
));
156 rtl_uString_release(pResult
);
160 sal_Int32 SAL_CALL
rtl_ustr_valueOfDouble(sal_Unicode
* pStr
, double d
)
164 rtl_uString
* pResult
= nullptr;
166 rtl_math_doubleToUString(
167 &pResult
, nullptr, 0, d
, rtl_math_StringFormat_G
,
168 RTL_USTR_MAX_VALUEOFDOUBLE
- RTL_CONSTASCII_LENGTH("-x.E-xxx"), '.', nullptr,
170 nLen
= pResult
->length
;
171 OSL_ASSERT(nLen
< RTL_USTR_MAX_VALUEOFDOUBLE
);
172 memcpy(pStr
, pResult
->buffer
, (nLen
+ 1) * sizeof(sal_Unicode
));
173 rtl_uString_release(pResult
);
179 // Avoid -fsanitize=undefined warning e.g. "runtime error: value 1e+99 is
180 // outside the range of representable values of type 'float'":
181 float doubleToFloat(double x
) {
183 x
< -std::numeric_limits
<float>::max()
184 ? -std::numeric_limits
<float>::infinity()
185 : x
> std::numeric_limits
<float>::max()
186 ? std::numeric_limits
<float>::infinity()
187 : static_cast<float>(x
);
192 float SAL_CALL
rtl_ustr_toFloat(sal_Unicode
const * pStr
) SAL_THROW_EXTERN_C()
195 return doubleToFloat(rtl_math_uStringToDouble(pStr
,
196 pStr
+ rtl_ustr_getLength(pStr
),
197 '.', 0, nullptr, nullptr));
200 double SAL_CALL
rtl_ustr_toDouble(sal_Unicode
const * pStr
) SAL_THROW_EXTERN_C()
203 return rtl_math_uStringToDouble(pStr
, pStr
+ rtl_ustr_getLength(pStr
), '.',
204 0, nullptr, nullptr);
207 /* ======================================================================= */
209 sal_Int32 SAL_CALL
rtl_ustr_ascii_compare( const sal_Unicode
* pStr1
,
218 nRet
= static_cast<sal_Int32
>(*pStr1
)-
219 static_cast<sal_Int32
>(static_cast<unsigned char>(*pStr2
));
220 if (!(nRet
== 0 && *pStr2
))
222 /* Check ASCII range */
223 SAL_WARN_IF( (static_cast<unsigned char>(*pStr2
)) > 127, "rtl.string",
224 "rtl_ustr_ascii_compare - Found char > 127" );
232 /* ----------------------------------------------------------------------- */
234 sal_Int32 SAL_CALL
rtl_ustr_ascii_compare_WithLength( const sal_Unicode
* pStr1
,
240 assert(nStr1Len
>= 0);
245 nRet
= (nStr1Len
? static_cast<sal_Int32
>(*pStr1
) : 0) -
246 static_cast<sal_Int32
>(static_cast<unsigned char>(*pStr2
));
247 if (!(nRet
== 0 && nStr1Len
&& *pStr2
))
249 /* Check ASCII range */
250 SAL_WARN_IF( (static_cast<unsigned char>(*pStr2
)) > 127, "rtl.string",
251 "rtl_ustr_ascii_compare_WithLength - Found char > 127" );
260 /* ----------------------------------------------------------------------- */
262 sal_Int32 SAL_CALL
rtl_ustr_ascii_shortenedCompare_WithLength( const sal_Unicode
* pStr1
,
265 sal_Int32 nShortenedLength
)
268 assert(nStr1Len
>= 0);
269 assert(nShortenedLength
>= 0);
270 const sal_Unicode
* pStr1End
= pStr1
+ nStr1Len
;
272 while ( (nShortenedLength
> 0) &&
273 (pStr1
< pStr1End
) && *pStr2
)
275 /* Check ASCII range */
276 SAL_WARN_IF( (static_cast<unsigned char>(*pStr2
)) > 127, "rtl.string",
277 "rtl_ustr_ascii_shortenedCompare_WithLength - Found char > 127" );
279 nRet
= static_cast<sal_Int32
>(*pStr1
)-
280 static_cast<sal_Int32
>(static_cast<unsigned char>(*pStr2
));
289 if ( nShortenedLength
<= 0 )
294 OSL_ENSURE( pStr1
== pStr1End
, "pStr1 == pStr1End failed" );
295 // first is a substring of the second string => less (negative value)
301 nRet
= pStr1End
- pStr1
;
307 /* ----------------------------------------------------------------------- */
309 sal_Int32 SAL_CALL
rtl_ustr_asciil_reverseCompare_WithLength( const sal_Unicode
* pStr1
,
315 assert(nStr1Len
>= 0 && nStr2Len
>= 0);
316 const sal_Unicode
* pStr1Run
= pStr1
+nStr1Len
;
317 const char* pStr2Run
= pStr2
+nStr2Len
;
319 while ( (pStr1
< pStr1Run
) && (pStr2
< pStr2Run
) )
321 /* Check ASCII range */
322 SAL_WARN_IF( (static_cast<unsigned char>(*pStr2
)) > 127, "rtl.string",
323 "rtl_ustr_asciil_reverseCompare_WithLength - Found char > 127" );
326 nRet
= static_cast<sal_Int32
>(*pStr1Run
)- static_cast<sal_Int32
>(*pStr2Run
);
331 return nStr1Len
- nStr2Len
;
334 /* ----------------------------------------------------------------------- */
336 sal_Bool SAL_CALL
rtl_ustr_asciil_reverseEquals_WithLength( const sal_Unicode
* pStr1
,
341 assert(nStrLen
>= 0);
342 const sal_Unicode
* pStr1Run
= pStr1
+nStrLen
;
343 const char* pStr2Run
= pStr2
+nStrLen
;
344 while ( pStr1
< pStr1Run
)
346 /* Check ASCII range */
347 SAL_WARN_IF( (static_cast<unsigned char>(*pStr2
)) > 127, "rtl.string",
348 "rtl_ustr_asciil_reverseEquals_WithLength - Found char > 127" );
351 if( *pStr1Run
!= static_cast<sal_Unicode
>(*pStr2Run
) )
358 /* ----------------------------------------------------------------------- */
360 sal_Int32 SAL_CALL
rtl_ustr_ascii_compareIgnoreAsciiCase( const sal_Unicode
* pStr1
,
371 /* Check ASCII range */
372 SAL_WARN_IF( (static_cast<unsigned char>(*pStr2
)) > 127, "rtl.string",
373 "rtl_ustr_ascii_compareIgnoreAsciiCase - Found char > 127" );
374 /* If character between 'A' and 'Z', then convert it to lowercase */
375 c1
= static_cast<sal_Int32
>(*pStr1
);
376 c2
= static_cast<sal_Int32
>(static_cast<unsigned char>(*pStr2
));
377 if ( (c1
>= 65) && (c1
<= 90) )
379 if ( (c2
>= 65) && (c2
<= 90) )
393 /* ----------------------------------------------------------------------- */
395 sal_Int32 SAL_CALL
rtl_ustr_ascii_compareIgnoreAsciiCase_WithLength( const sal_Unicode
* pStr1
,
400 assert(nStr1Len
>= 0);
407 /* Check ASCII range */
408 SAL_WARN_IF( (static_cast<unsigned char>(*pStr2
)) > 127, "rtl.string",
409 "rtl_ustr_ascii_compareIgnoreAsciiCase_WithLength - Found char > 127" );
411 return *pStr2
== '\0' ? 0 : -1;
413 /* If character between 'A' and 'Z', then convert it to lowercase */
414 c1
= static_cast<sal_Int32
>(*pStr1
);
415 c2
= static_cast<sal_Int32
>(static_cast<unsigned char>(*pStr2
));
416 if ( (c1
>= 65) && (c1
<= 90) )
418 if ( (c2
>= 65) && (c2
<= 90) )
433 sal_Int32
rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
434 sal_Unicode
const * first
, sal_Int32 firstLen
,
435 char const * second
, sal_Int32 secondLen
) SAL_THROW_EXTERN_C()
437 assert(firstLen
>= 0 && secondLen
>= 0);
439 sal_Int32 len
= std::min(firstLen
, secondLen
);
440 for (i
= 0; i
< len
; ++i
) {
441 /* Check ASCII range */
442 SAL_WARN_IF( (static_cast<unsigned char>(*second
)) > 127, "rtl.string",
443 "rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths - Found char > 127" );
444 sal_Int32 c1
= *first
++;
445 sal_Int32 c2
= static_cast<unsigned char>(*second
++);
447 if (c1
>= 65 && c1
<= 90) {
450 if (c2
>= 65 && c2
<= 90) {
458 return firstLen
- secondLen
;
461 /* ----------------------------------------------------------------------- */
463 sal_Int32 SAL_CALL
rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( const sal_Unicode
* pStr1
,
466 sal_Int32 nShortenedLength
)
469 assert(nStr1Len
>= 0);
470 assert(nShortenedLength
>= 0);
471 const sal_Unicode
* pStr1End
= pStr1
+ nStr1Len
;
475 while ( (nShortenedLength
> 0) &&
476 (pStr1
< pStr1End
) && *pStr2
)
478 /* Check ASCII range */
479 SAL_WARN_IF( (static_cast<unsigned char>(*pStr2
)) > 127, "rtl.string",
480 "rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength - Found char > 127" );
482 /* If character between 'A' and 'Z', then convert it to lowercase */
483 c1
= static_cast<sal_Int32
>(*pStr1
);
484 c2
= static_cast<sal_Int32
>(static_cast<unsigned char>(*pStr2
));
485 if ( (c1
>= 65) && (c1
<= 90) )
487 if ( (c2
>= 65) && (c2
<= 90) )
498 if ( nShortenedLength
<= 0 )
503 OSL_ENSURE( pStr1
== pStr1End
, "pStr1 == pStr1End failed" );
504 // first is a substring of the second string => less (negative value)
510 nRet
= pStr1End
- pStr1
;
516 /* ----------------------------------------------------------------------- */
518 void SAL_CALL
rtl_uString_newFromAscii( rtl_uString
** ppThis
,
519 const char* pCharStr
)
527 const char* pTempStr
= pCharStr
;
530 nLen
= pTempStr
-pCharStr
;
537 rtl_uString_new( ppThis
);
542 rtl_uString_release( *ppThis
);
544 *ppThis
= rtl_uString_ImplAlloc( nLen
);
545 OSL_ASSERT(*ppThis
!= nullptr);
549 sal_Unicode
* pBuffer
= (*ppThis
)->buffer
;
552 assert(static_cast<unsigned char>(*pCharStr
) < 0x80); // ASCII range
553 *pBuffer
= *pCharStr
;
559 RTL_LOG_STRING_NEW( *ppThis
);
562 void SAL_CALL
rtl_uString_newFromCodePoints(
563 rtl_uString
** newString
, sal_uInt32
const * codePoints
,
564 sal_Int32 codePointCount
) SAL_THROW_EXTERN_C()
569 assert(newString
!= nullptr);
570 assert((codePoints
!= nullptr || codePointCount
== 0) && codePointCount
>= 0);
571 if (codePointCount
== 0) {
572 rtl_uString_new(newString
);
575 if (*newString
!= nullptr) {
576 rtl_uString_release(*newString
);
579 for (i
= 0; i
< codePointCount
; ++i
) {
580 OSL_ASSERT(rtl::isUnicodeCodePoint(codePoints
[i
]));
581 if (codePoints
[i
] >= 0x10000) {
585 /* Builds on the assumption that sal_Int32 uses 32 bit two's complement
586 representation with wrap around (the necessary number of UTF-16 code
587 units will be no larger than 2 * SAL_MAX_INT32, represented as
590 // coverity[dead_error_begin] - assumes wrap around
591 *newString
= nullptr;
594 *newString
= rtl_uString_ImplAlloc(n
);
595 if (*newString
== nullptr) {
598 p
= (*newString
)->buffer
;
599 for (i
= 0; i
< codePointCount
; ++i
) {
600 p
+= rtl::splitSurrogates(codePoints
[i
], p
);
602 RTL_LOG_STRING_NEW( *newString
);
605 void rtl_uString_newConcatAsciiL(
606 rtl_uString
** newString
, rtl_uString
* left
, char const * right
,
607 sal_Int32 rightLength
)
609 assert(newString
!= nullptr);
610 assert(left
!= nullptr);
611 assert(right
!= nullptr);
612 assert(rightLength
>= 0);
613 if (left
->length
> std::numeric_limits
<sal_Int32
>::max() - rightLength
) {
614 #if !defined(__COVERITY__)
615 throw std::length_error("rtl_uString_newConcatAsciiL");
617 //coverity doesn't report std::bad_alloc as an unhandled exception when
618 //potentially thrown from destructors but does report std::length_error
619 throw std::bad_alloc();
622 sal_Int32 n
= left
->length
+ rightLength
;
623 rtl_uString_assign(newString
, left
);
624 rtl_uString_ensureCapacity(newString
, n
);
625 sal_Unicode
* p
= (*newString
)->buffer
+ (*newString
)->length
;
626 for (sal_Int32 i
= 0; i
!= rightLength
; ++i
) {
627 p
[i
] = static_cast<unsigned char>(right
[i
]);
629 (*newString
)->buffer
[n
] = 0;
630 (*newString
)->length
= n
;
633 void rtl_uString_newConcatUtf16L(
634 rtl_uString
** newString
, rtl_uString
* left
, sal_Unicode
const * right
,
635 sal_Int32 rightLength
)
637 assert(newString
!= nullptr);
638 assert(left
!= nullptr);
639 assert(right
!= nullptr || rightLength
== 0);
640 assert(rightLength
>= 0);
641 if (left
->length
> std::numeric_limits
<sal_Int32
>::max() - rightLength
) {
642 #if !defined(__COVERITY__)
643 throw std::length_error("rtl_uString_newConcatUtf16L");
645 //coverity doesn't report std::bad_alloc as an unhandled exception when
646 //potentially thrown from destructors but does report std::length_error
647 throw std::bad_alloc();
650 sal_Int32 n
= left
->length
+ rightLength
;
651 rtl_uString_assign(newString
, left
);
652 rtl_uString_ensureCapacity(newString
, n
);
653 if (rightLength
!= 0) {
655 (*newString
)->buffer
+ (*newString
)->length
, right
,
656 rightLength
* sizeof (sal_Unicode
));
658 (*newString
)->buffer
[n
] = 0;
659 (*newString
)->length
= n
;
662 /* ======================================================================= */
664 static int rtl_ImplGetFastUTF8UnicodeLen( const char* pStr
, sal_Int32 nLen
, bool * ascii
)
672 while ( pStr
< pEndStr
)
674 unsigned char c
= static_cast<unsigned char>(*pStr
);
680 if ( (c
& 0xE0) == 0xC0 )
682 else if ( (c
& 0xF0) == 0xE0 )
684 else if ( (c
& 0xF8) == 0xF0 )
686 else if ( (c
& 0xFC) == 0xF8 )
688 else if ( (c
& 0xFE) == 0xFC )
701 /* ----------------------------------------------------------------------- */
703 static void rtl_string2UString_status( rtl_uString
** ppThis
,
706 rtl_TextEncoding eTextEncoding
,
707 sal_uInt32 nCvtFlags
,
710 OSL_ENSURE(nLen
== 0 || rtl_isOctetTextEncoding(eTextEncoding
),
711 "rtl_string2UString_status() - Wrong TextEncoding" );
715 rtl_uString_new( ppThis
);
716 if (pInfo
!= nullptr) {
723 rtl_uString_release( *ppThis
);
725 /* Optimization for US-ASCII */
726 if ( eTextEncoding
== RTL_TEXTENCODING_ASCII_US
)
728 sal_Unicode
* pBuffer
;
729 *ppThis
= rtl_uString_ImplAlloc( nLen
);
730 if (*ppThis
== nullptr) {
731 if (pInfo
!= nullptr) {
732 *pInfo
= RTL_TEXTTOUNICODE_INFO_ERROR
|
733 RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOOSMALL
;
737 pBuffer
= (*ppThis
)->buffer
;
738 sal_Int32
nLenCopy(nLen
);
739 const char *pStrCopy(pStr
);
742 /* Check ASCII range */
743 if (static_cast<unsigned char>(*pStrCopy
) > 127)
745 rtl_uString_release(*ppThis
);
746 goto retry
; // cancel loop - try again with the converter
749 *pBuffer
= *pStrCopy
;
755 if (pInfo
!= nullptr) {
758 RTL_LOG_STRING_NEW( *ppThis
);
764 rtl_uString
* pTemp2
= nullptr;
765 rtl_TextToUnicodeConverter hConverter
;
771 /* Optimization for UTF-8 - we try to calculate the exact length */
772 /* For all other encoding we try the maximum - and reallocate
773 the buffer if needed */
774 if ( eTextEncoding
== RTL_TEXTENCODING_UTF8
)
777 nNewLen
= rtl_ImplGetFastUTF8UnicodeLen( pStr
, nLen
, &ascii
);
778 /* Includes the string only ASCII, then we could copy
782 sal_Unicode
* pBuffer
;
783 *ppThis
= rtl_uString_ImplAlloc( nLen
);
784 if (*ppThis
== nullptr)
786 if (pInfo
!= nullptr) {
787 *pInfo
= RTL_TEXTTOUNICODE_INFO_ERROR
|
788 RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOOSMALL
;
792 pBuffer
= (*ppThis
)->buffer
;
795 assert((static_cast<unsigned char>(*pStr
)) <= 127);
802 if (pInfo
!= nullptr) {
805 RTL_LOG_STRING_NEW( *ppThis
);
812 nCvtFlags
|= RTL_TEXTTOUNICODE_FLAGS_FLUSH
;
813 hConverter
= rtl_createTextToUnicodeConverter( eTextEncoding
);
815 pTemp
= rtl_uString_ImplAlloc( nNewLen
);
816 if (pTemp
== nullptr) {
817 if (pInfo
!= nullptr) {
818 *pInfo
= RTL_TEXTTOUNICODE_INFO_ERROR
|
819 RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOOSMALL
;
823 nDestChars
= rtl_convertTextToUnicode( hConverter
, nullptr,
825 pTemp
->buffer
, nNewLen
,
827 &nInfo
, &nSrcBytes
);
829 /* Buffer not big enough, try again with enough space */
830 /* Shouldn't be the case, but if we get textencoding which
831 could results in more unicode characters we have this
832 code here. Could be the case for apple encodings */
833 while ( nInfo
& RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOOSMALL
)
835 rtl_freeString( pTemp
);
837 pTemp
= rtl_uString_ImplAlloc( nNewLen
);
838 if (pTemp
== nullptr) {
839 if (pInfo
!= nullptr) {
840 *pInfo
= RTL_TEXTTOUNICODE_INFO_ERROR
|
841 RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOOSMALL
;
845 nDestChars
= rtl_convertTextToUnicode( hConverter
, nullptr,
847 pTemp
->buffer
, nNewLen
,
849 &nInfo
, &nSrcBytes
);
855 /* Set the buffer to the correct size or if there is too
856 much overhead, reallocate to the correct size */
857 if ( nNewLen
> nDestChars
+8 )
859 pTemp2
= rtl_uString_ImplAlloc( nDestChars
);
861 if (pTemp2
!= nullptr)
863 rtl_str_ImplCopy(pTemp2
->buffer
, pTemp
->buffer
, nDestChars
);
864 rtl_freeString(pTemp
);
869 pTemp
->length
= nDestChars
;
870 pTemp
->buffer
[nDestChars
] = 0;
873 rtl_destroyTextToUnicodeConverter( hConverter
);
876 /* Results the conversion in an empty buffer -
877 create an empty string */
878 if ( pTemp
&& !nDestChars
)
879 rtl_uString_new( ppThis
);
882 RTL_LOG_STRING_NEW( *ppThis
);
885 void SAL_CALL
rtl_string2UString( rtl_uString
** ppThis
,
888 rtl_TextEncoding eTextEncoding
,
889 sal_uInt32 nCvtFlags
) SAL_THROW_EXTERN_C()
893 rtl_string2UString_status( ppThis
, pStr
, nLen
, eTextEncoding
,
894 nCvtFlags
, nullptr );
897 /* ----------------------------------------------------------------------- */
911 static oslMutex pPoolGuard
= osl_createMutex();
916 /* returns true if we found a dup in the pool */
917 static void rtl_ustring_intern_internal( rtl_uString
** newStr
,
919 StrLifecycle can_return
)
923 pPoolMutex
= getInternMutex();
925 osl_acquireMutex( pPoolMutex
);
927 *newStr
= rtl_str_hash_intern (str
, can_return
);
929 osl_releaseMutex( pPoolMutex
);
931 RTL_LOG_STRING_INTERN_NEW(*newStr
, str
);
933 if( can_return
&& *newStr
!= str
)
934 { /* we dupped, then found a match */
935 rtl_freeString( str
);
939 void SAL_CALL
rtl_uString_intern( rtl_uString
** newStr
,
940 rtl_uString
* str
) SAL_THROW_EXTERN_C()
944 if (SAL_STRING_IS_INTERN(str
))
946 IMPL_RTL_ACQUIRE( str
);
951 rtl_uString
*pOrg
= *newStr
;
953 rtl_ustring_intern_internal( newStr
, str
, CANNOT_RETURN
);
955 rtl_uString_release (pOrg
);
959 static int rtl_canGuessUOutputLength( int len
, rtl_TextEncoding eTextEncoding
)
961 // FIXME: Maybe we should use a bit flag in the higher bits of the
962 // eTextEncoding value itself to determine the encoding type. But if we
963 // do, be sure to mask the value in certain places that expect the values
964 // to be numbered serially from 0 and up. One such place is
965 // Impl_getTextEncodingData().
967 switch ( eTextEncoding
)
969 // 1 to 1 (with no zero elements)
970 case RTL_TEXTENCODING_IBM_437
:
971 case RTL_TEXTENCODING_IBM_850
:
972 case RTL_TEXTENCODING_IBM_860
:
973 case RTL_TEXTENCODING_IBM_861
:
974 case RTL_TEXTENCODING_IBM_863
:
975 case RTL_TEXTENCODING_IBM_865
:
982 void SAL_CALL
rtl_uString_internConvert( rtl_uString
** newStr
,
985 rtl_TextEncoding eTextEncoding
,
986 sal_uInt32 convertFlags
,
992 rtl_uString
*scratch
;
996 rtl_uString_release (*newStr
);
1001 { // try various optimisations
1003 if ( eTextEncoding
== RTL_TEXTENCODING_ASCII_US
)
1006 rtl_uString
*pScratch
;
1007 pScratch
= static_cast< rtl_uString
* >(
1008 alloca(sizeof (rtl_uString
) + len
* sizeof (sal_Unicode
)));
1009 for (i
= 0; i
< len
; i
++)
1011 /* Check ASCII range */
1012 SAL_WARN_IF( (static_cast<unsigned char>(str
[i
])) > 127, "rtl.string",
1013 "rtl_ustring_internConvert() - Found char > 127 and RTL_TEXTENCODING_ASCII_US is specified" );
1014 pScratch
->buffer
[i
] = str
[i
];
1016 pScratch
->length
= len
;
1017 rtl_ustring_intern_internal( newStr
, pScratch
, CANNOT_RETURN
);
1020 if ( (ulen
= rtl_canGuessUOutputLength(len
, eTextEncoding
)) != 0 )
1022 rtl_uString
*pScratch
;
1023 rtl_TextToUnicodeConverter hConverter
;
1027 pScratch
= static_cast< rtl_uString
* >(
1029 sizeof (rtl_uString
) + ulen
* sizeof (sal_Unicode
)));
1031 hConverter
= rtl_createTextToUnicodeConverter( eTextEncoding
);
1032 rtl_convertTextToUnicode(
1033 hConverter
, nullptr, str
, len
, pScratch
->buffer
, ulen
, convertFlags
, &nInfo
, &nSrcBytes
);
1034 rtl_destroyTextToUnicodeConverter( hConverter
);
1039 pScratch
->length
= ulen
;
1040 rtl_ustring_intern_internal( newStr
, pScratch
, CANNOT_RETURN
);
1044 /* FIXME: we want a nice UTF-8 / alloca shortcut here */
1048 rtl_string2UString_status( &scratch
, str
, len
, eTextEncoding
, convertFlags
,
1053 rtl_ustring_intern_internal( newStr
, scratch
, CAN_RETURN
);
1057 internRelease (rtl_uString
*pThis
)
1059 rtl_uString
*pFree
= nullptr;
1060 if ( SAL_STRING_REFCOUNT(
1061 osl_atomic_decrement( &(pThis
->refCount
) ) ) == 0)
1063 RTL_LOG_STRING_INTERN_DELETE(pThis
);
1064 oslMutex pPoolMutex
= getInternMutex();
1065 osl_acquireMutex( pPoolMutex
);
1067 rtl_str_hash_remove (pThis
);
1069 /* May have been separately acquired */
1070 if ( SAL_STRING_REFCOUNT(
1071 osl_atomic_increment( &(pThis
->refCount
) ) ) == 1 )
1073 /* we got the last ref */
1076 else /* very unusual */
1078 internRelease (pThis
);
1081 osl_releaseMutex( pPoolMutex
);
1084 rtl_freeString (pFree
);
1087 sal_uInt32 SAL_CALL
rtl_uString_iterateCodePoints(
1088 rtl_uString
const * string
, sal_Int32
* indexUtf16
,
1089 sal_Int32 incrementCodePoints
)
1094 assert(string
!= nullptr && indexUtf16
!= nullptr);
1096 assert(n
>= 0 && n
<= string
->length
);
1097 while (incrementCodePoints
< 0) {
1099 cu
= string
->buffer
[--n
];
1100 if (rtl::isLowSurrogate(cu
) && n
!= 0 &&
1101 rtl::isHighSurrogate(string
->buffer
[n
- 1]))
1105 ++incrementCodePoints
;
1107 assert(n
>= 0 && n
< string
->length
);
1108 cu
= string
->buffer
[n
];
1109 if (rtl::isHighSurrogate(cu
) && string
->length
- n
>= 2 &&
1110 rtl::isLowSurrogate(string
->buffer
[n
+ 1]))
1112 cp
= rtl::combineSurrogates(cu
, string
->buffer
[n
+ 1]);
1116 while (incrementCodePoints
> 0) {
1117 assert(n
< string
->length
);
1118 cu
= string
->buffer
[n
++];
1119 if (rtl::isHighSurrogate(cu
) && n
!= string
->length
&&
1120 rtl::isLowSurrogate(string
->buffer
[n
]))
1124 --incrementCodePoints
;
1126 assert(n
>= 0 && n
<= string
->length
);
1131 sal_Bool
rtl_convertStringToUString(
1132 rtl_uString
** target
, char const * source
, sal_Int32 length
,
1133 rtl_TextEncoding encoding
, sal_uInt32 flags
) SAL_THROW_EXTERN_C()
1136 assert(length
>= 0);
1138 rtl_string2UString_status(target
, source
, length
, encoding
, flags
, &info
);
1139 return (info
& RTL_TEXTTOUNICODE_INFO_ERROR
) == 0;
1142 void rtl_uString_newReplaceFirst(
1143 rtl_uString
** newStr
, rtl_uString
* str
, rtl_uString
const * from
,
1144 rtl_uString
const * to
, sal_Int32
* index
) SAL_THROW_EXTERN_C()
1146 assert(str
!= nullptr);
1147 assert(index
!= nullptr);
1148 assert(*index
>= 0 && *index
<= str
->length
);
1149 assert(from
!= nullptr);
1150 assert(to
!= nullptr);
1151 sal_Int32 i
= rtl_ustr_indexOfStr_WithLength(
1152 str
->buffer
+ *index
, str
->length
- *index
, from
->buffer
, from
->length
);
1154 rtl_uString_assign(newStr
, str
);
1156 assert(i
<= str
->length
- *index
);
1158 assert(from
->length
<= str
->length
);
1159 if (str
->length
- from
->length
> SAL_MAX_INT32
- to
->length
) {
1162 sal_Int32 n
= str
->length
- from
->length
+ to
->length
;
1163 rtl_uString_acquire(str
); // in case *newStr == str
1164 rtl_uString_new_WithLength(newStr
, n
);
1166 (*newStr
)->length
= n
;
1167 assert(i
>= 0 && i
< str
->length
);
1169 (*newStr
)->buffer
, str
->buffer
, i
* sizeof (sal_Unicode
));
1171 (*newStr
)->buffer
+ i
, to
->buffer
,
1172 to
->length
* sizeof (sal_Unicode
));
1174 (*newStr
)->buffer
+ i
+ to
->length
,
1175 str
->buffer
+ i
+ from
->length
,
1176 (str
->length
- i
- from
->length
) * sizeof (sal_Unicode
));
1178 rtl_uString_release(str
);
1183 void rtl_uString_newReplaceFirstAsciiL(
1184 rtl_uString
** newStr
, rtl_uString
* str
, char const * from
,
1185 sal_Int32 fromLength
, rtl_uString
const * to
, sal_Int32
* index
)
1186 SAL_THROW_EXTERN_C()
1188 assert(str
!= nullptr);
1189 assert(index
!= nullptr);
1190 assert(*index
>= 0 && *index
<= str
->length
);
1191 assert(fromLength
>= 0);
1192 assert(to
!= nullptr);
1193 sal_Int32 i
= rtl_ustr_indexOfAscii_WithLength(
1194 str
->buffer
+ *index
, str
->length
- *index
, from
, fromLength
);
1196 rtl_uString_assign(newStr
, str
);
1198 assert(i
<= str
->length
- *index
);
1200 assert(fromLength
<= str
->length
);
1201 if (str
->length
- fromLength
> SAL_MAX_INT32
- to
->length
) {
1204 sal_Int32 n
= str
->length
- fromLength
+ to
->length
;
1205 rtl_uString_acquire(str
); // in case *newStr == str
1206 rtl_uString_new_WithLength(newStr
, n
);
1208 (*newStr
)->length
= n
;
1209 assert(i
>= 0 && i
< str
->length
);
1211 (*newStr
)->buffer
, str
->buffer
, i
* sizeof (sal_Unicode
));
1213 (*newStr
)->buffer
+ i
, to
->buffer
,
1214 to
->length
* sizeof (sal_Unicode
));
1216 (*newStr
)->buffer
+ i
+ to
->length
,
1217 str
->buffer
+ i
+ fromLength
,
1218 (str
->length
- i
- fromLength
) * sizeof (sal_Unicode
));
1220 rtl_uString_release(str
);
1225 void rtl_uString_newReplaceFirstToAsciiL(
1226 rtl_uString
** newStr
, rtl_uString
* str
, rtl_uString
const * from
,
1227 char const * to
, sal_Int32 toLength
, sal_Int32
* index
)
1228 SAL_THROW_EXTERN_C()
1230 assert(str
!= nullptr);
1231 assert(index
!= nullptr);
1232 assert(*index
>= 0 && *index
<= str
->length
);
1233 assert(from
!= nullptr);
1234 assert(toLength
>= 0);
1235 sal_Int32 i
= rtl_ustr_indexOfStr_WithLength(
1236 str
->buffer
+ *index
, str
->length
- *index
, from
->buffer
, from
->length
);
1238 rtl_uString_assign(newStr
, str
);
1240 assert(i
<= str
->length
- *index
);
1242 assert(from
->length
<= str
->length
);
1243 if (str
->length
- from
->length
> SAL_MAX_INT32
- toLength
) {
1246 sal_Int32 n
= str
->length
- from
->length
+ toLength
;
1247 rtl_uString_acquire(str
); // in case *newStr == str
1248 rtl_uString_new_WithLength(newStr
, n
);
1250 (*newStr
)->length
= n
;
1251 assert(i
>= 0 && i
< str
->length
);
1253 (*newStr
)->buffer
, str
->buffer
, i
* sizeof (sal_Unicode
));
1254 for (sal_Int32 j
= 0; j
!= toLength
; ++j
) {
1255 assert(static_cast< unsigned char >(to
[j
]) <= 0x7F);
1256 (*newStr
)->buffer
[i
+ j
] = to
[j
];
1259 (*newStr
)->buffer
+ i
+ toLength
,
1260 str
->buffer
+ i
+ from
->length
,
1261 (str
->length
- i
- from
->length
) * sizeof (sal_Unicode
));
1263 rtl_uString_release(str
);
1268 void rtl_uString_newReplaceFirstAsciiLAsciiL(
1269 rtl_uString
** newStr
, rtl_uString
* str
, char const * from
,
1270 sal_Int32 fromLength
, char const * to
, sal_Int32 toLength
,
1271 sal_Int32
* index
) SAL_THROW_EXTERN_C()
1273 assert(str
!= nullptr);
1274 assert(index
!= nullptr);
1275 assert(*index
>= 0 && *index
<= str
->length
);
1276 assert(fromLength
>= 0);
1277 assert(to
!= nullptr);
1278 assert(toLength
>= 0);
1279 sal_Int32 i
= rtl_ustr_indexOfAscii_WithLength(
1280 str
->buffer
+ *index
, str
->length
- *index
, from
, fromLength
);
1282 rtl_uString_assign(newStr
, str
);
1284 assert(i
<= str
->length
- *index
);
1286 assert(fromLength
<= str
->length
);
1287 if (str
->length
- fromLength
> SAL_MAX_INT32
- toLength
) {
1290 sal_Int32 n
= str
->length
- fromLength
+ toLength
;
1291 rtl_uString_acquire(str
); // in case *newStr == str
1292 rtl_uString_new_WithLength(newStr
, n
);
1294 (*newStr
)->length
= n
;
1295 assert(i
>= 0 && i
< str
->length
);
1297 (*newStr
)->buffer
, str
->buffer
, i
* sizeof (sal_Unicode
));
1298 for (sal_Int32 j
= 0; j
!= toLength
; ++j
) {
1299 assert(static_cast< unsigned char >(to
[j
]) <= 0x7F);
1300 (*newStr
)->buffer
[i
+ j
] = to
[j
];
1303 (*newStr
)->buffer
+ i
+ toLength
,
1304 str
->buffer
+ i
+ fromLength
,
1305 (str
->length
- i
- fromLength
) * sizeof (sal_Unicode
));
1307 rtl_uString_release(str
);
1312 void rtl_uString_newReplaceFirstAsciiLUtf16L(
1313 rtl_uString
** newStr
, rtl_uString
* str
, char const * from
,
1314 sal_Int32 fromLength
, sal_Unicode
const * to
, sal_Int32 toLength
,
1315 sal_Int32
* index
) SAL_THROW_EXTERN_C()
1317 assert(str
!= nullptr);
1318 assert(index
!= nullptr);
1319 assert(*index
>= 0 && *index
<= str
->length
);
1320 assert(fromLength
>= 0);
1321 assert(to
!= nullptr || toLength
== 0);
1322 assert(toLength
>= 0);
1323 sal_Int32 i
= rtl_ustr_indexOfAscii_WithLength(
1324 str
->buffer
+ *index
, str
->length
- *index
, from
, fromLength
);
1326 rtl_uString_assign(newStr
, str
);
1328 assert(i
<= str
->length
- *index
);
1330 assert(fromLength
<= str
->length
);
1331 if (str
->length
- fromLength
> SAL_MAX_INT32
- toLength
) {
1332 rtl_uString_release(*newStr
);
1335 sal_Int32 n
= str
->length
- fromLength
+ toLength
;
1336 rtl_uString_acquire(str
); // in case *newStr == str
1337 rtl_uString_new_WithLength(newStr
, n
);
1338 if (n
!= 0 && /*TODO:*/ *newStr
!= nullptr) {
1339 (*newStr
)->length
= n
;
1340 assert(i
>= 0 && i
< str
->length
);
1342 (*newStr
)->buffer
, str
->buffer
, i
* sizeof (sal_Unicode
));
1343 if (toLength
!= 0) {
1345 (*newStr
)->buffer
+ i
, to
, toLength
* sizeof (sal_Unicode
));
1348 (*newStr
)->buffer
+ i
+ toLength
,
1349 str
->buffer
+ i
+ fromLength
,
1350 (str
->length
- i
- fromLength
) * sizeof (sal_Unicode
));
1352 rtl_uString_release(str
);
1358 void rtl_uString_newReplaceFirstUtf16LAsciiL(
1359 rtl_uString
** newStr
, rtl_uString
* str
, sal_Unicode
const * from
,
1360 sal_Int32 fromLength
, char const * to
, sal_Int32 toLength
,
1361 sal_Int32
* index
) SAL_THROW_EXTERN_C()
1363 assert(str
!= nullptr);
1364 assert(index
!= nullptr);
1365 assert(*index
>= 0 && *index
<= str
->length
);
1366 assert(fromLength
>= 0);
1367 assert(to
!= nullptr);
1368 assert(toLength
>= 0);
1369 sal_Int32 i
= rtl_ustr_indexOfStr_WithLength(
1370 str
->buffer
+ *index
, str
->length
- *index
, from
, fromLength
);
1372 rtl_uString_assign(newStr
, str
);
1374 assert(i
<= str
->length
- *index
);
1376 assert(fromLength
<= str
->length
);
1377 if (str
->length
- fromLength
> SAL_MAX_INT32
- toLength
) {
1378 rtl_uString_release(*newStr
);
1381 sal_Int32 n
= str
->length
- fromLength
+ toLength
;
1382 rtl_uString_acquire(str
); // in case *newStr == str
1383 rtl_uString_new_WithLength(newStr
, n
);
1384 if (n
!= 0 && /*TODO:*/ *newStr
!= nullptr) {
1385 (*newStr
)->length
= n
;
1386 assert(i
>= 0 && i
< str
->length
);
1388 (*newStr
)->buffer
, str
->buffer
, i
* sizeof (sal_Unicode
));
1389 for (sal_Int32 j
= 0; j
!= toLength
; ++j
) {
1390 assert(static_cast< unsigned char >(to
[j
]) <= 0x7F);
1391 (*newStr
)->buffer
[i
+ j
] = to
[j
];
1394 (*newStr
)->buffer
+ i
+ toLength
,
1395 str
->buffer
+ i
+ fromLength
,
1396 (str
->length
- i
- fromLength
) * sizeof (sal_Unicode
));
1398 rtl_uString_release(str
);
1404 void rtl_uString_newReplaceFirstUtf16LUtf16L(
1405 rtl_uString
** newStr
, rtl_uString
* str
, sal_Unicode
const * from
,
1406 sal_Int32 fromLength
, sal_Unicode
const * to
, sal_Int32 toLength
,
1407 sal_Int32
* index
) SAL_THROW_EXTERN_C()
1409 assert(str
!= nullptr);
1410 assert(index
!= nullptr);
1411 assert(*index
>= 0 && *index
<= str
->length
);
1412 assert(from
!= nullptr || fromLength
== 0);
1413 assert(fromLength
>= 0);
1414 assert(to
!= nullptr || toLength
== 0);
1415 assert(toLength
>= 0);
1416 sal_Int32 i
= rtl_ustr_indexOfStr_WithLength(
1417 str
->buffer
+ *index
, str
->length
- *index
, from
, fromLength
);
1419 rtl_uString_assign(newStr
, str
);
1421 assert(i
<= str
->length
- *index
);
1423 assert(fromLength
<= str
->length
);
1424 if (str
->length
- fromLength
> SAL_MAX_INT32
- toLength
) {
1425 rtl_uString_release(*newStr
);
1428 sal_Int32 n
= str
->length
- fromLength
+ toLength
;
1429 rtl_uString_acquire(str
); // in case *newStr == str
1430 rtl_uString_new_WithLength(newStr
, n
);
1431 if (n
!= 0 && /*TODO:*/ *newStr
!= nullptr) {
1432 (*newStr
)->length
= n
;
1433 assert(i
>= 0 && i
< str
->length
);
1435 (*newStr
)->buffer
, str
->buffer
, i
* sizeof (sal_Unicode
));
1436 if (toLength
!= 0) {
1438 (*newStr
)->buffer
+ i
, to
, toLength
* sizeof (sal_Unicode
));
1441 (*newStr
)->buffer
+ i
+ toLength
,
1442 str
->buffer
+ i
+ fromLength
,
1443 (str
->length
- i
- fromLength
) * sizeof (sal_Unicode
));
1445 rtl_uString_release(str
);
1451 void rtl_uString_newReplaceAll(
1452 rtl_uString
** newStr
, rtl_uString
* str
, rtl_uString
const * from
,
1453 rtl_uString
const * to
) SAL_THROW_EXTERN_C()
1455 rtl_uString_newReplaceAllFromIndex( newStr
, str
, from
, to
, 0 );
1458 void rtl_uString_newReplaceAllFromIndex(
1459 rtl_uString
** newStr
, rtl_uString
* str
, rtl_uString
const * from
,
1460 rtl_uString
const * to
, sal_Int32 fromIndex
) SAL_THROW_EXTERN_C()
1462 assert(to
!= nullptr);
1463 assert(fromIndex
>= 0 && fromIndex
<= str
->length
);
1464 rtl_uString_assign(newStr
, str
);
1465 for (sal_Int32 i
= fromIndex
;; i
+= to
->length
) {
1466 rtl_uString_newReplaceFirst(newStr
, *newStr
, from
, to
, &i
);
1473 void rtl_uString_newReplaceAllAsciiL(
1474 rtl_uString
** newStr
, rtl_uString
* str
, char const * from
,
1475 sal_Int32 fromLength
, rtl_uString
const * to
) SAL_THROW_EXTERN_C()
1477 assert(to
!= nullptr);
1478 rtl_uString_assign(newStr
, str
);
1479 for (sal_Int32 i
= 0;; i
+= to
->length
) {
1480 rtl_uString_newReplaceFirstAsciiL(
1481 newStr
, *newStr
, from
, fromLength
, to
, &i
);
1488 void rtl_uString_newReplaceAllToAsciiL(
1489 rtl_uString
** newStr
, rtl_uString
* str
, rtl_uString
const * from
,
1490 char const * to
, sal_Int32 toLength
) SAL_THROW_EXTERN_C()
1492 assert(from
!= nullptr);
1493 rtl_uString_assign(newStr
, str
);
1494 for (sal_Int32 i
= 0;; i
+= toLength
) {
1495 rtl_uString_newReplaceFirstToAsciiL(
1496 newStr
, *newStr
, from
, to
, toLength
, &i
);
1503 void rtl_uString_newReplaceAllAsciiLAsciiL(
1504 rtl_uString
** newStr
, rtl_uString
* str
, char const * from
,
1505 sal_Int32 fromLength
, char const * to
, sal_Int32 toLength
)
1506 SAL_THROW_EXTERN_C()
1508 assert(toLength
>= 0);
1509 rtl_uString_assign(newStr
, str
);
1510 for (sal_Int32 i
= 0;; i
+= toLength
) {
1511 rtl_uString_newReplaceFirstAsciiLAsciiL(
1512 newStr
, *newStr
, from
, fromLength
, to
, toLength
, &i
);
1519 void rtl_uString_newReplaceAllAsciiLUtf16L(
1520 rtl_uString
** newStr
, rtl_uString
* str
, char const * from
,
1521 sal_Int32 fromLength
, sal_Unicode
const * to
, sal_Int32 toLength
)
1522 SAL_THROW_EXTERN_C()
1524 assert(toLength
>= 0);
1525 rtl_uString_assign(newStr
, str
);
1526 for (sal_Int32 i
= 0;; i
+= toLength
) {
1527 rtl_uString_newReplaceFirstAsciiLUtf16L(
1528 newStr
, *newStr
, from
, fromLength
, to
, toLength
, &i
);
1529 if (i
== -1 || *newStr
== nullptr) {
1535 void rtl_uString_newReplaceAllUtf16LAsciiL(
1536 rtl_uString
** newStr
, rtl_uString
* str
, sal_Unicode
const * from
,
1537 sal_Int32 fromLength
, char const * to
, sal_Int32 toLength
)
1538 SAL_THROW_EXTERN_C()
1540 assert(toLength
>= 0);
1541 rtl_uString_assign(newStr
, str
);
1542 for (sal_Int32 i
= 0;; i
+= toLength
) {
1543 rtl_uString_newReplaceFirstUtf16LAsciiL(
1544 newStr
, *newStr
, from
, fromLength
, to
, toLength
, &i
);
1545 if (i
== -1 || *newStr
== nullptr) {
1551 void rtl_uString_newReplaceAllUtf16LUtf16L(
1552 rtl_uString
** newStr
, rtl_uString
* str
, sal_Unicode
const * from
,
1553 sal_Int32 fromLength
, sal_Unicode
const * to
, sal_Int32 toLength
)
1554 SAL_THROW_EXTERN_C()
1556 rtl_uString_newReplaceAllFromIndexUtf16LUtf16L(newStr
, str
, from
, fromLength
, to
, toLength
, 0);
1559 void rtl_uString_newReplaceAllFromIndexUtf16LUtf16L(
1560 rtl_uString
** newStr
, rtl_uString
* str
, sal_Unicode
const * from
,
1561 sal_Int32 fromLength
, sal_Unicode
const * to
, sal_Int32 toLength
, sal_Int32 fromIndex
)
1562 SAL_THROW_EXTERN_C()
1564 assert(toLength
>= 0);
1565 assert(fromIndex
>= 0 && fromIndex
<= str
->length
);
1566 rtl_uString_assign(newStr
, str
);
1567 for (sal_Int32 i
= fromIndex
;; i
+= toLength
) {
1568 rtl_uString_newReplaceFirstUtf16LUtf16L(
1569 newStr
, *newStr
, from
, fromLength
, to
, toLength
, &i
);
1570 if (i
== -1 || *newStr
== nullptr) {
1576 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */