Changeset 681fdcca in mainline
- Timestamp:
- 2018-07-05T21:41:18Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- b0b46d59
- Parents:
- 7b1906e
- git-author:
- Jaroslav Jindrak <dzejrou@…> (2017-10-26 20:56:50)
- git-committer:
- Dzejrou <dzejrou@…> (2018-07-05 21:41:18)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/cpp/include/impl/string.hpp
r7b1906e r681fdcca 81 81 static size_t length(const char_type* s) 82 82 { 83 return std::str_size(s) ;83 return std::str_size(s) + 1; 84 84 } 85 85 … … 184 184 static size_t length(const char_type* s) 185 185 { 186 return std::wstr_size(s) ;186 return std::wstr_size(s) + 1; 187 187 } 188 188 … … 277 277 { /* DUMMY BODY */ } 278 278 279 explicit basic_string(const allocator_type& alloc); 280 281 basic_string(const basic_string& other); 282 283 basic_string(basic_string&& other); 279 explicit basic_string(const allocator_type& alloc) 280 : data_{}, size_{}, capacity_{}, allocator_{alloc} 281 { 282 /** 283 * Postconditions: 284 * data() = non-null copyable value that can have 0 added to it. 285 * size() = 0 286 * capacity() = unspecified 287 */ 288 data_ = allocator_.allocate(initial_capacity_); 289 capacity_ = initial_capacity_; 290 } 291 292 basic_string(const basic_string& other) 293 : data_{}, size_{other.size_}, capacity_{other.capacity_}, 294 allocator_{other.allocator_} 295 { 296 init_(other.data(), size_); 297 } 298 299 basic_string(basic_string&& other) 300 : data_{other.data_}, size_{other.size_}, 301 capacity_{other.capacity_}, allocator_{move(other.allocator_)} 302 { 303 other.data_ = nullptr; 304 other.size_ = 0; 305 other.capacity_ = 0; 306 } 284 307 285 308 basic_string(const basic_string& other, size_type pos, size_type n = npos, 286 const allocator_type& alloc = allocator_type{}); 287 288 basic_string(const value_type*, size_type n, const allocator_type& alloc = allocator{}); 289 290 basic_string(const value_type*, const allocator_type& alloc = allocator{}); 291 292 basic_string(size_type n, value_type c, const allocator_type& alloc = allocator{}); 309 const allocator_type& alloc = allocator_type{}) 310 : data_{}, size_{}, capacity_{}, allocator_{alloc} 311 { 312 // TODO: if pos < other.size() throw out_of_range. 313 auto len = min(n, other.size() - pos); 314 init_(other.data() + pos, len); 315 } 316 317 basic_string(const value_type* str, size_type n, const allocator_type& alloc = allocator{}) 318 : data_{}, size_{n}, capacity_{n}, allocator_{alloc} 319 { 320 init_(str, size_); 321 } 322 323 basic_string(const value_type* str, const allocator_type& alloc = allocator{}) 324 : data_{}, size_{}, capacity_{}, allocator_{alloc} 325 { 326 init_(str, traits_type::length(str)); 327 } 328 329 basic_string(size_type n, value_type c, const allocator_type& alloc = allocator{}) 330 : data_{}, size_{n}, capacity_{n}, allocator_{alloc} 331 { 332 data_ = allocator_.allocate(capacity_); 333 for (size_type i = 0; i < size_; ++i) 334 traits_type::asign(data_[i], c); 335 ensure_null_terminator_(); 336 } 293 337 294 338 template<class InputIterator> 295 339 basic_string(InputIterator first, InputIterator last, 296 const allocator_type& alloc = allocator{}); 297 298 basic_string(initializer_list<value_type> init, const allocator_type& alloc = allocator{}); 299 300 basic_string(const basic_string& other, const allocator_type& alloc); 301 302 basic_string(basic_string&& other, const allocator_type& alloc); 303 304 ~basic_string(); 305 306 basic_string& operator=(const basic_string& other); 340 const allocator_type& alloc = allocator{}) 341 : data_{}, size_{}, capacity_{}, allocator_{alloc} 342 { 343 if constexpr (is_integral_t<InputIterator>) 344 { // Required by the standard. 345 size_ = static_cast<size_type>(first); 346 capacity_ = size_; 347 data_ = allocator_.allocate(capacity_); 348 349 for (size_type i = 0; i < size_; ++i) 350 traits_type::assign(data_[i], static_cast<value_type>(last)); 351 ensure_null_terminator_(); 352 } 353 else 354 { 355 auto len = static_cast<size_type>(last - first); 356 init_(static_cast<value_type*>(first), len); 357 } 358 } 359 360 basic_string(initializer_list<value_type> init, const allocator_type& alloc = allocator{}) 361 : basic_string{init.begin(), init.size(), alloc} 362 { /* DUMMY BODY */ } 363 364 basic_string(const basic_string& other, const allocator_type& alloc) 365 : data_{}, size_{other.size_}, capacity_{other.capacity_}, allocator_{alloc} 366 { 367 init_(other.data(), size_); 368 } 369 370 basic_string(basic_string&& other, const allocator_type& alloc) 371 : data_{other.data_}, size_{other.size_}, capacity_{other.capacity_}, allocator_{alloc} 372 { 373 other.data_ = nullptr; 374 other.size_ = 0; 375 other.capacity_ = 0; 376 } 377 378 ~basic_string() 379 { 380 allocator_.deallocate(data_, capacity_); 381 } 382 383 basic_string& operator=(const basic_string& other) 384 { 385 if (this != &other) 386 { 387 basic_string tmp{other}; 388 swap(tmp); 389 } 390 } 307 391 308 392 basic_string& operator=(basic_string&& other) 309 393 noexcept(allocator_traits<allocator_type>::propagate_on_container_move_assignment::value || 310 allocator_traits<allocator_type>::is_always_equal::value); 311 312 basic_string& operator=(const value_type* other); 313 314 basic_string& operator=(value_type c); 315 316 basic_string& operator=(initializer_list<value_type>); 394 allocator_traits<allocator_type>::is_always_equal::value) 395 { 396 if (this != &other) 397 swap(other); 398 } 399 400 basic_string& operator=(const value_type* other) 401 { 402 *this = basic_string{other}; 403 404 return *this; 405 } 406 407 basic_string& operator=(value_type c) 408 { 409 *this = basic_string{1, c}; 410 411 return *this; 412 } 413 414 basic_string& operator=(initializer_list<value_type> init) 415 { 416 *this = basic_string{init}; 417 418 return *this; 419 } 317 420 318 421 /** … … 399 502 } 400 503 401 void resize(size_type n, value_type c); 402 403 void resize(size_type n); 504 void resize(size_type new_size, value_type c) 505 { 506 // TODO: if new_size > max_size() throw length_error. 507 if (new_size > size_) 508 { 509 ensure_free_space_(new_size - size_ + 1); 510 for (size_type i = size_; i < new_size; ++i) 511 traits_type::assign(data_[i], i); 512 } 513 514 size_ = new_size; 515 ensure_null_terminator_(); 516 } 517 518 void resize(size_type new_size) 519 { 520 resize(new_size, value_type{}); 521 } 404 522 405 523 size_type capacity() const noexcept … … 408 526 } 409 527 410 void reserve(size_type res_arg = 0); 411 412 void shrink_to_fit(); 413 414 void clear() noexcept; 528 void reserve(size_type new_capacity = 0) 529 { 530 // TODO: if new_capacity > max_size() throw 531 // length_error (this function shall have no 532 // effect in such case) 533 if (new_capacity > capacity_) 534 resize_with_copy_(size_, new_capacity); 535 else if (new_capacity < capacity) 536 shrink_to_fit(); // Non-binding request, but why not. 537 } 538 539 void shrink_to_fit() 540 { 541 if (size_ != capacity_) 542 resize_with_copy_(size_); 543 } 544 545 void clear() noexcept 546 { 547 size_ = 0; 548 } 415 549 416 550 bool empty() const noexcept … … 469 603 */ 470 604 471 basic_string& operator+=(const basic_string& str); 472 473 basic_string& operator+=(const value_type* str); 474 475 basic_string& operator+=(value_type c); 476 477 basic_string& operator+=(initializer_list<value_type> init); 478 479 basic_string& append(const basic_string& str); 605 basic_string& operator+=(const basic_string& str) 606 { 607 return append(str); 608 } 609 610 basic_string& operator+=(const value_type* str) 611 { 612 return append(str); 613 } 614 615 basic_string& operator+=(value_type c) 616 { 617 push_back(c); 618 return *this; 619 } 620 621 basic_string& operator+=(initializer_list<value_type> init) 622 { 623 return append(init.begin(), init.size()); 624 } 625 626 basic_string& append(const basic_string& str) 627 { 628 return append(str.data(), str.size()); 629 } 480 630 481 631 basic_string& append(const basic_string& str, size_type pos 482 size_type n = npos); 483 484 basic_string& append(const value_type* str, size_type n); 485 486 basic_string& append(const value_type* str); 487 488 basic_string& append(size_type n, value_type c); 632 size_type n = npos) 633 { 634 if (pos < str.size()) 635 { 636 auto len = min(n, str.size() - pos); 637 ensure_free_space_(len); 638 639 return append(str.data() + pos, len); 640 } 641 // TODO: Else throw out_of_range. 642 } 643 644 basic_string& append(const value_type* str, size_type n) 645 { 646 // TODO: if (size_ + n > max_size()) throw length_error 647 ensure_free_space_(n); 648 traits_type::copy(data_ + size_, str, n); 649 size_ += n; 650 ensure_null_terminator_(); 651 652 return *this; 653 } 654 655 basic_string& append(const value_type* str) 656 { 657 return append(str, traits_type::length(str)); 658 } 659 660 basic_string& append(size_type n, value_type c) 661 { 662 return append(basic_string(n, c)); 663 } 489 664 490 665 template<class InputIterator> 491 basic_string& append(InputIterator first, InputIterator last); 492 493 basic_string& append(initializer_list<value_type> init); 494 495 void push_back(value_type c); 496 497 basic_string& assign(const basic_string& str); 498 499 basic_string& assign(basic_string&& str); 666 basic_string& append(InputIterator first, InputIterator last) 667 { 668 return append(basic_string(frist, last)); 669 } 670 671 basic_string& append(initializer_list<value_type> init) 672 { 673 return append(init.begin(), init.size()); 674 } 675 676 void push_back(value_type c) 677 { 678 ensure_free_space_(1); 679 traits_type::assign(data_[size_++], c); 680 ensure_null_terminator_(); 681 } 682 683 basic_string& assign(const basic_string& str) 684 { 685 return assign(str, 0, npos); 686 } 687 688 basic_string& assign(basic_string&& str) 689 { 690 swap(str); 691 692 return *this; 693 } 500 694 501 695 basic_string& assign(const basic_string& str, size_type pos, 502 size_type n = npos); 503 504 basic_string& assign(const value_type* str, size_type n); 505 506 basic_string& assign(const value_type* str); 507 508 basic_string& assign(size_type n, value_type c); 696 size_type n = npos) 697 { 698 if (pos < str.size()) 699 { 700 auto len = min(n, str.size() - pos); 701 ensure_free_space_(len); 702 703 return assign(str.data() + pos, len); 704 } 705 // TODO: Else throw out_of_range. 706 } 707 708 basic_string& assign(const value_type* str, size_type n) 709 { 710 // TODO: if (n > max_size()) throw length_error. 711 resize_without_copy_(n); 712 traits_type::copy(begin(), str, n); 713 714 return *this; 715 } 716 717 basic_string& assign(const value_type* str) 718 { 719 return assign(str, traits_type::length(str)); 720 } 721 722 basic_string& assign(size_type n, value_type c) 723 { 724 return assign(basic_string(n, c)); 725 } 509 726 510 727 template<class InputIterator> 511 basic_string& assign(InputIterator first, InputIterator last); 512 513 basic_string& assign(initializer_list<value_type> init); 514 515 basic_string& insert(size_type pos, const basic_string& str); 728 basic_string& assign(InputIterator first, InputIterator last) 729 { 730 return assign(basic_string(first, last)); 731 } 732 733 basic_string& assign(initializer_list<value_type> init) 734 { 735 return assign(init.begin(), init.size()); 736 } 737 738 basic_string& insert(size_type pos, const basic_string& str) 739 { 740 // TODO: if (pos > str.size()) throw out_of_range. 741 return insert(pos, str.data(), str.size()); 742 } 516 743 517 744 basic_string& insert(size_type pos1, const basic_string& str, 518 size_type pos2, size_type n = npos); 519 520 basic_string& insert(size_type pos, const value_type* str, size_type n); 521 522 basic_string& insert(size_type pos, const value_type* str); 523 524 basic_string& insert(size_type pos, size_type n, value_type c); 525 526 iterator insert(const_iterator pos, value_type c); 527 528 iterator insert(const_iterator pos, size_type n, value_type c); 745 size_type pos2, size_type n = npos) 746 { 747 // TODO: if (pos1 > size() or pos2 > str.size()) throw 748 // out_of_range. 749 auto len = min(n, str.size() - pos2); 750 751 return insert(pos1, str.data() + pos2, len); 752 } 753 754 basic_string& insert(size_type pos, const value_type* str, size_type n) 755 { 756 ensure_free_space_(size_ + n); 757 copy_backward_(begin() + pos, end(), end() + n); 758 copy_(begin() + pos, begin() + pos + n, str); 759 760 return *this; 761 } 762 763 basic_string& insert(size_type pos, const value_type* str) 764 { 765 return insert(pos, str, traits_type::length(str)); 766 } 767 768 basic_string& insert(size_type pos, size_type n, value_type c) 769 { 770 return insert(pos, basic_string(n, c)); 771 } 772 773 iterator insert(const_iterator pos, value_type c) 774 { 775 auto idx = static_cast<size_type>(pos - begin()); 776 777 ensure_free_space_(1); 778 copy_backward_(begin() + pos, end(), end() + 1); 779 ensure_null_terminator_(); 780 781 return begin() + idx; 782 } 783 784 iterator insert(const_iterator pos, size_type n, value_type c) 785 { 786 if (n == 0) 787 return const_cast<iterator>(pos); 788 789 auto idx = static_cast<size_type>(pos - begin()); 790 791 ensure_free_space_(n); 792 copy_backward_(begin() + pos, end(), end() + n); 793 794 auto it = position; 795 for (size_type i = 0; i < n; ++i) 796 type_traits::assign(*it++, c); 797 ensure_null_terminator_(); 798 799 return begin() + idx; 800 } 529 801 530 802 template<class InputIterator> 531 803 iterator insert(const_iterator pos, InputIterator first, 532 InputIterator last); 533 534 iterator insert(const_iterator pos, initializer_list<value_type>); 535 536 basic_string& erase(size_type pos = 0; size_type n = npos); 804 InputIterator last) 805 { 806 return insert(pos - begin(), basic_string(first, last)); 807 } 808 809 iterator insert(const_iterator pos, initializer_list<value_type> init) 810 { 811 return insert(pos, init.begin(), init.end()); 812 } 813 814 basic_string& erase(size_type pos = 0; size_type n = npos) 815 { 816 auto len = min(n, size_ - pos); 817 copy_(begin() + pos + n, end(), begin() + pos); 818 size_ -= len; 819 ensure_null_terminator_(); 820 } 537 821 538 822 iterator erase(const_iterator pos); … … 540 824 iterator erase(const_iterator pos, const_iterator last); 541 825 542 void pop_back(); 826 void pop_back() 827 { 828 --size_; 829 ensure_null_terminator_(); 830 } 543 831 544 832 basic_string& replace(size_type pos, size_type n, const basic_string& str); … … 673 961 size_type capacity_; 674 962 allocator_type allocator_; 963 964 /** 965 * Arbitrary value, standard just requires 966 * data() to have some capacity. 967 * (Well, we could've done data_ = &data_ and 968 * set capacity to 0, but that would be too cryptic.) 969 */ 970 static constexpr size_type default_capacity_{4} 971 972 void init_(const value_type* str, size_type size) 973 { 974 if (data_) 975 allocator_.deallocate(data_, capacity_); 976 977 size_ = size; 978 capacity_ = size; 979 980 data_ = allocator_.allocate(capacity_); 981 traits_type::copy(data_, str, size); 982 ensure_null_terminator_(); 983 } 984 985 size_type next_capacity_(size_type hint = 0) const noexcept 986 { 987 if (hint != 0) 988 return max(capacity_ * 2, hint); 989 else 990 return max(capacity_ * 2, 2ul); 991 } 992 993 void ensure_free_space_(size_type n) 994 { 995 /** 996 * Note: We cannot use reserve like we 997 * did in vector, because in string 998 * reserve can cause shrinking. 999 */ 1000 if (size_ + 1 + n > capacity) 1001 resize_with_copy_(size_, max(size_ + 1 + n, next_capacity_())); 1002 } 1003 1004 void resize_without_copy_(size_type capacity) 1005 { 1006 if (data_) 1007 allocator_.deallocate(data_, capacity_); 1008 1009 data_ = allocator_.allocate(capacity); 1010 size_ = 0; 1011 capacity_ = capacity; 1012 ensure_null_terminator_(); 1013 } 1014 1015 void resize_with_copy_(size_type size, size_type capacity) 1016 { 1017 if(capacity_ == 0 || capacity_ < capacity) 1018 { 1019 auto new_data = allocator_.allocate(capacity); 1020 1021 auto to_copy = min(size, size_); 1022 traits_type::move(new_data, data_, to_copy); 1023 1024 std::swap(data_, new_data); 1025 1026 allocator_.deallocate(new_data, capacity_); 1027 } 1028 1029 capacity_ = capacity; 1030 size_ = size; 1031 ensure_null_terminator_(); 1032 } 1033 1034 iterator copy_(const_iterator first, const_iterator last, 1035 iterator result) 1036 { 1037 while (first != last) 1038 traits_type::assign(*result++, *first++); 1039 1040 ensure_null_terminator_(); 1041 return result; 1042 } 1043 1044 iterator copy_backward_(const_iterator first, const_iterator last, 1045 iterator result) 1046 { 1047 while (last-- != first) 1048 traits_type::assign(*result--, *last); 1049 1050 ensure_null_terminator_(); 1051 return result; 1052 } 1053 1054 void ensure_null_terminator_() 1055 { 1056 traits_type::assign(data_[size_], value_type{}); 1057 } 675 1058 }; 676 1059 }
Note:
See TracChangeset
for help on using the changeset viewer.