// 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 "net/third_party/quiche/src/quic/platform/api/quic_aligned.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"

namespace quic {

template <typename T>
class QuicArenaScopedPtr {
  static_assert(QUIC_ALIGN_OF(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();
    }
  }
  DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(value) & kFromArenaMask);
  value_ = value;
}

template <typename T>
QuicArenaScopedPtr<T>::QuicArenaScopedPtr(void* value, ConstructFrom from_arena)
    : value_(value) {
  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_
