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