﻿#ifndef __TOOL_H
#define __TOOL_H

#include <unistd.h>
#include <sys/syscall.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <mqueue.h>
#include <pthread.h>
#include <time.h>
#include <sys/select.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <stdarg.h>
#include <arpa/inet.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <net/if.h>
#include <linux/sockios.h>
#include <linux/ethtool.h>
#include <stdint.h>
#include <stdbool.h>
#include <pthread.h>
#include "log.h"
#include <sqlite3.h>

typedef char I8;
typedef short I16;
typedef int I32;
typedef long long I64;
typedef unsigned char U8;
typedef unsigned short U16;
typedef unsigned int U32;

#define CRITICAL_T	pthread_mutex_t
#define CRITICAL_INIT(x)	do { \
								pthread_mutexattr_t attr; \
								pthread_mutexattr_init(&attr); \
								pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); \
								pthread_mutex_init(x, &attr); \
							} while (0)
#define CRITICAL_LOCK(x)	pthread_mutex_lock(x)
#define CRITICAL_UNLOCK(x)	pthread_mutex_unlock(x)
#define CRITICAL_DESTORY(x) pthread_mutex_destroy(x)

#define enum_string(x) #x

#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)

#define EACH_STRING_INDEX(str,const_ptr,value){\
int ii;\
for(ii=0;ii<(sizeof(const_ptr)/sizeof((const_ptr)[0]));ii++){\
if(!strcmp(str,const_ptr[ii])){value = ii;break;}\
}\
if(ii == (sizeof(const_ptr)/sizeof((const_ptr)[0])))value = 0;\
}while(0)


void printf_mem(I8* mem, I32 len);

void mq_resource();


I32 check_timeout(struct timespec *prev, I32 timeout_ms);
I32 check_timeout_second(time_t *prev, I32 timeout_s);


/* 正常情况下不应去使用，因为会存在溢出情况 */
I64 clock_get_ms();

U32 clock_get_second();
I32 clock_diff_ms(struct timespec* now, struct timespec* prev);
void busy_wait(U32 us);

I32 my_timer_create();
I32 my_timer_delete(I32 timer);
/*
start_sec秒后首次触发，间隔为interval_ms毫秒，如果interval_ms == -1 则只触发一次
*/
I32 my_timer_set(I32 timer, I32 start_sec, I32 interval_ms);
/*
start_msec秒后首次触发，间隔为interval_ms毫秒，如果interval_ms == -1 则只触发一次
*/
I32 my_timer_set_ms(I32 timer, I32 start_msec, I32 interval_ms);

/*
参考系统时钟，start_sec秒后触发，且只触发一次
*/
I32 my_timer_set2(I32 timer, I32 start_sec);

/*
定时器触发后的处理
*/
I32 my_timer_read(I32 timer);

I32 file_read_map(I8* file_path, I8** addr, I32* len);

void file_read_unmap(I32 fd, I8* addr, I32 len);

I32 file_set_hole(I32 fd, I32 len);

void alog(char *format, ...);

I32 tcp_connect_host(I32 fd, U8 server_ip[4], U16 server_port);
I32 tcp_create_fd();

//基本等同于write，但当发生EINTR或EAGAIN时，等待10毫秒后重试，重试最多10次
I32 nwrite(I32 fd, void* data, I32 len);

//基本等同于read，但当发生EINTR或EAGAIN时，等待10毫秒后重试，重试最多10次
I32 nread(I32 fd, void* data, I32 len);

I32 net_set_mac(I8 *ifname, U8 mac[6]);
I32 net_set_ipv4_addr(I8 *ifname, U8 ip_addr[4] ,U8 mask_addr[4]);
I32 net_get_ipv4_addr(I8 *ifname, U32* ip);
I32 get_netlink_status(I8 *if_name);

I32 get_exec_info(I8* command, I8 *res, I32 buf_len);

void check_make_dir(I8 * dir);

void get_ip(U8 ip[4], const I8* ip_string);

//创建bitmask，包含元素数量为index_cnt个，index_cnt为8的倍数
void* bm_open(I32 index_cnt);
void bm_close(void* bm_handle);
I32 bm_set(void* bm_handle, I32 index);
I32 bm_clear(void* bm_handle, I32 index);
I32 bm_read(void* bm_handle, I32* index);

/**
 *
 * 执行system并将执行结果返回到rsp_command
 * @param[command]   需要执行的shell命令
 * @param[rsp_command]  返回执行命令的指针，如果return = 0,rsp_command 必须由调用方释放
 * @retval  0  成功
 * @retval  -1   错误
 * @par 标识符
 *      保留
 * @par 其它
 *      无
 * @par 修改日志
 *      张国宏于2019-06-12创建
 */
I32 system_reply(I8* command, I8 **rsp_command);

/**
 * 转化协议port项中字符类型为内部枚举，
 *
 * @param[c]   input char string.
 * @retval  该字符匹配成功返回：RS485_1/RS485_2/RS485_3/RS485_4/LORA_1;否则返回0
 * @par 标识符
 *      保留
 * @par 其它
 *      全词匹配，不区分大小写
 * @par 修改日志
 *      张国宏于2019-06-20创建
 */
int port_char2enum(char *c);

/**
 * 转化协议protocol项中字符类型为内部枚举，
 *
 * @param[c]   input char string.
 * @retval  该字符匹配成功返回：GW_PROTC_NULL/GW_PROTC_DYWL_LORA_V1/GW_PROTC_DYWL_RS485_V1/GW_PROTC_MODBUS;否则返回0
 * @par 标识符
 *      保留
 * @par 其它
 *      全词匹配,不区分大小写
 * @par 修改日志
 *      张国宏于2019-06-20创建
 */
int protocol_char2enum(char *c);

/**
 * 转化协议date_type项中字符类型为内部枚举，
 *
 * @param[c]   input char string.
 * @retval  该字符匹配成功返回：TAG_TYPE_NULL/TAG_TYPE_INT16/TAG_TYPE_UINT16/......;否则返回0
 * @par 标识符
 *      保留
 * @par 其它
 *      全词匹配,不区分大小写
 * @par 修改日志
 *      张国宏于2019-06-20创建
 */
int datatype_char2enum(char *c);

/**
 * 下载远程http文件
 *
 * @param[path]   下载到本地的路径
 * @param[remote_file] 远程文件资源的url
 * @param[timeout] 指定超时时间
 * @retval  0：成功;其他：失败
 * @par 标识符
 *      保留
 * @par 其它
 *      保留
 * @par 修改日志
 *      张国宏于2019-06-28创建
 */
int download_file(char* path,char* url,int timeout);

/**
 * 校验文件的MD5
 *
 * @param[file]   文件的本地的路径
 * @param[r_md5sum] 用来比较的MD5
 * @retval  0：匹配成功;其他：失败
 * @par 标识符
 *      保留
 * @par 其它
 *      保留
 * @par 修改日志
 *      张国宏于2019-06-28创建
 */
int check_md5sum_file(char* file,char* r_md5sum);

/**
 * 读取json文件中mi字段作为消息流水号
 *
 * @param[str] json string
 * @retval  0：没有读取到mi;-1：读取错误
 * @par 标识符
 *      保留
 * @par 其它
 *      保留
 * @par 修改日志
 *      张国宏于2019-07-03创建
 */
int json_pkt_json_mi(const char *str);

/**
 * 读取json文件中version字段
 *
 * @param[str] json string
 * @param[version] version buffer size
 * @param[size] version buffer size
 * @retval  0：没有读取到version;-1：读取错误
 * @par 标识符
 *      保留
 * @par 其它
 *      保留
 * @par 修改日志
 *      张国宏于2019-07-03创建
 */
int json_pkt_json_version(const char *str,char *version,int size);

/**
 * 从json串里读取version字段，并通知变更
 *
 * @param[ver_key] 版本名称的枚举
 * @param[str] json string
 * @retval
 * @par 标识符
 *      保留
 * @par 其它
 *      保留
 * @par 修改日志
 *      张国宏于2019-07-03创建
 */
void version_noify(int  ver_key,char *str);

/**
 * 读取json文件中URL字段
 *
 * @param[str] json string
 * @param[url_v] version buffer size
 * @retval  0：没有读取到version;-1：读取错误
 * @par 标识符
 *      保留
 * @par 其它
 *      保留
 * @par 修改日志
 *      张国宏于2019-08-09创建
 */
int json_pkt_json_url(const char *str,char *url_v);

/**
 * 读取json文件中MD5字段
 *
 * @param[str] json string
 * @param[md5_v] version buffer size
 * @retval  0：没有读取到md5;-1：读取错误
 * @par 标识符
 *      保留
 * @par 其它
 *      保留
 * @par 修改日志
 *      张国宏于2019-08-09创建
 */
int json_pkt_json_md5(const char *str,char *md5_v);

char * cJSON_GetItemString(const void * const object, const char * const string);

#endif /* __TOOL_H */
