topology-read: replace regex.h implementation with C++ regex

This commit is contained in:
Gabriel Ferreira
2022-05-25 11:41:52 -03:00
parent 5ad9678074
commit 6f8832bf12
4 changed files with 76 additions and 120 deletions

View File

@@ -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
)

View File

@@ -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}
)

View File

@@ -21,8 +21,8 @@
#include <fstream>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <regex.h>
#include <string>
#include <regex>
#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] -> <nuid-1> <nuid-2> ... {-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<std::string> &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<std::string>{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<Node> tmpNode = CreateObject<Node> ();
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<Node> tmpNode = CreateObject<Node> ();
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<std::string>& argv)
{
/* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-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<Node> tmpNode = CreateObject<Node> ();
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<Node> tmpNode = CreateObject<Node> ();
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 (&regex, 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, &regex, errbuf, sizeof (errbuf));
return RF_UNKNOWN;
}
ret = regexec (&regex, line, REGMATCH_MAX, regmatch, 0);
if (ret != REG_NOMATCH)
{
regfree (&regex);
return RF_MAPS;
}
regfree (&regex);
// Check whether Weights file or not
ret = regcomp (&regex, ROCKETFUEL_WEIGHTS_LINE, REG_EXTENDED | REG_NEWLINE);
if (ret != 0)
ret = std::regex_match (line, matches, rocketfuel_weights_regex);
if (ret)
{
regerror (ret, &regex, errbuf, sizeof (errbuf));
return RF_UNKNOWN;
}
ret = regexec (&regex, line, REGMATCH_MAX, regmatch, 0);
if (ret != REG_NOMATCH)
{
regfree (&regex);
return RF_WEIGHTS;
}
regfree (&regex);
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<std::string> 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 (&regex, 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, &regex, errbuf, sizeof (errbuf));
regfree (&regex);
break;
}
ret = regexec (&regex, buf, REGMATCH_MAX, regmatch, 0);
if (ret == REG_NOMATCH)
{
NS_LOG_WARN ("match failed (maps file): %s" << buf);
regfree (&regex);
NS_LOG_WARN ("match failed (maps file): %s" << line);
break;
}
}
else if (ftype == RF_WEIGHTS)
{
ret = regcomp (&regex, 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, &regex, errbuf, sizeof (errbuf));
regfree (&regex);
break;
}
ret = regexec (&regex, buf, REGMATCH_MAX, regmatch, 0);
if (ret == REG_NOMATCH)
{
NS_LOG_WARN ("match failed (weights file): %s" << buf);
regfree (&regex);
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 (&regex);
}

View File

@@ -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<std::string>& 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<std::string>& 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.