/*
 * platform-basetypes.h
 *
 *  Created on: 21 May 2020
 *      Author: Nick Pelling
 */

#ifndef PLATFORM_BASETYPES_H__
#define PLATFORM_BASETYPES_H__

#include <stdint.h>
#include <stdbool.h>

#include "platform-api.h"

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

#define EXTERN_INTEGER_FUNCS(READFUNC,WRITEFUNC)	\
	extern eAccess_t READFUNC(const void * pvField, int64_t * piOutput, const stPLUGIN_RangeInt_t * pstRange);	\
	extern eAccess_t WRITEFUNC(void * pvField, int64_t iValue, const stPLUGIN_RangeInt_t * pstRange)

EXTERN_INTEGER_FUNCS(Read_tInt8,  Write_tInt8);
EXTERN_INTEGER_FUNCS(Read_tInt16, Write_tInt16);
EXTERN_INTEGER_FUNCS(Read_tInt32, Write_tInt32);
EXTERN_INTEGER_FUNCS(Read_tInt64, Write_tInt64);

#define MAKE_INT8_BOUNDED(TYPE,MIN,MAX,UNITS)	\
	const stPLUGIN_RangeInt_t stRange_ ## TYPE = { MIN, MAX, UNITS };	\
	PLUGIN_INTEGER(TYPE,Read_tInt8,Write_tInt8,&stRange_ ## TYPE)

#define MAKE_INT16_BOUNDED(TYPE,MIN,MAX,UNITS)	\
	const stPLUGIN_RangeInt_t stRange_ ## TYPE = { MIN, MAX, UNITS };	\
	PLUGIN_INTEGER(TYPE,Read_tInt16,Write_tInt16,&stRange_ ## TYPE)

#define MAKE_INT32_BOUNDED(TYPE,MIN,MAX,UNITS)	\
	const stPLUGIN_RangeInt_t stRange_ ## TYPE = { MIN, MAX, UNITS };	\
	PLUGIN_INTEGER(TYPE,Read_tInt32,Write_tInt32,&stRange_ ## TYPE)

#define MAKE_INT64_BOUNDED(TYPE,MIN,MAX,UNITS)	\
	const stPLUGIN_RangeInt_t stRange_ ## TYPE = { MIN, MAX, UNITS };	\
	PLUGIN_INTEGER(TYPE,Read_tInt64,Write_tInt64,&stRange_ ## TYPE)

typedef uint8_t  tInt8;
typedef uint16_t tInt16;
typedef uint32_t tInt32;
typedef uint64_t tInt64;

extern const stPLUGIN_RangeInt_t stRange_Int8;
extern const stPLUGIN_RangeInt_t stRange_Int16;
extern const stPLUGIN_RangeInt_t stRange_Int32;

#define MAKE_INT8(TYPE)		PLUGIN_INTEGER(TYPE,Read_tInt8, Write_tInt8, &stRange_Int8)
#define MAKE_INT16(TYPE)	PLUGIN_INTEGER(TYPE,Read_tInt16,Write_tInt16,&stRange_Int16)
#define MAKE_INT32(TYPE)	PLUGIN_INTEGER(TYPE,Read_tInt32,Write_tInt32,&stRange_Int32)
#define MAKE_INT64(TYPE)	PLUGIN_INTEGER(TYPE,Read_tInt64,Write_tInt64,NULL)

MAKE_INT8(tInt8);
MAKE_INT16(tInt16);
MAKE_INT32(tInt32);
MAKE_INT64(tInt64);

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

#define EXTERN_UNSIGNEDINTEGER_FUNCS(READFUNC,WRITEFUNC)	\
	extern eAccess_t READFUNC(const void * pvField, uint64_t * puiOutput, const stPLUGIN_RangeUint_t * pstRange);	\
	extern eAccess_t WRITEFUNC(void * pvField, uint64_t uiValue, const stPLUGIN_RangeUint_t * pstRange)

EXTERN_UNSIGNEDINTEGER_FUNCS(Read_tUint8,  Write_tUint8);
EXTERN_UNSIGNEDINTEGER_FUNCS(Read_tUint16, Write_tUint16);
EXTERN_UNSIGNEDINTEGER_FUNCS(Read_tUint32, Write_tUint32);
EXTERN_UNSIGNEDINTEGER_FUNCS(Read_tUint64, Write_tUint64);

#define MAKE_UINT8_BOUNDED(TYPE,MIN,MAX,UNITS)	\
	const stPLUGIN_RangeUint_t stRange_ ## TYPE = { MIN, MAX, UNITS };	\
	PLUGIN_UNSIGNEDINTEGER(TYPE,Read_tUint8,Write_tUint8,&stRange_ ## TYPE)

#define MAKE_UINT16_BOUNDED(TYPE,MIN,MAX,UNITS)	\
	const stPLUGIN_RangeUint_t stRange_ ## TYPE = { MIN, MAX, UNITS };	\
	PLUGIN_UNSIGNEDINTEGER(TYPE,Read_tUint16,Write_tUint16,&stRange_ ## TYPE)

#define MAKE_UINT32_BOUNDED(TYPE,MIN,MAX,UNITS)	\
	const stPLUGIN_RangeUint_t stRange_ ## TYPE = { MIN, MAX, UNITS };	\
	PLUGIN_UNSIGNEDINTEGER(TYPE,Read_tUint32,Write_tUint32,&stRange_ ## TYPE)

#define MAKE_UINT64_BOUNDED(TYPE,MIN,MAX,UNITS)	\
	const stPLUGIN_RangeUint_t stRange_ ## TYPE = { MIN, MAX, UNITS };	\
	PLUGIN_UNSIGNEDINTEGER(TYPE,Read_tUint64,Write_tUint64,&stRange_ ## TYPE)

typedef uint8_t  tUint8;
typedef uint16_t tUint16;
typedef uint32_t tUint32;
typedef uint64_t tUint64;

extern const stPLUGIN_RangeUint_t stRange_Uint8;
extern const stPLUGIN_RangeUint_t stRange_Uint16;
extern const stPLUGIN_RangeUint_t stRange_Uint32;

#define MAKE_UINT8(TYPE)	PLUGIN_UNSIGNEDINTEGER(TYPE,Read_tUint8, Write_tUint8, &stRange_Uint8)
#define MAKE_UINT16(TYPE)	PLUGIN_UNSIGNEDINTEGER(TYPE,Read_tUint16,Write_tUint16,&stRange_Uint16)
#define MAKE_UINT32(TYPE)	PLUGIN_UNSIGNEDINTEGER(TYPE,Read_tUint32,Write_tUint32,&stRange_Uint32)
#define MAKE_UINT64(TYPE)	PLUGIN_UNSIGNEDINTEGER(TYPE,Read_tUint64,Write_tUint64,NULL)

MAKE_UINT8(tUint8);
MAKE_UINT16(tUint16);
MAKE_UINT32(tUint32);
MAKE_UINT64(tUint64);

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

#define EXTERN_REAL_FUNCS(READFUNC,WRITEFUNC)	\
	extern eAccess_t READFUNC(const void * pvField, double * pdOutput, const stPLUGIN_RangeReal_t * pstRange);	\
	extern eAccess_t WRITEFUNC(void * pvField, double dValue, const stPLUGIN_RangeReal_t * pstRange)

EXTERN_REAL_FUNCS(Read_tFloat,  Write_tFloat);
EXTERN_REAL_FUNCS(Read_tDouble, Write_tDouble);

#define MAKE_FLOAT(TYPE)	PLUGIN_REAL(TYPE,Read_tFloat,Write_tFloat,NULL)
#define MAKE_DOUBLE(TYPE)	PLUGIN_REAL(TYPE,Read_tDouble,Write_tDouble,NULL)

#define MAKE_FLOAT_BOUNDED(TYPE,MIN,MAX,UNITS)	\
	const stPLUGIN_RangeReal_t stRange_ ## TYPE = { MIN, MAX, UNITS };	\
	PLUGIN_REAL(TYPE,Read_tFloat,Write_tFloat,&stRange_ ## TYPE)

#define MAKE_DOUBLE_BOUNDED(TYPE,MIN,MAX,UNITS)	\
	const stPLUGIN_RangeReal_t stRange_ ## TYPE = { MIN, MAX, UNITS };	\
	PLUGIN_REAL(TYPE,Write_tFloat,Write_tDouble,&stRange_ ## TYPE)

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

#define EXTERN_ENUM_READ_FUNC(READFUNC)	\
	extern eAccess_t READFUNC( const void * pvField, const char * * ppchResult, const stPLUGIN_Dictionary_t * pastDictionary)

EXTERN_ENUM_READ_FUNC(  Read_tEnum8		);
EXTERN_ENUM_READ_FUNC(  Read_tEnum16	);
EXTERN_ENUM_READ_FUNC(  Read_tEnum32	);

#define EXTERN_ENUM_WRITE_FUNC(WRITEFUNC)	\
	extern eAccess_t WRITEFUNC(const void * pvField, const char * pchString, uint32_t uiStringLen, const stPLUGIN_Dictionary_t * pastDictionary)

EXTERN_ENUM_WRITE_FUNC(  Write_tEnum8	);
EXTERN_ENUM_WRITE_FUNC(  Write_tEnum16	);
EXTERN_ENUM_WRITE_FUNC(  Write_tEnum32	);

#define ENUM_READ(TYPE)	\
	(					\
		(sizeof(TYPE) == sizeof(uint8_t))  ? &Read_tEnum8  :		\
		(sizeof(TYPE) == sizeof(uint16_t)) ? &Read_tEnum16 :		\
		(sizeof(TYPE) == sizeof(uint32_t)) ? &Read_tEnum32 : NULL	\
	)

#define ENUM_WRITE(TYPE)	\
	(						\
		(sizeof(TYPE) == sizeof(uint8_t))  ? &Write_tEnum8  :		\
		(sizeof(TYPE) == sizeof(uint16_t)) ? &Write_tEnum16 :		\
		(sizeof(TYPE) == sizeof(uint32_t)) ? &Write_tEnum32 : NULL	\
	)

#define MAKE_ENUM(TYPE)	\
	PLUGIN_ENUM(TYPE, ENUM_READ(TYPE), ENUM_WRITE(TYPE), astDictionary_ ## TYPE)

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

extern eAccess_t Read_String( const void * pvField, const char * * ppchResult);
extern eAccess_t Write_String(void * pvField, const char * pachString, uint32_t uiSrcStringLen, uint32_t uiDstStringMax);

#define MAKE_STRING(TYPE)	PLUGIN_STRING(TYPE, Read_String, Write_String, sizeof(TYPE))

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

extern eAccess_t Read_Boolean(const void * pvField, bool * bValue);
extern eAccess_t Write_Boolean(void * pvField, bool bValue);

#define MAKE_BOOLEAN(TYPE,FALSE,TRUE)	\
	const stPLUGIN_BooleanNames_t stBooleanNames_ ## TYPE = { FALSE, TRUE };	\
	PLUGIN_BOOLEAN(TYPE, Read_Boolean, Write_Boolean, &stBooleanNames_ ## TYPE )

typedef bool tBool;

PLUGIN_BOOLEAN(tBool, Read_Boolean, Write_Boolean, NULL);

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

#endif
