Refactor config file parsing and improve error handling

Change-Id: I8a54ba1f0d414bea70923e0f45ca354ac7e957a3
This commit is contained in:
Davide Pesavento committed 2019-01-26 16:22:38 -05:00
1 parent 032c98004f
commit 306e5bc606
5 files changed
+196 -277

No files matched your search

+12 -13
View File
@@ -2,20 +2,19 @@
# THIS IS A SAMPLE CLIENT INTEREST TRAFFIC CONFIGURATION FILE # THIS IS A SAMPLE CLIENT INTEREST TRAFFIC CONFIGURATION FILE
# #
# * TO BE USED TO GENERATE INTEREST MESSAGES BASED ON A PROBABILITY # * TO BE USED TO GENERATE INTEREST MESSAGES BASED ON A PROBABILITY
# PATTERN. # PATTERN
# * EVERY INIVIDUAL PATTERN DESCRIPTION MUST BE SEPARATED BY ONE # * EVERY INDIVIDUAL PATTERN DESCRIPTION MUST BE SEPARATED BY ONE
# OR MORE '#' CHARACTERS FOR THE TOOL TO DISTINGUISH THEM # OR MORE '#' CHARACTERS FOR THE TOOL TO DISTINGUISH THEM
# INDIVIDUALLY
# * THE FOLLOWING PARAMETERS MAY BE ADDED FOR EVERY TRAFFIC PATTERN # * THE FOLLOWING PARAMETERS MAY BE ADDED FOR EVERY TRAFFIC PATTERN
# * (Mandatory) NEXT TO A PARAMETER MEANS EVERY PATTERN SHOULD HAVE # * 'Mandatory' ARE PARAMETERS THAT EVERY PATTERN MUST HAVE IN ORDER
# IT FOR BEING CONSIDERED VALID # TO BE CONSIDERED VALID
# (Optional) MEANS OTHERWISE # * 'Boolean' ACCEPTS EITHER 0/false/no/off OR 1/true/yes/on AS VALUE
# * ALSO PROVIDED ARE VALID VALUES POSSIBLE FOR EACH PARAMETER # * 'NNI' STANDS FOR NON-NEGATIVE INTEGER
# * PLEASE ENSURE THAT THE SUM OF TrafficPercentage FOR ALL DECLARED
# PATTERNS DOES NOT EXCEED 100 IN ORDER TO MAINTAIN CORRECT BEHAVIOR
# * NNI STANDS FOR NON-NEGATIVE INTEGER
# * RANGE OF POSSIBLE VALUES IS SPECIFIED IN [] # * RANGE OF POSSIBLE VALUES IS SPECIFIED IN []
# * PLEASE ENSURE THAT THE SUM OF 'TrafficPercentage' FOR ALL DECLARED
# PATTERNS DOES NOT EXCEED 100 IN ORDER TO MAINTAIN CORRECT BEHAVIOR
# #
# (Mandatory) # (Mandatory)
#TrafficPercentage=NNI [0-100] #TrafficPercentage=NNI [0-100]
#Name=NDN Name #Name=NDN Name
@@ -23,10 +22,10 @@
# (Optional) # (Optional)
#NameAppendBytes=NNI [>0] #NameAppendBytes=NNI [>0]
#NameAppendSequenceNumber=NNI [>=0] #NameAppendSequenceNumber=NNI [>=0]
#MustBeFresh=NNI [0-1] #MustBeFresh=Boolean
#NonceDuplicationPercentage=NNI [0-100] #NonceDuplicationPercentage=NNI [0-100]
#InterestLifetime=NNI [Milliseconds] #InterestLifetime=Milliseconds [>=0]
#NextHopFaceId=NNI #NextHopFaceId=NNI [>0]
#ExpectedContent=String #ExpectedContent=String
########## ##########
+8 -9
View File
@@ -3,26 +3,25 @@
# #
# * TO BE USED TO CONFIGURE RESPONSE TO INTERESTS # * TO BE USED TO CONFIGURE RESPONSE TO INTERESTS
# * MULTIPLE SERVER PREFIXES CAN BE CONFIGURED FOR BEING HANDLED # * MULTIPLE SERVER PREFIXES CAN BE CONFIGURED FOR BEING HANDLED
# * EVERY INIVIDUAL PATTERN DESCRIPTION MUST BE SEPARATED BY ONE # * EVERY INDIVIDUAL PATTERN DESCRIPTION MUST BE SEPARATED BY ONE
# OR MORE '#' CHARACTERS FOR THE TOOL TO DISTINGUISH THEM # OR MORE '#' CHARACTERS FOR THE TOOL TO DISTINGUISH THEM
# INDIVIDUALLY
# * THE FOLLOWING PARAMETERS MAY BE ADDED FOR EVERY TRAFFIC PATTERN # * THE FOLLOWING PARAMETERS MAY BE ADDED FOR EVERY TRAFFIC PATTERN
# * (Mandatory) NEXT TO A PARAMETER MEANS EVERY PATTERN SHOULD HAVE # * 'Mandatory' ARE PARAMETERS THAT EVERY PATTERN MUST HAVE IN ORDER
# IT FOR BEING CONSIDERED VALID # TO BE CONSIDERED VALID
# (Optional) MEANS OTHERWISE # * 'Boolean' ACCEPTS EITHER 0/false/no/off OR 1/true/yes/on AS VALUE
# * ALSO PROVIDED ARE VALID VALUES POSSIBLE FOR EACH PARAMETER # * 'NNI' STANDS FOR NON-NEGATIVE INTEGER
# * NNI STANDS FOR NON-NEGATIVE INTEGER
# * RANGE OF POSSIBLE VALUES IS SPECIFIED IN [] # * RANGE OF POSSIBLE VALUES IS SPECIFIED IN []
# #
# (Mandatory) # (Mandatory)
#Name=NDN Name #Name=NDN Name
# #
# (Optional) # (Optional)
#ContentDelay=Milliseconds [>=0]
#FreshnessPeriod=Milliseconds [>=0]
#ContentType=NNI [>=0] #ContentType=NNI [>=0]
#FreshnessPeriod=NNI [milliseconds]
#ContentBytes=NNI [>0] #ContentBytes=NNI [>0]
#Content=String #Content=String
#ContentDelay=NNI [milliseconds]
#SigningInfo=String [examples below] #SigningInfo=String [examples below]
########## ##########
+61 -130
View File
@@ -18,7 +18,6 @@
* Author: Jerald Paul Abraham <jeraldabraham@email.arizona.edu> * Author: Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
*/ */
#include "logger.hpp"
#include "util.hpp" #include "util.hpp"
#include <ndn-cxx/face.hpp> #include <ndn-cxx/face.hpp>
@@ -27,7 +26,6 @@
#include <ndn-cxx/util/backports.hpp> #include <ndn-cxx/util/backports.hpp>
#include <ndn-cxx/util/random.hpp> #include <ndn-cxx/util/random.hpp>
#include <cctype>
#include <limits> #include <limits>
#include <vector> #include <vector>
@@ -36,7 +34,6 @@
#include <boost/asio/signal_set.hpp> #include <boost/asio/signal_set.hpp>
#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/logic/tribool.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <boost/program_options/options_description.hpp> #include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp> #include <boost/program_options/parsers.hpp>
@@ -58,12 +55,6 @@ public:
{ {
} }
bool
hasError() const
{
return m_hasError;
}
void void
setMaximumInterests(uint64_t maxInterests) setMaximumInterests(uint64_t maxInterests)
{ {
@@ -83,15 +74,30 @@ public:
m_wantQuiet = true; m_wantQuiet = true;
} }
void int
run() run()
{ {
m_logger.initializeLog(to_string(random::generateWord32())); m_logger.initializeLog(to_string(random::generateWord32()));
initializeTrafficConfiguration();
if (!readConfigurationFile(m_configurationFile, m_trafficPatterns, m_logger)) {
return 2;
}
if (!checkTrafficPatternCorrectness()) {
m_logger.log("ERROR: Traffic configuration provided is not proper", false, true);
return 2;
}
m_logger.log("Traffic configuration file processing completed.\n", true, false);
for (std::size_t i = 0; i < m_trafficPatterns.size(); i++) {
m_logger.log("Traffic Pattern Type #" + to_string(i + 1), false, false);
m_trafficPatterns[i].printTrafficConfiguration(m_logger);
m_logger.log("", false, false);
}
if (m_nMaximumInterests == 0) { if (m_nMaximumInterests == 0) {
logStatistics(); logStatistics();
return; return 0;
} }
m_signalSet.async_wait([this] (auto&&...) { this->stop(); }); m_signalSet.async_wait([this] (auto&&...) { this->stop(); });
@@ -102,11 +108,12 @@ public:
try { try {
m_face.processEvents(); m_face.processEvents();
return m_hasError ? 1 : 0;
} }
catch (const std::exception& e) { catch (const std::exception& e) {
m_logger.log("ERROR: "s + e.what(), true, true); m_logger.log("ERROR: "s + e.what(), true, true);
m_hasError = true;
m_ioService.stop(); m_ioService.stop();
return 1;
} }
} }
@@ -120,14 +127,12 @@ private:
std::string detail; std::string detail;
detail += "TrafficPercentage=" + to_string(m_trafficPercentage) + ", "; detail += "TrafficPercentage=" + to_string(m_trafficPercentage) + ", ";
if (!m_name.empty()) detail += "Name=" + m_name + ", ";
detail += "Name=" + m_name + ", ";
if (m_nameAppendBytes) if (m_nameAppendBytes)
detail += "NameAppendBytes=" + to_string(*m_nameAppendBytes) + ", "; detail += "NameAppendBytes=" + to_string(*m_nameAppendBytes) + ", ";
if (m_nameAppendSeqNum) if (m_nameAppendSeqNum)
detail += "NameAppendSequenceNumber=" + to_string(*m_nameAppendSeqNum) + ", "; detail += "NameAppendSequenceNumber=" + to_string(*m_nameAppendSeqNum) + ", ";
if (!boost::logic::indeterminate(m_mustBeFresh)) detail += "MustBeFresh=" + to_string(m_mustBeFresh) + ", ";
detail += "MustBeFresh=" + to_string(bool(m_mustBeFresh)) + ", ";
if (m_nonceDuplicationPercentage > 0) if (m_nonceDuplicationPercentage > 0)
detail += "NonceDuplicationPercentage=" + to_string(m_nonceDuplicationPercentage) + ", "; detail += "NonceDuplicationPercentage=" + to_string(m_nonceDuplicationPercentage) + ", ";
if (m_interestLifetime >= 0_ms) if (m_interestLifetime >= 0_ms)
@@ -143,36 +148,45 @@ private:
} }
bool bool
processConfigurationDetail(const std::string& detail, Logger& logger, int lineNumber) parseConfigurationLine(const std::string& line, Logger& logger, int lineNumber)
{ {
std::string parameter, value; std::string parameter, value;
if (parseParameterAndValue(detail, parameter, value)) { if (!extractParameterAndValue(line, parameter, value)) {
if (parameter == "TrafficPercentage") logger.log("Line " + to_string(lineNumber) + " - Invalid syntax: " + line,
m_trafficPercentage = std::stoul(value); false, true);
else if (parameter == "Name") return false;
m_name = value; }
else if (parameter == "NameAppendBytes")
m_nameAppendBytes = std::stoul(value); if (parameter == "TrafficPercentage") {
else if (parameter == "NameAppendSequenceNumber") m_trafficPercentage = std::stoul(value);
m_nameAppendSeqNum = std::stoull(value); }
else if (parameter == "MustBeFresh") else if (parameter == "Name") {
m_mustBeFresh = bool(std::stoul(value)); m_name = value;
else if (parameter == "NonceDuplicationPercentage") }
m_nonceDuplicationPercentage = std::stoul(value); else if (parameter == "NameAppendBytes") {
else if (parameter == "InterestLifetime") m_nameAppendBytes = std::stoul(value);
m_interestLifetime = time::milliseconds(std::stoul(value)); }
else if (parameter == "NextHopFaceId") else if (parameter == "NameAppendSequenceNumber") {
m_nextHopFaceId = std::stoull(value); m_nameAppendSeqNum = std::stoull(value);
else if (parameter == "ExpectedContent") }
m_expectedContent = value; else if (parameter == "MustBeFresh") {
else m_mustBeFresh = parseBoolean(value);
logger.log("Line " + to_string(lineNumber) + }
" - Unknown parameter '" + parameter + "'", false, true); else if (parameter == "NonceDuplicationPercentage") {
m_nonceDuplicationPercentage = std::stoul(value);
}
else if (parameter == "InterestLifetime") {
m_interestLifetime = time::milliseconds(std::stoul(value));
}
else if (parameter == "NextHopFaceId") {
m_nextHopFaceId = std::stoull(value);
}
else if (parameter == "ExpectedContent") {
m_expectedContent = value;
} }
else { else {
logger.log("Line " + to_string(lineNumber) + logger.log("Line " + to_string(lineNumber) + " - Ignoring unknown parameter: " + parameter,
" - Invalid traffic configuration line: " + detail, false, true); false, true);
return false;
} }
return true; return true;
} }
@@ -188,7 +202,7 @@ private:
std::string m_name; std::string m_name;
optional<std::size_t> m_nameAppendBytes; optional<std::size_t> m_nameAppendBytes;
optional<uint64_t> m_nameAppendSeqNum; optional<uint64_t> m_nameAppendSeqNum;
boost::logic::tribool m_mustBeFresh = boost::logic::indeterminate; bool m_mustBeFresh = false;
uint8_t m_nonceDuplicationPercentage = 0; uint8_t m_nonceDuplicationPercentage = 0;
time::milliseconds m_interestLifetime = -1_ms; time::milliseconds m_interestLifetime = -1_ms;
uint64_t m_nextHopFaceId = 0; uint64_t m_nextHopFaceId = 0;
@@ -272,88 +286,10 @@ private:
bool bool
checkTrafficPatternCorrectness() const checkTrafficPatternCorrectness() const
{ {
// TODO
return true; return true;
} }
void
parseConfigurationFile()
{
std::ifstream patternFile;
m_logger.log("Parsing traffic configuration file: " + m_configurationFile, true, true);
patternFile.open(m_configurationFile.data());
if (patternFile.is_open()) {
int lineNumber = 0;
std::string patternLine;
while (getline(patternFile, patternLine)) {
lineNumber++;
if (std::isalpha(patternLine[0])) {
InterestTrafficConfiguration interestData;
bool shouldSkipLine = false;
if (interestData.processConfigurationDetail(patternLine, m_logger, lineNumber)) {
while (getline(patternFile, patternLine) && std::isalpha(patternLine[0])) {
lineNumber++;
if (!interestData.processConfigurationDetail(patternLine, m_logger, lineNumber)) {
shouldSkipLine = true;
break;
}
}
lineNumber++;
}
else {
shouldSkipLine = true;
}
if (!shouldSkipLine) {
if (interestData.checkTrafficDetailCorrectness()) {
m_trafficPatterns.push_back(interestData);
}
}
}
}
patternFile.close();
if (!checkTrafficPatternCorrectness()) {
m_logger.log("ERROR: Traffic configuration provided is not proper - " +
m_configurationFile, false, true);
exit(2);
}
m_logger.log("Traffic configuration file processing completed.\n", true, false);
for (std::size_t patternId = 0; patternId < m_trafficPatterns.size(); patternId++) {
m_logger.log("Traffic Pattern Type #" + to_string(patternId + 1), false, false);
m_trafficPatterns[patternId].printTrafficConfiguration(m_logger);
m_logger.log("", false, false);
}
}
else {
m_logger.log("ERROR: Unable to open traffic configuration file: " + m_configurationFile, false, true);
exit(2);
}
}
void
initializeTrafficConfiguration()
{
namespace fs = boost::filesystem;
fs::path configPath(m_configurationFile);
if (fs::exists(configPath)) {
if (fs::is_regular_file(configPath)) {
parseConfigurationFile();
}
else {
m_logger.log("ERROR: Traffic configuration file is not a regular file: " +
m_configurationFile, false, true);
exit(2);
}
}
else {
m_logger.log("ERROR: Traffic configuration file does not exist: " +
m_configurationFile, false, true);
exit(2);
}
}
uint32_t uint32_t
getNewNonce() getNewNonce()
{ {
@@ -409,10 +345,7 @@ private:
} }
interest.setName(name); interest.setName(name);
if (pattern.m_mustBeFresh) interest.setMustBeFresh(pattern.m_mustBeFresh);
interest.setMustBeFresh(true);
else if (!pattern.m_mustBeFresh)
interest.setMustBeFresh(false);
static std::uniform_int_distribution<> duplicateNonceDist(1, 100); static std::uniform_int_distribution<> duplicateNonceDist(1, 100);
if (duplicateNonceDist(random::getRandomNumberEngine()) <= pattern.m_nonceDuplicationPercentage) if (duplicateNonceDist(random::getRandomNumberEngine()) <= pattern.m_nonceDuplicationPercentage)
@@ -688,7 +621,5 @@ main(int argc, char* argv[])
client.setQuietLogging(); client.setQuietLogging();
} }
client.run(); return client.run();
return client.hasError() ? 1 : 0;
} }
+51 -124
View File
@@ -18,7 +18,6 @@
* Author: Jerald Paul Abraham <jeraldabraham@email.arizona.edu> * Author: Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
*/ */
#include "logger.hpp"
#include "util.hpp" #include "util.hpp"
#include <ndn-cxx/data.hpp> #include <ndn-cxx/data.hpp>
@@ -28,7 +27,6 @@
#include <ndn-cxx/util/backports.hpp> #include <ndn-cxx/util/backports.hpp>
#include <ndn-cxx/util/random.hpp> #include <ndn-cxx/util/random.hpp>
#include <cctype>
#include <limits> #include <limits>
#include <sstream> #include <sstream>
#include <vector> #include <vector>
@@ -57,12 +55,6 @@ public:
{ {
} }
bool
hasError() const
{
return m_hasError;
}
void void
setMaximumInterests(uint64_t maxInterests) setMaximumInterests(uint64_t maxInterests)
{ {
@@ -82,15 +74,30 @@ public:
m_wantQuiet = true; m_wantQuiet = true;
} }
void int
run() run()
{ {
m_logger.initializeLog(to_string(random::generateWord32())); m_logger.initializeLog(to_string(random::generateWord32()));
initializeTrafficConfiguration();
if (!readConfigurationFile(m_configurationFile, m_trafficPatterns, m_logger)) {
return 2;
}
if (!checkTrafficPatternCorrectness()) {
m_logger.log("ERROR: Traffic configuration provided is not proper", false, true);
return 2;
}
m_logger.log("Traffic configuration file processing completed.\n", true, false);
for (std::size_t i = 0; i < m_trafficPatterns.size(); i++) {
m_logger.log("Traffic Pattern Type #" + to_string(i + 1), false, false);
m_trafficPatterns[i].printTrafficConfiguration(m_logger);
m_logger.log("", false, false);
}
if (m_nMaximumInterests == 0) { if (m_nMaximumInterests == 0) {
logStatistics(); logStatistics();
return; return 0;
} }
m_signalSet.async_wait([this] (const boost::system::error_code&, int) { m_signalSet.async_wait([this] (const boost::system::error_code&, int) {
@@ -110,11 +117,12 @@ public:
try { try {
m_face.processEvents(); m_face.processEvents();
return m_hasError ? 1 : 0;
} }
catch (const std::exception& e) { catch (const std::exception& e) {
m_logger.log("ERROR: "s + e.what(), true, true); m_logger.log("ERROR: "s + e.what(), true, true);
m_hasError = true;
m_ioService.stop(); m_ioService.stop();
return 1;
} }
} }
@@ -151,40 +159,39 @@ private:
} }
bool bool
processConfigurationDetail(const std::string& detail, Logger& logger, int lineNumber) parseConfigurationLine(const std::string& line, Logger& logger, int lineNumber)
{ {
std::string parameter, value; std::string parameter, value;
if (parseParameterAndValue(detail, parameter, value)) { if (!extractParameterAndValue(line, parameter, value)) {
if (parameter == "Name") { logger.log("Line " + to_string(lineNumber) + " - Invalid syntax: " + line,
m_name = value; false, true);
} return false;
else if (parameter == "ContentDelay") { }
m_contentDelay = time::milliseconds(std::stoul(value));
} if (parameter == "Name") {
else if (parameter == "FreshnessPeriod") { m_name = value;
m_freshnessPeriod = time::milliseconds(std::stoul(value)); }
} else if (parameter == "ContentDelay") {
else if (parameter == "ContentType") { m_contentDelay = time::milliseconds(std::stoul(value));
m_contentType = std::stoul(value); }
} else if (parameter == "FreshnessPeriod") {
else if (parameter == "ContentBytes") { m_freshnessPeriod = time::milliseconds(std::stoul(value));
m_contentLength = std::stoul(value); }
} else if (parameter == "ContentType") {
else if (parameter == "Content") { m_contentType = std::stoul(value);
m_content = value; }
} else if (parameter == "ContentBytes") {
else if (parameter == "SigningInfo") { m_contentLength = std::stoul(value);
m_signingInfo = security::SigningInfo(value); }
} else if (parameter == "Content") {
else { m_content = value;
logger.log("Line " + to_string(lineNumber) + }
" - Unknown parameter '" + parameter + "'", false, true); else if (parameter == "SigningInfo") {
} m_signingInfo = security::SigningInfo(value);
} }
else { else {
logger.log("Line " + to_string(lineNumber) + logger.log("Line " + to_string(lineNumber) + " - Ignoring unknown parameter: " + parameter,
" - Invalid traffic configuration line: " + detail, false, true); false, true);
return false;
} }
return true; return true;
} }
@@ -226,88 +233,10 @@ private:
bool bool
checkTrafficPatternCorrectness() const checkTrafficPatternCorrectness() const
{ {
// TODO
return true; return true;
} }
void
parseConfigurationFile()
{
std::ifstream patternFile;
m_logger.log("Parsing traffic configuration file: " + m_configurationFile, true, true);
patternFile.open(m_configurationFile.data());
if (patternFile.is_open()) {
int lineNumber = 0;
std::string patternLine;
while (getline(patternFile, patternLine)) {
lineNumber++;
if (std::isalpha(patternLine[0])) {
DataTrafficConfiguration dataData;
bool shouldSkipLine = false;
if (dataData.processConfigurationDetail(patternLine, m_logger, lineNumber)) {
while (getline(patternFile, patternLine) && std::isalpha(patternLine[0])) {
lineNumber++;
if (!dataData.processConfigurationDetail(patternLine, m_logger, lineNumber)) {
shouldSkipLine = true;
break;
}
}
lineNumber++;
}
else {
shouldSkipLine = true;
}
if (!shouldSkipLine) {
if (dataData.checkTrafficDetailCorrectness()) {
m_trafficPatterns.push_back(dataData);
}
}
}
}
patternFile.close();
if (!checkTrafficPatternCorrectness()) {
m_logger.log("ERROR: Traffic configuration provided is not proper - " +
m_configurationFile, false, true);
exit(2);
}
m_logger.log("Traffic configuration file processing completed.\n", true, false);
for (std::size_t patternId = 0; patternId < m_trafficPatterns.size(); patternId++) {
m_logger.log("Traffic Pattern Type #" + to_string(patternId + 1), false, false);
m_trafficPatterns[patternId].printTrafficConfiguration(m_logger);
m_logger.log("", false, false);
}
}
else {
m_logger.log("ERROR: Unable to open traffic configuration file: " + m_configurationFile, false, true);
exit(2);
}
}
void
initializeTrafficConfiguration()
{
namespace fs = boost::filesystem;
fs::path configPath(m_configurationFile);
if (fs::exists(configPath)) {
if (fs::is_regular_file(configPath)) {
parseConfigurationFile();
}
else {
m_logger.log("ERROR: Traffic configuration file is not a regular file: " +
m_configurationFile, false, true);
exit(2);
}
}
else {
m_logger.log("ERROR: Traffic configuration file does not exist: " +
m_configurationFile, false, true);
exit(2);
}
}
static std::string static std::string
getRandomByteString(std::size_t length) getRandomByteString(std::size_t length)
{ {
@@ -501,7 +430,5 @@ main(int argc, char* argv[])
server.setQuietLogging(); server.setQuietLogging();
} }
server.run(); return server.run();
return server.hasError() ? 1 : 0;
} }
+64 -1
View File
@@ -21,13 +21,17 @@
#ifndef NTG_UTIL_HPP #ifndef NTG_UTIL_HPP
#define NTG_UTIL_HPP #define NTG_UTIL_HPP
#include "logger.hpp"
#include <cctype> #include <cctype>
#include <string> #include <string>
#include <boost/algorithm/string/predicate.hpp>
namespace ndn { namespace ndn {
static inline bool static inline bool
parseParameterAndValue(const std::string& input, std::string& parameter, std::string& value) extractParameterAndValue(const std::string& input, std::string& parameter, std::string& value)
{ {
static const std::string allowedCharacters = ":/+._-%"; static const std::string allowedCharacters = ":/+._-%";
parameter = ""; parameter = "";
@@ -56,6 +60,65 @@ parseParameterAndValue(const std::string& input, std::string& parameter, std::st
return !parameter.empty() && !value.empty() && i == input.length(); return !parameter.empty() && !value.empty() && i == input.length();
} }
static inline bool
parseBoolean(const std::string& input)
{
if (boost::iequals(input, "no") || boost::iequals(input, "off") ||
boost::iequals(input, "false") || input == "0")
return false;
if (boost::iequals(input, "yes") || boost::iequals(input, "on") ||
boost::iequals(input, "true") || input == "1")
return true;
throw std::invalid_argument("'" + input + "' is not a valid boolean value");
}
template<typename TrafficConfigurationType>
static inline bool
readConfigurationFile(const std::string& filename,
std::vector<TrafficConfigurationType>& patterns,
Logger& logger)
{
std::ifstream patternFile(filename);
if (!patternFile) {
logger.log("ERROR: Unable to open traffic configuration file: " + filename, false, true);
return false;
}
logger.log("Reading traffic configuration file: " + filename, true, true);
int lineNumber = 0;
std::string patternLine;
while (getline(patternFile, patternLine)) {
lineNumber++;
if (std::isalpha(patternLine[0])) {
TrafficConfigurationType trafficConf;
bool shouldSkipLine = false;
if (trafficConf.parseConfigurationLine(patternLine, logger, lineNumber)) {
while (getline(patternFile, patternLine) && std::isalpha(patternLine[0])) {
lineNumber++;
if (!trafficConf.parseConfigurationLine(patternLine, logger, lineNumber)) {
shouldSkipLine = true;
break;
}
}
lineNumber++;
}
else {
shouldSkipLine = true;
}
if (!shouldSkipLine) {
if (trafficConf.checkTrafficDetailCorrectness()) {
patterns.push_back(std::move(trafficConf));
}
}
}
}
return true;
}
} // namespace ndn } // namespace ndn
#endif // NTG_UTIL_HPP #endif // NTG_UTIL_HPP