// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#pragma once

#include <stdlib.h>
#include <fbl/alloc_checker.h>
#include <fbl/macros.h>
#include <fbl/recycler.h>
#include <fbl/type_support.h>
#include <zircon/compiler.h>

#include <type_traits>
#include <utility>

namespace fbl {

// This is a simplified version of std::unique_ptr<> that can automatically
// dispose a pointer when it goes out of scope.
//
// Compared to std::unique_ptr, it does not support custom deleters and has
// restrictive type conversion semantics.
template <typename T>
class unique_ptr {
public:
    constexpr unique_ptr() : ptr_(nullptr) {}
    constexpr unique_ptr(decltype(nullptr)) : unique_ptr() {}

    explicit unique_ptr(T* t) : ptr_(t) { }

    ~unique_ptr() {
        recycle(ptr_);
    }

    unique_ptr(unique_ptr&& o) : ptr_(o.release()) {}
    unique_ptr& operator=(unique_ptr&& o) {
        reset(o.release());
        return *this;
    }

    unique_ptr& operator=(decltype(nullptr)) {
        reset();
        return *this;
    }

    // Comparison against nullptr operators (of the form, myptr == nullptr).
    bool operator==(decltype(nullptr)) const { return (ptr_ == nullptr); }
    bool operator!=(decltype(nullptr)) const { return (ptr_ != nullptr); }

    // Comparison against other unique_ptr<>'s.
    bool operator==(const unique_ptr& o) const { return ptr_ == o.ptr_; }
    bool operator!=(const unique_ptr& o) const { return ptr_ != o.ptr_; }
    bool operator< (const unique_ptr& o) const { return ptr_ <  o.ptr_; }
    bool operator<=(const unique_ptr& o) const { return ptr_ <= o.ptr_; }
    bool operator> (const unique_ptr& o) const { return ptr_ >  o.ptr_; }
    bool operator>=(const unique_ptr& o) const { return ptr_ >= o.ptr_; }

    // move semantics only
    DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(unique_ptr);

    T* release() __WARN_UNUSED_RESULT {
        T* t = ptr_;
        ptr_ = nullptr;
        return t;
    }
    void reset(T* t = nullptr) {
        recycle(ptr_);
        ptr_ = t;
    }
    void swap(unique_ptr& other) {
        T* t = ptr_;
        ptr_ = other.ptr_;
        other.ptr_ = t;
    }

    T* get() const {
        return ptr_;
    }

    explicit operator bool() const {
        return static_cast<bool>(ptr_);
    }

    T& operator*() const {
        return *ptr_;
    }
    T* operator->() const {
        return ptr_;
    }

    // Implicit upcasting via construction.
    //
    // We permit implicit casting of a unique_ptr<U> to a unique_ptr<T> as long
    // as the following conditions both hold:
    //
    // 1) U* is implicitly convertible to a T*
    // 2) T is the same as const U, neither T nor U are a class/struct type, or
    //    both T and U are class/struct types and T has a virtual destructor.
    //
    // Note: we do this via an implicit converting constructor (instead of a
    // user-defined conversion operator) so that we can demand that we are
    // converting from a properly moved rvalue reference.
    //
    // Also Note:  This behavior is *not* the same as std::unique_ptr.
    // std::unique_ptr only cares about point #1.  Its behavior emulates raw
    // pointers and will gladly let you implicitly convert a class U to a class
    // T as an implicit upcast regardless of whether or not T has a virtual
    // destructor.
    template <typename U,
              typename = typename std::enable_if<is_convertible_pointer<U*, T*>::value>::type>
    unique_ptr(unique_ptr<U>&& o) : ptr_(o.release()) {
        static_assert(is_same<T, const U>::value ||
                (is_class<T>::value == is_class<U>::value &&
                     (!is_class<T>::value || has_virtual_destructor<T>::value)),
                "Cannot convert unique_ptr<U> to unique_ptr<T> unless T is the same "
                "as const U, neither T nor U are class/struct types, or T has a "
                "virtual destructor");
    }

private:
    static void recycle(T* ptr) {
        enum { type_must_be_complete = sizeof(T) };
        if (ptr) {
            if (::fbl::internal::has_fbl_recycle<T>::value) {
                ::fbl::internal::recycler<T>::recycle(ptr);
            } else {
                delete ptr;
            }
        }
    }

    T* ptr_;
};

template <typename T>
class unique_ptr<T[]> {
public:
    constexpr unique_ptr() : ptr_(nullptr) {}
    constexpr unique_ptr(decltype(nullptr)) : unique_ptr() {}

    explicit unique_ptr(T* array) : ptr_(array) {}

    unique_ptr(unique_ptr&& other) : ptr_(other.release()) {}

    ~unique_ptr() {
        enum { type_must_be_complete = sizeof(T) };
        if (ptr_) delete[] ptr_;
    }

    unique_ptr& operator=(unique_ptr&& o) {
        reset(o.release());
        return *this;
    }

    // Comparison against nullptr operators (of the form, myptr == nullptr).
    bool operator==(decltype(nullptr)) const { return (ptr_ == nullptr); }
    bool operator!=(decltype(nullptr)) const { return (ptr_ != nullptr); }

    // Comparison against other unique_ptr<>'s.
    bool operator==(const unique_ptr& o) const { return ptr_ == o.ptr_; }
    bool operator!=(const unique_ptr& o) const { return ptr_ != o.ptr_; }
    bool operator< (const unique_ptr& o) const { return ptr_ <  o.ptr_; }
    bool operator<=(const unique_ptr& o) const { return ptr_ <= o.ptr_; }
    bool operator> (const unique_ptr& o) const { return ptr_ >  o.ptr_; }
    bool operator>=(const unique_ptr& o) const { return ptr_ >= o.ptr_; }

    unique_ptr(const unique_ptr& o) = delete;
    unique_ptr& operator=(const unique_ptr& o) = delete;

    T* release() __WARN_UNUSED_RESULT {
        T* t = ptr_;
        ptr_ = nullptr;
        return t;
    }
    void reset(T* t = nullptr) {
        enum { type_must_be_complete = sizeof(T) };
        if (ptr_) delete[] ptr_;
        ptr_ = t;
    }
    void swap(unique_ptr& other) {
        T* t = ptr_;
        ptr_ = other.ptr_;
        other.ptr_ = t;
    }

    T* get() const {
        return ptr_;
    }

    explicit operator bool() const {
        return static_cast<bool>(ptr_);
    }
    T& operator[](size_t i) const {
        return ptr_[i];
    }

private:
    T* ptr_;
};

// Comparison against nullptr operators (of the form, nullptr == myptr) for T and T[]
template <typename T>
static inline bool operator==(decltype(nullptr), const unique_ptr<T>& ptr) {
    return (ptr.get() == nullptr);
}

template <typename T>
static inline bool operator!=(decltype(nullptr), const unique_ptr<T>& ptr) {
    return (ptr.get() != nullptr);
}

namespace internal {

template <typename T>
struct unique_type {
    using single = unique_ptr<T>;
};

template <typename T>
struct unique_type<T[]> {
    using incomplete_array = unique_ptr<T[]>;
};

} // namespace internal

// Constructs a new object and assigns it to a unique_ptr.
template <typename T, typename... Args>
typename internal::unique_type<T>::single
make_unique(Args&&... args) {
    return unique_ptr<T>(new T(std::forward<Args>(args)...));
}

template <typename T, typename... Args>
typename internal::unique_type<T>::incomplete_array
make_unique(size_t size) {
    using single_type = typename remove_extent<T>::type;
    return unique_ptr<single_type[]>(new single_type[size]());
}

template <typename T, typename... Args>
typename internal::unique_type<T>::single
make_unique_checked(AllocChecker* ac, Args&&... args) {
    return unique_ptr<T>(new (ac) T(std::forward<Args>(args)...));
}

}  // namespace fbl
