当前位置: 首页 > news >正文

第二章 EXI协议原理与实现--9.7 cbExiGen库bug及改进

9.7 cbExiGen库bug及改进

上一节作者改进了cjson库,成功的支持64位整数的解析和输出,但是在测试SessionSetupRes命令时,发现解码输出的时间戳仍然是乱码,说明 cbExigen库代码存在解码错误。本节作者分析了bug原因,提出了修改方案。 同时在github上提交这个bug,官方已经接受并且修复啦。

测试数据:

充电桩ISO15118-2协议的SessionSetupRes命令实例: 我故意把时间戳数据写成了这么长19位。

{
    "V2G_Message": {
        "Header": {
            "SessionID": "C08CDF36985A7190"
        },
        "Body": {
            "SessionSetupRes": {
                "ResponseCode": "OK_NewSessionEstablished",
                "EVSEID": "UK123E1234",
                "EVSETimeStamp": 1234567890123456789
            }
        }
    }
}

该命令对应的schema规范中定义了EVSETimeStamp的具体类型位long,因此必须要用到int64类型解析。

<xs:element name="EVSETimeStamp" type="xs:long" minOccurs="0"/>

代码运行后编码成功,解码成功,但是解码后的EVSETimeStamp并不是1234567890123456789,明显的是一个乱数字,长度也被截断了。怀疑是内部解码错误,跟踪代码发现了错误位置和原因。

代码:exi_basetypes.c,  把字节数组转换成64位长整数

int exi_basetypes_convert_64_from_unsigned(exi_unsigned_t* exi_unsigned, uint64_t* value)
{
    if (exi_unsigned->octets_count > EXI_BASETYPES_UINT64_MAX_OCTETS)
    {
        return EXI_ERROR__OCTET_COUNT_LARGER_THAN_TYPE_SUPPORTS;
    }

    uint8_t* current_octet = exi_unsigned->octets;
    *value = 0;

    for (size_t n = 0; n < exi_unsigned->octets_count; n++)
    {  //fix bug:  overflow of int,  Forced Typecasting to uint64_t,  Tom.hongtao.gao
        *value = (uint64_t)(*value + ((*current_octet & EXI_BASETYPES_OCTET_SEQ_VALUE_MASK) << (n * 7)));          
        current_octet++;
    }

    return EXI_ERROR__NO_ERROR;
}

上面转换思路:

每个字节去除最高位,然后左移7位,累加求和。

循环读取每个字节,直到数组结束。这样最后的和就是长整型数。

【错误原因】:在移位操作时,左边的操作数 (*current_octet & EXI_BASETYPES_OCTET_SEQ_VALUE_MASK) 默认类型是int类型,当连续操作到第6个字节时,该数字已经连续左移36位了,已经超过了32位整数的范围了,所以发生整数溢出。

【解决方法】:对移位的操作数强制类型转换,添加(uint64_t) 解决了溢出问题。

    for (size_t n = 0; n < exi_unsigned->octets_count; n++)
    {   //fix bug:  overflow of int,  Forced Typecasting to uint64_t,  Tom.hongtao.gao
        //*value = (uint64_t)(*value + ((*current_octet & EXI_BASETYPES_OCTET_SEQ_VALUE_MASK) << (n * 7)));    
        *value = (uint64_t)(*value + ((uint64_t)(*current_octet & EXI_BASETYPES_OCTET_SEQ_VALUE_MASK) << (n * 7))); 
        current_octet++;
    }

之后再用代码测试OK,解码出的数据能正确显示出1234567890123456789这个数字了。

json格式化后:
{
        "V2G_Message":  {
                "Header":       {
                        "SessionID":    "C08CDF36985A7190"
                },
                "Body": {
                        "SessionSetupRes":      {
                                "ResponseCode": "OK_NewSessionEstablished",
                                "EVSEID":       "UK123E1234",
                                "EVSETimeStamp":        1234567890123456789
                        }
                }
        }
}


lret = 0, timeStamp=1234567890123456789
1111 SessionSetupRes.EVSETimeStamp=1234567890123456789
ret1= 0
stream.byte_pos =34
dataRes (35 bytes):
+------------------------------------------------------------------------------+
| Offset  : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F   0123456789ABCDEF |
+------------------------------------------------------------------------------+
| 00000000: 80 98 02 30 23 37 CD A6 16 9C 64 11 E0 20 31 55   ...0#7....d.. 1U |
| 00000010: 2C C4 C8 CD 14 C4 C8 CC D0 12 B0 54 DD F8 F3 D0   ,..........T.... |
| 00000020: 92 22 20                                          ."               |
+------------------------------------------------------------------------------+
ret2= 0
2222, timeStamp=1234567890123456789
root: {
        "V2G_Message":  {
                "Header":       {
                        "SessionID":    "C08CDF36985A7190"
                },
                "Body": {
                        "SessionSetupRes":      {
                                "ResponseCode": "OK_NewSessionEstablished",
                                "EVSEID":       "UK123E1234",
                                "EVSETimeStamp":        1234567890123456789
                        }
                }
        }
}

tom@Tom-Hongtao:/mnt/c/e/codes/cbexigen-TestFrame$


文章转载自:

http://YhEFZkwB.kyybp.cn
http://2lUDeEsF.kyybp.cn
http://eyBv9rAm.kyybp.cn
http://ucufO8HL.kyybp.cn
http://1voa0LPF.kyybp.cn
http://sDW3uEzl.kyybp.cn
http://PuFA4Qni.kyybp.cn
http://0uVdO0Kx.kyybp.cn
http://5suR60cc.kyybp.cn
http://k12gWT9Z.kyybp.cn
http://0IlTV1m9.kyybp.cn
http://d6g3oS8l.kyybp.cn
http://A9PdrQUs.kyybp.cn
http://FaYq94Ci.kyybp.cn
http://EIaKzt5N.kyybp.cn
http://GNiWMI4F.kyybp.cn
http://qfYHHEpW.kyybp.cn
http://nY36Zzf6.kyybp.cn
http://OYFjHNDB.kyybp.cn
http://NpESbn00.kyybp.cn
http://oy71K3gZ.kyybp.cn
http://fg5uINzl.kyybp.cn
http://hXQVlMIb.kyybp.cn
http://rX8WIovi.kyybp.cn
http://WFI6BzYC.kyybp.cn
http://j510ogV2.kyybp.cn
http://AYiNrIB2.kyybp.cn
http://lR3TXfQ0.kyybp.cn
http://tgXODwla.kyybp.cn
http://x7ZUv2Vf.kyybp.cn
http://www.dtcms.com/a/89606.html

相关文章:

  • Android adb自身调试log开关
  • HashMap的位操作是什么?HashSet 的 contains 方法复杂度是多少?红黑树简单讲一下?
  • 基于Ebay拍卖网站成交价格的影响因素分析
  • 【TI MSPM0】PWM学习
  • Android 12.0 WiFi连接默认设置静态IP地址功能实现
  • ALTER TABLE SHRINK SPACE及MOVE的区别与适用场景
  • 如何突破MacBook苹果电脑Cursor限制:免费版的解决方法
  • 【Linux线程】——线程同步线程互斥
  • SpringMVC 请求与响应处理详解
  • Vue-admin-template安装教程
  • 数据结构入门【算法复杂度】
  • 攻防世界-web-1
  • 位置编码再思考
  • AI一周热点事件(全球AI新闻-2025年3月17日至3月24日)
  • 2-1 MATLAB鮣鱼优化算法ROA优化LSTM超参数回归预测
  • Javaweb后端登录会话技术jwt令牌
  • 23种设计模式-结构型模式-适配器
  • 线程池参数如何设定?如何动态调整线程池?
  • 字符串交替合并问题
  • Mysql内置函数篇
  • 【Golang】第八弹----面向对象编程
  • 如何使用Python实现智能交通信号控制系统
  • [特殊字符] 2025蓝桥杯备赛Day13——P10984 [蓝桥杯 2023 国 Python A] 残缺的数字
  • DNA-PAINT
  • 基于javaweb的spring学生选课管理系统设计与实现(源码+文档+部署讲解)
  • 自动化逆向框架使用(Objection+Radare2)
  • 揭秘大数据 | 12、大数据的五大问题 之 大数据管理与大数据分析
  • Android Compose 框架隐式动画之过渡动画深入剖析(二十六)
  • ADB工具电视盒子刷机详细教程
  • 【c++入门系列】:引用以及内联函数详解