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 <rtl/character.hxx>
43 : #include <rtl/ustring.h>
44 :
45 : #include "rtl/math.h"
46 :
47 : /* ======================================================================= */
48 :
49 : /* static data to be referenced by all empty strings
50 : * the refCount is predefined to 1 and must never become 0 !
51 : */
52 : static rtl_uString const aImplEmpty_rtl_uString =
53 : {
54 : (sal_Int32) (SAL_STRING_INTERN_FLAG|SAL_STRING_STATIC_FLAG|1), /*sal_Int32 refCount; */
55 : 0, /*sal_Int32 length; */
56 : { 0 } /*sal_Unicode buffer[1];*/
57 : };
58 :
59 : /* ======================================================================= */
60 : /* These macros are for the "poor-man templates" included from
61 : * the strtmpl.cxx just below, used to share code between here and
62 : * string.cxx
63 : */
64 :
65 : #define IMPL_RTL_IS_USTRING 1
66 :
67 : #define IMPL_RTL_STRCODE sal_Unicode
68 : #define IMPL_RTL_USTRCODE( c ) (c)
69 : #define IMPL_RTL_STRNAME( n ) rtl_ustr_ ## n
70 :
71 : #define IMPL_RTL_STRINGNAME( n ) rtl_uString_ ## n
72 : #define IMPL_RTL_STRINGDATA rtl_uString
73 : #define IMPL_RTL_EMPTYSTRING aImplEmpty_rtl_uString
74 :
75 : static void internRelease (rtl_uString *pThis);
76 :
77 : #if USE_SDT_PROBES
78 : #define RTL_LOG_STRING_BITS 16
79 : #endif
80 :
81 : /* ======================================================================= */
82 :
83 : /* Include String/UString template code */
84 :
85 : #include "strtmpl.cxx"
86 :
87 : #undef IMPL_RTL_EMPTYSTRING
88 : #undef IMPL_RTL_IS_USTRING
89 : #undef IMPL_RTL_STRCODE
90 : #undef IMPL_RTL_STRINGDATA
91 : #undef IMPL_RTL_STRINGNAME
92 : #undef IMPL_RTL_STRNAME
93 : #undef IMPL_RTL_USTRCODE
94 : #undef RTL_LOG_STRING_BITS
95 :
96 4306897 : sal_Int32 rtl_ustr_indexOfAscii_WithLength(
97 : sal_Unicode const * str, sal_Int32 len,
98 : char const * subStr, sal_Int32 subLen) SAL_THROW_EXTERN_C()
99 : {
100 : assert(len >= 0);
101 : assert(subLen >= 0);
102 4306897 : if (subLen > 0 && subLen <= len) {
103 : sal_Int32 i;
104 43944056 : for (i = 0; i <= len - subLen; ++i) {
105 41217058 : if (rtl_ustr_asciil_reverseEquals_WithLength(
106 41217058 : str + i, subStr, subLen))
107 : {
108 209426 : return i;
109 : }
110 : }
111 : }
112 4097471 : return -1;
113 : }
114 :
115 3384 : sal_Int32 rtl_ustr_lastIndexOfAscii_WithLength(
116 : sal_Unicode const * str, sal_Int32 len,
117 : char const * subStr, sal_Int32 subLen) SAL_THROW_EXTERN_C()
118 : {
119 : assert(len >= 0);
120 : assert(subLen >= 0);
121 3384 : if (subLen > 0 && subLen <= len) {
122 : sal_Int32 i;
123 3779 : for (i = len - subLen; i >= 0; --i) {
124 3778 : if (rtl_ustr_asciil_reverseEquals_WithLength(
125 3778 : str + i, subStr, subLen))
126 : {
127 3382 : return i;
128 : }
129 : }
130 : }
131 2 : return -1;
132 : }
133 :
134 61 : sal_Int32 SAL_CALL rtl_ustr_valueOfFloat(sal_Unicode * pStr, float f)
135 : SAL_THROW_EXTERN_C()
136 : {
137 : assert(pStr);
138 61 : rtl_uString * pResult = NULL;
139 : sal_Int32 nLen;
140 : rtl_math_doubleToUString(
141 : &pResult, 0, 0, f, rtl_math_StringFormat_G,
142 : RTL_USTR_MAX_VALUEOFFLOAT - RTL_CONSTASCII_LENGTH("-x.E-xxx"), '.', 0,
143 61 : 0, sal_True);
144 61 : nLen = pResult->length;
145 : OSL_ASSERT(nLen < RTL_USTR_MAX_VALUEOFFLOAT);
146 61 : memcpy(pStr, pResult->buffer, (nLen + 1) * sizeof(sal_Unicode));
147 61 : rtl_uString_release(pResult);
148 61 : return nLen;
149 : }
150 :
151 101926 : sal_Int32 SAL_CALL rtl_ustr_valueOfDouble(sal_Unicode * pStr, double d)
152 : SAL_THROW_EXTERN_C()
153 : {
154 : assert(pStr);
155 101926 : rtl_uString * pResult = NULL;
156 : sal_Int32 nLen;
157 : rtl_math_doubleToUString(
158 : &pResult, 0, 0, d, rtl_math_StringFormat_G,
159 : RTL_USTR_MAX_VALUEOFDOUBLE - RTL_CONSTASCII_LENGTH("-x.E-xxx"), '.', 0,
160 101926 : 0, sal_True);
161 101926 : nLen = pResult->length;
162 : OSL_ASSERT(nLen < RTL_USTR_MAX_VALUEOFDOUBLE);
163 101926 : memcpy(pStr, pResult->buffer, (nLen + 1) * sizeof(sal_Unicode));
164 101926 : rtl_uString_release(pResult);
165 101926 : return nLen;
166 : }
167 :
168 : namespace {
169 :
170 : // Avoid -fsanitize=undefined warning e.g. "runtime error: value 1e+99 is
171 : // outside the range of representable values of type 'float'":
172 116 : float doubleToFloat(double x) {
173 : return
174 116 : x < -std::numeric_limits<float>::max()
175 2 : ? -std::numeric_limits<float>::infinity()
176 114 : : x > std::numeric_limits<float>::max()
177 : ? std::numeric_limits<float>::infinity()
178 232 : : static_cast<float>(x);
179 : }
180 :
181 : }
182 :
183 116 : float SAL_CALL rtl_ustr_toFloat(sal_Unicode const * pStr) SAL_THROW_EXTERN_C()
184 : {
185 : assert(pStr);
186 : return doubleToFloat(rtl_math_uStringToDouble(pStr,
187 116 : pStr + rtl_ustr_getLength(pStr),
188 116 : '.', 0, 0, 0));
189 : }
190 :
191 31534 : double SAL_CALL rtl_ustr_toDouble(sal_Unicode const * pStr) SAL_THROW_EXTERN_C()
192 : {
193 : assert(pStr);
194 31534 : return rtl_math_uStringToDouble(pStr, pStr + rtl_ustr_getLength(pStr), '.',
195 31534 : 0, 0, 0);
196 : }
197 :
198 : /* ======================================================================= */
199 :
200 41724 : sal_Int32 SAL_CALL rtl_ustr_ascii_compare( const sal_Unicode* pStr1,
201 : const sal_Char* pStr2 )
202 : SAL_THROW_EXTERN_C()
203 : {
204 : assert(pStr1);
205 : assert(pStr2);
206 : sal_Int32 nRet;
207 339596 : while ( ((nRet = ((sal_Int32)(*pStr1))-
208 148936 : ((sal_Int32)((unsigned char)(*pStr2)))) == 0) &&
209 : *pStr2 )
210 : {
211 : /* Check ASCII range */
212 : SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
213 : "rtl_ustr_ascii_compare - Found char > 127" );
214 107212 : pStr1++;
215 107212 : pStr2++;
216 : }
217 :
218 41724 : return nRet;
219 : }
220 :
221 : /* ----------------------------------------------------------------------- */
222 :
223 1514202229 : sal_Int32 SAL_CALL rtl_ustr_ascii_compare_WithLength( const sal_Unicode* pStr1,
224 : sal_Int32 nStr1Len,
225 : const sal_Char* pStr2 )
226 : SAL_THROW_EXTERN_C()
227 : {
228 : assert(pStr1);
229 : assert(nStr1Len >= 0);
230 : assert(pStr2);
231 1514202229 : sal_Int32 nRet = 0;
232 9284219563 : while( ((nRet = (nStr1Len ? (sal_Int32)(*pStr1) : 0)-
233 2407568694 : ((sal_Int32)((unsigned char)(*pStr2)))) == 0) &&
234 6255814709 : nStr1Len && *pStr2 )
235 : {
236 : /* Check ASCII range */
237 : SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
238 : "rtl_ustr_ascii_compare_WithLength - Found char > 127" );
239 2370806438 : pStr1++;
240 2370806438 : pStr2++;
241 2370806438 : nStr1Len--;
242 : }
243 :
244 1514202229 : return nRet;
245 : }
246 :
247 : /* ----------------------------------------------------------------------- */
248 :
249 147952605 : sal_Int32 SAL_CALL rtl_ustr_ascii_shortenedCompare_WithLength( const sal_Unicode* pStr1,
250 : sal_Int32 nStr1Len,
251 : const sal_Char* pStr2,
252 : sal_Int32 nShortenedLength )
253 : SAL_THROW_EXTERN_C()
254 : {
255 : assert(nStr1Len >= 0);
256 : assert(nShortenedLength >= 0);
257 147952605 : const sal_Unicode* pStr1End = pStr1 + nStr1Len;
258 : sal_Int32 nRet;
259 312034757 : while ( (nShortenedLength > 0) &&
260 161857091 : (pStr1 < pStr1End) && *pStr2 )
261 : {
262 : /* Check ASCII range */
263 : SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
264 : "rtl_ustr_ascii_shortenedCompare_WithLength - Found char > 127" );
265 :
266 161857091 : nRet = ((sal_Int32)*pStr1)-
267 161857091 : ((sal_Int32)(unsigned char)*pStr2);
268 161857091 : if ( nRet != 0 )
269 145727544 : return nRet;
270 :
271 16129547 : nShortenedLength--;
272 16129547 : pStr1++;
273 16129547 : pStr2++;
274 : }
275 :
276 2225061 : if ( nShortenedLength <= 0 )
277 2208838 : return 0;
278 :
279 16223 : if ( *pStr2 )
280 : {
281 : OSL_ENSURE( pStr1 == pStr1End, "pStr1 == pStr1End failed" );
282 : // first is a substring of the second string => less (negative value)
283 16223 : nRet = -1;
284 : }
285 : else
286 : {
287 : // greater or equal
288 0 : nRet = pStr1End - pStr1;
289 : }
290 :
291 16223 : return nRet;
292 : }
293 :
294 : /* ----------------------------------------------------------------------- */
295 :
296 7628 : sal_Int32 SAL_CALL rtl_ustr_asciil_reverseCompare_WithLength( const sal_Unicode* pStr1,
297 : sal_Int32 nStr1Len,
298 : const sal_Char* pStr2,
299 : sal_Int32 nStr2Len )
300 : SAL_THROW_EXTERN_C()
301 : {
302 : assert(nStr1Len >= 0 && nStr2Len >= 0);
303 7628 : const sal_Unicode* pStr1Run = pStr1+nStr1Len;
304 7628 : const sal_Char* pStr2Run = pStr2+nStr2Len;
305 : sal_Int32 nRet;
306 17918 : while ( (pStr1 < pStr1Run) && (pStr2 < pStr2Run) )
307 : {
308 : /* Check ASCII range */
309 : SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
310 : "rtl_ustr_asciil_reverseCompare_WithLength - Found char > 127" );
311 10187 : pStr1Run--;
312 10187 : pStr2Run--;
313 10187 : nRet = ((sal_Int32)*pStr1Run)-((sal_Int32)*pStr2Run);
314 10187 : if ( nRet )
315 7525 : return nRet;
316 : }
317 :
318 103 : return nStr1Len - nStr2Len;
319 : }
320 :
321 : /* ----------------------------------------------------------------------- */
322 :
323 747792761 : sal_Bool SAL_CALL rtl_ustr_asciil_reverseEquals_WithLength( const sal_Unicode* pStr1,
324 : const sal_Char* pStr2,
325 : sal_Int32 nStrLen )
326 : SAL_THROW_EXTERN_C()
327 : {
328 : assert(nStrLen >= 0);
329 747792761 : const sal_Unicode* pStr1Run = pStr1+nStrLen;
330 747792761 : const sal_Char* pStr2Run = pStr2+nStrLen;
331 6415420040 : while ( pStr1 < pStr1Run )
332 : {
333 : /* Check ASCII range */
334 : SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
335 : "rtl_ustr_asciil_reverseEquals_WithLength - Found char > 127" );
336 5379838081 : pStr1Run--;
337 5379838081 : pStr2Run--;
338 5379838081 : if( *pStr1Run != (sal_Unicode)*pStr2Run )
339 460003563 : return sal_False;
340 : }
341 :
342 287789198 : return sal_True;
343 : }
344 :
345 : /* ----------------------------------------------------------------------- */
346 :
347 0 : sal_Int32 SAL_CALL rtl_ustr_ascii_compareIgnoreAsciiCase( const sal_Unicode* pStr1,
348 : const sal_Char* pStr2 )
349 : SAL_THROW_EXTERN_C()
350 : {
351 : assert(pStr1);
352 : assert(pStr2);
353 : sal_Int32 nRet;
354 : sal_Int32 c1;
355 : sal_Int32 c2;
356 0 : do
357 : {
358 : /* Check ASCII range */
359 : SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
360 : "rtl_ustr_ascii_compareIgnoreAsciiCase - Found char > 127" );
361 : /* If character between 'A' and 'Z', than convert it to lowercase */
362 0 : c1 = (sal_Int32)*pStr1;
363 0 : c2 = (sal_Int32)((unsigned char)*pStr2);
364 0 : if ( (c1 >= 65) && (c1 <= 90) )
365 0 : c1 += 32;
366 0 : if ( (c2 >= 65) && (c2 <= 90) )
367 0 : c2 += 32;
368 0 : nRet = c1-c2;
369 0 : if ( nRet != 0 )
370 0 : return nRet;
371 :
372 0 : pStr1++;
373 0 : pStr2++;
374 : }
375 : while ( c2 );
376 :
377 0 : return 0;
378 : }
379 :
380 : /* ----------------------------------------------------------------------- */
381 :
382 570833634 : sal_Int32 SAL_CALL rtl_ustr_ascii_compareIgnoreAsciiCase_WithLength( const sal_Unicode* pStr1,
383 : sal_Int32 nStr1Len,
384 : const sal_Char* pStr2 )
385 : SAL_THROW_EXTERN_C()
386 : {
387 : assert(nStr1Len >= 0);
388 : assert(pStr2);
389 : sal_Int32 nRet;
390 : sal_Int32 c1;
391 : sal_Int32 c2;
392 259199641 : do
393 : {
394 : /* Check ASCII range */
395 : SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
396 : "rtl_ustr_ascii_compareIgnoreAsciiCase_WithLength - Found char > 127" );
397 570833634 : if ( !nStr1Len )
398 28063427 : return *pStr2 == '\0' ? 0 : -1;
399 :
400 : /* If character between 'A' and 'Z', than convert it to lowercase */
401 542770207 : c1 = (sal_Int32)*pStr1;
402 542770207 : c2 = (sal_Int32)((unsigned char)*pStr2);
403 542770207 : if ( (c1 >= 65) && (c1 <= 90) )
404 287782164 : c1 += 32;
405 542770207 : if ( (c2 >= 65) && (c2 <= 90) )
406 284750716 : c2 += 32;
407 542770207 : nRet = c1-c2;
408 542770207 : if ( nRet != 0 )
409 283570566 : return nRet;
410 :
411 259199641 : pStr1++;
412 259199641 : pStr2++;
413 259199641 : nStr1Len--;
414 : }
415 : while( c2 );
416 :
417 0 : return 0;
418 : }
419 :
420 478077 : sal_Int32 rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
421 : sal_Unicode const * first, sal_Int32 firstLen,
422 : char const * second, sal_Int32 secondLen) SAL_THROW_EXTERN_C()
423 : {
424 : assert(firstLen >= 0 && secondLen >= 0);
425 : sal_Int32 i;
426 478077 : sal_Int32 len = firstLen < secondLen ? firstLen : secondLen;
427 1107031 : for (i = 0; i < len; ++i) {
428 : /* Check ASCII range */
429 : SAL_WARN_IF( ((unsigned char)*second) > 127, "rtl.string",
430 : "rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths - Found char > 127" );
431 1040380 : sal_Int32 c1 = *first++;
432 1040380 : sal_Int32 c2 = (unsigned char) *second++;
433 : sal_Int32 d;
434 1040380 : if (c1 >= 65 && c1 <= 90) {
435 116985 : c1 += 32;
436 : }
437 1040380 : if (c2 >= 65 && c2 <= 90) {
438 98301 : c2 += 32;
439 : }
440 1040380 : d = c1 - c2;
441 1040380 : if (d != 0) {
442 411426 : return d;
443 : }
444 : }
445 66651 : return firstLen - secondLen;
446 : }
447 :
448 : /* ----------------------------------------------------------------------- */
449 :
450 4097596 : sal_Int32 SAL_CALL rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( const sal_Unicode* pStr1,
451 : sal_Int32 nStr1Len,
452 : const sal_Char* pStr2,
453 : sal_Int32 nShortenedLength )
454 : SAL_THROW_EXTERN_C()
455 : {
456 : assert(nStr1Len >= 0);
457 : assert(nShortenedLength >= 0);
458 4097596 : const sal_Unicode* pStr1End = pStr1 + nStr1Len;
459 : sal_Int32 nRet;
460 : sal_Int32 c1;
461 : sal_Int32 c2;
462 10139322 : while ( (nShortenedLength > 0) &&
463 5832790 : (pStr1 < pStr1End) && *pStr2 )
464 : {
465 : /* Check ASCII range */
466 : SAL_WARN_IF( ((unsigned char)*pStr2) > 127, "rtl.string",
467 : "rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength - Found char > 127" );
468 :
469 : /* If character between 'A' and 'Z', than convert it to lowercase */
470 5832790 : c1 = (sal_Int32)*pStr1;
471 5832790 : c2 = (sal_Int32)((unsigned char)*pStr2);
472 5832790 : if ( (c1 >= 65) && (c1 <= 90) )
473 311834 : c1 += 32;
474 5832790 : if ( (c2 >= 65) && (c2 <= 90) )
475 311827 : c2 += 32;
476 5832790 : nRet = c1-c2;
477 5832790 : if ( nRet != 0 )
478 3888660 : return nRet;
479 :
480 1944130 : nShortenedLength--;
481 1944130 : pStr1++;
482 1944130 : pStr2++;
483 : }
484 :
485 208936 : if ( nShortenedLength <= 0 )
486 208869 : return 0;
487 :
488 67 : if ( *pStr2 )
489 : {
490 : OSL_ENSURE( pStr1 == pStr1End, "pStr1 == pStr1End failed" );
491 : // first is a substring of the second string => less (negative value)
492 67 : nRet = -1;
493 : }
494 : else
495 : {
496 : // greater or equal
497 0 : nRet = pStr1End - pStr1;
498 : }
499 :
500 67 : return nRet;
501 : }
502 :
503 : /* ----------------------------------------------------------------------- */
504 :
505 14511431 : void SAL_CALL rtl_uString_newFromAscii( rtl_uString** ppThis,
506 : const sal_Char* pCharStr )
507 : SAL_THROW_EXTERN_C()
508 : {
509 : assert(ppThis);
510 : sal_Int32 nLen;
511 :
512 14511431 : if ( pCharStr )
513 : {
514 14511263 : const sal_Char* pTempStr = pCharStr;
515 174852654 : while( *pTempStr )
516 145830128 : pTempStr++;
517 14511263 : nLen = pTempStr-pCharStr;
518 : }
519 : else
520 168 : nLen = 0;
521 :
522 14511431 : if ( !nLen )
523 : {
524 148799 : rtl_uString_new( ppThis );
525 14660230 : return;
526 : }
527 :
528 14362632 : if ( *ppThis )
529 7438 : rtl_uString_release( *ppThis );
530 :
531 14362632 : *ppThis = rtl_uString_ImplAlloc( nLen );
532 : OSL_ASSERT(*ppThis != NULL);
533 14362632 : if ( (*ppThis) )
534 : {
535 14362632 : sal_Unicode* pBuffer = (*ppThis)->buffer;
536 145830164 : do
537 : {
538 : assert(static_cast<unsigned char>(*pCharStr) < 0x80); // ASCII range
539 145830164 : *pBuffer = *pCharStr;
540 145830164 : pBuffer++;
541 145830164 : pCharStr++;
542 : }
543 : while ( *pCharStr );
544 :
545 : RTL_LOG_STRING_NEW( *ppThis );
546 : }
547 : }
548 :
549 18310 : void SAL_CALL rtl_uString_newFromCodePoints(
550 : rtl_uString ** newString, sal_uInt32 const * codePoints,
551 : sal_Int32 codePointCount) SAL_THROW_EXTERN_C()
552 : {
553 : sal_Int32 n;
554 : sal_Int32 i;
555 : sal_Unicode * p;
556 : assert(newString != nullptr);
557 : assert((codePoints != nullptr || codePointCount == 0) && codePointCount >= 0);
558 18310 : if (codePointCount == 0) {
559 4036 : rtl_uString_new(newString);
560 4036 : return;
561 : }
562 14274 : if (*newString != NULL) {
563 0 : rtl_uString_release(*newString);
564 : }
565 14274 : n = codePointCount;
566 28784 : for (i = 0; i < codePointCount; ++i) {
567 : OSL_ASSERT(codePoints[i] <= 0x10FFFF);
568 14510 : if (codePoints[i] >= 0x10000) {
569 4 : ++n;
570 : }
571 : }
572 : /* Builds on the assumption that sal_Int32 uses 32 bit two's complement
573 : representation with wrap around (the necessary number of UTF-16 code
574 : units will be no larger than 2 * SAL_MAX_INT32, represented as
575 : sal_Int32 -2): */
576 14274 : if (n < 0) {
577 : // coverity[dead_error_begin] - assumes wrap around
578 0 : *newString = NULL;
579 0 : return;
580 : }
581 14274 : *newString = rtl_uString_ImplAlloc(n);
582 14274 : if (*newString == NULL) {
583 0 : return;
584 : }
585 14274 : p = (*newString)->buffer;
586 28784 : for (i = 0; i < codePointCount; ++i) {
587 14510 : sal_uInt32 c = codePoints[i];
588 14510 : if (c < 0x10000) {
589 14506 : *p++ = (sal_Unicode) c;
590 : } else {
591 4 : *p++ = rtl::getHighSurrogate(c);
592 4 : *p++ = rtl::getLowSurrogate(c);
593 : }
594 : }
595 : RTL_LOG_STRING_NEW( *newString );
596 : }
597 :
598 : /* ======================================================================= */
599 :
600 27415622 : static int rtl_ImplGetFastUTF8UnicodeLen( const sal_Char* pStr, sal_Int32 nLen, bool * ascii )
601 : {
602 : int n;
603 : const sal_Char* pEndStr;
604 :
605 27415622 : *ascii = true;
606 27415622 : n = 0;
607 27415622 : pEndStr = pStr+nLen;
608 462839311 : while ( pStr < pEndStr )
609 : {
610 408008067 : unsigned char c = (unsigned char)*pStr;
611 :
612 408008067 : if ( !(c & 0x80) )
613 405381272 : pStr++;
614 : else
615 : {
616 2626795 : if ( (c & 0xE0) == 0xC0 )
617 38119 : pStr += 2;
618 2588676 : else if ( (c & 0xF0) == 0xE0 )
619 2588669 : pStr += 3;
620 7 : else if ( (c & 0xF8) == 0xF0 )
621 5 : pStr += 4;
622 2 : else if ( (c & 0xFC) == 0xF8 )
623 0 : pStr += 5;
624 2 : else if ( (c & 0xFE) == 0xFC )
625 0 : pStr += 6;
626 : else
627 2 : pStr++;
628 2626795 : *ascii = false;
629 : }
630 :
631 408008067 : n++;
632 : }
633 :
634 27415622 : return n;
635 : }
636 :
637 : /* ----------------------------------------------------------------------- */
638 :
639 42061305 : static void rtl_string2UString_status( rtl_uString** ppThis,
640 : const sal_Char* pStr,
641 : sal_Int32 nLen,
642 : rtl_TextEncoding eTextEncoding,
643 : sal_uInt32 nCvtFlags,
644 : sal_uInt32 *pInfo )
645 : {
646 : OSL_ENSURE(nLen == 0 || rtl_isOctetTextEncoding(eTextEncoding),
647 : "rtl_string2UString_status() - Wrong TextEncoding" );
648 :
649 42061305 : if ( !nLen )
650 : {
651 730783 : rtl_uString_new( ppThis );
652 730783 : if (pInfo != NULL) {
653 558442 : *pInfo = 0;
654 : }
655 : }
656 : else
657 : {
658 41330522 : if ( *ppThis )
659 10613078 : rtl_uString_release( *ppThis );
660 :
661 : /* Optimization for US-ASCII */
662 41330522 : if ( eTextEncoding == RTL_TEXTENCODING_ASCII_US )
663 : {
664 : sal_Unicode* pBuffer;
665 13745136 : *ppThis = rtl_uString_ImplAlloc( nLen );
666 13745136 : if (*ppThis == NULL) {
667 0 : if (pInfo != NULL) {
668 : *pInfo = RTL_TEXTTOUNICODE_INFO_ERROR |
669 0 : RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
670 : }
671 0 : return;
672 : }
673 13745136 : pBuffer = (*ppThis)->buffer;
674 13745136 : sal_Int32 nLenCopy(nLen);
675 13745136 : const sal_Char *pStrCopy(pStr);
676 197709810 : do
677 : {
678 : /* Check ASCII range */
679 197709824 : if (static_cast<unsigned char>(*pStrCopy) > 127)
680 : {
681 14 : rtl_uString_release(*ppThis);
682 14 : goto retry; // cancel loop - try again with the converter
683 : }
684 :
685 197709810 : *pBuffer = *pStrCopy;
686 197709810 : pBuffer++;
687 197709810 : pStrCopy++;
688 197709810 : nLenCopy--;
689 : }
690 : while (nLenCopy);
691 13745122 : if (pInfo != NULL) {
692 10149783 : *pInfo = 0;
693 : }
694 : RTL_LOG_STRING_NEW( *ppThis );
695 13745122 : return;
696 : }
697 : retry:
698 : {
699 : rtl_uString* pTemp;
700 27585400 : rtl_uString* pTemp2 = NULL;
701 : rtl_TextToUnicodeConverter hConverter;
702 : sal_uInt32 nInfo;
703 : sal_Size nSrcBytes;
704 : sal_Size nDestChars;
705 : sal_Size nNewLen;
706 :
707 : /* Optimization for UTF-8 - we try to calculate the exact length */
708 : /* For all other encoding we try the maximum - and reallocate
709 : the buffer if needed */
710 27585400 : if ( eTextEncoding == RTL_TEXTENCODING_UTF8 )
711 : {
712 : bool ascii;
713 27415623 : nNewLen = rtl_ImplGetFastUTF8UnicodeLen( pStr, nLen, &ascii );
714 : /* Includes the string only ASCII, then we could copy
715 : the buffer faster */
716 27415623 : if ( ascii )
717 : {
718 : sal_Unicode* pBuffer;
719 26703163 : *ppThis = rtl_uString_ImplAlloc( nLen );
720 26703161 : if (*ppThis == NULL)
721 : {
722 0 : if (pInfo != NULL) {
723 : *pInfo = RTL_TEXTTOUNICODE_INFO_ERROR |
724 0 : RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
725 : }
726 26703160 : return;
727 : }
728 26703162 : pBuffer = (*ppThis)->buffer;
729 399148691 : do
730 : {
731 : assert(((unsigned char)*pStr) <= 127);
732 399148691 : *pBuffer = *pStr;
733 399148691 : pBuffer++;
734 399148691 : pStr++;
735 399148691 : nLen--;
736 : }
737 : while ( nLen );
738 26703162 : if (pInfo != NULL) {
739 13691281 : *pInfo = 0;
740 : }
741 : RTL_LOG_STRING_NEW( *ppThis );
742 26703162 : return;
743 : }
744 : }
745 : else
746 169777 : nNewLen = nLen;
747 :
748 882237 : nCvtFlags |= RTL_TEXTTOUNICODE_FLAGS_FLUSH;
749 882237 : hConverter = rtl_createTextToUnicodeConverter( eTextEncoding );
750 :
751 882237 : pTemp = rtl_uString_ImplAlloc( nNewLen );
752 882237 : if (pTemp == NULL) {
753 0 : if (pInfo != NULL) {
754 : *pInfo = RTL_TEXTTOUNICODE_INFO_ERROR |
755 0 : RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
756 : }
757 0 : return;
758 : }
759 : nDestChars = rtl_convertTextToUnicode( hConverter, 0,
760 : pStr, nLen,
761 : pTemp->buffer, nNewLen,
762 : nCvtFlags,
763 882237 : &nInfo, &nSrcBytes );
764 :
765 : /* Buffer not big enough, try again with enough space */
766 : /* Shouldn't be the case, but if we get textencoding which
767 : could results in more unicode characters we have this
768 : code here. Could be the case for apple encodings */
769 1764531 : while ( nInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL )
770 : {
771 57 : rtl_freeMemory( pTemp );
772 57 : nNewLen += 8;
773 57 : pTemp = rtl_uString_ImplAlloc( nNewLen );
774 57 : if (pTemp == NULL) {
775 0 : if (pInfo != NULL) {
776 : *pInfo = RTL_TEXTTOUNICODE_INFO_ERROR |
777 0 : RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
778 : }
779 0 : return;
780 : }
781 : nDestChars = rtl_convertTextToUnicode( hConverter, 0,
782 : pStr, nLen,
783 : pTemp->buffer, nNewLen,
784 : nCvtFlags,
785 57 : &nInfo, &nSrcBytes );
786 : }
787 :
788 882237 : if (pInfo)
789 36510 : *pInfo = nInfo;
790 :
791 : /* Set the buffer to the correct size or if there is too
792 : much overhead, reallocate to the correct size */
793 882237 : if ( nNewLen > nDestChars+8 )
794 : {
795 4 : pTemp2 = rtl_uString_ImplAlloc( nDestChars );
796 : }
797 882237 : if (pTemp2 != NULL)
798 : {
799 4 : rtl_str_ImplCopy(pTemp2->buffer, pTemp->buffer, nDestChars);
800 4 : rtl_freeMemory(pTemp);
801 4 : pTemp = pTemp2;
802 : }
803 : else
804 : {
805 882233 : pTemp->length = nDestChars;
806 882233 : pTemp->buffer[nDestChars] = 0;
807 : }
808 :
809 882237 : rtl_destroyTextToUnicodeConverter( hConverter );
810 882237 : *ppThis = pTemp;
811 :
812 : /* Results the conversion in an empty buffer -
813 : create an empty string */
814 882237 : if ( pTemp && !nDestChars )
815 3 : rtl_uString_new( ppThis );
816 : }
817 : }
818 : RTL_LOG_STRING_NEW( *ppThis );
819 : }
820 :
821 16659250 : void SAL_CALL rtl_string2UString( rtl_uString** ppThis,
822 : const sal_Char* pStr,
823 : sal_Int32 nLen,
824 : rtl_TextEncoding eTextEncoding,
825 : sal_uInt32 nCvtFlags ) SAL_THROW_EXTERN_C()
826 : {
827 : assert(ppThis);
828 : assert(nLen >= 0);
829 : rtl_string2UString_status( ppThis, pStr, nLen, eTextEncoding,
830 16659250 : nCvtFlags, NULL );
831 16659248 : }
832 :
833 : /* ----------------------------------------------------------------------- */
834 :
835 : enum StrLifecycle {
836 : CANNOT_RETURN,
837 : CAN_RETURN = 1
838 : };
839 :
840 : static oslMutex
841 1632799 : getInternMutex()
842 : {
843 : static oslMutex pPoolGuard = NULL;
844 1632799 : if( !pPoolGuard )
845 : {
846 : oslMutex pGlobalGuard;
847 152 : pGlobalGuard = *osl_getGlobalMutex();
848 152 : osl_acquireMutex( pGlobalGuard );
849 152 : if( !pPoolGuard )
850 : {
851 152 : oslMutex p = osl_createMutex();
852 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
853 152 : pPoolGuard = p;
854 : }
855 152 : osl_releaseMutex( pGlobalGuard );
856 : }
857 : else
858 : {
859 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
860 : }
861 :
862 1632799 : return pPoolGuard;
863 : }
864 :
865 : /* returns true if we found a dup in the pool */
866 1017345 : static void rtl_ustring_intern_internal( rtl_uString ** newStr,
867 : rtl_uString * str,
868 : StrLifecycle can_return )
869 : {
870 : oslMutex pPoolMutex;
871 :
872 1017345 : pPoolMutex = getInternMutex();
873 :
874 1017345 : osl_acquireMutex( pPoolMutex );
875 :
876 1017345 : *newStr = rtl_str_hash_intern (str, can_return);
877 :
878 1017345 : osl_releaseMutex( pPoolMutex );
879 :
880 : RTL_LOG_STRING_INTERN_NEW(*newStr, str);
881 :
882 1017345 : if( can_return && *newStr != str )
883 : { /* we dupped, then found a match */
884 389952 : rtl_freeMemory( str );
885 : }
886 1017345 : }
887 :
888 38965 : void SAL_CALL rtl_uString_intern( rtl_uString ** newStr,
889 : rtl_uString * str) SAL_THROW_EXTERN_C()
890 : {
891 : assert(newStr);
892 : assert(str);
893 38965 : if (SAL_STRING_IS_INTERN(str))
894 : {
895 1 : IMPL_RTL_ACQUIRE( str );
896 1 : *newStr = str;
897 : }
898 : else
899 : {
900 38964 : rtl_uString *pOrg = *newStr;
901 38964 : *newStr = NULL;
902 38964 : rtl_ustring_intern_internal( newStr, str, CANNOT_RETURN );
903 38964 : if (pOrg)
904 0 : rtl_uString_release (pOrg);
905 : }
906 38965 : }
907 :
908 966039 : static int rtl_canGuessUOutputLength( int len, rtl_TextEncoding eTextEncoding )
909 : {
910 : // FIXME: Maybe we should use a bit flag in the higher bits of the
911 : // eTextEncoding value itself to determine the encoding type. But if we
912 : // do, be sure to mask the value in certain places that expect the values
913 : // to be numbered serially from 0 and up. One such place is
914 : // Impl_getTextEncodingData().
915 :
916 966039 : switch ( eTextEncoding )
917 : {
918 : // 1 to 1 (with no zero elements)
919 : case RTL_TEXTENCODING_IBM_437:
920 : case RTL_TEXTENCODING_IBM_850:
921 : case RTL_TEXTENCODING_IBM_860:
922 : case RTL_TEXTENCODING_IBM_861:
923 : case RTL_TEXTENCODING_IBM_863:
924 : case RTL_TEXTENCODING_IBM_865:
925 0 : return len;
926 : break;
927 : }
928 966039 : return 0;
929 : }
930 :
931 978381 : void SAL_CALL rtl_uString_internConvert( rtl_uString ** newStr,
932 : const sal_Char * str,
933 : sal_Int32 len,
934 : rtl_TextEncoding eTextEncoding,
935 : sal_uInt32 convertFlags,
936 : sal_uInt32 * pInfo )
937 : SAL_THROW_EXTERN_C()
938 : {
939 : assert(newStr);
940 : assert(len >= 0);
941 : rtl_uString *scratch;
942 :
943 978381 : if (*newStr)
944 : {
945 0 : rtl_uString_release (*newStr);
946 0 : *newStr = NULL;
947 : }
948 :
949 978381 : if ( len < 256 )
950 : { // try various optimisations
951 : sal_Int32 ulen;
952 978381 : if ( eTextEncoding == RTL_TEXTENCODING_ASCII_US )
953 : {
954 : int i;
955 : rtl_uString *pScratch;
956 : pScratch = static_cast< rtl_uString * >(
957 12342 : alloca(sizeof (rtl_uString) + len * sizeof (sal_Unicode)));
958 86416 : for (i = 0; i < len; i++)
959 : {
960 : /* Check ASCII range */
961 : SAL_WARN_IF( ((unsigned char)str[i]) > 127, "rtl.string",
962 : "rtl_ustring_internConvert() - Found char > 127 and RTL_TEXTENCODING_ASCII_US is specified" );
963 74074 : pScratch->buffer[i] = str[i];
964 : }
965 12342 : pScratch->length = len;
966 12342 : rtl_ustring_intern_internal( newStr, pScratch, CANNOT_RETURN );
967 24684 : return;
968 : }
969 966039 : else if ( (ulen = rtl_canGuessUOutputLength(len, eTextEncoding)) != 0 )
970 : {
971 : rtl_uString *pScratch;
972 : rtl_TextToUnicodeConverter hConverter;
973 : sal_Size nSrcBytes;
974 : sal_uInt32 nInfo;
975 :
976 : pScratch = static_cast< rtl_uString * >(
977 0 : alloca(
978 0 : sizeof (rtl_uString) + ulen * sizeof (sal_Unicode)));
979 :
980 0 : hConverter = rtl_createTextToUnicodeConverter( eTextEncoding );
981 : rtl_convertTextToUnicode(
982 0 : hConverter, 0, str, len, pScratch->buffer, ulen, convertFlags, &nInfo, &nSrcBytes );
983 0 : rtl_destroyTextToUnicodeConverter( hConverter );
984 :
985 0 : if (pInfo)
986 0 : *pInfo = nInfo;
987 :
988 0 : pScratch->length = ulen;
989 0 : rtl_ustring_intern_internal( newStr, pScratch, CANNOT_RETURN );
990 0 : return;
991 : }
992 :
993 : /* FIXME: we want a nice UTF-8 / alloca shortcut here */
994 : }
995 :
996 966039 : scratch = NULL;
997 : rtl_string2UString_status( &scratch, str, len, eTextEncoding, convertFlags,
998 966039 : pInfo );
999 966039 : if (!scratch) {
1000 0 : return;
1001 : }
1002 966039 : rtl_ustring_intern_internal( newStr, scratch, CAN_RETURN );
1003 : }
1004 :
1005 : static void
1006 7183761 : internRelease (rtl_uString *pThis)
1007 : {
1008 : oslMutex pPoolMutex;
1009 :
1010 7183761 : rtl_uString *pFree = NULL;
1011 7183761 : if ( SAL_STRING_REFCOUNT(
1012 : osl_atomic_decrement( &(pThis->refCount) ) ) == 0)
1013 : {
1014 : RTL_LOG_STRING_INTERN_DELETE(pThis);
1015 615454 : pPoolMutex = getInternMutex();
1016 615454 : osl_acquireMutex( pPoolMutex );
1017 :
1018 615454 : rtl_str_hash_remove (pThis);
1019 :
1020 : /* May have been separately acquired */
1021 615454 : if ( SAL_STRING_REFCOUNT(
1022 : osl_atomic_increment( &(pThis->refCount) ) ) == 1 )
1023 : {
1024 : /* we got the last ref */
1025 615454 : pFree = pThis;
1026 : }
1027 : else /* very unusual */
1028 : {
1029 0 : internRelease (pThis);
1030 : }
1031 :
1032 615454 : osl_releaseMutex( pPoolMutex );
1033 : }
1034 7183761 : if (pFree)
1035 615454 : rtl_freeMemory (pFree);
1036 7183761 : }
1037 :
1038 3724359508 : sal_uInt32 SAL_CALL rtl_uString_iterateCodePoints(
1039 : rtl_uString const * string, sal_Int32 * indexUtf16,
1040 : sal_Int32 incrementCodePoints)
1041 : {
1042 : sal_Int32 n;
1043 : sal_Unicode cu;
1044 : sal_uInt32 cp;
1045 : assert(string != NULL && indexUtf16 != NULL);
1046 3724359508 : n = *indexUtf16;
1047 : assert(n >= 0 && n <= string->length);
1048 7636056945 : while (incrementCodePoints < 0) {
1049 : assert(n > 0);
1050 187337929 : cu = string->buffer[--n];
1051 187337933 : if (rtl::isLowSurrogate(cu) && n != 0 &&
1052 4 : rtl::isHighSurrogate(string->buffer[n - 1]))
1053 : {
1054 3 : --n;
1055 : }
1056 187337929 : ++incrementCodePoints;
1057 : }
1058 : assert(n >= 0 && n < string->length);
1059 3724359508 : cu = string->buffer[n];
1060 3724359519 : if (rtl::isHighSurrogate(cu) && string->length - n >= 2 &&
1061 11 : rtl::isLowSurrogate(string->buffer[n + 1]))
1062 : {
1063 11 : cp = rtl::combineSurrogates(cu, string->buffer[n + 1]);
1064 : } else {
1065 3724359497 : cp = cu;
1066 : }
1067 9103500791 : while (incrementCodePoints > 0) {
1068 : assert(n < string->length);
1069 1654781775 : cu = string->buffer[n++];
1070 1654781783 : if (rtl::isHighSurrogate(cu) && n != string->length &&
1071 8 : rtl::isLowSurrogate(string->buffer[n]))
1072 : {
1073 8 : ++n;
1074 : }
1075 1654781775 : --incrementCodePoints;
1076 : }
1077 : assert(n >= 0 && n <= string->length);
1078 3724359508 : *indexUtf16 = n;
1079 3724359508 : return cp;
1080 : }
1081 :
1082 24436015 : sal_Bool rtl_convertStringToUString(
1083 : rtl_uString ** target, char const * source, sal_Int32 length,
1084 : rtl_TextEncoding encoding, sal_uInt32 flags) SAL_THROW_EXTERN_C()
1085 : {
1086 : assert(target);
1087 : assert(length >= 0);
1088 : sal_uInt32 info;
1089 24436015 : rtl_string2UString_status(target, source, length, encoding, flags, &info);
1090 24436016 : return (info & RTL_TEXTTOUNICODE_INFO_ERROR) == 0;
1091 : }
1092 :
1093 171134369 : void rtl_uString_newReplaceFirst(
1094 : rtl_uString ** newStr, rtl_uString * str, rtl_uString const * from,
1095 : rtl_uString const * to, sal_Int32 * index) SAL_THROW_EXTERN_C()
1096 : {
1097 : assert(str != 0);
1098 : assert(index != 0);
1099 : assert(*index >= 0 && *index <= str->length);
1100 : assert(from != 0);
1101 : assert(to != 0);
1102 : sal_Int32 i = rtl_ustr_indexOfStr_WithLength(
1103 171134369 : str->buffer + *index, str->length - *index, from->buffer, from->length);
1104 171134369 : if (i == -1) {
1105 171110757 : rtl_uString_assign(newStr, str);
1106 : } else {
1107 : assert(i <= str->length - *index);
1108 23612 : i += *index;
1109 : assert(from->length <= str->length);
1110 23612 : if (str->length - from->length > SAL_MAX_INT32 - to->length) {
1111 0 : std::abort();
1112 : }
1113 23612 : sal_Int32 n = str->length - from->length + to->length;
1114 23612 : rtl_uString_acquire(str); // in case *newStr == str
1115 23612 : rtl_uString_new_WithLength(newStr, n);
1116 23612 : if (n != 0) {
1117 23611 : (*newStr)->length = n;
1118 : assert(i >= 0 && i < str->length);
1119 : memcpy(
1120 23611 : (*newStr)->buffer, str->buffer, i * sizeof (sal_Unicode));
1121 : memcpy(
1122 23611 : (*newStr)->buffer + i, to->buffer,
1123 47222 : to->length * sizeof (sal_Unicode));
1124 : memcpy(
1125 23611 : (*newStr)->buffer + i + to->length,
1126 23611 : str->buffer + i + from->length,
1127 47222 : (str->length - i - from->length) * sizeof (sal_Unicode));
1128 : }
1129 23612 : rtl_uString_release(str);
1130 : }
1131 171134369 : *index = i;
1132 171134369 : }
1133 :
1134 35928 : void rtl_uString_newReplaceFirstAsciiL(
1135 : rtl_uString ** newStr, rtl_uString * str, char const * from,
1136 : sal_Int32 fromLength, rtl_uString const * to, sal_Int32 * index)
1137 : SAL_THROW_EXTERN_C()
1138 : {
1139 : assert(str != 0);
1140 : assert(index != 0);
1141 : assert(*index >= 0 && *index <= str->length);
1142 : assert(fromLength >= 0);
1143 : assert(to != 0);
1144 : sal_Int32 i = rtl_ustr_indexOfAscii_WithLength(
1145 35928 : str->buffer + *index, str->length - *index, from, fromLength);
1146 35928 : if (i == -1) {
1147 17740 : rtl_uString_assign(newStr, str);
1148 : } else {
1149 : assert(i <= str->length - *index);
1150 18188 : i += *index;
1151 : assert(fromLength <= str->length);
1152 18188 : if (str->length - fromLength > SAL_MAX_INT32 - to->length) {
1153 0 : std::abort();
1154 : }
1155 18188 : sal_Int32 n = str->length - fromLength + to->length;
1156 18188 : rtl_uString_acquire(str); // in case *newStr == str
1157 18188 : if (n != 0) {
1158 18188 : rtl_uString_new_WithLength(newStr, n);
1159 18188 : (*newStr)->length = n;
1160 : assert(i >= 0 && i < str->length);
1161 : memcpy(
1162 18188 : (*newStr)->buffer, str->buffer, i * sizeof (sal_Unicode));
1163 : memcpy(
1164 18188 : (*newStr)->buffer + i, to->buffer,
1165 36376 : to->length * sizeof (sal_Unicode));
1166 : memcpy(
1167 18188 : (*newStr)->buffer + i + to->length,
1168 18188 : str->buffer + i + fromLength,
1169 36376 : (str->length - i - fromLength) * sizeof (sal_Unicode));
1170 : }
1171 18188 : rtl_uString_release(str);
1172 : }
1173 35928 : *index = i;
1174 35928 : }
1175 :
1176 51001 : void rtl_uString_newReplaceFirstAsciiLAsciiL(
1177 : rtl_uString ** newStr, rtl_uString * str, char const * from,
1178 : sal_Int32 fromLength, char const * to, sal_Int32 toLength,
1179 : sal_Int32 * index) SAL_THROW_EXTERN_C()
1180 : {
1181 : assert(str != 0);
1182 : assert(index != 0);
1183 : assert(*index >= 0 && *index <= str->length);
1184 : assert(fromLength >= 0);
1185 : assert(to != 0);
1186 : assert(toLength >= 0);
1187 : sal_Int32 i = rtl_ustr_indexOfAscii_WithLength(
1188 51001 : str->buffer + *index, str->length - *index, from, fromLength);
1189 51001 : if (i == -1) {
1190 13612 : rtl_uString_assign(newStr, str);
1191 : } else {
1192 : assert(i <= str->length - *index);
1193 37389 : i += *index;
1194 : assert(fromLength <= str->length);
1195 37389 : if (str->length - fromLength > SAL_MAX_INT32 - toLength) {
1196 0 : std::abort();
1197 : }
1198 37389 : sal_Int32 n = str->length - fromLength + toLength;
1199 37389 : rtl_uString_acquire(str); // in case *newStr == str
1200 37389 : if (n != 0) {
1201 37389 : rtl_uString_new_WithLength(newStr, n);
1202 37389 : (*newStr)->length = n;
1203 : assert(i >= 0 && i < str->length);
1204 : memcpy(
1205 37389 : (*newStr)->buffer, str->buffer, i * sizeof (sal_Unicode));
1206 215541 : for (sal_Int32 j = 0; j != toLength; ++j) {
1207 : assert(static_cast< unsigned char >(to[j]) <= 0x7F);
1208 178152 : (*newStr)->buffer[i + j] = to[j];
1209 : }
1210 : memcpy(
1211 37389 : (*newStr)->buffer + i + toLength,
1212 37389 : str->buffer + i + fromLength,
1213 74778 : (str->length - i - fromLength) * sizeof (sal_Unicode));
1214 : }
1215 37389 : rtl_uString_release(str);
1216 : }
1217 51001 : *index = i;
1218 51001 : }
1219 :
1220 0 : void rtl_uString_newReplaceAll(
1221 : rtl_uString ** newStr, rtl_uString * str, rtl_uString const * from,
1222 : rtl_uString const * to) SAL_THROW_EXTERN_C()
1223 : {
1224 0 : rtl_uString_newReplaceAllFromIndex( newStr, str, from, to, 0 );
1225 0 : }
1226 :
1227 171109973 : void rtl_uString_newReplaceAllFromIndex(
1228 : rtl_uString ** newStr, rtl_uString * str, rtl_uString const * from,
1229 : rtl_uString const * to, sal_Int32 fromIndex) SAL_THROW_EXTERN_C()
1230 : {
1231 : assert(to != 0);
1232 : assert(fromIndex >= 0 && fromIndex <= str->length);
1233 171109973 : rtl_uString_assign(newStr, str);
1234 171132342 : for (sal_Int32 i = fromIndex;; i += to->length) {
1235 171132342 : rtl_uString_newReplaceFirst(newStr, *newStr, from, to, &i);
1236 171132342 : if (i == -1) {
1237 171109973 : break;
1238 : }
1239 22369 : }
1240 171109973 : }
1241 :
1242 16259 : void rtl_uString_newReplaceAllAsciiL(
1243 : rtl_uString ** newStr, rtl_uString * str, char const * from,
1244 : sal_Int32 fromLength, rtl_uString const * to) SAL_THROW_EXTERN_C()
1245 : {
1246 : assert(to != 0);
1247 16259 : rtl_uString_assign(newStr, str);
1248 18009 : for (sal_Int32 i = 0;; i += to->length) {
1249 : rtl_uString_newReplaceFirstAsciiL(
1250 18009 : newStr, *newStr, from, fromLength, to, &i);
1251 18009 : if (i == -1) {
1252 16259 : break;
1253 : }
1254 1750 : }
1255 16259 : }
1256 :
1257 13606 : void rtl_uString_newReplaceAllAsciiLAsciiL(
1258 : rtl_uString ** newStr, rtl_uString * str, char const * from,
1259 : sal_Int32 fromLength, char const * to, sal_Int32 toLength)
1260 : SAL_THROW_EXTERN_C()
1261 : {
1262 : assert(toLength >= 0);
1263 13606 : rtl_uString_assign(newStr, str);
1264 50293 : for (sal_Int32 i = 0;; i += toLength) {
1265 : rtl_uString_newReplaceFirstAsciiLAsciiL(
1266 50293 : newStr, *newStr, from, fromLength, to, toLength, &i);
1267 50293 : if (i == -1) {
1268 13606 : break;
1269 : }
1270 36687 : }
1271 13606 : }
1272 :
1273 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|