/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkTDynamicHash_DEFINED
#define SkTDynamicHash_DEFINED

// This is now a simple API wrapper around SkTHashTable<T*>;
// please just use SkTHash{Map,Set,Table} directly for new code.
#include "src/core/SkTHash.h"

// Traits requires:
//   static const Key& GetKey(const T&) { ... }
//   static uint32_t Hash(const Key&) { ... }
// We'll look on T for these by default, or you can pass a custom Traits type.
template <typename T,
          typename Key,
          typename Traits = T>
class SkTDynamicHash {
public:
    SkTDynamicHash() {}

    // It is not safe to call set() or remove() while iterating with either foreach().
    // If you mutate the entries be very careful not to change the Key.

    template <typename Fn>  // f(T*)
    void foreach(Fn&& fn) {
        fTable.foreach([&](T** entry) { fn(*entry); });
    }
    template <typename Fn>  // f(T) or f(const T&)
    void foreach(Fn&& fn) const {
        fTable.foreach([&](T* entry) { fn(*entry); });
    }

    int count() const { return fTable.count(); }

    size_t approxBytesUsed() const { return fTable.approxBytesUsed(); }

    T* find(const Key& key) const { return fTable.findOrNull(key); }

    void add(T* entry) { fTable.set(entry); }
    void remove(const Key& key) { fTable.remove(key); }

    void rewind() { fTable.reset(); }
    void reset () { fTable.reset(); }

private:
    struct AdaptedTraits {
        static const Key& GetKey(T* entry) { return Traits::GetKey(*entry); }
        static uint32_t Hash(const Key& key) { return Traits::Hash(key); }
    };
    SkTHashTable<T*, Key, AdaptedTraits> fTable;
};

#endif
