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