• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 namespace OHOS {
22 namespace Developtools {
23 namespace HiPerf {
24 class Link {
25 public:
26     Link() = default;
27     ~Link() = default;
Link(const Link & link)28     Link(const Link &link) : prev_ {link.prev_}, next_ {link.next_} {}
Link(Link && link)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 
52 template<typename Key, typename Val>
53 class LinkNode {
54 public:
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 
72 template<typename Key, typename Val>
73 class HashList {
74 public:
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);
GetNode()96         LinkNode<Key, Val> *GetNode() const
97         {
98             return pnode_;
99         }
100 
101     private:
IsDangled()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 
GetNode()133         LinkNode<Key, Val> *GetNode()
134         {
135             return pnode_;
136         }
137 
138     private:
IsDangled()139         bool IsDangled() const noexcept
140         {
141             return phashList_ == nullptr;
142         }
143 
144         LinkNode<Key, Val> *pnode_ {nullptr};
145         HashList *phashList_ {nullptr};
146     };
147 
148 public:
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
size()158     inline std::size_t size() const
159     {
160         return valueTab_.size();
161     }
empty()162     inline bool empty() const
163     {
164         return (dataHead_.next_ == &dataHead_) and (dataHead_.prev_ == &dataHead_);
165     }
capacity()166     inline std::size_t capacity() const
167     {
168         return numItem_;
169     }
IsFull()170     inline bool IsFull() const
171     {
172         return freeHead_.next_ == &freeHead_;
173     }
count(const Key & key)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 
207 private:
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
224 template<typename Key, typename Val>
LinkNode(const Key & key)225 LinkNode<Key, Val>::LinkNode(const Key &key) : key_ {key} {}
226 
227 template<typename Key, typename Val>
LinkNode(const Key & key,const Val & val)228 LinkNode<Key, Val>::LinkNode(const Key &key, const Val &val) : key_ {key}, val_ {val} {}
229 
230 template<typename Key, typename Val>
LinkNode(const Key & key,Val && val)231 LinkNode<Key, Val>::LinkNode(const Key &key, Val &&val) : key_ {key}, val_ {std::move(val)} {}
232 
233 template<typename Key, typename Val>
LinkNode(const LinkNode & node)234 LinkNode<Key, Val>::LinkNode(const LinkNode& node)
235     :link_ {node.link_},
236     key_ {node.key_},
237     val_ {node.val_}
238 {}
239 
240 template<typename Key, typename Val>
LinkNode(LinkNode && node)241 LinkNode<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 
247 template<typename Key, typename Val>
248 auto 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 
256 template<typename Key, typename Val>
257 auto 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 
265 template<typename Key, typename Val>
266 auto 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 
278 template<typename Key, typename Val>
279 auto 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
293 template<typename Key, typename Val>
Iterator(LinkNode<Key,Val> * pnode,HashList * phashList)294 HashList<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 
302 template<typename Key, typename Val>
Iterator(const LinkNode<Key,Val> * pnode,const HashList * phashList)303 HashList<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 
312 template<typename Key, typename Val>
Iterator(const Iterator & itr)313 HashList<Key, Val>::Iterator::Iterator(const Iterator& itr)
314     : pnode_ {itr.pnode_}, phashList_ {itr.phashList_}
315 {}
316 
317 template<typename Key, typename Val>
Iterator(Iterator && itr)318 HashList<Key, Val>::Iterator::Iterator(Iterator&& itr)
319     : pnode_ {itr.pnode_}, phashList_ {itr.phashList_}
320 {
321     itr.pnode_ = nullptr;
322     itr.phashList_ = nullptr;
323 }
324 
325 template<typename Key, typename Val>
326 auto 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 
334 template<typename Key, typename Val>
335 auto 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 
343 template<typename Key, typename Val>
344 auto 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 
361 template<typename Key, typename Val>
362 auto 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 
380 template<typename Key, typename Val>
381 auto 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 
402 template<typename Key, typename Val>
403 auto 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 
425 template<typename Key, typename Val>
426 bool 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 
447 template<typename Key, typename Val>
448 bool 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 
459 template<typename Key, typename Val>
460 Val& HashList<Key, Val>::Iterator::operator*()
461 {
462     return pnode_->val_;
463 }
464 
465 template<typename Key, typename Val>
466 const Val& HashList<Key, Val>::Iterator::operator*() const
467 {
468     return pnode_->val_;
469 }
470 
471 template<typename Key, typename Val>
472 Val* HashList<Key, Val>::Iterator::operator->()
473 {
474     return &pnode_->val_;
475 }
476 
477 template<typename Key, typename Val>
478 const Val* HashList<Key, Val>::Iterator::operator->() const
479 {
480     return &pnode_->val_;
481 }
482 
483 template<typename Key, typename Val>
swap(HashList<Key,Val>::Iterator & other)484 void 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
493 template<typename Key, typename Val>
ReverseIterator(LinkNode<Key,Val> * pnode,HashList * phashList)494 HashList<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 
502 template<typename Key, typename Val>
ReverseIterator(const LinkNode<Key,Val> * pnode,const HashList * phashList)503 HashList<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 
512 template<typename Key, typename Val>
ReverseIterator(const ReverseIterator & itr)513 HashList<Key, Val>::ReverseIterator::ReverseIterator(const ReverseIterator &itr)
514     : pnode_ {itr.pnode_}, phashList_ {itr.phashList_}
515 {}
516 
517 template<typename Key, typename Val>
ReverseIterator(ReverseIterator && itr)518 HashList<Key, Val>::ReverseIterator::ReverseIterator(ReverseIterator &&itr)
519     : pnode_ {itr.pnode_}, phashList_ {itr.phashList_}
520 {
521     itr.pnode_ = nullptr;
522     itr.phashList_ = nullptr;
523 }
524 
525 template<typename Key, typename Val>
526 auto 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 
534 template<typename Key, typename Val>
535 auto 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 
543 template<typename Key, typename Val>
544 auto 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 
561 template<typename Key, typename Val>
562 auto 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 
580 template<typename Key, typename Val>
581 auto 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 
602 template<typename Key, typename Val>
603 auto 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 
625 template<typename Key, typename Val>
626 bool 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 
648 template<typename Key, typename Val>
649 bool 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 
661 template<typename Key, typename Val>
662 Val& HashList<Key, Val>::ReverseIterator::operator*()
663 {
664     return pnode_->val_;
665 }
666 
667 template<typename Key, typename Val>
668 const Val& HashList<Key, Val>::ReverseIterator::operator*() const
669 {
670     return pnode_->val_;
671 }
672 
673 template<typename Key, typename Val>
674 Val* HashList<Key, Val>::ReverseIterator::operator->()
675 {
676     return &pnode_->val_;
677 }
678 
679 template<typename Key, typename Val>
680 const Val* HashList<Key, Val>::ReverseIterator::operator->() const
681 {
682     return &pnode_->val_;
683 }
684 
685 template<typename Key, typename Val>
swap(HashList<Key,Val>::ReverseIterator & other)686 void 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
695 template<typename Key, typename Val>
HashList(const std::size_t numItem)696 HashList<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 
719 template<typename Key, typename Val>
reserve(const std::size_t numItem)720 int 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 
748 template<typename Key, typename Val>
~HashList()749 HashList<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 
763 template<typename Key, typename Val>
HashList(HashList<Key,Val> && source)764 HashList<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 
774 template<typename Key, typename Val>
775 auto 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 
794 template<typename Key, typename Val>
795 auto 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 
804 template<typename Key, typename Val>
805 auto 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 
814 template<typename Key, typename Val>
815 auto HashList<Key, Val>::end()
816 -> HashList<Key, Val>::Iterator
817 {
818     return Iterator(nullptr, this);
819 }
820 
821 template<typename Key, typename Val>
822 auto HashList<Key, Val>::cend() const
823 -> const HashList<Key, Val>::Iterator
824 {
825     return Iterator(nullptr, this);
826 }
827 
828 template<typename Key, typename Val>
829 auto 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 
838 template<typename Key, typename Val>
839 auto 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 
848 template<typename Key, typename Val>
849 auto HashList<Key, Val>::rend()
850 -> HashList<Key, Val>::ReverseIterator
851 {
852     return ReverseIterator(nullptr, this);
853 }
854 
855 template<typename Key, typename Val>
856 auto HashList<Key, Val>::crend() const
857 -> const HashList<Key, Val>::ReverseIterator
858 {
859     return ReverseIterator(nullptr, this);
860 }
861 
862 template<typename Key, typename Val>
front()863 Val& HashList<Key, Val>::front()
864 {
865     LinkNode<Key, Val> *pnode = LinkNode<Key, Val>::GetLinkNode(dataHead_.next_);
866     return pnode->val_;
867 }
868 
869 template<typename Key, typename Val>
front()870 const Val& HashList<Key, Val>::front() const
871 {
872     return front();
873 }
874 
875 template<typename Key, typename Val>
back(bool prepend)876 Val& 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 
885 template<typename Key, typename Val>
886 Val& 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) {
896         MoveToHead(pnode);
897     }
898     return pnode->val_;
899 }
900 
901 template<typename Key, typename Val>
902 auto HashList<Key, Val>::find(const Key &key)
903 -> HashList<Key, Val>::Iterator
904 {
905     const auto &itr = valueTab_.find(key);
906     if (itr == valueTab_.end()) {
907         return end();
908     }
909     return Iterator(itr->second, this);
910 }
911 
912 template<typename Key, typename Val>
push_front(const Key & key,const Val & val)913 void HashList<Key, Val>::push_front(const Key& key, const Val& val)
914 {
915     if (valueTab_.find(key) == valueTab_.end()) {
916         LinkNode<Key, Val>* pnode = AllocateNode(key, val);
917         MoveToHead(pnode);
918         valueTab_[pnode->key_] = pnode;
919     } else {
920         MoveToHead(valueTab_[key]);
921         this->operator[](key) =  val;
922     }
923 }
924 
925 template<typename Key, typename Val>
push_front(const Key & key,Val && val)926 void HashList<Key, Val>::push_front(const Key& key, Val&& val)
927 {
928     if (valueTab_.find(key) == valueTab_.end()) {
929         LinkNode<Key, Val>* pnode = AllocateNode(key, std::move(val));
930         MoveToHead(pnode);
931         valueTab_[pnode->key_] = pnode;
932     } else {
933         MoveToHead(valueTab_[key]);
934         this->operator[](key) =  val;
935     }
936 }
937 
938 template<typename Key, typename Val>
push_back(const Key & key,const Val & val)939 void HashList<Key, Val>::push_back(const Key& key, const Val& val)
940 {
941     if (valueTab_.find(key) == valueTab_.end()) {
942         LinkNode<Key, Val>* pnode = AllocateNode(key, val);
943         MoveToTail(pnode);
944         valueTab_[pnode->key_] = pnode;
945     } else {
946         MoveToTail(valueTab_[key]);
947         this->operator[](key) =  val;
948     }
949 }
950 
951 template<typename Key, typename Val>
push_back(const Key & key,Val && val)952 void HashList<Key, Val>::push_back(const Key& key, Val&& val)
953 {
954     if (valueTab_.find(key) == valueTab_.end()) {
955         LinkNode<Key, Val>* pnode = AllocateNode(key, std::move(val));
956         MoveToTail(pnode);
957         valueTab_[pnode->key_] = pnode;
958     } else {
959         MoveToTail(valueTab_[key]);
960         this->operator[](key) =  val;
961     }
962 }
963 
964 template<typename Key, typename Val>
pop_front()965 void HashList<Key, Val>::pop_front()
966 {
967     if (empty()) {
968         return;
969     }
970     LinkNode<Key, Val>* pnode = LinkNode<Key, Val>::GetLinkNode(dataHead_.next_);
971     valueTab_.erase(pnode->key_);
972     ReclaimNode(pnode);
973 }
974 
975 template<typename Key, typename Val>
pop_back()976 void HashList<Key, Val>::pop_back()
977 {
978     if (empty()) {
979         return;
980     }
981     LinkNode<Key, Val>* pnode = LinkNode<Key, Val>::GetLinkNode(dataHead_.prev_);
982     valueTab_.erase(pnode->key_);
983     ReclaimNode(pnode);
984 }
985 
986 template<typename Key, typename Val>
987 auto HashList<Key, Val>::erase(const Key& key)
988 -> HashList<Key, Val>::Iterator
989 {
990     if (valueTab_.find(key) == valueTab_.end()) {
991         return end();
992     }
993     LinkNode<Key, Val> *pnode = valueTab_[key];
994     valueTab_.erase(key);
995     Link* plink = pnode->link_.next_;
996     Iterator tempItr {LinkNode<Key, Val>::GetLinkNode(plink), this};
997     ReclaimNode(pnode);
998     return tempItr;
999 }
1000 
1001 template<typename Key, typename Val>
1002 auto HashList<Key, Val>::erase(const Iterator pos)
1003 -> HashList<Key, Val>::Iterator
1004 {
1005     // assume pos is valid, otherwise the result is undefined
1006     Iterator tempItr {pos};
1007     ++tempItr;
1008     LinkNode<Key, Val> *pnode = pos.GetNode();
1009     valueTab_.erase(pnode->key_);
1010     ReclaimNode(pnode);
1011     return tempItr;
1012 }
1013 
1014 template<typename Key, typename Val>
1015 auto HashList<Key, Val>::erase(const Iterator first, const Iterator last)
1016 -> HashList<Key, Val>::Iterator
1017 {
1018     // assume pos is valid, otherwise the result is undefined
1019     if (first <= last) {
1020         Iterator curPos {first};
1021         while (curPos < last) {
1022             curPos = erase(curPos);
1023         }
1024         return last;
1025     }
1026     return end();
1027 }
1028 
1029 template<typename Key, typename Val>
MoveNode(const Iterator & pos,LinkNode<Key,Val> * & pnode)1030 bool HashList<Key, Val>::MoveNode(const Iterator& pos, LinkNode<Key, Val> *&pnode)
1031 {
1032     LinkNode<Key, Val> *curNode = pos.GetNode();
1033     if (curNode == pnode) {
1034         return true;
1035     }
1036     if (pnode->link_.next_ == &curNode->link_) {
1037         return true;
1038     }
1039     Link* prevLink = pnode->link_.prev_;
1040     Link* nextLink = pnode->link_.next_;
1041     if (prevLink and nextLink) {
1042         prevLink->next_ = nextLink;
1043         nextLink->prev_ = prevLink;
1044     }
1045     Link *currLink = &curNode->link_;
1046     prevLink = currLink->prev_;
1047     nextLink = &pnode->link_;
1048     prevLink->next_ = nextLink;
1049     nextLink->prev_ = prevLink;
1050     nextLink->next_ = currLink;
1051     currLink->prev_ = nextLink;
1052     return true;
1053 }
1054 
1055 template<typename Key, typename Val>
MoveToHead(LinkNode<Key,Val> * & pnode)1056 void HashList<Key, Val>::MoveToHead(LinkNode<Key, Val> *&pnode)
1057 {
1058     if (pnode->link_.prev_ and pnode->link_.next_) {
1059         Link* prev = pnode->link_.prev_;
1060         Link* next = pnode->link_.next_;
1061         prev->next_ = next;
1062         next->prev_ = prev;
1063     }
1064     pnode->link_.next_ = dataHead_.next_;
1065     dataHead_.next_->prev_ = &pnode->link_;
1066     dataHead_.next_ = &pnode->link_;
1067     pnode->link_.prev_ = &dataHead_;
1068 }
1069 
1070 template<typename Key, typename Val>
MoveToTail(LinkNode<Key,Val> * & pnode)1071 void HashList<Key, Val>::MoveToTail(LinkNode<Key, Val> *&pnode)
1072 {
1073     if (pnode->link_.prev_ and pnode->link_.next_) {
1074         Link* prev = pnode->link_.prev_;
1075         Link* next = pnode->link_.next_;
1076         prev->next_ = next;
1077         next->prev_ = prev;
1078     }
1079     pnode->link_.prev_ = dataHead_.prev_;
1080     dataHead_.prev_->next_ = &pnode->link_;
1081     pnode->link_.next_ = &dataHead_;
1082     dataHead_.prev_ = &pnode->link_;
1083 }
1084 
1085 template<typename Key, typename Val>
1086 auto HashList<Key, Val>::AllocateNode(const Key &key)
1087 ->LinkNode<Key, Val> *
1088 {
1089     if (IsFull()) {
1090         pop_back();
1091     }
1092     LinkNode<Key, Val> *pnode = LinkNode<Key, Val>::GetLinkNode(freeHead_.next_);
1093     freeHead_.next_ = freeHead_.next_->next_;
1094     pnode->link_.next_ = nullptr;
1095     pnode->link_.prev_ = nullptr;
1096     pnode->key_ = key;
1097     pnode->val_ = Val();
1098     return pnode;
1099 }
1100 
1101 template<typename Key, typename Val>
1102 auto HashList<Key, Val>::AllocateNode(const Key &key, const Val &val)
1103 ->LinkNode<Key, Val> *
1104 {
1105     if (IsFull()) {
1106         pop_back();
1107     }
1108     LinkNode<Key, Val> *pnode = LinkNode<Key, Val>::GetLinkNode(freeHead_.next_);
1109     freeHead_.next_ = freeHead_.next_->next_;
1110     pnode->link_.next_ = nullptr;
1111     pnode->link_.prev_ = nullptr;
1112     pnode->key_ = key;
1113     pnode->val_ = val;
1114     return pnode;
1115 }
1116 
1117 template<typename Key, typename Val>
1118 auto HashList<Key, Val>::AllocateNode(const Key &key, Val &&val)
1119 ->LinkNode<Key, Val> *
1120 {
1121     if (IsFull()) {
1122         pop_back();
1123     }
1124     LinkNode<Key, Val> *pnode = LinkNode<Key, Val>::GetLinkNode(freeHead_.next_);
1125     freeHead_.next_ = freeHead_.next_->next_;
1126     pnode->link_.next_ = nullptr;
1127     pnode->link_.prev_ = nullptr;
1128     pnode->key_ = key;
1129     pnode->val_ = std::move(val);
1130     return pnode;
1131 }
1132 
1133 template<typename Key, typename Val>
ReclaimNode(LinkNode<Key,Val> * & pnode)1134 void HashList<Key, Val>::ReclaimNode(LinkNode<Key, Val> *&pnode)
1135 {
1136     Link *prevLink = pnode->link_.prev_;
1137     Link *nextLink = pnode->link_.next_;
1138     prevLink->next_ = nextLink;
1139     nextLink->prev_ = prevLink;
1140     pnode->link_.prev_ = nullptr;
1141     pnode->link_.next_ = freeHead_.next_;
1142     freeHead_.next_ = &pnode->link_;
1143     return;
1144 }
1145 } // namespace HiPerf
1146 } // namespace Developtools
1147 } // namespace OHOS
1148 #endif // HIPERF_HASHLIST_H
1149