// vim:set ft=cpp: -*- Mode: C++ -*-
/**
 * \file
 * L4::Capability class.
 *
 * \author Alexander Warg <alexander.warg@os.inf.tu-dresden.de>
 *
 */
/*
 * (c) 2008-2009 Author(s)
 *     economic rights: Technische Universität Dresden (Germany)
 *
 * This file is part of TUD:OS and distributed under the terms of the
 * GNU General Public License 2.
 * Please see the COPYING-GPL-2 file for details.
 *
 * As a special exception, you may use this file as part of a free software
 * library without restriction.  Specifically, if other files instantiate
 * templates or use macros or inline functions from this file, or you compile
 * this file and link it with other files to produce an executable, this
 * file does not by itself cause the resulting executable to be covered by
 * the GNU General Public License.  This exception does not however
 * invalidate any other reasons why the executable file might be covered by
 * the GNU General Public License.
 */
#pragma once

#include <l4/sys/capability>

namespace L4 {

/**
 * Smart capability class.
 */
template< typename T, typename SMART >
class Smart_cap : public Cap_base, private SMART
{
public:

  SMART const &smart() const { return *this; }

  void _delete() throw()
  {
    SMART::free(const_cast<Smart_cap<T,SMART>&>(*this));
  }

  Cap<T> release() const throw()
  {
    l4_cap_idx_t r = cap();
    SMART::invalidate(const_cast<Smart_cap<T,SMART>&>(*this));

    return Cap<T>(r);
  }

  void reset()
  {
    _c = L4_INVALID_CAP;
  }

  Smart_cap() throw() : Cap_base(Invalid) {}

  Smart_cap(Cap_base::Cap_type t) throw() : Cap_base(t) {}

  /**
   * Internal constructor, use to generate a capability from a `this` pointer.
   *
   * \attention This constructor is only useful to generate a capability
   *            from the `this` pointer of an objected that is an L4::Kobject.
   *            Do `never` use this constructor for something else!
   * \param p  The `this` pointer of the Kobject or derived object
   */
  template< typename O >
  Smart_cap(Cap<O> const &p) throw() : Cap_base(p.cap())
  { T* __t = ((O*)100); (void)__t; }

  template< typename O >
  Smart_cap(Cap<O> const &p, SMART const &smart) throw()
  : Cap_base(p.cap()), SMART(smart)
  { T* __t = ((O*)100); (void)__t; }

  template< typename O >
  Smart_cap(Smart_cap<O, SMART> const &o) throw()
  : Cap_base(SMART::copy(o)), SMART(o.smart())
  { T* __t = ((O*)100); (void)__t; }

  Smart_cap(Smart_cap const &o) throw()
  : Cap_base(SMART::copy(o)), SMART(o.smart())
  { }

  template< typename O >
  Smart_cap(typename Cap<O>::Cap_type cap) throw() : Cap_base(cap)
  { T* __t = ((O*)100); (void)__t; }

  void operator = (typename Cap<T>::Cap_type cap) throw()
  {
    _delete();
    _c = cap;
  }

  template< typename O >
  void operator = (Smart_cap<O, SMART> const &o) throw()
  {
    _delete();
    _c = this->SMART::copy(o).cap();
    this->SMART::operator = (o.smart());
    // return *this;
  }

  Smart_cap const &operator = (Smart_cap const &o) throw()
  {
    if (&o == this)
      return *this;

    _delete();
    _c = this->SMART::copy(o).cap();
    this->SMART::operator = (o.smart());
    return *this;
  }

#if __cplusplus >= 201103L
  template< typename O >
  Smart_cap(Smart_cap<O, SMART> &&o) throw()
  : Cap_base(o.release()), SMART(o.smart())
  { T* __t = ((O*)100); (void)__t; }

  Smart_cap(Smart_cap &&o) throw()
  : Cap_base(o.release()), SMART(o.smart())
  { }

  template< typename O >
  void operator = (Smart_cap<O, SMART> &&o) throw()
  {
    _delete();
    _c = o.release().cap();
    this->SMART::operator = (o.smart());
    // return *this;
  }

  Smart_cap const &operator = (Smart_cap &&o) throw()
  {
    if (&o == this)
      return *this;

    _delete();
    _c = o.release().cap();
    this->SMART::operator = (o.smart());
    return *this;
  }
#endif

  /**
   * Member access of a `T`.
   */
  Cap<T> operator -> () const throw() { return Cap<T>(_c); }

  Cap<T> get() const throw() { return Cap<T>(_c); }

  ~Smart_cap() throw() { _delete(); }
};

template< typename T >
class Weak_cap : public Cap_base
{
public:
  Weak_cap() : Cap_base(Invalid) {}

  template< typename O >
  Weak_cap(typename Cap<O>::Cap_type t) : Cap_base(t)
  { T* __t = ((O*)100); (void)__t; }

  template< typename O, typename S >
  Weak_cap(Smart_cap<O, S> const &c) : Cap_base(c.cap())
  { T* __t = ((O*)100); (void)__t; }

  Weak_cap(Weak_cap const &o) : Cap_base(o) {}

  template< typename O >
  Weak_cap(Weak_cap<O> const &o) : Cap_base(o)
  { T* __t = ((O*)100); (void)__t; }

};

namespace Cap_traits {
  template< typename T1, typename T2 >
  struct Type { enum { Equal = false }; };

  template< typename T1 >
  struct Type<T1,T1> { enum { Equal = true }; };
};

/**
 * `static_cast` for (smart) capabilities.
 *
 * \tparam T      Type to cast the capability to.
 * \tparam F      (implicit) Type of the passed capability.
 * \tparam SMART  (implicit) Class implementing the Smart_cap interface.
 * \param  c      Capability to be casted.
 *
 * \return A smart capability with new type `T`.
 */
template< typename T, typename F, typename SMART >
inline
Smart_cap<T, SMART> cap_cast(Smart_cap<F, SMART> const &c) throw()
{
  (void)static_cast<T const *>(reinterpret_cast<F const *>(100));
  return Smart_cap<T, SMART>(Cap<T>(SMART::copy(c).cap()));
}


/**
 * `reinterpret_cast` for (smart) capabilities.
 *
 * \tparam T      Type to cast the capability to.
 * \tparam F      (implicit) Type of the passed capability.
 * \tparam SMART  (implicit) Class implementing the Smart_cap interface.
 * \param  c      Capability to be casted.
 *
 * \return A smart capability with new type `T`.
 */
template< typename T, typename F, typename SMART >
inline
Smart_cap<T, SMART> cap_reinterpret_cast(Smart_cap<F, SMART> const &c) throw()
{
  return Smart_cap<T, SMART>(Cap<T>(SMART::copy(c).cap()));
}


}

