/*----------------------------------------------------------------
* FileName    : toolkit.c
* Create Date : 2013-12-24
*
*---------------------------------------------------------------*/

#include <stdint.h>
#include <sys/stat.h>
#include <time.h>
#ifndef _MSC_VER
#include <sys/timerfd.h>
#endif
#include <errno.h>
#include "toolkit.h"
#include "bmser_log.h"

uint32_t CalculateXorCrc(uint8_t *arr_buff, uint32_t len)
{
    uint32_t i;
    uint32_t lastValue = 0;
    uint32_t crc=0;
    uint32_t *pt = (uint32_t *)arr_buff;
    uint16_t fractionalData = (uint16_t)(len & 0x3);
    uint8_t shiftBitNum[] = {24, 16, 8};

    for(i=0; i<(len>>2); i++)
    {
        crc = crc^pt[i];
    }

    if(fractionalData != 0)
    {
        for(i = 0; i < fractionalData; i++)
        {
            lastValue |= arr_buff[len-fractionalData+i] << shiftBitNum[i];
        }
        crc ^= lastValue;
    }

    return crc;
}

uint16_t CalculateU16XorCrc(uint8_t *arr_buff, uint32_t len)
{
    uint32_t i;
    uint16_t lastValue = 0;
    uint16_t crc=0;
    uint16_t *pt = (uint16_t *)arr_buff;
    uint16_t fractionalData = (uint16_t)(len & 0x1);
    uint8_t shiftBitNum = 8;

    for(i=0; i<(len>>1); i++)
    {
        crc = crc^pt[i];
    }

    if(fractionalData != 0)
    {
        lastValue |= arr_buff[len-fractionalData] << shiftBitNum;
        crc ^= lastValue;
    }

    return crc;
}

/*-----------------------------------------------------------------------------------------
 Discription:
 Author:      Wang Zheng
 Create:      2014-02-09
 Modify:
*-----------------------------------------------------------------------------------------*/
uint16_t BmsMsg_Crc16(uint8_t* arr_buff, uint8_t len)
{
    uint16_t crc = 0xFFFF;
    uint8_t i, j;

    for (j = 0; j < len; j++)
    {
        crc = (uint16_t)(crc ^ *arr_buff++);
        for (i = 0; i < 8; i++)
        {
            if ((crc & 0x0001) > 0)
            {
                crc = crc >> 1;
                crc = crc ^ 0xa001;
            }
            else
            {
                crc = crc >> 1;
            }
        }
    }

    return (crc);
}

void check_make_dir(char * dir)
{
    int32_t ret;
	struct stat stat_info;
	
	ret = stat(dir, &stat_info);
	if(ret == 0)
		return;

	ret = mkdir(dir, 0777);
	if(ret)
        dy_syslog(LOG_ERR,"mkdir %s fail", dir);
}

/*
start_sec秒后首次触发，间隔为interval_ms毫秒，如果interval_ms == -1 则只触发一次
*/
int32_t bmser_timerfd_set(int32_t timer, int32_t start_sec, int32_t interval_ms)
{
#ifdef _MSC_VER
    return -1;
#else
	struct itimerspec new_value;

	new_value.it_value.tv_sec = start_sec;
	new_value.it_value.tv_nsec = 0;

	if(interval_ms >= 1000)
	{
		new_value.it_interval.tv_sec = interval_ms / 1000;
		new_value.it_interval.tv_nsec = 0;
	}
	else if(interval_ms == -1)
	{
		new_value.it_interval.tv_sec = 0;
		new_value.it_interval.tv_nsec = 0;		
	}
	else
	{
		new_value.it_interval.tv_sec = 0;
		new_value.it_interval.tv_nsec = interval_ms*1000000;
	}

	if (timerfd_settime(timer, 0, &new_value, NULL) == -1)
	{
       dy_syslog(LOG_ERR,"timerfd_settime");
	   return -3;
	}

	return 0;
#endif
}

/*
start_msec毫秒后首次触发，间隔为interval_ms毫秒，如果interval_ms == -1 则只触发一次
*/
int32_t bmser_timerfd_set_ms(int32_t timer, int32_t start_msec, int32_t interval_ms)
{
#ifdef _MSC_VER
    return -1;
#else
	struct itimerspec new_value;

	if(start_msec < 1000)
	{
		new_value.it_value.tv_sec = 0;
		new_value.it_value.tv_nsec = start_msec*1000000;
	}
	else
	{
		new_value.it_value.tv_sec = start_msec / 1000;
		new_value.it_value.tv_nsec = (start_msec%1000)*1000000;
	}

	if(interval_ms >= 1000)
	{
		new_value.it_interval.tv_sec = interval_ms / 1000;
		new_value.it_interval.tv_nsec = 0;
	}
	else if(interval_ms == -1)
	{
		new_value.it_interval.tv_sec = 0;
		new_value.it_interval.tv_nsec = 0;		
	}
	else
	{
		new_value.it_interval.tv_sec = 0;
		new_value.it_interval.tv_nsec = interval_ms*1000000;
	}
	if (timerfd_settime(timer, 0, &new_value, NULL) == -1)
	{
        dy_syslog(LOG_ERR,"timerfd_settime3");
		return -3;
	}

	return 0;
#endif
}


int32_t bmser_timerfd_create()
{
#ifdef _MSC_VER
    return -1;
#else
    int32_t fd = -1;
     
    int retry = 3;
    while(retry--)
    {
	fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK);
	if (fd == -1)
	{
       dy_syslog(LOG_ERR,"timerfd_create error");
	   return -2;
	}
    if(fd > 2)break;
        dy_syslog(LOG_ERR,"timerfd_create retry !!!!! ,fd %d", fd);
    }

	return fd;
#endif
}

int32_t bmser_timerfd_delete(int32_t timer)
{
#ifdef _MSC_VER
    return -1;
#else
	return close(timer);
#endif
}

/*
定时器触发后的处理
*/
int bmser_timerfd_read(int timer)
{
#ifdef _MSC_VER
    return -1;
#else
    uint64_t exp;
    ssize_t s;

    s = read(timer, &exp, sizeof(uint64_t));
    if (s != sizeof(uint64_t))
    {
        dy_syslog(LOG_ERR, "tid %ld, timer %d read, errno %d", syscall(SYS_gettid), timer, errno);
        return -1;
    }

    return 0;
#endif
}

char* itoa(int num,char* str,int radix)
{
    char index[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";//索引表
    unsigned unum;//存放要转换的整数的绝对值,转换的整数可能是负数
    int i=0,j,k;//i用来指示设置字符串相应位，转换之后i其实就是字符串的长度；转换后顺序是逆序的，有正负的情况，k用来指示调整顺序的开始位置;j用来指示调整顺序时的交换。
 
    //获取要转换的整数的绝对值
    if(radix==10&&num<0)//要转换成十进制数并且是负数
    {
        unum=(unsigned)-num;//将num的绝对值赋给unum
        str[i++]='-';//在字符串最前面设置为'-'号，并且索引加1
    }
    else unum=(unsigned)num;//若是num为正，直接赋值给unum
 
    //转换部分，注意转换后是逆序的
    do
    {
        str[i++]=index[unum%(unsigned)radix];//取unum的最后一位，并设置为str对应位，指示索引加1
        unum/=radix;//unum去掉最后一位
 
    }while(unum);//直至unum为0退出循环
 
    str[i]='\0';//在字符串最后添加'\0'字符，c语言字符串以'\0'结束。
 
    //将顺序调整过来
    if(str[0]=='-') k=1;//如果是负数，符号不用调整，从符号后面开始调整
    else k=0;//不是负数，全部都要调整
 
    char temp;//临时变量，交换两个值时用到
    for(j=k;j<=(i-1)/2;j++)//头尾一一对称交换，i其实就是字符串的长度，索引最大值比长度少1
    {
        temp=str[j];//头部赋值给临时变量
        str[j]=str[i-1+k-j];//尾部赋值给头部
        str[i-1+k-j]=temp;//将临时变量的值(其实就是之前的头部值)赋给尾部
    }
 
    return str;//返回转换后的字符串
 
}

