/*
 * State assistance routines.
 * (C) May 16 2018 K.Ohta <whatisthis.sowhat _at_ gmail.com>
 * License: GPLv2 (or later)
 * Usage:
 * 1. Decl. state entries per device.
 *  #define STATE_VERSION n;
 *    void foo::decl_state(void)
 *    {
 *      state_entry = new csp_state_utils(STATE_VERSION, this_device_id, _T("NAME")); // Must be.
 *      DECL_STATE_ENTRY(var1)
 *      DECL_STATE_ENTRY_MULTI(array, sizeof(array));
 *    }
 * 2. Call decl_state() from VM's decl_state().
 * 3.
 * void foo::save_state(FILEIO *state_fio)
 * {
 *    if(state_entry != NULL) state_entry->save_state(state_fio, NULL); // Arg2 is pointer of initial CRC value.
 * }
 * bool foo::load_state(FILEIO *state_fio)
 * {
 *    if(state_entry != NULL) return state_entry->load_state(state_fio, NULL); // Arg2 is pointer of initial CRC value.
 *    return false;
 * }
 */


#if !defined(_CSP_STATE_SUB_H)
#define _CSP_STATE_SUB_H
#include "common.h"
#include "fileio.h"
#include "fifo.h"

#include <string>
#include <list>
#include <vector>
#include <typeindex>
#include <map>
//#include "state_data.h"
#if defined(_USE_QT)
#include <QObject>
#include <QString>
#endif
typedef enum csp_saver_type_t {
	csp_saver_entry_int = 0,
	csp_saver_entry_uint8,
	csp_saver_entry_int8,
	csp_saver_entry_uint16,
	csp_saver_entry_int16,
	csp_saver_entry_uint32,
	csp_saver_entry_int32,
	csp_saver_entry_uint64,
	csp_saver_entry_int64,
	csp_saver_entry_bool,
	csp_saver_entry_char,
	csp_saver_entry_tchar,
	csp_saver_entry_pair,
	csp_saver_entry_float,
	csp_saver_entry_double,
	csp_saver_entry_long_double,
	csp_saver_entry_void,
	csp_saver_entry_string,
	csp_saver_entry_cmt_recording,	
	csp_saver_entry_scrntype_t,
	csp_saver_entry_any,
	
	csp_saver_entry_fifo,
	csp_saver_entry_cur_time_t,
	csp_saver_entry_device,
	
	csp_saver_entry_custom0 = 256,
	csp_saver_entry_custom1 = 257,
	csp_saver_entry_custom2 = 258,
	csp_saver_entry_custom3 = 259,
	
	// Below are special value
	csp_saver_entry_vararray = 0x10000,
	csp_saver_entry_const = 0x20000,
};


class CSP_Logger;
class csp_state_data_saver;

#if defined(_USE_QT)
  QT_BEGIN_NAMESPACE
class DLL_PREFIX csp_state_utils : public QObject {
#else
class DLL_PREFIX csp_state_utils {
#endif
#if defined(_USE_QT)
	Q_OBJECT
#endif
private:
	int64_t nr_lines;
protected:
	typedef union  {
		int64_t s;
		uint64_t u;
		void *p;
	} union64_t;
	
	CSP_Logger *logger;
	const uint32_t CRC_MAGIC_WORD = 0x04C11DB7;
	struct __list_t {
		int type_id;
		int local_num;
		int stride;
		bool assume_byte;
		int len;
		int atomlen;
		std::string name;
		void *ptr;
		int *datalenptr;
		
		void *recv_ptr;
		_TCHAR *path_ptr;
	};
	//std::list<__list_t>listptr;
	std::vector<__list_t>listptr;
	_TCHAR __classname[128];
	_TCHAR __classname_bak[128];
	
	uint32_t crc_value;
	_TCHAR magic[16];
	_TCHAR magic_bak[16];
	int class_version;
	int class_version_bak;
	int internal_version;
	int internal_version_bak;
	int this_device_id;
	int this_device_id_bak;
	csp_state_data_saver *fio;

	void out_debug_log(const char *fmt, ...);
	
	int save_sub_char(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int save_sub_float(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int save_sub_double(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int save_sub_long_double(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int save_sub_pair_t(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int save_sub_int(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int save_sub_uint8(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int save_sub_int8(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int save_sub_uint16(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int save_sub_int16(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int save_sub_uint32(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int save_sub_int32(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int save_sub_uint64(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int save_sub_int64(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int save_sub_bool(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int save_sub_tchar(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int save_sub_string(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);

	int save_sub_fifo(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int save_sub_cur_time_t(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int save_sub_scrntype_t(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);

	int save_sub_byte_array(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride, int _atomsize);
	int save_sub_cmt_recording(uint32_t *crc_value, bool *_stat, void *pp, FILEIO **ffp, int _len, int _stride);

	int load_sub_char(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int load_sub_float(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int load_sub_double(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int load_sub_long_double(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int load_sub_pair_t(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int load_sub_int(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int load_sub_uint8(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int load_sub_int8(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int load_sub_uint16(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int load_sub_int16(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int load_sub_uint32(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int load_sub_int32(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int load_sub_uint64(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int load_sub_int64(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int load_sub_bool(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int load_sub_tchar(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int load_sub_string(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	
	int load_sub_fifo(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int load_sub_cur_time_t(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);
	int load_sub_scrntype_t(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride);

	int load_sub_byte_array(uint32_t *crc_value, bool *_stat, void *pp, int _len, int _stride, int _atomsize);
	int load_sub_cmt_recording(uint32_t *crc_value, bool *_stat, void *pp, FILEIO **ffp, _TCHAR *__path, int _len, int _stride);
	
	std::map <std::type_index, int> typeid_map= {
		{ typeid(int),  csp_saver_entry_int },
		{ typeid(pair_t), csp_saver_entry_pair },
		{ typeid(float), csp_saver_entry_float },
		{ typeid(double), csp_saver_entry_double },
		{ typeid(long double), csp_saver_entry_long_double },
		{ typeid(int8_t), csp_saver_entry_int8 },
		{ typeid(uint8_t), csp_saver_entry_uint8 },
		{ typeid(int16_t), csp_saver_entry_int16 },
		{ typeid(uint16_t), csp_saver_entry_uint16 },
		{ typeid(int32_t), csp_saver_entry_int32 },
		{ typeid(uint32_t), csp_saver_entry_uint32 },
		{ typeid(int64_t), csp_saver_entry_int64 },
		{ typeid(uint64_t), csp_saver_entry_uint64 },
		{ typeid(char), csp_saver_entry_char },
		{ typeid(bool), csp_saver_entry_bool },
		{ typeid(void), csp_saver_entry_void },
		{ typeid(FIFO), csp_saver_entry_fifo },
		{ typeid(cur_time_t), csp_saver_entry_cur_time_t },
		{ typeid(scrntype_t), csp_saver_entry_scrntype_t }
	};

public:
	csp_state_utils(int _version = 1, int device_id = 1, const _TCHAR *classname = NULL, CSP_Logger* p_logger = NULL);
	~csp_state_utils();
	std::list<std::string> get_entries_list(void);

	template <class T>
	void add_entry(const _TCHAR *__name, T *p, int _len = 1, int __num = -1, bool is_const = false, int stride = 0);
	template <class T>
	void add_entry_vararray(const _TCHAR *__name, T **p, void *datalen, bool assume_byte = false, int __num = -1, int stride = 0);

	void add_entry_fifo(const _TCHAR *__name, FIFO **p, int _len = 1, int __num = -1, int stride = 0);
	void add_entry_cur_time_t(const _TCHAR *__name, cur_time_t *p, int _len = 1, int __num = -1, int stride = 0);
	void add_entry_string(const _TCHAR *__name, _TCHAR *p, int _len = 1, int __num = -1, bool is_const = false);
	void add_entry_scrntype_t(const _TCHAR *__name, scrntype_t *p, int _len = 1, int __num = -1, int stride = 0);
	void add_entry_cmt_recording(const _TCHAR *__name, FILEIO **__fio, bool* __flag, _TCHAR *__path); 
	
	uint32_t get_crc_value(void);
	void get_class_name(_TCHAR *buf, int len);
	void save_state(FILEIO *__fio, uint32_t *pcrc = NULL);
	bool load_state(FILEIO *__fio, uint32_t *pcrc = NULL);
#if defined(_USE_QT)
signals:
	int sig_debug_log(int, int, QString);
#endif
};
#if defined(_USE_QT)
    QT_END_NAMESPACE
#endif
			
#define DECL_STATE_ENTRY0(_n_name, __list) {				  \
		__list->add_entry((const _TCHAR *)_T(#_n_name), &_n_name);		  \
	}

#define DECL_STATE_ENTRY1(_n_name, __list, __len) {				\
		__list->add_entry((const _TCHAR *)_T(#_n_name), _n_name, __len);		\
	}

#define DECL_STATE_ENTRY2(_n_name, __list, __len, __n) {					\
		__list->add_entry((const _TCHAR *)_T(#_n_name), &_n_name, __len, __n); \
	}

#define DECL_STATE_ENTRY4(_n_name, __list, __len, __n, __stride) {				\
			__list->add_entry((const _TCHAR *)_T(#_n_name), &_n_name, __len, __n, false, __stride); \
	}
		
#define DECL_STATE_ENTRY_MULTI0(__type, _n_name, __list, __size) {		\
		__list->add_entry((const _TCHAR *)_T(#_n_name), (uint8_t *)_n_name, __size * sizeof(__type)); \
	}
   
#define DECL_STATE_ENTRY_INT(___name) DECL_STATE_ENTRY0(___name, state_entry)

#define DECL_STATE_ENTRY_UINT8(___name) DECL_STATE_ENTRY0(___name, state_entry)
#define DECL_STATE_ENTRY_INT8(___name) DECL_STATE_ENTRY0(___name, state_entry)
#define DECL_STATE_ENTRY_UINT16(___name) DECL_STATE_ENTRY0(___name, state_entry)
#define DECL_STATE_ENTRY_INT16(___name) DECL_STATE_ENTRY0(___name, state_entry)
#define DECL_STATE_ENTRY_UINT32(___name) DECL_STATE_ENTRY0(___name, state_entry)
#define DECL_STATE_ENTRY_INT32(___name) DECL_STATE_ENTRY0(___name, state_entry)
#define DECL_STATE_ENTRY_UINT64(___name) DECL_STATE_ENTRY0( ___name, state_entry)
#define DECL_STATE_ENTRY_INT64(___name) DECL_STATE_ENTRY0(___name, state_entry)
#define DECL_STATE_ENTRY_PAIR(___name) DECL_STATE_ENTRY0(___name, state_entry)
#define DECL_STATE_ENTRY_BOOL(___name) DECL_STATE_ENTRY0(___name, state_entry)
#define DECL_STATE_ENTRY_TCHAR(___name) DECL_STATE_ENTRY0(___name, state_entry)
#define DECL_STATE_ENTRY_FLOAT(___name) DECL_STATE_ENTRY0(___name, state_entry)
#define DECL_STATE_ENTRY_DOUBLE(___name) DECL_STATE_ENTRY0(___name, state_entry)
#define DECL_STATE_ENTRY_LONG_DOUBLE(___name) DECL_STATE_ENTRY0(___name, state_entry)

#define DECL_STATE_ENTRY_UINT8_ARRAY(___name, __len) DECL_STATE_ENTRY1(___name, state_entry, __len)
#define DECL_STATE_ENTRY_INT8_ARRAY(___name, __len)  DECL_STATE_ENTRY1(___name, state_entry, __len)
#define DECL_STATE_ENTRY_UINT16_ARRAY(___name, __len) DECL_STATE_ENTRY1(___name, state_entry, __len)
#define DECL_STATE_ENTRY_INT16_ARRAY(___name, __len)  DECL_STATE_ENTRY1(___name, state_entry, __len)
#define DECL_STATE_ENTRY_UINT32_ARRAY(___name, __len) DECL_STATE_ENTRY1(___name, state_entry, __len)
#define DECL_STATE_ENTRY_INT32_ARRAY(___name, __len) DECL_STATE_ENTRY1(___name, state_entry, __len)
#define DECL_STATE_ENTRY_UINT64_ARRAY(___name, __len) DECL_STATE_ENTRY1(___name, state_entry, __len)
#define DECL_STATE_ENTRY_INT64_ARRAY(___name, __len) DECL_STATE_ENTRY1(___name, state_entry, __len)
#define DECL_STATE_ENTRY_BOOL_ARRAY(___name, __len) DECL_STATE_ENTRY1(___name, state_entry, __len)
#define DECL_STATE_ENTRY_PAIR_ARRAY(___name, __len) DECL_STATE_ENTRY1(___name, state_entry, __len)
#define DECL_STATE_ENTRY_FLOAT_ARRAY(___name, __len) DECL_STATE_ENTRY1(___name, state_entry, __len)
#define DECL_STATE_ENTRY_DOUBLE_ARRAY(___name, __len) DECL_STATE_ENTRY1(___name, state_entry, __len)
#define DECL_STATE_ENTRY_LONG_DOUBLE_ARRAY(___name, __len) DECL_STATE_ENTRY1(___name, state_entry, __len)

#define DECL_STATE_ENTRY_UINT8_MEMBER(___name, __num) DECL_STATE_ENTRY2(___name, state_entry, 1, __num)
#define DECL_STATE_ENTRY_INT8_MEMBER(___name, __num)  DECL_STATE_ENTRY2(___name, state_entry, 1, __num)
#define DECL_STATE_ENTRY_UINT16_MEMBER(___name, __num) DECL_STATE_ENTRY2(___name, state_entry, 1, __num)
#define DECL_STATE_ENTRY_INT16_MEMBER(___name, __num)  DECL_STATE_ENTRY2(___name, state_entry, 1, __num)
#define DECL_STATE_ENTRY_UINT32_MEMBER(___name, __num) DECL_STATE_ENTRY2(___name, state_entry, 1, __num)
#define DECL_STATE_ENTRY_INT32_MEMBER(___name, __num)  DECL_STATE_ENTRY2(___name, state_entry, 1, __num)
#define DECL_STATE_ENTRY_UINT64_MEMBER(___name, __num) DECL_STATE_ENTRY2(___name, state_entry, 1, __num)
#define DECL_STATE_ENTRY_INT64_MEMBER(___name, __num)  DECL_STATE_ENTRY2(___name, state_entry, 1, __num)
#define DECL_STATE_ENTRY_BOOL_MEMBER(___name, __num) DECL_STATE_ENTRY2(___name, state_entry, 1, __num)
#define DECL_STATE_ENTRY_PAIR_MEMBER(___name, __num)  DECL_STATE_ENTRY2(___name, state_entry, 1, __num)
#define DECL_STATE_ENTRY_UINT8_MEMBER(___name, __num) DECL_STATE_ENTRY2(___name, state_entry, 1, __num)
#define DECL_STATE_ENTRY_FLOAT_MEMBER(___name, __num)  DECL_STATE_ENTRY2(___name, state_entry, 1, __num)
#define DECL_STATE_ENTRY_DOUBLE_MEMBER(___name, __num) DECL_STATE_ENTRY2(___name, state_entry, 1, __num)
#define DECL_STATE_ENTRY_LONG_DOUBLE_MEMBER(___name, __num)  DECL_STATE_ENTRY2(___name, state_entry, 1, __num)

#define DECL_STATE_ENTRY_UINT8_STRIDE(___name, __len, __stride) DECL_STATE_ENTRY4(___name, state_entry, __len,  1, __stride)
#define DECL_STATE_ENTRY_INT8_STRIDE(___name, __len, __stride)  DECL_STATE_ENTRY4(___name, state_entry, __len,  1, __stride)
#define DECL_STATE_ENTRY_UINT16_STRIDE(___name, __len, __stride) DECL_STATE_ENTRY4(___name, state_entry, __len,  1, __stride)
#define DECL_STATE_ENTRY_INT16_STRIDE(___name, __len, __stride)  DECL_STATE_ENTRY4(___name, state_entry, __len,  1, __stride)
#define DECL_STATE_ENTRY_UINT32_STRIDE(___name, __len, __stride) DECL_STATE_ENTRY4(___name, state_entry, __len,  1, __stride)
#define DECL_STATE_ENTRY_INT32_STRIDE(___name, __len, __stride)  DECL_STATE_ENTRY4(___name, state_entry, __len,  1, __stride)
#define DECL_STATE_ENTRY_UINT64_STRIDE(___name, __len, __stride) DECL_STATE_ENTRY4(___name, state_entry, __len,  1, __stride)
#define DECL_STATE_ENTRY_INT64_STRIDE(___name, __len, __stride)  DECL_STATE_ENTRY4(___name, state_entry, __len,  1, __stride)
#define DECL_STATE_ENTRY_BOOL_STRIDE(___name, __len, __stride) DECL_STATE_ENTRY4(___name, state_entry, __len,  1, __stride)
#define DECL_STATE_ENTRY_PAIR_STRIDE(___name, __len, __stride)  DECL_STATE_ENTRY4(___name, state_entry, __len,  1, __stride)
#define DECL_STATE_ENTRY_UINT8_STRIDE(___name, __len, __stride) DECL_STATE_ENTRY4(___name, state_entry, __len,  1, __stride)
#define DECL_STATE_ENTRY_FLOAT_STRIDE(___name, __len, __stride)  DECL_STATE_ENTRY4(___name, state_entry, __len,  1, __stride)
#define DECL_STATE_ENTRY_DOUBLE_STRIDE(___name, __len, __stride) DECL_STATE_ENTRY4(___name, state_entry, __len,  1, __stride)
#define DECL_STATE_ENTRY_LONG_DOUBLE_STRIDE(___name, __len, __stride)  DECL_STATE_ENTRY4(___name, state_entry, __len,  1, __stride)


#define DECL_STATE_ENTRY_SCRNTYPE_T(__name) { \
			state_entry->add_entry_scrntype_t((_TCHAR *)(_T(#__name)), __name, 1, -1, 0); \
		}

#define DECL_STATE_ENTRY_SCRNTYPE_T_MEMBER(__name, __num) {					\
			state_entry->add_entry_scrntype_t((_TCHAR *)(_T(#__name)), __name, 1, __num, 0); \
		}

#define DECL_STATE_ENTRY_SCRNTYPE_T_1D_ARRAY(__name, __len) {					\
			state_entry->add_entry_scrntype_t((_TCHAR *)(_T(#__name)), __name, __len, -1, 0); \
		}

#define DECL_STATE_ENTRY_SCRNTYPE_T_2D_ARRAY(__name, __lenx, __leny) {			\
			state_entry->add_entry_scrntype_t((_TCHAR *)(_T(#__name)), &(__name[0][0]), (__lenx * __leny) , -1, 0); \
		}

#define DECL_STATE_ENTRY_SCRNTYPE_T_3D_ARRAY(__name, __lenx, __leny, __lenz) {	\
			state_entry->add_entry_scrntype_t((_TCHAR *)(_T(#__name)), &(__name[0][0][0]), (__lenx * __leny * __lenz), -1, 0); \
		}

#define DECL_STATE_ENTRY_SCRNTYPE_T_1D_ARRAY_MEMBER(__name, __len, __num) {	\
			state_entry->add_entry_scrntype_t((_TCHAR *)(_T(#__name)), __name, __num, -1, 0); \
		}

#define DECL_STATE_ENTRY_SCRNTYPE_T_2D_ARRAY_MEMBER(__name, __lenx, __leny, __num) {	\
			state_entry->add_entry_scrntype_t((_TCHAR *)(_T(#__name)), &(__name[0][0]), (__lenx * __leny) , __num, 0); \
		}

#define DECL_STATE_ENTRY_SCRNTYPE_T_3D_ARRAY_MEMBER(__name, __lenx, __leny, __lenz, __num) {	\
			state_entry->add_entry_scrntype_t((_TCHAR *)(_T(#__name)), &(__name[0][0][0]), (__lenx * __leny * __lenz), __num, 0); \
		}

		
#define DECL_STATE_ENTRY_SCRNTYPE_T_STRIDE(__name, __len, __stride) {	\
			state_entry->add_entry_scrntype_t((_TCHAR *)(_T(#__name)), __name, __len, -1, __stride); \
		}

#define DECL_STATE_ENTRY_SCRNTYPE_T_MEMBER_STRIDE(__name, __len, __num, __stride) {	\
			state_entry->add_entry_scrntype_t((_TCHAR *)(_T(#__name)), __name, __len, __num, __stride); \
		}
		

#define DECL_STATE_ENTRY_MULTI(_n_type, ___name, ___size) DECL_STATE_ENTRY_MULTI0(_n_type, ___name, state_entry, ___size)

#define DECL_STATE_ENTRY_STRING(___name, __len) { \
			state_entry->add_entry_string((_TCHAR *)(_T(#___name)), ___name, __len); \
	}

#define DECL_STATE_ENTRY_STRING_MEMBER(___name, __len, __num) {				\
			state_entry->add_entry_string((_TCHAR *)(_T(#___name)), ___name, __len, __num); \
	}

#define DECL_STATE_ENTRY_1D_ARRAY(___name, ___lenvar) { \
		state_entry->add_entry((const _TCHAR *)(_T(#___name)), ___name, ___lenvar); \
	}

#define DECL_STATE_ENTRY_2D_ARRAY(___name, __len1, __len2) {		\
		int __tmplen = ((int)__len1 * (int)__len2);					\
		state_entry->add_entry((const _TCHAR *)(_T(#___name)), &(___name[0][0]), __tmplen); \
	}

#define DECL_STATE_ENTRY_3D_ARRAY(___name, __len1, __len2, __len3) {	\
		int __tmplen = ((int)__len1 * (int)__len2 * (int)__len3);		\
		state_entry->add_entry((const _TCHAR *)_T(#___name), &(___name[0][0][0]), __tmplen); \
	}

#define DECL_STATE_ENTRY_4D_ARRAY(___name, __len1, __len2, __len3, __len4) {	\
		int __tmplen = ((int)__len1 * (int)__len2 * (int)__len3 * (int)__len4); \
		state_entry->add_entry((const _TCHAR *)_T(#___name), &(___name[0][0][0][0]), __tmplen); \
	}

#define DECL_STATE_ENTRY_1D_ARRAY_MEMBER(___name, ___lenvar, __num) {	\
		state_entry->add_entry((const _TCHAR *)(_T(#___name)), ___name, ___lenvar, __num); \
	}

#define DECL_STATE_ENTRY_2D_ARRAY_MEMBER(___name, __len1, __len2, __num) {	\
		int __tmplen = ((int)__len1 * (int)__len2);					\
		state_entry->add_entry((const _TCHAR *)(_T(#___name)), &(___name[0][0]), __tmplen, __num); \
	}

#define DECL_STATE_ENTRY_3D_ARRAY_MEMBER(___name, __len1, __len2, __len3, __num) { \
		int __tmplen = ((int)__len1 * (int)__len2 * (int)__len3);		\
		state_entry->add_entry((const _TCHAR *)_T(#___name), &(___name[0][0][0]), __tmplen, __num); \
	}

#define DECL_STATE_ENTRY_VARARRAY_VAR(_n_name, __sizevar) {				\
		state_entry->add_entry_vararray((const _TCHAR *)_T(#_n_name), &_n_name, (void *)(&__sizevar)); \
	}

#define DECL_STATE_ENTRY_VARARRAY_MEMBER(_n_name, __sizevar, __n) {			\
		state_entry->add_entry_vararray((const _TCHAR *)_T(#_n_name), &_n_name, (void *)(&__sizevar), false, __n); \
	}

#define DECL_STATE_ENTRY_VARARRAY_BYTES(_n_name, __sizevar) {				\
		state_entry->add_entry_vararray((const _TCHAR *)_T(#_n_name), &_n_name, (void *)(&__sizevar), true); \
	}

#define DECL_STATE_ENTRY_VARARRAY_BYTES_MEMBER(_n_name, __sizevar, __n) {	\
		state_entry->add_entry_vararray((const _TCHAR *)_T(#_n_name), &_n_name, (void *)(&__sizevar), true, __n); \
		}

#define DECL_STATE_ENTRY_CMT_RECORDING(__fio, __flag, __path) {				\
			state_entry->add_entry_cmt_recording((const _TCHAR *)_T(#__fio), &__fio, &__flag, (_TCHAR *)(&(__path[0]))); \
		}
		
#define DECL_STATE_ENTRY_SINGLE(___name) { \
		state_entry->add_entry((const _TCHAR *)_T(#___name) , &___name); \
	}

#define DECL_STATE_ENTRY_SINGLE_MEMBER(___name, __num) {						\
		state_entry->add_entry((const _TCHAR *)_T(#___name) , &___name, 1, __num); \
	}

#define DECL_STATE_ENTRY_SINGLE_ARRAY(___name, __len) {						\
		state_entry->add_entry((const _TCHAR *)_T(#___name) , &___name, __len); \
	}
#define DECL_STATE_ENTRY_SINGLE_ARRAY_MEMBER(___name, __len, __num) {			\
		state_entry->add_entry((const _TCHAR *)_T(#___name) , &___name, __len, __num); \
	}

#define DECL_STATE_ENTRY_FIFO(_n_name) {								\
		state_entry->add_entry_fifo((const _TCHAR *)_T(#_n_name), &_n_name, 1); \
	}

#define DECL_STATE_ENTRY_FIFO_ARRAY(_n_name, __len) {					\
		state_entry->add_entry_fifo((const _TCHAR *)_T(#_n_name), &_n_name, __len); \
	}

#define DECL_STATE_ENTRY_FIFO_MEMBER(_n_name, __n) {						\
		state_entry->add_entry_fifo((const _TCHAR *)_T(#_n_name), &_n_name, 1, __n); \
	}

#define DECL_STATE_ENTRY_FIFO_ARRAY_MEMBER(_n_name, __len, __n) {			\
		state_entry->add_entry_fifo((const _TCHAR *)_T(#_n_name), &_n_name, __len, __n); \
	}
   
#define DECL_STATE_ENTRY_CUR_TIME_T(_n_name) {							\
		state_entry->add_entry_cur_time_t((const _TCHAR *)_T(#_n_name), &_n_name, 1); \
	}

#define DECL_STATE_ENTRY_CUR_TIME_T_ARRAY(_n_name, __len) {					\
		state_entry->add_entry_cur_time_t((const _TCHAR *)_T(#_n_name), &_n_name, __len); \
	}

#define DECL_STATE_ENTRY_CUR_TIME_T_MEMBER(_n_name, __n) {				\
		state_entry->add_entry_cur_time_t((const _TCHAR *)_T(#_n_name), &_n_name, 1, __n); \
	}

#define DECL_STATE_ENTRY_CUR_TIME_T_ARRAY_MEMBER(_n_name, __len, __n) {	\
		state_entry->add_entry_cur_time_t((const _TCHAR *)_T(#_n_name), &_n_name, __len, __n); \
	}

#endif /* _CSP_STATE_SUB_H */
