1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#ifndef HIPERF_HASHLIST_H 17#define HIPERF_HASHLIST_H 18 19#include <unordered_map> 20 21namespace OHOS { 22namespace Developtools { 23namespace HiPerf { 24class Link { 25public: 26 Link() = default; 27 ~Link() = default; 28 Link(const Link &link) : prev_ {link.prev_}, next_ {link.next_} {} 29 Link(Link &&link) : prev_ {link.prev_}, next_ {link.next_} 30 { 31 link.prev_ = nullptr; 32 link.next_ = nullptr; 33 } 34 Link &operator=(const Link &link) 35 { 36 prev_ = link.prev_; 37 next_ = link.next_; 38 return *this; 39 } 40 Link &operator=(Link &&link) 41 { 42 prev_ = link.prev_; 43 link.prev_ = nullptr; 44 next_ = link.next_; 45 link.next_ = nullptr; 46 return *this; 47 } 48 Link *prev_ {nullptr}; 49 Link *next_ {nullptr}; 50}; 51 52template<typename Key, typename Val> 53class LinkNode { 54public: 55 Link link_ {}; 56 Key key_ {}; 57 Val val_ {}; 58 59 explicit LinkNode() = default; 60 ~LinkNode() = default; 61 explicit LinkNode(const Key &key); 62 explicit LinkNode(const Key &key, const Val &val); 63 explicit LinkNode(const Key &key, Val &&val); 64 LinkNode(const LinkNode &node); 65 LinkNode(LinkNode &&node); 66 LinkNode &operator=(const LinkNode &node); 67 LinkNode &operator=(LinkNode &&node); 68 static LinkNode<Key, Val> *GetLinkNode(Val *pval); 69 static LinkNode<Key, Val> *GetLinkNode(Link *plink); 70}; 71 72template<typename Key, typename Val> 73class HashList { 74public: 75 class Iterator { 76 public: 77 Iterator() = default; 78 ~Iterator() = default; 79 explicit Iterator(LinkNode<Key, Val> *pnode, HashList *phashList); 80 explicit Iterator(const LinkNode<Key, Val> *pnode, const HashList *phashList); 81 Iterator(const Iterator &itr); 82 Iterator(Iterator &&itr); 83 Iterator &operator=(const Iterator &itr); 84 Iterator &operator=(Iterator &&itr); 85 Iterator &operator++() noexcept; 86 Iterator operator++(int) noexcept; 87 Iterator &operator--() noexcept; 88 Iterator operator--(int) noexcept; 89 bool operator<(const Iterator &itr) const noexcept; 90 bool operator==(const Iterator &itr) const noexcept; 91 Val &operator*(); 92 const Val &operator*() const; 93 Val *operator->(); 94 const Val *operator->() const; 95 void swap(HashList<Key, Val>::Iterator &other); 96 LinkNode<Key, Val> *GetNode() const 97 { 98 return pnode_; 99 } 100 101 private: 102 bool IsDangled() const noexcept 103 { 104 return phashList_ == nullptr; 105 } 106 107 LinkNode<Key, Val> *pnode_ {nullptr}; 108 HashList *phashList_ {nullptr}; 109 }; 110 111 class ReverseIterator { 112 public: 113 ReverseIterator() = default; 114 ~ReverseIterator() = default; 115 explicit ReverseIterator(LinkNode<Key, Val> *pnode, HashList *phashList); 116 explicit ReverseIterator(const LinkNode<Key, Val> *pnode, const HashList *phashList); 117 ReverseIterator(const ReverseIterator &itr); 118 ReverseIterator(ReverseIterator &&itr); 119 ReverseIterator &operator=(const ReverseIterator &itr); 120 ReverseIterator &operator=(ReverseIterator &&itr); 121 ReverseIterator &operator++() noexcept; 122 ReverseIterator operator++(int) noexcept; 123 ReverseIterator &operator--() noexcept; 124 ReverseIterator operator--(int) noexcept; 125 bool operator<(const ReverseIterator &itr) const noexcept; 126 bool operator==(const ReverseIterator &itr) const noexcept; 127 Val &operator*(); 128 const Val &operator*() const; 129 Val *operator->(); 130 const Val *operator->() const; 131 void swap(HashList<Key, Val>::ReverseIterator &other); 132 133 LinkNode<Key, Val> *GetNode() 134 { 135 return pnode_; 136 } 137 138 private: 139 bool IsDangled() const noexcept 140 { 141 return phashList_ == nullptr; 142 } 143 144 LinkNode<Key, Val> *pnode_ {nullptr}; 145 HashList *phashList_ {nullptr}; 146 }; 147 148public: 149 explicit HashList(const std::size_t numItem = 0); 150 ~HashList(); 151 152 HashList(const HashList &source) = delete; 153 HashList &operator=(const HashList &source) = delete; 154 HashList(HashList &&source); 155 HashList &operator=(HashList &&source); 156 157 // capacity 158 inline std::size_t size() const 159 { 160 return valueTab_.size(); 161 } 162 inline bool empty() const 163 { 164 return (dataHead_.next_ == &dataHead_) and (dataHead_.prev_ == &dataHead_); 165 } 166 inline std::size_t capacity() const 167 { 168 return numItem_; 169 } 170 inline bool IsFull() const 171 { 172 return freeHead_.next_ == &freeHead_; 173 } 174 inline std::size_t count(const Key &key) const 175 { 176 return valueTab_.count(key); 177 } 178 179 int reserve(const std::size_t numItem); 180 // iterators 181 Iterator begin(); 182 const Iterator cbegin() const; 183 Iterator end(); 184 const Iterator cend() const; 185 ReverseIterator rbegin(); 186 const ReverseIterator crbegin() const; 187 ReverseIterator rend(); 188 const ReverseIterator crend() const; 189 // element access 190 Val &front(); 191 const Val &front() const; 192 Val &back(bool prepend = false); 193 Val &operator[](const Key &key); 194 // lookup 195 Iterator find(const Key &key); 196 // modifiers 197 void push_front(const Key &key, const Val &val); 198 void push_front(const Key &key, Val &&val); 199 void push_back(const Key &key, const Val &val); 200 void push_back(const Key &key, Val &&val); 201 void pop_front(); 202 void pop_back(); 203 Iterator erase(const Key &key); 204 Iterator erase(const Iterator pos); 205 Iterator erase(const Iterator first, const Iterator last); 206 207private: 208 void MoveToHead(LinkNode<Key, Val> *&pnode); 209 void MoveToTail(LinkNode<Key, Val> *&pnode); 210 bool MoveNode(const Iterator &pos, LinkNode<Key, Val> *&pnode); 211 LinkNode<Key, Val> *AllocateNode(const Key &key); 212 LinkNode<Key, Val> *AllocateNode(const Key &key, const Val &val); 213 LinkNode<Key, Val> *AllocateNode(const Key &key, Val &&val); 214 void ReclaimNode(LinkNode<Key, Val> *&pnode); 215 216 std::size_t numItem_ {0}; 217 LinkNode<Key, Val> *pData_ {nullptr}; 218 Link dataHead_ {}; 219 Link freeHead_ {}; 220 std::unordered_map<Key, LinkNode<Key, Val> *> valueTab_ {}; 221}; 222 223// implementation of template class LinkNode 224template<typename Key, typename Val> 225LinkNode<Key, Val>::LinkNode(const Key &key) : key_ {key} {} 226 227template<typename Key, typename Val> 228LinkNode<Key, Val>::LinkNode(const Key &key, const Val &val) : key_ {key}, val_ {val} {} 229 230template<typename Key, typename Val> 231LinkNode<Key, Val>::LinkNode(const Key &key, Val &&val) : key_ {key}, val_ {std::move(val)} {} 232 233template<typename Key, typename Val> 234LinkNode<Key, Val>::LinkNode(const LinkNode& node) 235 :link_ {node.link_}, 236 key_ {node.key_}, 237 val_ {node.val_} 238{} 239 240template<typename Key, typename Val> 241LinkNode<Key, Val>::LinkNode(LinkNode&& node) 242 :link_ {std::move(node.link_)}, 243 key_ {std::move(node.key_)}, 244 val_ {std::move(node.val_)} 245{} 246 247template<typename Key, typename Val> 248auto LinkNode<Key, Val>::operator=(const LinkNode& node) 249-> LinkNode<Key, Val>& 250{ 251 link_ = node.link_; 252 key_ = node.key_; 253 val_ = node.val_; 254} 255 256template<typename Key, typename Val> 257auto LinkNode<Key, Val>::operator=(LinkNode&& node) 258-> LinkNode<Key, Val>& 259{ 260 link_ = std::move(node.link_); 261 key_ = std::move(node.key_); 262 val_ = std::move(node.val_); 263} 264 265template<typename Key, typename Val> 266auto LinkNode<Key, Val>::GetLinkNode(Val *pval) 267-> LinkNode<Key, Val>* 268{ 269 if (pval) { 270 LinkNode<Key, Val> *pnode {nullptr}; 271 Val* offset = &pnode->val_; 272 auto nodeAddr = reinterpret_cast<char*>(pval) - reinterpret_cast<char*>(offset); 273 return reinterpret_cast<LinkNode<Key, Val>*>(nodeAddr); 274 } 275 return nullptr; 276} 277 278template<typename Key, typename Val> 279auto LinkNode<Key, Val>::GetLinkNode(Link *plink) 280-> LinkNode<Key, Val>* 281{ 282 if (plink) { 283 LinkNode<Key, Val> *pnode {nullptr}; 284 Link* offset = &pnode->link_; 285 auto nodeAddr = reinterpret_cast<char*>(plink) - reinterpret_cast<char*>(offset); 286 return reinterpret_cast<LinkNode<Key, Val>*>(nodeAddr); 287 } 288 return nullptr; 289} 290// end of LinkNode 291 292// implementation of template class Iterator 293template<typename Key, typename Val> 294HashList<Key, Val>::Iterator::Iterator(LinkNode<Key, Val> *pnode, HashList *phashList) 295 : pnode_ {pnode}, phashList_ {phashList} 296{ 297 if (phashList_ == nullptr) { 298 pnode_ = nullptr; 299 } 300} 301 302template<typename Key, typename Val> 303HashList<Key, Val>::Iterator::Iterator(const LinkNode<Key, Val> *pnode, const HashList *phashList) 304 : pnode_ {const_cast<LinkNode<Key, Val>*>(pnode)}, 305 phashList_ {const_cast<HashList*>(phashList)} 306{ 307 if (phashList_ == nullptr) { 308 pnode_ = nullptr; 309 } 310} 311 312template<typename Key, typename Val> 313HashList<Key, Val>::Iterator::Iterator(const Iterator& itr) 314 : pnode_ {itr.pnode_}, phashList_ {itr.phashList_} 315{} 316 317template<typename Key, typename Val> 318HashList<Key, Val>::Iterator::Iterator(Iterator&& itr) 319 : pnode_ {itr.pnode_}, phashList_ {itr.phashList_} 320{ 321 itr.pnode_ = nullptr; 322 itr.phashList_ = nullptr; 323} 324 325template<typename Key, typename Val> 326auto HashList<Key, Val>::Iterator::operator=(const Iterator& itr) 327-> HashList<Key, Val>::Iterator& 328{ 329 Iterator temp {itr}; 330 swap(temp); 331 return *this; 332} 333 334template<typename Key, typename Val> 335auto HashList<Key, Val>::Iterator::operator=(Iterator&& itr) 336-> HashList<Key, Val>::Iterator& 337{ 338 Iterator temp {std::move(itr)}; 339 swap(temp); 340 return *this; 341} 342 343template<typename Key, typename Val> 344auto HashList<Key, Val>::Iterator::operator++() noexcept 345-> HashList<Key, Val>::Iterator & 346{ 347 if (pnode_ == nullptr or phashList_ == nullptr) { 348 phashList_ = nullptr; 349 return *this; 350 } 351 Link* plink = pnode_->link_.next_; 352 if (plink == &phashList_->dataHead_) { 353 pnode_ = nullptr; 354 return *this; 355 } 356 auto pnode = LinkNode<Key, Val>::GetLinkNode(plink); 357 pnode_ = pnode; 358 return *this; 359} 360 361template<typename Key, typename Val> 362auto HashList<Key, Val>::Iterator::operator++(int) noexcept 363-> HashList<Key, Val>::Iterator 364{ 365 Iterator res {*this}; 366 if (pnode_ == nullptr or phashList_ == nullptr) { 367 phashList_ = nullptr; 368 return res; 369 } 370 Link* plink = pnode_->link_.next_; 371 if (plink == &phashList_->dataHead_) { 372 pnode_ = nullptr; 373 return res; 374 } 375 auto pnode = LinkNode<Key, Val>::GetLinkNode(plink); 376 pnode_ = pnode; 377 return res; 378} 379 380template<typename Key, typename Val> 381auto HashList<Key, Val>::Iterator::operator--() noexcept 382-> HashList<Key, Val>::Iterator & 383{ 384 if (phashList_ == nullptr) { 385 return *this; 386 } 387 Link* plink {nullptr}; 388 if (pnode_ == nullptr) { 389 plink = phashList_->dataHead_.prev_; 390 } else { 391 plink = pnode_->link_.prev_; 392 } 393 if (plink == &phashList_->dataHead_) { 394 pnode_ = nullptr; 395 phashList_ = nullptr; 396 return *this; 397 } 398 pnode_ = LinkNode<Key, Val>::GetLinkNode(plink); 399 return *this; 400} 401 402template<typename Key, typename Val> 403auto HashList<Key, Val>::Iterator::operator--(int) noexcept 404-> HashList<Key, Val>::Iterator 405{ 406 Iterator res {*this}; 407 if (phashList_ == nullptr) { 408 return res; 409 } 410 Link* plink {nullptr}; 411 if (pnode_ == nullptr) { 412 plink = phashList_->dataHead_.prev_; 413 } else { 414 plink = pnode_->link_.prev_; 415 } 416 if (plink == &phashList_->dataHead_) { 417 pnode_ = nullptr; 418 phashList_ = nullptr; 419 return res; 420 } 421 pnode_ = LinkNode<Key, Val>::GetLinkNode(plink); 422 return res; 423} 424 425template<typename Key, typename Val> 426bool HashList<Key, Val>::Iterator::operator<(const HashList<Key, Val>::Iterator &itr) const noexcept 427{ 428 if (IsDangled() or itr.IsDangled()) { 429 return false; 430 } 431 if (phashList_ != itr.phashList_) { 432 return false; 433 } 434 Iterator tempItr {*this}; 435 if (tempItr == itr) { 436 return false; 437 } 438 while (!tempItr.IsDangled()) { 439 tempItr++; 440 if (tempItr == itr) { 441 return true; 442 } 443 } 444 return false; 445} 446 447template<typename Key, typename Val> 448bool HashList<Key, Val>::Iterator::operator==(const HashList<Key, Val>::Iterator &itr) const noexcept 449{ 450 if (IsDangled() or itr.IsDangled()) { 451 return false; 452 } 453 if (phashList_ != itr.phashList_) { 454 return false; 455 } 456 return pnode_ == itr.pnode_; 457} 458 459template<typename Key, typename Val> 460Val& HashList<Key, Val>::Iterator::operator*() 461{ 462 return pnode_->val_; 463} 464 465template<typename Key, typename Val> 466const Val& HashList<Key, Val>::Iterator::operator*() const 467{ 468 return pnode_->val_; 469} 470 471template<typename Key, typename Val> 472Val* HashList<Key, Val>::Iterator::operator->() 473{ 474 return &pnode_->val_; 475} 476 477template<typename Key, typename Val> 478const Val* HashList<Key, Val>::Iterator::operator->() const 479{ 480 return &pnode_->val_; 481} 482 483template<typename Key, typename Val> 484void HashList<Key, Val>::Iterator::swap(HashList<Key, Val>::Iterator& other) 485{ 486 using std::swap; 487 swap(pnode_, other.pnode_); 488 swap(phashList_, other.phashList_); 489} 490// end of Iterator 491 492// Implementation of ReverseIterator 493template<typename Key, typename Val> 494HashList<Key, Val>::ReverseIterator::ReverseIterator(LinkNode<Key, Val> *pnode, HashList *phashList) 495 : pnode_ {pnode}, phashList_ {phashList} 496{ 497 if (phashList_ == nullptr) { 498 pnode_ = nullptr; 499 } 500} 501 502template<typename Key, typename Val> 503HashList<Key, Val>::ReverseIterator::ReverseIterator(const LinkNode<Key, Val> *pnode, const HashList *phashList) 504 : pnode_ {const_cast<LinkNode<Key, Val> *>(pnode)}, 505 phashList_ {const_cast<HashList *>(phashList)} 506{ 507 if (phashList_ == nullptr) { 508 pnode_ = nullptr; 509 } 510} 511 512template<typename Key, typename Val> 513HashList<Key, Val>::ReverseIterator::ReverseIterator(const ReverseIterator &itr) 514 : pnode_ {itr.pnode_}, phashList_ {itr.phashList_} 515{} 516 517template<typename Key, typename Val> 518HashList<Key, Val>::ReverseIterator::ReverseIterator(ReverseIterator &&itr) 519 : pnode_ {itr.pnode_}, phashList_ {itr.phashList_} 520{ 521 itr.pnode_ = nullptr; 522 itr.phashList_ = nullptr; 523} 524 525template<typename Key, typename Val> 526auto HashList<Key, Val>::ReverseIterator::operator=(const ReverseIterator& itr) 527-> HashList<Key, Val>::ReverseIterator& 528{ 529 ReverseIterator temp {itr}; 530 swap(temp); 531 return *this; 532} 533 534template<typename Key, typename Val> 535auto HashList<Key, Val>::ReverseIterator::operator=(ReverseIterator&& itr) 536-> HashList<Key, Val>::ReverseIterator& 537{ 538 ReverseIterator temp {std::move(itr)}; 539 swap(temp); 540 return *this; 541} 542 543template<typename Key, typename Val> 544auto HashList<Key, Val>::ReverseIterator::operator++() noexcept 545-> HashList<Key, Val>::ReverseIterator & 546{ 547 if (pnode_ == nullptr or phashList_ == nullptr) { 548 phashList_ = nullptr; 549 return *this; 550 } 551 Link* plink = &pnode_->link_; 552 plink = plink->prev_; 553 if (plink == &phashList_->dataHead_) { 554 pnode_ = nullptr; 555 return *this; 556 } 557 pnode_ = LinkNode<Key, Val>::GetLinkNode(plink); 558 return *this; 559} 560 561template<typename Key, typename Val> 562auto HashList<Key, Val>::ReverseIterator::operator++(int) noexcept 563-> HashList<Key, Val>::ReverseIterator 564{ 565 ReverseIterator res {*this}; 566 if (pnode_ == nullptr or phashList_ == nullptr) { 567 phashList_ = nullptr; 568 return res; 569 } 570 Link* plink = &pnode_->link_; 571 plink = plink->prev_; 572 if (plink == &phashList_->dataHead_) { 573 pnode_ = nullptr; 574 return res; 575 } 576 pnode_ = LinkNode<Key, Val>::GetLinkNode(plink); 577 return res; 578} 579 580template<typename Key, typename Val> 581auto HashList<Key, Val>::ReverseIterator::operator--() noexcept 582-> HashList<Key, Val>::ReverseIterator & 583{ 584 if (phashList_ == nullptr) { 585 return *this; 586 } 587 Link* plink {nullptr}; 588 if (pnode_ == nullptr) { 589 plink = phashList_->dataHead_.next_; 590 } else { 591 plink = pnode_->link_.next_; 592 } 593 if (plink == &phashList_->dataHead_) { 594 pnode_ = nullptr; 595 phashList_ = nullptr; 596 return *this; 597 } 598 pnode_ = LinkNode<Key, Val>::GetLinkNode(plink); 599 return *this; 600} 601 602template<typename Key, typename Val> 603auto HashList<Key, Val>::ReverseIterator::operator--(int) noexcept 604-> HashList<Key, Val>::ReverseIterator 605{ 606 ReverseIterator res {*this}; 607 if (phashList_ == nullptr) { 608 return res; 609 } 610 Link* plink {nullptr}; 611 if (pnode_ == nullptr) { 612 plink = phashList_->dataHead_.next_; 613 } else { 614 plink = pnode_->link_.next_; 615 } 616 if (plink == &phashList_->dataHead_) { 617 pnode_ = nullptr; 618 phashList_ = nullptr; 619 return res; 620 } 621 pnode_ = LinkNode<Key, Val>::GetLinkNode(plink); 622 return res; 623} 624 625template<typename Key, typename Val> 626bool HashList<Key, Val>::ReverseIterator::operator<( 627 const HashList<Key, Val>::ReverseIterator &itr) const noexcept 628{ 629 if (IsDangled() or itr.IsDangled()) { 630 return false; 631 } 632 if (phashList_ != itr.phashList_) { 633 return false; 634 } 635 HashList<Key, Val>::ReverseIterator tempItr {*this}; 636 if (tempItr == itr) { 637 return false; 638 } 639 while (!tempItr.IsDangled()) { 640 tempItr++; 641 if (tempItr == itr) { 642 return true; 643 } 644 } 645 return false; 646} 647 648template<typename Key, typename Val> 649bool HashList<Key, Val>::ReverseIterator::operator==( 650 const HashList<Key, Val>::ReverseIterator &itr) const noexcept 651{ 652 if (IsDangled() or itr.IsDangled()) { 653 return false; 654 } 655 if (phashList_ != itr.phashList_) { 656 return false; 657 } 658 return pnode_ == itr.pnode_; 659} 660 661template<typename Key, typename Val> 662Val& HashList<Key, Val>::ReverseIterator::operator*() 663{ 664 return pnode_->val_; 665} 666 667template<typename Key, typename Val> 668const Val& HashList<Key, Val>::ReverseIterator::operator*() const 669{ 670 return pnode_->val_; 671} 672 673template<typename Key, typename Val> 674Val* HashList<Key, Val>::ReverseIterator::operator->() 675{ 676 return &pnode_->val_; 677} 678 679template<typename Key, typename Val> 680const Val* HashList<Key, Val>::ReverseIterator::operator->() const 681{ 682 return &pnode_->val_; 683} 684 685template<typename Key, typename Val> 686void HashList<Key, Val>::ReverseIterator::swap(HashList<Key, Val>::ReverseIterator& other) 687{ 688 using std::swap; 689 swap(pnode_, other.pnode_); 690 swap(phashList_, other.phashList_); 691} 692// end of ReverseIterator 693 694// implementation of template class HashList 695template<typename Key, typename Val> 696HashList<Key, Val>::HashList(const std::size_t numItem) : numItem_ {numItem} 697{ 698 dataHead_.next_ = &dataHead_; 699 dataHead_.prev_ = &dataHead_; 700 if (numItem_) { 701 valueTab_.reserve(numItem_); 702 pData_ = new(std::nothrow) LinkNode<Key, Val>[numItem_]; 703 if (pData_) { 704 freeHead_.next_ = &(pData_[0].link_); 705 std::size_t last {numItem_ - 1}; 706 for (std::size_t index = 0; index < last;) { 707 LinkNode<Key, Val> &curNnode = pData_[index]; 708 curNnode.link_.next_ = &(pData_[++index].link_); 709 } 710 pData_[last].link_.next_ = &freeHead_; 711 } else { 712 numItem_ = 0; 713 freeHead_.next_ = &freeHead_; 714 freeHead_.prev_ = &freeHead_; 715 } 716 } 717} 718 719template<typename Key, typename Val> 720int HashList<Key, Val>::reserve(const std::size_t numItem) 721{ 722 if (numItem_ != 0) { 723 return -1; 724 } 725 if (numItem) { 726 numItem_ = numItem; 727 valueTab_.reserve(numItem_); 728 pData_ = new(std::nothrow) LinkNode<Key, Val>[numItem_]; 729 dataHead_.next_ = &dataHead_; 730 dataHead_.prev_ = &dataHead_; 731 if (pData_) { 732 freeHead_.next_ = &(pData_[0].link_); 733 std::size_t last {numItem_ - 1}; 734 for (std::size_t index = 0; index < last;) { 735 LinkNode<Key, Val> &curNnode = pData_[index]; 736 curNnode.link_.next_ = &(pData_[++index].link_); 737 } 738 pData_[last].link_.next_ = &freeHead_; 739 } else { 740 numItem_ = 0; 741 freeHead_.next_ = &freeHead_; 742 freeHead_.prev_ = &freeHead_; 743 } 744 } 745 return numItem_; 746} 747 748template<typename Key, typename Val> 749HashList<Key, Val>::~HashList() 750{ 751 if (pData_) { 752 delete[] pData_; 753 pData_ = nullptr; 754 } 755 valueTab_.clear(); 756 dataHead_.next_ = &dataHead_; 757 dataHead_.prev_ = &dataHead_; 758 freeHead_.next_ = nullptr; 759 freeHead_.prev_ = nullptr; 760 numItem_ = 0; 761} 762 763template<typename Key, typename Val> 764HashList<Key, Val>::HashList(HashList<Key, Val> &&source) 765 : numItem_ {source.numItem_}, 766 pData_ {source.pData_}, 767 dataHead_ {std::move(source.dataHead_)}, 768 freeHead_ {std::move(source.freeHead_)}, 769 valueTab_ {std::move(source.valueTab_)} 770{ 771 source.pData_ = nullptr; 772} 773 774template<typename Key, typename Val> 775auto HashList<Key, Val>::operator=(HashList &&source) 776-> HashList<Key, Val>& 777{ 778 if (this == &source) { 779 return *this; 780 } 781 if (pData_) { 782 delete[] pData_; 783 pData_ = nullptr; 784 } 785 numItem_ = source.numItem_; 786 pData_ = source.pData_; 787 source.pData_ = nullptr; 788 dataHead_ = std::move(source.dataHead_); 789 freeHead_ = std::move(source.freeHead_); 790 valueTab_ = std::move(source.valueTab_); 791 return *this; 792} 793 794template<typename Key, typename Val> 795auto HashList<Key, Val>::begin() 796-> HashList<Key, Val>::Iterator 797{ 798 if (empty()) { 799 return end(); 800 } 801 return Iterator(LinkNode<Key, Val>::GetLinkNode(dataHead_.next_), this); 802} 803 804template<typename Key, typename Val> 805auto HashList<Key, Val>::cbegin() const 806-> const HashList<Key, Val>::Iterator 807{ 808 if (empty()) { 809 return cend(); 810 } 811 return Iterator(LinkNode<Key, Val>::GetLinkNode(dataHead_.next_), this); 812} 813 814template<typename Key, typename Val> 815auto HashList<Key, Val>::end() 816-> HashList<Key, Val>::Iterator 817{ 818 return Iterator(nullptr, this); 819} 820 821template<typename Key, typename Val> 822auto HashList<Key, Val>::cend() const 823-> const HashList<Key, Val>::Iterator 824{ 825 return Iterator(nullptr, this); 826} 827 828template<typename Key, typename Val> 829auto HashList<Key, Val>::rbegin() 830-> HashList<Key, Val>::ReverseIterator 831{ 832 if (empty()) { 833 return rend(); 834 } 835 return ReverseIterator(LinkNode<Key, Val>::GetLinkNode(dataHead_.prev_), this); 836} 837 838template<typename Key, typename Val> 839auto HashList<Key, Val>::crbegin() const 840-> const HashList<Key, Val>::ReverseIterator 841{ 842 if (empty()) { 843 return crend(); 844 } 845 return ReverseIterator(LinkNode<Key, Val>::GetLinkNode(dataHead_.prev_), this); 846} 847 848template<typename Key, typename Val> 849auto HashList<Key, Val>::rend() 850-> HashList<Key, Val>::ReverseIterator 851{ 852 return ReverseIterator(nullptr, this); 853} 854 855template<typename Key, typename Val> 856auto HashList<Key, Val>::crend() const 857-> const HashList<Key, Val>::ReverseIterator 858{ 859 return ReverseIterator(nullptr, this); 860} 861 862template<typename Key, typename Val> 863Val& HashList<Key, Val>::front() 864{ 865 LinkNode<Key, Val> *pnode = LinkNode<Key, Val>::GetLinkNode(dataHead_.next_); 866 return pnode->val_; 867} 868 869template<typename Key, typename Val> 870const Val& HashList<Key, Val>::front() const 871{ 872 return front(); 873} 874 875template<typename Key, typename Val> 876Val& HashList<Key, Val>::back(bool prepend) 877{ 878 auto pnode = LinkNode<Key, Val>::GetLinkNode(dataHead_.prev_); 879 if (prepend) { 880 MoveToHead(pnode); 881 } 882 return pnode->val_; 883} 884 885template<typename Key, typename Val> 886Val& HashList<Key, Val>::operator[](const Key &key) 887{ 888 LinkNode<Key, Val> *pnode {nullptr}; 889 if (valueTab_.find(key) == valueTab_.end()) { 890 pnode = AllocateNode(key); 891 valueTab_[key] = pnode; 892 } else { 893 pnode = valueTab_[key]; 894 } 895 if (pnode == nullptr) { 896 static Val val = Val(); 897 return val; 898 } else { 899 MoveToHead(pnode); 900 } 901 return pnode->val_; 902} 903 904template<typename Key, typename Val> 905auto HashList<Key, Val>::find(const Key &key) 906-> HashList<Key, Val>::Iterator 907{ 908 const auto &itr = valueTab_.find(key); 909 if (itr == valueTab_.end()) { 910 return end(); 911 } 912 return Iterator(itr->second, this); 913} 914 915template<typename Key, typename Val> 916void HashList<Key, Val>::push_front(const Key& key, const Val& val) 917{ 918 if (valueTab_.find(key) == valueTab_.end()) { 919 LinkNode<Key, Val>* pnode = AllocateNode(key, val); 920 MoveToHead(pnode); 921 valueTab_[pnode->key_] = pnode; 922 } else { 923 MoveToHead(valueTab_[key]); 924 this->operator[](key) = val; 925 } 926} 927 928template<typename Key, typename Val> 929void HashList<Key, Val>::push_front(const Key& key, Val&& val) 930{ 931 if (valueTab_.find(key) == valueTab_.end()) { 932 LinkNode<Key, Val>* pnode = AllocateNode(key, std::move(val)); 933 MoveToHead(pnode); 934 valueTab_[pnode->key_] = pnode; 935 } else { 936 MoveToHead(valueTab_[key]); 937 this->operator[](key) = val; 938 } 939} 940 941template<typename Key, typename Val> 942void HashList<Key, Val>::push_back(const Key& key, const Val& val) 943{ 944 if (valueTab_.find(key) == valueTab_.end()) { 945 LinkNode<Key, Val>* pnode = AllocateNode(key, val); 946 MoveToTail(pnode); 947 valueTab_[pnode->key_] = pnode; 948 } else { 949 MoveToTail(valueTab_[key]); 950 this->operator[](key) = val; 951 } 952} 953 954template<typename Key, typename Val> 955void HashList<Key, Val>::push_back(const Key& key, Val&& val) 956{ 957 if (valueTab_.find(key) == valueTab_.end()) { 958 LinkNode<Key, Val>* pnode = AllocateNode(key, std::move(val)); 959 MoveToTail(pnode); 960 valueTab_[pnode->key_] = pnode; 961 } else { 962 MoveToTail(valueTab_[key]); 963 this->operator[](key) = val; 964 } 965} 966 967template<typename Key, typename Val> 968void HashList<Key, Val>::pop_front() 969{ 970 if (empty()) { 971 return; 972 } 973 LinkNode<Key, Val>* pnode = LinkNode<Key, Val>::GetLinkNode(dataHead_.next_); 974 valueTab_.erase(pnode->key_); 975 ReclaimNode(pnode); 976} 977 978template<typename Key, typename Val> 979void HashList<Key, Val>::pop_back() 980{ 981 if (empty()) { 982 return; 983 } 984 LinkNode<Key, Val>* pnode = LinkNode<Key, Val>::GetLinkNode(dataHead_.prev_); 985 if (pnode != nullptr) { 986 valueTab_.erase(pnode->key_); 987 ReclaimNode(pnode); 988 } 989} 990 991template<typename Key, typename Val> 992auto HashList<Key, Val>::erase(const Key& key) 993-> HashList<Key, Val>::Iterator 994{ 995 if (valueTab_.find(key) == valueTab_.end()) { 996 return end(); 997 } 998 LinkNode<Key, Val> *pnode = valueTab_[key]; 999 valueTab_.erase(key); 1000 Link* plink = pnode->link_.next_; 1001 Iterator tempItr {LinkNode<Key, Val>::GetLinkNode(plink), this}; 1002 ReclaimNode(pnode); 1003 return tempItr; 1004} 1005 1006template<typename Key, typename Val> 1007auto HashList<Key, Val>::erase(const Iterator pos) 1008-> HashList<Key, Val>::Iterator 1009{ 1010 // assume pos is valid, otherwise the result is undefined 1011 Iterator tempItr {pos}; 1012 ++tempItr; 1013 LinkNode<Key, Val> *pnode = pos.GetNode(); 1014 valueTab_.erase(pnode->key_); 1015 ReclaimNode(pnode); 1016 return tempItr; 1017} 1018 1019template<typename Key, typename Val> 1020auto HashList<Key, Val>::erase(const Iterator first, const Iterator last) 1021-> HashList<Key, Val>::Iterator 1022{ 1023 // assume pos is valid, otherwise the result is undefined 1024 if (first <= last) { 1025 Iterator curPos {first}; 1026 while (curPos < last) { 1027 curPos = erase(curPos); 1028 } 1029 return last; 1030 } 1031 return end(); 1032} 1033 1034template<typename Key, typename Val> 1035bool HashList<Key, Val>::MoveNode(const Iterator& pos, LinkNode<Key, Val> *&pnode) 1036{ 1037 LinkNode<Key, Val> *curNode = pos.GetNode(); 1038 if (curNode == pnode) { 1039 return true; 1040 } 1041 if (pnode->link_.next_ == &curNode->link_) { 1042 return true; 1043 } 1044 Link* prevLink = pnode->link_.prev_; 1045 Link* nextLink = pnode->link_.next_; 1046 if (prevLink and nextLink) { 1047 prevLink->next_ = nextLink; 1048 nextLink->prev_ = prevLink; 1049 } 1050 Link *currLink = &curNode->link_; 1051 prevLink = currLink->prev_; 1052 nextLink = &pnode->link_; 1053 prevLink->next_ = nextLink; 1054 nextLink->prev_ = prevLink; 1055 nextLink->next_ = currLink; 1056 currLink->prev_ = nextLink; 1057 return true; 1058} 1059 1060template<typename Key, typename Val> 1061void HashList<Key, Val>::MoveToHead(LinkNode<Key, Val> *&pnode) 1062{ 1063 if (pnode->link_.prev_ and pnode->link_.next_) { 1064 Link* prev = pnode->link_.prev_; 1065 Link* next = pnode->link_.next_; 1066 prev->next_ = next; 1067 next->prev_ = prev; 1068 } 1069 pnode->link_.next_ = dataHead_.next_; 1070 dataHead_.next_->prev_ = &pnode->link_; 1071 dataHead_.next_ = &pnode->link_; 1072 pnode->link_.prev_ = &dataHead_; 1073} 1074 1075template<typename Key, typename Val> 1076void HashList<Key, Val>::MoveToTail(LinkNode<Key, Val> *&pnode) 1077{ 1078 if (pnode->link_.prev_ and pnode->link_.next_) { 1079 Link* prev = pnode->link_.prev_; 1080 Link* next = pnode->link_.next_; 1081 prev->next_ = next; 1082 next->prev_ = prev; 1083 } 1084 pnode->link_.prev_ = dataHead_.prev_; 1085 dataHead_.prev_->next_ = &pnode->link_; 1086 pnode->link_.next_ = &dataHead_; 1087 dataHead_.prev_ = &pnode->link_; 1088} 1089 1090template<typename Key, typename Val> 1091auto HashList<Key, Val>::AllocateNode(const Key &key) 1092->LinkNode<Key, Val> * 1093{ 1094 if (IsFull()) { 1095 pop_back(); 1096 } 1097 LinkNode<Key, Val> *pnode = LinkNode<Key, Val>::GetLinkNode(freeHead_.next_); 1098 freeHead_.next_ = freeHead_.next_->next_; 1099 if (pnode != nullptr) { 1100 pnode->link_.next_ = nullptr; 1101 pnode->link_.prev_ = nullptr; 1102 pnode->key_ = key; 1103 pnode->val_ = Val(); 1104 } 1105 return pnode; 1106} 1107 1108template<typename Key, typename Val> 1109auto HashList<Key, Val>::AllocateNode(const Key &key, const Val &val) 1110->LinkNode<Key, Val> * 1111{ 1112 if (IsFull()) { 1113 pop_back(); 1114 } 1115 LinkNode<Key, Val> *pnode = LinkNode<Key, Val>::GetLinkNode(freeHead_.next_); 1116 freeHead_.next_ = freeHead_.next_->next_; 1117 pnode->link_.next_ = nullptr; 1118 pnode->link_.prev_ = nullptr; 1119 pnode->key_ = key; 1120 pnode->val_ = val; 1121 return pnode; 1122} 1123 1124template<typename Key, typename Val> 1125auto HashList<Key, Val>::AllocateNode(const Key &key, Val &&val) 1126->LinkNode<Key, Val> * 1127{ 1128 if (IsFull()) { 1129 pop_back(); 1130 } 1131 LinkNode<Key, Val> *pnode = LinkNode<Key, Val>::GetLinkNode(freeHead_.next_); 1132 freeHead_.next_ = freeHead_.next_->next_; 1133 pnode->link_.next_ = nullptr; 1134 pnode->link_.prev_ = nullptr; 1135 pnode->key_ = key; 1136 pnode->val_ = std::move(val); 1137 return pnode; 1138} 1139 1140template<typename Key, typename Val> 1141void HashList<Key, Val>::ReclaimNode(LinkNode<Key, Val> *&pnode) 1142{ 1143 Link *prevLink = pnode->link_.prev_; 1144 Link *nextLink = pnode->link_.next_; 1145 prevLink->next_ = nextLink; 1146 nextLink->prev_ = prevLink; 1147 pnode->link_.prev_ = nullptr; 1148 pnode->link_.next_ = freeHead_.next_; 1149 freeHead_.next_ = &pnode->link_; 1150 return; 1151} 1152} // namespace HiPerf 1153} // namespace Developtools 1154} // namespace OHOS 1155#endif // HIPERF_HASHLIST_H 1156