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