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