Update ooo320-m1
[ooovba.git] / tools / source / string / strimp.cxx
blobe876c9b9f3f74fe6a67f363b030a1d64e227d180
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: strimp.cxx,v $
10 * $Revision: 1.12 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // no include "precompiled_tools.hxx" because this is included in other cxx files.
33 // =======================================================================
35 static sal_Int32 ImplStringCompare( const STRCODE* pStr1, const STRCODE* pStr2 )
37 sal_Int32 nRet;
38 while ( ((nRet = ((sal_Int32)((STRCODEU)*pStr1))-((sal_Int32)((STRCODEU)*pStr2))) == 0) &&
39 *pStr2 )
41 ++pStr1,
42 ++pStr2;
45 return nRet;
48 // -----------------------------------------------------------------------
50 static sal_Int32 ImplStringCompare( const STRCODE* pStr1, const STRCODE* pStr2,
51 xub_StrLen nCount )
53 sal_Int32 nRet = 0;
54 while ( nCount &&
55 ((nRet = ((sal_Int32)((STRCODEU)*pStr1))-((sal_Int32)((STRCODEU)*pStr2))) == 0) &&
56 *pStr2 )
58 ++pStr1,
59 ++pStr2,
60 --nCount;
63 return nRet;
66 // -----------------------------------------------------------------------
68 static sal_Int32 ImplStringCompareWithoutZero( const STRCODE* pStr1, const STRCODE* pStr2,
69 sal_Int32 nCount )
71 sal_Int32 nRet = 0;
72 while ( nCount &&
73 ((nRet = ((sal_Int32)((STRCODEU)*pStr1))-((sal_Int32)((STRCODEU)*pStr2))) == 0) )
75 ++pStr1,
76 ++pStr2,
77 --nCount;
80 return nRet;
83 // -----------------------------------------------------------------------
85 static sal_Int32 ImplStringICompare( const STRCODE* pStr1, const STRCODE* pStr2 )
87 sal_Int32 nRet;
88 STRCODE c1;
89 STRCODE c2;
92 // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln
93 c1 = *pStr1;
94 c2 = *pStr2;
95 if ( (c1 >= 65) && (c1 <= 90) )
96 c1 += 32;
97 if ( (c2 >= 65) && (c2 <= 90) )
98 c2 += 32;
99 nRet = ((sal_Int32)((STRCODEU)c1))-((sal_Int32)((STRCODEU)c2));
100 if ( nRet != 0 )
101 break;
103 ++pStr1,
104 ++pStr2;
106 while ( c2 );
108 return nRet;
111 // -----------------------------------------------------------------------
113 static sal_Int32 ImplStringICompare( const STRCODE* pStr1, const STRCODE* pStr2,
114 xub_StrLen nCount )
116 sal_Int32 nRet = 0;
117 STRCODE c1;
118 STRCODE c2;
121 if ( !nCount )
122 break;
124 // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln
125 c1 = *pStr1;
126 c2 = *pStr2;
127 if ( (c1 >= 65) && (c1 <= 90) )
128 c1 += 32;
129 if ( (c2 >= 65) && (c2 <= 90) )
130 c2 += 32;
131 nRet = ((sal_Int32)((STRCODEU)c1))-((sal_Int32)((STRCODEU)c2));
132 if ( nRet != 0 )
133 break;
135 ++pStr1,
136 ++pStr2,
137 --nCount;
139 while ( c2 );
141 return nRet;
144 // -----------------------------------------------------------------------
146 static sal_Int32 ImplStringICompareWithoutZero( const STRCODE* pStr1, const STRCODE* pStr2,
147 sal_Int32 nCount )
149 sal_Int32 nRet = 0;
150 STRCODE c1;
151 STRCODE c2;
154 if ( !nCount )
155 break;
157 // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln
158 c1 = *pStr1;
159 c2 = *pStr2;
160 if ( (c1 >= 65) && (c1 <= 90) )
161 c1 += 32;
162 if ( (c2 >= 65) && (c2 <= 90) )
163 c2 += 32;
164 nRet = ((sal_Int32)((STRCODEU)c1))-((sal_Int32)((STRCODEU)c2));
166 ++pStr1,
167 ++pStr2,
168 --nCount;
170 while ( nRet == 0 );
172 return nRet;
175 // =======================================================================
177 #ifdef DBG_UTIL
178 const char* DBGCHECKSTRING( const void* pString )
180 STRING* p = (STRING*)pString;
182 if ( p->GetBuffer()[p->Len()] != 0 )
183 return "String damaged: aStr[nLen] != 0";
185 return NULL;
187 #endif
189 // =======================================================================
191 static STRINGDATA* ImplAllocData( sal_Int32 nLen )
193 // Dann kopiere die Daten
194 STRINGDATA* pData = (STRINGDATA*)rtl_allocateMemory( sizeof(STRINGDATA)+(nLen*sizeof( STRCODE )) );
195 pData->mnRefCount = 1;
196 pData->mnLen = nLen;
197 pData->maStr[nLen] = 0;
198 return pData;
201 // -----------------------------------------------------------------------
203 static STRINGDATA* _ImplCopyData( STRINGDATA* pData )
205 unsigned int nSize = sizeof(STRINGDATA)+(pData->mnLen*sizeof( STRCODE ));
206 STRINGDATA* pNewData = (STRINGDATA*)rtl_allocateMemory( nSize );
207 memcpy( pNewData, pData, nSize );
208 pNewData->mnRefCount = 1;
209 STRING_RELEASE((STRING_TYPE *)pData);
210 return pNewData;
213 // -----------------------------------------------------------------------
215 inline void STRING::ImplCopyData()
217 DBG_ASSERT( (mpData->mnRefCount != 0), "String::ImplCopyData() - RefCount == 0" );
219 // ist es ein referenzierter String, dann die Daten abkoppeln
220 if ( mpData->mnRefCount != 1 )
221 mpData = _ImplCopyData( mpData );
224 // -----------------------------------------------------------------------
226 inline STRCODE* STRING::ImplCopyStringData( STRCODE* pStr )
228 // Ist der Referenzzaehler groesser 0
229 if ( mpData->mnRefCount != 1 ) {
230 DBG_ASSERT( (pStr >= mpData->maStr) &&
231 ((pStr-mpData->maStr) < mpData->mnLen),
232 "ImplCopyStringData - pStr from other String-Instanz" );
233 unsigned int nIndex = (unsigned int)(pStr-mpData->maStr);
234 mpData = _ImplCopyData( mpData );
235 pStr = mpData->maStr + nIndex;
237 return pStr;
240 // -----------------------------------------------------------------------
242 inline sal_Int32 ImplGetCopyLen( sal_Int32 nStrLen, sal_Int32 nCopyLen )
244 OSL_ASSERT(nStrLen <= STRING_MAXLEN && nCopyLen <= STRING_MAXLEN);
245 if ( nCopyLen > STRING_MAXLEN-nStrLen )
246 nCopyLen = STRING_MAXLEN-nStrLen;
247 return nCopyLen;
250 // =======================================================================
252 STRING::STRING()
253 : mpData(NULL)
255 DBG_CTOR( STRING, DBGCHECKSTRING );
257 STRING_NEW((STRING_TYPE **)&mpData);
260 // -----------------------------------------------------------------------
262 STRING::STRING( const STRING& rStr )
264 DBG_CTOR( STRING, DBGCHECKSTRING );
265 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
267 // Pointer auf die Daten des uebergebenen Strings setzen und
268 // Referenzzaehler erhoehen
269 STRING_ACQUIRE((STRING_TYPE *)rStr.mpData);
270 mpData = rStr.mpData;
273 // -----------------------------------------------------------------------
275 STRING::STRING( const STRING& rStr, xub_StrLen nPos, xub_StrLen nLen )
276 : mpData( NULL )
278 DBG_CTOR( STRING, DBGCHECKSTRING );
279 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
281 // Stringlaenge ermitteln
282 if ( nPos > rStr.mpData->mnLen )
283 nLen = 0;
284 else
286 // Laenge korrigieren, wenn noetig
287 sal_Int32 nMaxLen = rStr.mpData->mnLen-nPos;
288 if ( nLen > nMaxLen )
289 nLen = static_cast< xub_StrLen >(nMaxLen);
292 // Ist es kein leerer String
293 if ( nLen )
295 // Reicht ein einfaches erhoehen des Referenzcounters
296 if ( (nPos == 0) && (nLen == rStr.mpData->mnLen) )
298 STRING_ACQUIRE((STRING_TYPE *)rStr.mpData);
299 mpData = rStr.mpData;
301 else
303 // Verwaltungsdaten anlegen und String kopieren
304 mpData = ImplAllocData( nLen );
305 memcpy( mpData->maStr, rStr.mpData->maStr+nPos, nLen*sizeof( STRCODE ) );
308 else
310 STRING_NEW((STRING_TYPE **)&mpData);
314 // -----------------------------------------------------------------------
316 STRING::STRING( const STRCODE* pCharStr )
317 : mpData(NULL)
319 DBG_CTOR( STRING, DBGCHECKSTRING );
321 // Stringlaenge ermitteln
322 // Bei diesem Ctor darf NULL uebergeben werden
323 xub_StrLen nLen;
324 if ( pCharStr )
325 nLen = ImplStringLen( pCharStr );
326 else
327 nLen = 0;
329 // Ist es kein leerer String
330 if ( nLen )
332 // Verwaltungsdaten anlegen und String kopieren
333 mpData = ImplAllocData( nLen );
334 memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
336 else
338 STRING_NEW((STRING_TYPE **)&mpData);
342 // -----------------------------------------------------------------------
344 STRING::STRING( const STRCODE* pCharStr, xub_StrLen nLen )
345 : mpData(NULL)
347 DBG_CTOR( STRING, DBGCHECKSTRING );
348 DBG_ASSERT( pCharStr, "String::String() - pCharStr is NULL" );
350 if ( nLen == STRING_LEN )
351 nLen = ImplStringLen( pCharStr );
353 #ifdef DBG_UTIL
354 if ( DbgIsAssert() )
356 for ( xub_StrLen i = 0; i < nLen; i++ )
358 if ( !pCharStr[i] )
360 DBG_ERROR( "String::String() : nLen is wrong" );
364 #endif
366 // Ist es kein leerer String
367 if ( nLen )
369 // Verwaltungsdaten anlegen und String kopieren
370 mpData = ImplAllocData( nLen );
371 memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
373 else
375 STRING_NEW((STRING_TYPE **)&mpData);
379 // -----------------------------------------------------------------------
381 STRING::STRING( STRCODE c )
383 DBG_CTOR( STRING, DBGCHECKSTRING );
384 DBG_ASSERT( c, "String::String() - c is 0" );
386 // Verwaltungsdaten anlegen und initialisieren
387 mpData = ImplAllocData( 1 );
388 mpData->maStr[0] = c;
391 // -----------------------------------------------------------------------
393 STRING::~STRING()
395 DBG_DTOR( STRING, DBGCHECKSTRING );
397 // Daten loeschen
398 STRING_RELEASE((STRING_TYPE *)mpData);
401 // -----------------------------------------------------------------------
403 STRING& STRING::Assign( const STRING& rStr )
405 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
406 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
408 STRING_ACQUIRE((STRING_TYPE *)rStr.mpData);
409 STRING_RELEASE((STRING_TYPE *)mpData);
410 mpData = rStr.mpData;
411 return *this;
414 // -----------------------------------------------------------------------
416 STRING& STRING::Assign( const STRCODE* pCharStr )
418 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
419 DBG_ASSERT( pCharStr, "String::Assign() - pCharStr is NULL" );
421 // Stringlaenge ermitteln
422 xub_StrLen nLen = ImplStringLen( pCharStr );
424 if ( !nLen )
426 STRING_NEW((STRING_TYPE **)&mpData);
428 else
430 // Wenn String genauso lang ist, wie der String, dann direkt kopieren
431 if ( (nLen == mpData->mnLen) && (mpData->mnRefCount == 1) )
432 memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
433 else
435 // Alte Daten loeschen
436 STRING_RELEASE((STRING_TYPE *)mpData);
438 // Daten initialisieren und String kopieren
439 mpData = ImplAllocData( nLen );
440 memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
444 return *this;
447 // -----------------------------------------------------------------------
449 STRING& STRING::Assign( const STRCODE* pCharStr, xub_StrLen nLen )
451 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
452 DBG_ASSERT( pCharStr, "String::Assign() - pCharStr is NULL" );
454 if ( nLen == STRING_LEN )
455 nLen = ImplStringLen( pCharStr );
457 #ifdef DBG_UTIL
458 if ( DbgIsAssert() )
460 for ( xub_StrLen i = 0; i < nLen; i++ )
462 if ( !pCharStr[i] )
464 DBG_ERROR( "String::Assign() : nLen is wrong" );
468 #endif
470 if ( !nLen )
472 STRING_NEW((STRING_TYPE **)&mpData);
474 else
476 // Wenn String genauso lang ist, wie der String, dann direkt kopieren
477 if ( (nLen == mpData->mnLen) && (mpData->mnRefCount == 1) )
478 memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
479 else
481 // Alte Daten loeschen
482 STRING_RELEASE((STRING_TYPE *)mpData);
484 // Daten initialisieren und String kopieren
485 mpData = ImplAllocData( nLen );
486 memcpy( mpData->maStr, pCharStr, nLen*sizeof( STRCODE ) );
490 return *this;
493 // -----------------------------------------------------------------------
495 STRING& STRING::Assign( STRCODE c )
497 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
498 DBG_ASSERT( c, "String::Assign() - c is 0" );
500 // Verwaltungsdaten anlegen und initialisieren
501 STRING_RELEASE((STRING_TYPE *)mpData);
502 mpData = ImplAllocData( 1 );
503 mpData->maStr[0] = c;
504 return *this;
507 // -----------------------------------------------------------------------
509 STRING& STRING::Append( const STRING& rStr )
511 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
512 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
514 // Wenn String leer, dann reicht eine Zuweisung
515 sal_Int32 nLen = mpData->mnLen;
516 if ( !nLen )
518 STRING_ACQUIRE((STRING_TYPE *)rStr.mpData);
519 STRING_RELEASE((STRING_TYPE *)mpData);
520 mpData = rStr.mpData;
522 else
524 // Ueberlauf abfangen
525 sal_Int32 nCopyLen = ImplGetCopyLen( nLen, rStr.mpData->mnLen );
527 // Ist der uebergebene String kein Leerstring
528 if ( nCopyLen )
530 // Neue Datenstruktur und neuen String erzeugen
531 STRINGDATA* pNewData = ImplAllocData( nLen+nCopyLen );
533 // String kopieren
534 memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
535 memcpy( pNewData->maStr+nLen, rStr.mpData->maStr, nCopyLen*sizeof( STRCODE ) );
537 // Alte Daten loeschen und Neue zuweisen
538 STRING_RELEASE((STRING_TYPE *)mpData);
539 mpData = pNewData;
543 return *this;
546 // -----------------------------------------------------------------------
548 STRING& STRING::Append( const STRCODE* pCharStr )
550 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
551 DBG_ASSERT( pCharStr, "String::Append() - pCharStr is NULL" );
553 // Stringlaenge ermitteln
554 sal_Int32 nLen = mpData->mnLen;
555 sal_Int32 nCopyLen = ImplStringLen( pCharStr );
557 // Ueberlauf abfangen
558 nCopyLen = ImplGetCopyLen( nLen, nCopyLen );
560 // Ist es kein leerer String
561 if ( nCopyLen )
563 // Neue Datenstruktur und neuen String erzeugen
564 STRINGDATA* pNewData = ImplAllocData( nLen+nCopyLen );
566 // String kopieren
567 memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
568 memcpy( pNewData->maStr+nLen, pCharStr, nCopyLen*sizeof( STRCODE ) );
570 // Alte Daten loeschen und Neue zuweisen
571 STRING_RELEASE((STRING_TYPE *)mpData);
572 mpData = pNewData;
575 return *this;
578 // -----------------------------------------------------------------------
580 STRING& STRING::Append( const STRCODE* pCharStr, xub_StrLen nCharLen )
582 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
583 DBG_ASSERT( pCharStr, "String::Append() - pCharStr is NULL" );
585 if ( nCharLen == STRING_LEN )
586 nCharLen = ImplStringLen( pCharStr );
588 #ifdef DBG_UTIL
589 if ( DbgIsAssert() )
591 for ( xub_StrLen i = 0; i < nCharLen; i++ )
593 if ( !pCharStr[i] )
595 DBG_ERROR( "String::Append() : nLen is wrong" );
599 #endif
601 // Ueberlauf abfangen
602 sal_Int32 nLen = mpData->mnLen;
603 sal_Int32 nCopyLen = ImplGetCopyLen( nLen, nCharLen );
605 // Ist es kein leerer String
606 if ( nCopyLen )
608 // Neue Datenstruktur und neuen String erzeugen
609 STRINGDATA* pNewData = ImplAllocData( nLen+nCopyLen );
611 // String kopieren
612 memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
613 memcpy( pNewData->maStr+nLen, pCharStr, nCopyLen*sizeof( STRCODE ) );
615 // Alte Daten loeschen und Neue zuweisen
616 STRING_RELEASE((STRING_TYPE *)mpData);
617 mpData = pNewData;
620 return *this;
623 // -----------------------------------------------------------------------
625 STRING& STRING::Append( STRCODE c )
627 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
629 // kein 0-Character und maximale Stringlaenge nicht ueberschreiten
630 sal_Int32 nLen = mpData->mnLen;
631 if ( c && (nLen < STRING_MAXLEN) )
633 // Neue Datenstruktur und neuen String erzeugen
634 STRINGDATA* pNewData = ImplAllocData( nLen+1 );
636 // String kopieren
637 memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
638 pNewData->maStr[nLen] = c;
640 // Alte Daten loeschen und Neue zuweisen
641 STRING_RELEASE((STRING_TYPE *)mpData);
642 mpData = pNewData;
645 return *this;
648 // -----------------------------------------------------------------------
650 void STRING::SetChar( xub_StrLen nIndex, STRCODE c )
652 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
653 DBG_ASSERT( nIndex < mpData->mnLen, "String::SetChar() - nIndex > String.Len()" );
655 // Daten kopieren, wenn noetig und Character zuweisen
656 ImplCopyData();
657 mpData->maStr[nIndex] = c;
660 // -----------------------------------------------------------------------
662 STRING& STRING::Insert( const STRING& rStr, xub_StrLen nIndex )
664 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
665 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
667 // Ueberlauf abfangen
668 sal_Int32 nCopyLen = ImplGetCopyLen( mpData->mnLen, rStr.mpData->mnLen );
670 // Ist der einzufuegende String ein Leerstring
671 if ( !nCopyLen )
672 return *this;
674 // Index groesser als Laenge
675 if ( nIndex > mpData->mnLen )
676 nIndex = static_cast< xub_StrLen >(mpData->mnLen);
678 // Neue Laenge ermitteln und neuen String anlegen
679 STRINGDATA* pNewData = ImplAllocData( mpData->mnLen+nCopyLen );
681 // String kopieren
682 memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
683 memcpy( pNewData->maStr+nIndex, rStr.mpData->maStr, nCopyLen*sizeof( STRCODE ) );
684 memcpy( pNewData->maStr+nIndex+nCopyLen, mpData->maStr+nIndex,
685 (mpData->mnLen-nIndex)*sizeof( STRCODE ) );
687 // Alte Daten loeschen und Neue zuweisen
688 STRING_RELEASE((STRING_TYPE *)mpData);
689 mpData = pNewData;
691 return *this;
694 // -----------------------------------------------------------------------
696 STRING& STRING::Insert( const STRING& rStr, xub_StrLen nPos, xub_StrLen nLen,
697 xub_StrLen nIndex )
699 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
700 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
702 // Stringlaenge ermitteln
703 if ( nPos > rStr.mpData->mnLen )
704 nLen = 0;
705 else
707 // Laenge korrigieren, wenn noetig
708 sal_Int32 nMaxLen = rStr.mpData->mnLen-nPos;
709 if ( nLen > nMaxLen )
710 nLen = static_cast< xub_StrLen >(nMaxLen);
713 // Ueberlauf abfangen
714 sal_Int32 nCopyLen = ImplGetCopyLen( mpData->mnLen, nLen );
716 // Ist der einzufuegende String ein Leerstring
717 if ( !nCopyLen )
718 return *this;
720 // Index groesser als Laenge
721 if ( nIndex > mpData->mnLen )
722 nIndex = static_cast< xub_StrLen >(mpData->mnLen);
724 // Neue Laenge ermitteln und neuen String anlegen
725 STRINGDATA* pNewData = ImplAllocData( mpData->mnLen+nCopyLen );
727 // String kopieren
728 memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
729 memcpy( pNewData->maStr+nIndex, rStr.mpData->maStr+nPos, nCopyLen*sizeof( STRCODE ) );
730 memcpy( pNewData->maStr+nIndex+nCopyLen, mpData->maStr+nIndex,
731 (mpData->mnLen-nIndex)*sizeof( STRCODE ) );
733 // Alte Daten loeschen und Neue zuweisen
734 STRING_RELEASE((STRING_TYPE *)mpData);
735 mpData = pNewData;
737 return *this;
740 // -----------------------------------------------------------------------
742 STRING& STRING::Insert( const STRCODE* pCharStr, xub_StrLen nIndex )
744 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
745 DBG_ASSERT( pCharStr, "String::Insert() - pCharStr is NULL" );
747 // Stringlaenge ermitteln
748 sal_Int32 nCopyLen = ImplStringLen( pCharStr );
750 // Ueberlauf abfangen
751 nCopyLen = ImplGetCopyLen( mpData->mnLen, nCopyLen );
753 // Ist der einzufuegende String ein Leerstring
754 if ( !nCopyLen )
755 return *this;
757 // Index groesser als Laenge
758 if ( nIndex > mpData->mnLen )
759 nIndex = static_cast< xub_StrLen >(mpData->mnLen);
761 // Neue Laenge ermitteln und neuen String anlegen
762 STRINGDATA* pNewData = ImplAllocData( mpData->mnLen+nCopyLen );
764 // String kopieren
765 memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
766 memcpy( pNewData->maStr+nIndex, pCharStr, nCopyLen*sizeof( STRCODE ) );
767 memcpy( pNewData->maStr+nIndex+nCopyLen, mpData->maStr+nIndex,
768 (mpData->mnLen-nIndex)*sizeof( STRCODE ) );
770 // Alte Daten loeschen und Neue zuweisen
771 STRING_RELEASE((STRING_TYPE *)mpData);
772 mpData = pNewData;
774 return *this;
777 // -----------------------------------------------------------------------
779 STRING& STRING::Insert( STRCODE c, xub_StrLen nIndex )
781 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
783 // Ist es kein 0-Character
784 if ( !c || (mpData->mnLen == STRING_MAXLEN) )
785 return *this;
787 // Index groesser als Laenge
788 if ( nIndex > mpData->mnLen )
789 nIndex = static_cast< xub_StrLen >(mpData->mnLen);
791 // Neue Laenge ermitteln und neuen String anlegen
792 STRINGDATA* pNewData = ImplAllocData( mpData->mnLen+1 );
794 // String kopieren
795 memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
796 pNewData->maStr[nIndex] = c;
797 memcpy( pNewData->maStr+nIndex+1, mpData->maStr+nIndex,
798 (mpData->mnLen-nIndex)*sizeof( STRCODE ) );
800 // Alte Daten loeschen und Neue zuweisen
801 STRING_RELEASE((STRING_TYPE *)mpData);
802 mpData = pNewData;
804 return *this;
807 // -----------------------------------------------------------------------
809 STRING& STRING::Replace( xub_StrLen nIndex, xub_StrLen nCount, const STRING& rStr )
811 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
812 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
814 // Wenn Index groessergleich Laenge ist, dann ist es ein Append
815 if ( nIndex >= mpData->mnLen )
817 Append( rStr );
818 return *this;
821 // Ist es eine Zuweisung
822 if ( (nIndex == 0) && (nCount >= mpData->mnLen) )
824 Assign( rStr );
825 return *this;
828 // Reicht ein Erase
829 sal_Int32 nStrLen = rStr.mpData->mnLen;
830 if ( !nStrLen )
831 return Erase( nIndex, nCount );
833 // nCount darf nicht ueber das Stringende hinnausgehen
834 if ( nCount > mpData->mnLen - nIndex )
835 nCount = static_cast< xub_StrLen >(mpData->mnLen-nIndex);
837 // Reicht ein Insert
838 if ( !nCount )
839 return Insert( rStr, nIndex );
841 // Reicht eine zeichenweise Zuweisung
842 if ( nCount == nStrLen )
844 ImplCopyData();
845 memcpy( mpData->maStr+nIndex, rStr.mpData->maStr, nCount*sizeof( STRCODE ) );
846 return *this;
849 // Ueberlauf abfangen
850 nStrLen = ImplGetCopyLen( mpData->mnLen-nCount, nStrLen );
852 // Neue Daten anlegen
853 STRINGDATA* pNewData = ImplAllocData( mpData->mnLen-nCount+nStrLen );
855 // String kopieren
856 memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
857 memcpy( pNewData->maStr+nIndex, rStr.mpData->maStr, nStrLen*sizeof( STRCODE ) );
858 memcpy( pNewData->maStr+nIndex+nStrLen, mpData->maStr+nIndex+nCount,
859 (mpData->mnLen-nIndex-nCount+1)*sizeof( STRCODE ) );
861 // Alte Daten loeschen und Neue zuweisen
862 STRING_RELEASE((STRING_TYPE *)mpData);
863 mpData = pNewData;
865 return *this;
868 // -----------------------------------------------------------------------
870 STRING& STRING::Erase( xub_StrLen nIndex, xub_StrLen nCount )
872 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
874 // Ist der Index ausserhalb des Strings oder ist nCount == 0
875 if ( (nIndex >= mpData->mnLen) || !nCount )
876 return *this;
878 // nCount darf nicht ueber das Stringende hinnausgehen
879 if ( nCount > mpData->mnLen - nIndex )
880 nCount = static_cast< xub_StrLen >(mpData->mnLen-nIndex);
882 // Ist das Ergebnis kein Leerstring
883 if ( mpData->mnLen - nCount )
885 // Neue Daten anlegen
886 STRINGDATA* pNewData = ImplAllocData( mpData->mnLen-nCount );
888 // String kopieren
889 memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
890 memcpy( pNewData->maStr+nIndex, mpData->maStr+nIndex+nCount,
891 (mpData->mnLen-nIndex-nCount+1)*sizeof( STRCODE ) );
893 // Alte Daten loeschen und Neue zuweisen
894 STRING_RELEASE((STRING_TYPE *)mpData);
895 mpData = pNewData;
897 else
899 STRING_NEW((STRING_TYPE **)&mpData);
902 return *this;
905 // -----------------------------------------------------------------------
907 STRING& STRING::Fill( xub_StrLen nCount, STRCODE cFillChar )
909 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
911 if ( !nCount )
912 return *this;
914 // Ist nCount groesser wie der jetzige String, dann verlaengern
915 if ( nCount > mpData->mnLen )
917 // dann neuen String mit der neuen Laenge anlegen
918 STRINGDATA* pNewData = ImplAllocData( nCount );
919 STRING_RELEASE((STRING_TYPE *)mpData);
920 mpData = pNewData;
922 else
923 ImplCopyData();
925 STRCODE* pStr = mpData->maStr;
928 *pStr = cFillChar;
929 ++pStr,
930 --nCount;
932 while ( nCount );
934 return *this;
937 // -----------------------------------------------------------------------
939 STRING& STRING::Expand( xub_StrLen nCount, STRCODE cExpandChar )
941 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
943 // Muss der String erweitert werden
944 sal_Int32 nLen = mpData->mnLen;
945 if ( nCount <= nLen )
946 return *this;
948 // Neuen String anlegen
949 STRINGDATA* pNewData = ImplAllocData( nCount );
951 // Alten String kopieren
952 memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
954 // und initialisieren
955 STRCODE* pStr = pNewData->maStr;
956 pStr += nLen;
957 for (sal_Int32 i = nCount - nLen; i > 0; --i) {
958 *pStr++ = cExpandChar;
961 // Alte Daten loeschen und Neue zuweisen
962 STRING_RELEASE((STRING_TYPE *)mpData);
963 mpData = pNewData;
965 return *this;
968 // -----------------------------------------------------------------------
970 STRING& STRING::EraseLeadingChars( STRCODE c )
972 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
974 if ( mpData->maStr[0] != c )
975 return *this;
977 xub_StrLen nStart = 0;
978 while ( mpData->maStr[nStart] == c )
979 ++nStart;
981 return Erase( 0, nStart );
984 // -----------------------------------------------------------------------
986 STRING& STRING::EraseTrailingChars( STRCODE c )
988 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
990 sal_Int32 nEnd = mpData->mnLen;
991 while ( nEnd && (mpData->maStr[nEnd-1] == c) )
992 nEnd--;
994 if ( nEnd != mpData->mnLen )
995 Erase( static_cast< xub_StrLen >(nEnd) );
997 return *this;
1000 // -----------------------------------------------------------------------
1002 STRING& STRING::EraseLeadingAndTrailingChars( STRCODE c )
1004 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1006 xub_StrLen nStart = 0;
1007 while ( mpData->maStr[nStart] == c )
1008 ++nStart;
1009 if ( nStart )
1010 Erase( 0, nStart );
1012 sal_Int32 nEnd = mpData->mnLen;
1013 while ( nEnd && (mpData->maStr[nEnd-1] == c) )
1014 nEnd--;
1015 if ( nEnd != mpData->mnLen )
1016 Erase( static_cast< xub_StrLen >(nEnd) );
1018 return *this;
1021 // -----------------------------------------------------------------------
1023 STRING& STRING::EraseAllChars( STRCODE c )
1025 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1027 sal_Int32 nCount = 0;
1028 for (sal_Int32 i = 0; i < mpData->mnLen; ++i) {
1029 if ( mpData->maStr[i] == c )
1030 ++nCount;
1033 if ( nCount )
1035 if ( nCount == mpData->mnLen )
1037 STRING_NEW((STRING_TYPE **)&mpData);
1039 else
1041 // Neuen String anlegen
1042 STRINGDATA* pNewData = ImplAllocData( mpData->mnLen-nCount );
1044 // Alten String kopieren und initialisieren
1045 nCount = 0;
1046 for( xub_StrLen j = 0; j < mpData->mnLen; ++j )
1048 if ( mpData->maStr[j] != c )
1050 pNewData->maStr[nCount] = mpData->maStr[j];
1051 ++nCount;
1055 // Alte Daten loeschen und Neue zuweisen
1056 STRING_RELEASE((STRING_TYPE *)mpData);
1057 mpData = pNewData;
1061 return *this;
1064 // -----------------------------------------------------------------------
1066 STRING& STRING::Reverse()
1068 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1070 if ( !mpData->mnLen )
1071 return *this;
1073 // Daten kopieren, wenn noetig
1074 ImplCopyData();
1076 // Reverse
1077 sal_Int32 nCount = mpData->mnLen / 2;
1078 for ( sal_Int32 i = 0; i < nCount; ++i )
1080 STRCODE cTemp = mpData->maStr[i];
1081 mpData->maStr[i] = mpData->maStr[mpData->mnLen-i-1];
1082 mpData->maStr[mpData->mnLen-i-1] = cTemp;
1085 return *this;
1088 // -----------------------------------------------------------------------
1090 STRING& STRING::ToLowerAscii()
1092 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1094 sal_Int32 nIndex = 0;
1095 sal_Int32 nLen = mpData->mnLen;
1096 STRCODE* pStr = mpData->maStr;
1097 while ( nIndex < nLen )
1099 // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln
1100 if ( (*pStr >= 65) && (*pStr <= 90) )
1102 // Daten kopieren, wenn noetig
1103 pStr = ImplCopyStringData( pStr );
1104 *pStr += 32;
1107 ++pStr,
1108 ++nIndex;
1111 return *this;
1114 // -----------------------------------------------------------------------
1116 STRING& STRING::ToUpperAscii()
1118 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1120 sal_Int32 nIndex = 0;
1121 sal_Int32 nLen = mpData->mnLen;
1122 STRCODE* pStr = mpData->maStr;
1123 while ( nIndex < nLen )
1125 // Ist das Zeichen zwischen 'a' und 'z' dann umwandeln
1126 if ( (*pStr >= 97) && (*pStr <= 122) )
1128 // Daten kopieren, wenn noetig
1129 pStr = ImplCopyStringData( pStr );
1130 *pStr -= 32;
1133 ++pStr,
1134 ++nIndex;
1137 return *this;
1140 // -----------------------------------------------------------------------
1142 STRING& STRING::ConvertLineEnd( LineEnd eLineEnd )
1144 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1146 // Zeilenumbrueche ermitteln und neue Laenge berechnen
1147 BOOL bConvert = FALSE; // Muss konvertiert werden
1148 const STRCODE* pStr = mpData->maStr; // damit es schneller geht
1149 xub_StrLen nLineEndLen = (eLineEnd == LINEEND_CRLF) ? 2 : 1;
1150 xub_StrLen nLen = 0; // Ziel-Laenge
1151 xub_StrLen i = 0; // Source-Zaehler
1153 while ( i < mpData->mnLen )
1155 // Bei \r oder \n gibt es neuen Zeilenumbruch
1156 if ( (pStr[i] == _CR) || (pStr[i] == _LF) )
1158 nLen = nLen + nLineEndLen;
1160 // Wenn schon gesetzt, dann brauchen wir keine aufwendige Abfrage
1161 if ( !bConvert )
1163 // Muessen wir Konvertieren
1164 if ( ((eLineEnd != LINEEND_LF) && (pStr[i] == _LF)) ||
1165 ((eLineEnd == LINEEND_CRLF) && (pStr[i+1] != _LF)) ||
1166 ((eLineEnd == LINEEND_LF) &&
1167 ((pStr[i] == _CR) || (pStr[i+1] == _CR))) ||
1168 ((eLineEnd == LINEEND_CR) &&
1169 ((pStr[i] == _LF) || (pStr[i+1] == _LF))) )
1170 bConvert = TRUE;
1173 // \r\n oder \n\r, dann Zeichen ueberspringen
1174 if ( ((pStr[i+1] == _CR) || (pStr[i+1] == _LF)) &&
1175 (pStr[i] != pStr[i+1]) )
1176 ++i;
1178 else
1179 ++nLen;
1180 ++i;
1182 // Wenn String zu lang, dann konvertieren wir nicht
1183 if ( nLen >= STRING_MAXLEN )
1184 return *this;
1187 // Zeilenumbrueche konvertieren
1188 if ( bConvert )
1190 // Neuen String anlegen
1191 STRINGDATA* pNewData = ImplAllocData( nLen );
1192 xub_StrLen j = 0;
1193 i = 0;
1194 while ( i < mpData->mnLen )
1196 // Bei \r oder \n gibt es neuen Zeilenumbruch
1197 if ( (pStr[i] == _CR) || (pStr[i] == _LF) )
1199 if ( eLineEnd == LINEEND_CRLF )
1201 pNewData->maStr[j] = _CR;
1202 pNewData->maStr[j+1] = _LF;
1203 j += 2;
1205 else
1207 if ( eLineEnd == LINEEND_CR )
1208 pNewData->maStr[j] = _CR;
1209 else
1210 pNewData->maStr[j] = _LF;
1211 ++j;
1214 if ( ((pStr[i+1] == _CR) || (pStr[i+1] == _LF)) &&
1215 (pStr[i] != pStr[i+1]) )
1216 ++i;
1218 else
1220 pNewData->maStr[j] = mpData->maStr[i];
1221 ++j;
1224 ++i;
1227 // Alte Daten loeschen und Neue zuweisen
1228 STRING_RELEASE((STRING_TYPE *)mpData);
1229 mpData = pNewData;
1232 return *this;
1235 // -----------------------------------------------------------------------
1237 StringCompare STRING::CompareTo( const STRING& rStr, xub_StrLen nLen ) const
1239 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1240 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1242 // Auf Gleichheit der Pointer testen
1243 if ( mpData == rStr.mpData )
1244 return COMPARE_EQUAL;
1246 // Maximale Laenge ermitteln
1247 if ( mpData->mnLen < nLen )
1248 nLen = static_cast< xub_StrLen >(mpData->mnLen+1);
1249 if ( rStr.mpData->mnLen < nLen )
1250 nLen = static_cast< xub_StrLen >(rStr.mpData->mnLen+1);
1252 // String vergleichen
1253 sal_Int32 nCompare = ImplStringCompareWithoutZero( mpData->maStr, rStr.mpData->maStr, nLen );
1255 // Rueckgabewert anpassen
1256 if ( nCompare == 0 )
1257 return COMPARE_EQUAL;
1258 else if ( nCompare < 0 )
1259 return COMPARE_LESS;
1260 else
1261 return COMPARE_GREATER;
1264 // -----------------------------------------------------------------------
1266 StringCompare STRING::CompareTo( const STRCODE* pCharStr, xub_StrLen nLen ) const
1268 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1270 // String vergleichen
1271 sal_Int32 nCompare = ImplStringCompare( mpData->maStr, pCharStr, nLen );
1273 // Rueckgabewert anpassen
1274 if ( nCompare == 0 )
1275 return COMPARE_EQUAL;
1276 else if ( nCompare < 0 )
1277 return COMPARE_LESS;
1278 else
1279 return COMPARE_GREATER;
1282 // -----------------------------------------------------------------------
1284 StringCompare STRING::CompareIgnoreCaseToAscii( const STRING& rStr,
1285 xub_StrLen nLen ) const
1287 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1288 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1290 // Auf Gleichheit der Pointer testen
1291 if ( mpData == rStr.mpData )
1292 return COMPARE_EQUAL;
1294 // Maximale Laenge ermitteln
1295 if ( mpData->mnLen < nLen )
1296 nLen = static_cast< xub_StrLen >(mpData->mnLen+1);
1297 if ( rStr.mpData->mnLen < nLen )
1298 nLen = static_cast< xub_StrLen >(rStr.mpData->mnLen+1);
1300 // String vergleichen
1301 sal_Int32 nCompare = ImplStringICompareWithoutZero( mpData->maStr, rStr.mpData->maStr, nLen );
1303 // Rueckgabewert anpassen
1304 if ( nCompare == 0 )
1305 return COMPARE_EQUAL;
1306 else if ( nCompare < 0 )
1307 return COMPARE_LESS;
1308 else
1309 return COMPARE_GREATER;
1312 // -----------------------------------------------------------------------
1314 StringCompare STRING::CompareIgnoreCaseToAscii( const STRCODE* pCharStr,
1315 xub_StrLen nLen ) const
1317 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1319 // String vergleichen
1320 sal_Int32 nCompare = ImplStringICompare( mpData->maStr, pCharStr, nLen );
1322 // Rueckgabewert anpassen
1323 if ( nCompare == 0 )
1324 return COMPARE_EQUAL;
1325 else if ( nCompare < 0 )
1326 return COMPARE_LESS;
1327 else
1328 return COMPARE_GREATER;
1331 // -----------------------------------------------------------------------
1333 BOOL STRING::Equals( const STRING& rStr ) const
1335 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1336 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1338 // Sind die Daten gleich
1339 if ( mpData == rStr.mpData )
1340 return TRUE;
1342 // Gleiche Laenge
1343 if ( mpData->mnLen != rStr.mpData->mnLen )
1344 return FALSE;
1346 // String vergleichen
1347 return (ImplStringCompareWithoutZero( mpData->maStr, rStr.mpData->maStr, mpData->mnLen ) == 0);
1350 // -----------------------------------------------------------------------
1352 BOOL STRING::Equals( const STRCODE* pCharStr ) const
1354 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1356 return (ImplStringCompare( mpData->maStr, pCharStr ) == 0);
1359 // -----------------------------------------------------------------------
1361 BOOL STRING::EqualsIgnoreCaseAscii( const STRING& rStr ) const
1363 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1364 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1366 // Sind die Daten gleich
1367 if ( mpData == rStr.mpData )
1368 return TRUE;
1370 // Gleiche Laenge
1371 if ( mpData->mnLen != rStr.mpData->mnLen )
1372 return FALSE;
1374 // String vergleichen
1375 return (ImplStringICompareWithoutZero( mpData->maStr, rStr.mpData->maStr, mpData->mnLen ) == 0);
1378 // -----------------------------------------------------------------------
1380 BOOL STRING::EqualsIgnoreCaseAscii( const STRCODE* pCharStr ) const
1382 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1384 return (ImplStringICompare( mpData->maStr, pCharStr ) == 0);
1387 // -----------------------------------------------------------------------
1389 BOOL STRING::Equals( const STRING& rStr, xub_StrLen nIndex, xub_StrLen nLen ) const
1391 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1392 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1394 // Are there enough codes for comparing?
1395 if ( nIndex > mpData->mnLen )
1396 return (rStr.mpData->mnLen == 0);
1397 sal_Int32 nMaxLen = mpData->mnLen-nIndex;
1398 if ( nMaxLen < nLen )
1400 if ( rStr.mpData->mnLen != nMaxLen )
1401 return FALSE;
1402 nLen = static_cast< xub_StrLen >(nMaxLen);
1405 // String vergleichen
1406 return (ImplStringCompareWithoutZero( mpData->maStr+nIndex, rStr.mpData->maStr, nLen ) == 0);
1409 // -----------------------------------------------------------------------
1411 BOOL STRING::Equals( const STRCODE* pCharStr, xub_StrLen nIndex, xub_StrLen nLen ) const
1413 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1415 // Are there enough codes for comparing?
1416 if ( nIndex > mpData->mnLen )
1417 return (*pCharStr == 0);
1419 return (ImplStringCompare( mpData->maStr+nIndex, pCharStr, nLen ) == 0);
1422 // -----------------------------------------------------------------------
1424 BOOL STRING::EqualsIgnoreCaseAscii( const STRING& rStr, xub_StrLen nIndex, xub_StrLen nLen ) const
1426 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1427 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1429 // Are there enough codes for comparing?
1430 if ( nIndex > mpData->mnLen )
1431 return (rStr.mpData->mnLen == 0);
1432 sal_Int32 nMaxLen = mpData->mnLen-nIndex;
1433 if ( nMaxLen < nLen )
1435 if ( rStr.mpData->mnLen != nMaxLen )
1436 return FALSE;
1437 nLen = static_cast< xub_StrLen >(nMaxLen);
1440 // String vergleichen
1441 return (ImplStringICompareWithoutZero( mpData->maStr+nIndex, rStr.mpData->maStr, nLen ) == 0);
1444 // -----------------------------------------------------------------------
1446 BOOL STRING::EqualsIgnoreCaseAscii( const STRCODE* pCharStr, xub_StrLen nIndex, xub_StrLen nLen ) const
1448 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1450 // Are there enough codes for comparing?
1451 if ( nIndex > mpData->mnLen )
1452 return (*pCharStr == 0);
1454 return (ImplStringICompare( mpData->maStr+nIndex, pCharStr, nLen ) == 0);
1457 // -----------------------------------------------------------------------
1459 xub_StrLen STRING::Match( const STRING& rStr ) const
1461 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1462 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1464 // Ist dieser String leer
1465 if ( !mpData->mnLen )
1466 return STRING_MATCH;
1468 // Suche bis Stringende nach dem ersten nicht uebereinstimmenden Zeichen
1469 const STRCODE* pStr1 = mpData->maStr;
1470 const STRCODE* pStr2 = rStr.mpData->maStr;
1471 xub_StrLen i = 0;
1472 while ( i < mpData->mnLen )
1474 // Stimmt das Zeichen nicht ueberein, dann abbrechen
1475 if ( *pStr1 != *pStr2 )
1476 return i;
1477 ++pStr1,
1478 ++pStr2,
1479 ++i;
1482 return STRING_MATCH;
1485 // -----------------------------------------------------------------------
1487 xub_StrLen STRING::Match( const STRCODE* pCharStr ) const
1489 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1491 // Ist dieser String leer
1492 if ( !mpData->mnLen )
1493 return STRING_MATCH;
1495 // Suche bis Stringende nach dem ersten nicht uebereinstimmenden Zeichen
1496 const STRCODE* pStr = mpData->maStr;
1497 xub_StrLen i = 0;
1498 while ( i < mpData->mnLen )
1500 // Stimmt das Zeichen nicht ueberein, dann abbrechen
1501 if ( *pStr != *pCharStr )
1502 return i;
1503 ++pStr,
1504 ++pCharStr,
1505 ++i;
1508 return STRING_MATCH;
1511 // -----------------------------------------------------------------------
1513 xub_StrLen STRING::Search( STRCODE c, xub_StrLen nIndex ) const
1515 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1517 sal_Int32 nLen = mpData->mnLen;
1518 const STRCODE* pStr = mpData->maStr;
1519 pStr += nIndex;
1520 while ( nIndex < nLen )
1522 if ( *pStr == c )
1523 return nIndex;
1524 ++pStr,
1525 ++nIndex;
1528 return STRING_NOTFOUND;
1531 // -----------------------------------------------------------------------
1533 xub_StrLen STRING::Search( const STRING& rStr, xub_StrLen nIndex ) const
1535 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1536 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1538 sal_Int32 nLen = mpData->mnLen;
1539 sal_Int32 nStrLen = rStr.mpData->mnLen;
1541 // Falls die Laenge des uebergebenen Strings 0 ist oder der Index
1542 // hinter dem String liegt, dann wurde der String nicht gefunden
1543 if ( !nStrLen || (nIndex >= nLen) )
1544 return STRING_NOTFOUND;
1546 const STRCODE* pStr1 = mpData->maStr;
1547 pStr1 += nIndex;
1549 if ( nStrLen == 1 )
1551 STRCODE cSearch = rStr.mpData->maStr[0];
1552 while ( nIndex < nLen )
1554 if ( *pStr1 == cSearch )
1555 return nIndex;
1556 ++pStr1,
1557 ++nIndex;
1560 else
1562 const STRCODE* pStr2 = rStr.mpData->maStr;
1564 // Nur innerhalb des Strings suchen
1565 while ( nLen - nIndex >= nStrLen )
1567 // Stimmt der String ueberein
1568 if ( ImplStringCompareWithoutZero( pStr1, pStr2, nStrLen ) == 0 )
1569 return nIndex;
1570 ++pStr1,
1571 ++nIndex;
1575 return STRING_NOTFOUND;
1578 // -----------------------------------------------------------------------
1580 xub_StrLen STRING::Search( const STRCODE* pCharStr, xub_StrLen nIndex ) const
1582 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1584 sal_Int32 nLen = mpData->mnLen;
1585 xub_StrLen nStrLen = ImplStringLen( pCharStr );
1587 // Falls die Laenge des uebergebenen Strings 0 ist oder der Index
1588 // hinter dem String liegt, dann wurde der String nicht gefunden
1589 if ( !nStrLen || (nIndex >= nLen) )
1590 return STRING_NOTFOUND;
1592 const STRCODE* pStr = mpData->maStr;
1593 pStr += nIndex;
1595 if ( nStrLen == 1 )
1597 STRCODE cSearch = *pCharStr;
1598 while ( nIndex < nLen )
1600 if ( *pStr == cSearch )
1601 return nIndex;
1602 ++pStr,
1603 ++nIndex;
1606 else
1608 // Nur innerhalb des Strings suchen
1609 while ( nLen - nIndex >= nStrLen )
1611 // Stimmt der String ueberein
1612 if ( ImplStringCompareWithoutZero( pStr, pCharStr, nStrLen ) == 0 )
1613 return nIndex;
1614 ++pStr,
1615 ++nIndex;
1619 return STRING_NOTFOUND;
1622 // -----------------------------------------------------------------------
1624 xub_StrLen STRING::SearchBackward( STRCODE c, xub_StrLen nIndex ) const
1626 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1628 if ( nIndex > mpData->mnLen )
1629 nIndex = (xub_StrLen)mpData->mnLen;
1631 const STRCODE* pStr = mpData->maStr;
1632 pStr += nIndex;
1634 while ( nIndex )
1636 nIndex--;
1637 pStr--;
1638 if ( *pStr == c )
1639 return nIndex;
1642 return STRING_NOTFOUND;
1645 // -----------------------------------------------------------------------
1647 xub_StrLen STRING::SearchChar( const STRCODE* pChars, xub_StrLen nIndex ) const
1649 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1651 sal_Int32 nLen = mpData->mnLen;
1652 const STRCODE* pStr = mpData->maStr;
1653 pStr += nIndex;
1654 while ( nIndex < nLen )
1656 STRCODE c = *pStr;
1657 const STRCODE* pCompStr = pChars;
1658 while ( *pCompStr )
1660 if ( *pCompStr == c )
1661 return nIndex;
1662 ++pCompStr;
1664 ++pStr,
1665 ++nIndex;
1668 return STRING_NOTFOUND;
1671 // -----------------------------------------------------------------------
1673 xub_StrLen STRING::SearchCharBackward( const STRCODE* pChars, xub_StrLen nIndex ) const
1675 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1677 if ( nIndex > mpData->mnLen )
1678 nIndex = (xub_StrLen)mpData->mnLen;
1680 const STRCODE* pStr = mpData->maStr;
1681 pStr += nIndex;
1683 while ( nIndex )
1685 nIndex--;
1686 pStr--;
1688 STRCODE c =*pStr;
1689 const STRCODE* pCompStr = pChars;
1690 while ( *pCompStr )
1692 if ( *pCompStr == c )
1693 return nIndex;
1694 ++pCompStr;
1698 return STRING_NOTFOUND;
1701 // -----------------------------------------------------------------------
1703 xub_StrLen STRING::SearchAndReplace( STRCODE c, STRCODE cRep, xub_StrLen nIndex )
1705 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1707 sal_Int32 nLen = mpData->mnLen;
1708 const STRCODE* pStr = mpData->maStr;
1709 pStr += nIndex;
1710 while ( nIndex < nLen )
1712 if ( *pStr == c )
1714 ImplCopyData();
1715 mpData->maStr[nIndex] = cRep;
1716 return nIndex;
1718 ++pStr,
1719 ++nIndex;
1722 return STRING_NOTFOUND;
1725 // -----------------------------------------------------------------------
1727 xub_StrLen STRING::SearchAndReplace( const STRING& rStr, const STRING& rRepStr,
1728 xub_StrLen nIndex )
1730 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1731 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1732 DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING );
1734 xub_StrLen nSPos = Search( rStr, nIndex );
1735 if ( nSPos != STRING_NOTFOUND )
1736 Replace( nSPos, rStr.Len(), rRepStr );
1738 return nSPos;
1741 // -----------------------------------------------------------------------
1743 xub_StrLen STRING::SearchAndReplace( const STRCODE* pCharStr, const STRING& rRepStr,
1744 xub_StrLen nIndex )
1746 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1747 DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING );
1749 xub_StrLen nSPos = Search( pCharStr, nIndex );
1750 if ( nSPos != STRING_NOTFOUND )
1751 Replace( nSPos, ImplStringLen( pCharStr ), rRepStr );
1753 return nSPos;
1756 // -----------------------------------------------------------------------
1758 void STRING::SearchAndReplaceAll( STRCODE c, STRCODE cRep )
1760 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1762 sal_Int32 nLen = mpData->mnLen;
1763 const STRCODE* pStr = mpData->maStr;
1764 sal_Int32 nIndex = 0;
1765 while ( nIndex < nLen )
1767 if ( *pStr == c )
1769 ImplCopyData();
1770 mpData->maStr[nIndex] = cRep;
1772 ++pStr,
1773 ++nIndex;
1777 // -----------------------------------------------------------------------
1779 void STRING::SearchAndReplaceAll( const STRCODE* pCharStr, const STRING& rRepStr )
1781 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1782 DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING );
1784 xub_StrLen nCharLen = ImplStringLen( pCharStr );
1785 xub_StrLen nSPos = Search( pCharStr, 0 );
1786 while ( nSPos != STRING_NOTFOUND )
1788 Replace( nSPos, nCharLen, rRepStr );
1789 nSPos = nSPos + rRepStr.Len();
1790 nSPos = Search( pCharStr, nSPos );
1794 // -----------------------------------------------------------------------
1796 void STRING::SearchAndReplaceAll( const STRING& rStr, const STRING& rRepStr )
1798 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1799 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1800 DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING );
1802 xub_StrLen nSPos = Search( rStr, 0 );
1803 while ( nSPos != STRING_NOTFOUND )
1805 Replace( nSPos, rStr.Len(), rRepStr );
1806 nSPos = nSPos + rRepStr.Len();
1807 nSPos = Search( rStr, nSPos );
1811 // -----------------------------------------------------------------------
1813 xub_StrLen STRING::GetTokenCount( STRCODE cTok ) const
1815 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1817 // Leerer String: TokenCount per Definition 0
1818 if ( !mpData->mnLen )
1819 return 0;
1821 xub_StrLen nTokCount = 1;
1822 sal_Int32 nLen = mpData->mnLen;
1823 const STRCODE* pStr = mpData->maStr;
1824 sal_Int32 nIndex = 0;
1825 while ( nIndex < nLen )
1827 // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount
1828 if ( *pStr == cTok )
1829 ++nTokCount;
1830 ++pStr,
1831 ++nIndex;
1834 return nTokCount;
1837 // -----------------------------------------------------------------------
1839 void STRING::SetToken( xub_StrLen nToken, STRCODE cTok, const STRING& rStr,
1840 xub_StrLen nIndex )
1842 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1843 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING );
1845 const STRCODE* pStr = mpData->maStr;
1846 xub_StrLen nLen = (xub_StrLen)mpData->mnLen;
1847 xub_StrLen nTok = 0;
1848 xub_StrLen nFirstChar = nIndex;
1849 xub_StrLen i = nFirstChar;
1851 // Bestimme die Token-Position und Laenge
1852 pStr += i;
1853 while ( i < nLen )
1855 // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount
1856 if ( *pStr == cTok )
1858 ++nTok;
1860 if ( nTok == nToken )
1861 nFirstChar = i+1;
1862 else
1864 if ( nTok > nToken )
1865 break;
1869 ++pStr,
1870 ++i;
1873 if ( nTok >= nToken )
1874 Replace( nFirstChar, i-nFirstChar, rStr );
1877 // -----------------------------------------------------------------------
1879 STRING STRING::GetToken( xub_StrLen nToken, STRCODE cTok, xub_StrLen& rIndex ) const
1881 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1883 const STRCODE* pStr = mpData->maStr;
1884 xub_StrLen nLen = (xub_StrLen)mpData->mnLen;
1885 xub_StrLen nTok = 0;
1886 xub_StrLen nFirstChar = rIndex;
1887 xub_StrLen i = nFirstChar;
1889 // Bestimme die Token-Position und Laenge
1890 pStr += i;
1891 while ( i < nLen )
1893 // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount
1894 if ( *pStr == cTok )
1896 ++nTok;
1898 if ( nTok == nToken )
1899 nFirstChar = i+1;
1900 else
1902 if ( nTok > nToken )
1903 break;
1907 ++pStr,
1908 ++i;
1911 if ( nTok >= nToken )
1913 if ( i < nLen )
1914 rIndex = i+1;
1915 else
1916 rIndex = STRING_NOTFOUND;
1917 return Copy( nFirstChar, i-nFirstChar );
1919 else
1921 rIndex = STRING_NOTFOUND;
1922 return STRING();
1926 // -----------------------------------------------------------------------
1928 xub_StrLen STRING::GetQuotedTokenCount( const STRING& rQuotedPairs, STRCODE cTok ) const
1930 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1931 DBG_CHKOBJ( &rQuotedPairs, STRING, DBGCHECKSTRING );
1932 DBG_ASSERT( !(rQuotedPairs.Len()%2), "String::GetQuotedTokenCount() - QuotedString%2 != 0" );
1933 DBG_ASSERT( rQuotedPairs.Search(cTok) == STRING_NOTFOUND, "String::GetQuotedTokenCount() - cTok in QuotedString" );
1935 // Leerer String: TokenCount per Definition 0
1936 if ( !mpData->mnLen )
1937 return 0;
1939 xub_StrLen nTokCount = 1;
1940 sal_Int32 nLen = mpData->mnLen;
1941 xub_StrLen nQuotedLen = rQuotedPairs.Len();
1942 STRCODE cQuotedEndChar = 0;
1943 const STRCODE* pQuotedStr = rQuotedPairs.mpData->maStr;
1944 const STRCODE* pStr = mpData->maStr;
1945 sal_Int32 nIndex = 0;
1946 while ( nIndex < nLen )
1948 STRCODE c = *pStr;
1949 if ( cQuotedEndChar )
1951 // Ende des Quotes erreicht ?
1952 if ( c == cQuotedEndChar )
1953 cQuotedEndChar = 0;
1955 else
1957 // Ist das Zeichen ein Quote-Anfang-Zeichen ?
1958 xub_StrLen nQuoteIndex = 0;
1959 while ( nQuoteIndex < nQuotedLen )
1961 if ( pQuotedStr[nQuoteIndex] == c )
1963 cQuotedEndChar = pQuotedStr[nQuoteIndex+1];
1964 break;
1966 else
1967 nQuoteIndex += 2;
1970 // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount
1971 if ( c == cTok )
1972 ++nTokCount;
1975 ++pStr,
1976 ++nIndex;
1979 return nTokCount;
1982 // -----------------------------------------------------------------------
1984 STRING STRING::GetQuotedToken( xub_StrLen nToken, const STRING& rQuotedPairs,
1985 STRCODE cTok, xub_StrLen& rIndex ) const
1987 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
1988 DBG_CHKOBJ( &rQuotedPairs, STRING, DBGCHECKSTRING );
1989 DBG_ASSERT( !(rQuotedPairs.Len()%2), "String::GetQuotedToken() - QuotedString%2 != 0" );
1990 DBG_ASSERT( rQuotedPairs.Search(cTok) == STRING_NOTFOUND, "String::GetQuotedToken() - cTok in QuotedString" );
1992 const STRCODE* pStr = mpData->maStr;
1993 const STRCODE* pQuotedStr = rQuotedPairs.mpData->maStr;
1994 STRCODE cQuotedEndChar = 0;
1995 xub_StrLen nQuotedLen = rQuotedPairs.Len();
1996 xub_StrLen nLen = (xub_StrLen)mpData->mnLen;
1997 xub_StrLen nTok = 0;
1998 xub_StrLen nFirstChar = rIndex;
1999 xub_StrLen i = nFirstChar;
2001 // Bestimme die Token-Position und Laenge
2002 pStr += i;
2003 while ( i < nLen )
2005 STRCODE c = *pStr;
2006 if ( cQuotedEndChar )
2008 // Ende des Quotes erreicht ?
2009 if ( c == cQuotedEndChar )
2010 cQuotedEndChar = 0;
2012 else
2014 // Ist das Zeichen ein Quote-Anfang-Zeichen ?
2015 xub_StrLen nQuoteIndex = 0;
2016 while ( nQuoteIndex < nQuotedLen )
2018 if ( pQuotedStr[nQuoteIndex] == c )
2020 cQuotedEndChar = pQuotedStr[nQuoteIndex+1];
2021 break;
2023 else
2024 nQuoteIndex += 2;
2027 // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount
2028 if ( c == cTok )
2030 ++nTok;
2032 if ( nTok == nToken )
2033 nFirstChar = i+1;
2034 else
2036 if ( nTok > nToken )
2037 break;
2042 ++pStr,
2043 ++i;
2046 if ( nTok >= nToken )
2048 if ( i < nLen )
2049 rIndex = i+1;
2050 else
2051 rIndex = STRING_NOTFOUND;
2052 return Copy( nFirstChar, i-nFirstChar );
2054 else
2056 rIndex = STRING_NOTFOUND;
2057 return STRING();
2061 // -----------------------------------------------------------------------
2063 STRCODE* STRING::GetBufferAccess()
2065 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
2067 // Daten kopieren, wenn noetig
2068 if ( mpData->mnLen )
2069 ImplCopyData();
2071 // Pointer auf den String zurueckgeben
2072 return mpData->maStr;
2075 // -----------------------------------------------------------------------
2077 void STRING::ReleaseBufferAccess( xub_StrLen nLen )
2079 // Hier ohne Funktionstest, da String nicht konsistent
2080 DBG_CHKTHIS( STRING, NULL );
2081 DBG_ASSERT( mpData->mnRefCount == 1, "String::ReleaseCharStr() called for String with RefCount" );
2083 if ( nLen > mpData->mnLen )
2084 nLen = ImplStringLen( mpData->maStr );
2085 OSL_ASSERT(nLen <= mpData->mnLen);
2086 if ( !nLen )
2088 STRING_NEW((STRING_TYPE **)&mpData);
2090 // Bei mehr als 8 Zeichen unterschied, kuerzen wir den Buffer
2091 else if ( mpData->mnLen - nLen > 8 )
2093 STRINGDATA* pNewData = ImplAllocData( nLen );
2094 memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) );
2095 STRING_RELEASE((STRING_TYPE *)mpData);
2096 mpData = pNewData;
2098 else
2099 mpData->mnLen = nLen;
2102 // -----------------------------------------------------------------------
2104 STRCODE* STRING::AllocBuffer( xub_StrLen nLen )
2106 DBG_CHKTHIS( STRING, DBGCHECKSTRING );
2108 STRING_RELEASE((STRING_TYPE *)mpData);
2109 if ( nLen )
2110 mpData = ImplAllocData( nLen );
2111 else
2113 mpData = NULL;
2114 STRING_NEW((STRING_TYPE **)&mpData);
2117 return mpData->maStr;