LoginSignup
3
3

More than 5 years have passed since last update.

【Cocos2d-x】cocos2d::Valueを使うのに便利なメソッドをいくつか作った

Posted at

cocos2d::Valueの中身を良い感じに出力する

PHPのvar_dump()みたいな感じ。

void ValueHelper::dumpValue(const cocos2d::Value &value)
{
    CCLOG("%s", ValueHelper::getDumpString(value).c_str());
}

std::string ValueHelper::getDumpString(const cocos2d::Value &value,
                                       unsigned int level /* = 1 */)
{
    std::string ret;

    switch (value.getType()) {
        case Value::Type::NONE:    ret = "NONE,\n";                                                                 break;
        case Value::Type::BYTE:    ret = StringUtils::format("BYTE(%c),\n",    value.asByte());                     break;
        case Value::Type::INTEGER: ret = StringUtils::format("INTEGER(%d),\n", value.asInt());                      break;
        case Value::Type::FLOAT:   ret = StringUtils::format("FLOAT(%f),\n",   value.asFloat());                    break;
        case Value::Type::DOUBLE:  ret = StringUtils::format("DOUBLE(%f),\n",  value.asDouble());                   break;
        case Value::Type::BOOLEAN: ret = StringUtils::format("BOOLEAN(%s),\n", value.asBool() ? "true" : "false");  break;
        case Value::Type::STRING:  ret = StringUtils::format("STRING(%s),\n",  value.asString().c_str());           break;

        case Value::Type::VECTOR:
            ret += "VECTOR(" + StrUtils::intToString((int)value.asValueVector().size()) + ")(\n";
            for (Value child : value.asValueVector()) {
                // 階層によるインデント
                for (int i=0; i<level; i++) ret += "    ";
                ret += ValueHelper::getDumpString(child, level+1);
            }
            // 階層によるインデント
            for (int i=0; i<level-1; i++) ret += "    ";
            ret += "),\n";
            break;

        case Value::Type::MAP:
            ret += "MAP(" + StrUtils::intToString((int)value.asValueMap().size()) + "){\n";
            for (ValueMap::const_iterator itr = value.asValueMap().begin(); itr != value.asValueMap().end(); itr++) {
                // 階層によるインデント
                for (int i=0; i<level; i++) ret += "    ";
                ret += StringUtils::format("\"%s\": ", (*itr).first.c_str()) + ValueHelper::getDumpString((*itr).second, level+1);
            }
            // 階層によるインデント
            for (int i=0; i<level-1; i++) ret += "    ";
            ret += "},\n";
            break;

        case Value::Type::INT_KEY_MAP:
            ret += "INT_KEY_MAP(" + StrUtils::intToString((int)value.asIntKeyMap().size()) + "){\n";
            for (ValueMap::const_iterator itr = value.asValueMap().begin(); itr != value.asValueMap().end(); itr++) {
                // 階層によるインデント
                for (int i=0; i<level; i++) ret += "    ";
                ret += StringUtils::format("\"%s\": ", (*itr).first.c_str()) + ValueHelper::getDumpString((*itr).second, level+1);
            }
            // 階層によるインデント
            for (int i=0; i<level-1; i++) ret += "    ";
            ret += "},\n";
            break;

        default:
            NERROR("引数 value の getType() の値が不正です。: %d", value.getType());
            break;
    }

    return ret;
}

cocos2d::Valueの中身を細かく比較する

bool ValueHelper::isEqual(const cocos2d::Value &value1,
                          const cocos2d::Value &value2)
{
    // 型が違えばもう違う
    if (value1.getType() != value2.getType()) return false;

    /***** 以下、value1とvalue2の型が等しいことは保証される *****/

    switch (value1.getType()) {
        case Value::Type::NONE:        return true;     // 中身が無いので比較する必要無し
        case Value::Type::BYTE:        return (value1.asByte()   == value2.asByte());
        case Value::Type::INTEGER:     return (value1.asInt()    == value2.asInt());
        case Value::Type::FLOAT:       return (value1.asFloat()  == value2.asFloat());
        case Value::Type::DOUBLE:      return (value1.asDouble() == value2.asDouble());
        case Value::Type::BOOLEAN:     return (value1.asBool()   == value2.asBool());
        case Value::Type::STRING:      return (value1.asString() == value2.asString());
        case Value::Type::VECTOR:      return ValueHelper::isEqualVector(value1.asValueVector(), value2.asValueVector());
        case Value::Type::MAP:         return ValueHelper::isEqualMap(value1.asValueMap(), value2.asValueMap());
        case Value::Type::INT_KEY_MAP: return ValueHelper::isEqualIntKeyMap(value1.asIntKeyMap(), value2.asIntKeyMap());
    }

    return false;
}

bool ValueHelper::isEqualVector(const cocos2d::ValueVector vector1,
                                const cocos2d::ValueVector vector2,
                                const bool considerOrder /* = false */)
{
    // 要素数が違えばもう違う
    if (vector1.size() != vector2.size()) return false;

    /***** 以下、vector1とvector2の要素数が等しいことは保証される *****/

    if (considerOrder) {
        // 順序を考慮する場合
        // vector1, vector2の同じ要素番号に格納されている値が、全て同じなら同じ。
        for (unsigned int i=0; i<vector1.size(); i++)
            // 一つでも違えば違う。
            if (!ValueHelper::isEqual(vector1.at(i), vector2.at(i))) return false;
    }
    else {
        // 順序を考慮しない場合
        // 要素数が等しいことは保証されているので、value1の要素が全てvalue2に入っていれば同じ。
        for (Value childValue1 : vector1)
            // 一つでも違えば違う。
            if (!ValueHelper::isContainsValue(vector2, childValue1)) return false;
    }

    return true;
}


bool ValueHelper::isEqualMap(const cocos2d::ValueMap &map1,
                             const cocos2d::ValueMap &map2)
{
    // 要素数が違えばもう違う
    if (map1.size() != map2.size()) return false;

    /**** 以下、map1とmap2の要素数が等しいことは保証される *****/

    // 要素数が等しいことは保証されているので、value1の全ての要素について
    //   - 同じキーが有る
    //   - そのキーに対する値が等しい
    // なら同じ。
    for (std::pair<std::string, Value> pair : map1) {
        const std::string key        = pair.first;
        const Value       childValue = pair.second;
        // 一つでも違えば違う。
        if (!ValueHelper::isExistsKey(map2, key)
            ||
            !ValueHelper::isEqual(childValue, map2.at(key))) return false;
    }

    return true;
}


bool ValueHelper::isEqualIntKeyMap(const cocos2d::ValueMapIntKey &map1,
                                     const cocos2d::ValueMapIntKey &map2)
{
    // 要素数が違えばもう違う
    if (map1.size() != map2.size()) return false;

    /**** 以下、map1とmap2の要素数が等しいことは保証される *****/

    // 要素数が等しいことは保証されているので、value1の全ての要素について
    //   - 同じキーが有る
    //   - そのキーに対する値が等しい
    // なら同じ。
    for (std::pair<int, Value> pair : map1) {
        const int key          = pair.first;
        const Value childValue = pair.second;
        // 一つでも違えば違う。
        if (!ValueHelper::isExistsKey(map2, key)
            ||
            !ValueHelper::isEqual(childValue, map2.at(key))) return false;
    }

    return true;
}

cocos2d::ValueMapcocos2d::ValueMapIntKeyの中に該当するキーが存在するか調べる


bool ValueHelper::isExistsKey(const cocos2d::ValueMap &map,
                              const std::string &key)
{
    return (map.find(key) != map.end());
}

bool ValueHelper::isExistsKey(const cocos2d::ValueMapIntKey &map,
                              const int key)
{
    return (map.find(key) != map.end());
}

cocos2d::ValueVectorの中に該当する値があるか調べる

bool ValueHelper::isContainsValue(const cocos2d::ValueVector &vector,
                                  const cocos2d::Value &value)
{
    for (Value comparison : vector)
        // 同値が見つかった時点でtrueを返却
        if (ValueHelper::isEqual(value, comparison)) return true;

    return false;
}
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3