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

// unique_ptr-style pointer that stores values that may be from an arena. Takes
// up the same storage as the platform's native pointer type. Takes ownership
// of the value it's constructed with; if holding a value in an arena, and the
// type has a non-trivial destructor, the arena must outlive the
// QuicArenaScopedPtr. Does not support array overloads.

#ifndef QUICHE_QUIC_CORE_QUIC_ARENA_SCOPED_PTR_H_
#define QUICHE_QUIC_CORE_QUIC_ARENA_SCOPED_PTR_H_

#include <cstdint>  // for uintptr_t

#include "quiche/quic/platform/api/quic_export.h"
#include "quiche/quic/platform/api/quic_logging.h"

namespace quic {

template <typename T>
class QUIC_NO_EXPORT QuicArenaScopedPtr {
  static_assert(alignof(T*) > 1,
                "QuicArenaScopedPtr can only store objects that are aligned to "
                "greater than 1 byte.");

 public:
  // Constructs an empty QuicArenaScopedPtr.
  QuicArenaScopedPtr();

  // Constructs a QuicArenaScopedPtr referencing the heap-allocated memory
  // provided.
  explicit QuicArenaScopedPtr(T* value);

  template <typename U>
  QuicArenaScopedPtr(QuicArenaScopedPtr<U>&& other);  // NOLINT
  template <typename U>
  QuicArenaScopedPtr& operator=(QuicArenaScopedPtr<U>&& other);
  ~QuicArenaScopedPtr();

  // Returns a pointer to the value.
  T* get() const;

  // Returns a reference to the value.
  T& operator*() const;

  // Returns a pointer to the value.
  T* operator->() const;

  // Swaps the value of this pointer with |other|.
  void swap(QuicArenaScopedPtr& other);

  // Resets the held value to |value|.
  void reset(T* value = nullptr);

  // Returns true if |this| came from an arena. Primarily exposed for testing
  // and assertions.
  bool is_from_arena();

 private:
  // Friends with other derived types of QuicArenaScopedPtr, to support the
  // derived-types case.
  template <typename U>
  friend class QuicArenaScopedPtr;
  // Also befriend all known arenas, only to prevent misuse.
  template <uint32_t ArenaSize>
  friend class QuicOneBlockArena;

  // Tag to denote that a QuicArenaScopedPtr is being explicitly created by an
  // arena.
  enum class ConstructFrom { kHeap, kArena };

  // Constructs a QuicArenaScopedPtr with the given representation.
  QuicArenaScopedPtr(void* value, ConstructFrom from);
  QuicArenaScopedPtr(const QuicArenaScopedPtr&) = delete;
  QuicArenaScopedPtr& operator=(const QuicArenaScopedPtr&) = delete;

  // Low-order bits of value_ that determine if the pointer came from an arena.
  static const uintptr_t kFromArenaMask = 0x1;

  // Every platform we care about has at least 4B aligned integers, so store the
  // is_from_arena bit in the least significant bit.
  void* value_;
};

template <typename T>
bool operator==(const QuicArenaScopedPtr<T>& left,
                const QuicArenaScopedPtr<T>& right) {
  return left.get() == right.get();
}

template <typename T>
bool operator!=(const QuicArenaScopedPtr<T>& left,
                const QuicArenaScopedPtr<T>& right) {
  return left.get() != right.get();
}

template <typename T>
bool operator==(std::nullptr_t, const QuicArenaScopedPtr<T>& right) {
  return nullptr == right.get();
}

template <typename T>
bool operator!=(std::nullptr_t, const QuicArenaScopedPtr<T>& right) {
  return nullptr != right.get();
}

template <typename T>
bool operator==(const QuicArenaScopedPtr<T>& left, std::nullptr_t) {
  return left.get() == nullptr;
}

template <typename T>
bool operator!=(const QuicArenaScopedPtr<T>& left, std::nullptr_t) {
  return left.get() != nullptr;
}

template <typename T>
QuicArenaScopedPtr<T>::QuicArenaScopedPtr() : value_(nullptr) {}

template <typename T>
QuicArenaScopedPtr<T>::QuicArenaScopedPtr(T* value)
    : QuicArenaScopedPtr(value, ConstructFrom::kHeap) {}

template <typename T>
template <typename U>
QuicArenaScopedPtr<T>::QuicArenaScopedPtr(QuicArenaScopedPtr<U>&& other)
    : value_(other.value_) {
  static_assert(
      std::is_base_of<T, U>::value || std::is_same<T, U>::value,
      "Cannot construct QuicArenaScopedPtr; type is not derived or same.");
  other.value_ = nullptr;
}

template <typename T>
template <typename U>
QuicArenaScopedPtr<T>& QuicArenaScopedPtr<T>::operator=(
    QuicArenaScopedPtr<U>&& other) {
  static_assert(
      std::is_base_of<T, U>::value || std::is_same<T, U>::value,
      "Cannot assign QuicArenaScopedPtr; type is not derived or same.");
  swap(other);
  return *this;
}

template <typename T>
QuicArenaScopedPtr<T>::~QuicArenaScopedPtr() {
  reset();
}

template <typename T>
T* QuicArenaScopedPtr<T>::get() const {
  return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(value_) &
                              ~kFromArenaMask);
}

template <typename T>
T& QuicArenaScopedPtr<T>::operator*() const {
  return *get();
}

template <typename T>
T* QuicArenaScopedPtr<T>::operator->() const {
  return get();
}

template <typename T>
void QuicArenaScopedPtr<T>::swap(QuicArenaScopedPtr& other) {
  using std::swap;
  swap(value_, other.value_);
}

template <typename T>
bool QuicArenaScopedPtr<T>::is_from_arena() {
  return (reinterpret_cast<uintptr_t>(value_) & kFromArenaMask) != 0;
}

template <typename T>
void QuicArenaScopedPtr<T>::reset(T* value) {
  if (value_ != nullptr) {
    if (is_from_arena()) {
      // Manually invoke the destructor.
      get()->~T();
    } else {
      delete get();
    }
  }
  QUICHE_DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(value) & kFromArenaMask);
  value_ = value;
}

template <typename T>
QuicArenaScopedPtr<T>::QuicArenaScopedPtr(void* value, ConstructFrom from_arena)
    : value_(value) {
  QUICHE_DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(value_) & kFromArenaMask);
  switch (from_arena) {
    case ConstructFrom::kHeap:
      break;
    case ConstructFrom::kArena:
      value_ = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(value_) |
                                       QuicArenaScopedPtr<T>::kFromArenaMask);
      break;
  }
}

}  // namespace quic

#endif  // QUICHE_QUIC_CORE_QUIC_ARENA_SCOPED_PTR_H_
