/*----------------------------------------------------------------
* FileName    : toolkit.h
* Create Date : 2013-12-24
*               顶层头文件
*---------------------------------------------------------------*/

#ifndef TOOLKIT_H__
#define TOOLKIT_H__
/*#include <stdint.h>*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "platmacro.h"
#include <stdarg.h>

/*-------------------------------------------------------------------------------*/
/* public define */
#ifndef MIN
#define MIN(a, b) ((a) > (b) ? (b) : (a))
#endif // !MIN

#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif // !MAX

#define MAX_CMD_LINE 256
#define MAX_PRINT_BUF_SIZE 128

#define ENDIAN_TYPE_CONVERT_16(num)  ((((uint16_t)(num) & 0xff00U) >> 8) | \
                                      (((uint16_t)(num) & 0x00ffU) << 8))
#define ENDIAN_TYPE_CONVERT_32(num)  ((((uint32_t)(num) & 0xff000000U) >> 24) | \
                                      (((uint32_t)(num) & 0x00ff0000U) >> 8) | \
                                      (((uint32_t)(num) & 0x0000ff00U) << 8) | \
                                      (((uint32_t)(num) & 0x000000ffU) << 24))

#define BIG_TO_LITTLE_ENDIAN_16  ENDIAN_TYPE_CONVERT_16
#define BIG_TO_LITTLE_ENDIAN_32  ENDIAN_TYPE_CONVERT_32

#define LITTLE_TO_BIG_ENDIAN_16  BIG_TO_LITTLE_ENDIAN_16
#define LITTLE_TO_BIG_ENDIAN_32  BIG_TO_LITTLE_ENDIAN_32

#if (HOST_ENDIAN_TYPE == BIG_ENDIAN_TYPE)

#define HOST_TO_SLAVE_CAN_NET_16 BIG_TO_LITTLE_ENDIAN_16
#define HOST_TO_SLAVE_CAN_NET_32 BIG_TO_LITTLE_ENDIAN_32
#define HOST_TO_MODBUS_NET_16(num) (num)
#define HOST_TO_MODBUS_NET_32(num) (num)
#define HOST_TO_BIGENDIAN_16(num) (num)
#define HOST_TO_BIGENDIAN_32(num) (num)
#define BIG_ENDIAN_TO_HOST_16(num) (num)
#define BIG_ENDIAN_TO_HOST_32(num) (num)
#define HOST_TO_LITTLE_ENDIAN_16  BIG_TO_LITTLE_ENDIAN_16
#define HOST_TO_LITTLE_ENDIAN_32  BIG_TO_LITTLE_ENDIAN_32
#define LITTLE_ENDIAN_TO_HOST_16  LITTLE_TO_BIG_ENDIAN_16
#define LITTLE_ENDIAN_TO_HOST_32  LITTLE_TO_BIG_ENDIAN_32
/*国标协议大小端转换*/
#define HOST_TO_COMPROL_16(num)  (num)
#define HOST_TO_COMPROL_32  BIG_TO_LITTLE_ENDIAN_32
#define COMPROL_TO_HOST_16(num)  (num)
#define COMPROL_TO_HOST_32  LITTLE_TO_BIG_ENDIAN_32
#else
#define HOST_TO_SLAVE_CAN_NET_16(num) (num)
#define HOST_TO_SLAVE_CAN_NET_32(num) (num)
#define HOST_TO_MODBUS_NET_16 LITTLE_TO_BIG_ENDIAN_16
#define HOST_TO_MODBUS_NET_32 LITTLE_TO_BIG_ENDIAN_32
#define HOST_TO_BIGENDIAN_16  LITTLE_TO_BIG_ENDIAN_16
#define HOST_TO_BIGENDIAN_32  LITTLE_TO_BIG_ENDIAN_32
#define BIG_ENDIAN_TO_HOST_16  BIG_TO_LITTLE_ENDIAN_16
#define BIG_ENDIAN_TO_HOST_32  BIG_TO_LITTLE_ENDIAN_32
#define HOST_TO_LITTLE_ENDIAN_16(num) (num)
#define HOST_TO_LITTLE_ENDIAN_32(num) (num)
#define LITTLE_ENDIAN_TO_HOST_16(num) (num)
#define LITTLE_ENDIAN_TO_HOST_32(num) (num)
/*国标协议大小端转换*/
#define HOST_TO_COMPROL_16  LITTLE_TO_BIG_ENDIAN_16
#define HOST_TO_COMPROL_32(num)  (num)
#define COMPROL_TO_HOST_16  BIG_TO_LITTLE_ENDIAN_16
#define COMPROL_TO_HOST_32(num)  (num)
#endif

#define MODBUS_NET_TO_HOST_16 HOST_TO_MODBUS_NET_16
#define MODBUS_NET_TO_HOST_32 HOST_TO_MODBUS_NET_32

#define SIZE_OF_ARRAY(array_t) (sizeof(array_t)/sizeof(array_t[0]))

#define SIZE_OF_TYPE_NOT_LARGER_THAN(type, size) \
    char size_of_##type##_not_larger_than_##size() \
    { \
        char __dummy1[size - sizeof(type) + 1] = {0}; \
        return __dummy1[0]; \
    }

#define SIZE_OF_TYPE_NOT_EQUAL(type, size) \
    char size_of_##type##_not_equal() \
    { \
        char __dummy3[size - sizeof(type) + 1] = {0}; \
        char __dummy4[sizeof(type) - size + 1] = {0}; \
        return __dummy3[0] + __dummy4[0]; \
    }

#define SIZE_OF_ARRAY_NOT_LARGER_THAN(array_t, size) \
    char size_of_##array_t##_not_larger_than_##size() \
    { \
        char __dummy1[size - SIZE_OF_ARRAY(array_t) + 1] = {0}; \
        return __dummy1[0]; \
    }

#define SIZE_OF_ARRAY_NOT_EQUAL(array_1, array_2) \
    char size_of_##array_1##array_2##_not_equal_##size() \
    { \
        char __dummy1[SIZE_OF_ARRAY(array_1) - SIZE_OF_ARRAY(array_2) + 1] = {0}; \
        char __dummy2[SIZE_OF_ARRAY(array_2) - SIZE_OF_ARRAY(array_1) + 1] = {0}; \
        return __dummy1[0] + __dummy2[0]; \
    }

#define SIZE_OF_ARRAY_NOT_EQUAL_SIZE(array_1, size) \
    char size_of_##array_1##array_2##_not_equal_##size() \
    { \
        char __dummy1[SIZE_OF_ARRAY(array_1) - size + 1] = {0}; \
        char __dummy2[size - SIZE_OF_ARRAY(array_1) + 1] = {0}; \
        return __dummy1[0] + __dummy2[0]; \
    }

#define CHECK_IS_DIVISOR(dividend, divisor) \
    char check_is_##dividend##_divisible() \
    { \
        char __dummy1[(-1 * ((int32_t)(dividend) % (int32_t)(divisor))) + 1] = {0}; \
        char __dummy2[dividend] = {0}; \
        return __dummy1[0] + __dummy2[0]; \
    }


#define FIELD_OFFSET(TYPE, MEMBER) ((uintptr_t) &((TYPE *)0)->MEMBER)

#define DEBUG_MSG(format,...)  \
    do{                        \
        printf(format,__VA_ARGS__) ;   \
    }while(0)

#define ASSERT_POINTER(a) \
    do{                     \
    if((a) == (void *)NULL)     \
    {                   \
      while(1) {}      \
    }                   \
    }while(0)

#define DEBUG_ASSERT(a, format,...) \
    do{                      \
    if(a)                \
    {                    \
        while(1)        \
        {                \
        }                \
    }                    \
    }while(0)

#define SELECT_INIT()   \
    do                  \
    {                   \
        maxfd = 0;      \
        FD_ZERO(&rset); \
    } while (0)

#define SELECT_ADD_FD(fd)      \
    do                         \
    {                          \
        if (fd > 0)            \
        {                      \
            FD_SET(fd, &rset); \
            if (maxfd < fd)    \
                maxfd = fd;    \
        }                      \
    } while (0)

#define TIMER_CONFIRM(timer)          \
    do                                \
    {                                 \
        if (bmser_timerfd_read(timer) < 0) \
            return 0;                 \
    } while (0)

#define GET_JSON_VALUE_DOUBLE(root, key, value_p)                                    \
    do                                                                               \
    {                                                                                \
        cJSON *__item = cJSON_GetObjectItem(root, key);                              \
        if (__item)                                                                  \
            memcpy((void *)&value_p, (void *)&__item->valuedouble, sizeof(value_p)); \
    } while (0)

#define GET_JSON_VALUE_INT(root, key, value_p)                                    \
    do                                                                            \
    {                                                                             \
        cJSON *__item = cJSON_GetObjectItem(root, key);                           \
        if (__item)                                                               \
            memcpy((void *)&value_p, (void *)&__item->valueint, sizeof(value_p)); \
    } while (0)

#define GET_JSON_VALUE_STRING(root, key, value_p)       \
    do                                                  \
    {                                                   \
        cJSON *__item = cJSON_GetObjectItem(root, key); \
        memset(value_p, 0, sizeof(value_p));            \
        if (__item)                                     \
        {                                               \
            if (__item->valuestring)                    \
                strcpy(value_p, __item->valuestring);   \
        }                                               \
    } while (0)

#define GET_JSON_VALUE_DY_STRING(root, key, value_p)    \
    do                                                  \
    {                                                   \
        cJSON *__item = cJSON_GetObjectItem(root, key); \
        if (__item)                                     \
        {                                               \
            if (__item->valuestring)                    \
                value_p = strdup(__item->valuestring);  \
            else                                        \
                value_p = NULL;                         \
        }                                               \
        else                                            \
        {                                               \
            value_p = NULL;                             \
        }                                               \
    } while (0)

/*-----------------------------------------------------------------------------------------
 Discription: CRC校验
 Param:       @param1:待校验的数据的起始地址
              @param2:待校验的数据长度
 Return:      校验结果
*-----------------------------------------------------------------------------------------*/
uint16_t BmsMsg_Crc16(uint8_t *arr_buff, uint8_t len);

/*-----------------------------------------------------------------------------------------
 Discription: 元素为四个字节表示的数组的CRC校验
 Param:       @param1:待校验的数据的起始地址
              @param2:待校验的数据的长度
 Return:      校验的结果
*-----------------------------------------------------------------------------------------*/
uint32_t CalculateXorCrc(uint8_t *arr_buff, uint32_t len);
/*-----------------------------------------------------------------------------------------
 Discription: 元素为两个字节表示的数组的CRC校验
 Param:       @param1:待校验的数据的起始地址
              @param2:待校验的数据的长度
 Return:      校验的结果
*-----------------------------------------------------------------------------------------*/
uint16_t CalculateU16XorCrc(uint8_t *arr_buff, uint32_t len);


/**
 * @brief       创建文件夹 
 * @return      void
 * @retval      none
 * @par         修改日志:
 * Date                Author     Description           \n
 * 2022-10-20           JHC        创建初始版本          \n
*/
void check_make_dir(char * dir);

int32_t bmser_timerfd_set(int32_t timer, int32_t start_sec, int32_t interval_ms);
int32_t bmser_timerfd_set_ms(int32_t timer, int32_t start_msec, int32_t interval_ms);
int32_t bmser_timerfd_create();
int32_t bmser_timerfd_delete(int32_t timer);
int bmser_timerfd_read(int timer);


char* itoa(int num,char* str,int radix);
#endif /* __TOOLKIT_H__ */

