| 706 | } |
| 707 | |
| 708 | sonic_force_inline bool removeMemberImpl(StringView key) { |
| 709 | MemberIterator m; |
| 710 | if (nullptr == children()) { |
| 711 | goto not_find; |
| 712 | } |
| 713 | if (getMapUnsfe()) { |
| 714 | auto it = getMapUnsfe()->find(MSType(key.data(), key.size())); |
| 715 | if (it != getMapUnsfe()->end()) { |
| 716 | m = memberBeginUnsafe() + it->second; |
| 717 | getMapUnsfe()->erase(it); |
| 718 | goto find; |
| 719 | } |
| 720 | |
| 721 | goto not_find; |
| 722 | } else { |
| 723 | m = memberBeginUnsafe(); |
| 724 | for (; m != memberEndUnsafe(); ++m) // { |
| 725 | if (m->name.GetStringView() == key) goto find; |
| 726 | |
| 727 | goto not_find; |
| 728 | } |
| 729 | find : { |
| 730 | MemberIterator m_tail = memberBeginUnsafe() + (this->Size() - 1); |
| 731 | // TODO: destroy() then memcpy. |
| 732 | if (m != m_tail) { |
| 733 | DNode* m_name = (DNode*)(&(m->name)); |
| 734 | DNode* tail_name = (DNode*)(&(m_tail->name)); |
| 735 | *m_name = std::move(*tail_name); |
| 736 | m->value = std::move(m_tail->value); |
| 737 | // maintain map |
| 738 | map_type* map = getMap(); |
| 739 | if (map) { |
| 740 | size_t pos = m - memberBeginUnsafe(); |
| 741 | // erase tail |
| 742 | auto range = |
| 743 | map->equal_range(m->name.GetStringView()); // already moved. |
| 744 | for (auto i = range.first; i != range.second; ++i) { |
| 745 | if (i->second == this->Size() - 1) { |
| 746 | map->erase(i); |
| 747 | break; // only one erase. |
| 748 | } |
| 749 | } |
| 750 | map->emplace(std::make_pair(m->name.GetStringView(), pos)); |
| 751 | } |
| 752 | } else { |
| 753 | m->name.~DNode(); |
| 754 | m->value.~DNode(); |
| 755 | } |
| 756 | |
| 757 | this->subLength(1); |
| 758 | return true; |
| 759 | } |
| 760 | not_find: |
| 761 | return false; |
| 762 | } |
| 763 | |
| 764 | MemberIterator eraseMemberImpl(MemberIterator first, MemberIterator last) { |
| 765 | // Destroy map before removing members. |
no test coverage detected