developtools_hiperf/include/hashlist.h

1156 lines
31 KiB
C
Raw Permalink Normal View History

/*
* 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