#include <iostream>

#ifdef _WIN32
#ifdef _WIN64
#define _INT __int64
#else
#define _INT int
#endif
#define EXPORT __declspec(dllexport)
#else
#include <cstring>
#define _INT long
#define sprintf_s sprintf
#define EXPORT
#endif


#define PARAM_INT 1
#define PARAM_STR 2
#define PARAM_DOUBLE 3
#define PARAM_POINTER 4

struct PARAM{
	void* pValue;
	int nSize;
	int nType;
};
struct PARAMS{
	int nCount;
	int nIndex;
	PARAM* pParams;
};

extern "C" {

	EXPORT PARAMS* create_params(int count)
	{
		if (count > 0)
		{
			PARAMS* pParam = new PARAMS;
			pParam->nCount = count;
			pParam->nIndex = 0;
			pParam->pParams = new PARAM[count];
			for (int i = 0; i < count; i++)
			{
				pParam->pParams[i].pValue = NULL;
				pParam->pParams[i].nSize = 0;
				pParam->pParams[i].nType = 0;
			}
			return pParam;
		}
		return NULL;
	}
	EXPORT void delete_params(PARAMS* pParam)
	{
		if (pParam)
		{
			for (int i = 0; i < pParam->nCount; i++)
			{
				if (pParam->pParams[i].nType == PARAM_INT)
					delete (_INT*)pParam->pParams[i].pValue;
				else if (pParam->pParams[i].nType == PARAM_DOUBLE)
					delete (double*)pParam->pParams[i].pValue;
				else if (pParam->pParams[i].nType == PARAM_STR)
					delete [](char*)pParam->pParams[i].pValue;
				else if (pParam->pParams[i].nType == PARAM_POINTER)
					delete (unsigned _INT*)pParam->pParams[i].pValue;
			}
			delete []pParam->pParams;
			delete pParam;
		}
	}
	EXPORT void add_int(PARAMS* pParam, _INT value)
	{
		if (pParam)
		{
			if (pParam->nIndex >= pParam->nCount)
				return;

			pParam->pParams[pParam->nIndex].nType = PARAM_INT;
			pParam->pParams[pParam->nIndex].nSize = sizeof(_INT);
			pParam->pParams[pParam->nIndex].pValue = new _INT;
			*(_INT*)(pParam->pParams[pParam->nIndex].pValue) = value;
			pParam->nIndex++;
		}
	}
	EXPORT void add_double(PARAMS* pParam, double value)
	{
		if (pParam)
		{
			if (pParam->nIndex >= pParam->nCount)
				return;

			pParam->pParams[pParam->nIndex].nType = PARAM_DOUBLE;
			pParam->pParams[pParam->nIndex].nSize = sizeof(double);
			pParam->pParams[pParam->nIndex].pValue = new double;
			*(double*)(pParam->pParams[pParam->nIndex].pValue) = value;
			pParam->nIndex++;
		}
	}
	EXPORT void add_string(PARAMS* pParam, const char* value, _INT size)
	{
		if (pParam)
		{
			if (pParam->nIndex >= pParam->nCount)
				return;

			if (size < 0)
				return;

			pParam->pParams[pParam->nIndex].nType = PARAM_STR;
			pParam->pParams[pParam->nIndex].nSize = size;
			pParam->pParams[pParam->nIndex].pValue = new char[size + 1];
			memcpy((char*)(pParam->pParams[pParam->nIndex].pValue), value, size);
			((char*)pParam->pParams[pParam->nIndex].pValue)[size] = 0;
			pParam->nIndex++;
		}

	}
	EXPORT void add_ptr(PARAMS* pParam, void* value)
	{
		if (pParam)
		{
			if (pParam->nIndex >= pParam->nCount)
				return;

			pParam->pParams[pParam->nIndex].nType = PARAM_POINTER;
			pParam->pParams[pParam->nIndex].nSize = sizeof(unsigned _INT);
			pParam->pParams[pParam->nIndex].pValue = new unsigned _INT;
			*(unsigned _INT*)(pParam->pParams[pParam->nIndex].pValue) = (unsigned _INT)value;
			pParam->nIndex++;
		}
	}
}
