• 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     void clear();
204     Iterator erase(const Key &key);
205     Iterator erase(const Iterator pos);
206     Iterator erase(const Iterator first, const Iterator last);
207 
208 private:
209     void MoveToHead(LinkNode<Key, Val> *&pnode);
210     void MoveToTail(LinkNode<Key, Val> *&pnode);
211     bool MoveNode(const Iterator &pos, LinkNode<Key, Val> *&pnode);
212     LinkNode<Key, Val> *AllocateNode(const Key &key);
213     LinkNode<Key, Val> *AllocateNode(const Key &key, const Val &val);
214     LinkNode<Key, Val> *AllocateNode(const Key &key, Val &&val);
215     void ReclaimNode(LinkNode<Key, Val> *&pnode);
216 
217     std::size_t numItem_ {0};
218     LinkNode<Key, Val> *pData_ {nullptr};
219     Link dataHead_ {};
220     Link freeHead_ {};
221     std::unordered_map<Key, LinkNode<Key, Val> *> valueTab_ {};
222 };
223 
224 // implementation of template class LinkNode
225 template<typename Key, typename Val>
LinkNode(const Key & key)226 LinkNode<Key, Val>::LinkNode(const Key &key) : key_ {key} {}
227 
228 template<typename Key, typename Val>
LinkNode(const Key & key,const Val & val)229 LinkNode<Key, Val>::LinkNode(const Key &key, const Val &val) : key_ {key}, val_ {val} {}
230 
231 template<typename Key, typename Val>
LinkNode(const Key & key,Val && val)232 LinkNode<Key, Val>::LinkNode(const Key &key, Val &&val) : key_ {key}, val_ {std::move(val)} {}
233 
234 template<typename Key, typename Val>
LinkNode(const LinkNode & node)235 LinkNode<Key, Val>::LinkNode(const LinkNode& node)
236     :link_ {node.link_},
237     key_ {node.key_},
238     val_ {node.val_}
239 {}
240 
241 template<typename Key, typename Val>
LinkNode(LinkNode && node)242 LinkNode<Key, Val>::LinkNode(LinkNode&& node)
243     :link_ {std::move(node.link_)},
244     key_ {std::move(node.key_)},
245     val_ {std::move(node.val_)}
246 {}
247 
248 template<typename Key, typename Val>
249 auto LinkNode<Key, Val>::operator=(const LinkNode& node)
250 -> LinkNode<Key, Val>&
251 {
252     link_ = node.link_;
253     key_ = node.key_;
254     val_ = node.val_;
255 }
256 
257 template<typename Key, typename Val>
258 auto LinkNode<Key, Val>::operator=(LinkNode&& node)
259 -> LinkNode<Key, Val>&
260 {
261     link_ = std::move(node.link_);
262     key_ = std::move(node.key_);
263     val_ = std::move(node.val_);
264 }
265 
266 template<typename Key, typename Val>
267 auto LinkNode<Key, Val>::GetLinkNode(Val *pval)
268 -> LinkNode<Key, Val>*
269 {
270     if (pval) {
271         LinkNode<Key, Val> *pnode {nullptr};
272         Val* offset = &pnode->val_;
273         auto nodeAddr = reinterpret_cast<char*>(pval) - reinterpret_cast<char*>(offset);
274         return reinterpret_cast<LinkNode<Key, Val>*>(nodeAddr);
275     }
276     return nullptr;
277 }
278 
279 template<typename Key, typename Val>
280 auto LinkNode<Key, Val>::GetLinkNode(Link *plink)
281 -> LinkNode<Key, Val>*
282 {
283     if (plink) {
284         LinkNode<Key, Val> *pnode {nullptr};
285         Link* offset = &pnode->link_;
286         auto  nodeAddr = reinterpret_cast<char*>(plink) - reinterpret_cast<char*>(offset);
287         return reinterpret_cast<LinkNode<Key, Val>*>(nodeAddr);
288     }
289     return nullptr;
290 }
291 // end of LinkNode
292 
293 // implementation of template class Iterator
294 template<typename Key, typename Val>
Iterator(LinkNode<Key,Val> * pnode,HashList * phashList)295 HashList<Key, Val>::Iterator::Iterator(LinkNode<Key, Val> *pnode, HashList *phashList)
296     : pnode_ {pnode}, phashList_ {phashList}
297 {
298     if (phashList_ == nullptr) {
299         pnode_ = nullptr;
300     }
301 }
302 
303 template<typename Key, typename Val>
Iterator(const LinkNode<Key,Val> * pnode,const HashList * phashList)304 HashList<Key, Val>::Iterator::Iterator(const LinkNode<Key, Val> *pnode, const HashList *phashList)
305     : pnode_ {const_cast<LinkNode<Key, Val>*>(pnode)},
306       phashList_ {const_cast<HashList*>(phashList)}
307 {
308     if (phashList_ == nullptr) {
309         pnode_ = nullptr;
310     }
311 }
312 
313 template<typename Key, typename Val>
Iterator(const Iterator & itr)314 HashList<Key, Val>::Iterator::Iterator(const Iterator& itr)
315     : pnode_ {itr.pnode_}, phashList_ {itr.phashList_}
316 {}
317 
318 template<typename Key, typename Val>
Iterator(Iterator && itr)319 HashList<Key, Val>::Iterator::Iterator(Iterator&& itr)
320     : pnode_ {itr.pnode_}, phashList_ {itr.phashList_}
321 {
322     itr.pnode_ = nullptr;
323     itr.phashList_ = nullptr;
324 }
325 
326 template<typename Key, typename Val>
327 auto HashList<Key, Val>::Iterator::operator=(const Iterator& itr)
328 -> HashList<Key, Val>::Iterator&
329 {
330     Iterator temp {itr};
331     swap(temp);
332     return *this;
333 }
334 
335 template<typename Key, typename Val>
336 auto HashList<Key, Val>::Iterator::operator=(Iterator&& itr)
337 -> HashList<Key, Val>::Iterator&
338 {
339     Iterator temp {std::move(itr)};
340     swap(temp);
341     return *this;
342 }
343 
344 template<typename Key, typename Val>
345 auto HashList<Key, Val>::Iterator::operator++() noexcept
346 -> HashList<Key, Val>::Iterator &
347 {
348     if (pnode_ == nullptr or phashList_ == nullptr) {
349         phashList_ = nullptr;
350         return *this;
351     }
352     Link* plink = pnode_->link_.next_;
353     if (plink == &phashList_->dataHead_) {
354         pnode_ = nullptr;
355         return *this;
356     }
357     auto pnode = LinkNode<Key, Val>::GetLinkNode(plink);
358     pnode_ = pnode;
359     return *this;
360 }
361 
362 template<typename Key, typename Val>
363 auto HashList<Key, Val>::Iterator::operator++(int) noexcept
364 -> HashList<Key, Val>::Iterator
365 {
366     Iterator res {*this};
367     if (pnode_ == nullptr or phashList_ == nullptr) {
368         phashList_ = nullptr;
369         return res;
370     }
371     Link* plink = pnode_->link_.next_;
372     if (plink == &phashList_->dataHead_) {
373         pnode_ = nullptr;
374         return res;
375     }
376     auto pnode = LinkNode<Key, Val>::GetLinkNode(plink);
377     pnode_ = pnode;
378     return res;
379 }
380 
381 template<typename Key, typename Val>
382 auto HashList<Key, Val>::Iterator::operator--() noexcept
383 -> HashList<Key, Val>::Iterator &
384 {
385     if (phashList_ == nullptr) {
386         return *this;
387     }
388     Link* plink {nullptr};
389     if (pnode_ == nullptr) {
390         plink = phashList_->dataHead_.prev_;
391     } else {
392         plink = pnode_->link_.prev_;
393     }
394     if (plink == &phashList_->dataHead_) {
395         pnode_ = nullptr;
396         phashList_ = nullptr;
397         return *this;
398     }
399     pnode_ = LinkNode<Key, Val>::GetLinkNode(plink);
400     return *this;
401 }
402 
403 template<typename Key, typename Val>
404 auto HashList<Key, Val>::Iterator::operator--(int) noexcept
405 -> HashList<Key, Val>::Iterator
406 {
407     Iterator res {*this};
408     if (phashList_ == nullptr) {
409         return res;
410     }
411     Link* plink {nullptr};
412     if (pnode_ == nullptr) {
413         plink = phashList_->dataHead_.prev_;
414     } else {
415         plink = pnode_->link_.prev_;
416     }
417     if (plink == &phashList_->dataHead_) {
418         pnode_ = nullptr;
419         phashList_ = nullptr;
420         return res;
421     }
422     pnode_ = LinkNode<Key, Val>::GetLinkNode(plink);
423     return res;
424 }
425 
426 template<typename Key, typename Val>
427 bool HashList<Key, Val>::Iterator::operator<(const HashList<Key, Val>::Iterator &itr) const noexcept
428 {
429     if (IsDangled() or itr.IsDangled()) {
430         return false;
431     }
432     if (phashList_ != itr.phashList_) {
433         return false;
434     }
435     Iterator tempItr {*this};
436     if (tempItr == itr) {
437         return false;
438     }
439     while (!tempItr.IsDangled()) {
440         tempItr++;
441         if (tempItr == itr) {
442             return true;
443         }
444     }
445     return false;
446 }
447 
448 template<typename Key, typename Val>
449 bool HashList<Key, Val>::Iterator::operator==(const HashList<Key, Val>::Iterator &itr) const noexcept
450 {
451     if (IsDangled() or itr.IsDangled()) {
452         return false;
453     }
454     if (phashList_ != itr.phashList_) {
455         return false;
456     }
457     return pnode_ == itr.pnode_;
458 }
459 
460 template<typename Key, typename Val>
461 Val& HashList<Key, Val>::Iterator::operator*()
462 {
463     return pnode_->val_;
464 }
465 
466 template<typename Key, typename Val>
467 const Val& HashList<Key, Val>::Iterator::operator*() const
468 {
469     return pnode_->val_;
470 }
471 
472 template<typename Key, typename Val>
473 Val* HashList<Key, Val>::Iterator::operator->()
474 {
475     return &pnode_->val_;
476 }
477 
478 template<typename Key, typename Val>
479 const Val* HashList<Key, Val>::Iterator::operator->() const
480 {
481     return &pnode_->val_;
482 }
483 
484 template<typename Key, typename Val>
swap(HashList<Key,Val>::Iterator & other)485 void HashList<Key, Val>::Iterator::swap(HashList<Key, Val>::Iterator& other)
486 {
487     using std::swap;
488     swap(pnode_, other.pnode_);
489     swap(phashList_, other.phashList_);
490 }
491 // end of Iterator
492 
493 // Implementation of ReverseIterator
494 template<typename Key, typename Val>
ReverseIterator(LinkNode<Key,Val> * pnode,HashList * phashList)495 HashList<Key, Val>::ReverseIterator::ReverseIterator(LinkNode<Key, Val> *pnode, HashList *phashList)
496     : pnode_ {pnode}, phashList_ {phashList}
497 {
498     if (phashList_ == nullptr) {
499         pnode_ = nullptr;
500     }
501 }
502 
503 template<typename Key, typename Val>
ReverseIterator(const LinkNode<Key,Val> * pnode,const HashList * phashList)504 HashList<Key, Val>::ReverseIterator::ReverseIterator(const LinkNode<Key, Val> *pnode, const HashList *phashList)
505     : pnode_ {const_cast<LinkNode<Key, Val> *>(pnode)},
506     phashList_ {const_cast<HashList *>(phashList)}
507 {
508     if (phashList_ == nullptr) {
509         pnode_ = nullptr;
510     }
511 }
512 
513 template<typename Key, typename Val>
ReverseIterator(const ReverseIterator & itr)514 HashList<Key, Val>::ReverseIterator::ReverseIterator(const ReverseIterator &itr)
515     : pnode_ {itr.pnode_}, phashList_ {itr.phashList_}
516 {}
517 
518 template<typename Key, typename Val>
ReverseIterator(ReverseIterator && itr)519 HashList<Key, Val>::ReverseIterator::ReverseIterator(ReverseIterator &&itr)
520     : pnode_ {itr.pnode_}, phashList_ {itr.phashList_}
521 {
522     itr.pnode_ = nullptr;
523     itr.phashList_ = nullptr;
524 }
525 
526 template<typename Key, typename Val>
527 auto HashList<Key, Val>::ReverseIterator::operator=(const ReverseIterator& itr)
528 -> HashList<Key, Val>::ReverseIterator&
529 {
530     ReverseIterator temp {itr};
531     swap(temp);
532     return *this;
533 }
534 
535 template<typename Key, typename Val>
536 auto HashList<Key, Val>::ReverseIterator::operator=(ReverseIterator&& itr)
537 -> HashList<Key, Val>::ReverseIterator&
538 {
539     ReverseIterator temp {std::move(itr)};
540     swap(temp);
541     return *this;
542 }
543 
544 template<typename Key, typename Val>
545 auto HashList<Key, Val>::ReverseIterator::operator++() noexcept
546 -> HashList<Key, Val>::ReverseIterator &
547 {
548     if (pnode_ == nullptr or phashList_ == nullptr) {
549         phashList_ = nullptr;
550         return *this;
551     }
552     Link* plink = &pnode_->link_;
553     plink = plink->prev_;
554     if (plink == &phashList_->dataHead_) {
555         pnode_ = nullptr;
556         return *this;
557     }
558     pnode_ = LinkNode<Key, Val>::GetLinkNode(plink);
559     return *this;
560 }
561 
562 template<typename Key, typename Val>
563 auto HashList<Key, Val>::ReverseIterator::operator++(int) noexcept
564 -> HashList<Key, Val>::ReverseIterator
565 {
566     ReverseIterator res {*this};
567     if (pnode_ == nullptr or phashList_ == nullptr) {
568         phashList_ = nullptr;
569         return res;
570     }
571     Link* plink = &pnode_->link_;
572     plink = plink->prev_;
573     if (plink == &phashList_->dataHead_) {
574         pnode_ = nullptr;
575         return res;
576     }
577     pnode_ = LinkNode<Key, Val>::GetLinkNode(plink);
578     return res;
579 }
580 
581 template<typename Key, typename Val>
582 auto HashList<Key, Val>::ReverseIterator::operator--() noexcept
583 -> HashList<Key, Val>::ReverseIterator &
584 {
585     if (phashList_ == nullptr) {
586         return *this;
587     }
588     Link* plink {nullptr};
589     if (pnode_ == nullptr) {
590         plink = phashList_->dataHead_.next_;
591     } else {
592         plink = pnode_->link_.next_;
593     }
594     if (plink == &phashList_->dataHead_) {
595         pnode_ = nullptr;
596         phashList_ = nullptr;
597         return *this;
598     }
599     pnode_ = LinkNode<Key, Val>::GetLinkNode(plink);
600     return *this;
601 }
602 
603 template<typename Key, typename Val>
604 auto HashList<Key, Val>::ReverseIterator::operator--(int) noexcept
605 -> HashList<Key, Val>::ReverseIterator
606 {
607     ReverseIterator res {*this};
608     if (phashList_ == nullptr) {
609         return res;
610     }
611     Link* plink {nullptr};
612     if (pnode_ == nullptr) {
613         plink = phashList_->dataHead_.next_;
614     } else {
615         plink = pnode_->link_.next_;
616     }
617     if (plink == &phashList_->dataHead_) {
618         pnode_ = nullptr;
619         phashList_ = nullptr;
620         return res;
621     }
622     pnode_ = LinkNode<Key, Val>::GetLinkNode(plink);
623     return res;
624 }
625 
626 template<typename Key, typename Val>
627 bool HashList<Key, Val>::ReverseIterator::operator<(
628     const HashList<Key, Val>::ReverseIterator &itr) const noexcept
629 {
630     if (IsDangled() or itr.IsDangled()) {
631         return false;
632     }
633     if (phashList_ != itr.phashList_) {
634         return false;
635     }
636     HashList<Key, Val>::ReverseIterator tempItr {*this};
637     if (tempItr == itr) {
638         return false;
639     }
640     while (!tempItr.IsDangled()) {
641         tempItr++;
642         if (tempItr == itr) {
643             return true;
644         }
645     }
646     return false;
647 }
648 
649 template<typename Key, typename Val>
650 bool HashList<Key, Val>::ReverseIterator::operator==(
651     const HashList<Key, Val>::ReverseIterator &itr) const noexcept
652 {
653     if (IsDangled() or itr.IsDangled()) {
654         return false;
655     }
656     if (phashList_ != itr.phashList_) {
657         return false;
658     }
659     return pnode_ == itr.pnode_;
660 }
661 
662 template<typename Key, typename Val>
663 Val& HashList<Key, Val>::ReverseIterator::operator*()
664 {
665     return pnode_->val_;
666 }
667 
668 template<typename Key, typename Val>
669 const Val& HashList<Key, Val>::ReverseIterator::operator*() const
670 {
671     return pnode_->val_;
672 }
673 
674 template<typename Key, typename Val>
675 Val* HashList<Key, Val>::ReverseIterator::operator->()
676 {
677     return &pnode_->val_;
678 }
679 
680 template<typename Key, typename Val>
681 const Val* HashList<Key, Val>::ReverseIterator::operator->() const
682 {
683     return &pnode_->val_;
684 }
685 
686 template<typename Key, typename Val>
swap(HashList<Key,Val>::ReverseIterator & other)687 void HashList<Key, Val>::ReverseIterator::swap(HashList<Key, Val>::ReverseIterator& other)
688 {
689     using std::swap;
690     swap(pnode_, other.pnode_);
691     swap(phashList_, other.phashList_);
692 }
693 // end of ReverseIterator
694 
695 // implementation of template class HashList
696 template<typename Key, typename Val>
HashList(const std::size_t numItem)697 HashList<Key, Val>::HashList(const std::size_t numItem) : numItem_ {numItem}
698 {
699     dataHead_.next_ = &dataHead_;
700     dataHead_.prev_ = &dataHead_;
701     if (numItem_) {
702         valueTab_.reserve(numItem_);
703         pData_ = new(std::nothrow) LinkNode<Key, Val>[numItem_];
704         if (pData_) {
705             freeHead_.next_ = &(pData_[0].link_);
706             std::size_t last {numItem_ - 1};
707             for (std::size_t index = 0; index < last;) {
708                 LinkNode<Key, Val> &curNnode = pData_[index];
709                 curNnode.link_.next_ = &(pData_[++index].link_);
710             }
711             pData_[last].link_.next_ = &freeHead_;
712         } else {
713             numItem_ = 0;
714             freeHead_.next_ = &freeHead_;
715             freeHead_.prev_ = &freeHead_;
716         }
717     }
718 }
719 
720 template<typename Key, typename Val>
reserve(const std::size_t numItem)721 int HashList<Key, Val>::reserve(const std::size_t numItem)
722 {
723     if (numItem_ != 0) {
724         return -1;
725     }
726     if (numItem) {
727         numItem_ = numItem;
728         valueTab_.reserve(numItem_);
729         pData_ = new(std::nothrow) LinkNode<Key, Val>[numItem_];
730         dataHead_.next_ = &dataHead_;
731         dataHead_.prev_ = &dataHead_;
732         if (pData_) {
733             freeHead_.next_ = &(pData_[0].link_);
734             std::size_t last {numItem_ - 1};
735             for (std::size_t index = 0; index < last;) {
736                 LinkNode<Key, Val> &curNnode = pData_[index];
737                 curNnode.link_.next_ = &(pData_[++index].link_);
738             }
739             pData_[last].link_.next_ = &freeHead_;
740         } else {
741             numItem_ = 0;
742             freeHead_.next_ = &freeHead_;
743             freeHead_.prev_ = &freeHead_;
744         }
745     }
746     return numItem_;
747 }
748 
749 template<typename Key, typename Val>
~HashList()750 HashList<Key, Val>::~HashList()
751 {
752     if (pData_) {
753         delete[] pData_;
754         pData_ = nullptr;
755     }
756     valueTab_.clear();
757     dataHead_.next_ = &dataHead_;
758     dataHead_.prev_ = &dataHead_;
759     freeHead_.next_ = nullptr;
760     freeHead_.prev_ = nullptr;
761     numItem_ = 0;
762 }
763 
764 template<typename Key, typename Val>
HashList(HashList<Key,Val> && source)765 HashList<Key, Val>::HashList(HashList<Key, Val> &&source)
766     : numItem_ {source.numItem_},
767     pData_ {source.pData_},
768     dataHead_ {std::move(source.dataHead_)},
769     freeHead_ {std::move(source.freeHead_)},
770     valueTab_ {std::move(source.valueTab_)}
771 {
772     source.pData_ = nullptr;
773 }
774 
775 template<typename Key, typename Val>
776 auto HashList<Key, Val>::operator=(HashList &&source)
777 -> HashList<Key, Val>&
778 {
779     if (this == &source) {
780         return *this;
781     }
782     if (pData_) {
783         delete[] pData_;
784         pData_ = nullptr;
785     }
786     numItem_ = source.numItem_;
787     pData_ = source.pData_;
788     source.pData_ = nullptr;
789     dataHead_ = std::move(source.dataHead_);
790     freeHead_ = std::move(source.freeHead_);
791     valueTab_ = std::move(source.valueTab_);
792     return *this;
793 }
794 
795 template<typename Key, typename Val>
796 auto HashList<Key, Val>::begin()
797 -> HashList<Key, Val>::Iterator
798 {
799     if (empty()) {
800         return end();
801     }
802     return Iterator(LinkNode<Key, Val>::GetLinkNode(dataHead_.next_), this);
803 }
804 
805 template<typename Key, typename Val>
806 auto HashList<Key, Val>::cbegin() const
807 -> const HashList<Key, Val>::Iterator
808 {
809     if (empty()) {
810         return cend();
811     }
812     return Iterator(LinkNode<Key, Val>::GetLinkNode(dataHead_.next_), this);
813 }
814 
815 template<typename Key, typename Val>
816 auto HashList<Key, Val>::end()
817 -> HashList<Key, Val>::Iterator
818 {
819     return Iterator(nullptr, this);
820 }
821 
822 template<typename Key, typename Val>
823 auto HashList<Key, Val>::cend() const
824 -> const HashList<Key, Val>::Iterator
825 {
826     return Iterator(nullptr, this);
827 }
828 
829 template<typename Key, typename Val>
830 auto HashList<Key, Val>::rbegin()
831 -> HashList<Key, Val>::ReverseIterator
832 {
833     if (empty()) {
834         return rend();
835     }
836     return ReverseIterator(LinkNode<Key, Val>::GetLinkNode(dataHead_.prev_), this);
837 }
838 
839 template<typename Key, typename Val>
840 auto HashList<Key, Val>::crbegin() const
841 -> const HashList<Key, Val>::ReverseIterator
842 {
843     if (empty()) {
844         return crend();
845     }
846     return ReverseIterator(LinkNode<Key, Val>::GetLinkNode(dataHead_.prev_), this);
847 }
848 
849 template<typename Key, typename Val>
850 auto HashList<Key, Val>::rend()
851 -> HashList<Key, Val>::ReverseIterator
852 {
853     return ReverseIterator(nullptr, this);
854 }
855 
856 template<typename Key, typename Val>
857 auto HashList<Key, Val>::crend() const
858 -> const HashList<Key, Val>::ReverseIterator
859 {
860     return ReverseIterator(nullptr, this);
861 }
862 
863 template<typename Key, typename Val>
front()864 Val& HashList<Key, Val>::front()
865 {
866     LinkNode<Key, Val> *pnode = LinkNode<Key, Val>::GetLinkNode(dataHead_.next_);
867     return pnode->val_;
868 }
869 
870 template<typename Key, typename Val>
front()871 const Val& HashList<Key, Val>::front() const
872 {
873     return front();
874 }
875 
876 template<typename Key, typename Val>
back(bool prepend)877 Val& HashList<Key, Val>::back(bool prepend)
878 {
879     auto pnode = LinkNode<Key, Val>::GetLinkNode(dataHead_.prev_);
880     if (prepend) {
881         MoveToHead(pnode);
882     }
883     return pnode->val_;
884 }
885 
886 template<typename Key, typename Val>
887 Val& HashList<Key, Val>::operator[](const Key &key)
888 {
889     LinkNode<Key, Val> *pnode {nullptr};
890     if (valueTab_.find(key) == valueTab_.end()) {
891         pnode = AllocateNode(key);
892         valueTab_[key] = pnode;
893     } else {
894         pnode = valueTab_[key];
895     }
896     if (pnode == nullptr) {
897         static Val val = Val();
898         return val;
899     } else {
900         MoveToHead(pnode);
901     }
902     return pnode->val_;
903 }
904 
905 template<typename Key, typename Val>
906 auto HashList<Key, Val>::find(const Key &key)
907 -> HashList<Key, Val>::Iterator
908 {
909     const auto &itr = valueTab_.find(key);
910     if (itr == valueTab_.end()) {
911         return end();
912     }
913     return Iterator(itr->second, this);
914 }
915 
916 template<typename Key, typename Val>
push_front(const Key & key,const Val & val)917 void HashList<Key, Val>::push_front(const Key& key, const Val& val)
918 {
919     if (valueTab_.find(key) == valueTab_.end()) {
920         LinkNode<Key, Val>* pnode = AllocateNode(key, val);
921         MoveToHead(pnode);
922         valueTab_[pnode->key_] = pnode;
923     } else {
924         MoveToHead(valueTab_[key]);
925         this->operator[](key) =  val;
926     }
927 }
928 
929 template<typename Key, typename Val>
push_front(const Key & key,Val && val)930 void HashList<Key, Val>::push_front(const Key& key, Val&& val)
931 {
932     if (valueTab_.find(key) == valueTab_.end()) {
933         LinkNode<Key, Val>* pnode = AllocateNode(key, std::move(val));
934         MoveToHead(pnode);
935         valueTab_[pnode->key_] = pnode;
936     } else {
937         MoveToHead(valueTab_[key]);
938         this->operator[](key) =  val;
939     }
940 }
941 
942 template<typename Key, typename Val>
push_back(const Key & key,const Val & val)943 void HashList<Key, Val>::push_back(const Key& key, const Val& val)
944 {
945     if (valueTab_.find(key) == valueTab_.end()) {
946         LinkNode<Key, Val>* pnode = AllocateNode(key, val);
947         MoveToTail(pnode);
948         valueTab_[pnode->key_] = pnode;
949     } else {
950         MoveToTail(valueTab_[key]);
951         this->operator[](key) =  val;
952     }
953 }
954 
955 template<typename Key, typename Val>
push_back(const Key & key,Val && val)956 void HashList<Key, Val>::push_back(const Key& key, Val&& val)
957 {
958     if (valueTab_.find(key) == valueTab_.end()) {
959         LinkNode<Key, Val>* pnode = AllocateNode(key, std::move(val));
960         MoveToTail(pnode);
961         valueTab_[pnode->key_] = pnode;
962     } else {
963         MoveToTail(valueTab_[key]);
964         this->operator[](key) =  val;
965     }
966 }
967 
968 template<typename Key, typename Val>
pop_front()969 void HashList<Key, Val>::pop_front()
970 {
971     if (empty()) {
972         return;
973     }
974     LinkNode<Key, Val>* pnode = LinkNode<Key, Val>::GetLinkNode(dataHead_.next_);
975     valueTab_.erase(pnode->key_);
976     ReclaimNode(pnode);
977 }
978 
979 template<typename Key, typename Val>
pop_back()980 void HashList<Key, Val>::pop_back()
981 {
982     if (empty()) {
983         return;
984     }
985     LinkNode<Key, Val>* pnode = LinkNode<Key, Val>::GetLinkNode(dataHead_.prev_);
986     if (pnode != nullptr) {
987         valueTab_.erase(pnode->key_);
988         ReclaimNode(pnode);
989     }
990 }
991 
992 template<typename Key, typename Val>
clear()993 void HashList<Key, Val>::clear()
994 {
995     Iterator curPos = begin();
996     LinkNode<Key, Val> *curNode = curPos.GetNode();
997     while (curNode != nullptr) {
998         curPos = erase(curPos);
999         curNode = curPos.GetNode();
1000     }
1001 }
1002 
1003 template<typename Key, typename Val>
1004 auto HashList<Key, Val>::erase(const Key& key)
1005 -> HashList<Key, Val>::Iterator
1006 {
1007     if (valueTab_.find(key) == valueTab_.end()) {
1008         return end();
1009     }
1010     LinkNode<Key, Val> *pnode = valueTab_[key];
1011     valueTab_.erase(key);
1012     Link* plink = pnode->link_.next_;
1013     Iterator tempItr {LinkNode<Key, Val>::GetLinkNode(plink), this};
1014     ReclaimNode(pnode);
1015     return tempItr;
1016 }
1017 
1018 template<typename Key, typename Val>
1019 auto HashList<Key, Val>::erase(const Iterator pos)
1020 -> HashList<Key, Val>::Iterator
1021 {
1022     // assume pos is valid, otherwise the result is undefined
1023     Iterator tempItr {pos};
1024     ++tempItr;
1025     LinkNode<Key, Val> *pnode = pos.GetNode();
1026     valueTab_.erase(pnode->key_);
1027     ReclaimNode(pnode);
1028     return tempItr;
1029 }
1030 
1031 template<typename Key, typename Val>
1032 auto HashList<Key, Val>::erase(const Iterator first, const Iterator last)
1033 -> HashList<Key, Val>::Iterator
1034 {
1035     // assume pos is valid, otherwise the result is undefined
1036     if (first <= last) {
1037         Iterator curPos {first};
1038         while (curPos < last) {
1039             curPos = erase(curPos);
1040         }
1041         return last;
1042     }
1043     return end();
1044 }
1045 
1046 template<typename Key, typename Val>
MoveNode(const Iterator & pos,LinkNode<Key,Val> * & pnode)1047 bool HashList<Key, Val>::MoveNode(const Iterator& pos, LinkNode<Key, Val> *&pnode)
1048 {
1049     LinkNode<Key, Val> *curNode = pos.GetNode();
1050     if (curNode == pnode) {
1051         return true;
1052     }
1053     if (pnode->link_.next_ == &curNode->link_) {
1054         return true;
1055     }
1056     Link* prevLink = pnode->link_.prev_;
1057     Link* nextLink = pnode->link_.next_;
1058     if (prevLink and nextLink) {
1059         prevLink->next_ = nextLink;
1060         nextLink->prev_ = prevLink;
1061     }
1062     Link *currLink = &curNode->link_;
1063     prevLink = currLink->prev_;
1064     nextLink = &pnode->link_;
1065     prevLink->next_ = nextLink;
1066     nextLink->prev_ = prevLink;
1067     nextLink->next_ = currLink;
1068     currLink->prev_ = nextLink;
1069     return true;
1070 }
1071 
1072 template<typename Key, typename Val>
MoveToHead(LinkNode<Key,Val> * & pnode)1073 void HashList<Key, Val>::MoveToHead(LinkNode<Key, Val> *&pnode)
1074 {
1075     if (pnode->link_.prev_ and pnode->link_.next_) {
1076         Link* prev = pnode->link_.prev_;
1077         Link* next = pnode->link_.next_;
1078         prev->next_ = next;
1079         next->prev_ = prev;
1080     }
1081     pnode->link_.next_ = dataHead_.next_;
1082     dataHead_.next_->prev_ = &pnode->link_;
1083     dataHead_.next_ = &pnode->link_;
1084     pnode->link_.prev_ = &dataHead_;
1085 }
1086 
1087 template<typename Key, typename Val>
MoveToTail(LinkNode<Key,Val> * & pnode)1088 void HashList<Key, Val>::MoveToTail(LinkNode<Key, Val> *&pnode)
1089 {
1090     if (pnode->link_.prev_ and pnode->link_.next_) {
1091         Link* prev = pnode->link_.prev_;
1092         Link* next = pnode->link_.next_;
1093         prev->next_ = next;
1094         next->prev_ = prev;
1095     }
1096     pnode->link_.prev_ = dataHead_.prev_;
1097     dataHead_.prev_->next_ = &pnode->link_;
1098     pnode->link_.next_ = &dataHead_;
1099     dataHead_.prev_ = &pnode->link_;
1100 }
1101 
1102 template<typename Key, typename Val>
1103 auto HashList<Key, Val>::AllocateNode(const Key &key)
1104 ->LinkNode<Key, Val> *
1105 {
1106     if (IsFull()) {
1107         pop_back();
1108     }
1109     LinkNode<Key, Val> *pnode = LinkNode<Key, Val>::GetLinkNode(freeHead_.next_);
1110     freeHead_.next_ = freeHead_.next_->next_;
1111     if (pnode != nullptr) {
1112         pnode->link_.next_ = nullptr;
1113         pnode->link_.prev_ = nullptr;
1114         pnode->key_ = key;
1115         pnode->val_ = Val();
1116     }
1117     return pnode;
1118 }
1119 
1120 template<typename Key, typename Val>
1121 auto HashList<Key, Val>::AllocateNode(const Key &key, const Val &val)
1122 ->LinkNode<Key, Val> *
1123 {
1124     if (IsFull()) {
1125         pop_back();
1126     }
1127     LinkNode<Key, Val> *pnode = LinkNode<Key, Val>::GetLinkNode(freeHead_.next_);
1128     freeHead_.next_ = freeHead_.next_->next_;
1129     pnode->link_.next_ = nullptr;
1130     pnode->link_.prev_ = nullptr;
1131     pnode->key_ = key;
1132     pnode->val_ = val;
1133     return pnode;
1134 }
1135 
1136 template<typename Key, typename Val>
1137 auto HashList<Key, Val>::AllocateNode(const Key &key, Val &&val)
1138 ->LinkNode<Key, Val> *
1139 {
1140     if (IsFull()) {
1141         pop_back();
1142     }
1143     LinkNode<Key, Val> *pnode = LinkNode<Key, Val>::GetLinkNode(freeHead_.next_);
1144     freeHead_.next_ = freeHead_.next_->next_;
1145     pnode->link_.next_ = nullptr;
1146     pnode->link_.prev_ = nullptr;
1147     pnode->key_ = key;
1148     pnode->val_ = std::move(val);
1149     return pnode;
1150 }
1151 
1152 template<typename Key, typename Val>
ReclaimNode(LinkNode<Key,Val> * & pnode)1153 void HashList<Key, Val>::ReclaimNode(LinkNode<Key, Val> *&pnode)
1154 {
1155     Link *prevLink = pnode->link_.prev_;
1156     Link *nextLink = pnode->link_.next_;
1157     prevLink->next_ = nextLink;
1158     nextLink->prev_ = prevLink;
1159     pnode->link_.prev_ = nullptr;
1160     pnode->link_.next_ = freeHead_.next_;
1161     freeHead_.next_ = &pnode->link_;
1162     return;
1163 }
1164 } // namespace HiPerf
1165 } // namespace Developtools
1166 } // namespace OHOS
1167 #endif // HIPERF_HASHLIST_H
1168