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