From 6f8832bf12b57d55c565ff15aa337e90998c3350 Mon Sep 17 00:00:00 2001 From: Gabriel Ferreira Date: Wed, 25 May 2022 11:41:52 -0300 Subject: [PATCH] topology-read: replace regex.h implementation with C++ regex --- src/topology-read/CMakeLists.txt | 1 - src/topology-read/examples/CMakeLists.txt | 22 ++- .../model/rocketfuel-topology-reader.cc | 165 +++++++----------- .../model/rocketfuel-topology-reader.h | 8 +- 4 files changed, 76 insertions(+), 120 deletions(-) diff --git a/src/topology-read/CMakeLists.txt b/src/topology-read/CMakeLists.txt index 17e3b4e19..df8e4cbd5 100644 --- a/src/topology-read/CMakeLists.txt +++ b/src/topology-read/CMakeLists.txt @@ -13,6 +13,5 @@ build_lib( model/rocketfuel-topology-reader.h model/topology-reader.h LIBRARIES_TO_LINK ${libnetwork} - ${PCRE_LIBRARIES} TEST_SOURCES test/rocketfuel-topology-reader-test-suite.cc ) diff --git a/src/topology-read/examples/CMakeLists.txt b/src/topology-read/examples/CMakeLists.txt index 5ed3442fd..4b6207f5e 100644 --- a/src/topology-read/examples/CMakeLists.txt +++ b/src/topology-read/examples/CMakeLists.txt @@ -1,12 +1,10 @@ -if(PCRE_FOUND) - build_lib_example( - NAME topology-example-sim - SOURCE_FILES topology-example-sim.cc - LIBRARIES_TO_LINK - ${libtopology-read} - ${libinternet} - ${libnix-vector-routing} - ${libpoint-to-point} - ${libapplications} - ) -endif() +build_lib_example( + NAME topology-example-sim + SOURCE_FILES topology-example-sim.cc + LIBRARIES_TO_LINK + ${libtopology-read} + ${libinternet} + ${libnix-vector-routing} + ${libpoint-to-point} + ${libapplications} +) diff --git a/src/topology-read/model/rocketfuel-topology-reader.cc b/src/topology-read/model/rocketfuel-topology-reader.cc index e5635f604..babe25182 100644 --- a/src/topology-read/model/rocketfuel-topology-reader.cc +++ b/src/topology-read/model/rocketfuel-topology-reader.cc @@ -21,8 +21,8 @@ #include #include #include -#include -#include +#include +#include #include "ns3/log.h" #include "ns3/node-container.h" #include "rocketfuel-topology-reader.h" @@ -64,9 +64,6 @@ RocketfuelTopologyReader::~RocketfuelTopologyReader () /* uid @loc [+] [bb] (num_neigh) [&ext] -> ... {-euid} ... =name[!] rn */ -/// Maximum nuber of matches in a regex query -#define REGMATCH_MAX 16 - /// Start of a line #define START "^" /// End of a line @@ -90,6 +87,16 @@ RocketfuelTopologyReader::~RocketfuelTopologyReader () #define ROCKETFUEL_WEIGHTS_LINE \ START "([^ \t]+)" SPACE "([^ \t]+)" SPACE "([0-9.]+)" MAYSPACE END +/** + * Regex object for RocketFuel topology maps file type + */ +static const std::regex rocketfuel_maps_regex (ROCKETFUEL_MAPS_LINE, std::regex::extended); + +/** + * Regex object for RocketFuel topology weights file type + */ +static const std::regex rocketfuel_weights_regex (ROCKETFUEL_WEIGHTS_LINE, std::regex::extended); + /** * \brief Print node info * \param uid node ID @@ -113,13 +120,12 @@ PrintNodeInfo (std::string & uid, std::string & loc, bool dns, bool bb, } NodeContainer -RocketfuelTopologyReader::GenerateFromMapsFile (int argc, char *argv[]) +RocketfuelTopologyReader::GenerateFromMapsFile (const std::vector &argv) { std::string uid; std::string loc; std::string ptr; std::string name; - std::string nuid; bool dns = false; bool bb = false; int num_neigh_s = 0; @@ -131,17 +137,17 @@ RocketfuelTopologyReader::GenerateFromMapsFile (int argc, char *argv[]) uid = argv[0]; loc = argv[1]; - if (argv[2]) + if (!argv[2].empty ()) { dns = true; } - if (argv[3]) + if (!argv[3].empty ()) { bb = true; } - num_neigh_s = ::atoi (argv[4]); + num_neigh_s = std::stoi (argv[4]); if (num_neigh_s < 0) { num_neigh = 0; @@ -153,15 +159,18 @@ RocketfuelTopologyReader::GenerateFromMapsFile (int argc, char *argv[]) } /* neighbors */ - if (argv[6]) + if (!argv[6].empty ()) { - char *nbr; - char *stringp = argv[6]; - while ((nbr = strsep (&stringp, " \t")) != NULL) - { - nbr[strlen (nbr) - 1] = '\0'; - neigh_list.push_back (nbr + 1); - } + // Each line contains a list <.*>[ |\t]<.*>[ |\t]<.*>[ |\t] + // First remove < and > + std::string temp; + std::regex replace_regex ("[<|>]"); + std::regex_replace (std::back_inserter (temp), argv[6].begin (), argv[6].end (), replace_regex, ""); + + // Then split list + std::regex split_regex ("[ |\t]"); + std::sregex_token_iterator first{temp.begin (), temp.end (), split_regex, -1}, last; + neigh_list = std::vector{first, last}; } if (num_neigh != neigh_list.size ()) { @@ -169,18 +178,18 @@ RocketfuelTopologyReader::GenerateFromMapsFile (int argc, char *argv[]) } /* externs */ - if (argv[7]) + if (!argv[7].empty ()) { // euid = argv[7]; } /* name */ - if (argv[8]) + if (!argv[8].empty ()) { name = argv[8]; } - radius = ::atoi (&argv[9][1]); + radius = std::atoi (&argv[9][1]); if (radius > 0) { return nodes; @@ -191,7 +200,7 @@ RocketfuelTopologyReader::GenerateFromMapsFile (int argc, char *argv[]) // Create node and link if (!uid.empty ()) { - if (m_nodeMap[uid] == 0) + if (m_nodeMap[uid] == nullptr) { Ptr tmpNode = CreateObject (); m_nodeMap[uid] = tmpNode; @@ -199,16 +208,14 @@ RocketfuelTopologyReader::GenerateFromMapsFile (int argc, char *argv[]) m_nodesNumber++; } - for (uint32_t i = 0; i < neigh_list.size (); ++i) + for (auto & nuid : neigh_list) { - nuid = neigh_list[i]; - if (nuid.empty ()) { return nodes; } - if (m_nodeMap[nuid] == 0) + if (m_nodeMap[nuid] == nullptr) { Ptr tmpNode = CreateObject (); m_nodeMap[nuid] = tmpNode; @@ -228,19 +235,19 @@ RocketfuelTopologyReader::GenerateFromMapsFile (int argc, char *argv[]) } NodeContainer -RocketfuelTopologyReader::GenerateFromWeightsFile (int argc, char *argv[]) +RocketfuelTopologyReader::GenerateFromWeightsFile (const std::vector& argv) { /* uid @loc [+] [bb] (num_neigh) [&ext] -> ... {-euid} ... =name[!] rn */ std::string sname; std::string tname; - char *endptr; + std::string::size_type endptr; NodeContainer nodes; sname = argv[0]; tname = argv[1]; - [[maybe_unused]] double v = strtod (argv[2], &endptr); // weight + double v [[maybe_unused]] = std::stod (argv[2], &endptr); // weight - if (*endptr != '\0') + if (argv[2].size () != endptr) { NS_LOG_WARN ("invalid weight: " << argv[2]); return nodes; @@ -249,7 +256,7 @@ RocketfuelTopologyReader::GenerateFromWeightsFile (int argc, char *argv[]) // Create node and link if (!sname.empty () && !tname.empty ()) { - if (m_nodeMap[sname] == 0) + if (m_nodeMap[sname] == nullptr) { Ptr tmpNode = CreateObject (); m_nodeMap[sname] = tmpNode; @@ -257,7 +264,7 @@ RocketfuelTopologyReader::GenerateFromWeightsFile (int argc, char *argv[]) m_nodesNumber++; } - if (m_nodeMap[tname] == 0) + if (m_nodeMap[tname] == nullptr) { Ptr tmpNode = CreateObject (); m_nodeMap[tname] = tmpNode; @@ -291,42 +298,24 @@ RocketfuelTopologyReader::GenerateFromWeightsFile (int argc, char *argv[]) } enum RocketfuelTopologyReader::RF_FileType -RocketfuelTopologyReader::GetFileType (const char *line) +RocketfuelTopologyReader::GetFileType (const std::string& line) { int ret; - regmatch_t regmatch[REGMATCH_MAX]; - regex_t regex; - char errbuf[512]; - // Check whether MAPS file or not - ret = regcomp (®ex, ROCKETFUEL_MAPS_LINE, REG_EXTENDED | REG_NEWLINE); - if (ret != 0) + // Check whether Maps file or not + std::smatch matches; + ret = std::regex_match (line, matches, rocketfuel_maps_regex); + if (ret) { - regerror (ret, ®ex, errbuf, sizeof (errbuf)); - return RF_UNKNOWN; - } - ret = regexec (®ex, line, REGMATCH_MAX, regmatch, 0); - if (ret != REG_NOMATCH) - { - regfree (®ex); return RF_MAPS; } - regfree (®ex); // Check whether Weights file or not - ret = regcomp (®ex, ROCKETFUEL_WEIGHTS_LINE, REG_EXTENDED | REG_NEWLINE); - if (ret != 0) + ret = std::regex_match (line, matches, rocketfuel_weights_regex); + if (ret) { - regerror (ret, ®ex, errbuf, sizeof (errbuf)); - return RF_UNKNOWN; - } - ret = regexec (®ex, line, REGMATCH_MAX, regmatch, 0); - if (ret != REG_NOMATCH) - { - regfree (®ex); return RF_WEIGHTS; } - regfree (®ex); return RF_UNKNOWN; } @@ -343,7 +332,6 @@ RocketfuelTopologyReader::Read (void) std::string line; int lineNumber = 0; enum RF_FileType ftype = RF_UNKNOWN; - char errbuf[512]; if (!topgen.is_open ()) { @@ -354,20 +342,17 @@ RocketfuelTopologyReader::Read (void) while (!topgen.eof ()) { int ret; - int argc; - char *argv[REGMATCH_MAX]; - char *buf; + std::vector argv; lineNumber++; line.clear (); lineBuffer.clear (); getline (topgen, line); - buf = (char *)line.c_str (); if (lineNumber == 1) { - ftype = GetFileType (buf); + ftype = GetFileType (line); if (ftype == RF_UNKNOWN) { NS_LOG_INFO ("Unknown File Format (" << GetFileName () << ")"); @@ -375,78 +360,54 @@ RocketfuelTopologyReader::Read (void) } } - regmatch_t regmatch[REGMATCH_MAX]; - regex_t regex; + std::smatch matches; if (ftype == RF_MAPS) { - ret = regcomp (®ex, ROCKETFUEL_MAPS_LINE, REG_EXTENDED | REG_NEWLINE); - if (ret != 0) + ret = std::regex_match (line, matches, rocketfuel_maps_regex); + if (ret != true || matches.empty ()) { - regerror (ret, ®ex, errbuf, sizeof (errbuf)); - regfree (®ex); - break; - } - - ret = regexec (®ex, buf, REGMATCH_MAX, regmatch, 0); - if (ret == REG_NOMATCH) - { - NS_LOG_WARN ("match failed (maps file): %s" << buf); - regfree (®ex); + NS_LOG_WARN ("match failed (maps file): %s" << line); break; } } else if (ftype == RF_WEIGHTS) { - ret = regcomp (®ex, ROCKETFUEL_WEIGHTS_LINE, REG_EXTENDED | REG_NEWLINE); - if (ret != 0) + ret = std::regex_match (line, matches, rocketfuel_weights_regex); + if (ret != true || matches.empty ()) { - regerror (ret, ®ex, errbuf, sizeof (errbuf)); - regfree (®ex); - break; - } - - ret = regexec (®ex, buf, REGMATCH_MAX, regmatch, 0); - if (ret == REG_NOMATCH) - { - NS_LOG_WARN ("match failed (weights file): %s" << buf); - regfree (®ex); + NS_LOG_WARN ("match failed (weights file): %s" << line); break; } } - line = buf; - argc = 0; + std::string matched_string; - /* regmatch[0] is the entire strings that matched */ - for (int i = 1; i < REGMATCH_MAX; i++) + for (auto it = matches.begin ()+1; it != matches.end (); it++) { - if (regmatch[i].rm_so == -1) + if (it->matched) { - argv[i - 1] = NULL; + matched_string = it->str (); } else { - line[regmatch[i].rm_eo] = '\0'; - argv[i - 1] = &line[regmatch[i].rm_so]; - argc = i; + matched_string = ""; } + argv.push_back (matched_string); } if (ftype == RF_MAPS) { - nodes.Add (GenerateFromMapsFile (argc, argv)); + nodes.Add (GenerateFromMapsFile (argv)); } else if (ftype == RF_WEIGHTS) { - nodes.Add (GenerateFromWeightsFile (argc, argv)); + nodes.Add (GenerateFromWeightsFile (argv)); } else { NS_LOG_WARN ("Unsupported file format (only Maps/Weights are supported)"); } - - regfree (®ex); } diff --git a/src/topology-read/model/rocketfuel-topology-reader.h b/src/topology-read/model/rocketfuel-topology-reader.h index b57bc353d..d1a561cca 100644 --- a/src/topology-read/model/rocketfuel-topology-reader.h +++ b/src/topology-read/model/rocketfuel-topology-reader.h @@ -80,11 +80,10 @@ private: * Parser for the *.cch file available at: * http://www.cs.washington.edu/research/networking/rocketfuel/maps/rocketfuel_maps_cch.tar.gz * - * \param [in] argc Argument counter. * \param [in] argv Argument vector. * \return The container of the nodes created (or empty container if there was an error). */ - NodeContainer GenerateFromMapsFile (int argc, char *argv[]); + NodeContainer GenerateFromMapsFile (const std::vector& argv); /** * \brief Topology read function from a file containing the nodes weights. @@ -92,11 +91,10 @@ private: * Parser for the weights.* file available at: * http://www.cs.washington.edu/research/networking/rocketfuel/maps/weights-dist.tar.gz * - * \param [in] argc Argument counter. * \param [in] argv Argument vector. * \return The container of the nodes created (or empty container if there was an error). */ - NodeContainer GenerateFromWeightsFile (int argc, char *argv[]); + NodeContainer GenerateFromWeightsFile (const std::vector& argv); /** * \brief Enum of the possible file types. @@ -115,7 +113,7 @@ private: * \param buf the first line of the file being read * \return The file type (RF_MAPS, RF_WEIGHTS, or RF_UNKNOWN) */ - enum RF_FileType GetFileType (const char *buf); + enum RF_FileType GetFileType (const std::string& buf); int m_linksNumber; //!< Number of links. int m_nodesNumber; //!< Number of nodes.