Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
3
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

@hashimotoryoh

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

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
3
Help us understand the problem. What are the problem?