1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: strimp.cxx,v $
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
)
38 while ( ((nRet
= ((sal_Int32
)((STRCODEU
)*pStr1
))-((sal_Int32
)((STRCODEU
)*pStr2
))) == 0) &&
48 // -----------------------------------------------------------------------
50 static sal_Int32
ImplStringCompare( const STRCODE
* pStr1
, const STRCODE
* pStr2
,
55 ((nRet
= ((sal_Int32
)((STRCODEU
)*pStr1
))-((sal_Int32
)((STRCODEU
)*pStr2
))) == 0) &&
66 // -----------------------------------------------------------------------
68 static sal_Int32
ImplStringCompareWithoutZero( const STRCODE
* pStr1
, const STRCODE
* pStr2
,
73 ((nRet
= ((sal_Int32
)((STRCODEU
)*pStr1
))-((sal_Int32
)((STRCODEU
)*pStr2
))) == 0) )
83 // -----------------------------------------------------------------------
85 static sal_Int32
ImplStringICompare( const STRCODE
* pStr1
, const STRCODE
* pStr2
)
92 // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln
95 if ( (c1
>= 65) && (c1
<= 90) )
97 if ( (c2
>= 65) && (c2
<= 90) )
99 nRet
= ((sal_Int32
)((STRCODEU
)c1
))-((sal_Int32
)((STRCODEU
)c2
));
111 // -----------------------------------------------------------------------
113 static sal_Int32
ImplStringICompare( const STRCODE
* pStr1
, const STRCODE
* pStr2
,
124 // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln
127 if ( (c1
>= 65) && (c1
<= 90) )
129 if ( (c2
>= 65) && (c2
<= 90) )
131 nRet
= ((sal_Int32
)((STRCODEU
)c1
))-((sal_Int32
)((STRCODEU
)c2
));
144 // -----------------------------------------------------------------------
146 static sal_Int32
ImplStringICompareWithoutZero( const STRCODE
* pStr1
, const STRCODE
* pStr2
,
157 // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln
160 if ( (c1
>= 65) && (c1
<= 90) )
162 if ( (c2
>= 65) && (c2
<= 90) )
164 nRet
= ((sal_Int32
)((STRCODEU
)c1
))-((sal_Int32
)((STRCODEU
)c2
));
175 // =======================================================================
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";
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;
197 pData
->maStr
[nLen
] = 0;
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
);
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
;
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
;
250 // =======================================================================
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
)
278 DBG_CTOR( STRING
, DBGCHECKSTRING
);
279 DBG_CHKOBJ( &rStr
, STRING
, DBGCHECKSTRING
);
281 // Stringlaenge ermitteln
282 if ( nPos
> rStr
.mpData
->mnLen
)
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
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
;
303 // Verwaltungsdaten anlegen und String kopieren
304 mpData
= ImplAllocData( nLen
);
305 memcpy( mpData
->maStr
, rStr
.mpData
->maStr
+nPos
, nLen
*sizeof( STRCODE
) );
310 STRING_NEW((STRING_TYPE
**)&mpData
);
314 // -----------------------------------------------------------------------
316 STRING::STRING( const STRCODE
* pCharStr
)
319 DBG_CTOR( STRING
, DBGCHECKSTRING
);
321 // Stringlaenge ermitteln
322 // Bei diesem Ctor darf NULL uebergeben werden
325 nLen
= ImplStringLen( pCharStr
);
329 // Ist es kein leerer String
332 // Verwaltungsdaten anlegen und String kopieren
333 mpData
= ImplAllocData( nLen
);
334 memcpy( mpData
->maStr
, pCharStr
, nLen
*sizeof( STRCODE
) );
338 STRING_NEW((STRING_TYPE
**)&mpData
);
342 // -----------------------------------------------------------------------
344 STRING::STRING( const STRCODE
* pCharStr
, xub_StrLen nLen
)
347 DBG_CTOR( STRING
, DBGCHECKSTRING
);
348 DBG_ASSERT( pCharStr
, "String::String() - pCharStr is NULL" );
350 if ( nLen
== STRING_LEN
)
351 nLen
= ImplStringLen( pCharStr
);
356 for ( xub_StrLen i
= 0; i
< nLen
; i
++ )
360 DBG_ERROR( "String::String() : nLen is wrong" );
366 // Ist es kein leerer String
369 // Verwaltungsdaten anlegen und String kopieren
370 mpData
= ImplAllocData( nLen
);
371 memcpy( mpData
->maStr
, pCharStr
, nLen
*sizeof( STRCODE
) );
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 // -----------------------------------------------------------------------
395 DBG_DTOR( STRING
, DBGCHECKSTRING
);
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
;
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
);
426 STRING_NEW((STRING_TYPE
**)&mpData
);
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
) );
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
) );
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
);
460 for ( xub_StrLen i
= 0; i
< nLen
; i
++ )
464 DBG_ERROR( "String::Assign() : nLen is wrong" );
472 STRING_NEW((STRING_TYPE
**)&mpData
);
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
) );
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
) );
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
;
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
;
518 STRING_ACQUIRE((STRING_TYPE
*)rStr
.mpData
);
519 STRING_RELEASE((STRING_TYPE
*)mpData
);
520 mpData
= rStr
.mpData
;
524 // Ueberlauf abfangen
525 sal_Int32 nCopyLen
= ImplGetCopyLen( nLen
, rStr
.mpData
->mnLen
);
527 // Ist der uebergebene String kein Leerstring
530 // Neue Datenstruktur und neuen String erzeugen
531 STRINGDATA
* pNewData
= ImplAllocData( nLen
+nCopyLen
);
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
);
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
563 // Neue Datenstruktur und neuen String erzeugen
564 STRINGDATA
* pNewData
= ImplAllocData( nLen
+nCopyLen
);
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
);
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
);
591 for ( xub_StrLen i
= 0; i
< nCharLen
; i
++ )
595 DBG_ERROR( "String::Append() : nLen is wrong" );
601 // Ueberlauf abfangen
602 sal_Int32 nLen
= mpData
->mnLen
;
603 sal_Int32 nCopyLen
= ImplGetCopyLen( nLen
, nCharLen
);
605 // Ist es kein leerer String
608 // Neue Datenstruktur und neuen String erzeugen
609 STRINGDATA
* pNewData
= ImplAllocData( nLen
+nCopyLen
);
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
);
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 );
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
);
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
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
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
);
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
);
694 // -----------------------------------------------------------------------
696 STRING
& STRING::Insert( const STRING
& rStr
, xub_StrLen nPos
, xub_StrLen nLen
,
699 DBG_CHKTHIS( STRING
, DBGCHECKSTRING
);
700 DBG_CHKOBJ( &rStr
, STRING
, DBGCHECKSTRING
);
702 // Stringlaenge ermitteln
703 if ( nPos
> rStr
.mpData
->mnLen
)
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
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
);
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
);
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
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
);
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
);
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
) )
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 );
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
);
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
)
821 // Ist es eine Zuweisung
822 if ( (nIndex
== 0) && (nCount
>= mpData
->mnLen
) )
829 sal_Int32 nStrLen
= rStr
.mpData
->mnLen
;
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
);
839 return Insert( rStr
, nIndex
);
841 // Reicht eine zeichenweise Zuweisung
842 if ( nCount
== nStrLen
)
845 memcpy( mpData
->maStr
+nIndex
, rStr
.mpData
->maStr
, nCount
*sizeof( STRCODE
) );
849 // Ueberlauf abfangen
850 nStrLen
= ImplGetCopyLen( mpData
->mnLen
-nCount
, nStrLen
);
852 // Neue Daten anlegen
853 STRINGDATA
* pNewData
= ImplAllocData( mpData
->mnLen
-nCount
+nStrLen
);
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
);
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
)
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
);
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
);
899 STRING_NEW((STRING_TYPE
**)&mpData
);
905 // -----------------------------------------------------------------------
907 STRING
& STRING::Fill( xub_StrLen nCount
, STRCODE cFillChar
)
909 DBG_CHKTHIS( STRING
, DBGCHECKSTRING
);
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
);
925 STRCODE
* pStr
= mpData
->maStr
;
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
)
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
;
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
);
968 // -----------------------------------------------------------------------
970 STRING
& STRING::EraseLeadingChars( STRCODE c
)
972 DBG_CHKTHIS( STRING
, DBGCHECKSTRING
);
974 if ( mpData
->maStr
[0] != c
)
977 xub_StrLen nStart
= 0;
978 while ( mpData
->maStr
[nStart
] == c
)
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
) )
994 if ( nEnd
!= mpData
->mnLen
)
995 Erase( static_cast< xub_StrLen
>(nEnd
) );
1000 // -----------------------------------------------------------------------
1002 STRING
& STRING::EraseLeadingAndTrailingChars( STRCODE c
)
1004 DBG_CHKTHIS( STRING
, DBGCHECKSTRING
);
1006 xub_StrLen nStart
= 0;
1007 while ( mpData
->maStr
[nStart
] == c
)
1012 sal_Int32 nEnd
= mpData
->mnLen
;
1013 while ( nEnd
&& (mpData
->maStr
[nEnd
-1] == c
) )
1015 if ( nEnd
!= mpData
->mnLen
)
1016 Erase( static_cast< xub_StrLen
>(nEnd
) );
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
)
1035 if ( nCount
== mpData
->mnLen
)
1037 STRING_NEW((STRING_TYPE
**)&mpData
);
1041 // Neuen String anlegen
1042 STRINGDATA
* pNewData
= ImplAllocData( mpData
->mnLen
-nCount
);
1044 // Alten String kopieren und initialisieren
1046 for( xub_StrLen j
= 0; j
< mpData
->mnLen
; ++j
)
1048 if ( mpData
->maStr
[j
] != c
)
1050 pNewData
->maStr
[nCount
] = mpData
->maStr
[j
];
1055 // Alte Daten loeschen und Neue zuweisen
1056 STRING_RELEASE((STRING_TYPE
*)mpData
);
1064 // -----------------------------------------------------------------------
1066 STRING
& STRING::Reverse()
1068 DBG_CHKTHIS( STRING
, DBGCHECKSTRING
);
1070 if ( !mpData
->mnLen
)
1073 // Daten kopieren, wenn noetig
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
;
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
);
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
);
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
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
))) )
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]) )
1182 // Wenn String zu lang, dann konvertieren wir nicht
1183 if ( nLen
>= STRING_MAXLEN
)
1187 // Zeilenumbrueche konvertieren
1190 // Neuen String anlegen
1191 STRINGDATA
* pNewData
= ImplAllocData( nLen
);
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
;
1207 if ( eLineEnd
== LINEEND_CR
)
1208 pNewData
->maStr
[j
] = _CR
;
1210 pNewData
->maStr
[j
] = _LF
;
1214 if ( ((pStr
[i
+1] == _CR
) || (pStr
[i
+1] == _LF
)) &&
1215 (pStr
[i
] != pStr
[i
+1]) )
1220 pNewData
->maStr
[j
] = mpData
->maStr
[i
];
1227 // Alte Daten loeschen und Neue zuweisen
1228 STRING_RELEASE((STRING_TYPE
*)mpData
);
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
;
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
;
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
;
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
;
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
)
1343 if ( mpData
->mnLen
!= rStr
.mpData
->mnLen
)
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
)
1371 if ( mpData
->mnLen
!= rStr
.mpData
->mnLen
)
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
)
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
)
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
;
1472 while ( i
< mpData
->mnLen
)
1474 // Stimmt das Zeichen nicht ueberein, dann abbrechen
1475 if ( *pStr1
!= *pStr2
)
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
;
1498 while ( i
< mpData
->mnLen
)
1500 // Stimmt das Zeichen nicht ueberein, dann abbrechen
1501 if ( *pStr
!= *pCharStr
)
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
;
1520 while ( nIndex
< nLen
)
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
;
1551 STRCODE cSearch
= rStr
.mpData
->maStr
[0];
1552 while ( nIndex
< nLen
)
1554 if ( *pStr1
== cSearch
)
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 )
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
;
1597 STRCODE cSearch
= *pCharStr
;
1598 while ( nIndex
< nLen
)
1600 if ( *pStr
== cSearch
)
1608 // Nur innerhalb des Strings suchen
1609 while ( nLen
- nIndex
>= nStrLen
)
1611 // Stimmt der String ueberein
1612 if ( ImplStringCompareWithoutZero( pStr
, pCharStr
, nStrLen
) == 0 )
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
;
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
;
1654 while ( nIndex
< nLen
)
1657 const STRCODE
* pCompStr
= pChars
;
1660 if ( *pCompStr
== c
)
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
;
1689 const STRCODE
* pCompStr
= pChars
;
1692 if ( *pCompStr
== c
)
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
;
1710 while ( nIndex
< nLen
)
1715 mpData
->maStr
[nIndex
] = cRep
;
1722 return STRING_NOTFOUND
;
1725 // -----------------------------------------------------------------------
1727 xub_StrLen
STRING::SearchAndReplace( const STRING
& rStr
, const STRING
& rRepStr
,
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
);
1741 // -----------------------------------------------------------------------
1743 xub_StrLen
STRING::SearchAndReplace( const STRCODE
* pCharStr
, const STRING
& rRepStr
,
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
);
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
)
1770 mpData
->maStr
[nIndex
] = cRep
;
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
)
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
)
1837 // -----------------------------------------------------------------------
1839 void STRING::SetToken( xub_StrLen nToken
, STRCODE cTok
, const STRING
& rStr
,
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
1855 // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount
1856 if ( *pStr
== cTok
)
1860 if ( nTok
== nToken
)
1864 if ( nTok
> nToken
)
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
1893 // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount
1894 if ( *pStr
== cTok
)
1898 if ( nTok
== nToken
)
1902 if ( nTok
> nToken
)
1911 if ( nTok
>= nToken
)
1916 rIndex
= STRING_NOTFOUND
;
1917 return Copy( nFirstChar
, i
-nFirstChar
);
1921 rIndex
= STRING_NOTFOUND
;
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
)
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
)
1949 if ( cQuotedEndChar
)
1951 // Ende des Quotes erreicht ?
1952 if ( c
== cQuotedEndChar
)
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];
1970 // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount
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
2006 if ( cQuotedEndChar
)
2008 // Ende des Quotes erreicht ?
2009 if ( c
== cQuotedEndChar
)
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];
2027 // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount
2032 if ( nTok
== nToken
)
2036 if ( nTok
> nToken
)
2046 if ( nTok
>= nToken
)
2051 rIndex
= STRING_NOTFOUND
;
2052 return Copy( nFirstChar
, i
-nFirstChar
);
2056 rIndex
= STRING_NOTFOUND
;
2061 // -----------------------------------------------------------------------
2063 STRCODE
* STRING::GetBufferAccess()
2065 DBG_CHKTHIS( STRING
, DBGCHECKSTRING
);
2067 // Daten kopieren, wenn noetig
2068 if ( mpData
->mnLen
)
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
);
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
);
2099 mpData
->mnLen
= nLen
;
2102 // -----------------------------------------------------------------------
2104 STRCODE
* STRING::AllocBuffer( xub_StrLen nLen
)
2106 DBG_CHKTHIS( STRING
, DBGCHECKSTRING
);
2108 STRING_RELEASE((STRING_TYPE
*)mpData
);
2110 mpData
= ImplAllocData( nLen
);
2114 STRING_NEW((STRING_TYPE
**)&mpData
);
2117 return mpData
->maStr
;