1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include <precomp.h> 29 #include <cosv/streamstr.hxx> 30 31 // NOT FULLY DECLARED SERVICES 32 #include <string.h> 33 #include <stdio.h> 34 #include <stdarg.h> // both are needed to satisfy all compilers 35 #include <cstdarg> // std::va_list and friends 36 37 #include <cosv/comfunc.hxx> 38 #include <cosv/tpl/swelist.hxx> 39 40 41 42 namespace csv 43 { 44 45 46 // Maximal sizes of resulting integers in text form: 47 const uintt C_short_max_size = sizeof(short) * 3; 48 const uintt C_int_max_size = sizeof(int) * 3; 49 const uintt C_long_max_size = sizeof(long) * 3; 50 51 52 inline void 53 StreamStr::Advance(size_type i_nAddedSize) 54 { pCur += i_nAddedSize; } 55 56 57 58 StreamStr::StreamStr( size_type i_nCapacity ) 59 : bostream(), 60 nCapacity1( i_nCapacity + 1 ), 61 dpData( new char [i_nCapacity + 1] ), 62 pEnd(dpData), 63 pCur(dpData), 64 eMode(str::overwrite) 65 { 66 *pEnd = '\0'; 67 } 68 69 StreamStr::StreamStr( const char * i_sInitStr, 70 size_type i_nCapacity ) 71 : bostream(), 72 nCapacity1(0), 73 dpData(0), 74 pEnd(0), 75 pCur(0), 76 eMode(str::overwrite) 77 { 78 size_type nLength = strlen(i_sInitStr); 79 nCapacity1 = csv::max(nLength, i_nCapacity) + 1; 80 dpData = new char [nCapacity1]; 81 strcpy(dpData, i_sInitStr); // SAFE STRCPY (#100211# - checked) 82 pCur = dpData + nLength; 83 pEnd = pCur; 84 } 85 86 StreamStr::StreamStr( size_type i_nGuessedCapacity, 87 const char * str1, 88 const char * str2, 89 ... ) 90 : bostream(), 91 nCapacity1( i_nGuessedCapacity + 1 ), 92 dpData( new char [i_nGuessedCapacity + 1] ), 93 pEnd(dpData), 94 pCur(dpData), 95 eMode(str::overwrite) 96 { 97 *pEnd = '\0'; 98 99 operator<<(str1); 100 operator<<(str2); 101 102 ::va_list ap; 103 104 va_start(ap, str2); 105 for ( const char * strAdd = va_arg(ap,const char*); 106 strAdd != 0; 107 strAdd = va_arg(ap,const char*) ) 108 { 109 size_type nLen = strlen(strAdd); 110 ProvideAddingSize( nLen ); 111 memcpy(pCur, strAdd, nLen); 112 Advance(nLen); 113 } // end for 114 va_end(ap); 115 } 116 117 StreamStr::StreamStr( const self & i_rOther ) 118 : bostream(), 119 nCapacity1( i_rOther.nCapacity1 ), 120 dpData( new char [i_rOther.nCapacity1] ), 121 pEnd( dpData + strlen(i_rOther.dpData) ), 122 pCur( dpData + i_rOther.tellp() ), 123 eMode(i_rOther.eMode) 124 { 125 strcpy( dpData, i_rOther.dpData ); // SAFE STRCPY (#100211# - checked) 126 } 127 128 StreamStr::StreamStr(csv::bstream & i_source) 129 : bostream(), 130 nCapacity1(0), 131 dpData(0), 132 pEnd(0), 133 pCur(0), 134 eMode(str::overwrite) 135 { 136 i_source.seek(0, csv::end); 137 nCapacity1 = static_cast<size_type>(i_source.position()) + 1; 138 i_source.seek(0); 139 140 dpData = new char[nCapacity1]; 141 i_source.read(dpData, nCapacity1 - 1); 142 pCur = dpData + nCapacity1 - 1; 143 pEnd = pCur; 144 *pCur = '\0'; 145 } 146 147 StreamStr::~StreamStr() 148 { 149 delete [] dpData; 150 } 151 152 153 StreamStr & 154 StreamStr::operator=( const self & i_rOther ) 155 { 156 delete [] dpData; 157 158 nCapacity1 = i_rOther.nCapacity1; 159 dpData = new char [i_rOther.nCapacity1]; 160 pEnd = dpData + strlen(i_rOther.dpData); 161 strcpy( dpData, i_rOther.dpData ); // SAFE STRCPY (#100211# - checked) 162 pCur = dpData + i_rOther.tellp(); 163 eMode = i_rOther.eMode; 164 165 return *this; 166 } 167 168 StreamStr & 169 StreamStr::operator<<( const char * i_s ) 170 { 171 size_type nLength = strlen(i_s); 172 173 ProvideAddingSize( nLength ); 174 memcpy( pCur, i_s, nLength ); 175 Advance(nLength); 176 177 return *this; 178 } 179 180 StreamStr & 181 StreamStr::operator<<( const String & i_s ) 182 { 183 size_type nLength = i_s.length(); 184 185 ProvideAddingSize( nLength ); 186 memcpy( pCur, i_s.c_str(), nLength ); 187 Advance(nLength); 188 189 return *this; 190 } 191 192 StreamStr & 193 StreamStr::operator<<( char i_c ) 194 { 195 ProvideAddingSize( 1 ); 196 *pCur = i_c; 197 Advance(1); 198 199 return *this; 200 } 201 202 StreamStr & 203 StreamStr::operator<<( unsigned char i_c ) 204 { 205 return operator<<( char(i_c) ); 206 } 207 208 StreamStr & 209 StreamStr::operator<<( signed char i_c ) 210 { 211 return operator<<( char(i_c) ); 212 } 213 214 StreamStr & 215 StreamStr::operator<<( short i_n ) 216 { 217 char buf[C_short_max_size] = ""; 218 sprintf( buf, "%hi", i_n ); // SAFE SPRINTF (#100211# - checked) 219 220 size_type nLength = strlen(buf); 221 ProvideAddingSize( nLength ); 222 memcpy( pCur, buf, nLength ); 223 Advance( nLength ); 224 225 return *this; 226 } 227 228 StreamStr & 229 StreamStr::operator<<( unsigned short i_n ) 230 { 231 char buf[C_short_max_size] = ""; 232 sprintf( buf, "%hu", i_n ); // SAFE SPRINTF (#100211# - checked) 233 234 size_type nLength = strlen(buf); 235 ProvideAddingSize( nLength ); 236 memcpy( pCur, buf, nLength ); 237 Advance( nLength ); 238 239 return *this; 240 } 241 242 StreamStr & 243 StreamStr::operator<<( int i_n ) 244 { 245 char buf[C_int_max_size] = ""; 246 sprintf( buf, "%i", i_n ); // SAFE SPRINTF (#100211# - checked) 247 248 size_type nLength = strlen(buf); 249 ProvideAddingSize( nLength ); 250 memcpy( pCur, buf, nLength ); 251 Advance( nLength ); 252 253 return *this; 254 } 255 256 StreamStr & 257 StreamStr::operator<<( unsigned int i_n ) 258 { 259 char buf[C_int_max_size] = ""; 260 sprintf( buf, "%u", i_n ); // SAFE SPRINTF (#100211# - checked) 261 262 size_type nLength = strlen(buf); 263 ProvideAddingSize( nLength ); 264 memcpy( pCur, buf, nLength ); 265 Advance( nLength ); 266 267 return *this; 268 } 269 270 StreamStr & 271 StreamStr::operator<<( long i_n ) 272 { 273 char buf[C_long_max_size] = ""; 274 sprintf( buf, "%li", i_n ); // SAFE SPRINTF (#100211# - checked) 275 276 size_type nLength = strlen(buf); 277 ProvideAddingSize( nLength ); 278 memcpy( pCur, buf, nLength ); 279 Advance( nLength ); 280 281 return *this; 282 } 283 284 StreamStr & 285 StreamStr::operator<<( unsigned long i_n ) 286 { 287 char buf[C_long_max_size] = ""; 288 sprintf( buf, "%lu", i_n ); // SAFE SPRINTF (#100211# - checked) 289 290 size_type nLength = strlen(buf); 291 ProvideAddingSize( nLength ); 292 memcpy( pCur, buf, nLength ); 293 Advance( nLength ); 294 295 return *this; 296 } 297 298 StreamStr & 299 StreamStr::operator<<( float i_n ) 300 { 301 const int C_float_max_size = 20; 302 char buf[C_float_max_size] = ""; 303 sprintf( buf, "%.*g", C_float_max_size-8, i_n ); // SAFE SPRINTF (#100211# - checked) 304 305 size_type nLength = strlen(buf); 306 ProvideAddingSize( nLength ); 307 memcpy( pCur, buf, nLength ); 308 Advance( nLength ); 309 310 return *this; 311 } 312 313 StreamStr & 314 StreamStr::operator<<( double i_n ) 315 { 316 const int C_double_max_size = 30; 317 char buf[C_double_max_size] = ""; 318 sprintf( buf, "%.*lg", C_double_max_size-8, i_n ); // SAFE SPRINTF (#100211# - checked) 319 320 size_type nLength = strlen(buf); 321 ProvideAddingSize( nLength ); 322 memcpy( pCur, buf, nLength ); 323 Advance( nLength ); 324 325 return *this; 326 } 327 328 const char & 329 StreamStr::operator[]( position_type i_nPosition ) const 330 { 331 static const char aNull_ = '\0'; 332 333 if ( position_type(pEnd - dpData) > i_nPosition ) 334 return dpData[i_nPosition]; 335 return aNull_; 336 } 337 338 char & 339 StreamStr::operator[]( position_type i_nPosition ) 340 { 341 static char aDummy_ = '\0'; 342 343 if ( position_type(pEnd - dpData) > i_nPosition ) 344 return dpData[i_nPosition]; 345 return aDummy_; 346 } 347 348 void 349 StreamStr::resize( size_type i_nMinimumCapacity ) 350 { 351 if ( i_nMinimumCapacity <= capacity() ) 352 return; 353 354 Resize(i_nMinimumCapacity); 355 } 356 357 void 358 StreamStr::swap( StreamStr & io_swap ) 359 { 360 size_type 361 n = io_swap.nCapacity1; 362 io_swap.nCapacity1 = nCapacity1; 363 nCapacity1 = n; 364 365 char * 366 p = io_swap.dpData; 367 io_swap.dpData = dpData; 368 dpData = p; 369 370 p = io_swap.pEnd; 371 io_swap.pEnd = pEnd; 372 pEnd = p; 373 374 p = io_swap.pCur; 375 io_swap.pCur = pCur; 376 pCur = p; 377 378 insert_mode 379 m = io_swap.eMode; 380 io_swap.eMode = eMode; 381 eMode = m; 382 } 383 384 StreamStr & 385 StreamStr::seekp( seek_type i_nCount, 386 seek_dir i_eDirection ) 387 { 388 seek_type nLength = seek_type( length() ); 389 seek_type nNewPos = tellp(); 390 391 switch ( i_eDirection ) 392 { 393 case ::csv::beg: nNewPos = i_nCount; 394 break; 395 case ::csv::cur: nNewPos += i_nCount; 396 break; 397 case ::csv::end: nNewPos = nLength + i_nCount; 398 break; 399 } 400 401 if ( in_range<seek_type>(0, nNewPos, nLength + 1) ) 402 { 403 pCur = dpData + nNewPos; 404 if (eMode == str::overwrite) 405 { 406 pEnd = pCur; 407 *pEnd = '\0'; 408 } 409 } 410 411 return *this; 412 } 413 414 StreamStr & 415 StreamStr::set_insert_mode( insert_mode i_eMode ) 416 { 417 eMode = i_eMode; 418 return *this; 419 } 420 421 void 422 StreamStr::push_front( const char * i_str ) 423 { 424 insert_mode eOriginalMode = eMode; 425 char * pOriginalCur = pCur; 426 eMode = str::insert; 427 pCur = dpData; 428 429 operator<<(i_str); 430 431 eMode = eOriginalMode; 432 pCur = pOriginalCur + strlen(i_str); 433 } 434 435 void 436 StreamStr::push_front( char i_c ) 437 { 438 insert_mode eOriginalMode = eMode; 439 char * pOriginalCur = pCur; 440 eMode = str::insert; 441 pCur = dpData; 442 443 operator<<(i_c); 444 445 eMode = eOriginalMode; 446 pCur = pOriginalCur + 1; 447 } 448 449 void 450 StreamStr::push_back( const char * i_str ) 451 { 452 insert_mode eOriginalMode = eMode; 453 eMode = str::overwrite; 454 455 operator<<(i_str); 456 457 eMode = eOriginalMode; 458 } 459 460 void 461 StreamStr::push_back( char i_c ) 462 { 463 insert_mode eOriginalMode = eMode; 464 eMode = str::overwrite; 465 466 operator<<(i_c); 467 468 eMode = eOriginalMode; 469 } 470 471 void 472 StreamStr::pop_front( size_type i_nCount ) 473 { 474 size_type nCount = min(i_nCount, length()); 475 476 MoveData( dpData + nCount, pEnd, -(seek_type(nCount)) ); 477 478 pCur -= nCount; 479 pEnd -= nCount; 480 *pEnd = '\0'; 481 } 482 483 void 484 StreamStr::pop_back( size_type i_nCount ) 485 { 486 size_type nCount = min(i_nCount, length()); 487 pEnd -= nCount; 488 if (pCur > pEnd) 489 pCur = pEnd; 490 *pEnd = '\0'; 491 } 492 493 StreamStr & 494 StreamStr::operator_join( std::vector<String>::const_iterator i_rBegin, 495 std::vector<String>::const_iterator i_rEnd, 496 const char * i_sLink ) 497 { 498 std::vector<String>::const_iterator it = i_rBegin; 499 if ( it != i_rEnd ) 500 { 501 operator<<(*it); 502 for ( ++it; it != i_rEnd; ++it ) 503 { 504 operator<<(i_sLink); 505 operator<<(*it); 506 } 507 } 508 return *this; 509 } 510 511 StreamStr & 512 StreamStr::operator_add_substr( const char * i_sText, 513 size_type i_nLength ) 514 { 515 size_type nLength = csv::min<size_type>(i_nLength, strlen(i_sText)); 516 517 ProvideAddingSize( nLength ); 518 memcpy( pCur, i_sText, nLength ); 519 Advance(nLength); 520 521 return *this; 522 } 523 524 StreamStr & 525 StreamStr::operator_add_token( const char * i_sText, 526 char i_cDelimiter ) 527 { 528 const char * pTokenEnd = strchr(i_sText, i_cDelimiter); 529 if (pTokenEnd == 0) 530 operator<<(i_sText); 531 else 532 operator_add_substr(i_sText, pTokenEnd-i_sText); 533 return *this; 534 } 535 536 StreamStr & 537 StreamStr::operator_read_line( bstream & i_src ) 538 { 539 char c = 0; 540 intt nCount = 0; 541 for ( nCount = i_src.read(&c, 1); 542 nCount == 1 AND c != 13 AND c != 10; 543 nCount = i_src.read(&c, 1) ) 544 { 545 operator<<(c); 546 } 547 548 bool bEndOfStream = nCount == 0; 549 // Check for line-end: 550 if ( NOT bEndOfStream AND c != 0 ) 551 { 552 char oldc = c; 553 if (i_src.read(&c, 1) == 1) 554 { 555 if ( (c != 13 AND c != 10) OR c == oldc) 556 i_src.seek(-1,::csv::cur); 557 } 558 } 559 return *this; 560 } 561 562 void 563 StreamStr::strip_front(char i_cToRemove) 564 { 565 const_iterator it = begin(); 566 for ( ; 567 it != end() ? *it == i_cToRemove : false; 568 ++it ) ; 569 pop_front(it - begin()); 570 } 571 572 void 573 StreamStr::strip_back(char i_cToRemove) 574 { 575 const_iterator it = end(); 576 for ( ; 577 it != begin() ? *(it-1) == i_cToRemove : false; 578 --it ) ; 579 pop_back(end() - it); 580 } 581 582 void 583 StreamStr::strip_frontback(char i_cToRemove) 584 { 585 strip_front(i_cToRemove); 586 strip_back(i_cToRemove); 587 } 588 589 void 590 StreamStr::strip_front_whitespace() 591 { 592 const_iterator it = begin(); 593 for ( ; 594 it != end() ? *it < 33 : false; 595 ++it ) ; 596 pop_front(it - begin()); 597 } 598 599 void 600 StreamStr::strip_back_whitespace() 601 { 602 const_iterator it = end(); 603 for ( ; 604 it != begin() ? *(it-1) < 33 : false; 605 --it ) ; 606 pop_back(end() - it); 607 } 608 609 void 610 StreamStr::strip_frontback_whitespace() 611 { 612 strip_front_whitespace(); 613 strip_back_whitespace(); 614 } 615 616 void 617 StreamStr::remove( iterator i_begin, 618 iterator i_end ) 619 { 620 csv_assert(i_begin >= dpData AND i_begin <= pEnd); 621 csv_assert(i_end >= dpData AND i_end <= pEnd); 622 csv_assert(i_end >= i_begin); 623 MoveData(i_end, pEnd, i_begin - i_end); 624 pCur = pEnd; 625 } 626 627 void 628 StreamStr::replace( position_type i_nStart, 629 size_type i_nSize, 630 Area i_aReplacement ) 631 { 632 if (i_nStart >= length() OR i_nSize < 1) 633 return; 634 635 insert_mode eOldMode = eMode; 636 eMode = str::insert; 637 pCur = dpData + i_nStart; 638 639 size_type anz = min( length() - i_nStart, i_nSize ); 640 641 if ( anz < i_aReplacement.nLength ) 642 { 643 ProvideAddingSize( i_aReplacement.nLength - anz ); 644 } 645 else if ( anz > i_aReplacement.nLength ) 646 { 647 seek_type nMove = seek_type(anz - i_aReplacement.nLength); 648 649 MoveData( dpData + i_nStart + anz, 650 pEnd, 651 -nMove ); 652 pEnd -= nMove; 653 *pEnd = '\0'; 654 } 655 656 if (i_aReplacement.nLength > 0) 657 { 658 memcpy( dpData + i_nStart, i_aReplacement.sStr, i_aReplacement.nLength ); 659 Advance(i_aReplacement.nLength); 660 } 661 662 eMode = eOldMode; 663 pCur = pEnd; 664 } 665 666 void 667 StreamStr::replace_all( char i_cCarToSearch, 668 char i_cReplacement ) 669 { 670 for ( char * p = dpData; p != pEnd; ++p ) 671 { 672 if (*p == i_cCarToSearch) 673 *p = i_cReplacement; 674 } 675 } 676 677 void 678 StreamStr::replace_all( Area i_aStrToSearch, 679 Area i_aReplacement ) 680 { 681 position_type p = 0; 682 const char * pSearch = i_aStrToSearch.sStr; 683 size_type nSearch = i_aStrToSearch.nLength; 684 685 while ( p <= length() - nSearch ) 686 { 687 if ( strncmp(dpData+p, pSearch, nSearch) == 0 ) 688 { 689 replace( p, nSearch, i_aReplacement ); 690 p += i_aReplacement.nLength; 691 } 692 else 693 { 694 ++p; 695 } 696 } // end while 697 } 698 699 StreamStr & 700 StreamStr::to_lower( position_type i_nStart, 701 size_type i_nLength ) 702 { 703 static char cLower[128] = 704 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 705 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 706 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 707 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 708 64, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, 709 112,113,114,115,116,117,118,119,120,121,122, 91, 92, 93, 94, 95, 710 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, 711 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127 }; 712 713 if ( i_nStart < length() ) 714 { 715 char * pStop = i_nStart + i_nLength < length() 716 ? dpData + i_nStart + i_nLength 717 : pEnd; 718 for ( char * pChange = dpData + i_nStart; 719 pChange != pStop; 720 ++pChange ) 721 { 722 *pChange = (static_cast< unsigned char >(*pChange) & 0x80) == 0 723 ? cLower[ UINT8(*pChange) ] 724 : *pChange; 725 } 726 } 727 return *this; 728 } 729 730 StreamStr & 731 StreamStr::to_upper( position_type i_nStart, 732 size_type i_nLength ) 733 { 734 static char cUpper[128] = 735 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 736 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 737 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 738 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 739 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 740 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 741 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 742 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127 }; 743 744 if ( i_nStart < length() ) 745 { 746 char * pStop = i_nStart + i_nLength < length() 747 ? dpData + i_nStart + i_nLength 748 : pEnd; 749 for ( char * pChange = dpData + i_nStart; 750 pChange != pStop; 751 ++pChange ) 752 { 753 *pChange = (static_cast< unsigned char >(*pChange) & 0x80) == 0 754 ? cUpper[ UINT8(*pChange) ] 755 : *pChange; 756 } 757 } 758 return *this; 759 } 760 761 762 StreamStr::size_type 763 StreamStr::token_count( char i_cSplit ) const 764 { 765 return count_chars(dpData, i_cSplit) + 1; 766 } 767 768 String 769 StreamStr::token( position_type i_nNr, 770 char i_cSplit ) const 771 { 772 // Find begin: 773 const char * pTokenBegin = dpData; 774 for ( position_type nNr = i_nNr; 775 nNr > 0; 776 --nNr ) 777 { 778 pTokenBegin = strchr(pTokenBegin,i_cSplit); 779 if (pTokenBegin == 0) 780 return String(""); 781 ++pTokenBegin; 782 } 783 784 // Find end: 785 const char * pTokenEnd = strchr(pTokenBegin, i_cSplit); 786 if (pTokenEnd == 0) 787 pTokenEnd = pEnd; 788 789 return String(pTokenBegin, size_type(pTokenEnd-pTokenBegin) ); 790 } 791 792 class StreamStrPool 793 { 794 public: 795 StreamStrPool(); 796 ~StreamStrPool(); 797 private: 798 // Non-copyable 799 StreamStrPool(StreamStrPool &); // not defined 800 void operator =(StreamStrPool &); // not defined 801 802 // Interface to: 803 friend class StreamStrLock; 804 static StreamStr & AcquireFromPool_( 805 uintt i_nMinimalSize ); 806 static void ReleaseToPool_( 807 DYN StreamStr * let_dpUsedStr ); 808 809 // DATA 810 SweList< DYN StreamStr* > 811 aPool; 812 }; 813 814 StreamStrPool::StreamStrPool() 815 { 816 } 817 818 StreamStrPool::~StreamStrPool() 819 { 820 for ( SweList< DYN StreamStr* >::iterator it = aPool.begin(); 821 it != aPool.end(); 822 ++it ) 823 { 824 delete (*it); 825 } 826 } 827 828 namespace 829 { 830 static StreamStrPool aPool_; 831 } 832 833 834 StreamStr & 835 StreamStrPool::AcquireFromPool_( uintt i_nMinimalSize ) 836 { 837 if ( aPool_.aPool.empty() ) 838 { 839 return *new StreamStr(i_nMinimalSize); 840 } 841 842 StreamStr & ret = *aPool_.aPool.front(); 843 aPool_.aPool.pop_front(); 844 ret.resize(i_nMinimalSize); 845 ret.seekp(0); 846 ret.set_insert_mode(str::overwrite); 847 return ret; 848 } 849 850 void 851 StreamStrPool::ReleaseToPool_( DYN StreamStr * let_dpUsedStr ) 852 { 853 aPool_.aPool.push_back( let_dpUsedStr ); 854 } 855 856 StreamStrLock::StreamStrLock( uintt i_nMinimalSize ) 857 : pStr( &StreamStrPool::AcquireFromPool_(i_nMinimalSize) ) 858 { 859 } 860 861 StreamStrLock::~StreamStrLock() 862 { 863 StreamStrPool::ReleaseToPool_(pStr); 864 } 865 866 867 UINT32 868 StreamStr::do_write( const void * i_pSrc, 869 UINT32 i_nNrofBytes ) 870 { 871 ProvideAddingSize( i_nNrofBytes ); 872 memcpy( pCur, i_pSrc, i_nNrofBytes ); 873 Advance(i_nNrofBytes); 874 875 return i_nNrofBytes; 876 } 877 878 void 879 StreamStr::ProvideAddingSize( size_type i_nSize2Add ) 880 { 881 size_type nLength = length(); 882 if ( capacity() - nLength < i_nSize2Add ) 883 Resize( nLength + i_nSize2Add ); 884 885 pEnd += i_nSize2Add; 886 *pEnd = '\0'; 887 888 if (eMode == str::insert AND pCur != pEnd) 889 { 890 MoveData( pCur, pCur + i_nSize2Add, seek_type(i_nSize2Add) ); 891 } 892 } 893 894 void 895 StreamStr::Resize( size_type i_nMinimumCapacity ) 896 { 897 size_type nNewSize = nCapacity1 < 128 898 ? nCapacity1 << 1 899 : (nCapacity1 << 1) - (nCapacity1 >> 1); 900 nCapacity1 = csv::max( nNewSize, size_type(i_nMinimumCapacity + 1) ); 901 902 char * pNew = new char[nCapacity1]; 903 strcpy ( pNew, dpData ); // SAFE STRCPY (#100211# - checked) 904 pEnd = pNew + (pEnd - dpData); 905 pCur = pNew + (pCur - dpData); 906 907 delete [] dpData; 908 dpData = pNew; 909 } 910 911 void 912 StreamStr::MoveData( char * i_pStart, 913 char * i_pEnd, 914 seek_type i_nDiff ) 915 { 916 if (i_nDiff > 0) 917 { 918 register const char * pSrc = i_pEnd; 919 register char * pDest = i_pEnd + i_nDiff; 920 for ( ; pSrc != i_pStart; --pSrc, --pDest ) 921 { 922 *pDest = *pSrc; 923 } 924 *pDest = *pSrc; 925 } 926 else if (i_nDiff < 0) 927 { 928 const char * pSrc = i_pStart; 929 char * pDest = i_pStart + i_nDiff; 930 for ( ; pSrc != i_pEnd; ++pSrc, ++pDest ) 931 { 932 *pDest = *pSrc; 933 } 934 } 935 } 936 937 // Does nothing, only the name of this function is needed. 938 void 939 c_str() 940 { 941 // Does nothing. 942 } 943 944 945 946 void 947 Split( std::vector<String> & o_list, 948 const char * i_text ) 949 { 950 const char * 951 pCurrentToken = 0; 952 bool 953 white = false; 954 for (const char * p = i_text; *p != '\0'; ++p) 955 { 956 white = UINT8(*p) > 32; 957 if (pCurrentToken != 0) 958 { 959 if (white) 960 { 961 o_list.push_back(String(pCurrentToken, p)); 962 pCurrentToken = 0; 963 } 964 } 965 else 966 { 967 if ( NOT white) 968 pCurrentToken = p; 969 } // endif (bInToken) else 970 } // end for 971 972 if (pCurrentToken != 0) 973 { 974 o_list.push_back(String(pCurrentToken)); 975 } 976 } 977 978 979 980 981 } // namespace csv 982