//----------------------------------------------------
/**
	\file		ctk/inc/datadef.h
	\ingroup	data
	\ingroup	all

	\brief		Definice pro praci s univerzalni datovou strukturou
				<<< ALL >>>

	\author		ConTeK s.r.o., Ing. Vladimir Kastner
	\version	01.02
	\date		15.10.2008
*/
//----------------------------------------------------

#ifndef _DATADEF_H_
#define _DATADEF_H_

#include <libsets.h>
#include <ctktypes.h>
#include <hwmodel.h>
#include <ctktime.h>
#include <packed.h>


// Popis typu hodnoty - datatype
// |---|---|---|-D-|---|---|---|---|
// |   TYPE    | S |     SIZE      |
// |---|---|---|---|---|---|---|---|
//
// TYPE 	C typ hodnoty (VT_TYPE_MASK)
// SIGN		hodnota obsahuje znamenko (VT_SIGNED)
// DEFINE	hodnota obsahuje definovane hodnoty (VT_DEFINED) - jen ENUM typy, XXXXX = 2460
// SIZE		velikost dat (VT_SIZE_MASK)

//----------------------------------------------------
//!	\name	Datovy typ popisu typu hodnoty
//@{

typedef uint8_t				datatype_t;		//!< Typ hodnoty

#define VT_SIGNED				0x10			//!< Hodnota se znamenkem, 0 = bez znamenka
#define VT_DEFINED				0x10			//!< Hodnota s definovanou hodnotou, 0 = bez definovane hodnoty,

#define VT_SIZE_1				1				//!< 1 byte
#define VT_SIZE_2				2				//!< 2 byte
#define VT_SIZE_4				4				//!< 4 byte

#if defined(DTDEF_SUPPORT_64BIT) || defined(DTDEF_SUPPORT_DOUBLE)
 #define VT_SIZE_8				8				//!< 8 byte
#endif // DTDEF_SUPPORT_64BIT || DTDEF_SUPPORT_DOUBLE

#define VT_TYPE_ORDINAL			0x00			//!< Cele cislo
#define VT_TYPE_FIXED			0x20			//!< Cislo s pevnou radovou carkou

#ifdef DTDEF_SUPPORT_FLOAT
 #define VT_TYPE_FLOAT			0x40			//!< Cislo s pohyblivou radovou carkou
#endif // DTDEF_SUPPORT_FLOAT

#define VT_TYPE_ENUM			0x60			//!< Vycet hodnot
#define VT_TYPE_TIME			0x80			//!< Datum/Cas (32bit - sekundy od 1.1.1970)

#ifdef DTDEF_SUPPORT_SSTRING
 #define VT_TYPE_SSTRING		0xC0			//!< Velikost sstring <0..31> parametru - gParam
#endif // DTDEF_SUPPORT_SSTRING

#ifdef DTDEF_SUPPORT_LSTRING
 #define VT_TYPE_LSTRING		0xA0			//!< Velikost lstring <0..((32 * 31)-1)> parametru - gParam
#endif // DTDEF_SUPPORT_LSTRING

#define VT_TYPE_MASK			0xE0			//!< Maska pro typ hodnoty
#define VT_SIGNED_MASK			0x10			//!< Hodnota se znamenkem
#define VT_DEFINED_MASK			0x10			//!< Hodnota s definovanymi typy - jen ENUM typy
#define VT_SIZE_MASK			0x0F			//!< Maska pro velikost hodnoty
#define VT_SIZE_STRING_MASK		0x1F			//!< Maska pro velikost stringu, je vyuzit i nejnizsi bit TYPE a SIGN
//@}

//----------------------------------------------------
//!	\name	Preddefinovane typy hodnot
//@{

#define VT_U8					( VT_SIZE_1 | VT_TYPE_ORDINAL )					//!< Unsigned 8 bit
#define VT_S8					( VT_SIZE_1 | VT_TYPE_ORDINAL | VT_SIGNED )		//!< Signed 8 bit
#define VT_U16					( VT_SIZE_2 | VT_TYPE_ORDINAL )					//!< Unsigned 16 bit
#define VT_S16					( VT_SIZE_2 | VT_TYPE_ORDINAL | VT_SIGNED )		//!< Signed 16 bit
#define VT_U32					( VT_SIZE_4 | VT_TYPE_ORDINAL )					//!< Unsigned 32 bit
#define VT_S32					( VT_SIZE_4 | VT_TYPE_ORDINAL | VT_SIGNED )		//!< Signed 32 bit

#ifdef DTDEF_SUPPORT_64BIT
 #define VT_U64					( VT_SIZE_8 | VT_TYPE_ORDINAL ) 				//!< Unsigned 64 bit
 #define VT_S64					( VT_SIZE_8 | VT_TYPE_ORDINAL | VT_SIGNED )		//!< Signed 64 bit
#endif // DTDEF_SUPPORT_64BIT

#define VT_FH8					( VT_SIZE_1 | VT_TYPE_FIXED )					//!< Fixed 8 bit, abs >= 1
#define VT_FL8					( VT_SIZE_1 | VT_TYPE_FIXED | VT_SIGNED )		//!< Fixed 8 bit, abs < 1
#define VT_FH16					( VT_SIZE_2 | VT_TYPE_FIXED )					//!< Fixed 16 bit, abs >= 1
#define VT_FL16					( VT_SIZE_2 | VT_TYPE_FIXED | VT_SIGNED )		//!< Fixed 16 bit, abs < 1
#define VT_FH32					( VT_SIZE_4 | VT_TYPE_FIXED )					//!< Fixed 32 bit, abs >= 1
#define VT_FL32					( VT_SIZE_4 | VT_TYPE_FIXED | VT_SIGNED )		//!< Fixed 32 bit, abs < 1

#ifdef DTDEF_SUPPORT_64BIT
 #define VT_FH64				( VT_SIZE_8 | VT_TYPE_FIXED )					//!< Fixed 64 bit, abs >= 1
 #define VT_FL64				( VT_SIZE_8 | VT_TYPE_FIXED | VT_SIGNED )		//!< Fixed 64 bit, abs < 1
#endif // DTDEF_SUPPORT_64BIT

#ifdef DTDEF_SUPPORT_FLOAT
 #define VT_FLT32				( VT_SIZE_4 | VT_TYPE_FLOAT | VT_SIGNED )		//!< Float 32 bit
#endif // DTDEF_SUPPORT_FLOAT

#ifdef DTDEF_SUPPORT_DOUBLE
 #define VT_DBL64				( VT_SIZE_8 | VT_TYPE_FLOAT | VT_SIGNED )		//!< Double 64 bit
#endif // DTDEF_SUPPORT_DOUBLE

#define VT_ENUM8				( VT_SIZE_1 | VT_TYPE_ENUM )					//!< Enum 8 bit
#define VT_DENUM8				( VT_SIZE_1 | VT_TYPE_ENUM | VT_DEFINED )		//!< Defined Enum 8 bit, definovane hodnoty
#define VT_BOOL					( VT_SIZE_1 | VT_TYPE_ENUM )					//!< Enum 8 bit, BOOLEAN, rozlisuje se ve vizualizaci podle atributu TYPE="bool_t"
#define VT_ENUM16				( VT_SIZE_2 | VT_TYPE_ENUM )					//!< Enum 16 bit
#define VT_DENUM16				( VT_SIZE_2 | VT_TYPE_ENUM | VT_DEFINED )		//!< Defined Enum 16 bit, definovane hodnoty
#define VT_DATETIME32			( VT_SIZE_4 | VT_TYPE_TIME )					//!< DateTime 32bit
#define VT_TIME32				( VT_SIZE_4 | VT_TYPE_TIME | VT_SIGNED )		//!< Time 32bit

#ifdef DTDEF_SUPPORT_DATETIME64
 #define VT_DATETIME64			( VT_SIZE_8 | VT_TYPE_TIME )					//!< DateTime 64bit
 #define VT_TIME64				( VT_SIZE_8 | VT_TYPE_TIME | VT_SIGNED )		//!< Time 64bit
#endif // DTDEF_SUPPORT_DATETIME64

#ifdef DTDEF_SUPPORT_SSTRING
 #define VT_SSTRING				( VT_TYPE_SSTRING )								//!< Velikost sstring <0..31> parametru
#endif // DTDEF_SUPPORT_SSTRING

#ifdef DTDEF_SUPPORT_LSTRING
 #define VT_LSTRING				( VT_TYPE_LSTRING )								//!< Velikost lstring <0..((32 * 32)-1)> parametru
#endif // DTDEF_SUPPORT_LTRING
//@}

// Format datumu a casu
//
// D .. den       01 - 31
// M .. mesic     01 - 12
// Y .. rok	      1970 - 2107
// y .. rok	      00 - 99
// H .. hodina    00 - 23
// M .. minuta    00 - 59
// S .. sekunda   00 -- 59
// h .. hodina    00 -- nnnn
// m .. minuta    00 -- nnnn
//

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

#ifdef QT_CORE_LIB
  #define STRCOMPARE	compare
  #define STRMODIF
#else
  #define STRCOMPARE	Compare
  #define STRMODIF	_T
#endif

//! Makra pro prevod textu do typu
#define mEndStrToValueType( type, string ) \
	((type) = VT_U8, false )

#ifdef DTDEF_SUPPORT_LSTRING
 #define mLStringStrToValueType( type, string ) \
      !(string).STRCOMPARE( STRMODIF("VT_LSTRING") ) ? ((type) = VT_LSTRING, true) : mEndStrToValueType( type, string )
#else
 #define mLStringStrToValueType( type, string ) \
	  mEndStrToValueType( type, string )
#endif // DTDEF_SUPPORT_LSTRING

#ifdef DTDEF_SUPPORT_SSTRING
 #define mSStringStrToValueType( type, string ) \
      !(string).STRCOMPARE( STRMODIF("VT_SSTRING") ) ? ((type) = VT_SSTRING, true) : mLStringStrToValueType( type, string )
#else
 #define mSStringStrToValueType( type, string ) \
	  mLStringStrToValueType( type, string )
#endif // DTDEF_SUPPORT_SSTRING

#ifdef DTDEF_SUPPORT_DATETIME64
 #define mDateTime64StrToValueType( type, string ) \
      !(string).STRCOMPARE( STRMODIF("VT_DATETIME64") ) ? ((type) = VT_DATETIME64, true) : \
      !(string).STRCOMPARE( STRMODIF("VT_TIME64") ) ? ((type) = VT_TIME32, true) : mSStringStrToValueType( type, string )
#else
 #define mDateTime64StrToValueType( type, string ) \
	  mSStringStrToValueType( type, string )
#endif // DTDEF_SUPPORT_DATETIME64

#define mStrToValueType( type, string ) \
    ( !(string).STRCOMPARE( STRMODIF("VT_U8") ) ? ((type) = VT_U8, true) : \
      !(string).STRCOMPARE( STRMODIF("VT_S8") ) ? ((type) = VT_S8, true) : \
      !(string).STRCOMPARE( STRMODIF("VT_U16") ) ? ((type) = VT_U16, true) : \
      !(string).STRCOMPARE( STRMODIF("VT_S16") ) ? ((type) = VT_S16, true) : \
      !(string).STRCOMPARE( STRMODIF("VT_U32") ) ? ((type) = VT_U32, true) : \
      !(string).STRCOMPARE( STRMODIF("VT_S32") ) ? ((type) = VT_S32, true) : \
      !(string).STRCOMPARE( STRMODIF("VT_U64") ) ? ((type) = VT_U64, true) : \
      !(string).STRCOMPARE( STRMODIF("VT_S64") ) ? ((type) = VT_S64, true) : \
      !(string).STRCOMPARE( STRMODIF("VT_FLT32") ) ? ((type) = VT_FLT32, true) : \
      !(string).STRCOMPARE( STRMODIF("VT_DBL64") ) ? ((type) = VT_DBL64, true) : \
      !(string).STRCOMPARE( STRMODIF("VT_ENUM8") ) ? ((type) = VT_ENUM8, true) : \
      !(string).STRCOMPARE( STRMODIF("VT_DENUM8") ) ? ((type) = VT_DENUM8, true) : \
      !(string).STRCOMPARE( STRMODIF("VT_BOOL") )  ? ((type) = VT_BOOL, true) : \
      !(string).STRCOMPARE( STRMODIF("VT_ENUM16") ) ? ((type) = VT_ENUM16, true) : \
      !(string).STRCOMPARE( STRMODIF("VT_DENUM16") ) ? ((type) = VT_DENUM16, true) : \
      !(string).STRCOMPARE( STRMODIF("VT_DATETIME32") ) ? ((type) = VT_DATETIME32, true) : \
      !(string).STRCOMPARE( STRMODIF("VT_TIME32") ) ? ((type) = VT_TIME32, true) : mDateTime64StrToValueType( type, string ))


//----------------------------------------------------
/**
	\brief	Funkce pro ziskani C typu z popisu typu parametru
*/
//----------------------------------------------------
static uint8_t dtaGetType( const datatype_t desc ) _const;
static inline uint8_t dtaGetType( const datatype_t desc )
{
	return (desc & VT_TYPE_MASK);
}

#ifdef DTDEF_SUPPORT_STRING
//----------------------------------------------------
/**
	\brief	Funkce pro ziskani skutecne velikosti parametru
*/
//----------------------------------------------------
static uint8_t dtaGetCurrSize( const datatype_t desc ) _const;
static inline uint8_t dtaGetCurrSize( const datatype_t desc )
{
	uint8_t result;
	switch (dtaGetType(desc))
	{
#ifdef DTDEF_SUPPORT_SSTRING
	case VT_TYPE_SSTRING:
		result = desc & VT_SIZE_STRING_MASK;		//!< VT_SSTRING, velikost sstring <0..31> parametru
		break;
#endif // DTDEF_SUPPORT_SSTRING

#ifdef DTDEF_SUPPORT_LSTRING
	case VT_TYPE_LSTRING:
		result = (((desc & VT_SIZE_STRING_MASK) != 0) ?
			(((desc & VT_SIZE_STRING_MASK) << 5) - 1) :
			0);										//!< VT_LSTRING, velikost lstring <0..((32 * 32)-1)> parametru, velikost je nasobkem 32
		break;
#endif // DTDEF_SUPPORT_LSTRING

	default:
		result = (desc & VT_SIZE_MASK);
	}
	return result;
}

#endif // DTDEF_SUPPORT_STRING

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani typove velikosti parametru
*/
//----------------------------------------------------
static uint16_t dtaGetTypeSize( const datatype_t desc ) _const;
static inline uint16_t dtaGetTypeSize( const datatype_t desc )
{
	uint16_t result;

#ifdef DTDEF_SUPPORT_STRING

	switch (dtaGetType(desc))
	{
#ifdef DTDEF_SUPPORT_SSTRING
	case VT_TYPE_SSTRING:
		result = DTDEF_SSTRING_BUFF_SIZE;				//!< VT_SSTRING, typova velikost sstring <0..31> parametru
		break;
#endif // DTDEF_SUPPORT_SSTRING

#ifdef DTDEF_SUPPORT_LSTRING
	case VT_TYPE_LSTRING:
		result = DTDEF_LSTRING_BUFF_SIZE;				//!< VT_LSTRING, typova velikost lstring <0..((32 * 32)-1)> parametru
		break;
#endif // DTDEF_SUPPORT_LSTRING

	default:
		result = (uint16_t)(desc & VT_SIZE_MASK);
	}

#else
	result = (uint16_t)(desc & VT_SIZE_MASK);
#endif

	return result;
}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani znamenka z type parametru
*/
//----------------------------------------------------
static bool_t dtaIsSigned( const datatype_t desc ) _const;
static inline bool_t dtaIsSigned( const datatype_t desc )
{
	// sstring, lstring ani enum nema definovan priznak znamenka
	bool_t result;
	switch (dtaGetType(desc))
	{
#ifdef DTDEF_SUPPORT_SSTRING
	case VT_TYPE_SSTRING:
		result = FALSE;
		break;
#endif // DTDEF_SUPPORT_SSTRING

#ifdef DTDEF_SUPPORT_LSTRING
	case VT_TYPE_LSTRING:
		result = FALSE;
		break;
#endif // DTDEF_SUPPORT_LSTRING

	case VT_TYPE_ENUM:
		result = FALSE;
		break;

	default:
		result = ((desc & VT_SIGNED_MASK) != 0);
	}
	return result;
}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani defined z type parametru, jen Enum typy
*/
//----------------------------------------------------
static bool_t dtaIsDefinedEnum( const datatype_t desc ) _const;
static inline bool_t dtaIsDefinedEnum( const datatype_t desc )
{
	// TRUE, je-li typ enum a ma priznak definovanosti
	return ((dtaGetType(desc) == VT_TYPE_ENUM) && (desc & VT_DEFINED_MASK));
}

//----------------------------------------------------
/**
	\brief	Funkce pro vytvoreni popisu typu z C typu, znamenka, define a velikosti
*/
//----------------------------------------------------
static datatype_t dtaMakeType( const uint8_t type, const bool_t sign, const uint8_t size ) _const;
static inline datatype_t dtaMakeType( const uint8_t type, const bool_t sign, const uint8_t size )
{
	datatype_t result;
	switch (result = dtaGetType(type))
	{
#ifdef DTDEF_SUPPORT_SSTRING
	case VT_TYPE_SSTRING:
		result |= (size & VT_SIZE_STRING_MASK);
		break;
#endif // DTDEF_SUPPORT_SSTRING

#ifdef DTDEF_SUPPORT_LSTRING
	case VT_TYPE_LSTRING:
		result |= (((size + 31) >> 5) & VT_SIZE_STRING_MASK);
		break;
#endif // DTDEF_SUPPORT_LSTRING

	case VT_TYPE_ENUM:
		result |= (size & VT_SIZE_MASK);
		break;

	default:
		result |= ((size & VT_SIZE_MASK) | (sign ? VT_SIGNED_MASK : 0));
	}
	return result;
}

// Priznaky pristupu k parametru (option)
// |---|---|---|---|---|---|---|---|
// | R | D | L | S | V |   ACCESS  |
// |---|---|---|---|---|---|---|---|
//
// READONLY		jen pro cteni
// DYNAMIC		dynamicky parametr
// LOCAL		lokalni, nekomunikuje se
// SECRET		neni videt ve stromu ale az v editaci
// VALID		platnost parametru
//				ve vizualizaci urcuje platnost (nakomunikoval se)
//				v ridicim systemu zadost o ulozeni
// ACCESS		pristup obsluhy, vyssi pristup umoznuje pristupovat k nizsim

//----------------------------------------------------
//!	\name	Priznaky pristupu k parametru
//@{

typedef uint8_t		dataoption_t;

#define PO_ACCESS0			0x00		//!< Uroven uzivatele 0 (all)
#define PO_ACCESS1			0x01		//!< Uroven uzivatele 1 (level1)
#define PO_ACCESS2			0x02		//!< Uroven uzivatele 2 (level2)
#define PO_ACCESS3			0x03		//!< Uroven uzivatele 3 (level3)
#define PO_ACCESS4			0x04		//!< Uroven uzivatele 4 (level4)
#define PO_ACCESS5			0x05		//!< Uroven uzivatele 5 (level5)
#define PO_ACCESS6			0x06		//!< Uroven uzivatele 6 (level6)
#define PO_ACCESS7			0x07		//!< Uroven uzivatele 7 (administrator)

#define PO_NO				0x00		//!< Bez priznaku
#define PO_READONLY			0x80		//!< Read-only parametr
#define PO_DYNAMIC			0x40		//!< Dynamicky parametr
#define PO_LOCAL			0x20		//!< Parametr je lokalni (nekomunikuje se)
#define PO_SECRET			0x10		//!< Hodnota parametru neni videt ve stromu (ale az v editaci)
#define PO_VALID			0x08		//!< platnost parametru

#define PO_OPTION_MASK		0xF8		//!< Maska priznaku
#define PO_ACCESS_MASK		0x07		//!< Maska urovne uzivatele
//@}

//----------------------------------------------------
// tyto alternativni nazvy pristupu jsou definovany v Xml
//#define ACCESS0			PO_ACCESS0	// Uroven uzivatele 0 (all)
//#define ACCESS1			PO_ACCESS1	// Uroven uzivatele 1 (level1)
//#define ACCESS2			PO_ACCESS2	// Uroven uzivatele 2 (level2)
//#define ACCESS3			PO_ACCESS3	// Uroven uzivatele 3 (level3)
//#define ACCESS4			PO_ACCESS4	// Uroven uzivatele 4 (level4)
//#define ACCESS5			PO_ACCESS5	// Uroven uzivatele 5 (level5)
//#define ACCESS6			PO_ACCESS6	// Uroven uzivatele 6 (level6)
//#define ACCESS7			PO_ACCESS7	// Uroven uzivatele 7 (administrator)

//----------------------------------------------------
// \name	Alternativni nazvy v Xml zadat bez predpony acs
#define acsAll				PO_ACCESS0	//!< Vsichni	(all)
#define acsUser				PO_ACCESS1	//!< Uzivatel	(level1)
#define acsTechnologist		PO_ACCESS2	//!< Technolog	(level2)
#define acsTechno			PO_ACCESS2	//!< Technolog	(level2)
#define acsService			PO_ACCESS3	//!< Servis		(level3)
#define acsProducer			PO_ACCESS5	//!< Vyrobce	(level5)
#define acsEngineering		PO_ACCESS6	//!< Technik	(level6)
#define acsDeveloper		PO_ACCESS6	//!< Vyvojar	(level6)
#define acsAdministrator	PO_ACCESS7	//!< Administrator (administrator)
#define acsAdmin			PO_ACCESS7	//!< Administrator (administrator)
//@}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani Access z option parametru
*/
//----------------------------------------------------
static uint8_t dtaGetAccess( const dataoption_t desc ) _const;
static inline uint8_t dtaGetAccess( const dataoption_t desc )
{
	return (desc & PO_ACCESS_MASK);
}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani priznaku READONLY
*/
//----------------------------------------------------
static bool_t dtaIsReadOnly( const dataoption_t option ) _const;
static inline bool_t dtaIsReadOnly( const dataoption_t option )
{
	return (!!(option & PO_READONLY));
}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani priznaku DYNAMIC
*/
//----------------------------------------------------
static bool_t dtaIsDynamic( const dataoption_t option ) _const;
static inline bool_t dtaIsDynamic( const dataoption_t option )
{
	return (!!(option & PO_DYNAMIC));
}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani priznaku LOCAL
*/
//----------------------------------------------------
static bool_t dtaIsLocal( const dataoption_t option ) _const;
static inline bool_t dtaIsLocal( const dataoption_t option )
{
	return (!!(option & PO_LOCAL));
}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani priznaku SECRET
*/
//----------------------------------------------------
static bool_t dtaIsSecret( const dataoption_t option ) _const;
static inline bool_t dtaIsSecret( const dataoption_t option )
{
	return (!!(option & PO_SECRET));
}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani priznaku VALID
*/
//----------------------------------------------------
static bool_t dtaIsValid( const dataoption_t option ) _const;
static inline bool_t dtaIsValid( const dataoption_t option )
{
	return (!!(option & PO_VALID));
}

//----------------------------------------------------
/**
	\brief	Funkce pro vytvoreni option z access, readonly, dynamic, local, secret a valid
*/
//----------------------------------------------------
static dataoption_t dtaMakeOption(
				const uint8_t access,
				const bool_t readonly,
				const bool_t dynamic,
				const bool_t local,
				const bool_t secret,
				const bool_t valid ) _const;

static inline dataoption_t dtaMakeOption(
							const uint8_t access,
							const bool_t readonly,
							const bool_t dynamic,
							const bool_t local,
							const bool_t secret,
							const bool_t valid )
{
	dataoption_t tmp = access;
	if (readonly)
	{
		tmp |= PO_READONLY;
	}

	if (dynamic)
	{
		tmp |= PO_DYNAMIC;
	}

	if (local)
	{
		tmp |= PO_LOCAL;
	}

	if (secret)
	{
		tmp |= PO_SECRET;
	}

	if (valid)
	{
		tmp |= PO_VALID;
	}

	return tmp;
}

//----------------------------------------------------
//! Typy

typedef uint32_t			paramcode_t;							//!< Kod parametru
typedef ptr_t				paramoffset_t;							//!< Ofset parametru
typedef ptr_t				dataoffset_t;							//!< Ofset parametru
typedef pconst_pvoidptr_t	dataextpptr_t;							//!< Ukazatel na rozsireny popis parametru, DENUM16, ...
typedef	float_t				dataincr_t;								//!< Inkrement pro editaci
typedef	float_t				datascale_t;							//!< Meritko pro zobrazeni
typedef	uint8_t				dataprecision_t;						//!< Presnost pro zobrazeni
typedef	uint8_t				datadecimal_t;							//!< Pocet mist
typedef uint8_t				indexcount_t;							//!< Pocet zaznamu pole
typedef uint16_t			indexcount2_t;							//!< Pocet zaznamu pole 16 bit
typedef uint32_t			indexsize_t;							//!< Ofset mezi dvema prvky pole (z duvodu zarovnavani nelze pouzit sizeof(xxx))
typedef	uint16_t			indexindex_t;							//!< Index do tabulky indexu parametru
typedef uint8_t				cantype_t;								//!< CAN typ hodnoty
typedef uint16_t			canoffset_t;							//!< Ofset CAN parametru
typedef uint16_t			cancode_t;								//!< CAN kod parametru
typedef	uint16_t			dataindex_t;							//!< Index do tabulky popisu parametru
typedef	uint16_t			stringindex_t;							//!< Index do tabulky stringu
typedef uint16_t			canindex_t;								//!< Index do tabulky CAN
typedef char_t				descstring_t[DTDEF_MAX_DESC_STRING_SIZE];	//!< String Desc, Unit a Enum
typedef char_t				valuestring_t[DTDEF_MAX_VALUE_STRING_SIZE];	//!< String jako textove vyjadreni hodnoty

//----------------------------------------------------
//! Spolecny typ parametru
typedef union
{
	uint8_t		u8;					//!< VT_U8
	int8_t		s8;					//!< VT_S8
	uint16_t	u16;				//!< VT_U16
	int16_t		s16;				//!< VT_S16
	uint32_t	u32;				//!< VT_U32
	int32_t		s32;				//!< VT_S32

#ifdef DTDEF_SUPPORT_64BIT
	uint64_t	u64;				//!< VT_U64
	int64_t		s64;				//!< VT_S64
#endif // DTDEF_SUPPORT_64BIT

	ctkdatetime32_t	datetime32;		//!< VT_DATETIME32
	ctktime32_t	time32;				//!< VT_TIME32

#ifdef DTDEF_SUPPORT_DATETIME64
	ctkdatetime64_t	datetime64;		//!< VT_DATETIME64
	ctktime64_t	time64;				//!< VT_TIME64
#endif // DTDEF_SUPPORT_DATETIME64

#ifdef DTDEF_SUPPORT_FLOAT
	float_t		flt32;				//!< VT_FLT32
#endif //DTDEF_SUPPORT_FLOAT

#ifdef DTDEF_SUPPORT_DOUBLE
	double_t	dbl64;				//!< VT_DBL64
#endif //DTDEF_SUPPORT_DOUBLE

	enum8_t		enum8;				//!< VT_ENUM8, VT_DENUM8, VT_BOOL
	enum16_t	enum16;				//!< VT_ENUM16, VT_DENUM16

#ifdef DTDEF_SUPPORT_SSTRING
	sstring8_t	sstring;
#endif

#ifdef DTDEF_SUPPORT_LSTRING
	lstring8_t	lstring;
#endif

} datavalue_t;

//----------------------------------------------------
//!	Index parametru
typedef struct _INDEX_DESC_ITEM
{
	indexcount_t			Count0;				//!< Pocet zaznamu pole 0
	indexsize_t				Size0;				//!< Delka zaznamu pole 0
	indexcount_t			Count1;				//!< Pocet zaznamu pole 1
	indexsize_t				Size1;				//!< Delka zaznamu pole 1
	indexcount2_t			Count2;				//!< Pocet zaznamu pole 2
	indexsize_t				Size2;				//!< Delka zaznamu pole 2
} INDEX_DESC_ITEM;
#define tIndexDescItem	INDEX_DESC_ITEM

//typedef INDEX_DESC_ITEM tIndexDescTable[et_IndexDesc_max];		//  IndexDesc table type, definovano v XmlIndexDesc

//----------------------------------------------------
//!  Popisovac dat parametru
typedef struct _DATA_DESC_ITEM
{
	datatype_t				Type;				//!< Typ parametru
	dataincr_t				Incr;				//!< Inkrement pro editaci
	datascale_t				Scale;				//!< Meritko pro zobrazeni
	dataprecision_t			Precision;			//!< Presnost pro zobrazeni
	dataextpptr_t			ExtPtr;				//!< Ukazatel na rozsireny popis parametru, DENUM16, ...
} DATA_DESC_ITEM;
#define tDataDescItem	DATA_DESC_ITEM

//typedef DATA_DESC_ITEM tDataDescTable[et_ParamDesc_max];	//  DataDesc table type, definovano v XmlDataDesc

//----------------------------------------------------
//! Popisovac parametru
typedef struct _PARAM_DESC_ITEM
{
	dataoption_t			Option;				//!< Priznaky dat
	dataoffset_t			Offset;				//!< Offset dat v datove strukture (gParam, Min, Max, Default)
	dataindex_t				IData;				//!< Index do tabulky popisu parametru
	indexindex_t			IIndex;				//!< Index do tabulky indexu parametru
	stringindex_t			IDesc;				//!< Index popisu
	stringindex_t			IUnit;				//!< Index jednotky

} PARAM_DESC_ITEM;
#define tParamDescItem	PARAM_DESC_ITEM

//----------------------------------------------------
//! Popisovac CAN parametru
typedef struct _CAN_DESC_ITEM
{
	dataoption_t			Option;				//!< Priznaky dat
	datatype_t				Type;				//!< Typ parametru
	cancode_t				CanCode;			//!< CAN code
	cantype_t				CanType;			//!< CAN typ hodnoty
	dataoffset_t			CanOffset;			//!< Offset dat do datove struktury (CanParam, CanMin, CanMax, CanDefault)
	indexcount2_t			Count;				//!< Pocet zaznamu pole
	indexsize_t				Size;				//!< Delka zaznamu pole
} CAN_DESC_ITEM;
#define tCanDescItem	CAN_DESC_ITEM


//----------------------------------------------------
/*
	\brief	Prevadi cancode na commcode - vraci FALSE v pripade chyby
*/
//----------------------------------------------------

bool_t dtaCanToComm( paramcode_t * CommCode, cancode_t CanCode, uint8_t idx );

//----------------------------------------------------
/**
	\brief	Prevadi commcode na cancode - vraci FALSE v pripade chyby
*/
//----------------------------------------------------
bool_t dtaCommToCan( cancode_t * CanCode, uint8_t * idx, paramcode_t CommCode );

// ParamCode
//32      21      15      12       0 bit
// |---|---|---|---|---|---|---|---|
// | index2| index1| index0| param |
// |---|---|---|---|---|---|---|---|
//    11       6       3      12   bits
//
// pocet param	= 4096	bits = 12
// pocet index0 =    8	bits =  3
// pocet index1 =   64	bits =  6
// pocet index2 = 2048	bits = 11

//----------------------------------------------------
//!	\name	Rozlozeni indexu v deskriptoru
//@{

#define PARAM_BITS		12
#define PARAM_MASK		((uint32_t)0xFFF)
#define PARAM_OFFSET	0

#define INDEX0_BITS		3
#define INDEX0_MASK		((uint32_t)0x07)
#define INDEX0_OFFSET	12
#define INDEX0_SIZE		8

#define INDEX1_BITS		6
#define INDEX1_MASK		((uint32_t)0x3F)
#define INDEX1_OFFSET	15
#define INDEX1_SIZE		64

#define INDEX2_BITS		11
#define INDEX2_MASK		((uint32_t)0x3FF)
#define INDEX2_OFFSET	21
#define INDEX2_SIZE		2048

typedef uint16_t	param_t;
typedef uint8_t		index0_t;
typedef uint8_t		index1_t;
typedef uint16_t	index2_t;
//@}

#ifdef DTDEF_XML_PARAM
 #ifdef COMPILED_LIB
	extern struct _tParam *ptrgParam;					//!< Definovano novym XmlCGen v XmlVariables.c
	extern const struct _tParam *ptrcminParam;			//!< Definovano novym XmlCGen v XmlConstantsMin.c
	extern const struct _tParam *ptrcmaxParam;			//!< Definovano novym XmlCGen v XmlConstantsMax.c
	extern const struct _tParam *ptrcdftParam;			//!< Definovano novym XmlCGen v XmlConstantsDefault.c
	extern const uint16_t constParamIndex_max;			//!< Definovano novym XmlCGen v XmlParamIndex.c

	extern const tParamDescItem *ptrcParamDescTable;	//!< Definovano novym XmlCGen v XmlParamDesc.c
	extern const tDataDescItem *ptrcDataDescTable;		//!< Definovano novym XmlCGen v XmlDataDesc.c
	extern const tIndexDescItem *ptrcIndexDescTable;	//!< Definovano novym XmlCGen v XmlIndexDesc.c

  #ifndef DTDEF_XML_MINIMAL
	extern const uint16_t constsniACCESS0;				//!< Definovano novym XmlCGen v XmlStringIndex.c
	extern const uint16_t constStringIndex_max;			//!< Definovano novym XmlCGen v XmlStringIndex.c
	extern const uint16_t constsniLanguage;				//!< Definovano novym XmlCGen v XmlStringIndex.c

	extern const pvoidptr_t ptrcLanguageTable;			//!< Definovano novym XmlCGen v XmlStringIndex.c
  #endif //DTDEF_XML_MINIMAL

 #else//COMPILED_LIB

  #include "XmlVariables.h"
  #include "XmlConstantsMin.h"
  #include "XmlConstantsMax.h"
  #include "XmlConstantsDefault.h"
  #include "XmlParamIndex.h"
  #include "XmlParamDesc.h"
  #include "XmlDataDesc.h"
  #include "XmlIndexDesc.h"
  #include "XmlStringIndex.h"
 #endif //COMPILED_LIB
#endif // DTDEF_XML_PARAM

#ifdef DTDEF_XML_CAN
 #ifdef COMPILED_LIB
	extern const tCanDescItem *ptrcCanDescTable;	//!< Definovano novym XmlCGen v XmlCanDesc.c
	extern const uint16_t constCanIndex_max;		//!< Definovano novym XmlCGen v XmlCanIndex.c
	extern const uint16_t *ptrcCanIndex;			//!< Definovano novym XmlCGen v XmlCanIndex.c (Zde by mohl nastat problem, kdyby se zmenil v definicnim XML CGeneratoru "IDIndexType")
	extern const uint16_t *ptrcCanParamIndex;		//!< Definovano novym XmlCGen v XmlCanParamIndex.c
 #endif //COMPILED_LIB
#endif //DTDEF_XML_CAN
//----------------------------------------------------
//! Makro pro slozeni kodu parametru z indexu parametru, indexu 0, indexu 1 a indexu 2
#define dtaMakeCode( param, index0, index1, index2 ) \
	(((((paramcode_t)param) & PARAM_MASK) << PARAM_OFFSET) \
	| ((((paramcode_t)index0 ) & INDEX0_MASK) << INDEX0_OFFSET) \
	| ((((paramcode_t)index1 ) & INDEX1_MASK) << INDEX1_OFFSET) \
	| ((((paramcode_t)index2 ) & INDEX2_MASK) << INDEX2_OFFSET))

//----------------------------------------------------
//! Makro pro ziskani indexu parametru z kodu parametru
static param_t dtaGetParam( const paramcode_t Code ) _const;
static inline param_t dtaGetParam( const paramcode_t Code )
{
	return ( Code >> PARAM_OFFSET ) & PARAM_MASK;
}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani indexu 0 z kodu parametru
	\note	Funkce nahrazuje makro #define mGetIndex0( code ) (((code) >> 10) & 0x07)
*/
//----------------------------------------------------
static index0_t dtaGetIndex0( const paramcode_t Code ) _const;
static inline index0_t dtaGetIndex0( const paramcode_t Code )
{
	return ( Code >> INDEX0_OFFSET ) & INDEX0_MASK;
}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani indexu 1 z kodu parametru
	\note	Funkce nahrazuje makro #define mGetIndex1( code ) (((code) >> 16) & 0x3F)
*/
//----------------------------------------------------
static index1_t dtaGetIndex1( const paramcode_t Code ) _const;
static inline index1_t dtaGetIndex1( const paramcode_t Code )
{
	return ( Code >> INDEX1_OFFSET ) & INDEX1_MASK;
}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani indexu 2 z kodu parametru
	\note	Funkce nahrazuje makro #define mGetIndex2( code ) (((code) >> 22) & 0x3FF)
*/
//----------------------------------------------------
static index2_t dtaGetIndex2( const paramcode_t Code ) _const;
static inline index2_t dtaGetIndex2( const paramcode_t Code )
{
	return ( Code >> INDEX2_OFFSET ) & INDEX2_MASK;
}

typedef enum _PARAM_ERROR
{
	PERR_NONE = 0,
	PERR_CODE,
	PERR_INDEX0,
	PERR_INDEX1,
	PERR_INDEX2,
	PERR_VALUE_OVERRANGE,
	PERR_VALUE_UNDERRANGE,
	PERR_VALUE_UNDEFINED,	// nedefinovana hodnota definovaneho enumu
	PERR_MEM,
	PERR_BUSY,
	PERR_TYPE,
	PERR_READONLY,
	PERR_WAITFORSAVE,
	PERR_USERREJECT,
	PERR_INVALIDRQ
} PARAM_ERROR;


//----------------------------------------------------
//! Index parametru
typedef struct _PARAMETER_ITEM {
	paramcode_t				Code;				//!< Code parametru
	PARAM_ERROR				Error;				//!< Chyba parametru
	paramoffset_t			ParamOffset;		//!< Offset parametru s indexy do datove struktury (gParam, Min, Max, Default)
	// Hodnoty ziskane z ofsetu
	uint8_t 				*pValue;			//!< Ukazatel na parametr
	// Hodnoty ziskane z ofsetu a tabulek konstant
	datavalue_t				minValue;			//!< Minimalni hodnota
	datavalue_t				maxValue;			//!< Maximalni hodnota
	datavalue_t				dftValue;			//!< Defaultni hodnota
	// Hodnoty ziskane z cParamDescTable
	dataoption_t			Option;				//!< Priznaky parametru
	dataoffset_t			Offset;				//!< Offset parametru do datove struktury bez indexu (gParam, Min, Max, Default)
	dataindex_t				IData;				//!< Index do tabulky popisu parametru
	indexindex_t			IIndex;				//!< Index do tabulky indexu parametru
	stringindex_t			IDesc;				//!< Index popisu
	stringindex_t			IUnit;				//!< Index jednotky
	// Hodnoty ziskane z cDataDescTable
	datatype_t				Type;				//!< Typ parametru
	dataincr_t				Incr;				//!< Inkrement pro editaci
	datascale_t				Scale;				//!< Meritko pro zobrazeni
	dataprecision_t			Precision;			//!< Presnost pro zobrazeni
	pvoidptr_t				ExtPtr;				//!< Ukazatel na doplnujici informace (DENUM atp)

	// Hodnoty ziskane z cIndexDescTable
	indexcount_t			Count0;				//!< Pocet zaznamu pole 0
	indexsize_t				Size0;				//!< Delka zaznamu pole 0
	indexcount_t			Count1;				//!< Pocet zaznamu pole 1
	indexsize_t				Size1;				//!< Delka zaznamu pole 1
	indexcount2_t			Count2;				//!< Pocet zaznamu pole 2
	indexsize_t				Size2;				//!< Delka zaznamu pole 2

} PARAMETER_ITEM;
#define tParameterItem	PARAMETER_ITEM

#ifndef DTDEF_XML_MINIMAL
//!	\brief	Ukazatel na tabulku stringu
//! \note	pro znemu jazyka nastavit ukazatel na danou jazykovou variantu
extern pvoidptr_t pStringTable;
#endif // DTDEF_XML_MINIMAL

#ifdef DTDEF_XML_PARAM

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani pristupu k parametru

	\note	Funkce vraci data zarovnana podle typu parametru,
			proto nelze vracet datavalue_t *, neni ve vsech pripadech spravne zarovnan
*/
//----------------------------------------------------
static inline  uint8_t * dtaGetValuePtr(const PARAMETER_ITEM * const _param)
{
#ifdef COMPILED_LIB
	return (uint8_t *)((ptr_t)ptrgParam + _param->ParamOffset);
#else
	return (uint8_t *)((ptr_t)&gParam + _param->ParamOffset);
#endif //COMPILED_LIB
}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani pristupu k minimu, MinParameter->u8
*/
//----------------------------------------------------
static inline const uint8_t * dtaGetMinPtr(const PARAMETER_ITEM * const _param)
{
#ifdef COMPILED_LIB
	return (const uint8_t*)(((pconst_ptr_t)ptrcminParam + _param->ParamOffset));
#else
	return (const uint8_t*)(((pconst_ptr_t)&cminParam + _param->ParamOffset));
#endif //COMPILED_LIB
}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani pristupu k maximu, MaxParameter->u8
*/
//----------------------------------------------------
static inline const uint8_t * dtaGetMaxPtr(const PARAMETER_ITEM * const _param)
{
#ifdef COMPILED_LIB
	return (const uint8_t*)(((pconst_ptr_t)ptrcmaxParam + _param->ParamOffset));
#else
	return (const uint8_t*)(((pconst_ptr_t)&cmaxParam + _param->ParamOffset));
#endif //COMPILED_LIB
}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani pristupu k defaultu, DftMaxParameter->u8
*/
//----------------------------------------------------
static inline const uint8_t * dtaGetDefaultPtr(const PARAMETER_ITEM * const _param)
{
#ifdef COMPILED_LIB
	return (const uint8_t*)(((pconst_ptr_t)ptrcdftParam + _param->ParamOffset));
#else
	return (const uint8_t*)(((pconst_ptr_t)&cdftParam + _param->ParamOffset));
#endif //COMPILED_LIB
}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani hodnoty minima, MinParameter->u8
*/
//----------------------------------------------------
static inline datavalue_t dtaGetMin(const PARAMETER_ITEM * const _param)
{
	datavalue_t val;
	pck_memcpy_pconst(&val, dtaGetMinPtr(_param), dtaGetTypeSize(_param->Type));
	return val;
}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani hodnoty maxima, MaxParameter->u8
*/
//----------------------------------------------------
static inline datavalue_t dtaGetMax(const PARAMETER_ITEM * const _param)
{
	datavalue_t val;
	pck_memcpy_pconst(&val, dtaGetMaxPtr(_param), dtaGetTypeSize(_param->Type));
	return val;
}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani hodnoty default, DftMaxParameter->u8
*/
//----------------------------------------------------
static inline datavalue_t dtaGetDefault(const PARAMETER_ITEM * const _param)
{
	datavalue_t val;
	pck_memcpy_pconst(&val, dtaGetDefaultPtr(_param), dtaGetTypeSize(_param->Type));
	return val;
}

#endif // DTDEF_XML_PARAM


//----------------------------------------------------
/**
	\brief	Funkce pro ziskani hodnoty parametru, Parameter->u8
*/
//----------------------------------------------------
static inline datavalue_t dtaGetValue(const PARAMETER_ITEM * const _param)
{
	datavalue_t val;
	pck_memcpy(&val, _param->pValue, dtaGetTypeSize(_param->Type));
	return val;
}

//----------------------------------------------------
/**
	\brief	Funkce pro nastaveni hodnoty parametru, Parameter->u8
*/
//----------------------------------------------------
static inline void dtaSetValue( PARAMETER_ITEM* const param, const datavalue_t* pValue )
{
	if (dtaIsReadOnly(param->Option))
	{
		param->Error = PERR_READONLY;
	}
	else
	{
		pck_memcpy(param->pValue, pValue, dtaGetTypeSize(param->Type));
	}
}

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

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani pristupu k parametru, Description(param).Type, ve strukture musi byt platna hodnota Code
*/
//----------------------------------------------------
const PARAM_DESC_ITEM * dtaParamDesc( const param_t param );

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani pristupu k popisu parametru, DataDesc(param).Type
*/
//----------------------------------------------------
const DATA_DESC_ITEM * dtaDataDesc( const dataindex_t IData );

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani pristupu k indexu parametru, IndexDesc(param).Count0
*/
//----------------------------------------------------
const INDEX_DESC_ITEM * dtaIndexDesc( const indexindex_t IIndex );

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani pristupu k can informacim parametru, IndexDesc(param).Count0
*/
//----------------------------------------------------
const CAN_DESC_ITEM * dtaCanDesc( const canindex_t CIndex );

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani pristupu k gParam, Description(param).Type
*/
//----------------------------------------------------
void dtaGetParamDesc( PARAMETER_ITEM* const param );

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani popisu ParamDesc, DataDesc(param).Type
*/
//----------------------------------------------------
void dtaGetDataDesc( PARAMETER_ITEM* const param );

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani pristupu k ParamIndex, ParamIndex(param).Count0
*/
//----------------------------------------------------
void dtaGetIndexDesc( PARAMETER_ITEM* const param );

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani pristupu k min,max,dft
*/
//----------------------------------------------------
void dtaGetMinMaxDefault( PARAMETER_ITEM* const param );

//----------------------------------------------------
//!	Makro pro ziskani hodnoty vyctoveho typu s definovanou hodnotou
#define dtaGetDefinedEnumValue( type, element ) \
	( (sizeof(type) == 1) ? read_pconst_byte( &c##type##[(element)] ) : \
	 ( (sizeof(type) == 2) ? read_pconst_word( &c##type##[(element)] ) : 0 ) )

//----------------------------------------------------
//!	Makro pro ziskani indexu do tabulky stringu
#define dtaGetEnumIndex( type, element ) \
	( (element) + sni##type )

#ifdef DTDEF_XML_PARAM

 #ifndef DTDEF_XML_MINIMAL

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani stringu z tabulky stringu

	\return	Ziska pouze odkaz
*/
//----------------------------------------------------
static inline pcharptr_t dtaGetStringPtr(const stringindex_t idx)
{
#ifdef COMPILED_LIB
	if (idx < constStringIndex_max)
#else
	if (idx < sniStringIndex_max)
#endif //COMPILED_LIB
	{
		// ziskame ukazatel na polozku tabulky v programove pameti
		pvoidptr_t idxPtr = (pvoidptr_t)((pptr_t)pStringTable + idx * sizeof(pcharptr_t));

		// precteme nalezenou polozku tabulky, kterou je ukazatel na cilovy retezec
		pcharptr_t strPtr = read_pconst_pchar(idxPtr);

		return strPtr;
	}
	else {
		return NULL;
	}
}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani stringu z tabulky stringu

	\return	Kopie do bufferu
*/
//----------------------------------------------------
static inline char_t * dtaCopyString( char_t * const dest, const uint16_t size, const stringindex_t idx )
{
	// ziskame ukazatel na retezec
	pcharptr_t tmp = dtaGetStringPtr(idx);
	strcpy_pconst(dest, size, tmp);
	return dest;
}

//----------------------------------------------------
//! Makro pro ziskani stringu do bufferu - automaticke, zjisti delku, vytvori buffer a zkopiruje
#define dtaGetString(bufName, idx) \
	pcharptr_t ___dtagetstringstr##bufName = dtaGetStringPtr(idx); \
	char_t * bufName; \
	if (___dtagetstringstr##bufName != NULL) \
	{ \
		size_t ___dtagetstringstrlen##bufName = strlen_pconst(___dtagetstringstr##bufName) + 1; \
		bufName = (char_t *)alloca(___dtagetstringstrlen##bufName * sizeof(char_t)); \
		strcpy_pconst(bufName, ___dtagetstringstrlen##bufName, ___dtagetstringstr##bufName); \
	} \
	else \
	{ \
		bufName = NULL; \
	}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani indexu retezce jednotky
*/
//----------------------------------------------------
static inline stringindex_t dtaGetUnitStrIdx( const PARAMETER_ITEM * const Desc )
{
	return Desc->IUnit;
}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani nazvu jazyka z tabulky stringu
*/
//----------------------------------------------------
static inline char_t * dtaGetLanguageStr( char_t * const dest, const uint8_t size )
{
#ifdef COMPILED_LIB
	return dtaCopyString( dest, size, constsniLanguage);
#else
	return dtaCopyString( dest, size, sniLanguage );
#endif //COMPILED_LIB
}

//----------------------------------------------------
/*
	\brief	Funkce pro nastaveni jazykove varianty tabulky stringu
*/
//----------------------------------------------------
static inline void dtaSetLanguage( const uint8_t language )
{
#ifdef COMPILED_LIB
	pStringTable = *((pvoidptr_t*)(((pptr_t)(ptrcLanguageTable) + language*sizeof(pvoidptr_t))));
#else
	pStringTable = cLanguageTable[language];
#endif //COMPILED_LIB
}

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani indexu do tabulky stringu z Access z option parametru
*/
//----------------------------------------------------
static stringindex_t dtaGetAccessIndex( const dataoption_t desc ) _const;
static inline stringindex_t dtaGetAccessIndex( const dataoption_t desc )
{
#ifdef COMPILED_LIB
	return ( constsniACCESS0 + dtaGetAccess( desc ) );
#else
	return ( sniACCESS0 + dtaGetAccess( desc ) );
#endif //COMPILED_LIB
}

//----------------------------------------------------
/**
	\brief	Funkce navrati textovy pristup parametru
*/
//----------------------------------------------------
static inline char_t * dtaGetAccessStr( const PARAMETER_ITEM * const param, char_t * dest, const uint8_t size )
{
	return dtaCopyString( dest, size, dtaGetAccessIndex( param->Option ) );
}

//----------------------------------------------------
/**
	\brief	Funkce navrati popis parametru
*/
//----------------------------------------------------

char_t * dtaGetDescStr(const PARAMETER_ITEM * const _param, char_t * _dest, const uint8_t _size);


//----------------------------------------------------
/**
	\brief	Funkce navrati popis jednotky parametru
*/
//----------------------------------------------------
static inline char_t * dtaGetUnitStr( const PARAMETER_ITEM * const param, char_t * dest, const uint8_t size )
{
	if (dtaGetType(param->Type) != VT_TYPE_ENUM)
	{
		return dtaCopyString( dest, size, param->IUnit );
	}
	else
	{
		dest[0] = (char_t)0;
		return dest;
	}
}

//----------------------------------------------------
/**
	\brief	Funkce navrati inkrement pro editaci ve stejnem typu, jako je samotna hodnota
*/
//----------------------------------------------------

datavalue_t * dtaGetIncr(const PARAMETER_ITEM * const _desc, datavalue_t * const _data);

 #endif // DTDEF_XML_MINIMAL

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

//----------------------------------------------------
/**
	\brief	Funkce pro prime ziskani udaju ze struktury na zaklade kodu
*/
//----------------------------------------------------
static inline dataoption_t dtcGetOption( const paramcode_t Code )
{
	const PARAM_DESC_ITEM * par = dtaParamDesc(dtaGetParam( Code ) );
	return read_pconst_byte( &par->Option );
}

static inline dataoffset_t dtcGetOffset( const paramcode_t Code )
{
	const PARAM_DESC_ITEM * par = dtaParamDesc( dtaGetParam( Code ) );
	return read_pconst_dword( &par->Offset );
}

static inline dataindex_t dtcGetDataIndex( const paramcode_t Code )
{
	const PARAM_DESC_ITEM * par = dtaParamDesc( dtaGetParam( Code ) );
	return read_pconst_word( &par->IData );
}

static inline indexindex_t dtcGetIndexIndex( const paramcode_t Code )
{
	const PARAM_DESC_ITEM * par = dtaParamDesc( dtaGetParam( Code ) );
	return read_pconst_word( &par->IIndex );
}

static inline stringindex_t dtcGetDescIndex( const paramcode_t Code )
{
	const PARAM_DESC_ITEM * par = dtaParamDesc( dtaGetParam(Code) );
	return read_pconst_word( &par->IDesc );
}

static inline stringindex_t dtcGetUnitIndex( const paramcode_t Code )
{
	const PARAM_DESC_ITEM * par = dtaParamDesc( dtaGetParam( Code ) );
	return read_pconst_word( &par->IUnit );
}

static inline datatype_t dtcGetType( const paramcode_t Code )
{
	const DATA_DESC_ITEM * dat = dtaDataDesc( dtcGetDataIndex( Code ) );
	return read_pconst_byte( &dat->Type );
}

static inline datascale_t dtcGetScale( const paramcode_t Code )
{
	const DATA_DESC_ITEM * dat = dtaDataDesc( dtcGetDataIndex( Code ) );
	return read_pconst_dword( &dat->Scale );
}

static inline dataprecision_t dtcGetPrecision( const paramcode_t Code )
{
	const DATA_DESC_ITEM * dat = dtaDataDesc( dtcGetDataIndex( Code ) );
	return read_pconst_word( &dat->Precision );
}

static inline dataextpptr_t dtcGetExtPtr( const paramcode_t Code )
{
	const DATA_DESC_ITEM * dat = dtaDataDesc( dtcGetDataIndex( Code ) );
	return (dataextpptr_t)read_pconst_ptr( &dat->ExtPtr );			//!<Ka
}

static inline indexcount_t dtcGetCount0( const paramcode_t Code )
{
	const INDEX_DESC_ITEM * idx = dtaIndexDesc( dtcGetIndexIndex( Code ) );
	return read_pconst_byte( &idx->Count0 );
}

static inline indexsize_t dtcGetSize0( const paramcode_t Code )
{
	const INDEX_DESC_ITEM * idx = dtaIndexDesc( dtcGetIndexIndex( Code ) );
	return read_pconst_word( &idx->Size0 );
}

static inline indexcount_t dtcGetCount1( const paramcode_t Code )
{
	const INDEX_DESC_ITEM * idx = dtaIndexDesc( dtcGetIndexIndex( Code ) );
	return read_pconst_byte( &idx->Count1 );
}

static inline indexsize_t dtcGetSize1( const paramcode_t Code )
{
	const INDEX_DESC_ITEM * idx = dtaIndexDesc( dtcGetIndexIndex( Code ) );
	return read_pconst_word( &idx->Size1 );
}

static inline indexcount2_t dtcGetCount2(const paramcode_t Code)
{
	const INDEX_DESC_ITEM * idx = dtaIndexDesc( dtcGetIndexIndex( Code ) );
	return read_pconst_word( &idx->Count2 );
}

static inline indexsize_t dtcGetSize2( const paramcode_t Code )
{
	const INDEX_DESC_ITEM * idx = dtaIndexDesc( dtcGetIndexIndex( Code ) );
	return read_pconst_word( &idx->Size2 );
}

static inline datavalue_t * dtcGetValuePtr( const paramcode_t Code )
{
#ifdef COMPILED_LIB
	return (datavalue_t*)((ptr_t)ptrgParam + dtcGetOffset( Code ) );
#else
	return (datavalue_t*)((ptr_t)&gParam + dtcGetOffset( Code ) );
#endif //COMPILED_LIB
}

static inline datavalue_t dtcGetValue( const paramcode_t Code )
{
	datavalue_t * ptr = dtcGetValuePtr( Code );
	return *ptr;
}

static inline void dtcSetValue( const paramcode_t Code, datavalue_t Value )
{
	datavalue_t * ptr = dtcGetValuePtr( Code );
	pck_memcpy( ptr, &Value, dtaGetTypeSize( dtcGetType( Code ) ) );
}

//----------------------------------------------------
/**
	\brief	Funkce kontroluje Code a nastavuje promenou Error dle zjistene chyby
*/
//----------------------------------------------------
static bool_t dtcCheckCode( const paramcode_t Code ) _const;
static inline bool_t dtcCheckCode( const paramcode_t Code )
{
#ifdef COMPILED_LIB
	return ( dtaGetParam( Code ) < constParamIndex_max );
#else
	return ( dtaGetParam( Code ) < ParamIndex_max );
#endif //COMPILED_LIB
}

#endif // DTDEF_XML_PARAM


//----------------------------------------------------
/*
	\brief	Funkce kontroluje hodnotu a nastavuje promenou Error dle zjistene chyby

	\param	param	Popisovac parametru
	\param	value	ukazatel na hodnotu parametru

	\return	Vraci TRUE, kdyz je vse OK
*/
//----------------------------------------------------
bool_t dtaCheckRange( PARAMETER_ITEM* const _param, const datavalue_t* const _value );


//----------------------------------------------------
/**
	\brief	Funkce kontroluje indexy a nastavuje promenou Error dle zjistene chyby
*/
//----------------------------------------------------
bool_t dtaCheckIndex( PARAMETER_ITEM* const param );

#ifdef DTDEF_XML_PARAM

//----------------------------------------------------
/**
	\brief	Funkce kontroluje Code a nastavuje promenou Error dle zjistene chyby
*/
//----------------------------------------------------
static inline bool_t dtaCheckCode( PARAMETER_ITEM* const param )
{
	param->Error = PERR_NONE;
#ifdef COMPILED_LIB
	if (dtaGetParam(param->Code) >= constParamIndex_max)
#else
	if (dtaGetParam(param->Code) >= ParamIndex_max)
#endif //COMPILED_LIB
	{
		param->Error = PERR_CODE;
	}

	return (param->Error == PERR_NONE);
}

#endif // DTDEF_XML_PARAM

//----------------------------------------------------
/**
	\brief	Funkce pro ziskani informaci o parametru a nastavuje promenou Error dle zjistene chyby
*/
//----------------------------------------------------
bool_t dtaGetParameters( PARAMETER_ITEM* const param, const paramcode_t code );

#ifndef DTDEF_XML_MINIMAL

//----------------------------------------------------
/**
	\brief	Konverze hodnoty na text

	\param	desc	Popisovac parametru
	\param	value	Konvertovana hodnota
	\param	str		Buffer pro ulozeni vysledku
	\param	size	Velikost bufferu

	\return	TRUE, pokud byla hodnota nalezena, FALSE pokud ne, pak je Result nedefinovany
*/
//----------------------------------------------------

bool_t dtaValueToStr( const PARAMETER_ITEM * desc, const datavalue_t * const value, char_t * const str, const uint16_t size );


//----------------------------------------------------
/**
	\brief	Konverze textu na hodnotu

	\param	desc	Popisovac parametru
	\param	value	Konvertovana hodnota
	\param	str		Konvertovany retezec

	\return	0 = OK, jinak chybovy kod
*/
//----------------------------------------------------

uint8_t dtaStrToValue( PARAMETER_ITEM * const desc, datavalue_t * const value, const char_t * const str );


//----------------------------------------------------
/*
	\brief	Funkce pro provedeni kroku dolu/nahoru nad parametrem

	\param	parDef		ukazatel do pole parametru (ukazatel do FLASH)
	\param	code		kod parametru
	\param	value		ukazatel na hodnotu parametru
	\param	up			1=krok nahoru/0=krok dolu

	\return	Funkce vraci TRUE hodnotu, pokud byl krok proveden
*/
//----------------------------------------------------

bool_t dtaDoStep( const PARAMETER_ITEM * const desc, datavalue_t * const value, const bool_t up );

#endif // DTDEF_XML_MINIMAL

//----------------------------------------------------
/**
	\brief	Funkce pro vypocet poctu platnych parametru

	\param	includeLocal	Do vypoctu zahrnou i lokalni parametry
*/
//----------------------------------------------------

uint16_t dtaCalcParamCount( const bool_t includeLocal );


//----------------------------------------------------
/**
	\brief	Ziska nasledujici kod ve strukture

	\param	Code			Vstupni kod
	\param	includeLocal	Priznak, zda se maji do prochazeni zahrnout i lokalni parametry

	\return		Platne cislo nasledujiciho kodu, pokud je posledni, tak neplatny kod
*/
//----------------------------------------------------

paramcode_t dtaNextCode( paramcode_t code, const bool_t includeLocal );

//----------------------------------------------------
/**
	\brief	Konverze definovane hodnoty enum8 na vnitrni

	\param	param	Popisovac parametru
	\param	Value	Konvertovana hodnota - I/O

	\return	TRUE, pokud byla hodnota nalezena, FALSE pokud ne, pak je Result nedefinovany
*/
//----------------------------------------------------

bool_t dtaEnum8DefToOrd(PARAMETER_ITEM * const param, enum8_t * const Value);


//----------------------------------------------------
/**
	\brief	Konverze definovane hodnoty enum16 na vnitrni

	\param	param	Popisovac parametru
	\param	Value	Konvertovana hodnota - I/O

	\return	TRUE, pokud byla hodnota nalezena, FALSE pokud ne, pak je Result nedefinovany
*/
//----------------------------------------------------

bool_t dtaEnum16DefToOrd(PARAMETER_ITEM * const param, enum16_t * const Value);


//----------------------------------------------------
/**
	\brief	Konverze vnitrni hodnoty enum8 na definovanou

	\param	param	Popisovac parametru
	\param	Value	Konvertovana hodnota - I/O

	\return	TRUE, pokud byla hodnota nalezena, FALSE pokud ne, pak je Result nedefinovany
*/
//----------------------------------------------------

bool_t dtaEnum8OrdToDef(PARAMETER_ITEM * const param, enum8_t * const Value);

//----------------------------------------------------
/**
	\brief	Konverze vnitrni hodnoty enum16 na definovanou

	\param	param	Popisovac parametru
	\param	Value	Konvertovana hodnota - I/O

	\return	TRUE, pokud byla hodnota nalezena, FALSE pokud ne, pak je Result nedefinovany
*/
//----------------------------------------------------

bool_t dtaEnum16OrdToDef(PARAMETER_ITEM * const param, enum16_t * const Value);

//----------------------------------------------------
//!\name	Funkce pro praci s enumy, nepouzivaji se primo, ale pomoci maker
//@{

//----------------------------------------------------
/**
	\brief	Hleda hodnotu v poli definovanych hodnot enum8

	\param	Result	Vystupni parametr - vysledny index
	\param	Data	Pole definovanych hodnot
	\param	Value	Hledana hodnota
	\param	Max		Pocet prvku v poli

	\return	TRUE, pokud byla hodnota nalezena, FALSE pokud ne, pak je Result nedefinovany
*/
//----------------------------------------------------
bool_t _SearchEnum8(uint8_t * const Result, const int8_t * Data, const int8_t Value, const uint8_t Max);
//----------------------------------------------------
/**
	\brief	Hleda hodnotu v poli definovanych hodnot enum16

	\param	Result	Vystupni parametr - vysledny index
	\param	Data	Pole definovanych hodnot
	\param	Value	Hledana hodnota
	\param	Max		Pocet prvku v poli

	\return	TRUE, pokud byla hodnota nalezena, FALSE pokud ne, pak je Result nedefinovany
*/
//----------------------------------------------------
bool_t _SearchEnum16(uint16_t * const Result, const int16_t * Data, const int16_t Value, const uint16_t Max);
//----------------------------------------------------
/**
	\brief	Hleda hodnotu v poli setridenych definovanych hodnot enum8

	\param	Result	Vystupni parametr - vysledny index
	\param	Data	Pole definovanych hodnot
	\param	Value	Hledana hodnota
	\param	Max		Pocet prvku v poli

	\return	TRUE, pokud byla hodnota nalezena, FALSE pokud ne, pak je Result nedefinovany
*/
//----------------------------------------------------
bool_t _BinSearchEnum8(uint8_t * const Result, const int8_t * Data, const int8_t Value, const uint8_t Max);
//----------------------------------------------------
/**
	\brief	Hleda hodnotu v poli setridenych definovanych hodnot enum16

	\param	Result	Vystupni parametr - vysledny index
	\param	Data	Pole definovanych hodnot
	\param	Value	Hledana hodnota
	\param	Max		Pocet prvku v poli

	\return	TRUE, pokud byla hodnota nalezena, FALSE pokud ne, pak je Result nedefinovany
*/
//----------------------------------------------------
bool_t _BinSearchEnum16(uint16_t * const Result, const int16_t * Data, const int16_t Value, const uint16_t Max);
//@}

//----------------------------------------------------
//!	\name	Makra pro praci s enumy
//@{
#ifdef COMPILED_LIB
//----------------------------------------------------
//! Makro vraci definovanou hodnotu na zaklade poradi polozky
#define GetEnumDefinedVal( enumtype, idx ) \
	(ptrc ## enumtype[( idx )])


//----------------------------------------------------
//! Makro vraci poradi polozky na zaklade definovane hodnoty
#define GetEnumOrdinalVal( resptr, enumtype, val ) \
	((sizeof(*ptrc ## enumtype) == 1) ? \
			_SearchEnum8((uint8_t *)(resptr), (const int8_t *)(ptrc ## enumtype), (int8_t)(val), (const ## enumtype ## _max)) \
				: \
		((sizeof(*ptrc ## enumtype) == 2) ? \
			_SearchEnum16((uint16_t *)(resptr), (const int16_t *)(ptrc ## enumtype), (int16_t)(val), (const ## enumtype ## _max)) \
			: \
			FALSE))

//----------------------------------------------------
//! Makro vraci poradi polozky na zaklade definovane hodnoty, pokud jsou definovane hodnoty setridene
#define GetSortedEnumOrdinalVal( resptr, enumtype, val ) \
	((sizeof(enumtype) == 1) ? \
			_BinSearchEnum8((uint8_t *)(resptr), (const int8_t *)(ptrc ## enumtype), (int8_t)(val), (const ## enumtype ## _max)) \
				: \
		((sizeof(enumtype) == 2) ? \
			_BinSearchEnum16((uint16_t *)(resptr), (const int16_t *)(ptrc ## enumtype), (int16_t)(val), (const ## enumtype ## _max)) \
			: \
			FALSE))
#else //COMPILED_LIB
//----------------------------------------------------
//! Makro vraci definovanou hodnotu na zaklade poradi polozky
#define GetEnumDefinedVal( enumtype, idx ) \
	(c ## enumtype[( idx )])


//----------------------------------------------------
//! Makro vraci poradi polozky na zaklade definovane hodnoty
#define GetEnumOrdinalVal( resptr, enumtype, val ) \
	((sizeof(enumtype) == 1) ? \
			_SearchEnum8((uint8_t *)(resptr), (const int8_t *)(c ## enumtype), (int8_t)(val), enumtype ## _max) \
				: \
		((sizeof(enumtype) == 2) ? \
			_SearchEnum16((uint16_t *)(resptr), (const int16_t *)(c ## enumtype), (int16_t)(val), enumtype ## _max) \
			: \
			FALSE))

//----------------------------------------------------
//! Makro vraci poradi polozky na zaklade definovane hodnoty, pokud jsou definovane hodnoty setridene
#define GetSortedEnumOrdinalVal( resptr, enumtype, val ) \
	((sizeof(enumtype) == 1) ? \
			_BinSearchEnum8((uint8_t *)(resptr), (const int8_t *)(c ## enumtype), (int8_t)(val), enumtype ## _max) \
				: \
		((sizeof(enumtype) == 2) ? \
			_BinSearchEnum16((uint16_t *)(resptr), (const int16_t *)(c ## enumtype), (int16_t)(val), enumtype ## _max) \
			: \
			FALSE))
#endif //COMPILED_LIB
//@}

struct _DATADEF_CTX;

//----------------------------------------------------
//!	\name	Metody datadefu
//@{

typedef void (*dtacbDone) ( const paramcode_t Code, const datavalue_t * const Data, const PARAM_ERROR status, void * const UserData );
typedef PARAM_ERROR (*dmLoadParam_t) ( const struct _DATADEF_CTX * const ctx, const paramcode_t Code, datavalue_t * const Val, uint16_t * const Size );
typedef PARAM_ERROR (*dmSaveParam_t) ( struct _DATADEF_CTX * const ctx, const paramcode_t Code, datavalue_t * const Data, const dtacbDone Done, void * const CbUserData );

typedef PARAM_ERROR (*dmSaveParamBefore_t) ( const paramcode_t Code, datavalue_t * const NewData, void * const UserData );
typedef PARAM_ERROR (*dmSaveParamAfter_t) ( const paramcode_t Code, const datavalue_t * const Data, const PARAM_ERROR Result, void * const UserData );
typedef PARAM_ERROR (*dmLoadParamBefore_t) ( const paramcode_t Code, void * const UserData );
typedef PARAM_ERROR (*dmLoadParamAfter_t) ( const paramcode_t Code, datavalue_t * const Data, const PARAM_ERROR Result, void * const UserData );
//@}

//----------------------------------------------------
//! Struktura pro uchovani odkazu na specialni nazvy prvku pole

typedef struct _DATADEF_ARRAYNAME
{
	uint8_t			Idx;		//!< Index parametru, ktery urcuje poradi polozky pole
	paramcode_t		Code;		//!< Kod s nulovym urcujicim indexem, ktereho se pojmenovavani tyka
	stringindex_t	Str;		//!< Popis prvni polozky pole, ostatni nasleduji
} DATADEF_ARRAYNAME;

//----------------------------------------------------
//! Kontext datadefu
typedef struct _DATADEF_CTX
{
	volatile bool_t			flRunning;

	dmLoadParam_t			LoadParam;
	dmSaveParam_t			SaveParam;

	dmSaveParamBefore_t		SaveParamBefore;
	dmSaveParamAfter_t		SaveParamAfter;
	dmLoadParamBefore_t		LoadParamBefore;
	dmLoadParamAfter_t		LoadParamAfter;

	void *	SaveParamBeforeUserData;
	void *	SaveParamAfterUserData;
	void *	LoadParamBeforeUserData;
	void *	LoadParamAfterUserData;

#ifdef DTDEF_ARRAY_NAMES
	DATADEF_ARRAYNAME		ArrayNames[DTDEF_ARRAY_NAMES];
#endif // DTDEF_ARRAY_NAMES
#ifndef MSVC
} DATADEF_CTX  __attribute__ ((aligned));
#else
} DATADEF_CTX;
#endif

//----------------------------------------------------
/**
	\brief	Zkopiruje hodnotu parametru do bufferu
*/
//----------------------------------------------------

PARAM_ERROR dtaLoadParam(const paramcode_t Code, datavalue_t * const Val, uint16_t * const Size);


//----------------------------------------------------
/**
	\brief	ulozi hodnotu parametru v bufferu do pameti
*/
//----------------------------------------------------

PARAM_ERROR dtaSaveParam(const paramcode_t Code, datavalue_t * const Data, dtacbDone Done, void * const UserData);


//----------------------------------------------------
/**
	\brief	zavola callback dokonceni nacitani parametru
*/
//----------------------------------------------------

PARAM_ERROR dtaLoadParamDone(const paramcode_t Code, datavalue_t * const Data, const PARAM_ERROR Result);


//----------------------------------------------------
/**
	\brief	zavola callback dokonceni ukladani parametru
*/
//----------------------------------------------------

PARAM_ERROR dtaSaveParamDone(const paramcode_t Code, const datavalue_t * const Data, const PARAM_ERROR Result);

void dtaSetMethodLoadParam(DATADEF_CTX * const ctx, dmLoadParam_t Method);
void dtaSetMethodSaveParam(DATADEF_CTX * const ctx, dmSaveParam_t Method);

void dtaSetMethodSaveParamBefore(DATADEF_CTX * const ctx, dmSaveParamBefore_t Method, void * const UserData);
void dtaSetMethodSaveParamAfter(DATADEF_CTX * const ctx, dmSaveParamAfter_t Method, void * const UserData);

void dtaSetMethodLoadParamBefore(DATADEF_CTX * const ctx, dmLoadParamBefore_t Method, void * const UserData);
void dtaSetMethodLoadParamAfter(DATADEF_CTX * const ctx, dmLoadParamAfter_t Method, void * const UserData);

#ifdef DTDEF_ARRAY_NAMES
bool_t dtaSetArrayNames(const paramcode_t _code, const uint8_t _idx, const stringindex_t _str);
bool_t dtaClearArrayNames(const paramcode_t _code, uint8_t _idx);
#endif // DTDEF_ARRAY_NAMES

void DatadefInitialize(DATADEF_CTX * const ctx);
void DatadefFinalize(DATADEF_CTX * const ctx);

#endif // _DATADEF_H_

