[Bugfix]CCFileUtils 解析 UTF8+BOM 字节文件时“key not found”的问题

存在 bug 的版本

Quick-Cocos2dx-Community 3.6 Release 以及 Cocos2d-x 3.3 final中。

bug 将在 Quick-Cocos2dx-Community 3.6.1 中修正。

bug 描述

CCFileUtils.cpp 文件中有一个用于帮助解析文本的 DictMaker 类。当解析带有 UTF8+BOM 的文件时,程序会首先调用 DictMaker 类的 textHandler 方法来解析文本。如下所示:

void textHandler(void *ctx, const char *ch, int len)
{
    CC_UNUSED_PARAM(ctx);
    if (_state == SAX_NONE)
    {
        return;
    }

    SAXState curState = _stateStack.empty() ? SAX_DICT : _stateStack.top();
    const std::string text = std::string((char*)ch,len);

    switch(_state)
    {
    case SAX_KEY:
        _curKey = text;
        break;
    case SAX_INT:
    case SAX_REAL:
    case SAX_STRING:
        {
            if (curState == SAX_DICT)
            {
                CCASSERT(!_curKey.empty(), "key not found : <integer/real>");
            }
            
            _curValue.append(text);
        }
        break;
    default:
        break;
    }
}

在以上方法开头会先判断 _state 值是否为 SAX_NONE。这里 _state 是 DictMaker 类中的一个变量,它是一个SAXState类型的枚举变量,用来表示 sax (用于处理XML事件驱动的推模型)的状态。细节我们这里就不过多的追究,这里我想说的是 _state 值一直都没被初始化,意思就是说进入 textHandler 方法事它根本就没有初值,判断 _state 值是否为 SAX_NONE是没有意义的。因为未初始化的变量值是不确定的,可能为0,也可能为任意的乱值。所以如果_state 的值恰好为5,也就是为枚举值SAX_STRING 时,就会报以下的错:

CCASSERT(!_curKey.empty(), "key not found : <integer/real>");

为了解决这个问题,显然我们应该先初始化这个值。

解决方案

在DictMaker的构造函数中加入_state的初始值,如下:

DictMaker()        
    : _resultType(SAX_RESULT_NONE)
    ,_state(SAX_NONE)
{
}

注:感谢“NO风鸟院花月”童鞋的反馈,以及提供的解决方案。

标签: none

?>