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 #ifdef DBG_UTIL 29 30 static sal_Bool ImplDbgCheckAsciiStr( const sal_Char* pAsciiStr, sal_Int32 nLen ) 31 { 32 while ( nLen && *pAsciiStr ) 33 { 34 if ( ((unsigned char)*pAsciiStr) > 127 ) 35 return sal_False; 36 ++pAsciiStr, 37 --nLen; 38 } 39 40 return sal_True; 41 } 42 43 #endif 44 45 // ======================================================================= 46 47 static void ImplCopyAsciiStr( sal_Unicode* pDest, const sal_Char* pSrc, 48 sal_Int32 nLen ) 49 { 50 DBG_ASSERT( ImplDbgCheckAsciiStr( pSrc, nLen ), 51 "UniString::CopyAsciiStr() - pAsciiStr include characters > 127" ); 52 53 while ( nLen ) 54 { 55 *pDest = (unsigned char)*pSrc; 56 ++pDest, 57 ++pSrc, 58 --nLen; 59 } 60 } 61 62 // ======================================================================= 63 64 static sal_Int32 ImplStringCompareAscii( const sal_Unicode* pStr1, const sal_Char* pStr2 ) 65 { 66 sal_Int32 nRet; 67 while ( ((nRet = ((sal_Int32)*pStr1)-((sal_Int32)((unsigned char)*pStr2))) == 0) && 68 *pStr2 ) 69 { 70 ++pStr1, 71 ++pStr2; 72 } 73 74 return nRet; 75 } 76 77 // ----------------------------------------------------------------------- 78 79 static sal_Int32 ImplStringCompareAscii( const sal_Unicode* pStr1, const sal_Char* pStr2, 80 xub_StrLen nCount ) 81 { 82 sal_Int32 nRet = 0; 83 while ( nCount && 84 ((nRet = ((sal_Int32)*pStr1)-((sal_Int32)((unsigned char)*pStr2))) == 0) && 85 *pStr2 ) 86 { 87 ++pStr1, 88 ++pStr2, 89 --nCount; 90 } 91 92 return nRet; 93 } 94 95 // ----------------------------------------------------------------------- 96 97 static sal_Int32 ImplStringCompareWithoutZeroAscii( const sal_Unicode* pStr1, const sal_Char* pStr2, 98 xub_StrLen nCount ) 99 { 100 sal_Int32 nRet = 0; 101 while ( nCount && 102 ((nRet = ((sal_Int32)*pStr1)-((sal_Int32)((unsigned char)*pStr2))) == 0) ) 103 { 104 ++pStr1, 105 ++pStr2, 106 --nCount; 107 } 108 109 return nRet; 110 } 111 112 // ----------------------------------------------------------------------- 113 114 static sal_Int32 ImplStringICompareAscii( const sal_Unicode* pStr1, const sal_Char* pStr2 ) 115 { 116 sal_Int32 nRet; 117 sal_Unicode c1; 118 sal_Char c2; 119 do 120 { 121 // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln 122 c1 = *pStr1; 123 c2 = *pStr2; 124 if ( (c1 >= 65) && (c1 <= 90) ) 125 c1 += 32; 126 if ( (c2 >= 65) && (c2 <= 90) ) 127 c2 += 32; 128 nRet = ((sal_Int32)c1)-((sal_Int32)((unsigned char)c2)); 129 if ( nRet != 0 ) 130 break; 131 132 ++pStr1, 133 ++pStr2; 134 } 135 while ( c2 ); 136 137 return nRet; 138 } 139 140 // ----------------------------------------------------------------------- 141 142 static sal_Int32 ImplStringICompareAscii( const sal_Unicode* pStr1, const sal_Char* pStr2, 143 xub_StrLen nCount ) 144 { 145 sal_Int32 nRet = 0; 146 sal_Unicode c1; 147 sal_Char c2; 148 do 149 { 150 if ( !nCount ) 151 break; 152 153 // Ist das Zeichen zwischen 'A' und 'Z' dann umwandeln 154 c1 = *pStr1; 155 c2 = *pStr2; 156 if ( (c1 >= 65) && (c1 <= 90) ) 157 c1 += 32; 158 if ( (c2 >= 65) && (c2 <= 90) ) 159 c2 += 32; 160 nRet = ((sal_Int32)c1)-((sal_Int32)((unsigned char)c2)); 161 if ( nRet != 0 ) 162 break; 163 164 ++pStr1, 165 ++pStr2, 166 --nCount; 167 } 168 while ( c2 ); 169 170 return nRet; 171 } 172 173 // ======================================================================= 174 175 UniString UniString::CreateFromAscii( const sal_Char* pAsciiStr ) 176 { 177 DBG_ASSERT( pAsciiStr, "UniString::CreateFromAscii() - pAsciiStr is NULL" ); 178 179 // Stringlaenge ermitteln 180 xub_StrLen nLen = ImplStringLen( pAsciiStr ); 181 182 UniString aTempStr; 183 if ( nLen ) 184 { 185 ImplCopyAsciiStr( aTempStr.AllocBuffer( nLen ), pAsciiStr, nLen ); 186 } 187 return aTempStr; 188 } 189 190 // ----------------------------------------------------------------------- 191 192 UniString UniString::CreateFromAscii( const sal_Char* pAsciiStr, xub_StrLen nLen ) 193 { 194 DBG_ASSERT( pAsciiStr, "UniString::CreateFromAscii() - pAsciiStr is NULL" ); 195 196 // Stringlaenge ermitteln 197 if ( nLen == STRING_LEN ) 198 nLen = ImplStringLen( pAsciiStr ); 199 200 UniString aTempStr; 201 202 if ( nLen ) 203 { 204 ImplCopyAsciiStr( aTempStr.AllocBuffer( nLen ), pAsciiStr, nLen ); 205 } 206 return aTempStr; 207 } 208 209 // ----------------------------------------------------------------------- 210 211 UniString& UniString::AssignAscii( const sal_Char* pAsciiStr ) 212 { 213 DBG_CHKTHIS( UniString, DbgCheckUniString ); 214 DBG_ASSERT( pAsciiStr, "UniString::AssignAscii() - pAsciiStr is NULL" ); 215 216 // Stringlaenge ermitteln 217 xub_StrLen nLen = ImplStringLen( pAsciiStr ); 218 219 if ( !nLen ) 220 { 221 STRING_NEW((STRING_TYPE **)&mpData); 222 } 223 else 224 { 225 // Wenn String genauso lang ist, wie der String, dann direkt kopieren 226 if ( (nLen == mpData->mnLen) && (mpData->mnRefCount == 1) ) 227 ImplCopyAsciiStr( mpData->maStr, pAsciiStr, nLen ); 228 else 229 { 230 // Alte Daten loeschen 231 STRING_RELEASE((STRING_TYPE *)mpData); 232 233 // Daten initialisieren und String kopieren 234 mpData = ImplAllocData( nLen ); 235 ImplCopyAsciiStr( mpData->maStr, pAsciiStr, nLen ); 236 } 237 } 238 239 return *this; 240 } 241 242 // ----------------------------------------------------------------------- 243 244 UniString& UniString::AssignAscii( const sal_Char* pAsciiStr, xub_StrLen nLen ) 245 { 246 DBG_CHKTHIS( UniString, DbgCheckUniString ); 247 DBG_ASSERT( pAsciiStr, "UniString::AssignAscii() - pAsciiStr is NULL" ); 248 249 if ( nLen == STRING_LEN ) 250 nLen = ImplStringLen( pAsciiStr ); 251 252 #ifdef DBG_UTIL 253 if ( DbgIsAssert() ) 254 { 255 for ( xub_StrLen i = 0; i < nLen; ++i ) 256 { 257 if ( !pAsciiStr[i] ) 258 { 259 DBG_ERROR( "UniString::AssignAscii() : nLen is wrong" ); 260 } 261 } 262 } 263 #endif 264 265 if ( !nLen ) 266 { 267 STRING_NEW((STRING_TYPE **)&mpData); 268 } 269 else 270 { 271 // Wenn String genauso lang ist, wie der String, dann direkt kopieren 272 if ( (nLen == mpData->mnLen) && (mpData->mnRefCount == 1) ) 273 ImplCopyAsciiStr( mpData->maStr, pAsciiStr, nLen ); 274 else 275 { 276 // Alte Daten loeschen 277 STRING_RELEASE((STRING_TYPE *)mpData); 278 279 // Daten initialisieren und String kopieren 280 mpData = ImplAllocData( nLen ); 281 ImplCopyAsciiStr( mpData->maStr, pAsciiStr, nLen ); 282 } 283 } 284 285 return *this; 286 } 287 288 // ----------------------------------------------------------------------- 289 290 UniString& UniString::AppendAscii( const sal_Char* pAsciiStr ) 291 { 292 DBG_CHKTHIS( UniString, DbgCheckUniString ); 293 DBG_ASSERT( pAsciiStr, "UniString::AppendAscii() - pAsciiStr is NULL" ); 294 295 // Stringlaenge ermitteln 296 sal_Int32 nCopyLen = ImplStringLen( pAsciiStr ); 297 298 // Ueberlauf abfangen 299 nCopyLen = ImplGetCopyLen( mpData->mnLen, nCopyLen ); 300 301 // Ist es kein leerer String 302 if ( nCopyLen ) 303 { 304 // Neue Datenstruktur und neuen String erzeugen 305 UniStringData* pNewData = ImplAllocData( mpData->mnLen+nCopyLen ); 306 307 // String kopieren 308 memcpy( pNewData->maStr, mpData->maStr, mpData->mnLen*sizeof( sal_Unicode ) ); 309 ImplCopyAsciiStr( pNewData->maStr+mpData->mnLen, pAsciiStr, nCopyLen ); 310 311 // Alte Daten loeschen und Neue zuweisen 312 STRING_RELEASE((STRING_TYPE *)mpData); 313 mpData = pNewData; 314 } 315 316 return *this; 317 } 318 319 // ----------------------------------------------------------------------- 320 321 UniString& UniString::AppendAscii( const sal_Char* pAsciiStr, xub_StrLen nLen ) 322 { 323 DBG_CHKTHIS( UniString, DbgCheckUniString ); 324 DBG_ASSERT( pAsciiStr, "UniString::AppendAscii() - pAsciiStr is NULL" ); 325 326 if ( nLen == STRING_LEN ) 327 nLen = ImplStringLen( pAsciiStr ); 328 329 #ifdef DBG_UTIL 330 if ( DbgIsAssert() ) 331 { 332 for ( xub_StrLen i = 0; i < nLen; ++i ) 333 { 334 if ( !pAsciiStr[i] ) 335 { 336 DBG_ERROR( "UniString::AppendAscii() : nLen is wrong" ); 337 } 338 } 339 } 340 #endif 341 342 // Ueberlauf abfangen 343 sal_Int32 nCopyLen = ImplGetCopyLen( mpData->mnLen, nLen ); 344 345 // Ist es kein leerer String 346 if ( nCopyLen ) 347 { 348 // Neue Datenstruktur und neuen String erzeugen 349 UniStringData* pNewData = ImplAllocData( mpData->mnLen+nCopyLen ); 350 351 // String kopieren 352 memcpy( pNewData->maStr, mpData->maStr, mpData->mnLen*sizeof( sal_Unicode ) ); 353 ImplCopyAsciiStr( pNewData->maStr+mpData->mnLen, pAsciiStr, nCopyLen ); 354 355 // Alte Daten loeschen und Neue zuweisen 356 STRING_RELEASE((STRING_TYPE *)mpData); 357 mpData = pNewData; 358 } 359 360 return *this; 361 } 362 363 // ----------------------------------------------------------------------- 364 365 UniString& UniString::InsertAscii( const char* pAsciiStr, xub_StrLen nIndex ) 366 { 367 DBG_CHKTHIS( UniString, DbgCheckUniString ); 368 DBG_ASSERT( pAsciiStr, "UniString::InsertAscii() - pAsciiStr is NULL" ); 369 370 // Stringlaenge ermitteln 371 sal_Int32 nCopyLen = ImplStringLen( pAsciiStr ); 372 373 // Ueberlauf abfangen 374 nCopyLen = ImplGetCopyLen( mpData->mnLen, nCopyLen ); 375 376 // Ist der einzufuegende String ein Leerstring 377 if ( !nCopyLen ) 378 return *this; 379 380 // Index groesser als Laenge 381 if ( nIndex > mpData->mnLen ) 382 nIndex = static_cast< xub_StrLen >(mpData->mnLen); 383 384 // Neue Laenge ermitteln und neuen String anlegen 385 UniStringData* pNewData = ImplAllocData( mpData->mnLen+nCopyLen ); 386 387 // String kopieren 388 memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( sal_Unicode ) ); 389 ImplCopyAsciiStr( pNewData->maStr+nIndex, pAsciiStr, nCopyLen ); 390 memcpy( pNewData->maStr+nIndex+nCopyLen, mpData->maStr+nIndex, 391 (mpData->mnLen-nIndex)*sizeof( sal_Unicode ) ); 392 393 // Alte Daten loeschen und Neue zuweisen 394 STRING_RELEASE((STRING_TYPE *)mpData); 395 mpData = pNewData; 396 397 return *this; 398 } 399 400 // ----------------------------------------------------------------------- 401 402 UniString& UniString::ReplaceAscii( xub_StrLen nIndex, xub_StrLen nCount, 403 const sal_Char* pAsciiStr, xub_StrLen nStrLen ) 404 { 405 DBG_CHKTHIS( UniString, DbgCheckUniString ); 406 DBG_ASSERT( pAsciiStr, "UniString::ReplaceAscii() - pAsciiStr is NULL" ); 407 408 // Wenn Index groessergleich Laenge ist, dann ist es ein Append 409 if ( nIndex >= mpData->mnLen ) 410 { 411 AppendAscii( pAsciiStr, nStrLen ); 412 return *this; 413 } 414 415 // Ist es eine Zuweisung 416 if ( (nIndex == 0) && (nCount >= mpData->mnLen) ) 417 { 418 AssignAscii( pAsciiStr, nStrLen ); 419 return *this; 420 } 421 422 // Reicht ein Erase 423 if ( nStrLen == STRING_LEN ) 424 nStrLen = ImplStringLen( pAsciiStr ); 425 if ( !nStrLen ) 426 return Erase( nIndex, nCount ); 427 428 // nCount darf nicht ueber das Stringende hinnausgehen 429 if ( nCount > mpData->mnLen - nIndex ) 430 nCount = static_cast< xub_StrLen >(mpData->mnLen-nIndex); 431 432 // Reicht eine zeichenweise Zuweisung 433 if ( nCount == nStrLen ) 434 { 435 ImplCopyData(); 436 ImplCopyAsciiStr( mpData->maStr+nIndex, pAsciiStr, nStrLen ); 437 return *this; 438 } 439 440 // Ueberlauf abfangen 441 sal_Int32 n = ImplGetCopyLen( mpData->mnLen-nCount, nStrLen ); 442 443 // Neue Daten anlegen 444 STRINGDATA* pNewData = ImplAllocData( mpData->mnLen-nCount+n ); 445 446 // String kopieren 447 memcpy( pNewData->maStr, mpData->maStr, nIndex*sizeof( STRCODE ) ); 448 ImplCopyAsciiStr( pNewData->maStr+nIndex, pAsciiStr, n ); 449 memcpy( pNewData->maStr+nIndex+n, mpData->maStr+nIndex+nCount, 450 (mpData->mnLen-nIndex-nCount+1)*sizeof( STRCODE ) ); 451 452 // Alte Daten loeschen und Neue zuweisen 453 STRING_RELEASE((STRING_TYPE *)mpData); 454 mpData = pNewData; 455 456 return *this; 457 } 458 459 // ----------------------------------------------------------------------- 460 461 StringCompare UniString::CompareToAscii( const sal_Char* pAsciiStr, 462 xub_StrLen nLen ) const 463 { 464 DBG_CHKTHIS( UniString, DbgCheckUniString ); 465 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, nLen ), 466 "UniString::CompareToAscii() - pAsciiStr include characters > 127" ); 467 468 // String vergleichen 469 sal_Int32 nCompare = ImplStringCompareAscii( mpData->maStr, pAsciiStr, nLen ); 470 471 // Rueckgabewert anpassen 472 if ( nCompare == 0 ) 473 return COMPARE_EQUAL; 474 else if ( nCompare < 0 ) 475 return COMPARE_LESS; 476 else 477 return COMPARE_GREATER; 478 } 479 480 // ----------------------------------------------------------------------- 481 482 StringCompare UniString::CompareIgnoreCaseToAscii( const sal_Char* pAsciiStr, 483 xub_StrLen nLen ) const 484 { 485 DBG_CHKTHIS( UniString, DbgCheckUniString ); 486 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, nLen ), 487 "UniString::CompareIgnoreCaseToAscii() - pAsciiStr include characters > 127" ); 488 489 // String vergleichen 490 sal_Int32 nCompare = ImplStringICompareAscii( mpData->maStr, pAsciiStr, nLen ); 491 492 // Rueckgabewert anpassen 493 if ( nCompare == 0 ) 494 return COMPARE_EQUAL; 495 else if ( nCompare < 0 ) 496 return COMPARE_LESS; 497 else 498 return COMPARE_GREATER; 499 } 500 501 // ----------------------------------------------------------------------- 502 503 sal_Bool UniString::EqualsAscii( const sal_Char* pAsciiStr ) const 504 { 505 DBG_CHKTHIS( UniString, DbgCheckUniString ); 506 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ), 507 "UniString::EqualsAscii() - pAsciiStr include characters > 127" ); 508 509 return (ImplStringCompareAscii( mpData->maStr, pAsciiStr ) == 0); 510 } 511 512 // ----------------------------------------------------------------------- 513 514 sal_Bool UniString::EqualsIgnoreCaseAscii( const sal_Char* pAsciiStr ) const 515 { 516 DBG_CHKTHIS( UniString, DbgCheckUniString ); 517 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ), 518 "UniString::EqualsIgnoreCaseAscii() - pAsciiStr include characters > 127" ); 519 520 return (ImplStringICompareAscii( mpData->maStr, pAsciiStr ) == 0); 521 } 522 523 // ----------------------------------------------------------------------- 524 525 sal_Bool UniString::EqualsAscii( const sal_Char* pAsciiStr, 526 xub_StrLen nIndex, xub_StrLen nLen ) const 527 { 528 DBG_CHKTHIS( UniString, DbgCheckUniString ); 529 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, nLen ), 530 "UniString::EqualsAscii() - pAsciiStr include characters > 127" ); 531 532 // Are there enough codes for comparing? 533 if ( nIndex > mpData->mnLen ) 534 return (*pAsciiStr == 0); 535 536 return (ImplStringCompareAscii( mpData->maStr+nIndex, pAsciiStr, nLen ) == 0); 537 } 538 539 // ----------------------------------------------------------------------- 540 541 sal_Bool UniString::EqualsIgnoreCaseAscii( const sal_Char* pAsciiStr, 542 xub_StrLen nIndex, xub_StrLen nLen ) const 543 { 544 DBG_CHKTHIS( UniString, DbgCheckUniString ); 545 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, nLen ), 546 "UniString::EqualsIgnoreCaseAscii() - pAsciiStr include characters > 127" ); 547 548 // Are there enough codes for comparing? 549 if ( nIndex > mpData->mnLen ) 550 return (*pAsciiStr == 0); 551 552 return (ImplStringICompareAscii( mpData->maStr+nIndex, pAsciiStr, nLen ) == 0); 553 } 554 555 // ----------------------------------------------------------------------- 556 557 xub_StrLen UniString::SearchAscii( const sal_Char* pAsciiStr, xub_StrLen nIndex ) const 558 { 559 DBG_CHKTHIS( UniString, DbgCheckUniString ); 560 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ), 561 "UniString::SearchAscii() - pAsciiStr include characters > 127" ); 562 563 sal_Int32 nLen = mpData->mnLen; 564 xub_StrLen nStrLen = ImplStringLen( pAsciiStr ); 565 566 // Falls die Laenge des uebergebenen Strings 0 ist oder der Index 567 // hinter dem String liegt, dann wurde der String nicht gefunden 568 if ( !nStrLen || (nIndex >= nLen) ) 569 return STRING_NOTFOUND; 570 571 const sal_Unicode* pStr = mpData->maStr; 572 pStr += nIndex; 573 574 if ( nStrLen == 1 ) 575 { 576 sal_Unicode cSearch = (unsigned char)*pAsciiStr; 577 while ( nIndex < nLen ) 578 { 579 if ( *pStr == cSearch ) 580 return nIndex; 581 ++pStr, 582 ++nIndex; 583 } 584 } 585 else 586 { 587 // Nur innerhalb des Strings suchen 588 while ( nLen - nIndex >= nStrLen ) 589 { 590 // Stimmt der String ueberein 591 if ( ImplStringCompareWithoutZeroAscii( pStr, pAsciiStr, nStrLen ) == 0 ) 592 return nIndex; 593 ++pStr, 594 ++nIndex; 595 } 596 } 597 598 return STRING_NOTFOUND; 599 } 600 601 // ----------------------------------------------------------------------- 602 603 xub_StrLen UniString::SearchAndReplaceAscii( const sal_Char* pAsciiStr, const UniString& rRepStr, 604 xub_StrLen nIndex ) 605 { 606 DBG_CHKTHIS( UniString, DbgCheckUniString ); 607 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ), 608 "UniString::SearchAndReplaceAscii() - pAsciiStr include characters > 127" ); 609 610 xub_StrLen nSPos = SearchAscii( pAsciiStr, nIndex ); 611 if ( nSPos != STRING_NOTFOUND ) 612 Replace( nSPos, ImplStringLen( pAsciiStr ), rRepStr ); 613 614 return nSPos; 615 } 616 617 // ----------------------------------------------------------------------- 618 619 void UniString::SearchAndReplaceAllAscii( const sal_Char* pAsciiStr, const UniString& rRepStr ) 620 { 621 DBG_CHKTHIS( UniString, DbgCheckUniString ); 622 DBG_ASSERT( ImplDbgCheckAsciiStr( pAsciiStr, STRING_LEN ), 623 "UniString::SearchAndReplaceAllAscii() - pAsciiStr include characters > 127" ); 624 625 xub_StrLen nCharLen = ImplStringLen( pAsciiStr ); 626 xub_StrLen nSPos = SearchAscii( pAsciiStr, 0 ); 627 while ( nSPos != STRING_NOTFOUND ) 628 { 629 Replace( nSPos, nCharLen, rRepStr ); 630 nSPos = nSPos + rRepStr.Len(); 631 nSPos = SearchAscii( pAsciiStr, nSPos ); 632 } 633 } 634