/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
#ifndef TinyPtrSet_h
#define TinyPtrSet_h

#include <wtf/Assertions.h>
#include <wtf/FastMalloc.h>

namespace JSC { namespace DFG {
class StructureAbstractValue;
} } // namespace JSC::DFG

namespace WTF {

// FIXME: This currently only works for types that are pointer-like: they should have the size
// of a pointer and like a pointer they should not have assignment operators, copy constructors,
// non-trivial default constructors, and non-trivial destructors. It may be possible to lift all
// of these restrictions. If we succeeded then this should be renamed to just TinySet.
// https://bugs.webkit.org/show_bug.cgi?id=145741

template<typename T>
class TinyPtrSet {
    static_assert(sizeof(T) == sizeof(void*), "It's in the title of the class.");
public:
    TinyPtrSet()
        : m_pointer(0)
    {
        setEmpty();
    }
    
    TinyPtrSet(T element)
        : m_pointer(0)
    {
        set(element);
    }
    
    ALWAYS_INLINE TinyPtrSet(const TinyPtrSet& other)
        : m_pointer(0)
    {
        copyFrom(other);
    }
    
    ALWAYS_INLINE TinyPtrSet& operator=(const TinyPtrSet& other)
    {
        if (this == &other)
            return *this;
        deleteListIfNecessary();
        copyFrom(other);
        return *this;
    }
    
    ~TinyPtrSet()
    {
        deleteListIfNecessary();
    }
    
    void clear()
    {
        deleteListIfNecessary();
        setEmpty();
    }
    
    // Returns the only entry if the array has exactly one entry.
    T onlyEntry() const
    {
        if (isThin())
            return singleEntry();
        OutOfLineList* list = this->list();
        if (list->m_length != 1)
            return T();
        return list->list()[0];
    }
    
    bool isEmpty() const
    {
        bool result = isThin() && !singleEntry();
        if (result)
            ASSERT(m_pointer != reservedValue);
        return result;
    }
    
    // Returns true if the value was added, or false if the value was already there.
    bool add(T value)
    {
        ASSERT(value);
        if (isThin()) {
            if (singleEntry() == value)
                return false;
            if (!singleEntry()) {
                set(value);
                return true;
            }
            
            OutOfLineList* list = OutOfLineList::create(defaultStartingSize);
            list->m_length = 2;
            list->list()[0] = singleEntry();
            list->list()[1] = value;
            set(list);
            return true;
        }
        
        return addOutOfLine(value);
    }
    
    bool remove(T value)
    {
        if (isThin()) {
            if (singleEntry() == value) {
                setEmpty();
                return true;
            }
            return false;
        }
        
        OutOfLineList* list = this->list();
        for (unsigned i = 0; i < list->m_length; ++i) {
            if (list->list()[i] != value)
                continue;
            list->list()[i] = list->list()[--list->m_length];
            if (!list->m_length) {
                OutOfLineList::destroy(list);
                setEmpty();
            }
            return true;
        }
        return false;
    }
    
    bool contains(T value) const
    {
        if (isThin())
            return singleEntry() == value;
        return containsOutOfLine(value);
    }
    
    bool merge(const TinyPtrSet& other)
    {
        if (other.isThin()) {
            if (other.singleEntry())
                return add(other.singleEntry());
            return false;
        }
        
        OutOfLineList* list = other.list();
        if (list->m_length >= 2) {
            if (isThin()) {
                OutOfLineList* myNewList = OutOfLineList::create(
                    list->m_length + !!singleEntry());
                if (singleEntry()) {
                    myNewList->m_length = 1;
                    myNewList->list()[0] = singleEntry();
                }
                set(myNewList);
            }
            bool changed = false;
            for (unsigned i = 0; i < list->m_length; ++i)
                changed |= addOutOfLine(list->list()[i]);
            return changed;
        }
        
        ASSERT(list->m_length);
        return add(list->list()[0]);
    }
    
    template<typename Functor>
    void forEach(const Functor& functor) const
    {
        if (isThin()) {
            if (!singleEntry())
                return;
            functor(singleEntry());
            return;
        }
        
        OutOfLineList* list = this->list();
        for (unsigned i = 0; i < list->m_length; ++i)
            functor(list->list()[i]);
    }
        
    template<typename Functor>
    void genericFilter(const Functor& functor)
    {
        if (isThin()) {
            if (!singleEntry())
                return;
            if (functor(singleEntry()))
                return;
            clear();
            return;
        }
        
        OutOfLineList* list = this->list();
        for (unsigned i = 0; i < list->m_length; ++i) {
            if (functor(list->list()[i]))
                continue;
            list->list()[i--] = list->list()[--list->m_length];
        }
        if (!list->m_length)
            clear();
    }
        
    void filter(const TinyPtrSet& other)
    {
        if (other.isThin()) {
            if (!other.singleEntry() || !contains(other.singleEntry()))
                clear();
            else {
                clear();
                set(other.singleEntry());
            }
            return;
        }
        
        genericFilter([&] (T value) { return other.containsOutOfLine(value); });
    }
    
    void exclude(const TinyPtrSet& other)
    {
        if (other.isThin()) {
            if (other.singleEntry())
                remove(other.singleEntry());
            return;
        }
        
        genericFilter([&] (T value) { return !other.containsOutOfLine(value); });
    }
    
    bool isSubsetOf(const TinyPtrSet& other) const
    {
        if (isThin()) {
            if (!singleEntry())
                return true;
            return other.contains(singleEntry());
        }
        
        if (other.isThin()) {
            if (!other.singleEntry())
                return false;
            OutOfLineList* list = this->list();
            if (list->m_length >= 2)
                return false;
            if (list->list()[0] == other.singleEntry())
                return true;
            return false;
        }
        
        OutOfLineList* list = this->list();
        for (unsigned i = 0; i < list->m_length; ++i) {
            if (!other.containsOutOfLine(list->list()[i]))
                return false;
        }
        return true;
    }
    
    bool isSupersetOf(const TinyPtrSet& other) const
    {
        return other.isSubsetOf(*this);
    }
    
    bool overlaps(const TinyPtrSet& other) const
    {
        if (isThin()) {
            if (!singleEntry())
                return false;
            return other.contains(singleEntry());
        }
        
        if (other.isThin()) {
            if (!other.singleEntry())
                return false;
            return containsOutOfLine(other.singleEntry());
        }
        
        OutOfLineList* list = this->list();
        for (unsigned i = 0; i < list->m_length; ++i) {
            if (other.containsOutOfLine(list->list()[i]))
                return true;
        }
        return false;
    }
    
    size_t size() const
    {
        if (isThin())
            return !!singleEntry();
        return list()->m_length;
    }
    
    T at(size_t i) const
    {
        if (isThin()) {
            ASSERT(!i);
            ASSERT(singleEntry());
            return singleEntry();
        }
        ASSERT(i < list()->m_length);
        return list()->list()[i];
    }
    
    T operator[](size_t i) const { return at(i); }
    
    T last() const
    {
        if (isThin()) {
            ASSERT(singleEntry());
            return singleEntry();
        }
        return list()->list()[list()->m_length - 1];
    }
    
    class iterator {
    public:
        iterator()
            : m_set(nullptr)
            , m_index(0)
        {
        }
        
        iterator(const TinyPtrSet* set, size_t index)
            : m_set(set)
            , m_index(index)
        {
        }
        
        T operator*() const { return m_set->at(m_index); }
        iterator& operator++()
        {
            m_index++;
            return *this;
        }
        bool operator==(const iterator& other) const { return m_index == other.m_index; }
        bool operator!=(const iterator& other) const { return !(*this == other); }
        
    private:
        const TinyPtrSet* m_set;
        size_t m_index;
    };
    
    iterator begin() const { return iterator(this, 0); }
    iterator end() const { return iterator(this, size()); }
    
    bool operator==(const TinyPtrSet& other) const
    {
        if (size() != other.size())
            return false;
        return isSubsetOf(other);
    }
    
private:
    friend class JSC::DFG::StructureAbstractValue;

    static const uintptr_t fatFlag = 1;
    static const uintptr_t reservedFlag = 2;
    static const uintptr_t flags = fatFlag | reservedFlag;
    static const uintptr_t reservedValue = 4;

    static const unsigned defaultStartingSize = 4;
    
    bool addOutOfLine(T value)
    {
        OutOfLineList* list = this->list();
        for (unsigned i = 0; i < list->m_length; ++i) {
            if (list->list()[i] == value)
                return false;
        }
        
        if (list->m_length < list->m_capacity) {
            list->list()[list->m_length++] = value;
            return true;
        }
        
        OutOfLineList* newList = OutOfLineList::create(list->m_capacity * 2);
        newList->m_length = list->m_length + 1;
        for (unsigned i = list->m_length; i--;)
            newList->list()[i] = list->list()[i];
        newList->list()[list->m_length] = value;
        OutOfLineList::destroy(list);
        set(newList);
        return true;
    }
    
    bool containsOutOfLine(T value) const
    {
        OutOfLineList* list = this->list();
        for (unsigned i = 0; i < list->m_length; ++i) {
            if (list->list()[i] == value)
                return true;
        }
        return false;
    }
    
    ALWAYS_INLINE void copyFrom(const TinyPtrSet& other)
    {
        if (other.isThin() || other.m_pointer == reservedValue) {
            bool value = getReservedFlag();
            m_pointer = other.m_pointer;
            setReservedFlag(value);
            return;
        }
        copyFromOutOfLine(other);
    }
    
    NEVER_INLINE void copyFromOutOfLine(const TinyPtrSet& other)
    {
        ASSERT(!other.isThin() && other.m_pointer != reservedValue);
        OutOfLineList* otherList = other.list();
        OutOfLineList* myList = OutOfLineList::create(otherList->m_length);
        myList->m_length = otherList->m_length;
        for (unsigned i = otherList->m_length; i--;)
            myList->list()[i] = otherList->list()[i];
        set(myList);
    }
    
    class OutOfLineList {
    public:
        static OutOfLineList* create(unsigned capacity)
        {
            return new (NotNull, fastMalloc(sizeof(OutOfLineList) + capacity * sizeof(T))) OutOfLineList(0, capacity);
        }
        
        static void destroy(OutOfLineList* list)
        {
            fastFree(list);
        }
        
        T* list() { return bitwise_cast<T*>(this + 1); }
        
        OutOfLineList(unsigned length, unsigned capacity)
            : m_length(length)
            , m_capacity(capacity)
        {
        }

        unsigned m_length;
        unsigned m_capacity;
    };
    
    ALWAYS_INLINE void deleteListIfNecessary()
    {
        if (!isThin()) {
            ASSERT(m_pointer != reservedValue);
            OutOfLineList::destroy(list());
        }
    }
    
    bool isThin() const { return !(m_pointer & fatFlag); }
    
    void* pointer() const
    {
        return bitwise_cast<void*>(m_pointer & ~flags);
    }
    
    T singleEntry() const
    {
        ASSERT(isThin());
        return bitwise_cast<T>(pointer());
    }
    
    OutOfLineList* list() const
    {
        ASSERT(!isThin());
        return static_cast<OutOfLineList*>(pointer());
    }
    
    void set(T value)
    {
        set(bitwise_cast<uintptr_t>(value), true);
    }
    void set(OutOfLineList* list)
    {
        set(bitwise_cast<uintptr_t>(list), false);
    }
    void setEmpty()
    {
        set(0, true);
    }
    void set(uintptr_t pointer, bool singleEntry)
    {
        m_pointer = pointer | (singleEntry ? 0 : fatFlag) | (m_pointer & reservedFlag);
    }
    bool getReservedFlag() const { return m_pointer & reservedFlag; }
    void setReservedFlag(bool value)
    {
        if (value)
            m_pointer |= reservedFlag;
        else
            m_pointer &= ~reservedFlag;
    }
    
    uintptr_t m_pointer;
};

} // namespace WTF

using WTF::TinyPtrSet;

#endif // TinyPtrSet_h

