14#include <initializer_list>
31template <
typename T,
typename K,
typename Traits = T>
43 fCapacity = that.fCapacity;
44 fSlots.reset(
new Slot[that.fCapacity]);
45 for (
int i = 0;
i < fCapacity;
i++) {
46 fSlots[
i] = that.fSlots[
i];
55 fCapacity = that.fCapacity;
56 fSlots = std::move(that.fSlots);
58 that.fCount = that.fCapacity = 0;
67 int count()
const {
return fCount; }
84 *
this = std::move(that);
100 if (4 * fCount >= 3 * fCapacity) {
101 this->
resize(fCapacity > 0 ? fCapacity * 2 : 4);
103 return this->uncheckedSet(std::move(val));
109 int index =
hash & (fCapacity-1);
110 for (
int n = 0; n < fCapacity; n++) {
111 Slot&
s = fSlots[index];
115 if (
hash ==
s.fHash &&
key == Traits::GetKey(*
s)) {
118 index = this->next(index);
127 if (
T*
p = this->
find(key)) {
137 int index =
hash & (fCapacity-1);
138 for (
int n = 0; n < fCapacity; n++) {
139 Slot&
s = fSlots[index];
143 if (
hash ==
s.fHash &&
key == Traits::GetKey(*
s)) {
144 this->removeSlot(index);
145 if (4 * fCount <= fCapacity && fCapacity > 4) {
146 this->
resize(fCapacity / 2);
150 index = this->next(index);
165 int oldCapacity = fCapacity;
170 std::unique_ptr<Slot[]> oldSlots = std::move(fSlots);
173 for (
int i = 0;
i < oldCapacity;
i++) {
176 this->uncheckedSet(*std::move(
s));
183 template <
typename Fn>
184 void foreach(Fn&& fn) {
185 for (
int i = 0;
i < fCapacity;
i++) {
186 if (fSlots[
i].has_value()) {
193 template <
typename Fn>
194 void foreach(Fn&& fn)
const {
195 for (
int i = 0;
i < fCapacity;
i++) {
196 if (fSlots[
i].has_value()) {
205 template <
typename SlotVal>
235 return !(*
this == that);
256 int firstPopulatedSlot()
const {
257 for (
int i = 0;
i < fCapacity;
i++) {
258 if (fSlots[
i].has_value()) {
266 int nextPopulatedSlot(
int currentSlot)
const {
267 for (
int i = currentSlot + 1;
i < fCapacity;
i++) {
268 if (fSlots[
i].has_value()) {
276 const T* slot(
int i)
const {
281 T* uncheckedSet(
T&& val) {
282 const K&
key = Traits::GetKey(val);
285 int index =
hash & (fCapacity-1);
286 for (
int n = 0; n < fCapacity; n++) {
287 Slot&
s = fSlots[index];
290 s.emplace(std::move(val),
hash);
294 if (
hash ==
s.fHash &&
key == Traits::GetKey(*
s)) {
297 s.emplace(std::move(val),
hash);
301 index = this->next(index);
307 void removeSlot(
int index) {
312 Slot& emptySlot = fSlots[index];
313 int emptyIndex = index;
322 index = this->next(index);
323 Slot&
s = fSlots[index];
329 originalIndex =
s.fHash & (fCapacity - 1);
330 }
while ((index <= originalIndex && originalIndex < emptyIndex)
331 || (originalIndex < emptyIndex && emptyIndex < index)
332 || (emptyIndex < index && index <= originalIndex));
334 Slot& moveFrom = fSlots[index];
335 emptySlot = std::move(moveFrom);
339 int next(
int index)
const {
341 if (index < 0) { index += fCapacity; }
345 static uint32_t Hash(
const K&
key) {
353 ~Slot() { this->
reset(); }
355 Slot(
const Slot& that) { *
this = that; }
362 fVal.fStorage = that.fVal.fStorage;
369 new (&fVal.fStorage)
T(that.fVal.fStorage);
378 Slot(
Slot&& that) { *
this = std::move(that); }
385 fVal.fStorage = std::move(that.fVal.fStorage);
392 new (&fVal.fStorage)
T(std::move(that.fVal.fStorage));
402 const T&
operator*() const& {
return fVal.fStorage; }
403 T&&
operator*() && {
return std::move(fVal.fStorage); }
404 const T&&
operator*() const&& {
return std::move(fVal.fStorage); }
406 Slot& emplace(
T&& v, uint32_t
h) {
408 new (&fVal.fStorage)
T(std::move(v));
413 bool has_value()
const {
return fHash != 0; }
414 explicit operator bool()
const {
return this->has_value(); }
415 bool empty()
const {
return !this->has_value(); }
436 std::unique_ptr<Slot[]> fSlots;
441template <
typename K,
typename V,
typename HashK = SkGoodHash>
454 struct Pair :
public std::pair<K, V> {
455 using std::pair<
K,
V>::pair;
461 fTable.resize(pairs.size() * 5 / 3);
462 for (
const Pair&
p : pairs) {
471 int count()
const {
return fTable.count(); }
474 bool empty()
const {
return fTable.count() == 0; }
488 Pair*
out = fTable.set({std::move(
key), std::move(val)});
502 if (
V* val = this->
find(key)) {
505 return *this->
set(key,
V{});
515 return fTable.removeIfExists(
key);
519 template <
typename Fn,
520 std::enable_if_t<std::is_invocable_v<Fn, K, V*>>* =
nullptr>
521 void foreach(Fn&& fn) {
522 fTable.foreach([&fn](
Pair*
p) { fn(
p->first, &
p->second); });
526 template <
typename Fn,
527 std::enable_if_t<std::is_invocable_v<Fn, K, V>>* =
nullptr>
528 void foreach(Fn&& fn)
const {
529 fTable.foreach([&fn](
const Pair&
p) { fn(
p.first,
p.second); });
533 template <
typename Fn,
534 std::enable_if_t<std::is_invocable_v<Fn, Pair>>* =
nullptr>
535 void foreach(Fn&& fn)
const {
536 fTable.foreach([&fn](
const Pair&
p) { fn(
p); });
543 return Iter::MakeBegin(&fTable);
547 return Iter::MakeEnd(&fTable);
555template <
typename T,
typename HashT = SkGoodHash>
569 fTable.
resize(vals.size() * 5 / 3);
570 for (
const T& val : vals) {
592 void add(
T item) { fTable.
set(std::move(item)); }
599 const T*
find(
const T& item)
const {
return fTable.
find(item); }
608 template <
typename Fn>
609 void foreach (Fn&& fn)
const {
615 static const T& GetKey(
const T& item) {
return item; }
616 static auto Hash(
const T& item) {
return HashT()(item); }
623 return Iter::MakeBegin(&fTable);
627 return Iter::MakeEnd(&fTable);
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
static uint32_t hash(const SkShaderBase::GradientInfo &v)
void swap(sk_sp< T > &a, sk_sp< T > &b)
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
static constexpr bool SkToBool(const T &x)
THashMap< K, V, HashK > & operator=(const THashMap< K, V, HashK > &that)=default
void swap(THashMap &that)
void swap(THashMap &&that)
V & operator[](const K &key)
THashMap< K, V, HashK > & operator=(THashMap< K, V, HashK > &&that)=default
size_t approxBytesUsed() const
V * find(const K &key) const
THashMap(const THashMap< K, V, HashK > &that)=default
THashMap(THashMap< K, V, HashK > &&that)=default
bool removeIfExists(const K &key)
void remove(const K &key)
THashMap(std::initializer_list< Pair > pairs)
typename THashTable< Pair, K >::template Iter< std::pair< K, V > > Iter
THashSet(THashSet< T, HashT > &&that)=default
THashSet< T, HashT > & operator=(THashSet< T, HashT > &&that)=default
const T * find(const T &item) const
THashSet(std::initializer_list< T > vals)
size_t approxBytesUsed() const
bool contains(const T &item) const
THashSet< T, HashT > & operator=(const THashSet< T, HashT > &that)=default
typename THashTable< T, T, Traits >::template Iter< T > Iter
void remove(const T &item)
void swap(THashSet &that)
void swap(THashSet &&that)
THashSet(const THashSet< T, HashT > &that)=default
bool operator==(const Iter &that) const
const SlotVal * operator->() const
bool operator!=(const Iter &that) const
static Iter MakeEnd(const TTable *table)
const SlotVal & operator*() const
Iter(const TTable *table, int slot)
static Iter MakeBegin(const TTable *table)
void remove(const K &key)
void swap(THashTable &that)
THashTable & operator=(THashTable &&that)
void resize(int capacity)
THashTable(const THashTable &that)
THashTable(THashTable &&that)
THashTable & operator=(const THashTable &that)
T * find(const K &key) const
T findOrNull(const K &key) const
size_t approxBytesUsed() const
bool removeIfExists(const K &key)
void swap(THashTable &&that)
EMSCRIPTEN_KEEPALIVE void empty()
T __attribute__((ext_vector_type(N))) V
static uint32_t Hash(uint32_t key)
constexpr Color operator*(T value, const Color &c)
static auto Hash(const K &key)
static const K & GetKey(const Pair &p)