xref: /AOO41X/main/tools/source/string/strimp.cxx (revision 4c90b64447d8b4dd5483d1f81d91722297945f4a)
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 // no include "precompiled_tools.hxx" because this is included in other cxx files.
25 
26 // =======================================================================
27 
ImplStringCompare(const STRCODE * pStr1,const STRCODE * pStr2)28 static sal_Int32 ImplStringCompare( const STRCODE* pStr1, const STRCODE* pStr2 )
29 {
30     sal_Int32 nRet;
31     while ( ((nRet = ((sal_Int32)((STRCODEU)*pStr1))-((sal_Int32)((STRCODEU)*pStr2))) == 0) &&
32             *pStr2 )
33     {
34         ++pStr1,
35         ++pStr2;
36     }
37 
38     return nRet;
39 }
40 
41 // -----------------------------------------------------------------------
42 
ImplStringCompare(const STRCODE * pStr1,const STRCODE * pStr2,xub_StrLen nCount)43 static sal_Int32 ImplStringCompare( const STRCODE* pStr1, const STRCODE* pStr2,
44                                     xub_StrLen nCount )
45 {
46     sal_Int32 nRet = 0;
47     while ( nCount &&
48             ((nRet = ((sal_Int32)((STRCODEU)*pStr1))-((sal_Int32)((STRCODEU)*pStr2))) == 0) &&
49             *pStr2 )
50     {
51         ++pStr1,
52         ++pStr2,
53         --nCount;
54     }
55 
56     return nRet;
57 }
58 
59 // -----------------------------------------------------------------------
60 
ImplStringCompareWithoutZero(const STRCODE * pStr1,const STRCODE * pStr2,sal_Int32 nCount)61 static sal_Int32 ImplStringCompareWithoutZero( const STRCODE* pStr1, const STRCODE* pStr2,
62                                                sal_Int32 nCount )
63 {
64     sal_Int32 nRet = 0;
65     while ( nCount &&
66             ((nRet = ((sal_Int32)((STRCODEU)*pStr1))-((sal_Int32)((STRCODEU)*pStr2))) == 0) )
67     {
68         ++pStr1,
69         ++pStr2,
70         --nCount;
71     }
72 
73     return nRet;
74 }
75 
76 // -----------------------------------------------------------------------
77 
ImplStringICompare(const STRCODE * pStr1,const STRCODE * pStr2)78 static sal_Int32 ImplStringICompare( const STRCODE* pStr1, const STRCODE* pStr2 )
79 {
80     sal_Int32   nRet;
81     STRCODE     c1;
82     STRCODE     c2;
83     do
84     {
85         // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln
86         c1 = *pStr1;
87         c2 = *pStr2;
88         if ( (c1 >= 65) && (c1 <= 90) )
89             c1 += 32;
90         if ( (c2 >= 65) && (c2 <= 90) )
91             c2 += 32;
92         nRet = ((sal_Int32)((STRCODEU)c1))-((sal_Int32)((STRCODEU)c2));
93         if ( nRet != 0 )
94             break;
95 
96         ++pStr1,
97         ++pStr2;
98     }
99     while ( c2 );
100 
101     return nRet;
102 }
103 
104 // -----------------------------------------------------------------------
105 
ImplStringICompare(const STRCODE * pStr1,const STRCODE * pStr2,xub_StrLen nCount)106 static sal_Int32 ImplStringICompare( const STRCODE* pStr1, const STRCODE* pStr2,
107                                      xub_StrLen nCount )
108 {
109     sal_Int32   nRet = 0;
110     STRCODE     c1;
111     STRCODE     c2;
112     do
113     {
114         if ( !nCount )
115             break;
116 
117         // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln
118         c1 = *pStr1;
119         c2 = *pStr2;
120         if ( (c1 >= 65) && (c1 <= 90) )
121             c1 += 32;
122         if ( (c2 >= 65) && (c2 <= 90) )
123             c2 += 32;
124         nRet = ((sal_Int32)((STRCODEU)c1))-((sal_Int32)((STRCODEU)c2));
125         if ( nRet != 0 )
126             break;
127 
128         ++pStr1,
129         ++pStr2,
130         --nCount;
131     }
132     while ( c2 );
133 
134     return nRet;
135 }
136 
137 // -----------------------------------------------------------------------
138 
ImplStringICompareWithoutZero(const STRCODE * pStr1,const STRCODE * pStr2,sal_Int32 nCount)139 static sal_Int32 ImplStringICompareWithoutZero( const STRCODE* pStr1, const STRCODE* pStr2,
140                                                 sal_Int32 nCount )
141 {
142     sal_Int32   nRet = 0;
143     STRCODE     c1;
144     STRCODE     c2;
145     do
146     {
147         if ( !nCount )
148             break;
149 
150         // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln
151         c1 = *pStr1;
152         c2 = *pStr2;
153         if ( (c1 >= 65) && (c1 <= 90) )
154             c1 += 32;
155         if ( (c2 >= 65) && (c2 <= 90) )
156             c2 += 32;
157         nRet = ((sal_Int32)((STRCODEU)c1))-((sal_Int32)((STRCODEU)c2));
158 
159         ++pStr1,
160         ++pStr2,
161         --nCount;
162     }
163     while ( nRet == 0 );
164 
165     return nRet;
166 }
167 
168 // =======================================================================
169 
170 #ifdef DBG_UTIL
DBGCHECKSTRING(const void * pString)171 const char* DBGCHECKSTRING( const void* pString )
172 {
173     STRING* p = (STRING*)pString;
174 
175     if ( p->GetBuffer()[p->Len()] != 0 )
176         return "String damaged: aStr[nLen] != 0";
177 
178     return NULL;
179 }
180 #endif
181 
182 // =======================================================================
183 
ImplAllocData(sal_Int32 nLen)184 static STRINGDATA* ImplAllocData( sal_Int32 nLen )
185 {
186     // Dann kopiere die Daten
187     STRINGDATA* pData   = (STRINGDATA*)rtl_allocateMemory( sizeof(STRINGDATA)+(nLen*sizeof( STRCODE )) );
188     pData->mnRefCount   = 1;
189     pData->mnLen        = nLen;
190     pData->maStr[nLen]  = 0;
191     return pData;
192 }
193 
194 // -----------------------------------------------------------------------
195 
_ImplCopyData(STRINGDATA * pData)196 static STRINGDATA* _ImplCopyData( STRINGDATA* pData )
197 {
198     unsigned int    nSize       = sizeof(STRINGDATA)+(pData->mnLen*sizeof( STRCODE ));
199     STRINGDATA*     pNewData    = (STRINGDATA*)rtl_allocateMemory( nSize );
200     memcpy( pNewData, pData, nSize );
201     pNewData->mnRefCount = 1;
202     STRING_RELEASE((STRING_TYPE *)pData);
203     return pNewData;
204 }
205 
206 // -----------------------------------------------------------------------
207 
ImplCopyData()208 inline void STRING::ImplCopyData()
209 {
210     DBG_ASSERT( (mpData->mnRefCount != 0), "String::ImplCopyData() - RefCount == 0" );
211 
212     // ist es ein referenzierter String, dann die Daten abkoppeln
213     if ( mpData->mnRefCount != 1 )
214         mpData = _ImplCopyData( mpData );
215 }
216 
217 // -----------------------------------------------------------------------
218 
ImplCopyStringData(STRCODE * pStr)219 inline STRCODE* STRING::ImplCopyStringData( STRCODE* pStr )
220 {
221     // Ist der Referenzzaehler groesser 0
222     if ( mpData->mnRefCount != 1 ) {
223         DBG_ASSERT( (pStr >= mpData->maStr) &&
224                     ((pStr-mpData->maStr) < mpData->mnLen),
225                     "ImplCopyStringData - pStr from other String-Instanz" );
226         unsigned int nIndex = (unsigned int)(pStr-mpData->maStr);
227         mpData = _ImplCopyData( mpData );
228         pStr = mpData->maStr + nIndex;
229     }
230     return pStr;
231 }
232 
233 // -----------------------------------------------------------------------
234 
ImplGetCopyLen(sal_Int32 nStrLen,sal_Int32 nCopyLen)235 inline sal_Int32 ImplGetCopyLen( sal_Int32 nStrLen, sal_Int32 nCopyLen )
236 {
237     OSL_ASSERT(nStrLen <= STRING_MAXLEN && nCopyLen <= STRING_MAXLEN);
238     if ( nCopyLen > STRING_MAXLEN-nStrLen )
239         nCopyLen = STRING_MAXLEN-nStrLen;
240     return nCopyLen;
241 }
242 
243 // =======================================================================
244 
STRING()245 STRING::STRING()
246     : mpData(NULL)
247 {
248     DBG_CTOR( STRING, DBGCHECKSTRING );
249 
250     STRING_NEW((STRING_TYPE **)&mpData);
251 }
252 
253 // -----------------------------------------------------------------------
254 
STRING(const STRING & rStr)255 STRING::STRING( const STRING& rStr )
256 {
257     DBG_CTOR( STRING, DBGCHECKSTRING );
258     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
259 
260     // Pointer auf die Daten des uebergebenen Strings setzen und
261     // Referenzzaehler erhoehen
262     STRING_ACQUIRE((STRING_TYPE *)rStr.mpData);
263     mpData = rStr.mpData;
264 }
265 
266 // -----------------------------------------------------------------------
267 
STRING(const STRING & rStr,xub_StrLen nPos,xub_StrLen nLen)268 STRING::STRING( const STRING& rStr, xub_StrLen nPos, xub_StrLen nLen )
269 : mpData( NULL )
270 {
271     DBG_CTOR( STRING, DBGCHECKSTRING );
272     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
273 
274     // Stringlaenge ermitteln
275     if ( nPos > rStr.mpData->mnLen )
276         nLen = 0;
277     else
278     {
279         // Laenge korrigieren, wenn noetig
280         sal_Int32 nMaxLen = rStr.mpData->mnLen-nPos;
281         if ( nLen > nMaxLen )
282             nLen = static_cast< xub_StrLen >(nMaxLen);
283     }
284 
285     // Ist es kein leerer String
286     if ( nLen )
287     {
288         // Reicht ein einfaches erhoehen des Referenzcounters
289         if ( (nPos == 0) && (nLen == rStr.mpData->mnLen) )
290         {
291             STRING_ACQUIRE((STRING_TYPE *)rStr.mpData);
292             mpData = rStr.mpData;
293         }
294         else
295         {
296             // Verwaltungsdaten anlegen und String kopieren
297             mpData = ImplAllocData( nLen );
298             memcpy( mpData->maStr, rStr.mpData->maStr+nPos, nLen*sizeof( STRCODE ) );
299         }
300     }
301     else
302     {
303         STRING_NEW((STRING_TYPE **)&mpData);
304     }
305 }
306 
307 // -----------------------------------------------------------------------
308 
STRING(const STRCODE * pCharStr)309 STRING::STRING( const STRCODE* pCharStr )
310     : mpData(NULL)
311 {
312     DBG_CTOR( STRING, DBGCHECKSTRING );
313 
314     // Stringlaenge ermitteln
315     // Bei diesem Ctor darf NULL uebergeben werden
316     xub_StrLen nLen;
317     if ( pCharStr )
318         nLen = ImplStringLen( pCharStr );
319     else
320         nLen = 0;
321 
322     // Ist es kein leerer String
323     if ( nLen )
324     {
325         // Verwaltungsdaten anlegen und String kopieren
326         mpData = ImplAllocData( nLen );
327         memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
328     }
329     else
330     {
331         STRING_NEW((STRING_TYPE **)&mpData);
332     }
333 }
334 
335 // -----------------------------------------------------------------------
336 
STRING(const STRCODE * pCharStr,xub_StrLen nLen)337 STRING::STRING( const STRCODE* pCharStr, xub_StrLen nLen )
338 : mpData(NULL)
339 {
340     DBG_CTOR( STRING, DBGCHECKSTRING );
341     DBG_ASSERT( pCharStr, "String::String() - pCharStr is NULL" );
342 
343     if ( nLen == STRING_LEN )
344         nLen = ImplStringLen( pCharStr );
345 
346 #ifdef DBG_UTIL
347     if ( DbgIsAssert() )
348     {
349         for ( xub_StrLen i = 0; i < nLen; i++ )
350         {
351             if ( !pCharStr[i] )
352             {
353                 DBG_ERROR( "String::String() : nLen is wrong" );
354             }
355         }
356     }
357 #endif
358 
359     // Ist es kein leerer String
360     if ( nLen )
361     {
362         // Verwaltungsdaten anlegen und String kopieren
363         mpData = ImplAllocData( nLen );
364         memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
365     }
366     else
367     {
368         STRING_NEW((STRING_TYPE **)&mpData);
369     }
370 }
371 
372 // -----------------------------------------------------------------------
373 
STRING(STRCODE c)374 STRING::STRING( STRCODE c )
375 {
376     DBG_CTOR( STRING, DBGCHECKSTRING );
377     DBG_ASSERT( c, "String::String() - c is 0" );
378 
379     // Verwaltungsdaten anlegen und initialisieren
380     mpData = ImplAllocData( 1 );
381     mpData->maStr[0] = c;
382 }
383 
384 // -----------------------------------------------------------------------
385 
~STRING()386 STRING::~STRING()
387 {
388     DBG_DTOR( STRING, DBGCHECKSTRING );
389 
390     // Daten loeschen
391     STRING_RELEASE((STRING_TYPE *)mpData);
392 }
393 
394 // -----------------------------------------------------------------------
395 
Assign(const STRING & rStr)396 STRING& STRING::Assign( const STRING& rStr )
397 {
398     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
399     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
400 
401     STRING_ACQUIRE((STRING_TYPE *)rStr.mpData);
402     STRING_RELEASE((STRING_TYPE *)mpData);
403     mpData = rStr.mpData;
404     return *this;
405 }
406 
407 // -----------------------------------------------------------------------
408 
Assign(const STRCODE * pCharStr)409 STRING& STRING::Assign( const STRCODE* pCharStr )
410 {
411     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
412     DBG_ASSERT( pCharStr, "String::Assign() - pCharStr is NULL" );
413 
414     // Stringlaenge ermitteln
415     xub_StrLen nLen = ImplStringLen( pCharStr );
416 
417     if ( !nLen )
418     {
419         STRING_NEW((STRING_TYPE **)&mpData);
420     }
421     else
422     {
423         // Wenn String genauso lang ist, wie der String, dann direkt kopieren
424         if ( (nLen == mpData->mnLen) && (mpData->mnRefCount == 1) )
425             memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
426         else
427         {
428             // Alte Daten loeschen
429             STRING_RELEASE((STRING_TYPE *)mpData);
430 
431             // Daten initialisieren und String kopieren
432             mpData = ImplAllocData( nLen );
433             memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
434         }
435     }
436 
437     return *this;
438 }
439 
440 // -----------------------------------------------------------------------
441 
Assign(const STRCODE * pCharStr,xub_StrLen nLen)442 STRING& STRING::Assign( const STRCODE* pCharStr, xub_StrLen nLen )
443 {
444     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
445     DBG_ASSERT( pCharStr, "String::Assign() - pCharStr is NULL" );
446 
447     if ( nLen == STRING_LEN )
448         nLen = ImplStringLen( pCharStr );
449 
450 #ifdef DBG_UTIL
451     if ( DbgIsAssert() )
452     {
453         for ( xub_StrLen i = 0; i < nLen; i++ )
454         {
455             if ( !pCharStr[i] )
456             {
457                 DBG_ERROR( "String::Assign() : nLen is wrong" );
458             }
459         }
460     }
461 #endif
462 
463     if ( !nLen )
464     {
465         STRING_NEW((STRING_TYPE **)&mpData);
466     }
467     else
468     {
469         // Wenn String genauso lang ist, wie der String, dann direkt kopieren
470         if ( (nLen == mpData->mnLen) && (mpData->mnRefCount == 1) )
471             memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
472         else
473         {
474             // Alte Daten loeschen
475             STRING_RELEASE((STRING_TYPE *)mpData);
476 
477             // Daten initialisieren und String kopieren
478             mpData = ImplAllocData( nLen );
479             memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
480         }
481     }
482 
483     return *this;
484 }
485 
486 // -----------------------------------------------------------------------
487 
Assign(STRCODE c)488 STRING& STRING::Assign( STRCODE c )
489 {
490     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
491     DBG_ASSERT( c, "String::Assign() - c is 0" );
492 
493     // Verwaltungsdaten anlegen und initialisieren
494     STRING_RELEASE((STRING_TYPE *)mpData);
495     mpData = ImplAllocData( 1 );
496     mpData->maStr[0] = c;
497     return *this;
498 }
499 
500 // -----------------------------------------------------------------------
501 
Append(const STRING & rStr)502 STRING& STRING::Append( const STRING& rStr )
503 {
504     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
505     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
506 
507     // Wenn String leer, dann reicht eine Zuweisung
508     sal_Int32 nLen = mpData->mnLen;
509     if ( !nLen )
510     {
511         STRING_ACQUIRE((STRING_TYPE *)rStr.mpData);
512         STRING_RELEASE((STRING_TYPE *)mpData);
513         mpData = rStr.mpData;
514     }
515     else
516     {
517         // Ueberlauf abfangen
518         sal_Int32 nCopyLen = ImplGetCopyLen( nLen, rStr.mpData->mnLen );
519 
520         // Ist der uebergebene String kein Leerstring
521         if ( nCopyLen )
522         {
523             // Neue Datenstruktur und neuen String erzeugen
524             STRINGDATA* pNewData = ImplAllocData( nLen+nCopyLen );
525 
526             // String kopieren
527             memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
528             memcpy( pNewData->maStr+nLen, rStr.mpData->maStr, nCopyLen*sizeof( STRCODE ) );
529 
530             // Alte Daten loeschen und Neue zuweisen
531             STRING_RELEASE((STRING_TYPE *)mpData);
532             mpData = pNewData;
533         }
534     }
535 
536     return *this;
537 }
538 
539 // -----------------------------------------------------------------------
540 
Append(const STRCODE * pCharStr)541 STRING& STRING::Append( const STRCODE* pCharStr )
542 {
543     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
544     DBG_ASSERT( pCharStr, "String::Append() - pCharStr is NULL" );
545 
546     // Stringlaenge ermitteln
547     sal_Int32 nLen = mpData->mnLen;
548     sal_Int32 nCopyLen = ImplStringLen( pCharStr );
549 
550     // Ueberlauf abfangen
551     nCopyLen = ImplGetCopyLen( nLen, nCopyLen );
552 
553     // Ist es kein leerer String
554     if ( nCopyLen )
555     {
556         // Neue Datenstruktur und neuen String erzeugen
557         STRINGDATA* pNewData = ImplAllocData( nLen+nCopyLen );
558 
559         // String kopieren
560         memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
561         memcpy( pNewData->maStr+nLen, pCharStr, nCopyLen*sizeof( STRCODE ) );
562 
563         // Alte Daten loeschen und Neue zuweisen
564         STRING_RELEASE((STRING_TYPE *)mpData);
565         mpData = pNewData;
566     }
567 
568     return *this;
569 }
570 
571 // -----------------------------------------------------------------------
572 
Append(const STRCODE * pCharStr,xub_StrLen nCharLen)573 STRING& STRING::Append( const STRCODE* pCharStr, xub_StrLen nCharLen )
574 {
575     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
576     DBG_ASSERT( pCharStr, "String::Append() - pCharStr is NULL" );
577 
578     if ( nCharLen == STRING_LEN )
579         nCharLen = ImplStringLen( pCharStr );
580 
581 #ifdef DBG_UTIL
582     if ( DbgIsAssert() )
583     {
584         for ( xub_StrLen i = 0; i < nCharLen; i++ )
585         {
586             if ( !pCharStr[i] )
587             {
588                 DBG_ERROR( "String::Append() : nLen is wrong" );
589             }
590         }
591     }
592 #endif
593 
594     // Ueberlauf abfangen
595     sal_Int32 nLen = mpData->mnLen;
596     sal_Int32 nCopyLen = ImplGetCopyLen( nLen, nCharLen );
597 
598     // Ist es kein leerer String
599     if ( nCopyLen )
600     {
601         // Neue Datenstruktur und neuen String erzeugen
602         STRINGDATA* pNewData = ImplAllocData( nLen+nCopyLen );
603 
604         // String kopieren
605         memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
606         memcpy( pNewData->maStr+nLen, pCharStr, nCopyLen*sizeof( STRCODE ) );
607 
608         // Alte Daten loeschen und Neue zuweisen
609         STRING_RELEASE((STRING_TYPE *)mpData);
610         mpData = pNewData;
611     }
612 
613     return *this;
614 }
615 
616 // -----------------------------------------------------------------------
617 
Append(STRCODE c)618 STRING& STRING::Append( STRCODE c )
619 {
620     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
621 
622     // kein 0-Character und maximale Stringlaenge nicht ueberschreiten
623     sal_Int32 nLen = mpData->mnLen;
624     if ( c && (nLen < STRING_MAXLEN) )
625     {
626         // Neue Datenstruktur und neuen String erzeugen
627         STRINGDATA* pNewData = ImplAllocData( nLen+1 );
628 
629         // String kopieren
630         memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
631         pNewData->maStr[nLen] = c;
632 
633         // Alte Daten loeschen und Neue zuweisen
634         STRING_RELEASE((STRING_TYPE *)mpData);
635         mpData = pNewData;
636     }
637 
638     return *this;
639 }
640 
641 // -----------------------------------------------------------------------
642 
SetChar(xub_StrLen nIndex,STRCODE c)643 void STRING::SetChar( xub_StrLen nIndex, STRCODE c )
644 {
645     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
646     DBG_ASSERT( nIndex < mpData->mnLen, "String::SetChar() - nIndex > String.Len()" );
647 
648     // Daten kopieren, wenn noetig und Character zuweisen
649     ImplCopyData();
650     mpData->maStr[nIndex] = c;
651 }
652 
653 // -----------------------------------------------------------------------
654 
Insert(const STRING & rStr,xub_StrLen nIndex)655 STRING& STRING::Insert( const STRING& rStr, xub_StrLen nIndex )
656 {
657     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
658     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
659 
660     // Ueberlauf abfangen
661     sal_Int32 nCopyLen = ImplGetCopyLen( mpData->mnLen, rStr.mpData->mnLen );
662 
663     // Ist der einzufuegende String ein Leerstring
664     if ( !nCopyLen )
665         return *this;
666 
667     // Index groesser als Laenge
668     if ( nIndex > mpData->mnLen )
669         nIndex = static_cast< xub_StrLen >(mpData->mnLen);
670 
671     // Neue Laenge ermitteln und neuen String anlegen
672     STRINGDATA* pNewData = ImplAllocData( mpData->mnLen+nCopyLen );
673 
674     // String kopieren
675     memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
676     memcpy( pNewData->maStr+nIndex, rStr.mpData->maStr, nCopyLen*sizeof( STRCODE ) );
677     memcpy( pNewData->maStr+nIndex+nCopyLen, mpData->maStr+nIndex,
678             (mpData->mnLen-nIndex)*sizeof( STRCODE ) );
679 
680     // Alte Daten loeschen und Neue zuweisen
681     STRING_RELEASE((STRING_TYPE *)mpData);
682     mpData = pNewData;
683 
684     return *this;
685 }
686 
687 // -----------------------------------------------------------------------
688 
Insert(const STRING & rStr,xub_StrLen nPos,xub_StrLen nLen,xub_StrLen nIndex)689 STRING& STRING::Insert( const STRING& rStr, xub_StrLen nPos, xub_StrLen nLen,
690                         xub_StrLen nIndex )
691 {
692     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
693     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
694 
695     // Stringlaenge ermitteln
696     if ( nPos > rStr.mpData->mnLen )
697         nLen = 0;
698     else
699     {
700         // Laenge korrigieren, wenn noetig
701         sal_Int32 nMaxLen = rStr.mpData->mnLen-nPos;
702         if ( nLen > nMaxLen )
703             nLen = static_cast< xub_StrLen >(nMaxLen);
704     }
705 
706     // Ueberlauf abfangen
707     sal_Int32 nCopyLen = ImplGetCopyLen( mpData->mnLen, nLen );
708 
709     // Ist der einzufuegende String ein Leerstring
710     if ( !nCopyLen )
711         return *this;
712 
713     // Index groesser als Laenge
714     if ( nIndex > mpData->mnLen )
715         nIndex = static_cast< xub_StrLen >(mpData->mnLen);
716 
717     // Neue Laenge ermitteln und neuen String anlegen
718     STRINGDATA* pNewData = ImplAllocData( mpData->mnLen+nCopyLen );
719 
720     // String kopieren
721     memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
722     memcpy( pNewData->maStr+nIndex, rStr.mpData->maStr+nPos, nCopyLen*sizeof( STRCODE ) );
723     memcpy( pNewData->maStr+nIndex+nCopyLen, mpData->maStr+nIndex,
724             (mpData->mnLen-nIndex)*sizeof( STRCODE ) );
725 
726     // Alte Daten loeschen und Neue zuweisen
727     STRING_RELEASE((STRING_TYPE *)mpData);
728     mpData = pNewData;
729 
730     return *this;
731 }
732 
733 // -----------------------------------------------------------------------
734 
Insert(const STRCODE * pCharStr,xub_StrLen nIndex)735 STRING& STRING::Insert( const STRCODE* pCharStr, xub_StrLen nIndex )
736 {
737     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
738     DBG_ASSERT( pCharStr, "String::Insert() - pCharStr is NULL" );
739 
740     // Stringlaenge ermitteln
741     sal_Int32 nCopyLen = ImplStringLen( pCharStr );
742 
743     // Ueberlauf abfangen
744     nCopyLen = ImplGetCopyLen( mpData->mnLen, nCopyLen );
745 
746     // Ist der einzufuegende String ein Leerstring
747     if ( !nCopyLen )
748         return *this;
749 
750     // Index groesser als Laenge
751     if ( nIndex > mpData->mnLen )
752         nIndex = static_cast< xub_StrLen >(mpData->mnLen);
753 
754     // Neue Laenge ermitteln und neuen String anlegen
755     STRINGDATA* pNewData = ImplAllocData( mpData->mnLen+nCopyLen );
756 
757     // String kopieren
758     memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
759     memcpy( pNewData->maStr+nIndex, pCharStr, nCopyLen*sizeof( STRCODE ) );
760     memcpy( pNewData->maStr+nIndex+nCopyLen, mpData->maStr+nIndex,
761             (mpData->mnLen-nIndex)*sizeof( STRCODE ) );
762 
763     // Alte Daten loeschen und Neue zuweisen
764     STRING_RELEASE((STRING_TYPE *)mpData);
765     mpData = pNewData;
766 
767     return *this;
768 }
769 
770 // -----------------------------------------------------------------------
771 
Insert(STRCODE c,xub_StrLen nIndex)772 STRING& STRING::Insert( STRCODE c, xub_StrLen nIndex )
773 {
774     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
775 
776     // Ist es kein 0-Character
777     if ( !c || (mpData->mnLen == STRING_MAXLEN) )
778         return *this;
779 
780     // Index groesser als Laenge
781     if ( nIndex > mpData->mnLen )
782         nIndex = static_cast< xub_StrLen >(mpData->mnLen);
783 
784     // Neue Laenge ermitteln und neuen String anlegen
785     STRINGDATA* pNewData = ImplAllocData( mpData->mnLen+1 );
786 
787     // String kopieren
788     memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
789     pNewData->maStr[nIndex] = c;
790     memcpy( pNewData->maStr+nIndex+1, mpData->maStr+nIndex,
791             (mpData->mnLen-nIndex)*sizeof( STRCODE ) );
792 
793     // Alte Daten loeschen und Neue zuweisen
794     STRING_RELEASE((STRING_TYPE *)mpData);
795     mpData = pNewData;
796 
797     return *this;
798 }
799 
800 // -----------------------------------------------------------------------
801 
Replace(xub_StrLen nIndex,xub_StrLen nCount,const STRING & rStr)802 STRING& STRING::Replace( xub_StrLen nIndex, xub_StrLen nCount, const STRING& rStr )
803 {
804     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
805     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
806 
807     // Wenn Index groessergleich Laenge ist, dann ist es ein Append
808     if ( nIndex >= mpData->mnLen )
809     {
810         Append( rStr );
811         return *this;
812     }
813 
814     // Ist es eine Zuweisung
815     if ( (nIndex == 0) && (nCount >= mpData->mnLen) )
816     {
817         Assign( rStr );
818         return *this;
819     }
820 
821     // Reicht ein Erase
822     sal_Int32 nStrLen = rStr.mpData->mnLen;
823     if ( !nStrLen )
824         return Erase( nIndex, nCount );
825 
826     // nCount darf nicht ueber das Stringende hinnausgehen
827     if ( nCount > mpData->mnLen - nIndex )
828         nCount = static_cast< xub_StrLen >(mpData->mnLen-nIndex);
829 
830     // Reicht ein Insert
831     if ( !nCount )
832         return Insert( rStr, nIndex );
833 
834     // Reicht eine zeichenweise Zuweisung
835     if ( nCount == nStrLen )
836     {
837         ImplCopyData();
838         memcpy( mpData->maStr+nIndex, rStr.mpData->maStr, nCount*sizeof( STRCODE ) );
839         return *this;
840     }
841 
842     // Ueberlauf abfangen
843     nStrLen = ImplGetCopyLen( mpData->mnLen-nCount, nStrLen );
844 
845     // Neue Daten anlegen
846     STRINGDATA* pNewData = ImplAllocData( mpData->mnLen-nCount+nStrLen );
847 
848     // String kopieren
849     memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
850     memcpy( pNewData->maStr+nIndex, rStr.mpData->maStr, nStrLen*sizeof( STRCODE ) );
851     memcpy( pNewData->maStr+nIndex+nStrLen, mpData->maStr+nIndex+nCount,
852             (mpData->mnLen-nIndex-nCount+1)*sizeof( STRCODE ) );
853 
854     // Alte Daten loeschen und Neue zuweisen
855     STRING_RELEASE((STRING_TYPE *)mpData);
856     mpData = pNewData;
857 
858     return *this;
859 }
860 
861 // -----------------------------------------------------------------------
862 
Erase(xub_StrLen nIndex,xub_StrLen nCount)863 STRING& STRING::Erase( xub_StrLen nIndex, xub_StrLen nCount )
864 {
865     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
866 
867     // Ist der Index ausserhalb des Strings oder ist nCount == 0
868     if ( (nIndex >= mpData->mnLen) || !nCount )
869         return *this;
870 
871     // nCount darf nicht ueber das Stringende hinnausgehen
872     if ( nCount > mpData->mnLen - nIndex )
873         nCount = static_cast< xub_StrLen >(mpData->mnLen-nIndex);
874 
875     // Ist das Ergebnis kein Leerstring
876     if ( mpData->mnLen - nCount )
877     {
878         // Neue Daten anlegen
879         STRINGDATA* pNewData = ImplAllocData( mpData->mnLen-nCount );
880 
881         // String kopieren
882         memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
883         memcpy( pNewData->maStr+nIndex, mpData->maStr+nIndex+nCount,
884                 (mpData->mnLen-nIndex-nCount+1)*sizeof( STRCODE ) );
885 
886         // Alte Daten loeschen und Neue zuweisen
887         STRING_RELEASE((STRING_TYPE *)mpData);
888         mpData = pNewData;
889     }
890     else
891     {
892         STRING_NEW((STRING_TYPE **)&mpData);
893     }
894 
895     return *this;
896 }
897 
898 // -----------------------------------------------------------------------
899 
Fill(xub_StrLen nCount,STRCODE cFillChar)900 STRING& STRING::Fill( xub_StrLen nCount, STRCODE cFillChar )
901 {
902     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
903 
904     if ( !nCount )
905         return *this;
906 
907     // Ist nCount groesser wie der jetzige String, dann verlaengern
908     if ( nCount > mpData->mnLen )
909     {
910         // dann neuen String mit der neuen Laenge anlegen
911         STRINGDATA* pNewData = ImplAllocData( nCount );
912         STRING_RELEASE((STRING_TYPE *)mpData);
913         mpData = pNewData;
914     }
915     else
916         ImplCopyData();
917 
918     STRCODE* pStr = mpData->maStr;
919     do
920     {
921         *pStr = cFillChar;
922         ++pStr,
923         --nCount;
924     }
925     while ( nCount );
926 
927     return *this;
928 }
929 
930 // -----------------------------------------------------------------------
931 
Expand(xub_StrLen nCount,STRCODE cExpandChar)932 STRING& STRING::Expand( xub_StrLen nCount, STRCODE cExpandChar )
933 {
934     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
935 
936     // Muss der String erweitert werden
937     sal_Int32 nLen = mpData->mnLen;
938     if ( nCount <= nLen )
939         return *this;
940 
941     // Neuen String anlegen
942     STRINGDATA* pNewData = ImplAllocData( nCount );
943 
944     // Alten String kopieren
945     memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
946 
947     // und initialisieren
948     STRCODE* pStr = pNewData->maStr;
949     pStr += nLen;
950     for (sal_Int32 i = nCount - nLen; i > 0; --i) {
951         *pStr++ = cExpandChar;
952     }
953 
954     // Alte Daten loeschen und Neue zuweisen
955     STRING_RELEASE((STRING_TYPE *)mpData);
956     mpData = pNewData;
957 
958     return *this;
959 }
960 
961 // -----------------------------------------------------------------------
962 
EraseLeadingChars(STRCODE c)963 STRING& STRING::EraseLeadingChars( STRCODE c )
964 {
965     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
966 
967     if ( mpData->maStr[0] != c )
968         return *this;
969 
970     xub_StrLen nStart = 0;
971     while ( mpData->maStr[nStart] == c )
972         ++nStart;
973 
974     return Erase( 0, nStart );
975 }
976 
977 // -----------------------------------------------------------------------
978 
EraseTrailingChars(STRCODE c)979 STRING& STRING::EraseTrailingChars( STRCODE c )
980 {
981     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
982 
983     sal_Int32 nEnd = mpData->mnLen;
984     while ( nEnd && (mpData->maStr[nEnd-1] == c) )
985         nEnd--;
986 
987     if ( nEnd != mpData->mnLen )
988         Erase( static_cast< xub_StrLen >(nEnd) );
989 
990     return *this;
991 }
992 
993 // -----------------------------------------------------------------------
994 
EraseLeadingAndTrailingChars(STRCODE c)995 STRING& STRING::EraseLeadingAndTrailingChars( STRCODE c )
996 {
997     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
998 
999     xub_StrLen nStart = 0;
1000     while ( mpData->maStr[nStart] == c )
1001         ++nStart;
1002     if ( nStart )
1003         Erase( 0, nStart );
1004 
1005     sal_Int32 nEnd = mpData->mnLen;
1006     while ( nEnd && (mpData->maStr[nEnd-1] == c) )
1007         nEnd--;
1008     if ( nEnd != mpData->mnLen )
1009         Erase( static_cast< xub_StrLen >(nEnd) );
1010 
1011     return *this;
1012 }
1013 
1014 // -----------------------------------------------------------------------
1015 
EraseAllChars(STRCODE c)1016 STRING& STRING::EraseAllChars( STRCODE c )
1017 {
1018     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1019 
1020     sal_Int32 nCount = 0;
1021     for (sal_Int32 i = 0; i < mpData->mnLen; ++i) {
1022         if ( mpData->maStr[i] == c )
1023             ++nCount;
1024     }
1025 
1026     if ( nCount )
1027     {
1028         if ( nCount == mpData->mnLen )
1029         {
1030             STRING_NEW((STRING_TYPE **)&mpData);
1031         }
1032         else
1033         {
1034             // Neuen String anlegen
1035             STRINGDATA* pNewData = ImplAllocData( mpData->mnLen-nCount );
1036 
1037             // Alten String kopieren und initialisieren
1038             nCount = 0;
1039             for( xub_StrLen j = 0; j < mpData->mnLen; ++j )
1040             {
1041                 if ( mpData->maStr[j] != c )
1042                 {
1043                     pNewData->maStr[nCount] = mpData->maStr[j];
1044                     ++nCount;
1045                 }
1046             }
1047 
1048             // Alte Daten loeschen und Neue zuweisen
1049             STRING_RELEASE((STRING_TYPE *)mpData);
1050             mpData = pNewData;
1051         }
1052     }
1053 
1054     return *this;
1055 }
1056 
1057 // -----------------------------------------------------------------------
1058 
Reverse()1059 STRING& STRING::Reverse()
1060 {
1061     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1062 
1063     if ( !mpData->mnLen )
1064         return *this;
1065 
1066     // Daten kopieren, wenn noetig
1067     ImplCopyData();
1068 
1069     // Reverse
1070     sal_Int32 nCount = mpData->mnLen / 2;
1071     for ( sal_Int32 i = 0; i < nCount; ++i )
1072     {
1073         STRCODE cTemp = mpData->maStr[i];
1074         mpData->maStr[i] = mpData->maStr[mpData->mnLen-i-1];
1075         mpData->maStr[mpData->mnLen-i-1] = cTemp;
1076     }
1077 
1078     return *this;
1079 }
1080 
1081 // -----------------------------------------------------------------------
1082 
ToLowerAscii()1083 STRING& STRING::ToLowerAscii()
1084 {
1085     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1086 
1087     sal_Int32 nIndex = 0;
1088     sal_Int32 nLen = mpData->mnLen;
1089     STRCODE*    pStr = mpData->maStr;
1090     while ( nIndex < nLen )
1091     {
1092         // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln
1093         if ( (*pStr >= 65) && (*pStr <= 90) )
1094         {
1095             // Daten kopieren, wenn noetig
1096             pStr = ImplCopyStringData( pStr );
1097             *pStr += 32;
1098         }
1099 
1100         ++pStr,
1101         ++nIndex;
1102     }
1103 
1104     return *this;
1105 }
1106 
1107 // -----------------------------------------------------------------------
1108 
ToUpperAscii()1109 STRING& STRING::ToUpperAscii()
1110 {
1111     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1112 
1113     sal_Int32 nIndex = 0;
1114     sal_Int32 nLen = mpData->mnLen;
1115     STRCODE*    pStr = mpData->maStr;
1116     while ( nIndex < nLen )
1117     {
1118         // Ist das Zeichen zwischen 'a' und 'z' dann umwandeln
1119         if ( (*pStr >= 97) && (*pStr <= 122) )
1120         {
1121             // Daten kopieren, wenn noetig
1122             pStr = ImplCopyStringData( pStr );
1123             *pStr -= 32;
1124         }
1125 
1126         ++pStr,
1127         ++nIndex;
1128     }
1129 
1130     return *this;
1131 }
1132 
1133 // -----------------------------------------------------------------------
1134 
ConvertLineEnd(LineEnd eLineEnd)1135 STRING& STRING::ConvertLineEnd( LineEnd eLineEnd )
1136 {
1137     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1138 
1139     // Zeilenumbrueche ermitteln und neue Laenge berechnen
1140     sal_Bool            bConvert    = sal_False;            // Muss konvertiert werden
1141     const STRCODE*  pStr        = mpData->maStr;    // damit es schneller geht
1142     xub_StrLen      nLineEndLen = (eLineEnd == LINEEND_CRLF) ? 2 : 1;
1143     xub_StrLen      nLen        = 0;                // Ziel-Laenge
1144     xub_StrLen      i           = 0;                // Source-Zaehler
1145 
1146     while ( i < mpData->mnLen )
1147     {
1148         // Bei \r oder \n gibt es neuen Zeilenumbruch
1149         if ( (pStr[i] == _CR) || (pStr[i] == _LF) )
1150         {
1151             if( nLen <= STRING_MAXLEN - nLineEndLen )
1152                 nLen = nLen + nLineEndLen;
1153             else
1154                 nLen = STRING_MAXLEN;
1155 
1156             // Wenn schon gesetzt, dann brauchen wir keine aufwendige Abfrage
1157             if ( !bConvert )
1158             {
1159                 // Muessen wir Konvertieren
1160                 if ( ((eLineEnd != LINEEND_LF) && (pStr[i] == _LF)) ||
1161                      ((eLineEnd == LINEEND_CRLF) && (pStr[i+1] != _LF)) ||
1162                      ((eLineEnd == LINEEND_LF) &&
1163                       ((pStr[i] == _CR) || (pStr[i+1] == _CR))) ||
1164                      ((eLineEnd == LINEEND_CR) &&
1165                       ((pStr[i] == _LF) || (pStr[i+1] == _LF))) )
1166                     bConvert = sal_True;
1167             }
1168 
1169             // \r\n oder \n\r, dann Zeichen ueberspringen
1170             if ( ((pStr[i+1] == _CR) || (pStr[i+1] == _LF)) &&
1171                  (pStr[i] != pStr[i+1]) )
1172                 ++i;
1173         }
1174         else
1175         {
1176             if( nLen < STRING_MAXLEN )
1177                 ++nLen;
1178         }
1179         ++i;
1180 
1181         // Wenn String zu lang, dann konvertieren wir nicht
1182         if ( nLen >= STRING_MAXLEN )
1183             return *this;
1184     }
1185 
1186     // Zeilenumbrueche konvertieren
1187     if ( bConvert )
1188     {
1189         // Neuen String anlegen
1190         STRINGDATA* pNewData = ImplAllocData( nLen );
1191         xub_StrLen  j = 0;
1192         i = 0;
1193         while ( i < mpData->mnLen )
1194         {
1195             // Bei \r oder \n gibt es neuen Zeilenumbruch
1196             if ( (pStr[i] == _CR) || (pStr[i] == _LF) )
1197             {
1198                 if ( eLineEnd == LINEEND_CRLF )
1199                 {
1200                     pNewData->maStr[j]   = _CR;
1201                     pNewData->maStr[j+1] = _LF;
1202                     j += 2;
1203                 }
1204                 else
1205                 {
1206                     if ( eLineEnd == LINEEND_CR )
1207                         pNewData->maStr[j] = _CR;
1208                     else
1209                         pNewData->maStr[j] = _LF;
1210                     ++j;
1211                 }
1212 
1213                 if ( ((pStr[i+1] == _CR) || (pStr[i+1] == _LF)) &&
1214                      (pStr[i] != pStr[i+1]) )
1215                     ++i;
1216             }
1217             else
1218             {
1219                 pNewData->maStr[j] = mpData->maStr[i];
1220                 ++j;
1221             }
1222 
1223             ++i;
1224         }
1225 
1226         // Alte Daten loeschen und Neue zuweisen
1227         STRING_RELEASE((STRING_TYPE *)mpData);
1228         mpData = pNewData;
1229     }
1230 
1231     return *this;
1232 }
1233 
1234 // -----------------------------------------------------------------------
1235 
CompareTo(const STRING & rStr,xub_StrLen nLen) const1236 StringCompare STRING::CompareTo( const STRING& rStr, xub_StrLen nLen ) const
1237 {
1238     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1239     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1240 
1241     // Auf Gleichheit der Pointer testen
1242     if ( mpData == rStr.mpData )
1243         return COMPARE_EQUAL;
1244 
1245     // Maximale Laenge ermitteln
1246     if ( mpData->mnLen < nLen )
1247         nLen = static_cast< xub_StrLen >(mpData->mnLen+1);
1248     if ( rStr.mpData->mnLen < nLen )
1249         nLen = static_cast< xub_StrLen >(rStr.mpData->mnLen+1);
1250 
1251     // String vergleichen
1252     sal_Int32 nCompare = ImplStringCompareWithoutZero( mpData->maStr, rStr.mpData->maStr, nLen );
1253 
1254     // Rueckgabewert anpassen
1255     if ( nCompare == 0 )
1256         return COMPARE_EQUAL;
1257     else if ( nCompare < 0 )
1258         return COMPARE_LESS;
1259     else
1260         return COMPARE_GREATER;
1261 }
1262 
1263 // -----------------------------------------------------------------------
1264 
CompareTo(const STRCODE * pCharStr,xub_StrLen nLen) const1265 StringCompare STRING::CompareTo( const STRCODE* pCharStr, xub_StrLen nLen ) const
1266 {
1267     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1268 
1269     // String vergleichen
1270     sal_Int32 nCompare = ImplStringCompare( mpData->maStr, pCharStr, nLen );
1271 
1272     // Rueckgabewert anpassen
1273     if ( nCompare == 0 )
1274         return COMPARE_EQUAL;
1275     else if ( nCompare < 0 )
1276         return COMPARE_LESS;
1277     else
1278         return COMPARE_GREATER;
1279 }
1280 
1281 // -----------------------------------------------------------------------
1282 
CompareIgnoreCaseToAscii(const STRING & rStr,xub_StrLen nLen) const1283 StringCompare STRING::CompareIgnoreCaseToAscii( const STRING& rStr,
1284                                                 xub_StrLen nLen ) const
1285 {
1286     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1287     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1288 
1289     // Auf Gleichheit der Pointer testen
1290     if ( mpData == rStr.mpData )
1291         return COMPARE_EQUAL;
1292 
1293     // Maximale Laenge ermitteln
1294     if ( mpData->mnLen < nLen )
1295         nLen = static_cast< xub_StrLen >(mpData->mnLen+1);
1296     if ( rStr.mpData->mnLen < nLen )
1297         nLen = static_cast< xub_StrLen >(rStr.mpData->mnLen+1);
1298 
1299     // String vergleichen
1300     sal_Int32 nCompare = ImplStringICompareWithoutZero( mpData->maStr, rStr.mpData->maStr, nLen );
1301 
1302     // Rueckgabewert anpassen
1303     if ( nCompare == 0 )
1304         return COMPARE_EQUAL;
1305     else if ( nCompare < 0 )
1306         return COMPARE_LESS;
1307     else
1308         return COMPARE_GREATER;
1309 }
1310 
1311 // -----------------------------------------------------------------------
1312 
CompareIgnoreCaseToAscii(const STRCODE * pCharStr,xub_StrLen nLen) const1313 StringCompare STRING::CompareIgnoreCaseToAscii( const STRCODE* pCharStr,
1314                                                 xub_StrLen nLen ) const
1315 {
1316     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1317 
1318     // String vergleichen
1319     sal_Int32 nCompare = ImplStringICompare( mpData->maStr, pCharStr, nLen );
1320 
1321     // Rueckgabewert anpassen
1322     if ( nCompare == 0 )
1323         return COMPARE_EQUAL;
1324     else if ( nCompare < 0 )
1325         return COMPARE_LESS;
1326     else
1327         return COMPARE_GREATER;
1328 }
1329 
1330 // -----------------------------------------------------------------------
1331 
Equals(const STRING & rStr) const1332 sal_Bool STRING::Equals( const STRING& rStr ) const
1333 {
1334     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1335     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1336 
1337     // Sind die Daten gleich
1338     if ( mpData == rStr.mpData )
1339         return sal_True;
1340 
1341     // Gleiche Laenge
1342     if ( mpData->mnLen != rStr.mpData->mnLen )
1343         return sal_False;
1344 
1345     // String vergleichen
1346     return (ImplStringCompareWithoutZero( mpData->maStr, rStr.mpData->maStr, mpData->mnLen ) == 0);
1347 }
1348 
1349 // -----------------------------------------------------------------------
1350 
Equals(const STRCODE * pCharStr) const1351 sal_Bool STRING::Equals( const STRCODE* pCharStr ) const
1352 {
1353     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1354 
1355     return (ImplStringCompare( mpData->maStr, pCharStr ) == 0);
1356 }
1357 
1358 // -----------------------------------------------------------------------
1359 
EqualsIgnoreCaseAscii(const STRING & rStr) const1360 sal_Bool STRING::EqualsIgnoreCaseAscii( const STRING& rStr ) const
1361 {
1362     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1363     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1364 
1365     // Sind die Daten gleich
1366     if ( mpData == rStr.mpData )
1367         return sal_True;
1368 
1369     // Gleiche Laenge
1370     if ( mpData->mnLen != rStr.mpData->mnLen )
1371         return sal_False;
1372 
1373     // String vergleichen
1374     return (ImplStringICompareWithoutZero( mpData->maStr, rStr.mpData->maStr, mpData->mnLen ) == 0);
1375 }
1376 
1377 // -----------------------------------------------------------------------
1378 
EqualsIgnoreCaseAscii(const STRCODE * pCharStr) const1379 sal_Bool STRING::EqualsIgnoreCaseAscii( const STRCODE* pCharStr ) const
1380 {
1381     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1382 
1383     return (ImplStringICompare( mpData->maStr, pCharStr ) == 0);
1384 }
1385 
1386 // -----------------------------------------------------------------------
1387 
Equals(const STRING & rStr,xub_StrLen nIndex,xub_StrLen nLen) const1388 sal_Bool STRING::Equals( const STRING& rStr, xub_StrLen nIndex, xub_StrLen nLen ) const
1389 {
1390     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1391     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1392 
1393     // Are there enough codes for comparing?
1394     if ( nIndex > mpData->mnLen )
1395         return (rStr.mpData->mnLen == 0);
1396     sal_Int32 nMaxLen = mpData->mnLen-nIndex;
1397     if ( nMaxLen < nLen )
1398     {
1399         if ( rStr.mpData->mnLen != nMaxLen )
1400             return sal_False;
1401         nLen = static_cast< xub_StrLen >(nMaxLen);
1402     }
1403 
1404     // String vergleichen
1405     return (ImplStringCompareWithoutZero( mpData->maStr+nIndex, rStr.mpData->maStr, nLen ) == 0);
1406 }
1407 
1408 // -----------------------------------------------------------------------
1409 
Equals(const STRCODE * pCharStr,xub_StrLen nIndex,xub_StrLen nLen) const1410 sal_Bool STRING::Equals( const STRCODE* pCharStr, xub_StrLen nIndex, xub_StrLen nLen ) const
1411 {
1412     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1413 
1414     // Are there enough codes for comparing?
1415     if ( nIndex > mpData->mnLen )
1416         return (*pCharStr == 0);
1417 
1418     return (ImplStringCompare( mpData->maStr+nIndex, pCharStr, nLen ) == 0);
1419 }
1420 
1421 // -----------------------------------------------------------------------
1422 
EqualsIgnoreCaseAscii(const STRING & rStr,xub_StrLen nIndex,xub_StrLen nLen) const1423 sal_Bool STRING::EqualsIgnoreCaseAscii( const STRING& rStr, xub_StrLen nIndex, xub_StrLen nLen ) const
1424 {
1425     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1426     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1427 
1428     // Are there enough codes for comparing?
1429     if ( nIndex > mpData->mnLen )
1430         return (rStr.mpData->mnLen == 0);
1431     sal_Int32 nMaxLen = mpData->mnLen-nIndex;
1432     if ( nMaxLen < nLen )
1433     {
1434         if ( rStr.mpData->mnLen != nMaxLen )
1435             return sal_False;
1436         nLen = static_cast< xub_StrLen >(nMaxLen);
1437     }
1438 
1439     // String vergleichen
1440     return (ImplStringICompareWithoutZero( mpData->maStr+nIndex, rStr.mpData->maStr, nLen ) == 0);
1441 }
1442 
1443 // -----------------------------------------------------------------------
1444 
EqualsIgnoreCaseAscii(const STRCODE * pCharStr,xub_StrLen nIndex,xub_StrLen nLen) const1445 sal_Bool STRING::EqualsIgnoreCaseAscii( const STRCODE* pCharStr, xub_StrLen nIndex, xub_StrLen nLen ) const
1446 {
1447     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1448 
1449     // Are there enough codes for comparing?
1450     if ( nIndex > mpData->mnLen )
1451         return (*pCharStr == 0);
1452 
1453     return (ImplStringICompare( mpData->maStr+nIndex, pCharStr, nLen ) == 0);
1454 }
1455 
1456 // -----------------------------------------------------------------------
1457 
Match(const STRING & rStr) const1458 xub_StrLen STRING::Match( const STRING& rStr ) const
1459 {
1460     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1461     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1462 
1463     // Ist dieser String leer
1464     if ( !mpData->mnLen )
1465         return STRING_MATCH;
1466 
1467     // Suche bis Stringende nach dem ersten nicht uebereinstimmenden Zeichen
1468     const STRCODE*  pStr1 = mpData->maStr;
1469     const STRCODE*  pStr2 = rStr.mpData->maStr;
1470     xub_StrLen      i = 0;
1471     while ( i < mpData->mnLen )
1472     {
1473         // Stimmt das Zeichen nicht ueberein, dann abbrechen
1474         if ( *pStr1 != *pStr2 )
1475             return i;
1476         ++pStr1,
1477         ++pStr2,
1478         ++i;
1479     }
1480 
1481     return STRING_MATCH;
1482 }
1483 
1484 // -----------------------------------------------------------------------
1485 
Match(const STRCODE * pCharStr) const1486 xub_StrLen STRING::Match( const STRCODE* pCharStr ) const
1487 {
1488     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1489 
1490     // Ist dieser String leer
1491     if ( !mpData->mnLen )
1492         return STRING_MATCH;
1493 
1494     // Suche bis Stringende nach dem ersten nicht uebereinstimmenden Zeichen
1495     const STRCODE*  pStr = mpData->maStr;
1496     xub_StrLen      i = 0;
1497     while ( i < mpData->mnLen )
1498     {
1499         // Stimmt das Zeichen nicht ueberein, dann abbrechen
1500         if ( *pStr != *pCharStr )
1501             return i;
1502         ++pStr,
1503         ++pCharStr,
1504         ++i;
1505     }
1506 
1507     return STRING_MATCH;
1508 }
1509 
1510 // -----------------------------------------------------------------------
1511 
Search(STRCODE c,xub_StrLen nIndex) const1512 xub_StrLen STRING::Search( STRCODE c, xub_StrLen nIndex ) const
1513 {
1514     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1515 
1516     sal_Int32       nLen = mpData->mnLen;
1517     const STRCODE*  pStr = mpData->maStr;
1518     pStr += nIndex;
1519     while ( nIndex < nLen )
1520     {
1521         if ( *pStr == c )
1522             return nIndex;
1523         ++pStr,
1524         ++nIndex;
1525     }
1526 
1527     return STRING_NOTFOUND;
1528 }
1529 
1530 // -----------------------------------------------------------------------
1531 
Search(const STRING & rStr,xub_StrLen nIndex) const1532 xub_StrLen STRING::Search( const STRING& rStr, xub_StrLen nIndex ) const
1533 {
1534     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1535     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1536 
1537     sal_Int32 nLen = mpData->mnLen;
1538     sal_Int32 nStrLen = rStr.mpData->mnLen;
1539 
1540     // Falls die Laenge des uebergebenen Strings 0 ist oder der Index
1541     // hinter dem String liegt, dann wurde der String nicht gefunden
1542     if ( !nStrLen || (nIndex >= nLen) )
1543         return STRING_NOTFOUND;
1544 
1545     const STRCODE* pStr1 = mpData->maStr;
1546     pStr1 += nIndex;
1547 
1548     if ( nStrLen == 1 )
1549     {
1550         STRCODE cSearch = rStr.mpData->maStr[0];
1551         while ( nIndex < nLen )
1552         {
1553             if ( *pStr1 == cSearch )
1554                 return nIndex;
1555             ++pStr1,
1556             ++nIndex;
1557         }
1558     }
1559     else
1560     {
1561         const STRCODE* pStr2 = rStr.mpData->maStr;
1562 
1563         // Nur innerhalb des Strings suchen
1564         while ( nLen - nIndex >= nStrLen )
1565         {
1566             // Stimmt der String ueberein
1567             if ( ImplStringCompareWithoutZero( pStr1, pStr2, nStrLen ) == 0 )
1568                 return nIndex;
1569             ++pStr1,
1570             ++nIndex;
1571         }
1572     }
1573 
1574     return STRING_NOTFOUND;
1575 }
1576 
1577 // -----------------------------------------------------------------------
1578 
Search(const STRCODE * pCharStr,xub_StrLen nIndex) const1579 xub_StrLen STRING::Search( const STRCODE* pCharStr, xub_StrLen nIndex ) const
1580 {
1581     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1582 
1583     sal_Int32 nLen = mpData->mnLen;
1584     xub_StrLen nStrLen  = ImplStringLen( pCharStr );
1585 
1586     // Falls die Laenge des uebergebenen Strings 0 ist oder der Index
1587     // hinter dem String liegt, dann wurde der String nicht gefunden
1588     if ( !nStrLen || (nIndex >= nLen) )
1589         return STRING_NOTFOUND;
1590 
1591     const STRCODE* pStr = mpData->maStr;
1592     pStr += nIndex;
1593 
1594     if ( nStrLen == 1 )
1595     {
1596         STRCODE cSearch = *pCharStr;
1597         while ( nIndex < nLen )
1598         {
1599             if ( *pStr == cSearch )
1600                 return nIndex;
1601             ++pStr,
1602             ++nIndex;
1603         }
1604     }
1605     else
1606     {
1607         // Nur innerhalb des Strings suchen
1608         while ( nLen - nIndex >= nStrLen )
1609         {
1610             // Stimmt der String ueberein
1611             if ( ImplStringCompareWithoutZero( pStr, pCharStr, nStrLen ) == 0 )
1612                 return nIndex;
1613             ++pStr,
1614             ++nIndex;
1615         }
1616     }
1617 
1618     return STRING_NOTFOUND;
1619 }
1620 
1621 // -----------------------------------------------------------------------
1622 
SearchBackward(STRCODE c,xub_StrLen nIndex) const1623 xub_StrLen STRING::SearchBackward( STRCODE c, xub_StrLen nIndex ) const
1624 {
1625     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1626 
1627     if ( nIndex > mpData->mnLen )
1628         nIndex = (xub_StrLen)mpData->mnLen;
1629 
1630     const STRCODE* pStr = mpData->maStr;
1631     pStr += nIndex;
1632 
1633     while ( nIndex )
1634     {
1635         nIndex--;
1636         pStr--;
1637         if ( *pStr == c )
1638             return nIndex;
1639     }
1640 
1641     return STRING_NOTFOUND;
1642 }
1643 
1644 // -----------------------------------------------------------------------
1645 
SearchChar(const STRCODE * pChars,xub_StrLen nIndex) const1646 xub_StrLen STRING::SearchChar( const STRCODE* pChars, xub_StrLen nIndex ) const
1647 {
1648     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1649 
1650     sal_Int32       nLen = mpData->mnLen;
1651     const STRCODE*  pStr = mpData->maStr;
1652     pStr += nIndex;
1653     while ( nIndex < nLen )
1654     {
1655         STRCODE         c = *pStr;
1656         const STRCODE*  pCompStr = pChars;
1657         while ( *pCompStr )
1658         {
1659             if ( *pCompStr == c )
1660                 return nIndex;
1661             ++pCompStr;
1662         }
1663         ++pStr,
1664         ++nIndex;
1665     }
1666 
1667     return STRING_NOTFOUND;
1668 }
1669 
1670 // -----------------------------------------------------------------------
1671 
SearchCharBackward(const STRCODE * pChars,xub_StrLen nIndex) const1672 xub_StrLen STRING::SearchCharBackward( const STRCODE* pChars, xub_StrLen nIndex ) const
1673 {
1674     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1675 
1676     if ( nIndex > mpData->mnLen )
1677         nIndex = (xub_StrLen)mpData->mnLen;
1678 
1679     const STRCODE* pStr = mpData->maStr;
1680     pStr += nIndex;
1681 
1682     while ( nIndex )
1683     {
1684         nIndex--;
1685         pStr--;
1686 
1687         STRCODE         c =*pStr;
1688         const STRCODE*  pCompStr = pChars;
1689         while ( *pCompStr )
1690         {
1691             if ( *pCompStr == c )
1692                 return nIndex;
1693             ++pCompStr;
1694         }
1695     }
1696 
1697     return STRING_NOTFOUND;
1698 }
1699 
1700 // -----------------------------------------------------------------------
1701 
SearchAndReplace(STRCODE c,STRCODE cRep,xub_StrLen nIndex)1702 xub_StrLen STRING::SearchAndReplace( STRCODE c, STRCODE cRep, xub_StrLen nIndex )
1703 {
1704     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1705 
1706     sal_Int32       nLen = mpData->mnLen;
1707     const STRCODE*  pStr = mpData->maStr;
1708     pStr += nIndex;
1709     while ( nIndex < nLen )
1710     {
1711         if ( *pStr == c )
1712         {
1713             ImplCopyData();
1714             mpData->maStr[nIndex] = cRep;
1715             return nIndex;
1716         }
1717         ++pStr,
1718         ++nIndex;
1719     }
1720 
1721     return STRING_NOTFOUND;
1722 }
1723 
1724 // -----------------------------------------------------------------------
1725 
SearchAndReplace(const STRING & rStr,const STRING & rRepStr,xub_StrLen nIndex)1726 xub_StrLen STRING::SearchAndReplace( const STRING& rStr, const STRING& rRepStr,
1727                                      xub_StrLen nIndex )
1728 {
1729     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1730     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1731     DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING );
1732 
1733     xub_StrLen nSPos = Search( rStr, nIndex );
1734     if ( nSPos != STRING_NOTFOUND )
1735         Replace( nSPos, rStr.Len(), rRepStr );
1736 
1737     return nSPos;
1738 }
1739 
1740 // -----------------------------------------------------------------------
1741 
SearchAndReplace(const STRCODE * pCharStr,const STRING & rRepStr,xub_StrLen nIndex)1742 xub_StrLen STRING::SearchAndReplace( const STRCODE* pCharStr, const STRING& rRepStr,
1743                                      xub_StrLen nIndex )
1744 {
1745     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1746     DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING );
1747 
1748     xub_StrLen nSPos = Search( pCharStr, nIndex );
1749     if ( nSPos != STRING_NOTFOUND )
1750         Replace( nSPos, ImplStringLen( pCharStr ), rRepStr );
1751 
1752     return nSPos;
1753 }
1754 
1755 // -----------------------------------------------------------------------
1756 
SearchAndReplaceAll(STRCODE c,STRCODE cRep)1757 void STRING::SearchAndReplaceAll( STRCODE c, STRCODE cRep )
1758 {
1759     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1760 
1761     sal_Int32       nLen    = mpData->mnLen;
1762     const STRCODE*  pStr    = mpData->maStr;
1763     sal_Int32       nIndex  = 0;
1764     while ( nIndex < nLen )
1765     {
1766         if ( *pStr == c )
1767         {
1768             ImplCopyData();
1769             mpData->maStr[nIndex] = cRep;
1770         }
1771         ++pStr,
1772         ++nIndex;
1773     }
1774 }
1775 
1776 // -----------------------------------------------------------------------
1777 
SearchAndReplaceAll(const STRCODE * pCharStr,const STRING & rRepStr)1778 void STRING::SearchAndReplaceAll( const STRCODE* pCharStr, const STRING& rRepStr )
1779 {
1780     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1781     DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING );
1782 
1783     xub_StrLen nCharLen = ImplStringLen( pCharStr );
1784     xub_StrLen nSPos = Search( pCharStr, 0 );
1785     while ( nSPos != STRING_NOTFOUND )
1786     {
1787         Replace( nSPos, nCharLen, rRepStr );
1788         nSPos = nSPos + rRepStr.Len();
1789         nSPos = Search( pCharStr, nSPos );
1790     }
1791 }
1792 
1793 // -----------------------------------------------------------------------
1794 
SearchAndReplaceAll(const STRING & rStr,const STRING & rRepStr)1795 void STRING::SearchAndReplaceAll( const STRING& rStr, const STRING& rRepStr )
1796 {
1797     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1798     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1799     DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING );
1800 
1801     xub_StrLen nSPos = Search( rStr, 0 );
1802     while ( nSPos != STRING_NOTFOUND )
1803     {
1804         Replace( nSPos, rStr.Len(), rRepStr );
1805         nSPos = nSPos + rRepStr.Len();
1806         nSPos = Search( rStr, nSPos );
1807     }
1808 }
1809 
1810 // -----------------------------------------------------------------------
1811 
GetTokenCount(STRCODE cTok) const1812 xub_StrLen STRING::GetTokenCount( STRCODE cTok ) const
1813 {
1814     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1815 
1816     // Leerer String: TokenCount per Definition 0
1817     if ( !mpData->mnLen )
1818         return 0;
1819 
1820     xub_StrLen      nTokCount       = 1;
1821     sal_Int32       nLen            = mpData->mnLen;
1822     const STRCODE*  pStr            = mpData->maStr;
1823     sal_Int32       nIndex          = 0;
1824     while ( nIndex < nLen )
1825     {
1826         // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount
1827         if ( *pStr == cTok )
1828             ++nTokCount;
1829         ++pStr,
1830         ++nIndex;
1831     }
1832 
1833     return nTokCount;
1834 }
1835 
1836 // -----------------------------------------------------------------------
1837 
SetToken(xub_StrLen nToken,STRCODE cTok,const STRING & rStr,xub_StrLen nIndex)1838 void STRING::SetToken( xub_StrLen nToken, STRCODE cTok, const STRING& rStr,
1839                        xub_StrLen nIndex )
1840 {
1841     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1842     DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1843 
1844     const STRCODE*  pStr            = mpData->maStr;
1845     xub_StrLen      nLen            = (xub_StrLen)mpData->mnLen;
1846     xub_StrLen      nTok            = 0;
1847     xub_StrLen      nFirstChar      = nIndex;
1848     xub_StrLen      i               = nFirstChar;
1849 
1850     // Bestimme die Token-Position und Laenge
1851     pStr += i;
1852     while ( i < nLen )
1853     {
1854         // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount
1855         if ( *pStr == cTok )
1856         {
1857             ++nTok;
1858 
1859             if ( nTok == nToken )
1860                 nFirstChar = i+1;
1861             else
1862             {
1863                 if ( nTok > nToken )
1864                     break;
1865             }
1866         }
1867 
1868         ++pStr,
1869         ++i;
1870     }
1871 
1872     if ( nTok >= nToken )
1873         Replace( nFirstChar, i-nFirstChar, rStr );
1874 }
1875 
1876 // -----------------------------------------------------------------------
1877 
GetToken(xub_StrLen nToken,STRCODE cTok,xub_StrLen & rIndex) const1878 STRING STRING::GetToken( xub_StrLen nToken, STRCODE cTok, xub_StrLen& rIndex ) const
1879 {
1880     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1881 
1882     const STRCODE*  pStr            = mpData->maStr;
1883     xub_StrLen      nLen            = (xub_StrLen)mpData->mnLen;
1884     xub_StrLen      nTok            = 0;
1885     xub_StrLen      nFirstChar      = rIndex;
1886     xub_StrLen      i               = nFirstChar;
1887 
1888     // Bestimme die Token-Position und Laenge
1889     pStr += i;
1890     while ( i < nLen )
1891     {
1892         // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount
1893         if ( *pStr == cTok )
1894         {
1895             ++nTok;
1896 
1897             if ( nTok == nToken )
1898                 nFirstChar = i+1;
1899             else
1900             {
1901                 if ( nTok > nToken )
1902                     break;
1903             }
1904         }
1905 
1906         ++pStr,
1907         ++i;
1908     }
1909 
1910     if ( nTok >= nToken )
1911     {
1912         if ( i < nLen )
1913             rIndex = i+1;
1914         else
1915             rIndex = STRING_NOTFOUND;
1916         return Copy( nFirstChar, i-nFirstChar );
1917     }
1918     else
1919     {
1920         rIndex = STRING_NOTFOUND;
1921         return STRING();
1922     }
1923 }
1924 
1925 // -----------------------------------------------------------------------
1926 
GetQuotedTokenCount(const STRING & rQuotedPairs,STRCODE cTok) const1927 xub_StrLen STRING::GetQuotedTokenCount( const STRING& rQuotedPairs, STRCODE cTok ) const
1928 {
1929     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1930     DBG_CHKOBJ( &rQuotedPairs, STRING, DBGCHECKSTRING );
1931     DBG_ASSERT( !(rQuotedPairs.Len()%2), "String::GetQuotedTokenCount() - QuotedString%2 != 0" );
1932     DBG_ASSERT( rQuotedPairs.Search(cTok) == STRING_NOTFOUND, "String::GetQuotedTokenCount() - cTok in QuotedString" );
1933 
1934     // Leerer String: TokenCount per Definition 0
1935     if ( !mpData->mnLen )
1936         return 0;
1937 
1938     xub_StrLen      nTokCount       = 1;
1939     sal_Int32       nLen            = mpData->mnLen;
1940     xub_StrLen      nQuotedLen      = rQuotedPairs.Len();
1941     STRCODE         cQuotedEndChar  = 0;
1942     const STRCODE*  pQuotedStr      = rQuotedPairs.mpData->maStr;
1943     const STRCODE*  pStr            = mpData->maStr;
1944     sal_Int32       nIndex          = 0;
1945     while ( nIndex < nLen )
1946     {
1947         STRCODE c = *pStr;
1948         if ( cQuotedEndChar )
1949         {
1950             // Ende des Quotes erreicht ?
1951             if ( c == cQuotedEndChar )
1952                 cQuotedEndChar = 0;
1953         }
1954         else
1955         {
1956             // Ist das Zeichen ein Quote-Anfang-Zeichen ?
1957             xub_StrLen nQuoteIndex = 0;
1958             while ( nQuoteIndex < nQuotedLen )
1959             {
1960                 if ( pQuotedStr[nQuoteIndex] == c )
1961                 {
1962                     cQuotedEndChar = pQuotedStr[nQuoteIndex+1];
1963                     break;
1964                 }
1965                 else
1966                     nQuoteIndex += 2;
1967             }
1968 
1969             // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount
1970             if ( c == cTok )
1971                 ++nTokCount;
1972         }
1973 
1974         ++pStr,
1975         ++nIndex;
1976     }
1977 
1978     return nTokCount;
1979 }
1980 
1981 // -----------------------------------------------------------------------
1982 
GetQuotedToken(xub_StrLen nToken,const STRING & rQuotedPairs,STRCODE cTok,xub_StrLen & rIndex) const1983 STRING STRING::GetQuotedToken( xub_StrLen nToken, const STRING& rQuotedPairs,
1984                                STRCODE cTok, xub_StrLen& rIndex ) const
1985 {
1986     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1987     DBG_CHKOBJ( &rQuotedPairs, STRING, DBGCHECKSTRING );
1988     DBG_ASSERT( !(rQuotedPairs.Len()%2), "String::GetQuotedToken() - QuotedString%2 != 0" );
1989     DBG_ASSERT( rQuotedPairs.Search(cTok) == STRING_NOTFOUND, "String::GetQuotedToken() - cTok in QuotedString" );
1990 
1991     const STRCODE*  pStr            = mpData->maStr;
1992     const STRCODE*  pQuotedStr      = rQuotedPairs.mpData->maStr;
1993     STRCODE         cQuotedEndChar  = 0;
1994     xub_StrLen      nQuotedLen      = rQuotedPairs.Len();
1995     xub_StrLen      nLen            = (xub_StrLen)mpData->mnLen;
1996     xub_StrLen      nTok            = 0;
1997     xub_StrLen      nFirstChar      = rIndex;
1998     xub_StrLen      i               = nFirstChar;
1999 
2000     // Bestimme die Token-Position und Laenge
2001     pStr += i;
2002     while ( i < nLen )
2003     {
2004         STRCODE c = *pStr;
2005         if ( cQuotedEndChar )
2006         {
2007             // Ende des Quotes erreicht ?
2008             if ( c == cQuotedEndChar )
2009                 cQuotedEndChar = 0;
2010         }
2011         else
2012         {
2013             // Ist das Zeichen ein Quote-Anfang-Zeichen ?
2014             xub_StrLen nQuoteIndex = 0;
2015             while ( nQuoteIndex < nQuotedLen )
2016             {
2017                 if ( pQuotedStr[nQuoteIndex] == c )
2018                 {
2019                     cQuotedEndChar = pQuotedStr[nQuoteIndex+1];
2020                     break;
2021                 }
2022                 else
2023                     nQuoteIndex += 2;
2024             }
2025 
2026             // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount
2027             if ( c == cTok )
2028             {
2029                 ++nTok;
2030 
2031                 if ( nTok == nToken )
2032                     nFirstChar = i+1;
2033                 else
2034                 {
2035                     if ( nTok > nToken )
2036                         break;
2037                 }
2038             }
2039         }
2040 
2041         ++pStr,
2042         ++i;
2043     }
2044 
2045     if ( nTok >= nToken )
2046     {
2047         if ( i < nLen )
2048             rIndex = i+1;
2049         else
2050             rIndex = STRING_NOTFOUND;
2051         return Copy( nFirstChar, i-nFirstChar );
2052     }
2053     else
2054     {
2055         rIndex = STRING_NOTFOUND;
2056         return STRING();
2057     }
2058 }
2059 
2060 // -----------------------------------------------------------------------
2061 
GetBufferAccess()2062 STRCODE* STRING::GetBufferAccess()
2063 {
2064     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
2065 
2066     // Daten kopieren, wenn noetig
2067     if ( mpData->mnLen )
2068         ImplCopyData();
2069 
2070     // Pointer auf den String zurueckgeben
2071     return mpData->maStr;
2072 }
2073 
2074 // -----------------------------------------------------------------------
2075 
ReleaseBufferAccess(xub_StrLen nLen)2076 void STRING::ReleaseBufferAccess( xub_StrLen nLen )
2077 {
2078     // Hier ohne Funktionstest, da String nicht konsistent
2079     DBG_CHKTHIS( STRING, NULL );
2080     DBG_ASSERT( mpData->mnRefCount == 1, "String::ReleaseCharStr() called for String with RefCount" );
2081 
2082     if ( nLen > mpData->mnLen )
2083         nLen = ImplStringLen( mpData->maStr );
2084     OSL_ASSERT(nLen <= mpData->mnLen);
2085     if ( !nLen )
2086     {
2087         STRING_NEW((STRING_TYPE **)&mpData);
2088     }
2089     // Bei mehr als 8 Zeichen unterschied, kuerzen wir den Buffer
2090     else if ( mpData->mnLen - nLen > 8 )
2091     {
2092         STRINGDATA* pNewData = ImplAllocData( nLen );
2093         memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
2094         STRING_RELEASE((STRING_TYPE *)mpData);
2095         mpData = pNewData;
2096     }
2097     else
2098         mpData->mnLen = nLen;
2099 }
2100 
2101 // -----------------------------------------------------------------------
2102 
AllocBuffer(xub_StrLen nLen)2103 STRCODE* STRING::AllocBuffer( xub_StrLen nLen )
2104 {
2105     DBG_CHKTHIS( STRING, DBGCHECKSTRING );
2106 
2107     STRING_RELEASE((STRING_TYPE *)mpData);
2108     if ( nLen )
2109         mpData = ImplAllocData( nLen );
2110     else
2111     {
2112         mpData = NULL;
2113         STRING_NEW((STRING_TYPE **)&mpData);
2114     }
2115 
2116     return mpData->maStr;
2117 }
2118