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