// ---------------------------------------------------------------------------
// - mutant.tcc                                                              -
// - afnix nuts and bolts - pointer mutation template                        -
// ---------------------------------------------------------------------------
// - This program is free software;  you can redistribute it  and/or  modify -
// - it provided that this copyright notice is kept intact.                  -
// -                                                                         -
// - This program  is  distributed in  the hope  that it will be useful, but -
// - without  any  warranty;  without  even   the   implied    warranty   of -
// - merchantability or fitness for a particular purpose.  In no event shall -
// - the copyright holder be liable for any  direct, indirect, incidental or -
// - special damages arising in any way out of the use of this software.     -
// ---------------------------------------------------------------------------
// - copyright (c) 1999-2023 amaury darsch                                   -
// ---------------------------------------------------------------------------

#ifndef  AFNIX_MUTANT_TCC
#define  AFNIX_MUTANT_TCC

namespace afnix {

  /// The mutatnt template is a generic pointer mutation detector. Initialy
  /// the template does not any pointer. Setting a different pointer marks
  /// the mutation flag.
  /// @author amaury darsch

  template <typename T>
  class t_mutant {
  protected:
    /// the mutant pointer
    T* p_mptr;
    /// the mutant flag
    bool d_mflg;

  public:
    /// create a null mutant
    t_mutant(void) {
      p_mptr = nullptr;
      d_mflg = false;
    }

    /// create a mutant object
    /// @param mptr the pointer object
    t_mutant(T* mptr) {
      d_mflg = (mptr == p_mptr) ? false : true;
      p_mptr = mptr;
    }

    /// copy move this mutant pointer
    /// @param that the object to copy move
    t_mutant (t_mutant&& that) noexcept {
      p_mptr = that.p_mptr; that.p_mptr = nullptr;
      d_mflg = that.d_mflg; that.d_mflg = false;
    }
    
    /// move this mutant pointer
    /// @param that the object to move
    t_mutant& operator = (t_mutant&& that) noexcept {
      if (this == &that) return *this;
      p_mptr = that.p_mptr; that.p_mptr = nullptr;
      d_mflg = that.d_mflg; that.d_mflg = false;
      return *this;
    }

    /// assign the mutant detector by pointer
    /// @param that the pointer to set
    t_mutant& operator = (T* mptr) {
      d_mflg = (mptr == p_mptr) ? false : true;
      p_mptr = mptr;
      return *this;
    }
      
    /// reset this mutant pointer
    void reset (void) {
      p_mptr = nullptr;
      d_mflg = false;
    }
    
    /// @return true is the pointer is valid
    bool valid (void) const {
      return (p_mptr == nullptr) ? false : true;
    }

    /// @return the mutation flag
    bool ismute (void) const {
      return d_mflg;
    }
    
    /// @return the mutant pointer
    T* operator * (void) {
      return p_mptr;
    }

    /// @return the mutant pointer
    const T* operator * (void) const {
      return p_mptr;
    }

    /// @return the mutant pointer
    T* operator -> (void) {
      return p_mptr;
    }

    /// @return the mutant pointer
    const T* operator -> (void) const {
      return p_mptr;
    }
    
  private:
    // make the copy constructor private
    t_mutant (const t_mutant&) =delete;
    // make the assignement operator private
    t_mutant& operator = (const t_mutant&) =delete; 
  };
}

#endif
