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 == nullptr) {
896 static Val val = Val();
897 return val;
898 } else {
899 MoveToHead(pnode);
900 }
901 return pnode->val_;
902 }
903
904 template<typename Key, typename Val>
905 auto 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
915 template<typename Key, typename Val>
push_front(const Key & key,const Val & val)916 void 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
928 template<typename Key, typename Val>
push_front(const Key & key,Val && val)929 void 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
941 template<typename Key, typename Val>
push_back(const Key & key,const Val & val)942 void 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
954 template<typename Key, typename Val>
push_back(const Key & key,Val && val)955 void 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
967 template<typename Key, typename Val>
pop_front()968 void 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
978 template<typename Key, typename Val>
pop_back()979 void 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
991 template<typename Key, typename Val>
992 auto 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
1006 template<typename Key, typename Val>
1007 auto 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
1019 template<typename Key, typename Val>
1020 auto 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
1034 template<typename Key, typename Val>
MoveNode(const Iterator & pos,LinkNode<Key,Val> * & pnode)1035 bool 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
1060 template<typename Key, typename Val>
MoveToHead(LinkNode<Key,Val> * & pnode)1061 void 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
1075 template<typename Key, typename Val>
MoveToTail(LinkNode<Key,Val> * & pnode)1076 void 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
1090 template<typename Key, typename Val>
1091 auto 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
1108 template<typename Key, typename Val>
1109 auto 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
1124 template<typename Key, typename Val>
1125 auto 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
1140 template<typename Key, typename Val>
ReclaimNode(LinkNode<Key,Val> * & pnode)1141 void 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