int NPathComplexityMetric::nPath(ForStmt *stmt) { // TODO: // Base on Nejmeh's NPATH, the first expression is used to initialize a loop control variable, // But the first child node for For statment is a statement in Clang's AST. // So here we need to be clear that if it's a statement or an expression // If it's a statement, meaning, a sequential statement, npath will be 1 // If it's an expression, on the contrary, without && or ||, npath should be 0 // For the implementation below, we treat it as a statement for now. // // And I realize here that, as a note: // If statment and If-Else statement are most easy cases to understand the nPath concept. // And both switch statement and for statement can be converted to if statement, // however, I noticed that, with the same logic, if the presentation formats are different, // the NPath of it may vary, // for example, for the following if statement // if (i == 1) { foo(1); } if (i == 2) { foo(2); } // NPath of it will be 4 // However, if convert to switch statement, it will be // switch (i) { case 1: foo(1); break; case 2: foo(2); break; }, the NPath is 2 here // Converted to for statement, it is // for (int i = 1; i <= 2; i++) { foo(i); }, the NPath is 3 // As a conclusion, in my opinion, same logic in different formats should not reduce // the complexity. However, here, I will follow Nejmeh's NPath return nPath(stmt->getInit()) + nPath(stmt->getCond()) + nPath(stmt->getInc()) + nPath(stmt->getBody()) + 1; }
int NPathComplexityMetric::nPath(BinaryOperator *expr) { if (expr->getOpcode() == BO_LAnd || expr->getOpcode() == BO_LOr) { return 1 + nPath(expr->getLHS()) + nPath(expr->getRHS()); } return 0; }
int NPathComplexityMetric::nPath(IfStmt *stmt) { int nPathElseStmt = 1; Stmt *elseStmt = stmt->getElse(); if (elseStmt) { nPathElseStmt = nPath(elseStmt); } return nPath(stmt->getCond()) + nPath(stmt->getThen()) + nPathElseStmt; }
int minCut(string s) { int n = (int) s.length(); vector<vector<int> > nexts(n+1); for (int i = 0; i < n; i++){ for (int d = 0; (i-d >= 0 && i+d < n); d++){ if (s[i-d] == s[i+d]) { nexts[i-d].push_back(i+d+1); } else break; } for (int d = 0; (i-d >= 0 && i+d < n); d++){ if (s[i-d] == s[i+1+d]) { nexts[i-d].push_back(i+d+2); } else break; } } // This version is a quadratic algorithm, subject to reduce to O(1) vector<int> nPath(n+1, INT_MAX); nPath[0] = 0; for (int i = 0; i < n; i++){ for (int j = 0; j < nexts[i].size(); j++){ nPath[nexts[i][j]] = min(nPath[nexts[i][j]], nPath[i] + 1); } } return nPath[n] - 1; }
int NPathComplexityMetric::nPath(CompoundStmt *stmt) { int npath = 1; for (CompoundStmt::body_iterator body = stmt->body_begin(), bodyEnd = stmt->body_end(); body != bodyEnd; body++) { npath *= nPath(*body); } return npath; }
int NPathComplexityMetric::nPath(SwitchStmt *stmt) { int internalNPath = 0, nPathSwitchStmt = nPath(stmt->getCond()); CompoundStmt *body = (CompoundStmt *)stmt->getBody(); for (CompoundStmt::body_iterator bodyStmt = body->body_begin(), bodyStmtEnd = body->body_end(); bodyStmt != bodyStmtEnd; bodyStmt++) { if (isa<SwitchCase>(*bodyStmt)) { SwitchCase *switchCase = dyn_cast<SwitchCase>(*bodyStmt); nPathSwitchStmt += internalNPath; internalNPath = nPath(switchCase->getSubStmt()); } else { internalNPath *= nPath(*bodyStmt); } } return nPathSwitchStmt + internalNPath; }
int NPathComplexityMetric::nPath(ObjCForCollectionStmt *stmt) { // If we convert a foreach loop to a simple for loop, it will looks like // for (int i = 0; i < [anArray count]; i++) { // id it = [anArray objectAtIndex:i]; // ... (same as foreach loop block) // } // So, convert to same logic in for statement, we assume the NPath complexity as below // NP(Foreach) := NP((for-range)) + 2 return nPath(stmt->getBody()) + 2; }
tree_node_<FILE_ITEM>* CFileTree::findNodeFromRootWithPath(char *path) { // No topNode - bail out. if (topNode.node == NULL){ return NULL; } std::string sPath(path); std::string nPath(topNode->path); // topNode path and requested path are the same? Use the node. if (sPath == nPath) { return topNode.node; } // printf("Did not find node for path : %s\n", path); // If the topNode path is part of the requested path this is a subpath. // Use the node. if (sPath.find(nPath) != std::string::npos) { // printf("Found %s is part of %s \n", sPath.c_str(), topNode->path); std::string splittedString = sPath.substr(strlen(topNode->path) + 1); return findNodeWithPathFromNode(splittedString, topNode.node); } else { // If the current topNode isn't related to the requested path // iterate over all _top_ level elements in the tree to look for // a matching item and register it as current top node. // printf("NOT found %s is NOT part of %s \n", sPath.c_str(), topNode->path); tree<FILE_ITEM>::sibling_iterator it; for (it = filesTree.begin(); it != filesTree.end(); it++) { std::string itPath(it.node->data.path); // Current item path matches the requested path - use the item as topNode. if (sPath == itPath) { // printf("Found parent node %s \n", it.node->data.path); topNode = it; return it.node; } else if (sPath.find(itPath) != std::string::npos) { // If the item path is part of the requested path this is a subpath. // Use the the item as topNode and continue analyzing. // printf("Found root node %s \n", it.node->data.path); topNode = it; std::string splittedString = sPath.substr(itPath.length() + 1); return findNodeWithPathFromNode(splittedString, it.node); } } } // Nothing found return NULL. return NULL; }
tree_node_<FILE_ITEM>* CFileTree::findParentNodeFromRootForPath(char *path) { std::string sPath(path); std::string nPath(topNode->path); // If the topNode path is not part of the requested path bail out. // This avoids also issues with taking substrings of incompatible // paths below. if (sPath.find(nPath) == std::string::npos) { // printf("Path %s doesn't belong to current topNode %s Found %s is part of %s \n", sPath.c_str(), topNode->path); return NULL; } std::string currentPath = sPath.substr(strlen(topNode->path) + 1); std::string followingPath = _dirname_932(currentPath); if (followingPath.empty()) { return topNode.node; } else { return findNodeWithPathFromNode(followingPath, topNode.node); } }
int NPathComplexityMetric::nPath(ConditionalOperator *expr) { return nPath(expr->getCond()) + nPath(expr->getTrueExpr()) + nPath(expr->getFalseExpr()) + 2; }
int NPathComplexityMetric::nPath(DoStmt *stmt) { return nPath(stmt->getCond()) + nPath(stmt->getBody()) + 1; }
int NPathComplexityMetric::nPath(CastExpr *expr) { return nPath(expr->getSubExpr()); }