xref: /AOO42X/main/sal/rtl/source/strtmpl.c (revision a3755bb1965cae69a2694ff18ee39835b152d832)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 /* ======================================================================= */
25 /* Internal C-String help functions which could be used without the        */
26 /* String-Class                                                            */
27 /* ======================================================================= */
28 
29 /*
30 inline void rtl_str_ImplCopy( IMPL_RTL_STRCODE* pDest,
31                               const IMPL_RTL_STRCODE* pSrc,
32                               sal_Int32 nCount )
33 {
34     while ( nCount > 0 )
35     {
36         *pDest = *pSrc;
37         pDest++;
38         pSrc++;
39         nCount--;
40     }
41 }
42 */
43 
44 #define rtl_str_ImplCopy( _pDest, _pSrc, _nCount )                  \
45 {                                                                   \
46     IMPL_RTL_STRCODE*       __mm_pDest      = _pDest;               \
47     const IMPL_RTL_STRCODE* __mm_pSrc       = _pSrc;                \
48     sal_Int32               __mm_nCount     = _nCount;              \
49     while ( __mm_nCount > 0 )                                       \
50     {                                                               \
51         *__mm_pDest = *__mm_pSrc;                                   \
52         __mm_pDest++;                                               \
53         __mm_pSrc++;                                                \
54         __mm_nCount--;                                              \
55     }                                                               \
56 }
57 
58 /* ======================================================================= */
59 /* NULL-pointer guards                                                     */
60 /*                                                                         */
61 /* The C-string functions below document (see rtl/string.h, rtl/ustring.h) */
62 /* that their string arguments must be non-NULL, null-terminated strings.  */
63 /* Passing NULL is a caller error.  In non-product builds (OSL_DEBUG_LEVEL  */
64 /* > 0) we diagnose it loudly via OSL_PRECOND and then fall back to defined */
65 /* behaviour so the diagnostic build never dereferences a NULL pointer.    */
66 /*                                                                         */
67 /* In product builds the guards compile away entirely: callers must honour */
68 /* the documented non-NULL contract, and we add zero release-build cost    */
69 /* (not even a pointer test) to these hot string primitives.               */
70 /*                                                                         */
71 /* Even in debug, the guards run exactly once, at function entry: they are  */
72 /* OUTSIDE the per-character processing loops, so they do not change        */
73 /* string-processing throughput.                                           */
74 /* ======================================================================= */
75 
76 #define IMPL_RTL_STR_GUARD_MSG \
77     "rtl string function: NULL pointer passed; the documented contract " \
78     "requires a non-NULL, null-terminated string"
79 
80 #if OSL_DEBUG_LEVEL > 0
81 
82 /* Read-only argument: treat a NULL pointer as the empty string. */
83 static const IMPL_RTL_STRCODE aImplGuardEmptyStr = 0;
84 #define IMPL_RTL_STR_NULL_AS_EMPTY( pStr )                                  \
85     do {                                                                    \
86         OSL_PRECOND( (pStr) != NULL, IMPL_RTL_STR_GUARD_MSG );              \
87         if ( !(pStr) )                                                      \
88             (pStr) = &aImplGuardEmptyStr;                                   \
89     } while (0)
90 
91 /* Argument that cannot be substituted (returns a value): bail out early. */
92 #define IMPL_RTL_STR_NULL_RETURN( pStr, _ret )                              \
93     do {                                                                    \
94         OSL_PRECOND( (pStr) != NULL, IMPL_RTL_STR_GUARD_MSG );              \
95         if ( !(pStr) )                                                      \
96             return _ret;                                                    \
97     } while (0)
98 
99 /* Same, for functions returning void. */
100 #define IMPL_RTL_STR_NULL_RETURN_VOID( pStr )                               \
101     do {                                                                    \
102         OSL_PRECOND( (pStr) != NULL, IMPL_RTL_STR_GUARD_MSG );              \
103         if ( !(pStr) )                                                      \
104             return;                                                         \
105     } while (0)
106 
107 #else /* product build: guards compile away, callers must honour contract */
108 
109 #define IMPL_RTL_STR_NULL_AS_EMPTY( pStr )      ((void)0)
110 #define IMPL_RTL_STR_NULL_RETURN( pStr, _ret )  ((void)0)
111 #define IMPL_RTL_STR_NULL_RETURN_VOID( pStr )   ((void)0)
112 
113 #endif
114 
115 /* ======================================================================= */
116 /* C-String functions which could be used without the String-Class         */
117 /* ======================================================================= */
118 
getLength(const IMPL_RTL_STRCODE * pStr)119 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( getLength )( const IMPL_RTL_STRCODE* pStr )
120 {
121     const IMPL_RTL_STRCODE* pTempStr = pStr;
122     /* A NULL string has length 0.  Guarding getLength here also protects
123        hashCode, lastIndexOfChar, indexOfStr, lastIndexOfStr and trim, which
124        all start by calling getLength and then a length-bounded helper. */
125     IMPL_RTL_STR_NULL_RETURN( pStr, 0 );
126     while( *pTempStr )
127         pTempStr++;
128     return pTempStr-pStr;
129 }
130 
131 /* ----------------------------------------------------------------------- */
132 
compare(const IMPL_RTL_STRCODE * pStr1,const IMPL_RTL_STRCODE * pStr2)133 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( compare )( const IMPL_RTL_STRCODE* pStr1,
134                                                 const IMPL_RTL_STRCODE* pStr2 )
135 {
136     sal_Int32 nRet;
137     /* A NULL argument is treated as the empty string; the loop below then
138        yields the correct ordering (empty < any non-empty string). */
139     IMPL_RTL_STR_NULL_AS_EMPTY( pStr1 );
140     IMPL_RTL_STR_NULL_AS_EMPTY( pStr2 );
141     while ( ((nRet = ((sal_Int32)(IMPL_RTL_USTRCODE(*pStr1)))-
142                      ((sal_Int32)(IMPL_RTL_USTRCODE(*pStr2)))) == 0) &&
143             *pStr2 )
144     {
145         pStr1++;
146         pStr2++;
147     }
148 
149     return nRet;
150 }
151 
152 /* ----------------------------------------------------------------------- */
153 
compare_WithLength(const IMPL_RTL_STRCODE * pStr1,sal_Int32 nStr1Len,const IMPL_RTL_STRCODE * pStr2,sal_Int32 nStr2Len)154 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( compare_WithLength )( const IMPL_RTL_STRCODE* pStr1,
155                                                            sal_Int32 nStr1Len,
156                                                            const IMPL_RTL_STRCODE* pStr2,
157                                                            sal_Int32 nStr2Len )
158 {
159     sal_Int32 nRet = nStr1Len - nStr2Len;
160     int nCount = (nRet <= 0) ? nStr1Len : nStr2Len;
161 
162     --pStr1;
163     --pStr2;
164     while( (--nCount >= 0) && (*++pStr1 == *++pStr2) );
165 
166     if( nCount >= 0 )
167         nRet = ((sal_Int32)(IMPL_RTL_USTRCODE( *pStr1 )))
168              - ((sal_Int32)(IMPL_RTL_USTRCODE( *pStr2 )));
169 
170     return nRet;
171 }
172 
173 /* ----------------------------------------------------------------------- */
174 
shortenedCompare_WithLength(const IMPL_RTL_STRCODE * pStr1,sal_Int32 nStr1Len,const IMPL_RTL_STRCODE * pStr2,sal_Int32 nStr2Len,sal_Int32 nShortenedLength)175 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( shortenedCompare_WithLength )( const IMPL_RTL_STRCODE* pStr1,
176                                                                     sal_Int32 nStr1Len,
177                                                                     const IMPL_RTL_STRCODE* pStr2,
178                                                                     sal_Int32 nStr2Len,
179                                                                     sal_Int32 nShortenedLength )
180 {
181     const IMPL_RTL_STRCODE* pStr1End = pStr1 + nStr1Len;
182     const IMPL_RTL_STRCODE* pStr2End = pStr2 + nStr2Len;
183     sal_Int32               nRet;
184     while ( (nShortenedLength > 0) &&
185             (pStr1 < pStr1End) && (pStr2 < pStr2End) )
186     {
187         nRet = ((sal_Int32)(IMPL_RTL_USTRCODE( *pStr1 )))-
188                ((sal_Int32)(IMPL_RTL_USTRCODE( *pStr2 )));
189         if ( nRet )
190             return nRet;
191 
192         nShortenedLength--;
193         pStr1++;
194         pStr2++;
195     }
196 
197     if ( nShortenedLength <= 0 )
198         return 0;
199     return nStr1Len - nStr2Len;
200 }
201 
202 /* ----------------------------------------------------------------------- */
203 
reverseCompare_WithLength(const IMPL_RTL_STRCODE * pStr1,sal_Int32 nStr1Len,const IMPL_RTL_STRCODE * pStr2,sal_Int32 nStr2Len)204 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( reverseCompare_WithLength )( const IMPL_RTL_STRCODE* pStr1,
205                                                                   sal_Int32 nStr1Len,
206                                                                   const IMPL_RTL_STRCODE* pStr2,
207                                                                   sal_Int32 nStr2Len )
208 {
209     const IMPL_RTL_STRCODE* pStr1Run = pStr1+nStr1Len;
210     const IMPL_RTL_STRCODE* pStr2Run = pStr2+nStr2Len;
211     sal_Int32               nRet;
212     while ( (pStr1 < pStr1Run) && (pStr2 < pStr2Run) )
213     {
214         pStr1Run--;
215         pStr2Run--;
216         nRet = ((sal_Int32)(IMPL_RTL_USTRCODE( *pStr1Run )))-
217                ((sal_Int32)(IMPL_RTL_USTRCODE( *pStr2Run )));
218         if ( nRet )
219             return nRet;
220     }
221 
222     return nStr1Len - nStr2Len;
223 }
224 
225 /* ----------------------------------------------------------------------- */
226 
compareIgnoreAsciiCase(const IMPL_RTL_STRCODE * pStr1,const IMPL_RTL_STRCODE * pStr2)227 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( compareIgnoreAsciiCase )( const IMPL_RTL_STRCODE* pStr1,
228                                                                const IMPL_RTL_STRCODE* pStr2 )
229 {
230     sal_Int32   nRet;
231     sal_Int32   c1;
232     sal_Int32   c2;
233     /* A NULL argument is treated as the empty string. */
234     IMPL_RTL_STR_NULL_AS_EMPTY( pStr1 );
235     IMPL_RTL_STR_NULL_AS_EMPTY( pStr2 );
236     do
237     {
238         /* If character between 'A' and 'Z', than convert it to lowercase */
239         c1 = (sal_Int32)IMPL_RTL_USTRCODE( *pStr1 );
240         c2 = (sal_Int32)IMPL_RTL_USTRCODE( *pStr2 );
241         if ( (c1 >= 65) && (c1 <= 90) )
242             c1 += 32;
243         if ( (c2 >= 65) && (c2 <= 90) )
244             c2 += 32;
245         nRet = c1-c2;
246         if ( nRet != 0 )
247             return nRet;
248 
249         pStr1++;
250         pStr2++;
251     }
252     while ( c2 );
253 
254     return 0;
255 }
256 
257 /* ----------------------------------------------------------------------- */
258 
compareIgnoreAsciiCase_WithLength(const IMPL_RTL_STRCODE * pStr1,sal_Int32 nStr1Len,const IMPL_RTL_STRCODE * pStr2,sal_Int32 nStr2Len)259 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( compareIgnoreAsciiCase_WithLength )( const IMPL_RTL_STRCODE* pStr1,
260                                                                           sal_Int32 nStr1Len,
261                                                                           const IMPL_RTL_STRCODE* pStr2,
262                                                                           sal_Int32 nStr2Len )
263 {
264     const IMPL_RTL_STRCODE* pStr1End = pStr1 + nStr1Len;
265     const IMPL_RTL_STRCODE* pStr2End = pStr2 + nStr2Len;
266     sal_Int32   nRet;
267     sal_Int32   c1;
268     sal_Int32   c2;
269     while ( (pStr1 < pStr1End) && (pStr2 < pStr2End) )
270     {
271         /* If character between 'A' and 'Z', than convert it to lowercase */
272         c1 = (sal_Int32)IMPL_RTL_USTRCODE( *pStr1 );
273         c2 = (sal_Int32)IMPL_RTL_USTRCODE( *pStr2 );
274         if ( (c1 >= 65) && (c1 <= 90) )
275             c1 += 32;
276         if ( (c2 >= 65) && (c2 <= 90) )
277             c2 += 32;
278         nRet = c1-c2;
279         if ( nRet != 0 )
280             return nRet;
281 
282         pStr1++;
283         pStr2++;
284     }
285 
286     return nStr1Len - nStr2Len;
287 }
288 
289 /* ----------------------------------------------------------------------- */
290 
shortenedCompareIgnoreAsciiCase_WithLength(const IMPL_RTL_STRCODE * pStr1,sal_Int32 nStr1Len,const IMPL_RTL_STRCODE * pStr2,sal_Int32 nStr2Len,sal_Int32 nShortenedLength)291 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( shortenedCompareIgnoreAsciiCase_WithLength )( const IMPL_RTL_STRCODE* pStr1,
292                                                                                    sal_Int32 nStr1Len,
293                                                                                    const IMPL_RTL_STRCODE* pStr2,
294                                                                                    sal_Int32 nStr2Len,
295                                                                                    sal_Int32 nShortenedLength )
296 {
297     const IMPL_RTL_STRCODE* pStr1End = pStr1 + nStr1Len;
298     const IMPL_RTL_STRCODE* pStr2End = pStr2 + nStr2Len;
299     sal_Int32               nRet;
300     sal_Int32               c1;
301     sal_Int32               c2;
302     while ( (nShortenedLength > 0) &&
303             (pStr1 < pStr1End) && (pStr2 < pStr2End) )
304     {
305         /* If character between 'A' and 'Z', than convert it to lowercase */
306         c1 = (sal_Int32)IMPL_RTL_USTRCODE( *pStr1 );
307         c2 = (sal_Int32)IMPL_RTL_USTRCODE( *pStr2 );
308         if ( (c1 >= 65) && (c1 <= 90) )
309             c1 += 32;
310         if ( (c2 >= 65) && (c2 <= 90) )
311             c2 += 32;
312         nRet = c1-c2;
313         if ( nRet != 0 )
314             return nRet;
315 
316         nShortenedLength--;
317         pStr1++;
318         pStr2++;
319     }
320 
321     if ( nShortenedLength <= 0 )
322         return 0;
323     return nStr1Len - nStr2Len;
324 }
325 
326 /* ----------------------------------------------------------------------- */
327 
hashCode(const IMPL_RTL_STRCODE * pStr)328 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( hashCode )( const IMPL_RTL_STRCODE* pStr )
329 {
330     return IMPL_RTL_STRNAME( hashCode_WithLength )( pStr, IMPL_RTL_STRNAME( getLength )( pStr ) );
331 }
332 
333 /* ----------------------------------------------------------------------- */
334 
hashCode_WithLength(const IMPL_RTL_STRCODE * pStr,sal_Int32 nLen)335 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( hashCode_WithLength )( const IMPL_RTL_STRCODE* pStr,
336                                                             sal_Int32 nLen )
337 {
338     sal_Int32 h = nLen;
339 
340     if ( nLen < 256 )
341     {
342         while ( nLen > 0 )
343         {
344             h = (h*37) + IMPL_RTL_USTRCODE( *pStr );
345             pStr++;
346             nLen--;
347         }
348     }
349     else
350     {
351         sal_Int32               nSkip;
352         const IMPL_RTL_STRCODE* pEndStr = pStr+nLen-5;
353 
354         /* only sample some characters */
355         /* the first 3, some characters between, and the last 5 */
356         h = (h*39) + IMPL_RTL_USTRCODE( *pStr );
357         pStr++;
358         h = (h*39) + IMPL_RTL_USTRCODE( *pStr );
359         pStr++;
360         h = (h*39) + IMPL_RTL_USTRCODE( *pStr );
361         pStr++;
362 
363         if ( nLen < 32 )
364             nSkip = nLen / 4;
365         else
366             nSkip = nLen / 8;
367         nLen -= 8;
368         while ( nLen > 0 )
369         {
370             h = (h*39) + IMPL_RTL_USTRCODE( *pStr );
371             pStr += nSkip;
372             nLen -= nSkip;
373         }
374 
375         h = (h*39) + IMPL_RTL_USTRCODE( *pEndStr );
376         pEndStr++;
377         h = (h*39) + IMPL_RTL_USTRCODE( *pEndStr );
378         pEndStr++;
379         h = (h*39) + IMPL_RTL_USTRCODE( *pEndStr );
380         pEndStr++;
381         h = (h*39) + IMPL_RTL_USTRCODE( *pEndStr );
382         pEndStr++;
383         h = (h*39) + IMPL_RTL_USTRCODE( *pEndStr );
384     }
385 
386     return h;
387 }
388 
389 /* ----------------------------------------------------------------------- */
390 
indexOfChar(const IMPL_RTL_STRCODE * pStr,IMPL_RTL_STRCODE c)391 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( indexOfChar )( const IMPL_RTL_STRCODE* pStr,
392                                                     IMPL_RTL_STRCODE c )
393 {
394     const IMPL_RTL_STRCODE* pTempStr = pStr;
395     /* Nothing can be found in a NULL (empty) string. */
396     IMPL_RTL_STR_NULL_RETURN( pStr, -1 );
397     while ( *pTempStr )
398     {
399         if ( *pTempStr == c )
400             return pTempStr-pStr;
401 
402         pTempStr++;
403     }
404 
405     return -1;
406 }
407 
408 /* ----------------------------------------------------------------------- */
409 
indexOfChar_WithLength(const IMPL_RTL_STRCODE * pStr,sal_Int32 nLen,IMPL_RTL_STRCODE c)410 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( indexOfChar_WithLength )( const IMPL_RTL_STRCODE* pStr,
411                                                                sal_Int32 nLen,
412                                                                IMPL_RTL_STRCODE c )
413 {
414     const IMPL_RTL_STRCODE* pTempStr = pStr;
415     while ( nLen > 0 )
416     {
417         if ( *pTempStr == c )
418             return pTempStr-pStr;
419 
420         pTempStr++;
421         nLen--;
422     }
423 
424     return -1;
425 }
426 
427 /* ----------------------------------------------------------------------- */
428 
lastIndexOfChar(const IMPL_RTL_STRCODE * pStr,IMPL_RTL_STRCODE c)429 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( lastIndexOfChar )( const IMPL_RTL_STRCODE* pStr,
430                                                         IMPL_RTL_STRCODE c )
431 {
432     return IMPL_RTL_STRNAME( lastIndexOfChar_WithLength )( pStr, IMPL_RTL_STRNAME( getLength )( pStr ), c );
433 }
434 
435 /* ----------------------------------------------------------------------- */
436 
lastIndexOfChar_WithLength(const IMPL_RTL_STRCODE * pStr,sal_Int32 nLen,IMPL_RTL_STRCODE c)437 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( lastIndexOfChar_WithLength )( const IMPL_RTL_STRCODE* pStr,
438                                                                    sal_Int32 nLen,
439                                                                    IMPL_RTL_STRCODE c )
440 {
441     pStr += nLen;
442     while ( nLen > 0 )
443     {
444         nLen--;
445         pStr--;
446 
447         if ( *pStr == c )
448             return nLen;
449     }
450 
451     return -1;
452 }
453 
454 /* ----------------------------------------------------------------------- */
455 
indexOfStr(const IMPL_RTL_STRCODE * pStr,const IMPL_RTL_STRCODE * pSubStr)456 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( indexOfStr )( const IMPL_RTL_STRCODE* pStr,
457                                                    const IMPL_RTL_STRCODE* pSubStr )
458 {
459     return IMPL_RTL_STRNAME( indexOfStr_WithLength )( pStr, IMPL_RTL_STRNAME( getLength )( pStr ),
460                                                       pSubStr, IMPL_RTL_STRNAME( getLength )( pSubStr ) );
461 }
462 
463 /* ----------------------------------------------------------------------- */
464 
indexOfStr_WithLength(const IMPL_RTL_STRCODE * pStr,sal_Int32 nStrLen,const IMPL_RTL_STRCODE * pSubStr,sal_Int32 nSubLen)465 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( indexOfStr_WithLength )( const IMPL_RTL_STRCODE* pStr,
466                                                               sal_Int32 nStrLen,
467                                                               const  IMPL_RTL_STRCODE* pSubStr,
468                                                               sal_Int32 nSubLen )
469 {
470     /* faster search for a single character */
471     if ( nSubLen < 2 )
472     {
473         /* an empty SubString is always not foundable */
474         if ( nSubLen == 1 )
475         {
476             IMPL_RTL_STRCODE        c = *pSubStr;
477             const IMPL_RTL_STRCODE* pTempStr = pStr;
478             while ( nStrLen > 0 )
479             {
480                 if ( *pTempStr == c )
481                     return pTempStr-pStr;
482 
483                 pTempStr++;
484                 nStrLen--;
485             }
486         }
487     }
488     else
489     {
490         const IMPL_RTL_STRCODE* pTempStr = pStr;
491         while ( nStrLen > 0 )
492         {
493             if ( *pTempStr == *pSubStr )
494             {
495                 /* Compare SubString */
496                 if ( nSubLen <= nStrLen )
497                 {
498                     const IMPL_RTL_STRCODE* pTempStr1 = pTempStr;
499                     const IMPL_RTL_STRCODE* pTempStr2 = pSubStr;
500                     sal_Int32               nTempLen = nSubLen;
501                     while ( nTempLen )
502                     {
503                         if ( *pTempStr1 != *pTempStr2 )
504                             break;
505 
506                         pTempStr1++;
507                         pTempStr2++;
508                         nTempLen--;
509                     }
510 
511                     if ( !nTempLen )
512                         return pTempStr-pStr;
513                 }
514                 else
515                     break;
516             }
517 
518             nStrLen--;
519             pTempStr++;
520         }
521     }
522 
523     return -1;
524 }
525 
526 /* ----------------------------------------------------------------------- */
527 
lastIndexOfStr(const IMPL_RTL_STRCODE * pStr,const IMPL_RTL_STRCODE * pSubStr)528 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( lastIndexOfStr )( const IMPL_RTL_STRCODE* pStr,
529                                                        const IMPL_RTL_STRCODE* pSubStr )
530 {
531     return IMPL_RTL_STRNAME( lastIndexOfStr_WithLength )( pStr, IMPL_RTL_STRNAME( getLength )( pStr ),
532                                                           pSubStr, IMPL_RTL_STRNAME( getLength )( pSubStr ) );
533 }
534 
535 /* ----------------------------------------------------------------------- */
536 
lastIndexOfStr_WithLength(const IMPL_RTL_STRCODE * pStr,sal_Int32 nStrLen,const IMPL_RTL_STRCODE * pSubStr,sal_Int32 nSubLen)537 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( lastIndexOfStr_WithLength )( const IMPL_RTL_STRCODE* pStr,
538                                                                   sal_Int32 nStrLen,
539                                                                   const IMPL_RTL_STRCODE* pSubStr,
540                                                                   sal_Int32 nSubLen )
541 {
542     /* faster search for a single character */
543     if ( nSubLen < 2 )
544     {
545         /* an empty SubString is always not foundable */
546         if ( nSubLen == 1 )
547         {
548             IMPL_RTL_STRCODE c = *pSubStr;
549             pStr += nStrLen;
550             while ( nStrLen > 0 )
551             {
552                 nStrLen--;
553                 pStr--;
554 
555                 if ( *pStr == c )
556                     return nStrLen;
557             }
558         }
559     }
560     else
561     {
562         pStr += nStrLen;
563         nStrLen -= nSubLen;
564         pStr -= nSubLen;
565         while ( nStrLen >= 0 )
566         {
567             const IMPL_RTL_STRCODE* pTempStr1 = pStr;
568             const IMPL_RTL_STRCODE* pTempStr2 = pSubStr;
569             sal_Int32               nTempLen = nSubLen;
570             while ( nTempLen )
571             {
572                 if ( *pTempStr1 != *pTempStr2 )
573                     break;
574 
575                 pTempStr1++;
576                 pTempStr2++;
577                 nTempLen--;
578             }
579 
580             if ( !nTempLen )
581                 return nStrLen;
582 
583             nStrLen--;
584             pStr--;
585         }
586     }
587 
588     return -1;
589 }
590 
591 /* ----------------------------------------------------------------------- */
592 
replaceChar(IMPL_RTL_STRCODE * pStr,IMPL_RTL_STRCODE cOld,IMPL_RTL_STRCODE cNew)593 void SAL_CALL IMPL_RTL_STRNAME( replaceChar )( IMPL_RTL_STRCODE* pStr,
594                                                IMPL_RTL_STRCODE cOld,
595                                                IMPL_RTL_STRCODE cNew )
596 {
597     /* Nothing to replace in a NULL (empty) string. */
598     IMPL_RTL_STR_NULL_RETURN_VOID( pStr );
599     while ( *pStr )
600     {
601         if ( *pStr == cOld )
602             *pStr = cNew;
603 
604         pStr++;
605     }
606 }
607 
608 /* ----------------------------------------------------------------------- */
609 
replaceChar_WithLength(IMPL_RTL_STRCODE * pStr,sal_Int32 nLen,IMPL_RTL_STRCODE cOld,IMPL_RTL_STRCODE cNew)610 void SAL_CALL IMPL_RTL_STRNAME( replaceChar_WithLength )( IMPL_RTL_STRCODE* pStr,
611                                                           sal_Int32 nLen,
612                                                           IMPL_RTL_STRCODE cOld,
613                                                           IMPL_RTL_STRCODE cNew )
614 {
615     while ( nLen > 0 )
616     {
617         if ( *pStr == cOld )
618             *pStr = cNew;
619 
620         pStr++;
621         nLen--;
622     }
623 }
624 
625 /* ----------------------------------------------------------------------- */
626 
toAsciiLowerCase(IMPL_RTL_STRCODE * pStr)627 void SAL_CALL IMPL_RTL_STRNAME( toAsciiLowerCase )( IMPL_RTL_STRCODE* pStr )
628 {
629     /* Nothing to convert in a NULL (empty) string. */
630     IMPL_RTL_STR_NULL_RETURN_VOID( pStr );
631     while ( *pStr )
632     {
633         /* Between A-Z (65-90), than to lowercase (+32) */
634         if ( (*pStr >= 65) && (*pStr <= 90) )
635             *pStr += 32;
636 
637         pStr++;
638     }
639 }
640 
641 /* ----------------------------------------------------------------------- */
642 
toAsciiLowerCase_WithLength(IMPL_RTL_STRCODE * pStr,sal_Int32 nLen)643 void SAL_CALL IMPL_RTL_STRNAME( toAsciiLowerCase_WithLength )( IMPL_RTL_STRCODE* pStr,
644                                                                sal_Int32 nLen )
645 {
646     while ( nLen > 0 )
647     {
648         /* Between A-Z (65-90), than to lowercase (+32) */
649         if ( (*pStr >= 65) && (*pStr <= 90) )
650             *pStr += 32;
651 
652         pStr++;
653         nLen--;
654     }
655 }
656 
657 /* ----------------------------------------------------------------------- */
658 
toAsciiUpperCase(IMPL_RTL_STRCODE * pStr)659 void SAL_CALL IMPL_RTL_STRNAME( toAsciiUpperCase )( IMPL_RTL_STRCODE* pStr )
660 {
661     /* Nothing to convert in a NULL (empty) string. */
662     IMPL_RTL_STR_NULL_RETURN_VOID( pStr );
663     while ( *pStr )
664     {
665         /* Between a-z (97-122), than to uppercase (-32) */
666         if ( (*pStr >= 97) && (*pStr <= 122) )
667             *pStr -= 32;
668 
669         pStr++;
670     }
671 }
672 
673 /* ----------------------------------------------------------------------- */
674 
toAsciiUpperCase_WithLength(IMPL_RTL_STRCODE * pStr,sal_Int32 nLen)675 void SAL_CALL IMPL_RTL_STRNAME( toAsciiUpperCase_WithLength )( IMPL_RTL_STRCODE* pStr,
676                                                                sal_Int32 nLen )
677 {
678     while ( nLen > 0 )
679     {
680         /* Between a-z (97-122), than to uppercase (-32) */
681         if ( (*pStr >= 97) && (*pStr <= 122) )
682             *pStr -= 32;
683 
684         pStr++;
685         nLen--;
686     }
687 }
688 
689 /* ----------------------------------------------------------------------- */
690 
trim(IMPL_RTL_STRCODE * pStr)691 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( trim )( IMPL_RTL_STRCODE* pStr )
692 {
693     return IMPL_RTL_STRNAME( trim_WithLength )( pStr, IMPL_RTL_STRNAME( getLength )( pStr ) );
694 }
695 
696 /* ----------------------------------------------------------------------- */
697 
trim_WithLength(IMPL_RTL_STRCODE * pStr,sal_Int32 nLen)698 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( trim_WithLength )( IMPL_RTL_STRCODE* pStr, sal_Int32 nLen )
699 {
700     sal_Int32 nPreSpaces    = 0;
701     sal_Int32 nPostSpaces   = 0;
702     sal_Int32 nIndex        = nLen-1;
703 
704     while ( (nPreSpaces < nLen) && rtl_ImplIsWhitespace( IMPL_RTL_USTRCODE(*(pStr+nPreSpaces)) ) )
705         nPreSpaces++;
706 
707     while ( (nIndex > nPreSpaces) && rtl_ImplIsWhitespace( IMPL_RTL_USTRCODE(*(pStr+nIndex)) ) )
708     {
709         nPostSpaces++;
710         nIndex--;
711     }
712 
713     if ( nPostSpaces )
714     {
715         nLen -= nPostSpaces;
716         *(pStr+nLen) = 0;
717     }
718 
719     if ( nPreSpaces )
720     {
721         IMPL_RTL_STRCODE* pNewStr = pStr+nPreSpaces;
722 
723         nLen -= nPreSpaces;
724         nIndex = nLen;
725 
726         while ( nIndex )
727         {
728             *pStr = *pNewStr;
729             pStr++;
730             pNewStr++;
731             nIndex--;
732         }
733         *pStr = 0;
734     }
735 
736     return nLen;
737 }
738 
739 /* ----------------------------------------------------------------------- */
740 
valueOfBoolean(IMPL_RTL_STRCODE * pStr,sal_Bool b)741 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( valueOfBoolean )( IMPL_RTL_STRCODE* pStr, sal_Bool b )
742 {
743     if ( b )
744     {
745         *pStr = 't';
746         pStr++;
747         *pStr = 'r';
748         pStr++;
749         *pStr = 'u';
750         pStr++;
751         *pStr = 'e';
752         pStr++;
753         *pStr = 0;
754         return 4;
755     }
756     else
757     {
758         *pStr = 'f';
759         pStr++;
760         *pStr = 'a';
761         pStr++;
762         *pStr = 'l';
763         pStr++;
764         *pStr = 's';
765         pStr++;
766         *pStr = 'e';
767         pStr++;
768         *pStr = 0;
769         return 5;
770     }
771 }
772 
773 /* ----------------------------------------------------------------------- */
774 
valueOfChar(IMPL_RTL_STRCODE * pStr,IMPL_RTL_STRCODE c)775 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( valueOfChar )( IMPL_RTL_STRCODE* pStr,
776                                                     IMPL_RTL_STRCODE c )
777 {
778     /* The caller must supply a writable buffer; on NULL write nothing. */
779     IMPL_RTL_STR_NULL_RETURN( pStr, 0 );
780     *pStr++ = c;
781     *pStr = 0;
782     return 1;
783 }
784 
785 /* ----------------------------------------------------------------------- */
786 
valueOfInt32(IMPL_RTL_STRCODE * pStr,sal_Int32 n,sal_Int16 nRadix)787 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( valueOfInt32 )( IMPL_RTL_STRCODE* pStr,
788                                                      sal_Int32 n,
789                                                      sal_Int16 nRadix )
790 {
791     sal_Char    aBuf[RTL_STR_MAX_VALUEOFINT32];
792     sal_Char*   pBuf = aBuf;
793     sal_Int32   nLen = 0;
794     sal_uInt32  nValue;
795 
796     /* Radix must be valid */
797     if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
798         nRadix = 10;
799 
800     /* is value negativ */
801     if ( n < 0 )
802     {
803         *pStr = '-';
804         pStr++;
805         nLen++;
806         nValue = -n; /* FIXME this code is not portable for n == -2147483648
807                         (smallest negative value for sal_Int32) */
808     }
809     else
810         nValue = n;
811 
812     /* create a recursive buffer with all values, except the last one */
813     do
814     {
815         sal_Char nDigit = (sal_Char)(nValue % nRadix);
816         nValue /= nRadix;
817         if ( nDigit > 9 )
818             *pBuf = (nDigit-10) + 'a';
819         else
820             *pBuf = (nDigit + '0' );
821         pBuf++;
822     }
823     while ( nValue > 0 );
824 
825     /* copy the values in the right direction into the destination buffer */
826     do
827     {
828         pBuf--;
829         *pStr = *pBuf;
830         pStr++;
831         nLen++;
832     }
833     while ( pBuf != aBuf );
834     *pStr = 0;
835 
836     return nLen;
837 }
838 
839 /* ----------------------------------------------------------------------- */
840 
valueOfInt64(IMPL_RTL_STRCODE * pStr,sal_Int64 n,sal_Int16 nRadix)841 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( valueOfInt64 )( IMPL_RTL_STRCODE* pStr,
842                                                      sal_Int64 n,
843                                                      sal_Int16 nRadix )
844 {
845     sal_Char    aBuf[RTL_STR_MAX_VALUEOFINT64];
846     sal_Char*   pBuf = aBuf;
847     sal_Int32   nLen = 0;
848     sal_uInt64  nValue;
849 
850     /* Radix must be valid */
851     if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
852         nRadix = 10;
853 
854     /* is value negativ */
855     if ( n < 0 )
856     {
857         *pStr = '-';
858         pStr++;
859         nLen++;
860         nValue = -n; /* FIXME this code is not portable for
861                         n == -9223372036854775808 (smallest negative value for
862                         sal_Int64) */
863     }
864     else
865         nValue = n;
866 
867     /* create a recursive buffer with all values, except the last one */
868     do
869     {
870         sal_Char nDigit = (sal_Char)(nValue % nRadix);
871         nValue /= nRadix;
872         if ( nDigit > 9 )
873             *pBuf = (nDigit-10) + 'a';
874         else
875             *pBuf = (nDigit + '0' );
876         pBuf++;
877     }
878     while ( nValue > 0 );
879 
880     /* copy the values in the right direction into the destination buffer */
881     do
882     {
883         pBuf--;
884         *pStr = *pBuf;
885         pStr++;
886         nLen++;
887     }
888     while ( pBuf != aBuf );
889     *pStr = 0;
890 
891     return nLen;
892 }
893 
894 /* ----------------------------------------------------------------------- */
895 
toBoolean(const IMPL_RTL_STRCODE * pStr)896 sal_Bool SAL_CALL IMPL_RTL_STRNAME( toBoolean )( const IMPL_RTL_STRCODE* pStr )
897 {
898     if ( *pStr == '1' )
899         return sal_True;
900 
901     if ( (*pStr == 'T') || (*pStr == 't') )
902     {
903         pStr++;
904         if ( (*pStr == 'R') || (*pStr == 'r') )
905         {
906             pStr++;
907             if ( (*pStr == 'U') || (*pStr == 'u') )
908             {
909                 pStr++;
910                 if ( (*pStr == 'E') || (*pStr == 'e') )
911                     return sal_True;
912             }
913         }
914     }
915 
916     return sal_False;
917 }
918 
919 /* ----------------------------------------------------------------------- */
920 
toInt32(const IMPL_RTL_STRCODE * pStr,sal_Int16 nRadix)921 sal_Int32 SAL_CALL IMPL_RTL_STRNAME( toInt32 )( const IMPL_RTL_STRCODE* pStr,
922                                                 sal_Int16 nRadix )
923 {
924     sal_Bool    bNeg;
925     sal_Int16   nDigit;
926     sal_Int32   n = 0;
927 
928     if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
929         nRadix = 10;
930 
931     /* Skip whitespaces */
932     while ( *pStr && rtl_ImplIsWhitespace( IMPL_RTL_USTRCODE( *pStr ) ) )
933         pStr++;
934 
935     if ( *pStr == '-' )
936     {
937         bNeg = sal_True;
938         pStr++;
939     }
940     else
941     {
942         if ( *pStr == '+' )
943             pStr++;
944         bNeg = sal_False;
945     }
946 
947     while ( *pStr )
948     {
949         nDigit = rtl_ImplGetDigit( IMPL_RTL_USTRCODE( *pStr ), nRadix );
950         if ( nDigit < 0 )
951             break;
952 
953         n *= nRadix;
954         n += nDigit;
955 
956         pStr++;
957     }
958 
959     if ( bNeg )
960         return -n;
961     else
962         return n;
963 }
964 
965 /* ----------------------------------------------------------------------- */
966 
toInt64(const IMPL_RTL_STRCODE * pStr,sal_Int16 nRadix)967 sal_Int64 SAL_CALL IMPL_RTL_STRNAME( toInt64 )( const IMPL_RTL_STRCODE* pStr,
968                                                 sal_Int16 nRadix )
969 {
970     sal_Bool    bNeg;
971     sal_Int16   nDigit;
972     sal_Int64   n = 0;
973 
974     if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
975         nRadix = 10;
976 
977     /* Skip whitespaces */
978     while ( *pStr && rtl_ImplIsWhitespace( IMPL_RTL_USTRCODE( *pStr ) ) )
979         pStr++;
980 
981     if ( *pStr == '-' )
982     {
983         bNeg = sal_True;
984         pStr++;
985     }
986     else
987     {
988         if ( *pStr == '+' )
989             pStr++;
990         bNeg = sal_False;
991     }
992 
993     while ( *pStr )
994     {
995         nDigit = rtl_ImplGetDigit( IMPL_RTL_USTRCODE( *pStr ), nRadix );
996         if ( nDigit < 0 )
997             break;
998 
999         n *= nRadix;
1000         n += nDigit;
1001 
1002         pStr++;
1003     }
1004 
1005     if ( bNeg )
1006         return -n;
1007     else
1008         return n;
1009 }
1010 
1011 /* ======================================================================= */
1012 /* Internal String-Class help functions                                    */
1013 /* ======================================================================= */
1014 
ImplAlloc(sal_Int32 nLen)1015 static IMPL_RTL_STRINGDATA* IMPL_RTL_STRINGNAME( ImplAlloc )( sal_Int32 nLen )
1016 {
1017     IMPL_RTL_STRINGDATA * pData
1018         = (SAL_INT_CAST(sal_uInt32, nLen)
1019            <= ((SAL_MAX_UINT32 - sizeof (IMPL_RTL_STRINGDATA))
1020                / sizeof (IMPL_RTL_STRCODE)))
1021         ? (IMPL_RTL_STRINGDATA *) rtl_allocateMemory(
1022             sizeof (IMPL_RTL_STRINGDATA) + nLen * sizeof (IMPL_RTL_STRCODE))
1023         : NULL;
1024     if (pData != NULL) {
1025         pData->refCount = 1;
1026         pData->length = nLen;
1027         pData->buffer[nLen] = 0;
1028     }
1029     return pData;
1030 }
1031 
1032 /* ----------------------------------------------------------------------- */
1033 
ImplNewCopy(IMPL_RTL_STRINGDATA ** ppThis,IMPL_RTL_STRINGDATA * pStr,sal_Int32 nCount)1034 static IMPL_RTL_STRCODE* IMPL_RTL_STRINGNAME( ImplNewCopy )( IMPL_RTL_STRINGDATA** ppThis,
1035                                                              IMPL_RTL_STRINGDATA* pStr,
1036                                                              sal_Int32 nCount )
1037 {
1038     IMPL_RTL_STRCODE*       pDest;
1039     const IMPL_RTL_STRCODE* pSrc;
1040     IMPL_RTL_STRINGDATA*    pData = IMPL_RTL_STRINGNAME( ImplAlloc )( pStr->length );
1041     OSL_ASSERT(pData != NULL);
1042 
1043     pDest   = pData->buffer;
1044     pSrc    = pStr->buffer;
1045     while ( nCount > 0 )
1046     {
1047         *pDest = *pSrc;
1048         pDest++;
1049         pSrc++;
1050         nCount--;
1051     }
1052 
1053     *ppThis = pData;
1054     return pDest;
1055 }
1056 
1057 /* ======================================================================= */
1058 /* String-Class functions                                                  */
1059 /* ======================================================================= */
1060 
1061 #define IMPL_RTL_AQUIRE( pThis )                                \
1062 {                                                               \
1063     if (!SAL_STRING_IS_STATIC (pThis))                          \
1064         osl_incrementInterlockedCount( &((pThis)->refCount) );  \
1065 }
1066 
1067 /* ----------------------------------------------------------------------- */
1068 
acquire(IMPL_RTL_STRINGDATA * pThis)1069 void SAL_CALL IMPL_RTL_STRINGNAME( acquire )( IMPL_RTL_STRINGDATA* pThis )
1070 {
1071     IMPL_RTL_AQUIRE( pThis );
1072 }
1073 
1074 /* ----------------------------------------------------------------------- */
1075 
release(IMPL_RTL_STRINGDATA * pThis)1076 void SAL_CALL IMPL_RTL_STRINGNAME( release )( IMPL_RTL_STRINGDATA* pThis )
1077 {
1078     if (SAL_STRING_IS_STATIC (pThis))
1079         return;
1080 
1081 /* OString doesn't have an 'intern' */
1082 #ifdef IMPL_RTL_INTERN
1083     if (SAL_STRING_IS_INTERN (pThis))
1084     {
1085         internRelease (pThis);
1086         return;
1087     }
1088 #endif
1089 
1090     if ( pThis->refCount == 1 ||
1091          !osl_decrementInterlockedCount( &(pThis->refCount) ) )
1092     {
1093         rtl_freeMemory( pThis );
1094     }
1095 }
1096 
1097 /* ----------------------------------------------------------------------- */
1098 
new(IMPL_RTL_STRINGDATA ** ppThis)1099 void SAL_CALL IMPL_RTL_STRINGNAME( new )( IMPL_RTL_STRINGDATA** ppThis )
1100 {
1101     if ( *ppThis)
1102         IMPL_RTL_STRINGNAME( release )( *ppThis );
1103 
1104     *ppThis = (IMPL_RTL_STRINGDATA*) (&IMPL_RTL_EMPTYSTRING);
1105     IMPL_RTL_AQUIRE( *ppThis );
1106 }
1107 
1108 /* ----------------------------------------------------------------------- */
1109 
new_WithLength(IMPL_RTL_STRINGDATA ** ppThis,sal_Int32 nLen)1110 void SAL_CALL IMPL_RTL_STRINGNAME( new_WithLength )( IMPL_RTL_STRINGDATA** ppThis, sal_Int32 nLen )
1111 {
1112     if ( nLen <= 0 )
1113         IMPL_RTL_STRINGNAME( new )( ppThis );
1114     else
1115     {
1116         if ( *ppThis)
1117             IMPL_RTL_STRINGNAME( release )( *ppThis );
1118 
1119         *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
1120         OSL_ASSERT(*ppThis != NULL);
1121         (*ppThis)->length   = 0;
1122 
1123         {
1124         IMPL_RTL_STRCODE* pTempStr = (*ppThis)->buffer;
1125         while ( nLen >= 0 )
1126         {
1127             *pTempStr = 0;
1128             pTempStr++;
1129             nLen--;
1130         }
1131         }
1132     }
1133 }
1134 
1135 /* ----------------------------------------------------------------------- */
1136 
newFromString(IMPL_RTL_STRINGDATA ** ppThis,const IMPL_RTL_STRINGDATA * pStr)1137 void SAL_CALL IMPL_RTL_STRINGNAME( newFromString )( IMPL_RTL_STRINGDATA** ppThis,
1138                                                     const IMPL_RTL_STRINGDATA* pStr )
1139 {
1140     IMPL_RTL_STRINGDATA* pOrg;
1141 
1142     if ( !pStr->length )
1143     {
1144         IMPL_RTL_STRINGNAME( new )( ppThis );
1145         return;
1146     }
1147 
1148     pOrg = *ppThis;
1149     *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( pStr->length );
1150     OSL_ASSERT(*ppThis != NULL);
1151     rtl_str_ImplCopy( (*ppThis)->buffer, pStr->buffer, pStr->length );
1152 
1153     /* must be done at least, if pStr == *ppThis */
1154     if ( pOrg )
1155         IMPL_RTL_STRINGNAME( release )( pOrg );
1156 }
1157 
1158 /* ----------------------------------------------------------------------- */
1159 
newFromStr(IMPL_RTL_STRINGDATA ** ppThis,const IMPL_RTL_STRCODE * pCharStr)1160 void SAL_CALL IMPL_RTL_STRINGNAME( newFromStr )( IMPL_RTL_STRINGDATA** ppThis,
1161                                                  const IMPL_RTL_STRCODE* pCharStr )
1162 {
1163     IMPL_RTL_STRCODE*       pBuffer;
1164     IMPL_RTL_STRINGDATA*    pOrg;
1165     sal_Int32               nLen;
1166 
1167     if ( pCharStr )
1168     {
1169         const IMPL_RTL_STRCODE* pTempStr = pCharStr;
1170         while( *pTempStr )
1171             pTempStr++;
1172         nLen = pTempStr-pCharStr;
1173     }
1174     else
1175         nLen = 0;
1176 
1177     if ( !nLen )
1178     {
1179         IMPL_RTL_STRINGNAME( new )( ppThis );
1180         return;
1181     }
1182 
1183     pOrg = *ppThis;
1184     *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
1185     OSL_ASSERT(*ppThis != NULL);
1186     pBuffer = (*ppThis)->buffer;
1187     do
1188     {
1189         *pBuffer = *pCharStr;
1190         pBuffer++;
1191         pCharStr++;
1192     }
1193     while ( *pCharStr );
1194 
1195     /* must be done at least, if pCharStr == *ppThis */
1196     if ( pOrg )
1197         IMPL_RTL_STRINGNAME( release )( pOrg );
1198 }
1199 
1200 /* ----------------------------------------------------------------------- */
1201 
newFromStr_WithLength(IMPL_RTL_STRINGDATA ** ppThis,const IMPL_RTL_STRCODE * pCharStr,sal_Int32 nLen)1202 void SAL_CALL IMPL_RTL_STRINGNAME( newFromStr_WithLength )( IMPL_RTL_STRINGDATA** ppThis,
1203                                                             const IMPL_RTL_STRCODE* pCharStr,
1204                                                             sal_Int32 nLen )
1205 {
1206     IMPL_RTL_STRINGDATA* pOrg;
1207 
1208     if ( !pCharStr || (nLen <= 0) )
1209     {
1210         IMPL_RTL_STRINGNAME( new )( ppThis );
1211         return;
1212     }
1213 
1214     pOrg = *ppThis;
1215     *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
1216     OSL_ASSERT(*ppThis != NULL);
1217     rtl_str_ImplCopy( (*ppThis)->buffer, pCharStr, nLen );
1218 
1219     /* must be done at least, if pCharStr == *ppThis */
1220     if ( pOrg )
1221         IMPL_RTL_STRINGNAME( release )( pOrg );
1222 }
1223 
1224 /* ----------------------------------------------------------------------- */
1225 
assign(IMPL_RTL_STRINGDATA ** ppThis,IMPL_RTL_STRINGDATA * pStr)1226 void SAL_CALL IMPL_RTL_STRINGNAME( assign )( IMPL_RTL_STRINGDATA** ppThis,
1227                                              IMPL_RTL_STRINGDATA* pStr )
1228 {
1229     /* must be done at first, if pStr == *ppThis */
1230     IMPL_RTL_AQUIRE( pStr );
1231 
1232     if ( *ppThis )
1233         IMPL_RTL_STRINGNAME( release )( *ppThis );
1234 
1235     *ppThis = pStr;
1236 }
1237 
1238 /* ----------------------------------------------------------------------- */
1239 
getLength(const IMPL_RTL_STRINGDATA * pThis)1240 sal_Int32 SAL_CALL IMPL_RTL_STRINGNAME( getLength )( const IMPL_RTL_STRINGDATA* pThis )
1241 {
1242     return pThis->length;
1243 }
1244 
1245 /* ----------------------------------------------------------------------- */
1246 
getStr(IMPL_RTL_STRINGDATA * pThis)1247 IMPL_RTL_STRCODE* SAL_CALL IMPL_RTL_STRINGNAME( getStr )( IMPL_RTL_STRINGDATA * pThis )
1248 {
1249     return pThis->buffer;
1250 }
1251 
1252 /* ----------------------------------------------------------------------- */
1253 
newConcat(IMPL_RTL_STRINGDATA ** ppThis,IMPL_RTL_STRINGDATA * pLeft,IMPL_RTL_STRINGDATA * pRight)1254 void SAL_CALL IMPL_RTL_STRINGNAME( newConcat )( IMPL_RTL_STRINGDATA** ppThis,
1255                                                 IMPL_RTL_STRINGDATA* pLeft,
1256                                                 IMPL_RTL_STRINGDATA* pRight )
1257 {
1258     IMPL_RTL_STRINGDATA* pOrg = *ppThis;
1259 
1260     /* Test for 0-Pointer - if not, change newReplaceStrAt! */
1261     if ( !pRight || !pRight->length )
1262     {
1263         *ppThis = pLeft;
1264         IMPL_RTL_AQUIRE( pLeft );
1265     }
1266     else if ( !pLeft || !pLeft->length )
1267     {
1268         *ppThis = pRight;
1269         IMPL_RTL_AQUIRE( pRight );
1270     }
1271     else
1272     {
1273         IMPL_RTL_STRINGDATA* pTempStr = IMPL_RTL_STRINGNAME( ImplAlloc )( pLeft->length + pRight->length );
1274         OSL_ASSERT(pTempStr != NULL);
1275         rtl_str_ImplCopy( pTempStr->buffer, pLeft->buffer, pLeft->length );
1276         rtl_str_ImplCopy( pTempStr->buffer+pLeft->length, pRight->buffer, pRight->length );
1277         *ppThis = pTempStr;
1278     }
1279 
1280     /* must be done at least, if left or right == *ppThis */
1281     if ( pOrg )
1282         IMPL_RTL_STRINGNAME( release )( pOrg );
1283 }
1284 
1285 /* ----------------------------------------------------------------------- */
1286 
newReplaceStrAt(IMPL_RTL_STRINGDATA ** ppThis,IMPL_RTL_STRINGDATA * pStr,sal_Int32 nIndex,sal_Int32 nCount,IMPL_RTL_STRINGDATA * pNewSubStr)1287 void SAL_CALL IMPL_RTL_STRINGNAME( newReplaceStrAt )( IMPL_RTL_STRINGDATA** ppThis,
1288                                                       IMPL_RTL_STRINGDATA* pStr,
1289                                                       sal_Int32 nIndex,
1290                                                       sal_Int32 nCount,
1291                                                       IMPL_RTL_STRINGDATA* pNewSubStr )
1292 {
1293     /* Append? */
1294     if ( nIndex >= pStr->length )
1295     {
1296         /* newConcat test, if pNewSubStr is 0 */
1297         IMPL_RTL_STRINGNAME( newConcat )( ppThis, pStr, pNewSubStr );
1298         return;
1299     }
1300 
1301     /* negativ index? */
1302     if ( nIndex < 0 )
1303     {
1304         nCount -= nIndex;
1305         nIndex = 0;
1306     }
1307 
1308     /* not more than the String length could be deleted */
1309     if ( nCount >= pStr->length-nIndex )
1310     {
1311         nCount = pStr->length-nIndex;
1312 
1313         /* Assign of NewSubStr? */
1314         if ( !nIndex && (nCount >= pStr->length) )
1315         {
1316             if ( !pNewSubStr )
1317                 IMPL_RTL_STRINGNAME( new )( ppThis );
1318             else
1319                 IMPL_RTL_STRINGNAME( assign )( ppThis, pNewSubStr );
1320             return;
1321         }
1322     }
1323 
1324     /* Assign of Str? */
1325     if ( !nCount && (!pNewSubStr || !pNewSubStr->length) )
1326     {
1327         IMPL_RTL_STRINGNAME( assign )( ppThis, pStr );
1328         return;
1329     }
1330 
1331     {
1332     IMPL_RTL_STRINGDATA*    pOrg = *ppThis;
1333     IMPL_RTL_STRCODE*       pBuffer;
1334     sal_Int32               nNewLen;
1335 
1336     /* Calculate length of the new string */
1337     nNewLen = pStr->length-nCount;
1338     if ( pNewSubStr )
1339         nNewLen += pNewSubStr->length;
1340 
1341     /* Alloc New Buffer */
1342     *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nNewLen );
1343     OSL_ASSERT(*ppThis != NULL);
1344     pBuffer = (*ppThis)->buffer;
1345     if ( nIndex )
1346     {
1347         rtl_str_ImplCopy( pBuffer, pStr->buffer, nIndex );
1348         pBuffer += nIndex;
1349     }
1350     if ( pNewSubStr && pNewSubStr->length )
1351     {
1352         rtl_str_ImplCopy( pBuffer, pNewSubStr->buffer, pNewSubStr->length );
1353         pBuffer += pNewSubStr->length;
1354     }
1355     rtl_str_ImplCopy( pBuffer, pStr->buffer+nIndex+nCount, pStr->length-nIndex-nCount );
1356 
1357     /* must be done at least, if pStr or pNewSubStr == *ppThis */
1358     if ( pOrg )
1359         IMPL_RTL_STRINGNAME( release )( pOrg );
1360     }
1361 }
1362 
1363 /* ----------------------------------------------------------------------- */
1364 
newReplace(IMPL_RTL_STRINGDATA ** ppThis,IMPL_RTL_STRINGDATA * pStr,IMPL_RTL_STRCODE cOld,IMPL_RTL_STRCODE cNew)1365 void SAL_CALL IMPL_RTL_STRINGNAME( newReplace )( IMPL_RTL_STRINGDATA** ppThis,
1366                                                  IMPL_RTL_STRINGDATA* pStr,
1367                                                  IMPL_RTL_STRCODE cOld,
1368                                                  IMPL_RTL_STRCODE cNew )
1369 {
1370     IMPL_RTL_STRINGDATA*    pOrg        = *ppThis;
1371     int                     bChanged    = 0;
1372     sal_Int32               nLen        = pStr->length;
1373     const IMPL_RTL_STRCODE* pCharStr    = pStr->buffer;
1374 
1375     while ( nLen > 0 )
1376     {
1377         if ( *pCharStr == cOld )
1378         {
1379             /* Copy String */
1380             IMPL_RTL_STRCODE* pNewCharStr = IMPL_RTL_STRINGNAME( ImplNewCopy )( ppThis, pStr, pCharStr-pStr->buffer );
1381 
1382             /* replace/copy rest of the string */
1383             if ( pNewCharStr )
1384             {
1385                 *pNewCharStr = cNew;
1386                 pNewCharStr++;
1387                 pCharStr++;
1388                 nLen--;
1389 
1390                 while ( nLen > 0 )
1391                 {
1392                     if ( *pCharStr == cOld )
1393                         *pNewCharStr = cNew;
1394                     else
1395                         *pNewCharStr = *pCharStr;
1396 
1397                     pNewCharStr++;
1398                     pCharStr++;
1399                     nLen--;
1400                 }
1401             }
1402 
1403             bChanged = 1;
1404             break;
1405         }
1406 
1407         pCharStr++;
1408         nLen--;
1409     }
1410 
1411     if ( !bChanged )
1412     {
1413         *ppThis = pStr;
1414         IMPL_RTL_AQUIRE( pStr );
1415     }
1416 
1417     /* must be done at least, if pStr == *ppThis */
1418     if ( pOrg )
1419         IMPL_RTL_STRINGNAME( release )( pOrg );
1420 }
1421 
1422 /* ----------------------------------------------------------------------- */
1423 
newToAsciiLowerCase(IMPL_RTL_STRINGDATA ** ppThis,IMPL_RTL_STRINGDATA * pStr)1424 void SAL_CALL IMPL_RTL_STRINGNAME( newToAsciiLowerCase )( IMPL_RTL_STRINGDATA** ppThis,
1425                                                           IMPL_RTL_STRINGDATA* pStr )
1426 {
1427     IMPL_RTL_STRINGDATA*    pOrg        = *ppThis;
1428     int                     bChanged    = 0;
1429     sal_Int32               nLen        = pStr->length;
1430     const IMPL_RTL_STRCODE* pCharStr    = pStr->buffer;
1431 
1432     while ( nLen > 0 )
1433     {
1434         /* Between A-Z (65-90), than to lowercase (+32) */
1435         if ( (*pCharStr >= 65) && (*pCharStr <= 90) )
1436         {
1437             /* Copy String */
1438             IMPL_RTL_STRCODE* pNewCharStr = IMPL_RTL_STRINGNAME( ImplNewCopy )( ppThis, pStr, pCharStr-pStr->buffer );
1439 
1440             /* replace/copy rest of the string */
1441             if ( pNewCharStr )
1442             {
1443                 /* to lowercase (+32) */
1444                 *pNewCharStr = *pCharStr+32;
1445                 pNewCharStr++;
1446                 pCharStr++;
1447                 nLen--;
1448 
1449                 while ( nLen > 0 )
1450                 {
1451                     /* Between A-Z (65-90), than to lowercase (+32) */
1452                     if ( (*pCharStr >= 65) && (*pCharStr <= 90) )
1453                         *pNewCharStr = *pCharStr+32;
1454                     else
1455                         *pNewCharStr = *pCharStr;
1456 
1457                     pNewCharStr++;
1458                     pCharStr++;
1459                     nLen--;
1460                 }
1461             }
1462 
1463             bChanged = 1;
1464             break;
1465         }
1466 
1467         pCharStr++;
1468         nLen--;
1469     }
1470 
1471     if ( !bChanged )
1472     {
1473         *ppThis = pStr;
1474         IMPL_RTL_AQUIRE( pStr );
1475     }
1476 
1477     /* must be done at least, if pStr == *ppThis */
1478     if ( pOrg )
1479         IMPL_RTL_STRINGNAME( release )( pOrg );
1480 }
1481 
1482 /* ----------------------------------------------------------------------- */
1483 
newToAsciiUpperCase(IMPL_RTL_STRINGDATA ** ppThis,IMPL_RTL_STRINGDATA * pStr)1484 void SAL_CALL IMPL_RTL_STRINGNAME( newToAsciiUpperCase )( IMPL_RTL_STRINGDATA** ppThis,
1485                                                           IMPL_RTL_STRINGDATA* pStr )
1486 {
1487     IMPL_RTL_STRINGDATA*    pOrg        = *ppThis;
1488     int                     bChanged    = 0;
1489     sal_Int32               nLen        = pStr->length;
1490     const IMPL_RTL_STRCODE* pCharStr    = pStr->buffer;
1491 
1492     while ( nLen > 0 )
1493     {
1494         /* Between a-z (97-122), than to uppercase (-32) */
1495         if ( (*pCharStr >= 97) && (*pCharStr <= 122) )
1496         {
1497             /* Copy String */
1498             IMPL_RTL_STRCODE* pNewCharStr = IMPL_RTL_STRINGNAME( ImplNewCopy )( ppThis, pStr, pCharStr-pStr->buffer );
1499 
1500             /* replace/copy rest of the string */
1501             if ( pNewCharStr )
1502             {
1503                 /* to uppercase (-32) */
1504                 *pNewCharStr = *pCharStr-32;
1505                 pNewCharStr++;
1506                 pCharStr++;
1507                 nLen--;
1508 
1509                 while ( nLen > 0 )
1510                 {
1511                     /* Between a-z (97-122), than to uppercase (-32) */
1512                     if ( (*pCharStr >= 97) && (*pCharStr <= 122) )
1513                         *pNewCharStr = *pCharStr-32;
1514                     else
1515                         *pNewCharStr = *pCharStr;
1516 
1517                     pNewCharStr++;
1518                     pCharStr++;
1519                     nLen--;
1520                 }
1521             }
1522 
1523             bChanged = 1;
1524             break;
1525         }
1526 
1527         pCharStr++;
1528         nLen--;
1529     }
1530 
1531     if ( !bChanged )
1532     {
1533         *ppThis = pStr;
1534         IMPL_RTL_AQUIRE( pStr );
1535     }
1536 
1537     /* must be done at least, if pStr == *ppThis */
1538     if ( pOrg )
1539         IMPL_RTL_STRINGNAME( release )( pOrg );
1540 }
1541 
1542 /* ----------------------------------------------------------------------- */
1543 
newTrim(IMPL_RTL_STRINGDATA ** ppThis,IMPL_RTL_STRINGDATA * pStr)1544 void SAL_CALL IMPL_RTL_STRINGNAME( newTrim )( IMPL_RTL_STRINGDATA** ppThis,
1545                                               IMPL_RTL_STRINGDATA* pStr )
1546 {
1547     IMPL_RTL_STRINGDATA*    pOrg        = *ppThis;
1548     const IMPL_RTL_STRCODE* pCharStr    = pStr->buffer;
1549     sal_Int32               nPreSpaces  = 0;
1550     sal_Int32               nPostSpaces = 0;
1551     sal_Int32               nLen        = pStr->length;
1552     sal_Int32               nIndex      = nLen-1;
1553 
1554     while ( (nPreSpaces < nLen) && rtl_ImplIsWhitespace( IMPL_RTL_USTRCODE(*(pCharStr+nPreSpaces)) ) )
1555         nPreSpaces++;
1556 
1557     while ( (nIndex > nPreSpaces) && rtl_ImplIsWhitespace( IMPL_RTL_USTRCODE(*(pCharStr+nIndex)) ) )
1558     {
1559         nPostSpaces++;
1560         nIndex--;
1561     }
1562 
1563     if ( !nPreSpaces && !nPostSpaces )
1564     {
1565         *ppThis = pStr;
1566         IMPL_RTL_AQUIRE( pStr );
1567     }
1568     else
1569     {
1570         nLen -= nPostSpaces+nPreSpaces;
1571         *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
1572         OSL_ASSERT(*ppThis != NULL);
1573         if ( *ppThis )
1574             rtl_str_ImplCopy( (*ppThis)->buffer, pStr->buffer+nPreSpaces, nLen );
1575     }
1576 
1577     /* must be done at least, if pStr == *ppThis */
1578     if ( pOrg )
1579         IMPL_RTL_STRINGNAME( release )( pOrg );
1580 }
1581 
1582 /* ----------------------------------------------------------------------- */
1583 
getToken(IMPL_RTL_STRINGDATA ** ppThis,IMPL_RTL_STRINGDATA * pStr,sal_Int32 nToken,IMPL_RTL_STRCODE cTok,sal_Int32 nIndex)1584 sal_Int32 SAL_CALL IMPL_RTL_STRINGNAME( getToken )( IMPL_RTL_STRINGDATA** ppThis,
1585                                                     IMPL_RTL_STRINGDATA* pStr,
1586                                                     sal_Int32 nToken,
1587                                                     IMPL_RTL_STRCODE cTok,
1588                                                     sal_Int32 nIndex )
1589 {
1590     const IMPL_RTL_STRCODE* pCharStr        = pStr->buffer;
1591     const IMPL_RTL_STRCODE* pCharStrStart;
1592     const IMPL_RTL_STRCODE* pOrgCharStr;
1593     sal_Int32               nLen            = pStr->length-nIndex;
1594     sal_Int32               nTokCount       = 0;
1595 
1596     // Set ppThis to an empty string and return -1 if either nToken or nIndex is
1597     // negative:
1598     if (nIndex < 0) {
1599         nToken = -1;
1600     }
1601 
1602     pCharStr += nIndex;
1603     pOrgCharStr = pCharStr;
1604     pCharStrStart = pCharStr;
1605     while ( nLen > 0 )
1606     {
1607         if ( *pCharStr == cTok )
1608         {
1609             nTokCount++;
1610 
1611             if ( nTokCount == nToken )
1612                 pCharStrStart = pCharStr+1;
1613             else
1614             {
1615                 if ( nTokCount > nToken )
1616                     break;
1617             }
1618         }
1619 
1620         pCharStr++;
1621         nLen--;
1622     }
1623 
1624     if ( (nToken < 0) || (nTokCount < nToken) || (pCharStr == pCharStrStart) )
1625     {
1626         IMPL_RTL_STRINGNAME( new )( ppThis );
1627         if( (nToken < 0) || (nTokCount < nToken ) )
1628             return -1;
1629         else if( nLen > 0 )
1630             return nIndex+(pCharStr-pOrgCharStr)+1;
1631         else return -1;
1632     }
1633     else
1634     {
1635         IMPL_RTL_STRINGNAME( newFromStr_WithLength )( ppThis, pCharStrStart, pCharStr-pCharStrStart );
1636         if ( nLen )
1637             return nIndex+(pCharStr-pOrgCharStr)+1;
1638         else
1639             return -1;
1640     }
1641 }
1642