/**
 * @file convert.c
 * @author Chen Jihang (embedded@eseaoptics.com)
 * @brief 字符串相关的转换函数
 * @version 1.0
 * @date 2022-07-18
 * 
 * @copyright ESEA (c) 2022
 * 
 */
#include "convert.h"
#include "math.h"
/**
 * @brief 将uint64_t类型数据转换为字符串
 * 
 * @param integer 要转换的数据
 * @param str 存放转换后数据的缓冲区
 * @param length 缓冲区大小
 * @return unsigned 成功:使用的缓冲区长度 失败:0
 */
unsigned convert_u64_to_s(uint64_t integer,char *str,unsigned length)
{
    unsigned i;
    unsigned j=length-1;
    while(j<length){
        str[j]=integer%10+'0';
        integer/=10;
        if(integer==0)
            break;
        j--;
    }
    if(integer!=0)
        return 0;
    for(i=0;j<length;i++,j++){
        str[i]=str[j];
    }
    return i;
}
/**
 * @brief 将字符串转换为64bit无符号整型数据
 * 
 * @param integer 存放读取数据的地址
 * @param str 要转换的字符串
 * @param length 字符串长度
 * @return unsigned 成功:转换成功的字符串长度 失败:0
 */
unsigned convert_s_to_u64(uint64_t *integer,char *str,unsigned length)
{
    unsigned i;
    *integer=0;
    for(i=0;i<length;i++){
        if(str[i]<'0' || str[i]>'9'){
            break;
        }
        *integer*=10;
        *integer+=str[i]-'0';
    }
    return i;
}
/**
 * @brief 将int64_t类型数据转换为字符串
 * 
 * @param integer 要转换的数据
 * @param str 存放转换后数据的缓冲区
 * @param length 缓冲区大小
 * @return unsigned 成功:使用的缓冲区长度 失败:0
 */
unsigned convert_i64_to_s(int64_t integer,char *str,unsigned length)
{
    unsigned i=0,j;
    if(integer<0){
        integer=-integer;
        str[i++]='-';
    }
    j=convert_u64_to_s(integer,&str[i],length-i);
    return (j==0)?(0):(j+i);
}
/**
 * @brief 将字符串转换为64bit有符号整型数据
 * 
 * @param integer 存放读取数据的地址
 * @param str 要转换的字符串
 * @param length 字符串长度
 * @return unsigned 成功:转换成功的字符串长度 失败:0
 */
unsigned convert_s_to_i64(int64_t *integer,char *str,unsigned length)
{
    unsigned i=0,j;
    uint64_t tmp;
    if(str[0]=='-'){
        i++;
    }
    j=convert_s_to_u64(&tmp,&str[i],length-i);
    if((tmp&((uint64_t)1<<(sizeof(tmp)*8-1)))!=0){
        return 0;
    }
    *integer=(int64_t)tmp;
    if(str[0]=='-'){
        *integer=-*integer;
    }
    return (j==0)?(0):(j+i);
}
/**
 * @brief 将uint32_t类型数据转换为字符串
 * 
 * @param integer 要转换的数据
 * @param str 存放转换后数据的缓冲区
 * @param length 缓冲区大小
 * @return unsigned 成功:使用的缓冲区长度 失败:0
 */
unsigned convert_u32_to_s(uint32_t integer,char *str,unsigned length)
{
    unsigned i;
    unsigned j=length-1;
    while(j<length){
        str[j]=integer%10+'0';
        integer/=10;
        if(integer==0)
            break;
        j--;
    }
    if(integer!=0)
        return 0;
    for(i=0;j<length;i++,j++){
        str[i]=str[j];
    }
    return i;
}
/**
 * @brief 将字符串转换为32bit无符号整型数据
 * 
 * @param integer 存放读取数据的地址
 * @param str 要转换的字符串
 * @param length 字符串长度
 * @return unsigned 成功:转换成功的字符串长度 失败:0
 */
unsigned convert_s_to_u32(uint32_t *integer,char *str,unsigned length)
{
    unsigned i;
    *integer=0;
    for(i=0;i<length;i++){
        if(str[i]<'0' || str[i]>'9'){
            break;
        }
        *integer*=10;
        *integer+=str[i]-'0';
    }
    return i;
}
/**
 * @brief 将int32_t类型数据转换为字符串
 * 
 * @param integer 要转换的数据
 * @param str 存放转换后数据的缓冲区
 * @param length 缓冲区大小
 * @return unsigned 成功:使用的缓冲区长度 失败:0
 */
unsigned convert_i32_to_s(int32_t integer,char *str,unsigned length)
{
    unsigned i=0,j;
    if(integer<0){
        integer=-integer;
        str[i++]='-';
    }
    j=convert_u32_to_s(integer,&str[i],length-i);
    return (j==0)?(0):(j+i);
}
/**
 * @brief 将字符串转换为32bit有符号整型数据
 * 
 * @param integer 存放读取数据的地址
 * @param str 要转换的字符串
 * @param length 字符串长度
 * @return unsigned 成功:转换成功的字符串长度 失败:0
 */
unsigned convert_s_to_i32(int32_t *integer,char *str,unsigned length)
{
    unsigned i=0,j;
    uint32_t tmp;
    if(str[0]=='-'){
        i++;
    }
    j=convert_s_to_u32(&tmp,&str[i],length-i);
    if((tmp&((uint32_t)1<<(sizeof(tmp)*8-1)))!=0){
        return 0;
    }
    *integer=(int32_t)tmp;
    if(str[0]=='-'){
        *integer=-*integer;
    }
    return (j==0)?(0):(j+i);
}
/**
 * @brief 将double类型数据转换为字符串
 * 
 * @param double_float 要转换的数据
 * @param str 存放转换后数据的缓冲区
 * @param length 缓冲区大小
 * @param sig 转换后的有效位数,4舍6入5前凑偶
 * @return unsigned 成功:使用的缓冲区长度 失败:0
 */
unsigned convert_d2s(double double_float,char *str,unsigned length,unsigned sig)
{
    unsigned i=0,j;
    uint64_t tmp;
    unsigned sig_con;
    unsigned remainder;
    if(sig>16){
        sig=16;
    }
    if(length<sig+3){
        return 0;
    }
    if(double_float<0){
        str[i++]='-';
        double_float=-double_float;
    }
    tmp=double_float;
    j=convert_u64_to_s(tmp,&str[i],length-i);
    if(j==0){
        return 0;
    }
    i+=j;
    sig_con=j;
    if(tmp==0){
        sig_con=0;
    }
    str[i++]='.';
    double_float-=tmp;
    tmp=0;
    for(;sig_con<=sig;){
        double_float*=10;
        remainder=double_float;
        if(remainder==0 && sig_con==0){
            str[i++]=remainder+'0';
        }
        else{
            sig_con++;
        }
        tmp=tmp*10+remainder;
        double_float-=remainder;
    }
    remainder=tmp%10;
    tmp/=10;
    if(remainder>5){
        remainder=1;
    }
    else if(remainder<5){
        remainder=0;
    }
    else{
        if((tmp&1)==1){
            remainder=1;
        }
        else{
            remainder=0;
        }
    }
    tmp+=remainder;
    j=convert_u64_to_s(tmp,&str[i],length-i);
    return (j==0)?(0):(i+j);
}
/**
 * @brief 将字符串转换为double型数据
 * 
 * @param double_float 存放读取数据的地址
 * @param str 要转换的字符串
 * @param length 字符串长度
 * @param sig 要转换的有效位数
 * @return unsigned 成功:转换成功的字符串长度 失败:0
 */
unsigned convert_s2d(double *double_float,char *str,unsigned length,unsigned sig)
{
    uint64_t tmp_u64;
    int64_t mantissa;
    int32_t exp=0;
    int32_t tmp_i32;
    unsigned sig_con=0;
    unsigned i=0,j;
    if(sig>16){
        sig=16;
    }
    if(str[i]=='-'){
        i++;
    }
    j=convert_s_to_u64(&tmp_u64,&str[i],sig>length-i?length-i:sig);
    if(j==0){
        return 0;
    }
    i+=j;
    if(tmp_u64!=0){
        sig_con+=j;
    }
    mantissa=tmp_u64;
    if(sig_con<sig){
        if(i<length && str[i]=='.'){
            i++;
            for(j=0;j<length-i&&sig_con<sig;j++,sig_con++){
                if(str[i+j]>='0' && str[i+j]<='9'){
                    mantissa*=10;
                    mantissa+=str[i+j]-'0';
                }
                else{
                    break;
                }
            }
            if(j==0){
                return 0;
            }
            i+=j;
            exp=-j;
            for(j=0;;j++){
                if(i+j>=length){
                    *double_float=mantissa;
                    *double_float*=pow(10,exp);
                    if(str[0]=='-'){
                        *double_float=-*double_float;
                    }
                    return i+j;
                }
                if(str[i+j]>'9' || str[i+j]<'0'){
                    break;
                }
            }
            i+=j;
        }
        if(i<length && (str[i]=='e' || str[i]=='E')){
            i++;
            j=convert_s_to_i32(&tmp_i32,&str[i],length-i);
            if(j==0){
                return 0;
            }
            exp+=tmp_i32;
            if(exp>1000 || exp<-1000){
                return 0;
            }
            i+=j;
        }
    }
    *double_float=mantissa;
    *double_float*=pow(10,exp);
    if(str[0]=='-'){
        *double_float=-*double_float;
    }
    return i;
}
/**
 * @brief 将unsigned数据转换为字符串
 * 
 * @param integer 要转换的数据
 * @param str 字符串指针
 * @param length 字符串长度
 * @return unsigned 转换的字符串长度
 */
unsigned convert_u2s(unsigned integer,char *str,unsigned length)
{
    unsigned i;
    unsigned j=length-1;
    while(j<length){
        str[j]=integer%10+'0';
        integer/=10;
        if(integer==0)
            break;
        j--;
    }
    if(integer!=0)
        return 0;
    for(i=0;j<length;i++,j++){
        str[i]=str[j];
    }
    return i;
}
/**
 * @brief 将字符串转换为unsigned
 * 
 * @param str 字符串指针
 * @param length 字符串长度
 * @param integer 转换完成的数据
 * @return unsigned 转换的字符串长度
 */
unsigned convert_s2u(unsigned *integer,char *str,unsigned length)
{
    unsigned i;
    *integer=0;
    for(i=0;i<length;i++){
        if(str[i]<'0' || str[i]>'9'){
            break;
        }
        *integer*=10;
        *integer+=str[i]-'0';
    }
    return i;
}
/**
 * @brief 将int数据转换为字符串
 * 
 * @param integer 要转换的数据
 * @param str 字符串指针
 * @param length 字符串长度
 * @return unsigned 转换的字符串长度
 */
unsigned convert_i2s(int integer,char *str,unsigned length)
{
    unsigned i=0,j;
    if(integer<0){
        integer=-integer;
        str[i++]='-';
    }
    j=convert_u2s(integer,&str[i],length-i);
    return (j==0)?(0):(j+i);
}
/**
 * @brief 将字符串转换为int
 * 
 * @param integer 转换完成的数据
 * @param str 字符串指针
 * @param length 字符串长度
 * @return unsigned 转换的字符串长度
 */
unsigned convert_s2i(int *integer,char *str,unsigned length)
{
    unsigned i=0,j;
    unsigned tmp;
    if(str[0]=='-'){
        i++;
    }
    j=convert_s2u(&tmp,&str[i],length-i);
    if((tmp&((unsigned)1<<(sizeof(tmp)*8-1)))!=0){
        return 0;
    }
    *integer=(int)tmp;
    if(str[0]=='-'){
        *integer=-*integer;
    }
    return (j==0)?(0):(j+i);
}
/**
 * @brief 将字符串形式的ip地址转换为整型形式的ip地址
 * 
 * @param ip 指向存放整型ip地址的位置的指针
 * @param ips 字符串形式的ip地址
 * @param length 字符串长度
 * @return unsigned 转换的字符串长度
 */
unsigned convert_ips2ip(uint32_t *ip,char *ips,unsigned length)
{
    int i=0;
    unsigned tmp;
    *ip=0;
    i+=convert_s2u(&tmp,&ips[i],length-i);
    if(ips[i++]!='.'){
        return 0;
    }
    *ip|=((tmp&0xff)<<24);
    i+=convert_s2u(&tmp,&ips[i],length-i);
    if(ips[i++]!='.'){
        return 0;
    }
    *ip|=((tmp&0xff)<<16);
    i+=convert_s2u(&tmp,&ips[i],length-i);
    if(ips[i++]!='.'){
        return 0;
    }
    *ip|=((tmp&0xff)<<8);
    i+=convert_s2u(&tmp,&ips[i],length-i);
    *ip|=(tmp&0xff);
    return i;
}
/**
 * @brief 将整型形式的ip地址转换为字符串形式的ip地址
 * 
 * @param ip 整型形式的ip地址
 * @param ips 用于存储字符串形式的ip地址的缓冲区
 * @param length 缓冲区长度
 * @return unsigned 转换的字符串长度
 */
unsigned convert_ip2ips(uint32_t ip,char *ips,unsigned length)
{
    int i=0;
    i+=convert_u2s((ip>>24)&0xff,&ips[i],length-i);
    ips[i++]='.';
    i+=convert_u2s((ip>>16)&0xff,&ips[i],length-i);
    ips[i++]='.';
    i+=convert_u2s((ip>>8)&0xff,&ips[i],length-i);
    ips[i++]='.';
    i+=convert_u2s(ip&0xff,&ips[i],length-i);
    return i;
}