// 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.

#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_REFERENCE_COUNTED_H_
#define QUICHE_COMMON_PLATFORM_API_QUICHE_REFERENCE_COUNTED_H_

#include "quiche_platform_impl/quiche_reference_counted_impl.h"

#include "absl/base/nullability.h"
#include "quiche/common/platform/api/quiche_export.h"

namespace quiche {

// Base class for explicitly reference-counted objects in QUIC.
class QUICHE_EXPORT QuicheReferenceCounted : public QuicheReferenceCountedImpl {
 public:
  QuicheReferenceCounted() {}

 protected:
  ~QuicheReferenceCounted() override {}
};

// A class representing a reference counted pointer in QUIC.
//
// Construct or initialize QuicheReferenceCountedPointer from raw pointer. Here
// raw pointer MUST be a newly created object. Reference count of a newly
// created object is undefined, but that will be 1 after being added to
// QuicheReferenceCountedPointer.
// QuicheReferenceCountedPointer is used as a local variable.
// QuicheReferenceCountedPointer<T> r_ptr(new T());
// or, equivalently:
// QuicheReferenceCountedPointer<T> r_ptr;
// T* p = new T();
// r_ptr = T;
//
// QuicheReferenceCountedPointer is used as a member variable:
// MyClass::MyClass() : r_ptr(new T()) {}
//
// This is WRONG, since *p is not guaranteed to be newly created:
// MyClass::MyClass(T* p) : r_ptr(p) {}
//
// Given an existing QuicheReferenceCountedPointer, create a duplicate that has
// its own reference on the object:
// QuicheReferenceCountedPointer<T> r_ptr_b(r_ptr_a);
// or, equivalently:
// QuicheReferenceCountedPointer<T> r_ptr_b = r_ptr_a;
//
// Given an existing QuicheReferenceCountedPointer, create a
// QuicheReferenceCountedPointer that adopts the reference:
// QuicheReferenceCountedPointer<T> r_ptr_b(std::move(r_ptr_a));
// or, equivalently:
// QuicheReferenceCountedPointer<T> r_ptr_b = std::move(r_ptr_a);

template <class T>
class QUICHE_NO_EXPORT ABSL_NULLABILITY_COMPATIBLE
    QuicheReferenceCountedPointer {
 public:
  // For compatibility with googletest's `Pointee` matcher.
  using element_type = T;

  QuicheReferenceCountedPointer() = default;

  // Constructor from raw pointer |p|. This guarantees that the reference count
  // of *p is 1. This should be only called when a new object is created.
  // Calling this on an already existent object does not increase its reference
  // count.
  explicit QuicheReferenceCountedPointer(T* p) : impl_(p) {}

  // Allows implicit conversion from nullptr.
  QuicheReferenceCountedPointer(std::nullptr_t) : impl_(nullptr) {}  // NOLINT

  // Copy and copy conversion constructors. It does not take the reference away
  // from |other| and they each end up with their own reference.
  template <typename U>
  QuicheReferenceCountedPointer(  // NOLINT
      const QuicheReferenceCountedPointer<U>& other)
      : impl_(other.impl()) {}
  QuicheReferenceCountedPointer(const QuicheReferenceCountedPointer& other)
      : impl_(other.impl()) {}

  // Move constructors. After move, it adopts the reference from |other|.
  template <typename U>
  QuicheReferenceCountedPointer(
      QuicheReferenceCountedPointer<U>&& other)  // NOLINT
      : impl_(std::move(other.impl())) {}
  QuicheReferenceCountedPointer(QuicheReferenceCountedPointer&& other)
      : impl_(std::move(other.impl())) {}

  ~QuicheReferenceCountedPointer() = default;

  // Copy assignments.
  QuicheReferenceCountedPointer& operator=(
      const QuicheReferenceCountedPointer& other) {
    impl_ = other.impl();
    return *this;
  }
  template <typename U>
  QuicheReferenceCountedPointer<T>& operator=(
      const QuicheReferenceCountedPointer<U>& other) {
    impl_ = other.impl();
    return *this;
  }

  // Move assignments.
  QuicheReferenceCountedPointer& operator=(
      QuicheReferenceCountedPointer&& other) {
    impl_ = std::move(other.impl());
    return *this;
  }
  template <typename U>
  QuicheReferenceCountedPointer<T>& operator=(
      QuicheReferenceCountedPointer<U>&& other) {
    impl_ = std::move(other.impl());
    return *this;
  }

  // Accessors for the referenced object.
  // operator*() and operator->() will assert() if there is no current object.
  T& operator*() const { return *impl_; }
  T* operator->() const { return impl_.get(); }

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

  // Assignment operator on raw pointer. Drops a reference to current pointee,
  // if any, and replaces it with |p|. This guarantees that the reference count
  // of *p is 1. This should only be used when a new object is created.  Calling
  // this on an already existent object is undefined behavior.
  QuicheReferenceCountedPointer<T>& operator=(T* p) {
    impl_ = p;
    return *this;
  }

  // Returns the raw pointer with no change in reference count.
  T* get() const { return impl_.get(); }

  QuicheReferenceCountedPointerImpl<T>& impl() { return impl_; }
  const QuicheReferenceCountedPointerImpl<T>& impl() const { return impl_; }

  // Comparisons against same type.
  friend bool operator==(const QuicheReferenceCountedPointer& a,
                         const QuicheReferenceCountedPointer& b) {
    return a.get() == b.get();
  }
  friend bool operator!=(const QuicheReferenceCountedPointer& a,
                         const QuicheReferenceCountedPointer& b) {
    return a.get() != b.get();
  }

  // Comparisons against nullptr.
  friend bool operator==(const QuicheReferenceCountedPointer& a,
                         std::nullptr_t) {
    return a.get() == nullptr;
  }
  friend bool operator==(std::nullptr_t,
                         const QuicheReferenceCountedPointer& b) {
    return nullptr == b.get();
  }
  friend bool operator!=(const QuicheReferenceCountedPointer& a,
                         std::nullptr_t) {
    return a.get() != nullptr;
  }
  friend bool operator!=(std::nullptr_t,
                         const QuicheReferenceCountedPointer& b) {
    return nullptr != b.get();
  }

 private:
  QuicheReferenceCountedPointerImpl<T> impl_;
};

}  // namespace quiche

#endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_REFERENCE_COUNTED_H_
