// RuntimeForStatic base library | C+- (SysRoutine) | Author: Sergei Y.Kitáev
#pragma once
#include "include_restrictions.h"
namespace RuntimeForStatic {
//==================================================================================================

template<typename T>$ap<T>::$ap()
{
   ResetSuperstructure();
   ValidateDisposable($$);
}
template<typename T>$ap<T>::$ap($A, T* pointer )
: $ap($ci, pointer, false )
{}
template<typename T>$ap<T>::$ap($A, T* pointer, bool isArray )
{
   $$VERIFY_POINTER_ARG( pointer );
   ResetSuperstructure();
   _Pointer_ = pointer;
   _IsArray_ = isArray;
   ValidateDisposable($$);
}

//==================================================================================================

template<typename T>$ap<T>& $ap<T>::operator = ($ap<T>& predecessor) $owner_transfer
{
   $memory::Copy($, &predecessor, this );
   if ( predecessor.IsValidDisposable )
   {
      predecessor._Pointer_ = nullptr;
      predecessor.Dispose();
   }
   return *this;
}

//--------------------------------------------------------------------------------------------------

template<typename T>void $ap<T>::DoDispose($CI_REF)
{
   Delete();
}

template<typename T>void $ap<T>::ResetSuperstructure()
{
   _Pointer_ = nullptr;
   _IsArray_ = false;
}

//==================================================================================================

template<typename T>T* $ap<T>::P($O) const $strict_result
{
   VerifyHasPointer($ci); return _Pointer_;
}

//--------------------------------------------------------------------------------------------------

template<typename T>bool $ap<T>::IsArray($O) const
{
   $$VERIFY_VALID_DISPOSABLE(); return _IsArray_;
}

template<typename T>bool $ap<T>::GetHasPointer() const
{
   return IsValidDisposable && $BOOL( _Pointer_ );
}

template<typename T>void $ap<T>::VerifyHasPointer($O) const
{
   $$VERIFY_VALID_DISPOSABLE();
   if ( !_Pointer_ )
      $INVALID_OPERATION_WITH_MESSAGE( $TEXT(
         L"Pointer is not attached ($ap<T>).",
         L"Указатель не подключен ($ap<T>)." ));
}

//==================================================================================================

template<typename T>T* $ap<T>::Attach($OA,T* pointer) $imaginary_param("freePrevious",true)
                                                      $ret_target
{
   return Attach($ci, true, pointer );
}
template<typename T>T* $ap<T>::Attach($OA, T* pointer, bool isArray )
                                           $imaginary_param("freePrevious",true)
                                           $ret_target
{
   return Attach($ci, true, pointer, isArray );
}

template<typename T>T* $ap<T>::Attach($OA,bool deletePrevious,T* pointer)
{
   return Attach($ci, freePrevious, pointer, false);
}
template<typename T>T* $ap<T>::Attach($OA,bool deletePrevious,T* pointer,bool isArray)
{
   $$VERIFY_VALID_DISPOSABLE();
   $$VERIFY_POINTER_ARG( pointer );
   if ( deletePrevious )
      Delete();
   else
      ResetSuperstructure();
   _Pointer_ = pointer;
   _IsArray_ = isArray;
   return pointer;
}

//--------------------------------------------------------------------------------------------------

template<typename T>T* $ap<T>::Detach() $or_null $ret_previous $needs_free
{
   if ( !HasPointer )
      return nullptr;
   T* previous = _Pointer_;
   ResetSuperstructure();
   return previous;
}

template<typename T>T* $ap<T>::TakePointerOwnership($O) $not_null $needs_free
{
   VerifyHasPointer($$CI);
   return Detach();
}

template<typename T>void $ap<T>::Delete()
{
   if ( !IsValidDisposable )
      return;
   T* pointer = _Pointer_;
   if ( pointer )
   {
      bool isArray = _IsArray_;
      ResetSuperstructure();
      if ( isArray )
         delete[] pointer;
      else
         delete pointer;
   }
}

//==================================================================================================
} // RuntimeForStatic
