зеркало из https://github.com/mozilla/gecko-dev.git
194 строки
5.9 KiB
C++
194 строки
5.9 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef XPCOM_DS_NSTHASHSET_H_
|
|
#define XPCOM_DS_NSTHASHSET_H_
|
|
|
|
#include "nsHashtablesFwd.h"
|
|
#include "nsTHashMap.h" // for nsKeyClass
|
|
|
|
/**
|
|
* Templated hash set. Don't use this directly, but use nsTHashSet instead
|
|
* (defined as a type alias in nsHashtablesFwd.h).
|
|
*
|
|
* @param KeyClass a wrapper-class for the hashtable key, see nsHashKeys.h
|
|
* for a complete specification.
|
|
*/
|
|
template <class KeyClass>
|
|
class nsTBaseHashSet : protected nsTHashtable<KeyClass> {
|
|
using Base = nsTHashtable<KeyClass>;
|
|
typedef mozilla::fallible_t fallible_t;
|
|
|
|
public:
|
|
// XXX We have a similar situation here like with DataType/UserDataType in
|
|
// nsBaseHashtable. It's less problematic here due to the more constrained
|
|
// interface, but it may still be confusing. KeyType is not the stored key
|
|
// type, but the one exposed to the user, i.e. as a parameter type, and as the
|
|
// value type when iterating. It is currently impossible to move-insert a
|
|
// RefPtr<T>, e.g., since the KeyType is T* in that case.
|
|
using ValueType = typename KeyClass::KeyType;
|
|
|
|
// KeyType is defined just for compatibility with nsTHashMap. For a set, the
|
|
// key type is conceptually equivalent to the value type.
|
|
using KeyType = typename KeyClass::KeyType;
|
|
|
|
using Base::Base;
|
|
|
|
// Query operations.
|
|
|
|
using Base::Contains;
|
|
using Base::GetGeneration;
|
|
using Base::ShallowSizeOfExcludingThis;
|
|
using Base::ShallowSizeOfIncludingThis;
|
|
using Base::SizeOfExcludingThis;
|
|
using Base::SizeOfIncludingThis;
|
|
|
|
/**
|
|
* Return the number of entries in the table.
|
|
* @return number of entries
|
|
*/
|
|
[[nodiscard]] uint32_t Count() const { return Base::Count(); }
|
|
|
|
/**
|
|
* Return whether the table is empty.
|
|
* @return whether empty
|
|
*/
|
|
[[nodiscard]] bool IsEmpty() const { return Base::IsEmpty(); }
|
|
|
|
using iterator = ::detail::nsTHashtableKeyIterator<KeyClass>;
|
|
using const_iterator = iterator;
|
|
|
|
[[nodiscard]] auto begin() const { return Base::Keys().begin(); }
|
|
|
|
[[nodiscard]] auto end() const { return Base::Keys().end(); }
|
|
|
|
[[nodiscard]] auto cbegin() const { return Base::Keys().cbegin(); }
|
|
|
|
[[nodiscard]] auto cend() const { return Base::Keys().cend(); }
|
|
|
|
// Mutating operations.
|
|
|
|
using Base::Clear;
|
|
using Base::MarkImmutable;
|
|
|
|
/**
|
|
* Inserts a value into the set. Has no effect if the value is already in the
|
|
* set. This overload is infallible and crashes if memory is exhausted.
|
|
*
|
|
* \note For strict consistency with nsTHashtable::EntryHandle method naming,
|
|
* this should rather be called OrInsert, as it is legal to call it when the
|
|
* value is already in the set. For simplicity, as we don't have two methods,
|
|
* we still use "Insert" instead.
|
|
*/
|
|
void Insert(ValueType aValue) { Base::PutEntry(aValue); }
|
|
|
|
/**
|
|
* Inserts a value into the set. Has no effect if the value is already in the
|
|
* set. This overload is fallible and returns false if memory is exhausted.
|
|
*
|
|
* \note See note on infallible overload.
|
|
*/
|
|
[[nodiscard]] bool Insert(ValueType aValue, const mozilla::fallible_t&) {
|
|
return Base::PutEntry(aValue, mozilla::fallible);
|
|
}
|
|
|
|
/**
|
|
* Inserts a value into the set. Has no effect if the value is already in the
|
|
* set. This member function is infallible and crashes if memory is exhausted.
|
|
*
|
|
* \return true if the value was actually inserted, false if it was already in
|
|
* the set.
|
|
*/
|
|
bool EnsureInserted(ValueType aValue) { return Base::EnsureInserted(aValue); }
|
|
|
|
using Base::Remove;
|
|
|
|
/**
|
|
* Removes a value from the set. Has no effect if the value is not in the set.
|
|
*
|
|
* \note For strict consistency with nsTHashtable::EntryHandle method naming,
|
|
* this should rather be called OrRemove, as it is legal to call it when the
|
|
* value is not in the set. For simplicity, as we don't have two methods,
|
|
* we still use "Remove" instead.
|
|
*/
|
|
void Remove(ValueType aValue) { Base::RemoveEntry(aValue); }
|
|
|
|
using Base::EnsureRemoved;
|
|
|
|
/**
|
|
* Removes all elements matching a predicate.
|
|
*
|
|
* The predicate must be compatible with signature bool (ValueType).
|
|
*/
|
|
template <typename Pred>
|
|
void RemoveIf(Pred&& aPred) {
|
|
for (auto it = cbegin(), end = cend(); it != end; ++it) {
|
|
if (aPred(static_cast<ValueType>(*it))) {
|
|
Remove(it);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
template <typename KeyClass>
|
|
auto RangeSize(const nsTBaseHashSet<KeyClass>& aRange) {
|
|
return aRange.Count();
|
|
}
|
|
|
|
class nsCycleCollectionTraversalCallback;
|
|
|
|
template <class KeyClass>
|
|
inline void ImplCycleCollectionUnlink(nsTBaseHashSet<KeyClass>& aField) {
|
|
aField.Clear();
|
|
}
|
|
|
|
template <class KeyClass>
|
|
inline void ImplCycleCollectionTraverse(
|
|
nsCycleCollectionTraversalCallback& aCallback,
|
|
const nsTBaseHashSet<KeyClass>& aField, const char* aName,
|
|
uint32_t aFlags = 0) {
|
|
for (const auto& entry : aField) {
|
|
CycleCollectionNoteChild(aCallback, mozilla::detail::PtrGetWeak(entry),
|
|
aName, aFlags);
|
|
}
|
|
}
|
|
|
|
namespace mozilla {
|
|
template <typename SetT>
|
|
class nsTSetInserter {
|
|
SetT* mSet;
|
|
|
|
class Proxy {
|
|
SetT& mSet;
|
|
|
|
public:
|
|
explicit Proxy(SetT& aSet) : mSet{aSet} {}
|
|
|
|
template <typename E2>
|
|
void operator=(E2&& aValue) {
|
|
mSet.Insert(std::forward<E2>(aValue));
|
|
}
|
|
};
|
|
|
|
public:
|
|
using iterator_category = std::output_iterator_tag;
|
|
|
|
explicit nsTSetInserter(SetT& aSet) : mSet{&aSet} {}
|
|
|
|
Proxy operator*() { return Proxy(*mSet); }
|
|
|
|
nsTSetInserter& operator++() { return *this; }
|
|
nsTSetInserter& operator++(int) { return *this; }
|
|
};
|
|
} // namespace mozilla
|
|
|
|
template <typename E>
|
|
auto MakeInserter(nsTBaseHashSet<E>& aSet) {
|
|
return mozilla::nsTSetInserter<nsTBaseHashSet<E>>{aSet};
|
|
}
|
|
|
|
#endif // XPCOM_DS_NSTHASHSET_H_
|