mirror of
https://gitee.com/openharmony/developtools_hiperf
synced 2024-11-23 07:29:42 +00:00
57cd4808a5
Signed-off-by:wenlong12 <wenlong12@huawei.com> Signed-off-by: wenlong12 <wenlong12@huawei.com>
1156 lines
31 KiB
C++
1156 lines
31 KiB
C++
/*
|
|
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef HIPERF_HASHLIST_H
|
|
#define HIPERF_HASHLIST_H
|
|
|
|
#include <unordered_map>
|
|
|
|
namespace OHOS {
|
|
namespace Developtools {
|
|
namespace HiPerf {
|
|
class Link {
|
|
public:
|
|
Link() = default;
|
|
~Link() = default;
|
|
Link(const Link &link) : prev_ {link.prev_}, next_ {link.next_} {}
|
|
Link(Link &&link) : prev_ {link.prev_}, next_ {link.next_}
|
|
{
|
|
link.prev_ = nullptr;
|
|
link.next_ = nullptr;
|
|
}
|
|
Link &operator=(const Link &link)
|
|
{
|
|
prev_ = link.prev_;
|
|
next_ = link.next_;
|
|
return *this;
|
|
}
|
|
Link &operator=(Link &&link)
|
|
{
|
|
prev_ = link.prev_;
|
|
link.prev_ = nullptr;
|
|
next_ = link.next_;
|
|
link.next_ = nullptr;
|
|
return *this;
|
|
}
|
|
Link *prev_ {nullptr};
|
|
Link *next_ {nullptr};
|
|
};
|
|
|
|
template<typename Key, typename Val>
|
|
class LinkNode {
|
|
public:
|
|
Link link_ {};
|
|
Key key_ {};
|
|
Val val_ {};
|
|
|
|
explicit LinkNode() = default;
|
|
~LinkNode() = default;
|
|
explicit LinkNode(const Key &key);
|
|
explicit LinkNode(const Key &key, const Val &val);
|
|
explicit LinkNode(const Key &key, Val &&val);
|
|
LinkNode(const LinkNode &node);
|
|
LinkNode(LinkNode &&node);
|
|
LinkNode &operator=(const LinkNode &node);
|
|
LinkNode &operator=(LinkNode &&node);
|
|
static LinkNode<Key, Val> *GetLinkNode(Val *pval);
|
|
static LinkNode<Key, Val> *GetLinkNode(Link *plink);
|
|
};
|
|
|
|
template<typename Key, typename Val>
|
|
class HashList {
|
|
public:
|
|
class Iterator {
|
|
public:
|
|
Iterator() = default;
|
|
~Iterator() = default;
|
|
explicit Iterator(LinkNode<Key, Val> *pnode, HashList *phashList);
|
|
explicit Iterator(const LinkNode<Key, Val> *pnode, const HashList *phashList);
|
|
Iterator(const Iterator &itr);
|
|
Iterator(Iterator &&itr);
|
|
Iterator &operator=(const Iterator &itr);
|
|
Iterator &operator=(Iterator &&itr);
|
|
Iterator &operator++() noexcept;
|
|
Iterator operator++(int) noexcept;
|
|
Iterator &operator--() noexcept;
|
|
Iterator operator--(int) noexcept;
|
|
bool operator<(const Iterator &itr) const noexcept;
|
|
bool operator==(const Iterator &itr) const noexcept;
|
|
Val &operator*();
|
|
const Val &operator*() const;
|
|
Val *operator->();
|
|
const Val *operator->() const;
|
|
void swap(HashList<Key, Val>::Iterator &other);
|
|
LinkNode<Key, Val> *GetNode() const
|
|
{
|
|
return pnode_;
|
|
}
|
|
|
|
private:
|
|
bool IsDangled() const noexcept
|
|
{
|
|
return phashList_ == nullptr;
|
|
}
|
|
|
|
LinkNode<Key, Val> *pnode_ {nullptr};
|
|
HashList *phashList_ {nullptr};
|
|
};
|
|
|
|
class ReverseIterator {
|
|
public:
|
|
ReverseIterator() = default;
|
|
~ReverseIterator() = default;
|
|
explicit ReverseIterator(LinkNode<Key, Val> *pnode, HashList *phashList);
|
|
explicit ReverseIterator(const LinkNode<Key, Val> *pnode, const HashList *phashList);
|
|
ReverseIterator(const ReverseIterator &itr);
|
|
ReverseIterator(ReverseIterator &&itr);
|
|
ReverseIterator &operator=(const ReverseIterator &itr);
|
|
ReverseIterator &operator=(ReverseIterator &&itr);
|
|
ReverseIterator &operator++() noexcept;
|
|
ReverseIterator operator++(int) noexcept;
|
|
ReverseIterator &operator--() noexcept;
|
|
ReverseIterator operator--(int) noexcept;
|
|
bool operator<(const ReverseIterator &itr) const noexcept;
|
|
bool operator==(const ReverseIterator &itr) const noexcept;
|
|
Val &operator*();
|
|
const Val &operator*() const;
|
|
Val *operator->();
|
|
const Val *operator->() const;
|
|
void swap(HashList<Key, Val>::ReverseIterator &other);
|
|
|
|
LinkNode<Key, Val> *GetNode()
|
|
{
|
|
return pnode_;
|
|
}
|
|
|
|
private:
|
|
bool IsDangled() const noexcept
|
|
{
|
|
return phashList_ == nullptr;
|
|
}
|
|
|
|
LinkNode<Key, Val> *pnode_ {nullptr};
|
|
HashList *phashList_ {nullptr};
|
|
};
|
|
|
|
public:
|
|
explicit HashList(const std::size_t numItem = 0);
|
|
~HashList();
|
|
|
|
HashList(const HashList &source) = delete;
|
|
HashList &operator=(const HashList &source) = delete;
|
|
HashList(HashList &&source);
|
|
HashList &operator=(HashList &&source);
|
|
|
|
// capacity
|
|
inline std::size_t size() const
|
|
{
|
|
return valueTab_.size();
|
|
}
|
|
inline bool empty() const
|
|
{
|
|
return (dataHead_.next_ == &dataHead_) and (dataHead_.prev_ == &dataHead_);
|
|
}
|
|
inline std::size_t capacity() const
|
|
{
|
|
return numItem_;
|
|
}
|
|
inline bool IsFull() const
|
|
{
|
|
return freeHead_.next_ == &freeHead_;
|
|
}
|
|
inline std::size_t count(const Key &key) const
|
|
{
|
|
return valueTab_.count(key);
|
|
}
|
|
|
|
int reserve(const std::size_t numItem);
|
|
// iterators
|
|
Iterator begin();
|
|
const Iterator cbegin() const;
|
|
Iterator end();
|
|
const Iterator cend() const;
|
|
ReverseIterator rbegin();
|
|
const ReverseIterator crbegin() const;
|
|
ReverseIterator rend();
|
|
const ReverseIterator crend() const;
|
|
// element access
|
|
Val &front();
|
|
const Val &front() const;
|
|
Val &back(bool prepend = false);
|
|
Val &operator[](const Key &key);
|
|
// lookup
|
|
Iterator find(const Key &key);
|
|
// modifiers
|
|
void push_front(const Key &key, const Val &val);
|
|
void push_front(const Key &key, Val &&val);
|
|
void push_back(const Key &key, const Val &val);
|
|
void push_back(const Key &key, Val &&val);
|
|
void pop_front();
|
|
void pop_back();
|
|
Iterator erase(const Key &key);
|
|
Iterator erase(const Iterator pos);
|
|
Iterator erase(const Iterator first, const Iterator last);
|
|
|
|
private:
|
|
void MoveToHead(LinkNode<Key, Val> *&pnode);
|
|
void MoveToTail(LinkNode<Key, Val> *&pnode);
|
|
bool MoveNode(const Iterator &pos, LinkNode<Key, Val> *&pnode);
|
|
LinkNode<Key, Val> *AllocateNode(const Key &key);
|
|
LinkNode<Key, Val> *AllocateNode(const Key &key, const Val &val);
|
|
LinkNode<Key, Val> *AllocateNode(const Key &key, Val &&val);
|
|
void ReclaimNode(LinkNode<Key, Val> *&pnode);
|
|
|
|
std::size_t numItem_ {0};
|
|
LinkNode<Key, Val> *pData_ {nullptr};
|
|
Link dataHead_ {};
|
|
Link freeHead_ {};
|
|
std::unordered_map<Key, LinkNode<Key, Val> *> valueTab_ {};
|
|
};
|
|
|
|
// implementation of template class LinkNode
|
|
template<typename Key, typename Val>
|
|
LinkNode<Key, Val>::LinkNode(const Key &key) : key_ {key} {}
|
|
|
|
template<typename Key, typename Val>
|
|
LinkNode<Key, Val>::LinkNode(const Key &key, const Val &val) : key_ {key}, val_ {val} {}
|
|
|
|
template<typename Key, typename Val>
|
|
LinkNode<Key, Val>::LinkNode(const Key &key, Val &&val) : key_ {key}, val_ {std::move(val)} {}
|
|
|
|
template<typename Key, typename Val>
|
|
LinkNode<Key, Val>::LinkNode(const LinkNode& node)
|
|
:link_ {node.link_},
|
|
key_ {node.key_},
|
|
val_ {node.val_}
|
|
{}
|
|
|
|
template<typename Key, typename Val>
|
|
LinkNode<Key, Val>::LinkNode(LinkNode&& node)
|
|
:link_ {std::move(node.link_)},
|
|
key_ {std::move(node.key_)},
|
|
val_ {std::move(node.val_)}
|
|
{}
|
|
|
|
template<typename Key, typename Val>
|
|
auto LinkNode<Key, Val>::operator=(const LinkNode& node)
|
|
-> LinkNode<Key, Val>&
|
|
{
|
|
link_ = node.link_;
|
|
key_ = node.key_;
|
|
val_ = node.val_;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto LinkNode<Key, Val>::operator=(LinkNode&& node)
|
|
-> LinkNode<Key, Val>&
|
|
{
|
|
link_ = std::move(node.link_);
|
|
key_ = std::move(node.key_);
|
|
val_ = std::move(node.val_);
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto LinkNode<Key, Val>::GetLinkNode(Val *pval)
|
|
-> LinkNode<Key, Val>*
|
|
{
|
|
if (pval) {
|
|
LinkNode<Key, Val> *pnode {nullptr};
|
|
Val* offset = &pnode->val_;
|
|
auto nodeAddr = reinterpret_cast<char*>(pval) - reinterpret_cast<char*>(offset);
|
|
return reinterpret_cast<LinkNode<Key, Val>*>(nodeAddr);
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto LinkNode<Key, Val>::GetLinkNode(Link *plink)
|
|
-> LinkNode<Key, Val>*
|
|
{
|
|
if (plink) {
|
|
LinkNode<Key, Val> *pnode {nullptr};
|
|
Link* offset = &pnode->link_;
|
|
auto nodeAddr = reinterpret_cast<char*>(plink) - reinterpret_cast<char*>(offset);
|
|
return reinterpret_cast<LinkNode<Key, Val>*>(nodeAddr);
|
|
}
|
|
return nullptr;
|
|
}
|
|
// end of LinkNode
|
|
|
|
// implementation of template class Iterator
|
|
template<typename Key, typename Val>
|
|
HashList<Key, Val>::Iterator::Iterator(LinkNode<Key, Val> *pnode, HashList *phashList)
|
|
: pnode_ {pnode}, phashList_ {phashList}
|
|
{
|
|
if (phashList_ == nullptr) {
|
|
pnode_ = nullptr;
|
|
}
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
HashList<Key, Val>::Iterator::Iterator(const LinkNode<Key, Val> *pnode, const HashList *phashList)
|
|
: pnode_ {const_cast<LinkNode<Key, Val>*>(pnode)},
|
|
phashList_ {const_cast<HashList*>(phashList)}
|
|
{
|
|
if (phashList_ == nullptr) {
|
|
pnode_ = nullptr;
|
|
}
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
HashList<Key, Val>::Iterator::Iterator(const Iterator& itr)
|
|
: pnode_ {itr.pnode_}, phashList_ {itr.phashList_}
|
|
{}
|
|
|
|
template<typename Key, typename Val>
|
|
HashList<Key, Val>::Iterator::Iterator(Iterator&& itr)
|
|
: pnode_ {itr.pnode_}, phashList_ {itr.phashList_}
|
|
{
|
|
itr.pnode_ = nullptr;
|
|
itr.phashList_ = nullptr;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::Iterator::operator=(const Iterator& itr)
|
|
-> HashList<Key, Val>::Iterator&
|
|
{
|
|
Iterator temp {itr};
|
|
swap(temp);
|
|
return *this;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::Iterator::operator=(Iterator&& itr)
|
|
-> HashList<Key, Val>::Iterator&
|
|
{
|
|
Iterator temp {std::move(itr)};
|
|
swap(temp);
|
|
return *this;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::Iterator::operator++() noexcept
|
|
-> HashList<Key, Val>::Iterator &
|
|
{
|
|
if (pnode_ == nullptr or phashList_ == nullptr) {
|
|
phashList_ = nullptr;
|
|
return *this;
|
|
}
|
|
Link* plink = pnode_->link_.next_;
|
|
if (plink == &phashList_->dataHead_) {
|
|
pnode_ = nullptr;
|
|
return *this;
|
|
}
|
|
auto pnode = LinkNode<Key, Val>::GetLinkNode(plink);
|
|
pnode_ = pnode;
|
|
return *this;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::Iterator::operator++(int) noexcept
|
|
-> HashList<Key, Val>::Iterator
|
|
{
|
|
Iterator res {*this};
|
|
if (pnode_ == nullptr or phashList_ == nullptr) {
|
|
phashList_ = nullptr;
|
|
return res;
|
|
}
|
|
Link* plink = pnode_->link_.next_;
|
|
if (plink == &phashList_->dataHead_) {
|
|
pnode_ = nullptr;
|
|
return res;
|
|
}
|
|
auto pnode = LinkNode<Key, Val>::GetLinkNode(plink);
|
|
pnode_ = pnode;
|
|
return res;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::Iterator::operator--() noexcept
|
|
-> HashList<Key, Val>::Iterator &
|
|
{
|
|
if (phashList_ == nullptr) {
|
|
return *this;
|
|
}
|
|
Link* plink {nullptr};
|
|
if (pnode_ == nullptr) {
|
|
plink = phashList_->dataHead_.prev_;
|
|
} else {
|
|
plink = pnode_->link_.prev_;
|
|
}
|
|
if (plink == &phashList_->dataHead_) {
|
|
pnode_ = nullptr;
|
|
phashList_ = nullptr;
|
|
return *this;
|
|
}
|
|
pnode_ = LinkNode<Key, Val>::GetLinkNode(plink);
|
|
return *this;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::Iterator::operator--(int) noexcept
|
|
-> HashList<Key, Val>::Iterator
|
|
{
|
|
Iterator res {*this};
|
|
if (phashList_ == nullptr) {
|
|
return res;
|
|
}
|
|
Link* plink {nullptr};
|
|
if (pnode_ == nullptr) {
|
|
plink = phashList_->dataHead_.prev_;
|
|
} else {
|
|
plink = pnode_->link_.prev_;
|
|
}
|
|
if (plink == &phashList_->dataHead_) {
|
|
pnode_ = nullptr;
|
|
phashList_ = nullptr;
|
|
return res;
|
|
}
|
|
pnode_ = LinkNode<Key, Val>::GetLinkNode(plink);
|
|
return res;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
bool HashList<Key, Val>::Iterator::operator<(const HashList<Key, Val>::Iterator &itr) const noexcept
|
|
{
|
|
if (IsDangled() or itr.IsDangled()) {
|
|
return false;
|
|
}
|
|
if (phashList_ != itr.phashList_) {
|
|
return false;
|
|
}
|
|
Iterator tempItr {*this};
|
|
if (tempItr == itr) {
|
|
return false;
|
|
}
|
|
while (!tempItr.IsDangled()) {
|
|
tempItr++;
|
|
if (tempItr == itr) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
bool HashList<Key, Val>::Iterator::operator==(const HashList<Key, Val>::Iterator &itr) const noexcept
|
|
{
|
|
if (IsDangled() or itr.IsDangled()) {
|
|
return false;
|
|
}
|
|
if (phashList_ != itr.phashList_) {
|
|
return false;
|
|
}
|
|
return pnode_ == itr.pnode_;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
Val& HashList<Key, Val>::Iterator::operator*()
|
|
{
|
|
return pnode_->val_;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
const Val& HashList<Key, Val>::Iterator::operator*() const
|
|
{
|
|
return pnode_->val_;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
Val* HashList<Key, Val>::Iterator::operator->()
|
|
{
|
|
return &pnode_->val_;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
const Val* HashList<Key, Val>::Iterator::operator->() const
|
|
{
|
|
return &pnode_->val_;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
void HashList<Key, Val>::Iterator::swap(HashList<Key, Val>::Iterator& other)
|
|
{
|
|
using std::swap;
|
|
swap(pnode_, other.pnode_);
|
|
swap(phashList_, other.phashList_);
|
|
}
|
|
// end of Iterator
|
|
|
|
// Implementation of ReverseIterator
|
|
template<typename Key, typename Val>
|
|
HashList<Key, Val>::ReverseIterator::ReverseIterator(LinkNode<Key, Val> *pnode, HashList *phashList)
|
|
: pnode_ {pnode}, phashList_ {phashList}
|
|
{
|
|
if (phashList_ == nullptr) {
|
|
pnode_ = nullptr;
|
|
}
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
HashList<Key, Val>::ReverseIterator::ReverseIterator(const LinkNode<Key, Val> *pnode, const HashList *phashList)
|
|
: pnode_ {const_cast<LinkNode<Key, Val> *>(pnode)},
|
|
phashList_ {const_cast<HashList *>(phashList)}
|
|
{
|
|
if (phashList_ == nullptr) {
|
|
pnode_ = nullptr;
|
|
}
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
HashList<Key, Val>::ReverseIterator::ReverseIterator(const ReverseIterator &itr)
|
|
: pnode_ {itr.pnode_}, phashList_ {itr.phashList_}
|
|
{}
|
|
|
|
template<typename Key, typename Val>
|
|
HashList<Key, Val>::ReverseIterator::ReverseIterator(ReverseIterator &&itr)
|
|
: pnode_ {itr.pnode_}, phashList_ {itr.phashList_}
|
|
{
|
|
itr.pnode_ = nullptr;
|
|
itr.phashList_ = nullptr;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::ReverseIterator::operator=(const ReverseIterator& itr)
|
|
-> HashList<Key, Val>::ReverseIterator&
|
|
{
|
|
ReverseIterator temp {itr};
|
|
swap(temp);
|
|
return *this;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::ReverseIterator::operator=(ReverseIterator&& itr)
|
|
-> HashList<Key, Val>::ReverseIterator&
|
|
{
|
|
ReverseIterator temp {std::move(itr)};
|
|
swap(temp);
|
|
return *this;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::ReverseIterator::operator++() noexcept
|
|
-> HashList<Key, Val>::ReverseIterator &
|
|
{
|
|
if (pnode_ == nullptr or phashList_ == nullptr) {
|
|
phashList_ = nullptr;
|
|
return *this;
|
|
}
|
|
Link* plink = &pnode_->link_;
|
|
plink = plink->prev_;
|
|
if (plink == &phashList_->dataHead_) {
|
|
pnode_ = nullptr;
|
|
return *this;
|
|
}
|
|
pnode_ = LinkNode<Key, Val>::GetLinkNode(plink);
|
|
return *this;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::ReverseIterator::operator++(int) noexcept
|
|
-> HashList<Key, Val>::ReverseIterator
|
|
{
|
|
ReverseIterator res {*this};
|
|
if (pnode_ == nullptr or phashList_ == nullptr) {
|
|
phashList_ = nullptr;
|
|
return res;
|
|
}
|
|
Link* plink = &pnode_->link_;
|
|
plink = plink->prev_;
|
|
if (plink == &phashList_->dataHead_) {
|
|
pnode_ = nullptr;
|
|
return res;
|
|
}
|
|
pnode_ = LinkNode<Key, Val>::GetLinkNode(plink);
|
|
return res;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::ReverseIterator::operator--() noexcept
|
|
-> HashList<Key, Val>::ReverseIterator &
|
|
{
|
|
if (phashList_ == nullptr) {
|
|
return *this;
|
|
}
|
|
Link* plink {nullptr};
|
|
if (pnode_ == nullptr) {
|
|
plink = phashList_->dataHead_.next_;
|
|
} else {
|
|
plink = pnode_->link_.next_;
|
|
}
|
|
if (plink == &phashList_->dataHead_) {
|
|
pnode_ = nullptr;
|
|
phashList_ = nullptr;
|
|
return *this;
|
|
}
|
|
pnode_ = LinkNode<Key, Val>::GetLinkNode(plink);
|
|
return *this;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::ReverseIterator::operator--(int) noexcept
|
|
-> HashList<Key, Val>::ReverseIterator
|
|
{
|
|
ReverseIterator res {*this};
|
|
if (phashList_ == nullptr) {
|
|
return res;
|
|
}
|
|
Link* plink {nullptr};
|
|
if (pnode_ == nullptr) {
|
|
plink = phashList_->dataHead_.next_;
|
|
} else {
|
|
plink = pnode_->link_.next_;
|
|
}
|
|
if (plink == &phashList_->dataHead_) {
|
|
pnode_ = nullptr;
|
|
phashList_ = nullptr;
|
|
return res;
|
|
}
|
|
pnode_ = LinkNode<Key, Val>::GetLinkNode(plink);
|
|
return res;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
bool HashList<Key, Val>::ReverseIterator::operator<(
|
|
const HashList<Key, Val>::ReverseIterator &itr) const noexcept
|
|
{
|
|
if (IsDangled() or itr.IsDangled()) {
|
|
return false;
|
|
}
|
|
if (phashList_ != itr.phashList_) {
|
|
return false;
|
|
}
|
|
HashList<Key, Val>::ReverseIterator tempItr {*this};
|
|
if (tempItr == itr) {
|
|
return false;
|
|
}
|
|
while (!tempItr.IsDangled()) {
|
|
tempItr++;
|
|
if (tempItr == itr) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
bool HashList<Key, Val>::ReverseIterator::operator==(
|
|
const HashList<Key, Val>::ReverseIterator &itr) const noexcept
|
|
{
|
|
if (IsDangled() or itr.IsDangled()) {
|
|
return false;
|
|
}
|
|
if (phashList_ != itr.phashList_) {
|
|
return false;
|
|
}
|
|
return pnode_ == itr.pnode_;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
Val& HashList<Key, Val>::ReverseIterator::operator*()
|
|
{
|
|
return pnode_->val_;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
const Val& HashList<Key, Val>::ReverseIterator::operator*() const
|
|
{
|
|
return pnode_->val_;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
Val* HashList<Key, Val>::ReverseIterator::operator->()
|
|
{
|
|
return &pnode_->val_;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
const Val* HashList<Key, Val>::ReverseIterator::operator->() const
|
|
{
|
|
return &pnode_->val_;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
void HashList<Key, Val>::ReverseIterator::swap(HashList<Key, Val>::ReverseIterator& other)
|
|
{
|
|
using std::swap;
|
|
swap(pnode_, other.pnode_);
|
|
swap(phashList_, other.phashList_);
|
|
}
|
|
// end of ReverseIterator
|
|
|
|
// implementation of template class HashList
|
|
template<typename Key, typename Val>
|
|
HashList<Key, Val>::HashList(const std::size_t numItem) : numItem_ {numItem}
|
|
{
|
|
dataHead_.next_ = &dataHead_;
|
|
dataHead_.prev_ = &dataHead_;
|
|
if (numItem_) {
|
|
valueTab_.reserve(numItem_);
|
|
pData_ = new(std::nothrow) LinkNode<Key, Val>[numItem_];
|
|
if (pData_) {
|
|
freeHead_.next_ = &(pData_[0].link_);
|
|
std::size_t last {numItem_ - 1};
|
|
for (std::size_t index = 0; index < last;) {
|
|
LinkNode<Key, Val> &curNnode = pData_[index];
|
|
curNnode.link_.next_ = &(pData_[++index].link_);
|
|
}
|
|
pData_[last].link_.next_ = &freeHead_;
|
|
} else {
|
|
numItem_ = 0;
|
|
freeHead_.next_ = &freeHead_;
|
|
freeHead_.prev_ = &freeHead_;
|
|
}
|
|
}
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
int HashList<Key, Val>::reserve(const std::size_t numItem)
|
|
{
|
|
if (numItem_ != 0) {
|
|
return -1;
|
|
}
|
|
if (numItem) {
|
|
numItem_ = numItem;
|
|
valueTab_.reserve(numItem_);
|
|
pData_ = new(std::nothrow) LinkNode<Key, Val>[numItem_];
|
|
dataHead_.next_ = &dataHead_;
|
|
dataHead_.prev_ = &dataHead_;
|
|
if (pData_) {
|
|
freeHead_.next_ = &(pData_[0].link_);
|
|
std::size_t last {numItem_ - 1};
|
|
for (std::size_t index = 0; index < last;) {
|
|
LinkNode<Key, Val> &curNnode = pData_[index];
|
|
curNnode.link_.next_ = &(pData_[++index].link_);
|
|
}
|
|
pData_[last].link_.next_ = &freeHead_;
|
|
} else {
|
|
numItem_ = 0;
|
|
freeHead_.next_ = &freeHead_;
|
|
freeHead_.prev_ = &freeHead_;
|
|
}
|
|
}
|
|
return numItem_;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
HashList<Key, Val>::~HashList()
|
|
{
|
|
if (pData_) {
|
|
delete[] pData_;
|
|
pData_ = nullptr;
|
|
}
|
|
valueTab_.clear();
|
|
dataHead_.next_ = &dataHead_;
|
|
dataHead_.prev_ = &dataHead_;
|
|
freeHead_.next_ = nullptr;
|
|
freeHead_.prev_ = nullptr;
|
|
numItem_ = 0;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
HashList<Key, Val>::HashList(HashList<Key, Val> &&source)
|
|
: numItem_ {source.numItem_},
|
|
pData_ {source.pData_},
|
|
dataHead_ {std::move(source.dataHead_)},
|
|
freeHead_ {std::move(source.freeHead_)},
|
|
valueTab_ {std::move(source.valueTab_)}
|
|
{
|
|
source.pData_ = nullptr;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::operator=(HashList &&source)
|
|
-> HashList<Key, Val>&
|
|
{
|
|
if (this == &source) {
|
|
return *this;
|
|
}
|
|
if (pData_) {
|
|
delete[] pData_;
|
|
pData_ = nullptr;
|
|
}
|
|
numItem_ = source.numItem_;
|
|
pData_ = source.pData_;
|
|
source.pData_ = nullptr;
|
|
dataHead_ = std::move(source.dataHead_);
|
|
freeHead_ = std::move(source.freeHead_);
|
|
valueTab_ = std::move(source.valueTab_);
|
|
return *this;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::begin()
|
|
-> HashList<Key, Val>::Iterator
|
|
{
|
|
if (empty()) {
|
|
return end();
|
|
}
|
|
return Iterator(LinkNode<Key, Val>::GetLinkNode(dataHead_.next_), this);
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::cbegin() const
|
|
-> const HashList<Key, Val>::Iterator
|
|
{
|
|
if (empty()) {
|
|
return cend();
|
|
}
|
|
return Iterator(LinkNode<Key, Val>::GetLinkNode(dataHead_.next_), this);
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::end()
|
|
-> HashList<Key, Val>::Iterator
|
|
{
|
|
return Iterator(nullptr, this);
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::cend() const
|
|
-> const HashList<Key, Val>::Iterator
|
|
{
|
|
return Iterator(nullptr, this);
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::rbegin()
|
|
-> HashList<Key, Val>::ReverseIterator
|
|
{
|
|
if (empty()) {
|
|
return rend();
|
|
}
|
|
return ReverseIterator(LinkNode<Key, Val>::GetLinkNode(dataHead_.prev_), this);
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::crbegin() const
|
|
-> const HashList<Key, Val>::ReverseIterator
|
|
{
|
|
if (empty()) {
|
|
return crend();
|
|
}
|
|
return ReverseIterator(LinkNode<Key, Val>::GetLinkNode(dataHead_.prev_), this);
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::rend()
|
|
-> HashList<Key, Val>::ReverseIterator
|
|
{
|
|
return ReverseIterator(nullptr, this);
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::crend() const
|
|
-> const HashList<Key, Val>::ReverseIterator
|
|
{
|
|
return ReverseIterator(nullptr, this);
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
Val& HashList<Key, Val>::front()
|
|
{
|
|
LinkNode<Key, Val> *pnode = LinkNode<Key, Val>::GetLinkNode(dataHead_.next_);
|
|
return pnode->val_;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
const Val& HashList<Key, Val>::front() const
|
|
{
|
|
return front();
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
Val& HashList<Key, Val>::back(bool prepend)
|
|
{
|
|
auto pnode = LinkNode<Key, Val>::GetLinkNode(dataHead_.prev_);
|
|
if (prepend) {
|
|
MoveToHead(pnode);
|
|
}
|
|
return pnode->val_;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
Val& HashList<Key, Val>::operator[](const Key &key)
|
|
{
|
|
LinkNode<Key, Val> *pnode {nullptr};
|
|
if (valueTab_.find(key) == valueTab_.end()) {
|
|
pnode = AllocateNode(key);
|
|
valueTab_[key] = pnode;
|
|
} else {
|
|
pnode = valueTab_[key];
|
|
}
|
|
if (pnode == nullptr) {
|
|
static Val val = Val();
|
|
return val;
|
|
} else {
|
|
MoveToHead(pnode);
|
|
}
|
|
return pnode->val_;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::find(const Key &key)
|
|
-> HashList<Key, Val>::Iterator
|
|
{
|
|
const auto &itr = valueTab_.find(key);
|
|
if (itr == valueTab_.end()) {
|
|
return end();
|
|
}
|
|
return Iterator(itr->second, this);
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
void HashList<Key, Val>::push_front(const Key& key, const Val& val)
|
|
{
|
|
if (valueTab_.find(key) == valueTab_.end()) {
|
|
LinkNode<Key, Val>* pnode = AllocateNode(key, val);
|
|
MoveToHead(pnode);
|
|
valueTab_[pnode->key_] = pnode;
|
|
} else {
|
|
MoveToHead(valueTab_[key]);
|
|
this->operator[](key) = val;
|
|
}
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
void HashList<Key, Val>::push_front(const Key& key, Val&& val)
|
|
{
|
|
if (valueTab_.find(key) == valueTab_.end()) {
|
|
LinkNode<Key, Val>* pnode = AllocateNode(key, std::move(val));
|
|
MoveToHead(pnode);
|
|
valueTab_[pnode->key_] = pnode;
|
|
} else {
|
|
MoveToHead(valueTab_[key]);
|
|
this->operator[](key) = val;
|
|
}
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
void HashList<Key, Val>::push_back(const Key& key, const Val& val)
|
|
{
|
|
if (valueTab_.find(key) == valueTab_.end()) {
|
|
LinkNode<Key, Val>* pnode = AllocateNode(key, val);
|
|
MoveToTail(pnode);
|
|
valueTab_[pnode->key_] = pnode;
|
|
} else {
|
|
MoveToTail(valueTab_[key]);
|
|
this->operator[](key) = val;
|
|
}
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
void HashList<Key, Val>::push_back(const Key& key, Val&& val)
|
|
{
|
|
if (valueTab_.find(key) == valueTab_.end()) {
|
|
LinkNode<Key, Val>* pnode = AllocateNode(key, std::move(val));
|
|
MoveToTail(pnode);
|
|
valueTab_[pnode->key_] = pnode;
|
|
} else {
|
|
MoveToTail(valueTab_[key]);
|
|
this->operator[](key) = val;
|
|
}
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
void HashList<Key, Val>::pop_front()
|
|
{
|
|
if (empty()) {
|
|
return;
|
|
}
|
|
LinkNode<Key, Val>* pnode = LinkNode<Key, Val>::GetLinkNode(dataHead_.next_);
|
|
valueTab_.erase(pnode->key_);
|
|
ReclaimNode(pnode);
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
void HashList<Key, Val>::pop_back()
|
|
{
|
|
if (empty()) {
|
|
return;
|
|
}
|
|
LinkNode<Key, Val>* pnode = LinkNode<Key, Val>::GetLinkNode(dataHead_.prev_);
|
|
if (pnode != nullptr) {
|
|
valueTab_.erase(pnode->key_);
|
|
ReclaimNode(pnode);
|
|
}
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::erase(const Key& key)
|
|
-> HashList<Key, Val>::Iterator
|
|
{
|
|
if (valueTab_.find(key) == valueTab_.end()) {
|
|
return end();
|
|
}
|
|
LinkNode<Key, Val> *pnode = valueTab_[key];
|
|
valueTab_.erase(key);
|
|
Link* plink = pnode->link_.next_;
|
|
Iterator tempItr {LinkNode<Key, Val>::GetLinkNode(plink), this};
|
|
ReclaimNode(pnode);
|
|
return tempItr;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::erase(const Iterator pos)
|
|
-> HashList<Key, Val>::Iterator
|
|
{
|
|
// assume pos is valid, otherwise the result is undefined
|
|
Iterator tempItr {pos};
|
|
++tempItr;
|
|
LinkNode<Key, Val> *pnode = pos.GetNode();
|
|
valueTab_.erase(pnode->key_);
|
|
ReclaimNode(pnode);
|
|
return tempItr;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::erase(const Iterator first, const Iterator last)
|
|
-> HashList<Key, Val>::Iterator
|
|
{
|
|
// assume pos is valid, otherwise the result is undefined
|
|
if (first <= last) {
|
|
Iterator curPos {first};
|
|
while (curPos < last) {
|
|
curPos = erase(curPos);
|
|
}
|
|
return last;
|
|
}
|
|
return end();
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
bool HashList<Key, Val>::MoveNode(const Iterator& pos, LinkNode<Key, Val> *&pnode)
|
|
{
|
|
LinkNode<Key, Val> *curNode = pos.GetNode();
|
|
if (curNode == pnode) {
|
|
return true;
|
|
}
|
|
if (pnode->link_.next_ == &curNode->link_) {
|
|
return true;
|
|
}
|
|
Link* prevLink = pnode->link_.prev_;
|
|
Link* nextLink = pnode->link_.next_;
|
|
if (prevLink and nextLink) {
|
|
prevLink->next_ = nextLink;
|
|
nextLink->prev_ = prevLink;
|
|
}
|
|
Link *currLink = &curNode->link_;
|
|
prevLink = currLink->prev_;
|
|
nextLink = &pnode->link_;
|
|
prevLink->next_ = nextLink;
|
|
nextLink->prev_ = prevLink;
|
|
nextLink->next_ = currLink;
|
|
currLink->prev_ = nextLink;
|
|
return true;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
void HashList<Key, Val>::MoveToHead(LinkNode<Key, Val> *&pnode)
|
|
{
|
|
if (pnode->link_.prev_ and pnode->link_.next_) {
|
|
Link* prev = pnode->link_.prev_;
|
|
Link* next = pnode->link_.next_;
|
|
prev->next_ = next;
|
|
next->prev_ = prev;
|
|
}
|
|
pnode->link_.next_ = dataHead_.next_;
|
|
dataHead_.next_->prev_ = &pnode->link_;
|
|
dataHead_.next_ = &pnode->link_;
|
|
pnode->link_.prev_ = &dataHead_;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
void HashList<Key, Val>::MoveToTail(LinkNode<Key, Val> *&pnode)
|
|
{
|
|
if (pnode->link_.prev_ and pnode->link_.next_) {
|
|
Link* prev = pnode->link_.prev_;
|
|
Link* next = pnode->link_.next_;
|
|
prev->next_ = next;
|
|
next->prev_ = prev;
|
|
}
|
|
pnode->link_.prev_ = dataHead_.prev_;
|
|
dataHead_.prev_->next_ = &pnode->link_;
|
|
pnode->link_.next_ = &dataHead_;
|
|
dataHead_.prev_ = &pnode->link_;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::AllocateNode(const Key &key)
|
|
->LinkNode<Key, Val> *
|
|
{
|
|
if (IsFull()) {
|
|
pop_back();
|
|
}
|
|
LinkNode<Key, Val> *pnode = LinkNode<Key, Val>::GetLinkNode(freeHead_.next_);
|
|
freeHead_.next_ = freeHead_.next_->next_;
|
|
if (pnode != nullptr) {
|
|
pnode->link_.next_ = nullptr;
|
|
pnode->link_.prev_ = nullptr;
|
|
pnode->key_ = key;
|
|
pnode->val_ = Val();
|
|
}
|
|
return pnode;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::AllocateNode(const Key &key, const Val &val)
|
|
->LinkNode<Key, Val> *
|
|
{
|
|
if (IsFull()) {
|
|
pop_back();
|
|
}
|
|
LinkNode<Key, Val> *pnode = LinkNode<Key, Val>::GetLinkNode(freeHead_.next_);
|
|
freeHead_.next_ = freeHead_.next_->next_;
|
|
pnode->link_.next_ = nullptr;
|
|
pnode->link_.prev_ = nullptr;
|
|
pnode->key_ = key;
|
|
pnode->val_ = val;
|
|
return pnode;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
auto HashList<Key, Val>::AllocateNode(const Key &key, Val &&val)
|
|
->LinkNode<Key, Val> *
|
|
{
|
|
if (IsFull()) {
|
|
pop_back();
|
|
}
|
|
LinkNode<Key, Val> *pnode = LinkNode<Key, Val>::GetLinkNode(freeHead_.next_);
|
|
freeHead_.next_ = freeHead_.next_->next_;
|
|
pnode->link_.next_ = nullptr;
|
|
pnode->link_.prev_ = nullptr;
|
|
pnode->key_ = key;
|
|
pnode->val_ = std::move(val);
|
|
return pnode;
|
|
}
|
|
|
|
template<typename Key, typename Val>
|
|
void HashList<Key, Val>::ReclaimNode(LinkNode<Key, Val> *&pnode)
|
|
{
|
|
Link *prevLink = pnode->link_.prev_;
|
|
Link *nextLink = pnode->link_.next_;
|
|
prevLink->next_ = nextLink;
|
|
nextLink->prev_ = prevLink;
|
|
pnode->link_.prev_ = nullptr;
|
|
pnode->link_.next_ = freeHead_.next_;
|
|
freeHead_.next_ = &pnode->link_;
|
|
return;
|
|
}
|
|
} // namespace HiPerf
|
|
} // namespace Developtools
|
|
} // namespace OHOS
|
|
#endif // HIPERF_HASHLIST_H
|