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 <config_options.h>
29 #include <o3tl/intcmp.hxx>
30 #include <o3tl/safeint.hxx>
31 #include <o3tl/string_view.hxx>
32 #include <osl/diagnose.h>
33 #include <osl/interlck.h>
34 #include <osl/mutex.h>
35 #include <rtl/tencinfo.h>
38 #include <sal/alloca.h>
39 #include <sal/log.hxx>
43 #include <rtl/character.hxx>
44 #include <rtl/ustring.h>
49 // Temporary check to verify that the #pragma pack around rtl_uString is indeed cargo cult and can
51 static_assert(alignof (rtl_uString
) == 4);
52 static_assert(sizeof (rtl_uString
) == 12);
55 /* ======================================================================= */
58 #define RTL_LOG_STRING_BITS 16
61 #include "strtmpl.hxx"
63 /* ======================================================================= */
65 sal_Int32
rtl_ustr_indexOfAscii_WithLength(
66 sal_Unicode
const * str
, sal_Int32 len
,
67 char const * subStr
, sal_Int32 subLen
) SAL_THROW_EXTERN_C()
69 return rtl::str::indexOfStr_WithLength(str
, len
, subStr
, subLen
);
72 sal_Int32
rtl_ustr_lastIndexOfAscii_WithLength(
73 sal_Unicode
const * str
, sal_Int32 len
,
74 char const * subStr
, sal_Int32 subLen
) SAL_THROW_EXTERN_C()
78 if (subLen
> 0 && subLen
<= len
) {
80 for (i
= len
- subLen
; i
>= 0; --i
) {
81 if (rtl_ustr_asciil_reverseEquals_WithLength(
82 str
+ i
, subStr
, subLen
))
91 sal_Int32 SAL_CALL
rtl_ustr_valueOfFloat(sal_Unicode
* pStr
, float f
)
94 return rtl::str::valueOfFP
<RTL_USTR_MAX_VALUEOFFLOAT
>(pStr
, f
);
97 sal_Int32 SAL_CALL
rtl_ustr_valueOfDouble(sal_Unicode
* pStr
, double d
)
100 return rtl::str::valueOfFP
<RTL_USTR_MAX_VALUEOFDOUBLE
>(pStr
, d
);
105 // Avoid -fsanitize=undefined warning e.g. "runtime error: value 1e+99 is
106 // outside the range of representable values of type 'float'" with Clang prior to
107 // <https://github.com/llvm/llvm-project/commit/9e52c43090f8cd980167bbd2719878ae36bcf6b5> "Treat the
108 // range of representable values of floating-point types as [-inf, +inf] not as [-max, +max]"
109 // (ENABLE_RUNTIME_OPTIMIZATIONS is an approximation for checking whether building is done without
110 // -fsanitize=undefined):
111 float doubleToFloat(double x
) {
112 #if !defined __clang__ || __clang_major__ >= 9 || ENABLE_RUNTIME_OPTIMIZATIONS
113 return static_cast<float>(x
);
116 x
< -std::numeric_limits
<float>::max()
117 ? -std::numeric_limits
<float>::infinity()
118 : x
> std::numeric_limits
<float>::max()
119 ? std::numeric_limits
<float>::infinity()
120 : static_cast<float>(x
);
126 float SAL_CALL
rtl_ustr_toFloat(sal_Unicode
const * pStr
) SAL_THROW_EXTERN_C()
129 return doubleToFloat(rtl_math_uStringToDouble(pStr
,
130 pStr
+ rtl_ustr_getLength(pStr
),
131 '.', 0, nullptr, nullptr));
134 double SAL_CALL
rtl_ustr_toDouble(sal_Unicode
const * pStr
) SAL_THROW_EXTERN_C()
137 return rtl_math_uStringToDouble(pStr
, pStr
+ rtl_ustr_getLength(pStr
), '.',
138 0, nullptr, nullptr);
141 /* ======================================================================= */
143 sal_Int32 SAL_CALL
rtl_ustr_ascii_compare( const sal_Unicode
* pStr1
,
147 return rtl::str::compare(rtl::str::null_terminated(pStr1
), rtl::str::null_terminated(pStr2
),
148 rtl::str::CompareNormal(), rtl::str::noShortening
);
151 /* ----------------------------------------------------------------------- */
153 sal_Int32 SAL_CALL
rtl_ustr_ascii_compare_WithLength( const sal_Unicode
* pStr1
,
158 return rtl::str::compare(rtl::str::with_length(pStr1
, nStr1Len
),
159 rtl::str::null_terminated(pStr2
),
160 rtl::str::CompareNormal(), rtl::str::noShortening
);
163 /* ----------------------------------------------------------------------- */
165 sal_Int32 SAL_CALL
rtl_ustr_ascii_shortenedCompare_WithLength( const sal_Unicode
* pStr1
,
168 sal_Int32 nShortenedLength
)
171 return rtl::str::compare(rtl::str::with_length(pStr1
, nStr1Len
),
172 rtl::str::null_terminated(pStr2
),
173 rtl::str::CompareNormal(), nShortenedLength
);
176 /* ----------------------------------------------------------------------- */
178 sal_Int32 SAL_CALL
rtl_ustr_asciil_reverseCompare_WithLength( const sal_Unicode
* pStr1
,
184 return rtl::str::reverseCompare_WithLengths(pStr1
, nStr1Len
, pStr2
, nStr2Len
,
185 rtl::str::CompareNormal());
188 /* ----------------------------------------------------------------------- */
190 sal_Bool SAL_CALL
rtl_ustr_asciil_reverseEquals_WithLength( const sal_Unicode
* pStr1
,
195 assert(nStrLen
>= 0);
196 const sal_Unicode
* pStr1Run
= pStr1
+nStrLen
;
197 const char* pStr2Run
= pStr2
+nStrLen
;
198 while ( pStr1
< pStr1Run
)
202 SAL_WARN_IF( !rtl::isAscii(static_cast<unsigned char>(*pStr2Run
)), "rtl.string",
203 "rtl_ustr_asciil_reverseEquals_WithLength - Found char > 127" );
204 if( *pStr1Run
!= static_cast<sal_Unicode
>(*pStr2Run
) )
211 /* ----------------------------------------------------------------------- */
213 sal_Int32 SAL_CALL
rtl_ustr_ascii_compareIgnoreAsciiCase( const sal_Unicode
* pStr1
,
217 return rtl::str::compare(rtl::str::null_terminated(pStr1
), rtl::str::null_terminated(pStr2
),
218 rtl::str::CompareIgnoreAsciiCase(), rtl::str::noShortening
);
221 /* ----------------------------------------------------------------------- */
223 sal_Int32 SAL_CALL
rtl_ustr_ascii_compareIgnoreAsciiCase_WithLength( const sal_Unicode
* pStr1
,
228 return rtl::str::compare(rtl::str::with_length(pStr1
, nStr1Len
),
229 rtl::str::null_terminated(pStr2
),
230 rtl::str::CompareIgnoreAsciiCase(), rtl::str::noShortening
);
233 sal_Int32
rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
234 sal_Unicode
const * first
, sal_Int32 firstLen
,
235 char const * second
, sal_Int32 secondLen
) SAL_THROW_EXTERN_C()
237 return rtl::str::compare(rtl::str::with_length(first
, firstLen
),
238 rtl::str::with_length(second
, secondLen
),
239 rtl::str::CompareIgnoreAsciiCase(), rtl::str::noShortening
);
242 /* ----------------------------------------------------------------------- */
244 sal_Int32 SAL_CALL
rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( const sal_Unicode
* pStr1
,
247 sal_Int32 nShortenedLength
)
250 return rtl::str::compare(rtl::str::with_length(pStr1
, nStr1Len
),
251 rtl::str::null_terminated(pStr2
),
252 rtl::str::CompareIgnoreAsciiCase(), nShortenedLength
);
255 /* ----------------------------------------------------------------------- */
257 void SAL_CALL
rtl_uString_newFromAscii( rtl_uString
** ppThis
,
258 const char* pCharStr
)
262 sal_Int32 nLen
= pCharStr
? rtl::str::getLength(pCharStr
) : 0;
266 rtl_uString_new( ppThis
);
271 rtl_uString_release( *ppThis
);
273 *ppThis
= rtl_uString_ImplAlloc( nLen
);
274 OSL_ASSERT(*ppThis
!= nullptr);
278 sal_Unicode
* pBuffer
= (*ppThis
)->buffer
;
281 assert(static_cast<unsigned char>(*pCharStr
) < 0x80); // ASCII range
282 *pBuffer
= *pCharStr
;
288 RTL_LOG_STRING_NEW( *ppThis
);
291 void SAL_CALL
rtl_uString_newFromCodePoints(
292 rtl_uString
** newString
, sal_uInt32
const * codePoints
,
293 sal_Int32 codePointCount
) SAL_THROW_EXTERN_C()
298 assert(newString
!= nullptr);
299 assert((codePoints
!= nullptr || codePointCount
== 0) && codePointCount
>= 0);
300 if (codePointCount
== 0) {
301 rtl_uString_new(newString
);
304 if (*newString
!= nullptr) {
305 rtl_uString_release(*newString
);
308 for (i
= 0; i
< codePointCount
; ++i
) {
309 OSL_ASSERT(rtl::isUnicodeCodePoint(codePoints
[i
]));
310 if (codePoints
[i
] >= 0x10000) {
314 /* Builds on the assumption that sal_Int32 uses 32 bit two's complement
315 representation with wrap around (the necessary number of UTF-16 code
316 units will be no larger than 2 * SAL_MAX_INT32, represented as
319 // coverity[dead_error_begin] - assumes wrap around
320 *newString
= nullptr;
323 *newString
= rtl_uString_ImplAlloc(n
);
324 if (*newString
== nullptr) {
327 p
= (*newString
)->buffer
;
328 for (i
= 0; i
< codePointCount
; ++i
) {
329 p
+= rtl::splitSurrogates(codePoints
[i
], p
);
331 RTL_LOG_STRING_NEW( *newString
);
334 void rtl_uString_newConcatAsciiL(
335 rtl_uString
** newString
, rtl_uString
* left
, char const * right
,
336 sal_Int32 rightLength
)
338 rtl::str::newConcat(newString
, left
, right
, rightLength
);
341 void rtl_uString_newConcatUtf16L(
342 rtl_uString
** newString
, rtl_uString
* left
, sal_Unicode
const * right
,
343 sal_Int32 rightLength
)
345 rtl::str::newConcat(newString
, left
, right
, rightLength
);
348 /* ======================================================================= */
350 static int rtl_ImplGetFastUTF8UnicodeLen( const char* pStr
, sal_Int32 nLen
, bool * ascii
)
358 while ( pStr
< pEndStr
)
360 unsigned char c
= static_cast<unsigned char>(*pStr
);
366 if ( (c
& 0xE0) == 0xC0 )
368 else if ( (c
& 0xF0) == 0xE0 )
370 else if ( (c
& 0xF8) == 0xF0 )
372 else if ( (c
& 0xFC) == 0xF8 )
374 else if ( (c
& 0xFE) == 0xFC )
387 /* ----------------------------------------------------------------------- */
389 static void rtl_string2UString_status( rtl_uString
** ppThis
,
392 rtl_TextEncoding eTextEncoding
,
393 sal_uInt32 nCvtFlags
,
396 OSL_ENSURE(nLen
== 0 || rtl_isOctetTextEncoding(eTextEncoding
),
397 "rtl_string2UString_status() - Wrong TextEncoding" );
401 rtl_uString_new( ppThis
);
402 if (pInfo
!= nullptr) {
409 rtl_uString_release( *ppThis
);
411 /* Optimization for US-ASCII */
412 if ( eTextEncoding
== RTL_TEXTENCODING_ASCII_US
)
414 sal_Unicode
* pBuffer
;
415 *ppThis
= rtl_uString_ImplAlloc( nLen
);
416 if (*ppThis
== nullptr) {
417 if (pInfo
!= nullptr) {
418 *pInfo
= RTL_TEXTTOUNICODE_INFO_ERROR
|
419 RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOOSMALL
;
423 pBuffer
= (*ppThis
)->buffer
;
424 sal_Int32
nLenCopy(nLen
);
425 const char *pStrCopy(pStr
);
428 /* Check ASCII range */
429 if (static_cast<unsigned char>(*pStrCopy
) > 127)
431 rtl_uString_release(*ppThis
);
432 goto retry
; // cancel loop - try again with the converter
435 *pBuffer
= *pStrCopy
;
441 if (pInfo
!= nullptr) {
444 RTL_LOG_STRING_NEW( *ppThis
);
450 rtl_uString
* pTemp2
= nullptr;
451 rtl_TextToUnicodeConverter hConverter
;
457 /* Optimization for UTF-8 - we try to calculate the exact length */
458 /* For all other encoding we try the maximum - and reallocate
459 the buffer if needed */
460 if ( eTextEncoding
== RTL_TEXTENCODING_UTF8
)
463 nNewLen
= rtl_ImplGetFastUTF8UnicodeLen( pStr
, nLen
, &ascii
);
464 /* Includes the string only ASCII, then we could copy
468 sal_Unicode
* pBuffer
;
469 *ppThis
= rtl_uString_ImplAlloc( nLen
);
470 if (*ppThis
== nullptr)
472 if (pInfo
!= nullptr) {
473 *pInfo
= RTL_TEXTTOUNICODE_INFO_ERROR
|
474 RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOOSMALL
;
478 pBuffer
= (*ppThis
)->buffer
;
481 assert((static_cast<unsigned char>(*pStr
)) <= 127);
488 if (pInfo
!= nullptr) {
491 RTL_LOG_STRING_NEW( *ppThis
);
498 nCvtFlags
|= RTL_TEXTTOUNICODE_FLAGS_FLUSH
;
499 hConverter
= rtl_createTextToUnicodeConverter( eTextEncoding
);
501 pTemp
= rtl_uString_ImplAlloc( nNewLen
);
502 if (pTemp
== nullptr) {
503 if (pInfo
!= nullptr) {
504 *pInfo
= RTL_TEXTTOUNICODE_INFO_ERROR
|
505 RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOOSMALL
;
509 nDestChars
= rtl_convertTextToUnicode( hConverter
, nullptr,
511 pTemp
->buffer
, nNewLen
,
513 &nInfo
, &nSrcBytes
);
515 /* Buffer not big enough, try again with enough space */
516 /* Shouldn't be the case, but if we get textencoding which
517 could results in more unicode characters we have this
518 code here. Could be the case for apple encodings */
519 while ( nInfo
& RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOOSMALL
)
521 rtl_freeString( pTemp
);
523 pTemp
= rtl_uString_ImplAlloc( nNewLen
);
524 if (pTemp
== nullptr) {
525 if (pInfo
!= nullptr) {
526 *pInfo
= RTL_TEXTTOUNICODE_INFO_ERROR
|
527 RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOOSMALL
;
531 nDestChars
= rtl_convertTextToUnicode( hConverter
, nullptr,
533 pTemp
->buffer
, nNewLen
,
535 &nInfo
, &nSrcBytes
);
541 /* Set the buffer to the correct size or if there is too
542 much overhead, reallocate to the correct size */
543 if ( nNewLen
> nDestChars
+8 )
545 pTemp2
= rtl_uString_ImplAlloc( nDestChars
);
547 if (pTemp2
!= nullptr)
549 rtl::str::Copy(pTemp2
->buffer
, pTemp
->buffer
, nDestChars
);
550 rtl_freeString(pTemp
);
555 pTemp
->length
= nDestChars
;
556 pTemp
->buffer
[nDestChars
] = 0;
559 rtl_destroyTextToUnicodeConverter( hConverter
);
562 /* Results the conversion in an empty buffer -
563 create an empty string */
564 if ( pTemp
&& !nDestChars
)
565 rtl_uString_new( ppThis
);
568 RTL_LOG_STRING_NEW( *ppThis
);
571 void SAL_CALL
rtl_string2UString( rtl_uString
** ppThis
,
574 rtl_TextEncoding eTextEncoding
,
575 sal_uInt32 nCvtFlags
) SAL_THROW_EXTERN_C()
579 rtl_string2UString_status( ppThis
, pStr
, nLen
, eTextEncoding
,
580 nCvtFlags
, nullptr );
583 /* ----------------------------------------------------------------------- */
597 static oslMutex pPoolGuard
= osl_createMutex();
602 /* returns true if we found a dup in the pool */
603 static void rtl_ustring_intern_internal( rtl_uString
** newStr
,
605 StrLifecycle can_return
)
609 pPoolMutex
= getInternMutex();
611 osl_acquireMutex( pPoolMutex
);
613 *newStr
= rtl_str_hash_intern (str
, can_return
);
615 osl_releaseMutex( pPoolMutex
);
617 RTL_LOG_STRING_INTERN_NEW(*newStr
, str
);
619 if( can_return
&& *newStr
!= str
)
620 { /* we dupped, then found a match */
621 rtl_freeString( str
);
625 void SAL_CALL
rtl_uString_intern( rtl_uString
** newStr
,
626 rtl_uString
* str
) SAL_THROW_EXTERN_C()
630 if (SAL_STRING_IS_INTERN(str
))
632 rtl::str::acquire(str
);
637 rtl_uString
*pOrg
= *newStr
;
639 rtl_ustring_intern_internal( newStr
, str
, CANNOT_RETURN
);
641 rtl_uString_release (pOrg
);
645 static int rtl_canGuessUOutputLength( int len
, rtl_TextEncoding eTextEncoding
)
647 // FIXME: Maybe we should use a bit flag in the higher bits of the
648 // eTextEncoding value itself to determine the encoding type. But if we
649 // do, be sure to mask the value in certain places that expect the values
650 // to be numbered serially from 0 and up. One such place is
651 // Impl_getTextEncodingData().
653 switch ( eTextEncoding
)
655 // 1 to 1 (with no zero elements)
656 case RTL_TEXTENCODING_IBM_437
:
657 case RTL_TEXTENCODING_IBM_850
:
658 case RTL_TEXTENCODING_IBM_860
:
659 case RTL_TEXTENCODING_IBM_861
:
660 case RTL_TEXTENCODING_IBM_863
:
661 case RTL_TEXTENCODING_IBM_865
:
667 void SAL_CALL
rtl_uString_internConvert( rtl_uString
** newStr
,
670 rtl_TextEncoding eTextEncoding
,
671 sal_uInt32 convertFlags
,
677 rtl_uString
*scratch
;
681 rtl_uString_release (*newStr
);
686 { // try various optimisations
688 if ( eTextEncoding
== RTL_TEXTENCODING_ASCII_US
)
691 rtl_uString
*pScratch
;
692 pScratch
= static_cast< rtl_uString
* >(
693 alloca(sizeof (rtl_uString
) + len
* sizeof (sal_Unicode
)));
694 for (i
= 0; i
< len
; i
++)
696 /* Check ASCII range */
697 SAL_WARN_IF( !rtl::isAscii(static_cast<unsigned char>(str
[i
])), "rtl.string",
698 "rtl_ustring_internConvert() - Found char > 127 and RTL_TEXTENCODING_ASCII_US is specified" );
699 pScratch
->buffer
[i
] = str
[i
];
701 pScratch
->length
= len
;
702 rtl_ustring_intern_internal( newStr
, pScratch
, CANNOT_RETURN
);
705 if ( (ulen
= rtl_canGuessUOutputLength(len
, eTextEncoding
)) != 0 )
707 rtl_uString
*pScratch
;
708 rtl_TextToUnicodeConverter hConverter
;
712 pScratch
= static_cast< rtl_uString
* >(
714 sizeof (rtl_uString
) + ulen
* sizeof (sal_Unicode
)));
716 hConverter
= rtl_createTextToUnicodeConverter( eTextEncoding
);
717 rtl_convertTextToUnicode(
718 hConverter
, nullptr, str
, len
, pScratch
->buffer
, ulen
, convertFlags
, &nInfo
, &nSrcBytes
);
719 rtl_destroyTextToUnicodeConverter( hConverter
);
724 pScratch
->length
= ulen
;
725 rtl_ustring_intern_internal( newStr
, pScratch
, CANNOT_RETURN
);
729 /* FIXME: we want a nice UTF-8 / alloca shortcut here */
733 rtl_string2UString_status( &scratch
, str
, len
, eTextEncoding
, convertFlags
,
738 rtl_ustring_intern_internal( newStr
, scratch
, CAN_RETURN
);
741 void internRelease (rtl_uString
*pThis
)
743 rtl_uString
*pFree
= nullptr;
744 if ( SAL_STRING_REFCOUNT(
745 osl_atomic_decrement( &(pThis
->refCount
) ) ) == 0)
747 RTL_LOG_STRING_INTERN_DELETE(pThis
);
748 oslMutex pPoolMutex
= getInternMutex();
749 osl_acquireMutex( pPoolMutex
);
751 rtl_str_hash_remove (pThis
);
753 /* May have been separately acquired */
754 if ( SAL_STRING_REFCOUNT(
755 osl_atomic_increment( &(pThis
->refCount
) ) ) == 1 )
757 /* we got the last ref */
760 else /* very unusual */
762 internRelease (pThis
);
765 osl_releaseMutex( pPoolMutex
);
768 rtl_freeString (pFree
);
771 sal_uInt32 SAL_CALL
rtl_uString_iterateCodePoints(
772 rtl_uString
const * string
, sal_Int32
* indexUtf16
,
773 sal_Int32 incrementCodePoints
)
775 assert(string
!= nullptr && indexUtf16
!= nullptr);
778 && o3tl::cmp_less_equal(*indexUtf16
, std::numeric_limits
<std::size_t>::max()));
779 // using o3tl::cmp_less_equal nicely avoids potential
780 // -Wtautological-constant-out-of-range-compare
781 auto const cp
= o3tl::iterateCodePoints(
782 std::u16string_view(string
->buffer
, string
->length
), indexUtf16
, incrementCodePoints
);
786 sal_Bool
rtl_convertStringToUString(
787 rtl_uString
** target
, char const * source
, sal_Int32 length
,
788 rtl_TextEncoding encoding
, sal_uInt32 flags
) SAL_THROW_EXTERN_C()
793 rtl_string2UString_status(target
, source
, length
, encoding
, flags
, &info
);
794 return (info
& RTL_TEXTTOUNICODE_INFO_ERROR
) == 0;
797 void rtl_uString_newReplaceFirst(
798 rtl_uString
** newStr
, rtl_uString
* str
, rtl_uString
const * from
,
799 rtl_uString
const * to
, sal_Int32
* index
) SAL_THROW_EXTERN_C()
801 assert(from
!= nullptr);
802 assert(to
!= nullptr);
803 rtl_uString_newReplaceFirstUtf16LUtf16L(newStr
, str
, from
->buffer
, from
->length
, to
->buffer
,
807 void rtl_uString_newReplaceFirstAsciiL(
808 rtl_uString
** newStr
, rtl_uString
* str
, char const * from
,
809 sal_Int32 fromLength
, rtl_uString
const * to
, sal_Int32
* index
)
812 assert(to
!= nullptr);
813 rtl_uString_newReplaceFirstAsciiLUtf16L(newStr
, str
, from
, fromLength
, to
->buffer
, to
->length
,
817 void rtl_uString_newReplaceFirstToAsciiL(
818 rtl_uString
** newStr
, rtl_uString
* str
, rtl_uString
const * from
,
819 char const * to
, sal_Int32 toLength
, sal_Int32
* index
)
822 assert(from
!= nullptr);
823 rtl_uString_newReplaceFirstUtf16LAsciiL(newStr
, str
, from
->buffer
, from
->length
, to
, toLength
,
827 void rtl_uString_newReplaceFirstAsciiLAsciiL(
828 rtl_uString
** newStr
, rtl_uString
* str
, char const * from
,
829 sal_Int32 fromLength
, char const * to
, sal_Int32 toLength
,
830 sal_Int32
* index
) SAL_THROW_EXTERN_C()
832 assert(index
!= nullptr);
833 rtl::str::newReplaceFirst(newStr
, str
, from
, fromLength
, to
, toLength
, *index
);
836 void rtl_uString_newReplaceFirstAsciiLUtf16L(
837 rtl_uString
** newStr
, rtl_uString
* str
, char const * from
,
838 sal_Int32 fromLength
, sal_Unicode
const * to
, sal_Int32 toLength
,
839 sal_Int32
* index
) SAL_THROW_EXTERN_C()
841 assert(index
!= nullptr);
842 rtl::str::newReplaceFirst(newStr
, str
, from
, fromLength
, to
, toLength
, *index
);
845 void rtl_uString_newReplaceFirstUtf16LAsciiL(
846 rtl_uString
** newStr
, rtl_uString
* str
, sal_Unicode
const * from
,
847 sal_Int32 fromLength
, char const * to
, sal_Int32 toLength
,
848 sal_Int32
* index
) SAL_THROW_EXTERN_C()
850 assert(index
!= nullptr);
851 rtl::str::newReplaceFirst(newStr
, str
, from
, fromLength
, to
, toLength
, *index
);
854 void rtl_uString_newReplaceFirstUtf16LUtf16L(
855 rtl_uString
** newStr
, rtl_uString
* str
, sal_Unicode
const * from
,
856 sal_Int32 fromLength
, sal_Unicode
const * to
, sal_Int32 toLength
,
857 sal_Int32
* index
) SAL_THROW_EXTERN_C()
859 assert(index
!= nullptr);
860 rtl::str::newReplaceFirst(newStr
, str
, from
, fromLength
, to
, toLength
, *index
);
863 void rtl_uString_newReplaceAll(
864 rtl_uString
** newStr
, rtl_uString
* str
, rtl_uString
const * from
,
865 rtl_uString
const * to
) SAL_THROW_EXTERN_C()
867 rtl_uString_newReplaceAllFromIndex( newStr
, str
, from
, to
, 0 );
870 void rtl_uString_newReplaceAllFromIndex(
871 rtl_uString
** newStr
, rtl_uString
* str
, rtl_uString
const * from
,
872 rtl_uString
const * to
, sal_Int32 fromIndex
) SAL_THROW_EXTERN_C()
874 assert(to
!= nullptr);
875 assert(fromIndex
>= 0 && fromIndex
<= str
->length
);
876 rtl_uString_newReplaceAllFromIndexUtf16LUtf16L(newStr
, str
, from
->buffer
, from
->length
,
877 to
->buffer
, to
->length
, fromIndex
);
880 void rtl_uString_newReplaceAllAsciiL(
881 rtl_uString
** newStr
, rtl_uString
* str
, char const * from
,
882 sal_Int32 fromLength
, rtl_uString
const * to
) SAL_THROW_EXTERN_C()
884 assert(to
!= nullptr);
885 rtl_uString_newReplaceAllAsciiLUtf16L(newStr
, str
, from
, fromLength
, to
->buffer
, to
->length
);
888 void rtl_uString_newReplaceAllToAsciiL(
889 rtl_uString
** newStr
, rtl_uString
* str
, rtl_uString
const * from
,
890 char const * to
, sal_Int32 toLength
) SAL_THROW_EXTERN_C()
892 assert(from
!= nullptr);
893 rtl_uString_newReplaceAllUtf16LAsciiL(newStr
, str
, from
->buffer
, from
->length
, to
, toLength
);
896 void rtl_uString_newReplaceAllAsciiLAsciiL(
897 rtl_uString
** newStr
, rtl_uString
* str
, char const * from
,
898 sal_Int32 fromLength
, char const * to
, sal_Int32 toLength
)
901 rtl::str::newReplaceAllFromIndex(newStr
, str
, from
, fromLength
, to
, toLength
, 0);
904 void rtl_uString_newReplaceAllAsciiLUtf16L(
905 rtl_uString
** newStr
, rtl_uString
* str
, char const * from
,
906 sal_Int32 fromLength
, sal_Unicode
const * to
, sal_Int32 toLength
)
909 rtl::str::newReplaceAllFromIndex(newStr
, str
, from
, fromLength
, to
, toLength
, 0);
912 void rtl_uString_newReplaceAllUtf16LAsciiL(
913 rtl_uString
** newStr
, rtl_uString
* str
, sal_Unicode
const * from
,
914 sal_Int32 fromLength
, char const * to
, sal_Int32 toLength
)
917 rtl::str::newReplaceAllFromIndex(newStr
, str
, from
, fromLength
, to
, toLength
, 0);
920 void rtl_uString_newReplaceAllUtf16LUtf16L(
921 rtl_uString
** newStr
, rtl_uString
* str
, sal_Unicode
const * from
,
922 sal_Int32 fromLength
, sal_Unicode
const * to
, sal_Int32 toLength
)
925 rtl_uString_newReplaceAllFromIndexUtf16LUtf16L(newStr
, str
, from
, fromLength
, to
, toLength
, 0);
928 void rtl_uString_newReplaceAllFromIndexUtf16LUtf16L(
929 rtl_uString
** newStr
, rtl_uString
* str
, sal_Unicode
const * from
,
930 sal_Int32 fromLength
, sal_Unicode
const * to
, sal_Int32 toLength
, sal_Int32 fromIndex
)
933 rtl::str::newReplaceAllFromIndex(newStr
, str
, from
, fromLength
, to
, toLength
, fromIndex
);
936 sal_Int32 SAL_CALL
rtl_ustr_getLength(const sal_Unicode
* pStr
) SAL_THROW_EXTERN_C()
938 return rtl::str::getLength(pStr
);
941 sal_Int32 SAL_CALL
rtl_ustr_compare(const sal_Unicode
* pStr1
, const sal_Unicode
* pStr2
)
944 return rtl::str::compare(rtl::str::null_terminated(pStr1
), rtl::str::null_terminated(pStr2
),
945 rtl::str::CompareNormal(), rtl::str::noShortening
);
948 sal_Int32 SAL_CALL
rtl_ustr_compare_WithLength(const sal_Unicode
* pStr1
, sal_Int32 nStr1Len
,
949 const sal_Unicode
* pStr2
, sal_Int32 nStr2Len
)
952 return rtl::str::compare(rtl::str::with_length(pStr1
, nStr1Len
),
953 rtl::str::with_length(pStr2
, nStr2Len
), rtl::str::CompareNormal(),
954 rtl::str::noShortening
);
957 sal_Int32 SAL_CALL
rtl_ustr_shortenedCompare_WithLength(
958 const sal_Unicode
* pStr1
, sal_Int32 nStr1Len
, const sal_Unicode
* pStr2
, sal_Int32 nStr2Len
,
959 sal_Int32 nShortenedLength
) SAL_THROW_EXTERN_C()
961 return rtl::str::compare(rtl::str::with_length(pStr1
, nStr1Len
),
962 rtl::str::with_length(pStr2
, nStr2Len
), rtl::str::CompareNormal(),
966 sal_Int32 SAL_CALL
rtl_ustr_reverseCompare_WithLength(const sal_Unicode
* pStr1
, sal_Int32 nStr1Len
,
967 const sal_Unicode
* pStr2
, sal_Int32 nStr2Len
)
970 return rtl::str::reverseCompare_WithLengths(pStr1
, nStr1Len
, pStr2
, nStr2Len
,
971 rtl::str::CompareNormal());
974 sal_Int32 SAL_CALL
rtl_ustr_compareIgnoreAsciiCase(const sal_Unicode
* pStr1
,
975 const sal_Unicode
* pStr2
) SAL_THROW_EXTERN_C()
977 return rtl::str::compare(rtl::str::null_terminated(pStr1
), rtl::str::null_terminated(pStr2
),
978 rtl::str::CompareIgnoreAsciiCase(), rtl::str::noShortening
);
981 sal_Int32 SAL_CALL
rtl_ustr_compareIgnoreAsciiCase_WithLength(const sal_Unicode
* pStr1
,
983 const sal_Unicode
* pStr2
,
987 return rtl::str::compare(rtl::str::with_length(pStr1
, nStr1Len
),
988 rtl::str::with_length(pStr2
, nStr2Len
),
989 rtl::str::CompareIgnoreAsciiCase(), rtl::str::noShortening
);
992 sal_Int32 SAL_CALL
rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength(
993 const sal_Unicode
* pStr1
, sal_Int32 nStr1Len
, const sal_Unicode
* pStr2
, sal_Int32 nStr2Len
,
994 sal_Int32 nShortenedLength
) SAL_THROW_EXTERN_C()
996 return rtl::str::compare(rtl::str::with_length(pStr1
, nStr1Len
),
997 rtl::str::with_length(pStr2
, nStr2Len
),
998 rtl::str::CompareIgnoreAsciiCase(), nShortenedLength
);
1001 sal_Int32 SAL_CALL
rtl_ustr_hashCode(const sal_Unicode
* pStr
) SAL_THROW_EXTERN_C()
1003 return rtl::str::hashCode(pStr
);
1006 sal_Int32 SAL_CALL
rtl_ustr_hashCode_WithLength(const sal_Unicode
* pStr
, sal_Int32 nLen
)
1007 SAL_THROW_EXTERN_C()
1009 return rtl::str::hashCode_WithLength(pStr
, nLen
);
1012 sal_Int32 SAL_CALL
rtl_ustr_indexOfChar(const sal_Unicode
* pStr
, sal_Unicode c
) SAL_THROW_EXTERN_C()
1014 return rtl::str::indexOfChar(pStr
, c
);
1017 sal_Int32 SAL_CALL
rtl_ustr_indexOfChar_WithLength(const sal_Unicode
* pStr
, sal_Int32 nLen
,
1018 sal_Unicode c
) SAL_THROW_EXTERN_C()
1020 return rtl::str::indexOfChar_WithLength(pStr
, nLen
, c
);
1023 sal_Int32 SAL_CALL
rtl_ustr_lastIndexOfChar(const sal_Unicode
* pStr
, sal_Unicode c
)
1024 SAL_THROW_EXTERN_C()
1026 return rtl::str::lastIndexOfChar(pStr
, c
);
1029 sal_Int32 SAL_CALL
rtl_ustr_lastIndexOfChar_WithLength(const sal_Unicode
* pStr
, sal_Int32 nLen
,
1030 sal_Unicode c
) SAL_THROW_EXTERN_C()
1032 return rtl::str::lastIndexOfChar_WithLength(pStr
, nLen
, c
);
1035 sal_Int32 SAL_CALL
rtl_ustr_indexOfStr(const sal_Unicode
* pStr
, const sal_Unicode
* pSubStr
)
1036 SAL_THROW_EXTERN_C()
1038 return rtl::str::indexOfStr(pStr
, pSubStr
);
1041 sal_Int32 SAL_CALL
rtl_ustr_indexOfStr_WithLength(const sal_Unicode
* pStr
, sal_Int32 nStrLen
,
1042 const sal_Unicode
* pSubStr
, sal_Int32 nSubLen
)
1043 SAL_THROW_EXTERN_C()
1045 return rtl::str::indexOfStr_WithLength(pStr
, nStrLen
, pSubStr
, nSubLen
);
1048 sal_Int32 SAL_CALL
rtl_ustr_lastIndexOfStr(const sal_Unicode
* pStr
, const sal_Unicode
* pSubStr
)
1049 SAL_THROW_EXTERN_C()
1051 return rtl::str::lastIndexOfStr(pStr
, pSubStr
);
1054 sal_Int32 SAL_CALL
rtl_ustr_lastIndexOfStr_WithLength(const sal_Unicode
* pStr
, sal_Int32 nStrLen
,
1055 const sal_Unicode
* pSubStr
, sal_Int32 nSubLen
)
1056 SAL_THROW_EXTERN_C()
1058 return rtl::str::lastIndexOfStr_WithLength(pStr
, nStrLen
, pSubStr
, nSubLen
);
1061 void SAL_CALL
rtl_ustr_replaceChar(sal_Unicode
* pStr
, sal_Unicode cOld
, sal_Unicode cNew
)
1062 SAL_THROW_EXTERN_C()
1064 return rtl::str::replaceChars(rtl::str::null_terminated(pStr
), rtl::str::FromTo(cOld
, cNew
));
1067 void SAL_CALL
rtl_ustr_replaceChar_WithLength(sal_Unicode
* pStr
, sal_Int32 nLen
, sal_Unicode cOld
,
1068 sal_Unicode cNew
) SAL_THROW_EXTERN_C()
1070 return rtl::str::replaceChars(rtl::str::with_length(pStr
, nLen
), rtl::str::FromTo(cOld
, cNew
));
1073 void SAL_CALL
rtl_ustr_toAsciiLowerCase(sal_Unicode
* pStr
) SAL_THROW_EXTERN_C()
1075 return rtl::str::replaceChars(rtl::str::null_terminated(pStr
), rtl::str::toAsciiLower
);
1078 void SAL_CALL
rtl_ustr_toAsciiLowerCase_WithLength(sal_Unicode
* pStr
, sal_Int32 nLen
)
1079 SAL_THROW_EXTERN_C()
1081 return rtl::str::replaceChars(rtl::str::with_length(pStr
, nLen
), rtl::str::toAsciiLower
);
1084 void SAL_CALL
rtl_ustr_toAsciiUpperCase(sal_Unicode
* pStr
) SAL_THROW_EXTERN_C()
1086 return rtl::str::replaceChars(rtl::str::null_terminated(pStr
), rtl::str::toAsciiUpper
);
1089 void SAL_CALL
rtl_ustr_toAsciiUpperCase_WithLength(sal_Unicode
* pStr
, sal_Int32 nLen
)
1090 SAL_THROW_EXTERN_C()
1092 return rtl::str::replaceChars(rtl::str::with_length(pStr
, nLen
), rtl::str::toAsciiUpper
);
1095 sal_Int32 SAL_CALL
rtl_ustr_trim(sal_Unicode
* pStr
) SAL_THROW_EXTERN_C()
1097 return rtl::str::trim(pStr
);
1100 sal_Int32 SAL_CALL
rtl_ustr_trim_WithLength(sal_Unicode
* pStr
, sal_Int32 nLen
) SAL_THROW_EXTERN_C()
1102 return rtl::str::trim_WithLength(pStr
, nLen
);
1105 sal_Int32 SAL_CALL
rtl_ustr_valueOfBoolean(sal_Unicode
* pStr
, sal_Bool b
) SAL_THROW_EXTERN_C()
1107 return rtl::str::valueOfBoolean(pStr
, b
);
1110 sal_Int32 SAL_CALL
rtl_ustr_valueOfChar(sal_Unicode
* pStr
, sal_Unicode c
) SAL_THROW_EXTERN_C()
1112 return rtl::str::valueOfChar(pStr
, c
);
1115 sal_Int32 SAL_CALL
rtl_ustr_valueOfInt32(sal_Unicode
* pStr
, sal_Int32 n
, sal_Int16 nRadix
)
1116 SAL_THROW_EXTERN_C()
1118 return rtl::str::valueOfInt
<RTL_USTR_MAX_VALUEOFINT32
>(pStr
, n
, nRadix
);
1121 sal_Int32 SAL_CALL
rtl_ustr_valueOfInt64(sal_Unicode
* pStr
, sal_Int64 n
, sal_Int16 nRadix
)
1122 SAL_THROW_EXTERN_C()
1124 return rtl::str::valueOfInt
<RTL_USTR_MAX_VALUEOFINT64
>(pStr
, n
, nRadix
);
1127 sal_Int32 SAL_CALL
rtl_ustr_valueOfUInt64(sal_Unicode
* pStr
, sal_uInt64 n
, sal_Int16 nRadix
)
1128 SAL_THROW_EXTERN_C()
1130 return rtl::str::valueOfInt
<RTL_USTR_MAX_VALUEOFUINT64
>(pStr
, n
, nRadix
);
1133 sal_Bool SAL_CALL
rtl_ustr_toBoolean(const sal_Unicode
* pStr
) SAL_THROW_EXTERN_C()
1135 return rtl::str::toBoolean(pStr
);
1138 sal_Int32 SAL_CALL
rtl_ustr_toInt32(const sal_Unicode
* pStr
, sal_Int16 nRadix
) SAL_THROW_EXTERN_C()
1140 return rtl::str::toInt
<sal_Int32
>(rtl::str::null_terminated(pStr
), nRadix
);
1143 sal_Int64 SAL_CALL
rtl_ustr_toInt64(const sal_Unicode
* pStr
, sal_Int16 nRadix
) SAL_THROW_EXTERN_C()
1145 return rtl::str::toInt
<sal_Int64
>(rtl::str::null_terminated(pStr
), nRadix
);
1148 sal_Int64 SAL_CALL
rtl_ustr_toInt64_WithLength(const sal_Unicode
* pStr
, sal_Int16 nRadix
,
1149 sal_Int32 nStrLength
) SAL_THROW_EXTERN_C()
1151 return rtl::str::toInt
<sal_Int64
>(rtl::str::with_length(pStr
, nStrLength
), nRadix
);
1154 sal_uInt32 SAL_CALL
rtl_ustr_toUInt32(const sal_Unicode
* pStr
, sal_Int16 nRadix
)
1155 SAL_THROW_EXTERN_C()
1157 return rtl::str::toInt
<sal_uInt32
>(rtl::str::null_terminated(pStr
), nRadix
);
1160 sal_uInt64 SAL_CALL
rtl_ustr_toUInt64(const sal_Unicode
* pStr
, sal_Int16 nRadix
)
1161 SAL_THROW_EXTERN_C()
1163 return rtl::str::toInt
<sal_uInt64
>(rtl::str::null_terminated(pStr
), nRadix
);
1166 rtl_uString
* rtl_uString_ImplAlloc(sal_Int32 nLen
)
1168 return rtl::str::Alloc
<rtl_uString
>(nLen
);
1171 void SAL_CALL
rtl_uString_acquire(rtl_uString
* pThis
) SAL_THROW_EXTERN_C()
1173 return rtl::str::acquire(pThis
);
1176 void SAL_CALL
rtl_uString_release(rtl_uString
* pThis
) SAL_THROW_EXTERN_C()
1178 return rtl::str::release(pThis
);
1181 void SAL_CALL
rtl_uString_new(rtl_uString
** ppThis
) SAL_THROW_EXTERN_C()
1183 return rtl::str::new_(ppThis
);
1186 rtl_uString
* SAL_CALL
rtl_uString_alloc(sal_Int32 nLen
) SAL_THROW_EXTERN_C()
1189 return rtl::str::Alloc
<rtl_uString
>(nLen
);
1192 void SAL_CALL
rtl_uString_new_WithLength(rtl_uString
** ppThis
, sal_Int32 nLen
) SAL_THROW_EXTERN_C()
1194 rtl::str::new_WithLength(ppThis
, nLen
);
1197 void SAL_CALL
rtl_uString_newFromString(rtl_uString
** ppThis
, const rtl_uString
* pStr
)
1198 SAL_THROW_EXTERN_C()
1200 rtl::str::newFromString(ppThis
, pStr
);
1203 void SAL_CALL
rtl_uString_newFromStr(rtl_uString
** ppThis
, const sal_Unicode
* pCharStr
)
1204 SAL_THROW_EXTERN_C()
1206 rtl::str::newFromStr(ppThis
, pCharStr
);
1209 void SAL_CALL
rtl_uString_newFromStr_WithLength(rtl_uString
** ppThis
, const sal_Unicode
* pCharStr
,
1210 sal_Int32 nLen
) SAL_THROW_EXTERN_C()
1212 rtl::str::newFromStr_WithLength(ppThis
, pCharStr
, nLen
);
1215 void SAL_CALL
rtl_uString_newFromSubString(rtl_uString
** ppThis
, const rtl_uString
* pFrom
,
1216 sal_Int32 beginIndex
, sal_Int32 count
)
1217 SAL_THROW_EXTERN_C()
1219 rtl::str::newFromSubString(ppThis
, pFrom
, beginIndex
, count
);
1222 // Used when creating from string literals.
1223 void SAL_CALL
rtl_uString_newFromLiteral(rtl_uString
** ppThis
, const char* pCharStr
, sal_Int32 nLen
,
1224 sal_Int32 allocExtra
) SAL_THROW_EXTERN_C()
1226 rtl::str::newFromStr_WithLength(ppThis
, pCharStr
, nLen
, allocExtra
);
1229 void SAL_CALL
rtl_uString_assign(rtl_uString
** ppThis
, rtl_uString
* pStr
) SAL_THROW_EXTERN_C()
1231 rtl::str::assign(ppThis
, pStr
);
1234 sal_Int32 SAL_CALL
rtl_uString_getLength(const rtl_uString
* pThis
) SAL_THROW_EXTERN_C()
1236 return rtl::str::getLength(pThis
);
1239 sal_Unicode
* SAL_CALL
rtl_uString_getStr(rtl_uString
* pThis
) SAL_THROW_EXTERN_C()
1241 return rtl::str::getStr(pThis
);
1244 void SAL_CALL
rtl_uString_newConcat(rtl_uString
** ppThis
, rtl_uString
* pLeft
, rtl_uString
* pRight
)
1245 SAL_THROW_EXTERN_C()
1247 rtl::str::newConcat(ppThis
, pLeft
, pRight
);
1250 void SAL_CALL
rtl_uString_ensureCapacity(rtl_uString
** ppThis
, sal_Int32 size
) SAL_THROW_EXTERN_C()
1252 rtl::str::ensureCapacity(ppThis
, size
);
1255 void SAL_CALL
rtl_uString_newReplaceStrAt(rtl_uString
** ppThis
, rtl_uString
* pStr
, sal_Int32 nIndex
,
1256 sal_Int32 nCount
, rtl_uString
* pNewSubStr
)
1257 SAL_THROW_EXTERN_C()
1259 rtl::str::newReplaceStrAt(ppThis
, pStr
, nIndex
, nCount
, pNewSubStr
);
1262 void SAL_CALL
rtl_uString_newReplaceStrAtUtf16L(rtl_uString
** ppThis
, rtl_uString
* pStr
, sal_Int32 nIndex
,
1263 sal_Int32 nCount
, sal_Unicode
const * subStr
, sal_Int32 substrLen
)
1264 SAL_THROW_EXTERN_C()
1266 rtl::str::newReplaceStrAt(ppThis
, pStr
, nIndex
, nCount
, subStr
, substrLen
);
1269 void SAL_CALL
rtl_uString_newReplace(rtl_uString
** ppThis
, rtl_uString
* pStr
, sal_Unicode cOld
,
1270 sal_Unicode cNew
) SAL_THROW_EXTERN_C()
1272 rtl::str::newReplaceChars(ppThis
, pStr
, rtl::str::FromTo(cOld
, cNew
));
1275 void SAL_CALL
rtl_uString_newToAsciiLowerCase(rtl_uString
** ppThis
, rtl_uString
* pStr
)
1276 SAL_THROW_EXTERN_C()
1278 rtl::str::newReplaceChars(ppThis
, pStr
, rtl::str::toAsciiLower
);
1281 void SAL_CALL
rtl_uString_newToAsciiUpperCase(rtl_uString
** ppThis
, rtl_uString
* pStr
)
1282 SAL_THROW_EXTERN_C()
1284 rtl::str::newReplaceChars(ppThis
, pStr
, rtl::str::toAsciiUpper
);
1287 void SAL_CALL
rtl_uString_newTrim(rtl_uString
** ppThis
, rtl_uString
* pStr
) SAL_THROW_EXTERN_C()
1289 rtl::str::newTrim(ppThis
, pStr
);
1292 sal_Int32 SAL_CALL
rtl_uString_getToken(rtl_uString
** ppThis
, rtl_uString
* pStr
, sal_Int32 nToken
,
1293 sal_Unicode cTok
, sal_Int32 nIndex
) SAL_THROW_EXTERN_C()
1295 return rtl::str::getToken(ppThis
, pStr
, nToken
, cTok
, nIndex
);
1298 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */