#ifndef LIP_OPCUA_BINARY_TYPE_PARSE_H
#define LIP_OPCUA_BINARY_TYPE_PARSE_H

#include "../lip_opcua_cfg_defs.h"

/* ----------- PUT -----------------------------------------------------------*/
#define LIP_OPCUA_PUT_UINT16(fld, data) do { *data++ = ((fld) & 0xFF); *data++ = ((fld) >> 8) & 0xFF;} while (0)
#define LIP_OPCUA_PUT_UINT32(fld, data) do { *data++ = ((fld) & 0xFF); *data++ = ((fld) >> 8) & 0xFF; *data++ = ((fld) >> 16) & 0xFF; *data++ = ((fld) >> 24) & 0xFF; } while (0)
#define LIP_OPCUA_PUT_UINT64(fld, data) do { *data++ = ((fld) & 0xFF); *data++ = ((fld) >> 8) & 0xFF; *data++ = ((fld) >> 16) & 0xFF; *data++ = ((fld) >> 24) & 0xFF; \
        *data++ = ((fld) >> 32) & 0xFF; *data++ = ((fld) >> 40) & 0xFF; *data++ = ((fld) >> 48) & 0xFF; *data++ = ((fld) >> 56) & 0xFF; } while (0)


#define LIP_OPCUA_PUT_INT16(fld, data) do { uint16_t ufld = (uint16_t)fld; LIP_OPCUA_PUT_UINT16(ufld, data); } while (0)
#define LIP_OPCUA_PUT_INT32(fld, data) do { uint32_t ufld = (uint32_t)fld; LIP_OPCUA_PUT_UINT32(ufld, data); } while (0)
#define LIP_OPCUA_PUT_INT64(fld, data) do { uint64_t ufld = (uint64_t)fld; LIP_OPCUA_PUT_UINT64(ufld, data); } while (0)

#if LIP_OPCUA_TSTMP_PICOSEC_EN
#define LIP_OPCUA_PET_TSTMP(fld, data_ptr, ps_en) do { \
    LIP_OPCUA_PUT_INT64((fld).ns100, data_ptr); \
    if (ps_en) { LIP_OPCUA_PUT_UINT16((fld).ps, data_ptr); } \
} while(0)
#else
#define LIP_OPCUA_PET_TSTMP(fld, data_ptr, ps_en) do { \
    LIP_OPCUA_PUT_INT64((fld).ns100, data_ptr); \
    if (ps_en) { LIP_OPCUA_PUT_UINT16(0, data_ptr); } \
} while(0)
#endif



/* ----------- GET -----------------------------------------------------------*/
#define LIP_OPCUA_GET_UINT16(fld, data) do { (fld) = *data++; fld |= *data++ << 8;} while (0)
#define LIP_OPCUA_GET_UINT32(fld, data) do { fld = *data++; fld |= *data++ << 8;fld |= *data++ << 16;fld |= *data++ << 24;} while (0)
#define LIP_OPCUA_GET_UINT64(fld, data) do { fld = *data++; fld |= *data++ << 8;fld |= *data++ << 16;fld |= (uint32_t)(*data++ << 24); \
fld |= (uint64_t)*data++ << 32; \
    fld |= (uint64_t)*data++ << 40; \
    fld |= (uint64_t)*data++ << 48; \
    fld |= (uint64_t)*data++ << 56; \
} while (0)

#define LIP_OPCUA_GET_INT16(fld, data) do  { uint16_t ufld; LIP_OPCUA_GET_UINT16(ufld, data); (fld) = (int16_t)ufld;} while (0)
#define LIP_OPCUA_GET_INT32(fld, data) do  { uint32_t ufld; LIP_OPCUA_GET_UINT32(ufld, data); (fld) = (int32_t)ufld;} while (0)
#define LIP_OPCUA_GET_INT64(fld, data) do  { uint64_t ufld; LIP_OPCUA_GET_UINT64(ufld, data); (fld) = (int64_t)ufld;} while (0)


#define LIP_UADP_DROP_TSTMP(data_ptr, ps_en) ((data_ptr) += (ps_en ? 10 : 8))
#if LIP_OPCUA_TSTMP_PICOSEC_EN
#define LIP_OPCUA_GET_TSTMP(fld, data_ptr, ps_en) do { \
    LIP_OPCUA_GET_INT64((fld).ns100, data_ptr); \
    if (ps_en) { \
        LIP_OPCUA_GET_UINT16((fld).ps, data_ptr); \
} \
} while(0)
#else
#define LIP_OPCUA_GET_TSTMP(fld, data_ptr, ps_en) do { \
    LIP_OPCUA_GET_INT64((fld).ns100, data_ptr); \
    if (ps_en) { \
        data_ptr += 2; \
} \
} while(0)
#endif


#endif // LIP_OPCUA_BINARY_TYPE_PARSE_H
