/*
 * Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>.
 * Copyright (C) 2019 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include <wtf/HashSet.h>
#include <wtf/text/StringHash.h>
#include <wtf/text/SymbolImpl.h>
#include <wtf/text/WTFString.h>

namespace WTF {

// Since StringImpl* used for Symbol uid doesn't have a hash value reflecting the string content,
// to compare with an external string in string contents, introduce SymbolRegistryKey.
// SymbolRegistryKey holds a hash value reflecting the string content additionally.
class SymbolRegistryKey {
public:
    SymbolRegistryKey() = default;
    explicit SymbolRegistryKey(StringImpl* uid);
    SymbolRegistryKey(WTF::HashTableDeletedValueType);

    unsigned hash() const { return m_hash; }
    StringImpl* impl() const { return m_impl; }

    bool isHashTableDeletedValue() const { return m_impl == hashTableDeletedValue(); }

private:
    static StringImpl* hashTableDeletedValue() { return reinterpret_cast<StringImpl*>(-1); }

    StringImpl* m_impl { nullptr };
    unsigned m_hash { 0 };
};

template<typename> struct DefaultHash;
template<> struct DefaultHash<SymbolRegistryKey> : StringHash {
    static unsigned hash(const SymbolRegistryKey& key)
    {
        return key.hash();
    }
    static bool equal(const SymbolRegistryKey& a, const SymbolRegistryKey& b)
    {
        return StringHash::equal(a.impl(), b.impl());
    }
};

template<> struct HashTraits<SymbolRegistryKey> : SimpleClassHashTraits<SymbolRegistryKey> {
    static constexpr bool hasIsEmptyValueFunction = true;
    static bool isEmptyValue(const SymbolRegistryKey& key)
    {
        return key.impl() == nullptr;
    }
};

class SymbolRegistry {
    WTF_MAKE_FAST_ALLOCATED;
    WTF_MAKE_NONCOPYABLE(SymbolRegistry);
public:
    enum class Type : uint8_t { PublicSymbol, PrivateSymbol };
    WTF_EXPORT_PRIVATE SymbolRegistry(Type = Type::PublicSymbol);
    WTF_EXPORT_PRIVATE ~SymbolRegistry();

    WTF_EXPORT_PRIVATE Ref<RegisteredSymbolImpl> symbolForKey(const String&);

    void remove(RegisteredSymbolImpl&);

private:
    HashSet<SymbolRegistryKey> m_table;
    Type m_symbolType;
};

inline SymbolRegistryKey::SymbolRegistryKey(StringImpl* uid)
    : m_impl(uid)
{
    if (uid->isSymbol()) {
        if (uid->is8Bit())
            m_hash = StringHasher::computeHashAndMaskTop8Bits(uid->characters8(), uid->length());
        else
            m_hash = StringHasher::computeHashAndMaskTop8Bits(uid->characters16(), uid->length());
    } else
        m_hash = uid->hash();
}

inline SymbolRegistryKey::SymbolRegistryKey(WTF::HashTableDeletedValueType)
    : m_impl(hashTableDeletedValue())
{
}

}
