//**************************************************************************************************
//
// CommonHelpers satellite library | Author: Sergei Y.Kitáev
//
// TEMPLATES AND THEIR IMPLEMENTATION:
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#pragma once
#ifndef COMMON_HELPERS_H
   #error "This header file is designed to be included only from 'CommonHelpers.h'."
#endif
#define HTEMPLATES_H

namespace CommonHelpers {

//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//
// GENERAL OPERATIONS:
//
//==================================================================================================
ref class HTOps { HTOps(){} public:
//--------------------------------------------------------------------------------------------------

template<typename T> static int CountOf(T% fixedArrayVar);
template<typename T> static T* LastElementOf(T% fixedArrayVar);

template<typename T> static T* ClearArrayVar(T% fixedArrayVar);

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

template<typename T> static bool AsBool(T value);

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

template<typename T> static T Exchange(T% operand,T subst);
template<typename T> static T ZeroExchange(T% operand);

template<typename T> static void Swap(T% operand_1,T% operand_2);

template<typename T> static T ZeroSubstitution(T value,T subst);
template<typename T> static T SubstiteZero(T% operand,T subst);

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

template<typename T> static bool IsOneOf(T v,T v1,T v2);
template<typename T> static bool IsOneOf(T v,T v1,T v2,T v3);
template<typename T> static bool IsOneOf(T v,T v1,T v2,T v3,T v4);
template<typename T> static bool IsOneOf(T v,T v1,T v2,T v3,T v4,T v5);
template<typename T> static bool IsOneOf(T v,T v1,T v2,T v3,T v4,T v5,T v6);
template<typename T> static bool IsOneOf(T v,T v1,T v2,T v3,T v4,T v5,T v6,T v7);
template<typename T> static bool IsOneOf(T v,T v1,T v2,T v3,T v4,T v5,T v6,T v7,T v8);
template<typename T> static bool IsOneOf(T v,T v1,T v2,T v3,T v4,T v5,T v6,T v7,T v8,T v9);
template<typename T> static bool IsOneOf(T v,T v1,T v2,T v3,T v4,T v5,T v6,T v7,T v8,T v9,T v10);

//--------------------------------------------------------------------------------------------------
}; // HTOps
//==================================================================================================


//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//
// TYPIFIED MEMORY OPERATIONS:
//
//==================================================================================================
ref class HTMemory { HTMemory(){} public:
//--------------------------------------------------------------------------------------------------

template<typename T> static int ElementSize();
template<typename T> static int CountToSize(int count);

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

template<typename T> static T* Clear($OUT T* pDestinationElements);
template<typename T> static T* Clear($OUT T* pDestinationElements,$NULLABLE<int> count);

template<typename T> static T* Copy( $IN const T* pcSourceElements,
                                     $OUT T* pDestinationElements,
                                     int count );

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

/// <exception cref="CommonHelpers::HOperationFailedException" />
template<typename T> static T* Allocate();
/// <exception cref="CommonHelpers::HOperationFailedException" />
template<typename T> static T* Allocate(int capacity);
/// <exception cref="CommonHelpers::HOperationFailedException" />
template<typename T> static T* ReAllocate($IN T* pAllocatedBuffer,int newCapacity);
/// <exception cref="CommonHelpers::HOperationFailedException" />
template<typename T> static T* ReAllocate( $IN T* %pAllocatedBuffer,
                                           int newCapacity );
/// <exception cref="CommonHelpers::HOperationFailedException" />
template<typename T> static T* Duplicate($IN const T* pcAllocatedBuffer);

/// <exception cref="CommonHelpers::HOperationFailedException" />
template<typename T> static int GetAllocatedCapacity(const T* pcAllocatedBuffer);

/// <exception cref="::System::ComponentModel::Win32Exception" />
template<typename T> static bool Free($OPT T* pAllocatedBuffer);
/// <exception cref="::System::ComponentModel::Win32Exception" />
template<typename T> static bool Free($OPT T* volatile* ppAllocatedBuffer);

//--------------------------------------------------------------------------------------------------
}; // HTMemory
//==================================================================================================


//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//
// TYPIFIED POINTER HELPERS:
//
//==================================================================================================
ref class HTPointer { HTPointer(){} public:
//--------------------------------------------------------------------------------------------------

template<typename T> static T* GetNullValue();
template<typename T> static T* GetAllBitsValue();

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

template<typename T> static T* Exchange(T*% operand,T* value);
template<typename T> static T* NullValueExchange(T*% operand);
template<typename T> static T* AllBitsValueExchange(T*% operand);

template<typename T> static void Swap(T*% operand_1,T*% operand_2);

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

template<typename T> static T* IsNullSubstitution(T* value,T* subst);
template<typename T> static T* SubstiteNullValue(T*% operand,T* subst);

template<typename T> static T* AllBitsValueSubstitution(T* value,T* subst);
template<typename T> static T* SubstiteAllBitsValue(T*% operand,T* subst);

template<typename T> static T* XValueSubstitution(T* value,T* xValue,T* subst);
template<typename T> static T* SubstituteXValue(T*% operand,T* xValue,T* subst);

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

template<typename T> static T* _InterlockedExchange( $INOUT T* volatile* pPointerOperand,
                                                     T* substutionPointerValue );

template<typename T> static T* InterlockedNullValueExchange(
   $INOUT T* volatile* pPointerOperand );
template<typename T> static T* InterlockedAllBitsValueExchange(
   $INOUT T* volatile* pPointerOperand );

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

template<typename T> static const T* GetNullValueC();
template<typename T> static const T* GetAllBitsValueC();

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

template<typename T> static const T* ExchangeC(const T*% operand,const T* value);
template<typename T> static const T* NullValueExchangeC(const T*% operand);
template<typename T> static const T* AllBitsValueExchangeC(const T*% operand);

template<typename T> static void SwapC(const T*% operand_1,const T*% operand_2);

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

template<typename T> static const T* IsNullSubstitutionC(const T* value,const T* subst);
template<typename T> static const T* SubstiteNullValueC(const T*% operand,const T* subst);

template<typename T> static const T* AllBitsValueSubstitutionC(const T* value,const T* subst);
template<typename T> static const T* SubstiteAllBitsValueC(const T*% operand,const T* subst);

template<typename T> static const T* XValueSubstitutionC( const T* value,
                                                          const T* xValue,
                                                          const T* subst );
template<typename T> static const T* SubstituteXValueC( const T*% operand,
                                                        const T* xValue,
                                                        const T* subst );

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

template<typename T> static const T* InterlockedExchangeC(
   $INOUT const T* volatile* pConstPointerOperand,
   const T* substutionConstPointerValue );

template<typename T> static const T* InterlockedNullValueExchangeC(
   $INOUT const T* volatile* pConstPointerOperand );
template<typename T> static const T* InterlockedAllBitsValueExchangeC(
   $INOUT const T* volatile* pConstPointerOperand );

//--------------------------------------------------------------------------------------------------
}; // HTPointer
//==================================================================================================


//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//
// ZERO TERMINATED STRING HELPERS:
//
//==================================================================================================
ref class HTZS { HTZS(){} public:
//--------------------------------------------------------------------------------------------------

template<typename> static $PSZ ZeroizeLastCharOf($PCHAR charBufferVar);

//--------------------------------------------------------------------------------------------------
}; // HTZS
//==================================================================================================

} // CommonHelpers
