Merge pull request #7269 from minggo/fix-crash

Fix crash
This commit is contained in:
minggo 2014-07-01 16:30:50 +08:00
commit 05ca61d62b
3 changed files with 133 additions and 101 deletions

View File

@ -861,24 +861,25 @@ void Node::enumerateChildren(const std::string &name, std::function<bool (Node *
} }
} }
// TODO: support ends with '/..'
// End with '/..'? // End with '/..'?
bool searchFromParent = false; // bool searchFromParent = false;
if (length > 3 && // if (length > 3 &&
name[length-3] == '/' && // name[length-3] == '/' &&
name[length-2] == '.' && // name[length-2] == '.' &&
name[length-1] == '.') // name[length-1] == '.')
{ // {
searchFromParent = true; // searchFromParent = true;
subStrlength -= 3; // subStrlength -= 3;
} // }
// Remove '/', '//' and '/..' if exist // Remove '/', '//' if exist
std::string newName = name.substr(subStrStartPos, subStrlength); std::string newName = name.substr(subStrStartPos, subStrlength);
// If search from parent, then add * at first to make it match its children, which will do make // If search from parent, then add * at first to make it match its children, which will do make
if (searchFromParent) // if (searchFromParent)
{ // {
newName.insert(0, "[[:alnum:]]+/"); // newName.insert(0, "[[:alnum:]]+/");
} // }
if (searchFromRoot) if (searchFromRoot)
{ {
@ -943,10 +944,14 @@ bool Node::doEnumerate(std::string name, std::function<bool (Node *)> callback)
needRecursive = true; needRecursive = true;
} }
std::hash<std::string> h;
size_t hashOfName = h(searchName);
bool ret = false; bool ret = false;
for (const auto& child : _children) for (const auto& child : _children)
{ {
if(std::regex_match(child->_name, std::regex(searchName))) // TODO: regular expression support
// Android doesn't support c++ 11 regular expression well, may use external lib
if (hashOfName == child->_hashOfName && searchName.compare(child->_name) == 0)
{ {
if (!needRecursive) if (!needRecursive)
{ {

View File

@ -714,20 +714,17 @@ public:
virtual Node* getChildByName(const std::string& name) const; virtual Node* getChildByName(const std::string& name) const;
/** Search the children of the receiving node to perform processing for nodes which share a name. /** Search the children of the receiving node to perform processing for nodes which share a name.
* *
* @param name The name to search for, support c++11 regular expression * @param name The name to search for
* Search syntax options: * Search syntax options:
* `/` : When placed at the start of the search string, this indicates that the search should be performed on the tree's node. * `/` : When placed at the start of the search string, this indicates that the search should be performed on the tree's node.
* `//`: Can only be placed at the begin of the search string. This indicates that the search should be performed on the tree's node * `//`: Can only be placed at the begin of the search string. This indicates that the search should be performed on the tree's node
* and be performed recursively across the entire node tree. * and be performed recursively across the entire node tree.
* `..`: The search should move up to the node's parent. Can only be placed at the end of string
* `/` : When placed anywhere but the start of the search string, this indicates that the search should move to the node's children * `/` : When placed anywhere but the start of the search string, this indicates that the search should move to the node's children
* *
* @code * @code
* enumerateChildren("/MyName", ...): This searches the root's children and matches any node with the name `MyName`. * enumerateChildren("/MyName", ...): This searches the root's children and matches any node with the name `MyName`.
* enumerateChildren("//MyName", ...): This searches the root's children recursively and matches any node with the name `MyName`. * enumerateChildren("//MyName", ...): This searches the root's children recursively and matches any node with the name `MyName`.
* enumerateChildren("[[:alnum:]]+", ...): This search string matches every node of its children.
* enumerateChildren("/MyName", ...): This searches the node tree and matches the parent node of every node named `MyName`. * enumerateChildren("/MyName", ...): This searches the node tree and matches the parent node of every node named `MyName`.
* enumerateChildren("A[[:digit:]]", ...): This searches the node's children and returns any child named `A0`, `A1`, ..., `A9`
* enumerateChildren("Abby/Normal", ...): This searches the node's grandchildren and returns any node whose name is `Normal` * enumerateChildren("Abby/Normal", ...): This searches the node's grandchildren and returns any node whose name is `Normal`
* and whose parent is named `Abby`. * and whose parent is named `Abby`.
* enumerateChildren("//Abby/Normal", ...): This searches the node tree and returns any node whose name is `Normal` and whose * enumerateChildren("//Abby/Normal", ...): This searches the node tree and returns any node whose name is `Normal` and whose

View File

@ -1269,28 +1269,28 @@ void NodeNameTest::onEnter()
// enumerateChildren() // enumerateChildren()
// name = regular expression // name = regular expression
int i = 0; int i = 0;
parent = Node::create(); // parent = Node::create();
for (int i = 0; i < 100; ++i) // for (int i = 0; i < 100; ++i)
{ // {
auto node = Node::create(); // auto node = Node::create();
sprintf(name, "node%d", i); // sprintf(name, "node%d", i);
node->setName(name); // node->setName(name);
parent->addChild(node); // parent->addChild(node);
} // }
//
i = 0; // i = 0;
parent->enumerateChildren("node[[:digit:]]+", [&i](Node* node) -> bool { // parent->enumerateChildren("node[[:digit:]]+", [&i](Node* node) -> bool {
++i; // ++i;
return false; // return false;
}); // });
CCAssert(i == 100, ""); // CCAssert(i == 100, "");
//
i = 0; // i = 0;
parent->enumerateChildren("node[[:digit:]]+", [&i](Node* node) -> bool { // parent->enumerateChildren("node[[:digit:]]+", [&i](Node* node) -> bool {
++i; // ++i;
return true; // return true;
}); // });
CCAssert(i == 1, ""); // CCAssert(i == 1, "");
// enumerateChildren // enumerateChildren
@ -1326,89 +1326,119 @@ void NodeNameTest::onEnter()
}); });
CCAssert(i == 1, ""); CCAssert(i == 1, "");
i = 0; // search from root
parent->enumerateChildren("node[[:digit:]]+/node", [&i](Node* node) -> bool {
++i;
return false;
});
CCAssert(i == 10000, "");
i = 0;
parent->enumerateChildren("node[[:digit:]]+/node", [&i](Node* node) -> bool {
++i;
return true;
});
CCAssert(i == 1, "");
// search from parent
// name is xxx/..
i = 0;
parent->enumerateChildren("node/..", [&i](Node* node) -> bool {
++i;
return true;
});
CCAssert(i == 1, "");
i = 0;
parent->enumerateChildren("node/..", [&i](Node* node) -> bool {
++i;
return false;
});
CCAssert(i == 10000, "");
// name = /xxx : search from root
parent = getScene(); parent = getScene();
for (int j = 0; j < 100; j++) for (int i = 0; i < 100; ++i)
{ {
auto node = Node::create(); auto node = Node::create();
sprintf(name, "node%d", j); node->setName("node");
node->setName(name);
parent->addChild(node); parent->addChild(node);
for (int k = 0; k < 100; ++k) for (int j = 0; j < 100; ++j)
{ {
auto child = Node::create(); auto child = Node::create();
sprintf(name, "node%d", k); child->setName("child");
child->setName(name);
node->addChild(child); node->addChild(child);
} }
} }
i = 0; i = 0;
enumerateChildren("/node[[:digit:]]+", [&i](Node* node) -> bool { parent->enumerateChildren("/node", [&i](Node* node) -> bool {
++i; ++i;
return false; return false;
}); });
CCAssert(i == 100, ""); CCAssert(i == 100, "");
i = 0; i = 0;
enumerateChildren("/node[[:digit:]]+", [&i](Node* node) -> bool { parent->enumerateChildren("//child", [&i](Node* node) -> bool {
++i;
return true;
});
CCAssert(i == 1, "");
i = 0;
enumerateChildren("//node[[:digit:]]+", [&i](Node* node) -> bool {
++i;
return false;
});
CCAssert(i == 10100, ""); // 10000(children) + 100(parent)
i = 0;
enumerateChildren("//node[[:digit:]]+", [&i](Node* node) -> bool {
++i;
return true;
});
CCAssert(i == 1, "");
i = 0;
enumerateChildren("//node[[:digit:]]+/..", [&i](Node* node) -> bool {
++i; ++i;
return false; return false;
}); });
CCAssert(i == 10000, ""); CCAssert(i == 10000, "");
// i = 0;
// parent->enumerateChildren("node[[:digit:]]+/node", [&i](Node* node) -> bool {
// ++i;
// return false;
// });
// CCAssert(i == 10000, "");
//
// i = 0;
// parent->enumerateChildren("node[[:digit:]]+/node", [&i](Node* node) -> bool {
// ++i;
// return true;
// });
// CCAssert(i == 1, "");
// search from parent
// name is xxx/..
// i = 0;
// parent->enumerateChildren("node/..", [&i](Node* node) -> bool {
// ++i;
// return true;
// });
// CCAssert(i == 1, "");
//
// i = 0;
// parent->enumerateChildren("node/..", [&i](Node* node) -> bool {
// ++i;
// return false;
// });
// CCAssert(i == 10000, "");
// name = /xxx : search from root
// parent = getScene();
// for (int j = 0; j < 100; j++)
// {
// auto node = Node::create();
// sprintf(name, "node%d", j);
// node->setName(name);
// parent->addChild(node);
//
// for (int k = 0; k < 100; ++k)
// {
// auto child = Node::create();
// sprintf(name, "node%d", k);
// child->setName(name);
// node->addChild(child);
// }
// }
//
// i = 0;
// enumerateChildren("/node[[:digit:]]+", [&i](Node* node) -> bool {
// ++i;
// return false;
// });
// CCAssert(i == 100, "");
// i = 0;
// enumerateChildren("/node[[:digit:]]+", [&i](Node* node) -> bool {
// ++i;
// return true;
// });
// CCAssert(i == 1, "");
//
// i = 0;
// enumerateChildren("//node[[:digit:]]+", [&i](Node* node) -> bool {
// ++i;
// return false;
// });
// CCAssert(i == 10100, ""); // 10000(children) + 100(parent)
//
// i = 0;
// enumerateChildren("//node[[:digit:]]+", [&i](Node* node) -> bool {
// ++i;
// return true;
// });
// CCAssert(i == 1, "");
//
// i = 0;
// enumerateChildren("//node[[:digit:]]+/..", [&i](Node* node) -> bool {
// ++i;
// return false;
// });
// CCAssert(i == 10000, "");
// utils::findChildren() // utils::findChildren()
parent = Node::create(); parent = Node::create();