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

$StrBuffAuto::$StrBuffAuto()
{
   _Pointer_ = nullptr;
   _Capacity_ = 0;
   ValidateDisposable($$);
}

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

bool $StrBuffAuto::GetIsAllocated() const
{
   return IsValidDisposable && _Pointer_;
}

int $StrBuffAuto::Capacity($O) const
{
   $$VERIFY_VALID_DISPOSABLE();
   return _Capacity_;
}
PWSTR $StrBuffAuto::P($O) const $alias("Pointer")
{
   VerifyAllocated($$CI);
   return _Pointer_;
}

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

void $StrBuffAuto::VerifyAllocated($O) const $fatal_error_on_failure
{
   $$VERIFY_VALID_DISPOSABLE();
   if ( !IsAllocated )
      $INVALID_OPERATION_WITH_MESSAGE( $TEXT(
         L"Buffer is not allocated ($StrBuffAuto).",
         L"Буффер не был выделен в памяти ($StrBuffAuto)." ));
}

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

bool $StrBuffAuto::ReAllocate($OAM, int newCapacity $positive ) $fatal_error_on_failure
{
   return ReAllocate($ci,$ci, newCapacity );
}
bool $StrBuffAuto::ReAllocateNS($OAM, int newCapacity $positive ) $last_error
{
   return ReAllocateNS($ci,$ci, newCapacity );
}

bool $StrBuffAuto::TwiceEnlarge($OM) $fatal_error_on_failure
{
   return TwiceEnlarge($ci,$ci);
}
bool $StrBuffAuto::TwiceEnlargeNS($OM) $last_error
{
   return TwiceEnlargeNS($ci,$ci);
}

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

bool $StrBuffAuto::ReAllocate($OA,$M, int newCapacity $positive ) $fatal_error_on_failure
{
   $$VERIFY_VALID_DISPOSABLE();
   $$VERIFY_POSITIVE_VALUE_ARG( newCapacity );
   _Pointer_ = IsAllocated ?
      $memory::ReAllocate<WCHAR>($ci,$m, _Pointer_, newCapacity ) :
      $memory::Allocate<WCHAR>($ci,$m, newCapacity );
   _Capacity_ = newCapacity;
   return $BOOL( _Pointer_ );
}
bool $StrBuffAuto::ReAllocateNS($OA,$M, int newCapacity $positive ) $last_error
{
   $$VERIFY_VALID_DISPOSABLE();
   $$VERIFY_POSITIVE_VALUE_ARG( newCapacity );
   PWSTR pointer = IsAllocated ?
      $memory::ReAllocateNS<WCHAR>($ci,$m, _Pointer_, newCapacity ) :
      $memory::AllocateNS<WCHAR>($ci,$m, newCapacity );
   if ( !pointer )
      return false;
   _Pointer_ = pointer;
   _Capacity_ = newCapacity;
   return $BOOL( _Pointer_ );
}

bool $StrBuffAuto::TwiceEnlarge($O,$M) $fatal_error_on_failure
{
   $VERIFY_VALID_DISPOSABLE();
   int newCapacity;
   if ( !$CheckInt::TryDouble( &newCapacity, _Capacity_ ) )
      $FatalError::Raise($$CI, $Memory::SizeTooLargeForTwiceEnlarge_Message() );
   return ReAllocate($ci,$m, newCapacity );
}
bool $StrBuffAuto::TwiceEnlargeNS($O,$M) $last_error
{
   $VERIFY_VALID_DISPOSABLE();
   int newCapacity;
   return $CheckInt::TryDouble( &newCapacity, _Capacity_ ) ?
      ReAllocateNS($ci,$m, newCapacity ) :
      $SET_ERROR_LE( $Memory::SizeTooLargeForTwiceEnlarge_Message() );
}

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

WCHAR $StrBuffAuto::LastChar($O) const
{
   VerifyAllocated($$CI);
   return _Pointer_[ _Capacity_-1 ];
}
PWSTR $StrBuffAuto::SetLastChar($O, WCHAR value ) $ret_target $not_null
{
   VerifyAllocated($$CI);
   _Pointer_[ _Capacity_-1 ] = value;
   return _Pointer_;
}
PWSTR $StrBuffAuto::ZeroizeLastChar($O) $ret_target $not_null
{
   return SetLastChar($ci, L'\0' );
}

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

PWSTR $StrBuffAuto::DetachPointer() $or_null $ret_previous $needs_free
{
   if ( !IsAllocated )
      return nullptr;
   PWSTR pointer = _Pointer_;
   ResetSuperstructure();
   return pointer;
}

PWSTR $StrBuffAuto::TakePointerOwnership($O) $not_null $needs_free
{
   VerifyAllocated($$CI);
   return DetachPointer();
}

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

void $StrBuffAuto::DoDispose($CI_REF)
{
   if ( _Pointer_ || _Capacity_ )
   {
      $memory::Free( _Pointer_ );
      _Capacity_ = 0;
   }
}

void $StrBuffAuto::ResetSuperstructure()
{
   _Pointer_ = nullptr;
   _Capacity_ = 0;
}

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