1. hashimotoryoh

    Posted

    hashimotoryoh
Changes in title
+【Cocos2d-x】cocos2d::Valueを使うのに便利なメソッドをいくつか作った
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,204 @@
+# `cocos2d::Value`の中身を良い感じに出力する
+
+PHPの`var_dump()`みたいな感じ。
+
+```cpp
+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`の中身を細かく比較する
+
+```cpp
+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::ValueMap``cocos2d::ValueMapIntKey`の中に該当するキーが存在するか調べる
+
+```cpp
+
+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`の中に該当する値があるか調べる
+
+```cpp
+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;
+}
+```