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 if( nLen <= STRING_MAXLEN - nLineEndLen ) 1152 nLen = nLen + nLineEndLen; 1153 else 1154 nLen = STRING_MAXLEN; 1155 1156 // Wenn schon gesetzt, dann brauchen wir keine aufwendige Abfrage 1157 if ( !bConvert ) 1158 { 1159 // Muessen wir Konvertieren 1160 if ( ((eLineEnd != LINEEND_LF) && (pStr[i] == _LF)) || 1161 ((eLineEnd == LINEEND_CRLF) && (pStr[i+1] != _LF)) || 1162 ((eLineEnd == LINEEND_LF) && 1163 ((pStr[i] == _CR) || (pStr[i+1] == _CR))) || 1164 ((eLineEnd == LINEEND_CR) && 1165 ((pStr[i] == _LF) || (pStr[i+1] == _LF))) ) 1166 bConvert = sal_True; 1167 } 1168 1169 // \r\n oder \n\r, dann Zeichen ueberspringen 1170 if ( ((pStr[i+1] == _CR) || (pStr[i+1] == _LF)) && 1171 (pStr[i] != pStr[i+1]) ) 1172 ++i; 1173 } 1174 else 1175 { 1176 if( nLen < STRING_MAXLEN ) 1177 ++nLen; 1178 } 1179 ++i; 1180 1181 // Wenn String zu lang, dann konvertieren wir nicht 1182 if ( nLen >= STRING_MAXLEN ) 1183 return *this; 1184 } 1185 1186 // Zeilenumbrueche konvertieren 1187 if ( bConvert ) 1188 { 1189 // Neuen String anlegen 1190 STRINGDATA* pNewData = ImplAllocData( nLen ); 1191 xub_StrLen j = 0; 1192 i = 0; 1193 while ( i < mpData->mnLen ) 1194 { 1195 // Bei \r oder \n gibt es neuen Zeilenumbruch 1196 if ( (pStr[i] == _CR) || (pStr[i] == _LF) ) 1197 { 1198 if ( eLineEnd == LINEEND_CRLF ) 1199 { 1200 pNewData->maStr[j] = _CR; 1201 pNewData->maStr[j+1] = _LF; 1202 j += 2; 1203 } 1204 else 1205 { 1206 if ( eLineEnd == LINEEND_CR ) 1207 pNewData->maStr[j] = _CR; 1208 else 1209 pNewData->maStr[j] = _LF; 1210 ++j; 1211 } 1212 1213 if ( ((pStr[i+1] == _CR) || (pStr[i+1] == _LF)) && 1214 (pStr[i] != pStr[i+1]) ) 1215 ++i; 1216 } 1217 else 1218 { 1219 pNewData->maStr[j] = mpData->maStr[i]; 1220 ++j; 1221 } 1222 1223 ++i; 1224 } 1225 1226 // Alte Daten loeschen und Neue zuweisen 1227 STRING_RELEASE((STRING_TYPE *)mpData); 1228 mpData = pNewData; 1229 } 1230 1231 return *this; 1232 } 1233 1234 // ----------------------------------------------------------------------- 1235 1236 StringCompare STRING::CompareTo( const STRING& rStr, xub_StrLen nLen ) const 1237 { 1238 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1239 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING ); 1240 1241 // Auf Gleichheit der Pointer testen 1242 if ( mpData == rStr.mpData ) 1243 return COMPARE_EQUAL; 1244 1245 // Maximale Laenge ermitteln 1246 if ( mpData->mnLen < nLen ) 1247 nLen = static_cast< xub_StrLen >(mpData->mnLen+1); 1248 if ( rStr.mpData->mnLen < nLen ) 1249 nLen = static_cast< xub_StrLen >(rStr.mpData->mnLen+1); 1250 1251 // String vergleichen 1252 sal_Int32 nCompare = ImplStringCompareWithoutZero( mpData->maStr, rStr.mpData->maStr, nLen ); 1253 1254 // Rueckgabewert anpassen 1255 if ( nCompare == 0 ) 1256 return COMPARE_EQUAL; 1257 else if ( nCompare < 0 ) 1258 return COMPARE_LESS; 1259 else 1260 return COMPARE_GREATER; 1261 } 1262 1263 // ----------------------------------------------------------------------- 1264 1265 StringCompare STRING::CompareTo( const STRCODE* pCharStr, xub_StrLen nLen ) const 1266 { 1267 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1268 1269 // String vergleichen 1270 sal_Int32 nCompare = ImplStringCompare( mpData->maStr, pCharStr, nLen ); 1271 1272 // Rueckgabewert anpassen 1273 if ( nCompare == 0 ) 1274 return COMPARE_EQUAL; 1275 else if ( nCompare < 0 ) 1276 return COMPARE_LESS; 1277 else 1278 return COMPARE_GREATER; 1279 } 1280 1281 // ----------------------------------------------------------------------- 1282 1283 StringCompare STRING::CompareIgnoreCaseToAscii( const STRING& rStr, 1284 xub_StrLen nLen ) const 1285 { 1286 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1287 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING ); 1288 1289 // Auf Gleichheit der Pointer testen 1290 if ( mpData == rStr.mpData ) 1291 return COMPARE_EQUAL; 1292 1293 // Maximale Laenge ermitteln 1294 if ( mpData->mnLen < nLen ) 1295 nLen = static_cast< xub_StrLen >(mpData->mnLen+1); 1296 if ( rStr.mpData->mnLen < nLen ) 1297 nLen = static_cast< xub_StrLen >(rStr.mpData->mnLen+1); 1298 1299 // String vergleichen 1300 sal_Int32 nCompare = ImplStringICompareWithoutZero( mpData->maStr, rStr.mpData->maStr, nLen ); 1301 1302 // Rueckgabewert anpassen 1303 if ( nCompare == 0 ) 1304 return COMPARE_EQUAL; 1305 else if ( nCompare < 0 ) 1306 return COMPARE_LESS; 1307 else 1308 return COMPARE_GREATER; 1309 } 1310 1311 // ----------------------------------------------------------------------- 1312 1313 StringCompare STRING::CompareIgnoreCaseToAscii( const STRCODE* pCharStr, 1314 xub_StrLen nLen ) const 1315 { 1316 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1317 1318 // String vergleichen 1319 sal_Int32 nCompare = ImplStringICompare( mpData->maStr, pCharStr, nLen ); 1320 1321 // Rueckgabewert anpassen 1322 if ( nCompare == 0 ) 1323 return COMPARE_EQUAL; 1324 else if ( nCompare < 0 ) 1325 return COMPARE_LESS; 1326 else 1327 return COMPARE_GREATER; 1328 } 1329 1330 // ----------------------------------------------------------------------- 1331 1332 sal_Bool STRING::Equals( const STRING& rStr ) const 1333 { 1334 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1335 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING ); 1336 1337 // Sind die Daten gleich 1338 if ( mpData == rStr.mpData ) 1339 return sal_True; 1340 1341 // Gleiche Laenge 1342 if ( mpData->mnLen != rStr.mpData->mnLen ) 1343 return sal_False; 1344 1345 // String vergleichen 1346 return (ImplStringCompareWithoutZero( mpData->maStr, rStr.mpData->maStr, mpData->mnLen ) == 0); 1347 } 1348 1349 // ----------------------------------------------------------------------- 1350 1351 sal_Bool STRING::Equals( const STRCODE* pCharStr ) const 1352 { 1353 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1354 1355 return (ImplStringCompare( mpData->maStr, pCharStr ) == 0); 1356 } 1357 1358 // ----------------------------------------------------------------------- 1359 1360 sal_Bool STRING::EqualsIgnoreCaseAscii( const STRING& rStr ) const 1361 { 1362 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1363 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING ); 1364 1365 // Sind die Daten gleich 1366 if ( mpData == rStr.mpData ) 1367 return sal_True; 1368 1369 // Gleiche Laenge 1370 if ( mpData->mnLen != rStr.mpData->mnLen ) 1371 return sal_False; 1372 1373 // String vergleichen 1374 return (ImplStringICompareWithoutZero( mpData->maStr, rStr.mpData->maStr, mpData->mnLen ) == 0); 1375 } 1376 1377 // ----------------------------------------------------------------------- 1378 1379 sal_Bool STRING::EqualsIgnoreCaseAscii( const STRCODE* pCharStr ) const 1380 { 1381 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1382 1383 return (ImplStringICompare( mpData->maStr, pCharStr ) == 0); 1384 } 1385 1386 // ----------------------------------------------------------------------- 1387 1388 sal_Bool STRING::Equals( const STRING& rStr, xub_StrLen nIndex, xub_StrLen nLen ) const 1389 { 1390 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1391 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING ); 1392 1393 // Are there enough codes for comparing? 1394 if ( nIndex > mpData->mnLen ) 1395 return (rStr.mpData->mnLen == 0); 1396 sal_Int32 nMaxLen = mpData->mnLen-nIndex; 1397 if ( nMaxLen < nLen ) 1398 { 1399 if ( rStr.mpData->mnLen != nMaxLen ) 1400 return sal_False; 1401 nLen = static_cast< xub_StrLen >(nMaxLen); 1402 } 1403 1404 // String vergleichen 1405 return (ImplStringCompareWithoutZero( mpData->maStr+nIndex, rStr.mpData->maStr, nLen ) == 0); 1406 } 1407 1408 // ----------------------------------------------------------------------- 1409 1410 sal_Bool STRING::Equals( const STRCODE* pCharStr, xub_StrLen nIndex, xub_StrLen nLen ) const 1411 { 1412 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1413 1414 // Are there enough codes for comparing? 1415 if ( nIndex > mpData->mnLen ) 1416 return (*pCharStr == 0); 1417 1418 return (ImplStringCompare( mpData->maStr+nIndex, pCharStr, nLen ) == 0); 1419 } 1420 1421 // ----------------------------------------------------------------------- 1422 1423 sal_Bool STRING::EqualsIgnoreCaseAscii( const STRING& rStr, xub_StrLen nIndex, xub_StrLen nLen ) const 1424 { 1425 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1426 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING ); 1427 1428 // Are there enough codes for comparing? 1429 if ( nIndex > mpData->mnLen ) 1430 return (rStr.mpData->mnLen == 0); 1431 sal_Int32 nMaxLen = mpData->mnLen-nIndex; 1432 if ( nMaxLen < nLen ) 1433 { 1434 if ( rStr.mpData->mnLen != nMaxLen ) 1435 return sal_False; 1436 nLen = static_cast< xub_StrLen >(nMaxLen); 1437 } 1438 1439 // String vergleichen 1440 return (ImplStringICompareWithoutZero( mpData->maStr+nIndex, rStr.mpData->maStr, nLen ) == 0); 1441 } 1442 1443 // ----------------------------------------------------------------------- 1444 1445 sal_Bool STRING::EqualsIgnoreCaseAscii( const STRCODE* pCharStr, xub_StrLen nIndex, xub_StrLen nLen ) const 1446 { 1447 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1448 1449 // Are there enough codes for comparing? 1450 if ( nIndex > mpData->mnLen ) 1451 return (*pCharStr == 0); 1452 1453 return (ImplStringICompare( mpData->maStr+nIndex, pCharStr, nLen ) == 0); 1454 } 1455 1456 // ----------------------------------------------------------------------- 1457 1458 xub_StrLen STRING::Match( const STRING& rStr ) const 1459 { 1460 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1461 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING ); 1462 1463 // Ist dieser String leer 1464 if ( !mpData->mnLen ) 1465 return STRING_MATCH; 1466 1467 // Suche bis Stringende nach dem ersten nicht uebereinstimmenden Zeichen 1468 const STRCODE* pStr1 = mpData->maStr; 1469 const STRCODE* pStr2 = rStr.mpData->maStr; 1470 xub_StrLen i = 0; 1471 while ( i < mpData->mnLen ) 1472 { 1473 // Stimmt das Zeichen nicht ueberein, dann abbrechen 1474 if ( *pStr1 != *pStr2 ) 1475 return i; 1476 ++pStr1, 1477 ++pStr2, 1478 ++i; 1479 } 1480 1481 return STRING_MATCH; 1482 } 1483 1484 // ----------------------------------------------------------------------- 1485 1486 xub_StrLen STRING::Match( const STRCODE* pCharStr ) const 1487 { 1488 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1489 1490 // Ist dieser String leer 1491 if ( !mpData->mnLen ) 1492 return STRING_MATCH; 1493 1494 // Suche bis Stringende nach dem ersten nicht uebereinstimmenden Zeichen 1495 const STRCODE* pStr = mpData->maStr; 1496 xub_StrLen i = 0; 1497 while ( i < mpData->mnLen ) 1498 { 1499 // Stimmt das Zeichen nicht ueberein, dann abbrechen 1500 if ( *pStr != *pCharStr ) 1501 return i; 1502 ++pStr, 1503 ++pCharStr, 1504 ++i; 1505 } 1506 1507 return STRING_MATCH; 1508 } 1509 1510 // ----------------------------------------------------------------------- 1511 1512 xub_StrLen STRING::Search( STRCODE c, xub_StrLen nIndex ) const 1513 { 1514 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1515 1516 sal_Int32 nLen = mpData->mnLen; 1517 const STRCODE* pStr = mpData->maStr; 1518 pStr += nIndex; 1519 while ( nIndex < nLen ) 1520 { 1521 if ( *pStr == c ) 1522 return nIndex; 1523 ++pStr, 1524 ++nIndex; 1525 } 1526 1527 return STRING_NOTFOUND; 1528 } 1529 1530 // ----------------------------------------------------------------------- 1531 1532 xub_StrLen STRING::Search( const STRING& rStr, xub_StrLen nIndex ) const 1533 { 1534 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1535 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING ); 1536 1537 sal_Int32 nLen = mpData->mnLen; 1538 sal_Int32 nStrLen = rStr.mpData->mnLen; 1539 1540 // Falls die Laenge des uebergebenen Strings 0 ist oder der Index 1541 // hinter dem String liegt, dann wurde der String nicht gefunden 1542 if ( !nStrLen || (nIndex >= nLen) ) 1543 return STRING_NOTFOUND; 1544 1545 const STRCODE* pStr1 = mpData->maStr; 1546 pStr1 += nIndex; 1547 1548 if ( nStrLen == 1 ) 1549 { 1550 STRCODE cSearch = rStr.mpData->maStr[0]; 1551 while ( nIndex < nLen ) 1552 { 1553 if ( *pStr1 == cSearch ) 1554 return nIndex; 1555 ++pStr1, 1556 ++nIndex; 1557 } 1558 } 1559 else 1560 { 1561 const STRCODE* pStr2 = rStr.mpData->maStr; 1562 1563 // Nur innerhalb des Strings suchen 1564 while ( nLen - nIndex >= nStrLen ) 1565 { 1566 // Stimmt der String ueberein 1567 if ( ImplStringCompareWithoutZero( pStr1, pStr2, nStrLen ) == 0 ) 1568 return nIndex; 1569 ++pStr1, 1570 ++nIndex; 1571 } 1572 } 1573 1574 return STRING_NOTFOUND; 1575 } 1576 1577 // ----------------------------------------------------------------------- 1578 1579 xub_StrLen STRING::Search( const STRCODE* pCharStr, xub_StrLen nIndex ) const 1580 { 1581 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1582 1583 sal_Int32 nLen = mpData->mnLen; 1584 xub_StrLen nStrLen = ImplStringLen( pCharStr ); 1585 1586 // Falls die Laenge des uebergebenen Strings 0 ist oder der Index 1587 // hinter dem String liegt, dann wurde der String nicht gefunden 1588 if ( !nStrLen || (nIndex >= nLen) ) 1589 return STRING_NOTFOUND; 1590 1591 const STRCODE* pStr = mpData->maStr; 1592 pStr += nIndex; 1593 1594 if ( nStrLen == 1 ) 1595 { 1596 STRCODE cSearch = *pCharStr; 1597 while ( nIndex < nLen ) 1598 { 1599 if ( *pStr == cSearch ) 1600 return nIndex; 1601 ++pStr, 1602 ++nIndex; 1603 } 1604 } 1605 else 1606 { 1607 // Nur innerhalb des Strings suchen 1608 while ( nLen - nIndex >= nStrLen ) 1609 { 1610 // Stimmt der String ueberein 1611 if ( ImplStringCompareWithoutZero( pStr, pCharStr, nStrLen ) == 0 ) 1612 return nIndex; 1613 ++pStr, 1614 ++nIndex; 1615 } 1616 } 1617 1618 return STRING_NOTFOUND; 1619 } 1620 1621 // ----------------------------------------------------------------------- 1622 1623 xub_StrLen STRING::SearchBackward( STRCODE c, xub_StrLen nIndex ) const 1624 { 1625 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1626 1627 if ( nIndex > mpData->mnLen ) 1628 nIndex = (xub_StrLen)mpData->mnLen; 1629 1630 const STRCODE* pStr = mpData->maStr; 1631 pStr += nIndex; 1632 1633 while ( nIndex ) 1634 { 1635 nIndex--; 1636 pStr--; 1637 if ( *pStr == c ) 1638 return nIndex; 1639 } 1640 1641 return STRING_NOTFOUND; 1642 } 1643 1644 // ----------------------------------------------------------------------- 1645 1646 xub_StrLen STRING::SearchChar( const STRCODE* pChars, xub_StrLen nIndex ) const 1647 { 1648 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1649 1650 sal_Int32 nLen = mpData->mnLen; 1651 const STRCODE* pStr = mpData->maStr; 1652 pStr += nIndex; 1653 while ( nIndex < nLen ) 1654 { 1655 STRCODE c = *pStr; 1656 const STRCODE* pCompStr = pChars; 1657 while ( *pCompStr ) 1658 { 1659 if ( *pCompStr == c ) 1660 return nIndex; 1661 ++pCompStr; 1662 } 1663 ++pStr, 1664 ++nIndex; 1665 } 1666 1667 return STRING_NOTFOUND; 1668 } 1669 1670 // ----------------------------------------------------------------------- 1671 1672 xub_StrLen STRING::SearchCharBackward( const STRCODE* pChars, xub_StrLen nIndex ) const 1673 { 1674 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1675 1676 if ( nIndex > mpData->mnLen ) 1677 nIndex = (xub_StrLen)mpData->mnLen; 1678 1679 const STRCODE* pStr = mpData->maStr; 1680 pStr += nIndex; 1681 1682 while ( nIndex ) 1683 { 1684 nIndex--; 1685 pStr--; 1686 1687 STRCODE c =*pStr; 1688 const STRCODE* pCompStr = pChars; 1689 while ( *pCompStr ) 1690 { 1691 if ( *pCompStr == c ) 1692 return nIndex; 1693 ++pCompStr; 1694 } 1695 } 1696 1697 return STRING_NOTFOUND; 1698 } 1699 1700 // ----------------------------------------------------------------------- 1701 1702 xub_StrLen STRING::SearchAndReplace( STRCODE c, STRCODE cRep, xub_StrLen nIndex ) 1703 { 1704 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1705 1706 sal_Int32 nLen = mpData->mnLen; 1707 const STRCODE* pStr = mpData->maStr; 1708 pStr += nIndex; 1709 while ( nIndex < nLen ) 1710 { 1711 if ( *pStr == c ) 1712 { 1713 ImplCopyData(); 1714 mpData->maStr[nIndex] = cRep; 1715 return nIndex; 1716 } 1717 ++pStr, 1718 ++nIndex; 1719 } 1720 1721 return STRING_NOTFOUND; 1722 } 1723 1724 // ----------------------------------------------------------------------- 1725 1726 xub_StrLen STRING::SearchAndReplace( const STRING& rStr, const STRING& rRepStr, 1727 xub_StrLen nIndex ) 1728 { 1729 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1730 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING ); 1731 DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING ); 1732 1733 xub_StrLen nSPos = Search( rStr, nIndex ); 1734 if ( nSPos != STRING_NOTFOUND ) 1735 Replace( nSPos, rStr.Len(), rRepStr ); 1736 1737 return nSPos; 1738 } 1739 1740 // ----------------------------------------------------------------------- 1741 1742 xub_StrLen STRING::SearchAndReplace( const STRCODE* pCharStr, const STRING& rRepStr, 1743 xub_StrLen nIndex ) 1744 { 1745 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1746 DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING ); 1747 1748 xub_StrLen nSPos = Search( pCharStr, nIndex ); 1749 if ( nSPos != STRING_NOTFOUND ) 1750 Replace( nSPos, ImplStringLen( pCharStr ), rRepStr ); 1751 1752 return nSPos; 1753 } 1754 1755 // ----------------------------------------------------------------------- 1756 1757 void STRING::SearchAndReplaceAll( STRCODE c, STRCODE cRep ) 1758 { 1759 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1760 1761 sal_Int32 nLen = mpData->mnLen; 1762 const STRCODE* pStr = mpData->maStr; 1763 sal_Int32 nIndex = 0; 1764 while ( nIndex < nLen ) 1765 { 1766 if ( *pStr == c ) 1767 { 1768 ImplCopyData(); 1769 mpData->maStr[nIndex] = cRep; 1770 } 1771 ++pStr, 1772 ++nIndex; 1773 } 1774 } 1775 1776 // ----------------------------------------------------------------------- 1777 1778 void STRING::SearchAndReplaceAll( const STRCODE* pCharStr, const STRING& rRepStr ) 1779 { 1780 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1781 DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING ); 1782 1783 xub_StrLen nCharLen = ImplStringLen( pCharStr ); 1784 xub_StrLen nSPos = Search( pCharStr, 0 ); 1785 while ( nSPos != STRING_NOTFOUND ) 1786 { 1787 Replace( nSPos, nCharLen, rRepStr ); 1788 nSPos = nSPos + rRepStr.Len(); 1789 nSPos = Search( pCharStr, nSPos ); 1790 } 1791 } 1792 1793 // ----------------------------------------------------------------------- 1794 1795 void STRING::SearchAndReplaceAll( const STRING& rStr, const STRING& rRepStr ) 1796 { 1797 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1798 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING ); 1799 DBG_CHKOBJ( &rRepStr, STRING, DBGCHECKSTRING ); 1800 1801 xub_StrLen nSPos = Search( rStr, 0 ); 1802 while ( nSPos != STRING_NOTFOUND ) 1803 { 1804 Replace( nSPos, rStr.Len(), rRepStr ); 1805 nSPos = nSPos + rRepStr.Len(); 1806 nSPos = Search( rStr, nSPos ); 1807 } 1808 } 1809 1810 // ----------------------------------------------------------------------- 1811 1812 xub_StrLen STRING::GetTokenCount( STRCODE cTok ) const 1813 { 1814 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1815 1816 // Leerer String: TokenCount per Definition 0 1817 if ( !mpData->mnLen ) 1818 return 0; 1819 1820 xub_StrLen nTokCount = 1; 1821 sal_Int32 nLen = mpData->mnLen; 1822 const STRCODE* pStr = mpData->maStr; 1823 sal_Int32 nIndex = 0; 1824 while ( nIndex < nLen ) 1825 { 1826 // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount 1827 if ( *pStr == cTok ) 1828 ++nTokCount; 1829 ++pStr, 1830 ++nIndex; 1831 } 1832 1833 return nTokCount; 1834 } 1835 1836 // ----------------------------------------------------------------------- 1837 1838 void STRING::SetToken( xub_StrLen nToken, STRCODE cTok, const STRING& rStr, 1839 xub_StrLen nIndex ) 1840 { 1841 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1842 DBG_CHKOBJ( &rStr, STRING, DBGCHECKSTRING ); 1843 1844 const STRCODE* pStr = mpData->maStr; 1845 xub_StrLen nLen = (xub_StrLen)mpData->mnLen; 1846 xub_StrLen nTok = 0; 1847 xub_StrLen nFirstChar = nIndex; 1848 xub_StrLen i = nFirstChar; 1849 1850 // Bestimme die Token-Position und Laenge 1851 pStr += i; 1852 while ( i < nLen ) 1853 { 1854 // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount 1855 if ( *pStr == cTok ) 1856 { 1857 ++nTok; 1858 1859 if ( nTok == nToken ) 1860 nFirstChar = i+1; 1861 else 1862 { 1863 if ( nTok > nToken ) 1864 break; 1865 } 1866 } 1867 1868 ++pStr, 1869 ++i; 1870 } 1871 1872 if ( nTok >= nToken ) 1873 Replace( nFirstChar, i-nFirstChar, rStr ); 1874 } 1875 1876 // ----------------------------------------------------------------------- 1877 1878 STRING STRING::GetToken( xub_StrLen nToken, STRCODE cTok, xub_StrLen& rIndex ) const 1879 { 1880 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1881 1882 const STRCODE* pStr = mpData->maStr; 1883 xub_StrLen nLen = (xub_StrLen)mpData->mnLen; 1884 xub_StrLen nTok = 0; 1885 xub_StrLen nFirstChar = rIndex; 1886 xub_StrLen i = nFirstChar; 1887 1888 // Bestimme die Token-Position und Laenge 1889 pStr += i; 1890 while ( i < nLen ) 1891 { 1892 // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount 1893 if ( *pStr == cTok ) 1894 { 1895 ++nTok; 1896 1897 if ( nTok == nToken ) 1898 nFirstChar = i+1; 1899 else 1900 { 1901 if ( nTok > nToken ) 1902 break; 1903 } 1904 } 1905 1906 ++pStr, 1907 ++i; 1908 } 1909 1910 if ( nTok >= nToken ) 1911 { 1912 if ( i < nLen ) 1913 rIndex = i+1; 1914 else 1915 rIndex = STRING_NOTFOUND; 1916 return Copy( nFirstChar, i-nFirstChar ); 1917 } 1918 else 1919 { 1920 rIndex = STRING_NOTFOUND; 1921 return STRING(); 1922 } 1923 } 1924 1925 // ----------------------------------------------------------------------- 1926 1927 xub_StrLen STRING::GetQuotedTokenCount( const STRING& rQuotedPairs, STRCODE cTok ) const 1928 { 1929 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1930 DBG_CHKOBJ( &rQuotedPairs, STRING, DBGCHECKSTRING ); 1931 DBG_ASSERT( !(rQuotedPairs.Len()%2), "String::GetQuotedTokenCount() - QuotedString%2 != 0" ); 1932 DBG_ASSERT( rQuotedPairs.Search(cTok) == STRING_NOTFOUND, "String::GetQuotedTokenCount() - cTok in QuotedString" ); 1933 1934 // Leerer String: TokenCount per Definition 0 1935 if ( !mpData->mnLen ) 1936 return 0; 1937 1938 xub_StrLen nTokCount = 1; 1939 sal_Int32 nLen = mpData->mnLen; 1940 xub_StrLen nQuotedLen = rQuotedPairs.Len(); 1941 STRCODE cQuotedEndChar = 0; 1942 const STRCODE* pQuotedStr = rQuotedPairs.mpData->maStr; 1943 const STRCODE* pStr = mpData->maStr; 1944 sal_Int32 nIndex = 0; 1945 while ( nIndex < nLen ) 1946 { 1947 STRCODE c = *pStr; 1948 if ( cQuotedEndChar ) 1949 { 1950 // Ende des Quotes erreicht ? 1951 if ( c == cQuotedEndChar ) 1952 cQuotedEndChar = 0; 1953 } 1954 else 1955 { 1956 // Ist das Zeichen ein Quote-Anfang-Zeichen ? 1957 xub_StrLen nQuoteIndex = 0; 1958 while ( nQuoteIndex < nQuotedLen ) 1959 { 1960 if ( pQuotedStr[nQuoteIndex] == c ) 1961 { 1962 cQuotedEndChar = pQuotedStr[nQuoteIndex+1]; 1963 break; 1964 } 1965 else 1966 nQuoteIndex += 2; 1967 } 1968 1969 // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount 1970 if ( c == cTok ) 1971 ++nTokCount; 1972 } 1973 1974 ++pStr, 1975 ++nIndex; 1976 } 1977 1978 return nTokCount; 1979 } 1980 1981 // ----------------------------------------------------------------------- 1982 1983 STRING STRING::GetQuotedToken( xub_StrLen nToken, const STRING& rQuotedPairs, 1984 STRCODE cTok, xub_StrLen& rIndex ) const 1985 { 1986 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 1987 DBG_CHKOBJ( &rQuotedPairs, STRING, DBGCHECKSTRING ); 1988 DBG_ASSERT( !(rQuotedPairs.Len()%2), "String::GetQuotedToken() - QuotedString%2 != 0" ); 1989 DBG_ASSERT( rQuotedPairs.Search(cTok) == STRING_NOTFOUND, "String::GetQuotedToken() - cTok in QuotedString" ); 1990 1991 const STRCODE* pStr = mpData->maStr; 1992 const STRCODE* pQuotedStr = rQuotedPairs.mpData->maStr; 1993 STRCODE cQuotedEndChar = 0; 1994 xub_StrLen nQuotedLen = rQuotedPairs.Len(); 1995 xub_StrLen nLen = (xub_StrLen)mpData->mnLen; 1996 xub_StrLen nTok = 0; 1997 xub_StrLen nFirstChar = rIndex; 1998 xub_StrLen i = nFirstChar; 1999 2000 // Bestimme die Token-Position und Laenge 2001 pStr += i; 2002 while ( i < nLen ) 2003 { 2004 STRCODE c = *pStr; 2005 if ( cQuotedEndChar ) 2006 { 2007 // Ende des Quotes erreicht ? 2008 if ( c == cQuotedEndChar ) 2009 cQuotedEndChar = 0; 2010 } 2011 else 2012 { 2013 // Ist das Zeichen ein Quote-Anfang-Zeichen ? 2014 xub_StrLen nQuoteIndex = 0; 2015 while ( nQuoteIndex < nQuotedLen ) 2016 { 2017 if ( pQuotedStr[nQuoteIndex] == c ) 2018 { 2019 cQuotedEndChar = pQuotedStr[nQuoteIndex+1]; 2020 break; 2021 } 2022 else 2023 nQuoteIndex += 2; 2024 } 2025 2026 // Stimmt das Tokenzeichen ueberein, dann erhoehe TokCount 2027 if ( c == cTok ) 2028 { 2029 ++nTok; 2030 2031 if ( nTok == nToken ) 2032 nFirstChar = i+1; 2033 else 2034 { 2035 if ( nTok > nToken ) 2036 break; 2037 } 2038 } 2039 } 2040 2041 ++pStr, 2042 ++i; 2043 } 2044 2045 if ( nTok >= nToken ) 2046 { 2047 if ( i < nLen ) 2048 rIndex = i+1; 2049 else 2050 rIndex = STRING_NOTFOUND; 2051 return Copy( nFirstChar, i-nFirstChar ); 2052 } 2053 else 2054 { 2055 rIndex = STRING_NOTFOUND; 2056 return STRING(); 2057 } 2058 } 2059 2060 // ----------------------------------------------------------------------- 2061 2062 STRCODE* STRING::GetBufferAccess() 2063 { 2064 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 2065 2066 // Daten kopieren, wenn noetig 2067 if ( mpData->mnLen ) 2068 ImplCopyData(); 2069 2070 // Pointer auf den String zurueckgeben 2071 return mpData->maStr; 2072 } 2073 2074 // ----------------------------------------------------------------------- 2075 2076 void STRING::ReleaseBufferAccess( xub_StrLen nLen ) 2077 { 2078 // Hier ohne Funktionstest, da String nicht konsistent 2079 DBG_CHKTHIS( STRING, NULL ); 2080 DBG_ASSERT( mpData->mnRefCount == 1, "String::ReleaseCharStr() called for String with RefCount" ); 2081 2082 if ( nLen > mpData->mnLen ) 2083 nLen = ImplStringLen( mpData->maStr ); 2084 OSL_ASSERT(nLen <= mpData->mnLen); 2085 if ( !nLen ) 2086 { 2087 STRING_NEW((STRING_TYPE **)&mpData); 2088 } 2089 // Bei mehr als 8 Zeichen unterschied, kuerzen wir den Buffer 2090 else if ( mpData->mnLen - nLen > 8 ) 2091 { 2092 STRINGDATA* pNewData = ImplAllocData( nLen ); 2093 memcpy( pNewData->maStr, mpData->maStr, nLen*sizeof( STRCODE ) ); 2094 STRING_RELEASE((STRING_TYPE *)mpData); 2095 mpData = pNewData; 2096 } 2097 else 2098 mpData->mnLen = nLen; 2099 } 2100 2101 // ----------------------------------------------------------------------- 2102 2103 STRCODE* STRING::AllocBuffer( xub_StrLen nLen ) 2104 { 2105 DBG_CHKTHIS( STRING, DBGCHECKSTRING ); 2106 2107 STRING_RELEASE((STRING_TYPE *)mpData); 2108 if ( nLen ) 2109 mpData = ImplAllocData( nLen ); 2110 else 2111 { 2112 mpData = NULL; 2113 STRING_NEW((STRING_TYPE **)&mpData); 2114 } 2115 2116 return mpData->maStr; 2117 } 2118