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