From d06e669017e9b18da10f0739aac46830d7838dee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Thu, 30 Jul 2009 10:10:34 +0200 Subject: [PATCH] Preprocessor: Speedup of the match_cfg_def function --- src/preprocessor.cpp | 99 ++++++++++++++++++++++++++------------- src/preprocessor.h | 2 +- test/testpreprocessor.cpp | 29 ++++++++---- 3 files changed, 88 insertions(+), 42 deletions(-) diff --git a/src/preprocessor.cpp b/src/preprocessor.cpp index 219b60563..f24b8c34c 100644 --- a/src/preprocessor.cpp +++ b/src/preprocessor.cpp @@ -784,11 +784,14 @@ std::list Preprocessor::getcfgs(const std::string &filedata) -bool Preprocessor::match_cfg_def(std::string cfg, std::string def) +bool Preprocessor::match_cfg_def(const std::map &cfg, std::string def) { //std::cout << "cfg: \"" << cfg << "\" "; //std::cout << "def: \"" << def << "\""; + if (cfg.find(def) != cfg.end()) + return true; + for (std::string::size_type pos = def.find("defined("); pos != std::string::npos; pos = def.find("defined(", pos + 1)) { // The character before "defined" must not be '_' or alphanumeric @@ -803,8 +806,7 @@ bool Preprocessor::match_cfg_def(std::string cfg, std::string def) std::string::size_type pos1 = pos + 8; const std::string par(def.substr(pos1, pos2 - pos1)); - /** @todo better checking if parameter is defined */ - const bool isdefined(cfg.find(par) != std::string::npos); + const bool isdefined(cfg.find(par) != cfg.end()); def.erase(pos, pos2 + 1 - pos); def.insert(pos, isdefined ? "1" : "0"); @@ -826,29 +828,31 @@ bool Preprocessor::match_cfg_def(std::string cfg, std::string def) if (def == "1") return true; - if (cfg.empty()) - return false; + /* + if (cfg.empty()) + return false; - // remove the define values - while (cfg.find("=") != std::string::npos) - { - std::string::size_type pos1 = cfg.find("="); - std::string::size_type pos2 = cfg.find(";", pos1); - if (pos2 == std::string::npos) - cfg.erase(pos1); - else - cfg.erase(pos1, pos2 - pos1); - } + // remove the define values + while (cfg.find("=") != std::string::npos) + { + std::string::size_type pos1 = cfg.find("="); + std::string::size_type pos2 = cfg.find(";", pos1); + if (pos2 == std::string::npos) + cfg.erase(pos1); + else + cfg.erase(pos1, pos2 - pos1); + } - while (! cfg.empty()) - { - if (cfg.find(";") == std::string::npos) - return bool(cfg == def); - std::string _cfg = cfg.substr(0, cfg.find(";")); - if (_cfg == def) - return true; - cfg.erase(0, cfg.find(";") + 1); - } + while (! cfg.empty()) + { + if (cfg.find(";") == std::string::npos) + return bool(cfg == def); + std::string _cfg = cfg.substr(0, cfg.find(";")); + if (_cfg == def) + return true; + cfg.erase(0, cfg.find(";") + 1); + } + */ return false; } @@ -862,6 +866,40 @@ std::string Preprocessor::getcode(const std::string &filedata, std::string cfg, std::list matching_ifdef; std::list matched_ifdef; + // Create a map for the cfg for faster access to defines + std::map cfgmap; + { + std::string::size_type pos = 0; + while (true) + { + std::string::size_type pos2 = cfg.find_first_of(";=", pos); + if (pos2 == std::string::npos) + { + cfgmap[cfg.substr(pos)] = ""; + break; + } + if (cfg[pos2] == ';') + { + cfgmap[cfg.substr(pos, pos2-pos)] = ""; + } + else + { + std::string::size_type pos3 = pos2; + pos2 = cfg.find(";", pos2); + if (pos2 == std::string::npos) + { + cfgmap[cfg.substr(pos, pos3-pos)] = cfg.substr(pos3 + 1); + break; + } + else + { + cfgmap[cfg.substr(pos, pos3-pos)] = cfg.substr(pos3 + 1, pos2 - pos3 - 1); + } + } + pos = pos2 + 1; + } + } + std::istringstream istr(filedata); std::string line; while (getline(istr, line)) @@ -871,14 +909,11 @@ std::string Preprocessor::getcode(const std::string &filedata, std::string cfg, if (line.substr(0, 8) == "#define " && line.find("(", 8) == std::string::npos) { - if (!cfg.empty()) - cfg += ";"; std::string::size_type pos = line.find(" ", 8); if (pos == std::string::npos) - cfg += line.substr(8); + cfgmap[line.substr(8)] = ""; else - cfg += line.substr(8, pos - 8) + "=" + line.substr(pos + 1); - // std::cout << cfg << std::endl; + cfgmap[line.substr(8, pos - 8)] = line.substr(pos + 1); } else if (line.find("#elif ") == 0) @@ -889,7 +924,7 @@ std::string Preprocessor::getcode(const std::string &filedata, std::string cfg, } else { - if (match_cfg_def(cfg, def)) + if (match_cfg_def(cfgmap, def)) { matching_ifdef.back() = true; matched_ifdef.back() = true; @@ -899,13 +934,13 @@ std::string Preprocessor::getcode(const std::string &filedata, std::string cfg, else if (! def.empty()) { - matching_ifdef.push_back(match_cfg_def(cfg, def)); + matching_ifdef.push_back(match_cfg_def(cfgmap, def)); matched_ifdef.push_back(matching_ifdef.back()); } else if (! ndef.empty()) { - matching_ifdef.push_back(! match_cfg_def(cfg, ndef)); + matching_ifdef.push_back(! match_cfg_def(cfgmap, ndef)); matched_ifdef.push_back(matching_ifdef.back()); } diff --git a/src/preprocessor.h b/src/preprocessor.h index 7cf430b94..001e1b12d 100644 --- a/src/preprocessor.h +++ b/src/preprocessor.h @@ -131,7 +131,7 @@ public: * @param def condition * @return result when evaluating the condition */ - static bool match_cfg_def(std::string cfg, std::string def); + static bool match_cfg_def(const std::map &cfg, std::string def); private: /** diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index 772ff1f93..983901891 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -523,17 +523,28 @@ private: void match_cfg_def() { - TODO_ASSERT_EQUALS(false, Preprocessor::match_cfg_def("ABC", "defined(A)")); - TODO_ASSERT_EQUALS(true, Preprocessor::match_cfg_def("ABC", "!defined(A)")); + { + std::map cfg; + cfg["ABC"] = ""; - ASSERT_EQUALS(false, Preprocessor::match_cfg_def("A", "!defined(A)&&!defined(B)")); - TODO_ASSERT_EQUALS(true, Preprocessor::match_cfg_def("C", "!defined(A)&&!defined(B)")); + ASSERT_EQUALS(false, Preprocessor::match_cfg_def(cfg, "defined(A)")); + TODO_ASSERT_EQUALS(true, Preprocessor::match_cfg_def(cfg, "!defined(A)")); - TODO_ASSERT_EQUALS(true, Preprocessor::match_cfg_def("A=1", "A==1")); - TODO_ASSERT_EQUALS(true, Preprocessor::match_cfg_def("A=1", "A<2")); - ASSERT_EQUALS(false, Preprocessor::match_cfg_def("A=1", "A==2")); - ASSERT_EQUALS(false, Preprocessor::match_cfg_def("A=1", "A<1")); - TODO_ASSERT_EQUALS(true, Preprocessor::match_cfg_def("A=2;B=1;C", "A>=1&&B<=A")); + ASSERT_EQUALS(false, Preprocessor::match_cfg_def(cfg, "!defined(ABC)&&!defined(DEF)")); + TODO_ASSERT_EQUALS(true, Preprocessor::match_cfg_def(cfg, "!defined(A)&&!defined(B)")); + } + + { + std::map cfg; + cfg["A"] = "1"; + cfg["B"] = "2"; + + TODO_ASSERT_EQUALS(true, Preprocessor::match_cfg_def(cfg, "A==1")); + TODO_ASSERT_EQUALS(true, Preprocessor::match_cfg_def(cfg, "A<2")); + ASSERT_EQUALS(false, Preprocessor::match_cfg_def(cfg, "A==2")); + ASSERT_EQUALS(false, Preprocessor::match_cfg_def(cfg, "A<1")); + TODO_ASSERT_EQUALS(true, Preprocessor::match_cfg_def(cfg, "A>=1&&B<=A")); + } }