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