| 645 | } // namespace |
| 646 | |
| 647 | Value StringValue::Substring(int64_t start) const { |
| 648 | if (start < 0) { |
| 649 | return ErrorValue(absl::InvalidArgumentError( |
| 650 | "<string>.substring(<start>): <start> is less than 0")); |
| 651 | } |
| 652 | if (static_cast<uint64_t>(start) > value_.size()) { |
| 653 | return ErrorValue(absl::InvalidArgumentError( |
| 654 | "<string>.substring(<start>, <end>): <start> or <end> is greater than " |
| 655 | "<string>.size()")); |
| 656 | } |
| 657 | if (start == 0) { |
| 658 | return *this; |
| 659 | } |
| 660 | switch (value_.GetKind()) { |
| 661 | case common_internal::ByteStringKind::kSmall: { |
| 662 | absl::StatusOr<size_t> status_or_index = |
| 663 | (SubstringImpl)(value_.GetSmall(), start); |
| 664 | if (!status_or_index.ok()) { |
| 665 | return ErrorValue(std::move(status_or_index).status()); |
| 666 | } |
| 667 | StringValue result; |
| 668 | result.value_.rep_.header.kind = common_internal::ByteStringKind::kSmall; |
| 669 | result.value_.rep_.small.size = value_.rep_.small.size - *status_or_index; |
| 670 | std::memcpy(result.value_.rep_.small.data, |
| 671 | value_.rep_.small.data + *status_or_index, |
| 672 | result.value_.rep_.small.size); |
| 673 | result.value_.rep_.small.arena = value_.rep_.small.arena; |
| 674 | return result; |
| 675 | } |
| 676 | case common_internal::ByteStringKind::kMedium: { |
| 677 | absl::StatusOr<size_t> status_or_index = |
| 678 | (SubstringImpl)(value_.GetMedium(), start); |
| 679 | if (!status_or_index.ok()) { |
| 680 | return ErrorValue(std::move(status_or_index).status()); |
| 681 | } |
| 682 | StringValue result; |
| 683 | result.value_.rep_.header.kind = common_internal::ByteStringKind::kMedium; |
| 684 | result.value_.rep_.medium.size = |
| 685 | value_.rep_.medium.size - *status_or_index; |
| 686 | result.value_.rep_.medium.data = |
| 687 | value_.rep_.medium.data + *status_or_index; |
| 688 | result.value_.rep_.medium.owner = value_.rep_.medium.owner; |
| 689 | common_internal::StrongRef(result.value_.GetMediumReferenceCount()); |
| 690 | return result; |
| 691 | } |
| 692 | case common_internal::ByteStringKind::kLarge: { |
| 693 | absl::StatusOr<absl::Cord> status_or_cord = |
| 694 | (SubstringImpl)(value_.GetLarge(), start); |
| 695 | if (!status_or_cord.ok()) { |
| 696 | return ErrorValue(std::move(status_or_cord).status()); |
| 697 | } |
| 698 | return StringValue::Wrap(*std::move(status_or_cord)); |
| 699 | } |
| 700 | } |
| 701 | } |
| 702 | |
| 703 | namespace { |
| 704 |
no test coverage detected