Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

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;
}
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away