Files
openfoam/src/OpenFOAM/containers/HashTables/StaticHashTable/StaticHashTableI.H
Mark Olesen f73b5b629f ENH: added HashTable 'lookup' and 'retain' methods
- lookup(): with a default value (const access)
  For example,
      Map<label> something;
      value = something.lookup(key, -1);

    being equivalent to the following:

      Map<label> something;
      value = -1;  // bad value
      if (something.found(key))
      {
          value = something[key];
      }

    except that lookup also makes it convenient to handle const references.
    Eg,

      const labelList& ids = someHash.lookup(key, labelList());

- For consistency, provide a two parameter HashTable '()' operator.
  The lookup() method is, however, normally preferable when
  const-only access is to be ensured.

- retain(): the counterpart to erase(), it only retains entries
  corresponding to the listed keys.

  For example,
      HashTable<someType> largeCache;
      wordHashSet preserve = ...;

      largeCache.retain(preserve);

    being roughly equivalent to the following two-stage process,
    but with reduced overhead and typing, and fewer potential mistakes.

      HashTable<someType> largeCache;
      wordHashSet preserve = ...;

      {
          wordHashSet cull(largeCache.toc()); // all keys
          cull.erase(preserve);               // except those to preserve
          largeCache.erase(cull);             //
      }

  The HashSet &= operator and retain() are functionally equivalent,
  but retain() also works with dissimilar value types.
2017-05-11 12:25:35 +02:00

414 lines
9.1 KiB
C++

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "error.H"
#include "IOstreams.H"
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
template<class T, class Key, class Hash>
inline Foam::label
Foam::StaticHashTable<T, Key, Hash>::hashKeyIndex(const Key& key) const
{
// size is power of two - this is the modulus
return Hash()(key) & (keys_.size() - 1);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T, class Key, class Hash>
inline Foam::label Foam::StaticHashTable<T, Key, Hash>::size() const
{
return nElmts_;
}
template<class T, class Key, class Hash>
inline bool Foam::StaticHashTable<T, Key, Hash>::empty() const
{
return !nElmts_;
}
template<class T, class Key, class Hash>
inline bool Foam::StaticHashTable<T, Key, Hash>::insert
(
const Key& key,
const T& obj
)
{
return set(key, obj, true);
}
template<class T, class Key, class Hash>
inline bool Foam::StaticHashTable<T, Key, Hash>::set
(
const Key& key,
const T& obj
)
{
return set(key, obj, false);
}
template<class T, class Key, class Hash>
inline Foam::Xfer<Foam::StaticHashTable<T, Key, Hash>>
Foam::StaticHashTable<T, Key, Hash>::xfer()
{
return xferMove(*this);
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class T, class Key, class Hash>
inline T& Foam::StaticHashTable<T, Key, Hash>::operator[](const Key& key)
{
iterator iter = find(key);
if (iter == end())
{
FatalErrorInFunction
<< toc()
<< exit(FatalError);
}
return *iter;
}
template<class T, class Key, class Hash>
inline const T& Foam::StaticHashTable<T, Key, Hash>::operator[]
(
const Key& key
) const
{
const_iterator iter = find(key);
if (iter == cend())
{
FatalErrorInFunction
<< toc()
<< exit(FatalError);
}
return *iter;
}
template<class T, class Key, class Hash>
inline T& Foam::StaticHashTable<T, Key, Hash>::operator()(const Key& key)
{
iterator iter = find(key);
if (iter == end())
{
insert(key, T());
return *find(key);
}
else
{
return *iter;
}
}
// * * * * * * * * * * * * * * * * STL iterator * * * * * * * * * * * * * * //
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::Iterator
(
TableRef hashTbl,
label hashIndex,
label elemIndex
)
:
hashTable_(hashTbl),
hashIndex_(hashIndex),
elemIndex_(elemIndex)
{}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::Iterator
(
const iterator& iter
)
:
hashTable_(iter.hashTable_),
hashIndex_(iter.hashIndex_),
elemIndex_(iter.elemIndex_)
{}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline void
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator=
(
const iterator& iter
)
{
this->hashIndex_ = iter.hashIndex_;
this->elemIndex_ = iter.elemIndex_;
}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline bool
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator==
(
const iterator& iter
) const
{
return hashIndex_ == iter.hashIndex_ && elemIndex_ == iter.elemIndex_;
}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline bool
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator==
(
const const_iterator& iter
) const
{
return hashIndex_ == iter.hashIndex_ && elemIndex_ == iter.elemIndex_;
}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline bool
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator!=
(
const iterator& iter
) const
{
return !operator==(iter);
}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline bool
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator!=
(
const const_iterator& iter
) const
{
return !operator==(iter);
}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline TRef
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator*()
{
return hashTable_.objects_[hashIndex_][elemIndex_];
}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline TRef
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::operator()()
{
return operator*();
}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline
typename Foam::StaticHashTable<T, Key, Hash>::template Iterator
<
TRef,
TableRef
>&
Foam::StaticHashTable<T, Key, Hash>::Iterator
<
TRef,
TableRef
>::operator++()
{
// A negative index is a special value from erase
// (see notes in HashTable)
if (hashIndex_ < 0)
{
hashIndex_ = -(hashIndex_+1) - 1;
}
else
{
// Try the next element on the local list
elemIndex_++;
if (elemIndex_ < hashTable_.objects_[hashIndex_].size())
{
return *this;
}
}
// Step to the next table entry
elemIndex_ = 0;
while
(
++hashIndex_ < hashTable_.objects_.size()
&& !hashTable_.objects_[hashIndex_].size()
)
{}
if (hashIndex_ >= hashTable_.objects_.size())
{
// make end iterator
hashIndex_ = hashTable_.keys_.size();
}
return *this;
}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline
typename Foam::StaticHashTable<T, Key, Hash>::template Iterator
<
TRef,
TableRef
>
Foam::StaticHashTable<T, Key, Hash>::Iterator
<
TRef,
TableRef
>::operator++
(
int
)
{
iterator tmp = *this;
++*this;
return tmp;
}
template<class T, class Key, class Hash>
template<class TRef, class TableRef>
inline const Key&
Foam::StaticHashTable<T, Key, Hash>::Iterator<TRef, TableRef>::key() const
{
return hashTable_.keys_[hashIndex_][elemIndex_];
}
template<class T, class Key, class Hash>
inline typename Foam::StaticHashTable<T, Key, Hash>::iterator
Foam::StaticHashTable<T, Key, Hash>::begin()
{
// Find first non-empty entry
forAll(keys_, hashIdx)
{
if (keys_[hashIdx].size())
{
return iterator(*this, hashIdx, 0);
}
}
#ifdef FULLDEBUG
if (debug)
{
Info<< "StaticHashTable is empty\n";
}
#endif
return StaticHashTable<T, Key, Hash>::endIter_;
}
template<class T, class Key, class Hash>
inline const typename Foam::StaticHashTable<T, Key, Hash>::iterator&
Foam::StaticHashTable<T, Key, Hash>::end()
{
return StaticHashTable<T, Key, Hash>::endIter_;
}
template<class T, class Key, class Hash>
inline typename Foam::StaticHashTable<T, Key, Hash>::const_iterator
Foam::StaticHashTable<T, Key, Hash>::cbegin() const
{
// Find first non-empty entry
forAll(keys_, hashIdx)
{
if (keys_[hashIdx].size())
{
return const_iterator(*this, hashIdx, 0);
}
}
#ifdef FULLDEBUG
if (debug)
{
Info<< "StaticHashTable is empty\n";
}
#endif
return StaticHashTable<T, Key, Hash>::endConstIter_;
}
template<class T, class Key, class Hash>
inline const typename Foam::StaticHashTable<T, Key, Hash>::const_iterator&
Foam::StaticHashTable<T, Key, Hash>::cend() const
{
return StaticHashTable<T, Key, Hash>::endConstIter_;
}
template<class T, class Key, class Hash>
inline typename Foam::StaticHashTable<T, Key, Hash>::const_iterator
Foam::StaticHashTable<T, Key, Hash>::begin() const
{
return this->cbegin();
}
template<class T, class Key, class Hash>
inline const typename Foam::StaticHashTable<T, Key, Hash>::const_iterator&
Foam::StaticHashTable<T, Key, Hash>::end() const
{
return StaticHashTable<T, Key, Hash>::endConstIter_;
}
// ************************************************************************* //