/*
 * Copyright (C) 2014 Google 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER OR 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.
 */

#ifndef SKY_ENGINE_WTF_RAWPTR_H_
#define SKY_ENGINE_WTF_RAWPTR_H_

#include <stdint.h>
#include <algorithm>

#include "sky/engine/wtf/HashTableDeletedValueType.h"

// RawPtr is a simple wrapper for a raw pointer that provides the
// interface (get, clear) of other pointer types such as RefPtr,
// Persistent and Member. This is used for the Blink garbage
// collection work in order to be able to write shared code that will
// use reference counting or garbage collection based on a
// compile-time flag.

namespace WTF {

template<typename T>
class RawPtr {
    WTF_DISALLOW_CONSTRUCTION_FROM_ZERO(RawPtr);
    WTF_DISALLOW_ZERO_ASSIGNMENT(RawPtr);
public:
    RawPtr()
    {
#if ENABLE(ASSERT)
        m_ptr = reinterpret_cast<T*>(rawPtrZapValue);
#endif
    }
    RawPtr(std::nullptr_t) : m_ptr(0) { }
    RawPtr(T* ptr) : m_ptr(ptr) { }
    explicit RawPtr(T& reference) : m_ptr(&reference) { }
    RawPtr(const RawPtr& other)
        : m_ptr(other.get())
    {
    }

    template<typename U>
    RawPtr(const RawPtr<U>& other)
        : m_ptr(other.get())
    {
    }

    // Hash table deleted values, which are only constructed and never copied or destroyed.
    RawPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
    bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }

    T* get() const { return m_ptr; }
    void clear() { m_ptr = 0; }
    // FIXME: oilpan: Remove release and leakRef once we remove RefPtr.
    RawPtr<T> release()
    {
        RawPtr<T> tmp = m_ptr;
        m_ptr = 0;
        return tmp;
    }
    T* leakRef()
    {
        T* ptr = m_ptr;
        m_ptr = 0;
        return ptr;
    }
    T* leakPtr()
    {
        T* ptr = m_ptr;
        m_ptr = 0;
        return ptr;
    }

    template<typename U>
    RawPtr& operator=(U* ptr)
    {
        m_ptr = ptr;
        return *this;
    }

    template<typename U>
    RawPtr& operator=(RawPtr<U> ptr)
    {
        m_ptr = ptr.get();
        return *this;
    }

    RawPtr& operator=(std::nullptr_t)
    {
        m_ptr = 0;
        return *this;
    }

    operator T*() const { return m_ptr; }
    T& operator*() const { return *m_ptr; }
    T* operator->() const { return m_ptr; }
    bool operator!() const { return !m_ptr; }

    void swap(RawPtr& o)
    {
        std::swap(m_ptr, o.m_ptr);
    }

    static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }

private:
    static const uintptr_t rawPtrZapValue = 0x3a3a3a3a;
    T* m_ptr;
};

template<typename T, typename U> inline RawPtr<T> static_pointer_cast(const RawPtr<U>& p)
{
    return RawPtr<T>(static_cast<T*>(p.get()));
}

template<typename T> inline T* getPtr(const RawPtr<T>& p)
{
    return p.get();
}

} // namespace WTF

using WTF::RawPtr;

#endif  // SKY_ENGINE_WTF_RAWPTR_H_
