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