Update ooo320-m1
[ooovba.git] / tools / source / string / strascii.cxx
blobc47c8363ec348cb2f04bd9de79b49811cbb95787
1 #/*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: strascii.cxx,v $
10 * $Revision: 1.9 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // no include "precompiled_tools.hxx" because this is included in other cxx files.
33 // =======================================================================
35 #ifdef DBG_UTIL
37 static BOOL ImplDbgCheckAsciiStr( const sal_Char* pAsciiStr, sal_Int32 nLen )
39 while ( nLen && *pAsciiStr )
41 if ( ((unsigned char)*pAsciiStr) > 127 )
42 return FALSE;
43 ++pAsciiStr,
44 --nLen;
47 return TRUE;
50 #endif
52 // =======================================================================
54 static void ImplCopyAsciiStr( sal_Unicode* pDest, const sal_Char* pSrc,
55 sal_Int32 nLen )
57 DBG_ASSERT( ImplDbgCheckAsciiStr( pSrc, nLen ),
58 "UniString::CopyAsciiStr() - pAsciiStr include characters > 127" );
60 while ( nLen )
62 *pDest = (unsigned char)*pSrc;
63 ++pDest,
64 ++pSrc,
65 --nLen;
69 // =======================================================================
71 static sal_Int32 ImplStringCompareAscii( const sal_Unicode* pStr1, const sal_Char* pStr2 )
73 sal_Int32 nRet;
74 while ( ((nRet = ((sal_Int32)*pStr1)-((sal_Int32)((unsigned char)*pStr2))) == 0) &&
75 *pStr2 )
77 ++pStr1,
78 ++pStr2;
81 return nRet;
84 // -----------------------------------------------------------------------
86 static sal_Int32 ImplStringCompareAscii( const sal_Unicode* pStr1, const sal_Char* pStr2,
87 xub_StrLen nCount )
89 sal_Int32 nRet = 0;
90 while ( nCount &&
91 ((nRet = ((sal_Int32)*pStr1)-((sal_Int32)((unsigned char)*pStr2))) == 0) &&
92 *pStr2 )
94 ++pStr1,
95 ++pStr2,
96 --nCount;
99 return nRet;
102 // -----------------------------------------------------------------------
104 static sal_Int32 ImplStringCompareWithoutZeroAscii( const sal_Unicode* pStr1, const sal_Char* pStr2,
105 xub_StrLen nCount )
107 sal_Int32 nRet = 0;
108 while ( nCount &&
109 ((nRet = ((sal_Int32)*pStr1)-((sal_Int32)((unsigned char)*pStr2))) == 0) )
111 ++pStr1,
112 ++pStr2,
113 --nCount;
116 return nRet;
119 // -----------------------------------------------------------------------
121 static sal_Int32 ImplStringICompareAscii( const sal_Unicode* pStr1, const sal_Char* pStr2 )
123 sal_Int32 nRet;
124 sal_Unicode c1;
125 sal_Char c2;
128 // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln
129 c1 = *pStr1;
130 c2 = *pStr2;
131 if ( (c1 >= 65) && (c1 <= 90) )
132 c1 += 32;
133 if ( (c2 >= 65) && (c2 <= 90) )
134 c2 += 32;
135 nRet = ((sal_Int32)c1)-((sal_Int32)((unsigned char)c2));
136 if ( nRet != 0 )
137 break;
139 ++pStr1,
140 ++pStr2;
142 while ( c2 );
144 return nRet;
147 // -----------------------------------------------------------------------
149 static sal_Int32 ImplStringICompareAscii( const sal_Unicode* pStr1, const sal_Char* pStr2,
150 xub_StrLen nCount )
152 sal_Int32 nRet = 0;
153 sal_Unicode c1;
154 sal_Char c2;
157 if ( !nCount )
158 break;
160 // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln
161 c1 = *pStr1;
162 c2 = *pStr2;
163 if ( (c1 >= 65) && (c1 <= 90) )
164 c1 += 32;
165 if ( (c2 >= 65) && (c2 <= 90) )
166 c2 += 32;
167 nRet = ((sal_Int32)c1)-((sal_Int32)((unsigned char)c2));
168 if ( nRet != 0 )
169 break;
171 ++pStr1,
172 ++pStr2,
173 --nCount;
175 while ( c2 );
177 return nRet;
180 // =======================================================================
182 UniString UniString::CreateFromAscii( const sal_Char* pAsciiStr )
184 DBG_ASSERT( pAsciiStr, "UniString::CreateFromAscii() - pAsciiStr is NULL" );
186 // Stringlaenge ermitteln
187 xub_StrLen nLen = ImplStringLen( pAsciiStr );
189 UniString aTempStr;
190 if ( nLen )
192 ImplCopyAsciiStr( aTempStr.AllocBuffer( nLen ), pAsciiStr, nLen );
194 return aTempStr;
197 // -----------------------------------------------------------------------
199 UniString UniString::CreateFromAscii( const sal_Char* pAsciiStr, xub_StrLen nLen )
201 DBG_ASSERT( pAsciiStr, "UniString::CreateFromAscii() - pAsciiStr is NULL" );
203 // Stringlaenge ermitteln
204 if ( nLen == STRING_LEN )
205 nLen = ImplStringLen( pAsciiStr );
207 UniString aTempStr;
209 if ( nLen )
211 ImplCopyAsciiStr( aTempStr.AllocBuffer( nLen ), pAsciiStr, nLen );
213 return aTempStr;
216 // -----------------------------------------------------------------------
218 UniString& UniString::AssignAscii( const sal_Char* pAsciiStr )
220 DBG_CHKTHIS( UniString, DbgCheckUniString );
221 DBG_ASSERT( pAsciiStr, "UniString::AssignAscii() - pAsciiStr is NULL" );
223 // Stringlaenge ermitteln
224 xub_StrLen nLen = ImplStringLen( pAsciiStr );
226 if ( !nLen )
228 STRING_NEW((STRING_TYPE **)&mpData);
230 else
232 // Wenn String genauso lang ist, wie der String, dann direkt kopieren
233 if ( (nLen == mpData->mnLen) && (mpData->mnRefCount == 1) )
234 ImplCopyAsciiStr( mpData->maStr, pAsciiStr, nLen );
235 else
237 // Alte Daten loeschen
238 STRING_RELEASE((STRING_TYPE *)mpData);
240 // Daten initialisieren und String kopieren
241 mpData = ImplAllocData( nLen );
242 ImplCopyAsciiStr( mpData->maStr, pAsciiStr, nLen );
246 return *this;
249 // -----------------------------------------------------------------------
251 UniString& UniString::AssignAscii( const sal_Char* pAsciiStr, xub_StrLen nLen )
253 DBG_CHKTHIS( UniString, DbgCheckUniString );
254 DBG_ASSERT( pAsciiStr, "UniString::AssignAscii() - pAsciiStr is NULL" );
256 if ( nLen == STRING_LEN )
257 nLen = ImplStringLen( pAsciiStr );
259 #ifdef DBG_UTIL
260 if ( DbgIsAssert() )
262 for ( xub_StrLen i = 0; i < nLen; ++i )
264 if ( !pAsciiStr[i] )
266 DBG_ERROR( "UniString::AssignAscii() : nLen is wrong" );
270 #endif
272 if ( !nLen )
274 STRING_NEW((STRING_TYPE **)&mpData);
276 else
278 // Wenn String genauso lang ist, wie der String, dann direkt kopieren
279 if ( (nLen == mpData->mnLen) && (mpData->mnRefCount == 1) )
280 ImplCopyAsciiStr( mpData->maStr, pAsciiStr, nLen );
281 else
283 // Alte Daten loeschen
284 STRING_RELEASE((STRING_TYPE *)mpData);
286 // Daten initialisieren und String kopieren
287 mpData = ImplAllocData( nLen );
288 ImplCopyAsciiStr( mpData->maStr, pAsciiStr, nLen );
292 return *this;
295 // -----------------------------------------------------------------------
297 UniString& UniString::AppendAscii( const sal_Char* pAsciiStr )
299 DBG_CHKTHIS( UniString, DbgCheckUniString );
300 DBG_ASSERT( pAsciiStr, "UniString::AppendAscii() - pAsciiStr is NULL" );
302 // Stringlaenge ermitteln
303 sal_Int32 nCopyLen = ImplStringLen( pAsciiStr );
305 // Ueberlauf abfangen
306 nCopyLen = ImplGetCopyLen( mpData->mnLen, nCopyLen );
308 // Ist es kein leerer String
309 if ( nCopyLen )
311 // Neue Datenstruktur und neuen String erzeugen
312 UniStringData* pNewData = ImplAllocData( mpData->mnLen+nCopyLen );
314 // String kopieren
315 memcpy( pNewData->maStr, mpData->maStr, mpData->mnLen*sizeof( sal_Unicode ) );
316 ImplCopyAsciiStr( pNewData->maStr+mpData->mnLen, pAsciiStr, nCopyLen );
318 // Alte Daten loeschen und Neue zuweisen
319 STRING_RELEASE((STRING_TYPE *)mpData);
320 mpData = pNewData;
323 return *this;
326 // -----------------------------------------------------------------------
328 UniString& UniString::AppendAscii( const sal_Char* pAsciiStr, xub_StrLen nLen )
330 DBG_CHKTHIS( UniString, DbgCheckUniString );
331 DBG_ASSERT( pAsciiStr, "UniString::AppendAscii() - pAsciiStr is NULL" );
333 if ( nLen == STRING_LEN )
334 nLen = ImplStringLen( pAsciiStr );
336 #ifdef DBG_UTIL
337 if ( DbgIsAssert() )
339 for ( xub_StrLen i = 0; i < nLen; ++i )
341 if ( !pAsciiStr[i] )
343 DBG_ERROR( "UniString::AppendAscii() : nLen is wrong" );
347 #endif
349 // Ueberlauf abfangen
350 sal_Int32 nCopyLen = ImplGetCopyLen( mpData->mnLen, nLen );
352 // Ist es kein leerer String
353 if ( nCopyLen )
355 // Neue Datenstruktur und neuen String erzeugen
356 UniStringData* pNewData = ImplAllocData( mpData->mnLen+nCopyLen );
358 // String kopieren
359 memcpy( pNewData->maStr, mpData->maStr, mpData->mnLen*sizeof( sal_Unicode ) );
360 ImplCopyAsciiStr( pNewData->maStr+mpData->mnLen, pAsciiStr, nCopyLen );
362 // Alte Daten loeschen und Neue zuweisen
363 STRING_RELEASE((STRING_TYPE *)mpData);
364 mpData = pNewData;
367 return *this;
370 // -----------------------------------------------------------------------
372 UniString& UniString::InsertAscii( const char* pAsciiStr, xub_StrLen nIndex )
374 DBG_CHKTHIS( UniString, DbgCheckUniString );
375 DBG_ASSERT( pAsciiStr, "UniString::InsertAscii() - pAsciiStr is NULL" );
377 // Stringlaenge ermitteln
378 sal_Int32 nCopyLen = ImplStringLen( pAsciiStr );
380 // Ueberlauf abfangen
381 nCopyLen = ImplGetCopyLen( mpData->mnLen, nCopyLen );
383 // Ist der einzufuegende String ein Leerstring
384 if ( !nCopyLen )
385 return *this;
387 // Index groesser als Laenge
388 if ( nIndex > mpData->mnLen )
389 nIndex = static_cast< xub_StrLen >(mpData->mnLen);
391 // Neue Laenge ermitteln und neuen String anlegen
392 UniStringData* pNewData = ImplAllocData( mpData->mnLen+nCopyLen );
394 // String kopieren
395 memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( sal_Unicode ) );
396 ImplCopyAsciiStr( pNewData->maStr+nIndex, pAsciiStr, nCopyLen );
397 memcpy( pNewData->maStr+nIndex+nCopyLen, mpData->maStr+nIndex,
398 (mpData->mnLen-nIndex)*sizeof( sal_Unicode ) );
400 // Alte Daten loeschen und Neue zuweisen
401 STRING_RELEASE((STRING_TYPE *)mpData);
402 mpData = pNewData;
404 return *this;
407 // -----------------------------------------------------------------------
409 UniString& UniString::ReplaceAscii( xub_StrLen nIndex, xub_StrLen nCount,
410 const sal_Char* pAsciiStr, xub_StrLen nStrLen )
412 DBG_CHKTHIS( UniString, DbgCheckUniString );
413 DBG_ASSERT( pAsciiStr, "UniString::ReplaceAscii() - pAsciiStr is NULL" );
415 // Wenn Index groessergleich Laenge ist, dann ist es ein Append
416 if ( nIndex >= mpData->mnLen )
418 AppendAscii( pAsciiStr, nStrLen );
419 return *this;
422 // Ist es eine Zuweisung
423 if ( (nIndex == 0) && (nCount >= mpData->mnLen) )
425 AssignAscii( pAsciiStr, nStrLen );
426 return *this;
429 // Reicht ein Erase
430 if ( nStrLen == STRING_LEN )
431 nStrLen = ImplStringLen( pAsciiStr );
432 if ( !nStrLen )
433 return Erase( nIndex, nCount );
435 // nCount darf nicht ueber das Stringende hinnausgehen
436 if ( nCount > mpData->mnLen - nIndex )
437 nCount = static_cast< xub_StrLen >(mpData->mnLen-nIndex);
439 // Reicht eine zeichenweise Zuweisung
440 if ( nCount == nStrLen )
442 ImplCopyData();
443 ImplCopyAsciiStr( mpData->maStr+nIndex, pAsciiStr, nStrLen );
444 return *this;
447 // Ueberlauf abfangen
448 sal_Int32 n = ImplGetCopyLen( mpData->mnLen-nCount, nStrLen );
450 // Neue Daten anlegen
451 STRINGDATA* pNewData = ImplAllocData( mpData->mnLen-nCount+n );
453 // String kopieren
454 memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) );
455 ImplCopyAsciiStr( pNewData->maStr+nIndex, pAsciiStr, n );
456 memcpy( pNewData->maStr+nIndex+n, mpData->maStr+nIndex+nCount,
457 (mpData->mnLen-nIndex-nCount+1)*sizeof( STRCODE ) );
459 // Alte Daten loeschen und Neue zuweisen
460 STRING_RELEASE((STRING_TYPE *)mpData);
461 mpData = pNewData;
463 return *this;
466 // -----------------------------------------------------------------------
468 StringCompare UniString::CompareToAscii( const sal_Char* pAsciiStr,
469 xub_StrLen nLen ) const
471 DBG_CHKTHIS( UniString, DbgCheckUniString );
472 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, nLen ),
473 "UniString::CompareToAscii() - pAsciiStr include characters > 127" );
475 // String vergleichen
476 sal_Int32 nCompare = ImplStringCompareAscii( mpData->maStr, pAsciiStr, nLen );
478 // Rueckgabewert anpassen
479 if ( nCompare == 0 )
480 return COMPARE_EQUAL;
481 else if ( nCompare < 0 )
482 return COMPARE_LESS;
483 else
484 return COMPARE_GREATER;
487 // -----------------------------------------------------------------------
489 StringCompare UniString::CompareIgnoreCaseToAscii( const sal_Char* pAsciiStr,
490 xub_StrLen nLen ) const
492 DBG_CHKTHIS( UniString, DbgCheckUniString );
493 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, nLen ),
494 "UniString::CompareIgnoreCaseToAscii() - pAsciiStr include characters > 127" );
496 // String vergleichen
497 sal_Int32 nCompare = ImplStringICompareAscii( mpData->maStr, pAsciiStr, nLen );
499 // Rueckgabewert anpassen
500 if ( nCompare == 0 )
501 return COMPARE_EQUAL;
502 else if ( nCompare < 0 )
503 return COMPARE_LESS;
504 else
505 return COMPARE_GREATER;
508 // -----------------------------------------------------------------------
510 BOOL UniString::EqualsAscii( const sal_Char* pAsciiStr ) const
512 DBG_CHKTHIS( UniString, DbgCheckUniString );
513 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ),
514 "UniString::EqualsAscii() - pAsciiStr include characters > 127" );
516 return (ImplStringCompareAscii( mpData->maStr, pAsciiStr ) == 0);
519 // -----------------------------------------------------------------------
521 BOOL UniString::EqualsIgnoreCaseAscii( const sal_Char* pAsciiStr ) const
523 DBG_CHKTHIS( UniString, DbgCheckUniString );
524 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ),
525 "UniString::EqualsIgnoreCaseAscii() - pAsciiStr include characters > 127" );
527 return (ImplStringICompareAscii( mpData->maStr, pAsciiStr ) == 0);
530 // -----------------------------------------------------------------------
532 BOOL UniString::EqualsAscii( const sal_Char* pAsciiStr,
533 xub_StrLen nIndex, xub_StrLen nLen ) const
535 DBG_CHKTHIS( UniString, DbgCheckUniString );
536 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, nLen ),
537 "UniString::EqualsAscii() - pAsciiStr include characters > 127" );
539 // Are there enough codes for comparing?
540 if ( nIndex > mpData->mnLen )
541 return (*pAsciiStr == 0);
543 return (ImplStringCompareAscii( mpData->maStr+nIndex, pAsciiStr, nLen ) == 0);
546 // -----------------------------------------------------------------------
548 BOOL UniString::EqualsIgnoreCaseAscii( const sal_Char* pAsciiStr,
549 xub_StrLen nIndex, xub_StrLen nLen ) const
551 DBG_CHKTHIS( UniString, DbgCheckUniString );
552 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, nLen ),
553 "UniString::EqualsIgnoreCaseAscii() - pAsciiStr include characters > 127" );
555 // Are there enough codes for comparing?
556 if ( nIndex > mpData->mnLen )
557 return (*pAsciiStr == 0);
559 return (ImplStringICompareAscii( mpData->maStr+nIndex, pAsciiStr, nLen ) == 0);
562 // -----------------------------------------------------------------------
564 xub_StrLen UniString::SearchAscii( const sal_Char* pAsciiStr, xub_StrLen nIndex ) const
566 DBG_CHKTHIS( UniString, DbgCheckUniString );
567 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ),
568 "UniString::SearchAscii() - pAsciiStr include characters > 127" );
570 sal_Int32 nLen = mpData->mnLen;
571 xub_StrLen nStrLen = ImplStringLen( pAsciiStr );
573 // Falls die Laenge des uebergebenen Strings 0 ist oder der Index
574 // hinter dem String liegt, dann wurde der String nicht gefunden
575 if ( !nStrLen || (nIndex >= nLen) )
576 return STRING_NOTFOUND;
578 const sal_Unicode* pStr = mpData->maStr;
579 pStr += nIndex;
581 if ( nStrLen == 1 )
583 sal_Unicode cSearch = (unsigned char)*pAsciiStr;
584 while ( nIndex < nLen )
586 if ( *pStr == cSearch )
587 return nIndex;
588 ++pStr,
589 ++nIndex;
592 else
594 // Nur innerhalb des Strings suchen
595 while ( nLen - nIndex >= nStrLen )
597 // Stimmt der String ueberein
598 if ( ImplStringCompareWithoutZeroAscii( pStr, pAsciiStr, nStrLen ) == 0 )
599 return nIndex;
600 ++pStr,
601 ++nIndex;
605 return STRING_NOTFOUND;
608 // -----------------------------------------------------------------------
610 xub_StrLen UniString::SearchAndReplaceAscii( const sal_Char* pAsciiStr, const UniString& rRepStr,
611 xub_StrLen nIndex )
613 DBG_CHKTHIS( UniString, DbgCheckUniString );
614 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ),
615 "UniString::SearchAndReplaceAscii() - pAsciiStr include characters > 127" );
617 xub_StrLen nSPos = SearchAscii( pAsciiStr, nIndex );
618 if ( nSPos != STRING_NOTFOUND )
619 Replace( nSPos, ImplStringLen( pAsciiStr ), rRepStr );
621 return nSPos;
624 // -----------------------------------------------------------------------
626 void UniString::SearchAndReplaceAllAscii( const sal_Char* pAsciiStr, const UniString& rRepStr )
628 DBG_CHKTHIS( UniString, DbgCheckUniString );
629 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ),
630 "UniString::SearchAndReplaceAllAscii() - pAsciiStr include characters > 127" );
632 xub_StrLen nCharLen = ImplStringLen( pAsciiStr );
633 xub_StrLen nSPos = SearchAscii( pAsciiStr, 0 );
634 while ( nSPos != STRING_NOTFOUND )
636 Replace( nSPos, nCharLen, rRepStr );
637 nSPos = nSPos + rRepStr.Len();
638 nSPos = SearchAscii( pAsciiStr, nSPos );