1 // Copyright (C) 2006 Davis E. King (davis@dlib.net) 2 // License: Boost Software License See LICENSE.txt for the full license. 3 #ifndef DLIB_STRINg_ 4 #define DLIB_STRINg_ 5 6 #include "string_abstract.h" 7 #include <sstream> 8 #include "../algs.h" 9 #include <string> 10 #include <iostream> 11 #include <iomanip> 12 #include "../error.h" 13 #include "../assert.h" 14 #include "../uintn.h" 15 #include <cctype> 16 #include <algorithm> 17 #include <vector> 18 #include "../enable_if.h" 19 20 namespace dlib 21 { 22 23 // ---------------------------------------------------------------------------------------- 24 25 template < 26 typename charT, 27 typename traits, 28 typename alloc 29 > narrow(const std::basic_string<charT,traits,alloc> & str)30 inline const typename disable_if<is_same_type<charT,char>,std::string>::type narrow ( 31 const std::basic_string<charT,traits,alloc>& str 32 ) 33 { 34 std::string temp; 35 temp.reserve(str.size()); 36 std::string::size_type i; 37 for (i = 0; i < str.size(); ++i) 38 { 39 if (zero_extend_cast<unsigned long>(str[i]) > 255) 40 temp += ' '; 41 else 42 temp += zero_extend_cast<char>(str[i]); 43 } 44 return temp; 45 } 46 47 template < 48 typename charT, 49 typename traits, 50 typename alloc 51 > narrow(const std::basic_string<charT,traits,alloc> & str)52 inline const typename enable_if<is_same_type<charT,char>,std::string>::type narrow ( 53 const std::basic_string<charT,traits,alloc>& str 54 ) 55 { 56 return str; 57 } 58 59 // ---------------------------------------------------------------------------------------- 60 61 template < 62 typename traits, 63 typename alloc 64 > tolower(const std::basic_string<char,traits,alloc> & str)65 const std::basic_string<char,traits,alloc> tolower ( 66 const std::basic_string<char,traits,alloc>& str 67 ) 68 { 69 std::basic_string<char,traits,alloc> temp; 70 71 temp.resize(str.size()); 72 73 for (typename std::basic_string<char,traits,alloc>::size_type i = 0; i < str.size(); ++i) 74 temp[i] = (char)std::tolower(str[i]); 75 76 return temp; 77 } 78 79 // ---------------------------------------------------------------------------------------- 80 81 template < 82 typename traits, 83 typename alloc 84 > toupper(const std::basic_string<char,traits,alloc> & str)85 const std::basic_string<char,traits,alloc> toupper ( 86 const std::basic_string<char,traits,alloc>& str 87 ) 88 { 89 std::basic_string<char,traits,alloc> temp; 90 91 temp.resize(str.size()); 92 93 for (typename std::basic_string<char,traits,alloc>::size_type i = 0; i < str.size(); ++i) 94 temp[i] = (char)std::toupper(str[i]); 95 96 return temp; 97 } 98 99 // ---------------------------------------------------------------------------------------- 100 101 template < 102 typename traits, 103 typename alloc 104 > strings_equal_ignore_case(const std::basic_string<char,traits,alloc> & str1,const std::basic_string<char,traits,alloc> & str2)105 bool strings_equal_ignore_case ( 106 const std::basic_string<char,traits,alloc>& str1, 107 const std::basic_string<char,traits,alloc>& str2 108 ) 109 { 110 if (str1.size() != str2.size()) 111 return false; 112 113 for (typename std::basic_string<char,traits,alloc>::size_type i = 0; i < str1.size(); ++i) 114 { 115 if (std::tolower(str1[i]) != std::tolower(str2[i])) 116 return false; 117 } 118 119 return true; 120 } 121 122 template < 123 typename traits, 124 typename alloc 125 > strings_equal_ignore_case(const std::basic_string<char,traits,alloc> & str1,const char * str2)126 bool strings_equal_ignore_case ( 127 const std::basic_string<char,traits,alloc>& str1, 128 const char* str2 129 ) 130 { 131 typename std::basic_string<char,traits,alloc>::size_type i; 132 for (i = 0; i < str1.size(); ++i) 133 { 134 // if we hit the end of str2 then the strings aren't the same length 135 if (str2[i] == '\0') 136 return false; 137 138 if (std::tolower(str1[i]) != std::tolower(str2[i])) 139 return false; 140 } 141 142 // This happens when str2 is longer than str1 143 if (str2[i] != '\0') 144 return false; 145 146 return true; 147 } 148 149 template < 150 typename traits, 151 typename alloc 152 > strings_equal_ignore_case(const char * str1,const std::basic_string<char,traits,alloc> & str2)153 bool strings_equal_ignore_case ( 154 const char* str1, 155 const std::basic_string<char,traits,alloc>& str2 156 ) 157 { 158 return strings_equal_ignore_case(str2, str1); 159 } 160 161 // ---------------------------------------------------------------------------------------- 162 163 template < 164 typename traits, 165 typename alloc 166 > strings_equal_ignore_case(const std::basic_string<char,traits,alloc> & str1,const std::basic_string<char,traits,alloc> & str2,unsigned long num)167 bool strings_equal_ignore_case ( 168 const std::basic_string<char,traits,alloc>& str1, 169 const std::basic_string<char,traits,alloc>& str2, 170 unsigned long num 171 ) 172 { 173 if (str1.size() != str2.size() && (str1.size() < num || str2.size() < num)) 174 return false; 175 176 for (typename std::basic_string<char,traits,alloc>::size_type i = 0; i < str1.size() && i < num; ++i) 177 { 178 if (std::tolower(str1[i]) != std::tolower(str2[i])) 179 return false; 180 } 181 182 return true; 183 } 184 185 template < 186 typename traits, 187 typename alloc 188 > strings_equal_ignore_case(const std::basic_string<char,traits,alloc> & str1,const char * str2,unsigned long num)189 bool strings_equal_ignore_case ( 190 const std::basic_string<char,traits,alloc>& str1, 191 const char* str2, 192 unsigned long num 193 ) 194 { 195 typename std::basic_string<char,traits,alloc>::size_type i; 196 for (i = 0; i < str1.size() && i < num; ++i) 197 { 198 // if we hit the end of str2 then the strings aren't the same length 199 if (str2[i] == '\0') 200 return false; 201 202 if (std::tolower(str1[i]) != std::tolower(str2[i])) 203 return false; 204 } 205 206 return true; 207 } 208 209 template < 210 typename traits, 211 typename alloc 212 > strings_equal_ignore_case(const char * str1,const std::basic_string<char,traits,alloc> & str2,unsigned long num)213 bool strings_equal_ignore_case ( 214 const char* str1, 215 const std::basic_string<char,traits,alloc>& str2, 216 unsigned long num 217 ) 218 { 219 return strings_equal_ignore_case(str2, str1, num); 220 } 221 222 // ---------------------------------------------------------------------------------------- 223 224 class cast_to_string_error : public error 225 { 226 public: cast_to_string_error()227 cast_to_string_error():error(ECAST_TO_STRING) {} 228 }; 229 230 template < 231 typename T 232 > cast_to_string(const T & item)233 const std::string cast_to_string ( 234 const T& item 235 ) 236 { 237 std::ostringstream sout; 238 sout << item; 239 if (!sout) 240 throw cast_to_string_error(); 241 return sout.str(); 242 } 243 244 // don't declare this if we are using mingw because it apparently doesn't 245 // support iostreams with wchar_t? 246 #if !(defined(__MINGW32__) && (__GNUC__ < 4)) 247 template < 248 typename T 249 > cast_to_wstring(const T & item)250 const std::wstring cast_to_wstring ( 251 const T& item 252 ) 253 { 254 std::basic_ostringstream<wchar_t> sout; 255 sout << item; 256 if (!sout) 257 throw cast_to_string_error(); 258 return sout.str(); 259 } 260 #endif 261 262 // ---------------------------------------------------------------------------------------- 263 264 inline std::string pad_int_with_zeros ( 265 int i, 266 unsigned long width = 6 267 ) 268 { 269 std::ostringstream sout; 270 sout << std::setw(width) << std::setfill('0') << i; 271 return sout.str(); 272 } 273 274 // ---------------------------------------------------------------------------------------- 275 276 class string_cast_error : public error 277 { 278 public: string_cast_error(const std::string & str)279 string_cast_error(const std::string& str): 280 error(ESTRING_CAST,"string cast error: invalid string = '" + str + "'") {} 281 }; 282 283 template < 284 typename T 285 > 286 struct string_cast_helper 287 { 288 template < typename charT, typename traits, typename alloc > caststring_cast_helper289 static const T cast ( 290 const std::basic_string<charT,traits,alloc>& str 291 ) 292 { 293 using namespace std; 294 basic_istringstream<charT,traits,alloc> sin(str); 295 T temp; 296 sin >> temp; 297 if (!sin) throw string_cast_error(narrow(str)); 298 if (sin.get() != std::char_traits<charT>::eof()) throw string_cast_error(narrow(str)); 299 return temp; 300 } 301 }; 302 303 template <typename C, typename T, typename A> 304 struct string_cast_helper<std::basic_string<C,T,A> > 305 { 306 template < typename charT, typename traits, typename alloc > 307 static const std::basic_string<C,T,A> cast ( 308 const std::basic_string<charT,traits,alloc>& str 309 ) 310 { 311 std::basic_string<C,T,A> temp; 312 temp.resize(str.size()); 313 for (unsigned long i = 0; i < str.size(); ++i) 314 temp[i] = zero_extend_cast<C>(str[i]); 315 return temp; 316 } 317 }; 318 319 template <> 320 struct string_cast_helper<bool> 321 { 322 template < typename charT, typename traits, typename alloc > 323 static bool cast ( 324 const std::basic_string<charT,traits,alloc>& str 325 ) 326 { 327 using namespace std; 328 if (str.size() == 1 && str[0] == '1') 329 return true; 330 if (str.size() == 1 && str[0] == '0') 331 return false; 332 if (tolower(narrow(str)) == "true") 333 return true; 334 if (tolower(narrow(str)) == "false") 335 return false; 336 337 throw string_cast_error(narrow(str)); 338 } 339 }; 340 341 #define DLIB_STRING_CAST_INTEGRAL(type) \ 342 template <> \ 343 struct string_cast_helper<type> \ 344 { \ 345 template < typename charT, typename traits, typename alloc> \ 346 static type cast ( \ 347 const std::basic_string<charT,traits,alloc>& str \ 348 ) \ 349 { \ 350 using namespace std; \ 351 basic_istringstream<charT,traits,alloc> sin(str); \ 352 type temp; \ 353 if (str.size() > 2 && str[0] == _dT(charT,'0') && str[1] == _dT(charT,'x')) \ 354 sin >> hex >> temp; \ 355 else \ 356 sin >> temp; \ 357 if (!sin) throw string_cast_error(narrow(str)); \ 358 if (sin.get() != std::char_traits<charT>::eof()) throw string_cast_error(narrow(str)); \ 359 return temp; \ 360 } \ 361 }; 362 363 DLIB_STRING_CAST_INTEGRAL(unsigned short) 364 DLIB_STRING_CAST_INTEGRAL(short) 365 DLIB_STRING_CAST_INTEGRAL(unsigned int) 366 DLIB_STRING_CAST_INTEGRAL(int) 367 DLIB_STRING_CAST_INTEGRAL(unsigned long) 368 DLIB_STRING_CAST_INTEGRAL(long) 369 DLIB_STRING_CAST_INTEGRAL(uint64) 370 371 template < 372 typename T, 373 typename charT, 374 typename traits, 375 typename alloc 376 > 377 inline const T string_cast ( 378 const std::basic_string<charT,traits,alloc>& str 379 ) 380 { 381 COMPILE_TIME_ASSERT(is_pointer_type<T>::value == false); 382 return string_cast_helper<T>::cast(str); 383 } 384 385 template <typename T> 386 inline const T string_cast (const char* str){ return string_cast<T>(std::string(str)); } 387 template <typename T> 388 inline const T string_cast (const wchar_t* str){ return string_cast<T>(std::wstring(str)); } 389 390 // ---------------------------------------------------------------------------------------- 391 392 class string_assign 393 { 394 template < 395 typename charT, 396 typename traits, 397 typename alloc 398 > 399 class string_assign_helper 400 { 401 public: 402 string_assign_helper ( 403 const std::basic_string<charT,traits,alloc>& str_ 404 ) : str(str_) {} 405 406 template <typename T> 407 operator T () const 408 { 409 return string_cast<T>(str); 410 } 411 412 private: 413 414 const std::basic_string<charT,traits,alloc>& str; 415 }; 416 417 // ------------- 418 419 class char_assign_helper 420 { 421 public: 422 char_assign_helper ( 423 const char* str_ 424 ) : str(str_) {} 425 426 template <typename T> 427 operator T () const 428 { 429 return string_cast<T>(str); 430 } 431 432 private: 433 434 const char* str; 435 }; 436 437 // ------------- 438 439 class wchar_t_assign_helper 440 { 441 public: 442 wchar_t_assign_helper ( 443 const wchar_t* str_ 444 ) : str(str_) {} 445 446 template <typename T> 447 operator T () const 448 { 449 return string_cast<T>(str); 450 } 451 452 private: 453 454 const wchar_t* str; 455 }; 456 457 // ------------- 458 459 public: 460 461 template < 462 typename charT, 463 typename traits, 464 typename alloc 465 > 466 string_assign_helper<charT,traits,alloc> operator=( 467 const std::basic_string<charT,traits,alloc>& str 468 ) const 469 { 470 return string_assign_helper<charT,traits,alloc>(str); 471 } 472 473 char_assign_helper operator= ( 474 const char* str 475 ) const 476 { 477 return char_assign_helper(str); 478 } 479 480 wchar_t_assign_helper operator= ( 481 const wchar_t* str 482 ) const 483 { 484 return wchar_t_assign_helper(str); 485 } 486 }; 487 488 const string_assign sa = string_assign(); 489 490 // ---------------------------------------------------------------------------------------- 491 492 template < 493 typename charT, 494 typename traits, 495 typename alloc 496 > 497 const std::basic_string<charT,traits,alloc> wrap_string ( 498 const std::basic_string<charT,traits,alloc>& str, 499 const unsigned long first_pad = 0, 500 const unsigned long rest_pad = 0, 501 const unsigned long max_per_line = 79 502 ) 503 { 504 DLIB_ASSERT ( first_pad < max_per_line && rest_pad < max_per_line && 505 rest_pad >= first_pad, 506 "\tconst std::basic_string<charT,traits,alloc> wrap_string()" 507 << "\n\tfirst_pad: " << first_pad 508 << "\n\trest_pad: " << rest_pad 509 << "\n\tmax_per_line: " << max_per_line ); 510 511 using namespace std; 512 513 basic_ostringstream<charT,traits,alloc> sout; 514 basic_istringstream<charT,traits,alloc> sin(str); 515 516 for (unsigned long i = 0; i < rest_pad; ++i) 517 sout << _dT(charT," "); 518 const basic_string<charT,traits,alloc> pad(sout.str()); 519 sout.str(_dT(charT,"")); 520 521 for (unsigned long i = 0; i < first_pad; ++i) 522 sout << _dT(charT," "); 523 524 525 typename basic_string<charT,traits,alloc>::size_type remaining = max_per_line - rest_pad; 526 527 basic_string<charT,traits,alloc> temp; 528 529 sin >> temp; 530 while (sin) 531 { 532 if (temp.size() > remaining) 533 { 534 if (temp.size() + rest_pad >= max_per_line) 535 { 536 string::size_type i = 0; 537 for (; i < temp.size(); ++i) 538 { 539 sout << temp[i]; 540 --remaining; 541 if (remaining == 0) 542 { 543 sout << _dT(charT,"\n") << pad; 544 remaining = max_per_line - rest_pad; 545 } 546 } 547 } 548 else 549 { 550 sout << _dT(charT,"\n") << pad << temp; 551 remaining = max_per_line - rest_pad - temp.size(); 552 } 553 } 554 else if (temp.size() == remaining) 555 { 556 sout << temp; 557 remaining = 0; 558 } 559 else 560 { 561 sout << temp; 562 remaining -= temp.size(); 563 } 564 565 sin >> temp; 566 if (remaining == 0 && sin) 567 { 568 sout << _dT(charT,"\n") << pad; 569 remaining = max_per_line - rest_pad; 570 } 571 else 572 { 573 sout << _dT(charT," "); 574 --remaining; 575 } 576 } 577 578 return sout.str(); 579 } 580 581 template < 582 typename charT 583 > 584 const std::basic_string<charT> wrap_string ( 585 const charT* str, 586 const unsigned long first_pad = 0, 587 const unsigned long rest_pad = 0, 588 const unsigned long max_per_line = 79 589 ) { return wrap_string(std::basic_string<charT>(str),first_pad,rest_pad,max_per_line); } 590 591 // ---------------------------------------------------------------------------------------- 592 593 template < 594 typename charT, 595 typename traits, 596 typename alloc 597 > 598 const std::basic_string<charT,traits,alloc> ltrim ( 599 const std::basic_string<charT,traits,alloc>& str, 600 const std::basic_string<charT,traits,alloc>& trim_chars 601 ) 602 { 603 typedef std::basic_string<charT,traits,alloc> string; 604 typename string::size_type pos = str.find_first_not_of(trim_chars); 605 if (pos != string::npos) 606 return str.substr(pos); 607 else 608 return std::basic_string<charT,traits,alloc>(); 609 } 610 611 template < 612 typename charT, 613 typename traits, 614 typename alloc 615 > 616 const std::basic_string<charT,traits,alloc> ltrim ( 617 const std::basic_string<charT,traits,alloc>& str, 618 const charT* trim_chars = _dT(charT," \t\r\n") 619 ) { return ltrim(str,std::basic_string<charT,traits,alloc>(trim_chars)); } 620 621 // ---------------------------------------------------------------------------------------- 622 623 template < 624 typename charT, 625 typename traits, 626 typename alloc 627 > 628 const std::basic_string<charT,traits,alloc> rtrim ( 629 const std::basic_string<charT,traits,alloc>& str, 630 const std::basic_string<charT,traits,alloc>& trim_chars 631 ) 632 { 633 typedef std::basic_string<charT,traits,alloc> string; 634 635 typename string::size_type pos = str.find_last_not_of(trim_chars); 636 if (pos != string::npos) 637 return str.substr(0,pos+1); 638 else 639 return std::basic_string<charT,traits,alloc>(); 640 } 641 642 template < 643 typename charT, 644 typename traits, 645 typename alloc 646 > 647 const std::basic_string<charT,traits,alloc> rtrim ( 648 const std::basic_string<charT,traits,alloc>& str, 649 const charT* trim_chars = _dT(charT," \t\r\n") 650 ) { return rtrim(str,std::basic_string<charT,traits,alloc>(trim_chars)); } 651 652 // ---------------------------------------------------------------------------------------- 653 654 template < 655 typename charT, 656 typename traits, 657 typename alloc 658 > 659 const std::basic_string<charT,traits,alloc> trim ( 660 const std::basic_string<charT,traits,alloc>& str, 661 const std::basic_string<charT,traits,alloc>& trim_chars 662 ) 663 { 664 typedef std::basic_string<charT,traits,alloc> string; 665 typename string::size_type lpos = str.find_first_not_of(trim_chars); 666 if (lpos != string::npos) 667 { 668 typename string::size_type rpos = str.find_last_not_of(trim_chars); 669 return str.substr(lpos,rpos-lpos+1); 670 } 671 else 672 { 673 return std::basic_string<charT,traits,alloc>(); 674 } 675 } 676 677 template < 678 typename charT, 679 typename traits, 680 typename alloc 681 > 682 const std::basic_string<charT,traits,alloc> trim ( 683 const std::basic_string<charT,traits,alloc>& str, 684 const charT* trim_chars = _dT(charT," \t\r\n") 685 ) { return trim(str,std::basic_string<charT,traits,alloc>(trim_chars)); } 686 687 // ---------------------------------------------------------------------------------------- 688 689 template < 690 typename charT, 691 typename traits, 692 typename alloc 693 > 694 const std::basic_string<charT,traits,alloc> rpad ( 695 const std::basic_string<charT,traits,alloc>& str, 696 long pad_length, 697 const std::basic_string<charT,traits,alloc>& pad_string 698 ) 699 { 700 typedef std::basic_string<charT,traits,alloc> string; 701 // if str is too big then just return str 702 if (pad_length <= static_cast<long>(str.size())) 703 return str; 704 705 // make the string we will padd onto the string 706 string P; 707 while (P.size() < pad_length - str.size()) 708 P += pad_string; 709 P = P.substr(0,pad_length - str.size()); 710 711 // return the padded string 712 return str + P; 713 } 714 715 template < 716 typename charT, 717 typename traits, 718 typename alloc 719 > 720 const std::basic_string<charT,traits,alloc> rpad ( 721 const std::basic_string<charT,traits,alloc>& str, 722 long pad_length, 723 const charT* pad_string = _dT(charT," ") 724 ) { return rpad(str,pad_length,std::basic_string<charT,traits,alloc>(pad_string)); } 725 726 // ---------------------------------------------------------------------------------------- 727 728 template < 729 typename charT, 730 typename traits, 731 typename alloc 732 > 733 const std::basic_string<charT,traits,alloc> lpad ( 734 const std::basic_string<charT,traits,alloc>& str, 735 long pad_length, 736 const std::basic_string<charT,traits,alloc>& pad_string 737 ) 738 { 739 typedef std::basic_string<charT,traits,alloc> string; 740 // if str is too big then just return str 741 if (pad_length <= static_cast<long>(str.size())) 742 return str; 743 744 // make the string we will padd onto the string 745 string P; 746 while (P.size() < pad_length - str.size()) 747 P += pad_string; 748 P = P.substr(0,pad_length - str.size()); 749 750 // return the padded string 751 return P + str; 752 } 753 754 template < 755 typename charT, 756 typename traits, 757 typename alloc 758 > 759 const std::basic_string<charT,traits,alloc> lpad ( 760 const std::basic_string<charT,traits,alloc>& str, 761 long pad_length, 762 const charT* pad_string = _dT(charT," ") 763 ) { return lpad(str,pad_length,std::basic_string<charT,traits,alloc>(pad_string)); } 764 765 // ---------------------------------------------------------------------------------------- 766 767 template < 768 typename charT, 769 typename traits, 770 typename alloc 771 > 772 const std::basic_string<charT,traits,alloc> pad ( 773 const std::basic_string<charT,traits,alloc>& str, 774 long pad_length, 775 const std::basic_string<charT,traits,alloc>& pad_string 776 ) 777 { 778 const long str_size = static_cast<long>(str.size()); 779 return rpad(lpad(str,(pad_length-str_size)/2 + str_size,pad_string), 780 pad_length, 781 pad_string); 782 } 783 784 template < 785 typename charT, 786 typename traits, 787 typename alloc 788 > 789 const std::basic_string<charT,traits,alloc> pad ( 790 const std::basic_string<charT,traits,alloc>& str, 791 long pad_length, 792 const charT* pad_string = _dT(charT," ") 793 ) { return pad(str,pad_length,std::basic_string<charT,traits,alloc>(pad_string)); } 794 795 // ---------------------------------------------------------------------------------------- 796 797 template < 798 typename charT, 799 typename traits, 800 typename alloc 801 > 802 const std::basic_string<charT,traits,alloc> left_substr ( 803 const std::basic_string<charT,traits,alloc>& str, 804 const std::basic_string<charT,traits,alloc>& delim 805 ) 806 { 807 return str.substr(0,str.find_first_of(delim)); 808 } 809 810 template < 811 typename charT, 812 typename traits, 813 typename alloc 814 > 815 const std::basic_string<charT,traits,alloc> left_substr ( 816 const std::basic_string<charT,traits,alloc>& str, 817 const charT* delim = _dT(charT," \n\r\t") 818 ) 819 { 820 return str.substr(0,str.find_first_of(delim)); 821 } 822 823 // ---------------------------------------------------------------------------------------- 824 825 template < 826 typename charT, 827 typename traits, 828 typename alloc 829 > 830 const std::basic_string<charT,traits,alloc> right_substr ( 831 const std::basic_string<charT,traits,alloc>& str, 832 const std::basic_string<charT,traits,alloc>& delim 833 ) 834 { 835 typename std::basic_string<charT,traits,alloc>::size_type delim_pos = str.find_last_of(delim); 836 if (delim_pos != std::basic_string<charT,traits,alloc>::npos) 837 return str.substr(delim_pos+1); 838 else 839 return _dT(charT,""); 840 } 841 842 template < 843 typename charT, 844 typename traits, 845 typename alloc 846 > 847 const std::basic_string<charT,traits,alloc> right_substr ( 848 const std::basic_string<charT,traits,alloc>& str, 849 const charT* delim = _dT(charT," \n\r\t") 850 ) 851 { 852 typename std::basic_string<charT,traits,alloc>::size_type delim_pos = str.find_last_of(delim); 853 if (delim_pos != std::basic_string<charT,traits,alloc>::npos) 854 return str.substr(delim_pos+1); 855 else 856 return _dT(charT,""); 857 } 858 859 // ---------------------------------------------------------------------------------------- 860 861 template < 862 typename charT, 863 typename traits, 864 typename alloc 865 > 866 std::pair<std::basic_string<charT,traits,alloc>, std::basic_string<charT,traits,alloc> > 867 split_on_first ( 868 const std::basic_string<charT,traits,alloc>& str, 869 const charT* delim = _dT(charT," \n\r\t") 870 ) 871 { 872 typename std::basic_string<charT,traits,alloc>::size_type delim_pos = str.find_first_of(delim); 873 if (delim_pos != std::basic_string<charT,traits,alloc>::npos) 874 return std::make_pair(str.substr(0, delim_pos), str.substr(delim_pos+1)); 875 else 876 return std::make_pair(str, _dT(charT,"")); 877 } 878 879 template < 880 typename charT, 881 typename traits, 882 typename alloc 883 > 884 inline std::pair<std::basic_string<charT,traits,alloc>, std::basic_string<charT,traits,alloc> > 885 split_on_first ( 886 const std::basic_string<charT,traits,alloc>& str, 887 const std::basic_string<charT,traits,alloc>& delim 888 ) 889 { 890 return split_on_first(str, delim.c_str()); 891 } 892 893 // ---------------------------------------------------------------------------------------- 894 895 template < 896 typename charT, 897 typename traits, 898 typename alloc 899 > 900 std::pair<std::basic_string<charT,traits,alloc>, std::basic_string<charT,traits,alloc> > 901 split_on_last ( 902 const std::basic_string<charT,traits,alloc>& str, 903 const charT* delim = _dT(charT," \n\r\t") 904 ) 905 { 906 typename std::basic_string<charT,traits,alloc>::size_type delim_pos = str.find_last_of(delim); 907 if (delim_pos != std::basic_string<charT,traits,alloc>::npos) 908 return std::make_pair(str.substr(0, delim_pos), str.substr(delim_pos+1)); 909 else 910 return std::make_pair(str, _dT(charT,"")); 911 } 912 913 template < 914 typename charT, 915 typename traits, 916 typename alloc 917 > 918 inline std::pair<std::basic_string<charT,traits,alloc>, std::basic_string<charT,traits,alloc> > 919 split_on_last ( 920 const std::basic_string<charT,traits,alloc>& str, 921 const std::basic_string<charT,traits,alloc>& delim 922 ) 923 { 924 return split_on_last(str, delim.c_str()); 925 } 926 927 // ---------------------------------------------------------------------------------------- 928 929 template < 930 typename charT, 931 typename traits, 932 typename alloc 933 > 934 const std::vector<std::basic_string<charT,traits,alloc> > split ( 935 const std::basic_string<charT,traits,alloc>& str, 936 const charT* delim = _dT(charT," \n\r\t") 937 ) 938 { 939 std::basic_string<charT,traits,alloc> temp; 940 941 std::vector<std::basic_string<charT,traits,alloc> > res; 942 943 for (unsigned long i = 0; i < str.size(); ++i) 944 { 945 // check if delim contains the character str[i] 946 bool hit = false; 947 const charT* d = delim; 948 while (*d != '\0') 949 { 950 if (str[i] == *d) 951 { 952 hit = true; 953 break; 954 } 955 ++d; 956 } 957 958 if (hit) 959 { 960 if (temp.size() != 0) 961 { 962 res.push_back(temp); 963 temp.clear(); 964 } 965 } 966 else 967 { 968 temp.push_back(str[i]); 969 } 970 } 971 972 if (temp.size() != 0) 973 res.push_back(temp); 974 975 return res; 976 } 977 978 template < 979 typename charT, 980 typename traits, 981 typename alloc 982 > 983 const std::vector<std::basic_string<charT,traits,alloc> > split ( 984 const std::basic_string<charT,traits,alloc>& str, 985 const std::basic_string<charT,traits,alloc>& delim 986 ) 987 { 988 return split(str,delim.c_str()); 989 } 990 991 inline const std::vector<std::string> split ( 992 const char* str, 993 const char* delim = " \n\r\t" 994 ) 995 { 996 return split(std::string(str),delim); 997 } 998 999 // ---------------------------------------------------------------------------------------- 1000 1001 } 1002 1003 #endif // DLIB_STRINg_ 1004 1005