diff --git a/src/config-store/model/raw-text-config.cc b/src/config-store/model/raw-text-config.cc index 6e243d8a8..ff1a0bc84 100644 --- a/src/config-store/model/raw-text-config.cc +++ b/src/config-store/model/raw-text-config.cc @@ -26,6 +26,10 @@ #include "ns3/log.h" #include "ns3/config.h" +#include +#include +#include + namespace ns3 { NS_LOG_COMPONENT_DEFINE ("RawTextConfig"); @@ -45,14 +49,14 @@ RawTextConfigSave::~RawTextConfigSave () delete m_os; m_os = 0; } -void +void RawTextConfigSave::SetFilename (std::string filename) { NS_LOG_FUNCTION (this << filename); m_os = new std::ofstream (); m_os->open (filename.c_str (), std::ios::out); } -void +void RawTextConfigSave::Default (void) { NS_LOG_FUNCTION (this); @@ -77,7 +81,7 @@ private: RawTextDefaultIterator iterator = RawTextDefaultIterator (m_os); iterator.Iterate (); } -void +void RawTextConfigSave::Global (void) { NS_LOG_FUNCTION (this); @@ -89,7 +93,7 @@ RawTextConfigSave::Global (void) *m_os << "global " << (*i)->GetName () << " \"" << value.Get () << "\"" << std::endl; } } -void +void RawTextConfigSave::Attributes (void) { NS_LOG_FUNCTION (this); @@ -127,7 +131,7 @@ RawTextConfigLoad::~RawTextConfigLoad () m_is = 0; } } -void +void RawTextConfigLoad::SetFilename (std::string filename) { NS_LOG_FUNCTION (this << filename); @@ -138,69 +142,96 @@ std::string RawTextConfigLoad::Strip (std::string value) { std::string::size_type start = value.find ("\""); - std::string::size_type end = value.find ("\"", 1); - NS_ASSERT (start == 0); - NS_ASSERT (end == value.size () - 1); + NS_ASSERT_MSG (start != std::string::npos, "Ill-formed attribute value: " << value); + + std::string::size_type end = value.find ("\"", start + 1); + + NS_ASSERT_MSG (end != std::string::npos, "Ill-formed attribute value: " << value); return value.substr (start+1, end-start-1); } -void +void RawTextConfigLoad::Default (void) { NS_LOG_FUNCTION (this); m_is->clear (); m_is->seekg (0); std::string type, name, value; - *m_is >> type >> name >> value; - while (m_is->good ()) + for (std::string line; std::getline (*m_is, line);) { + if (!ParseLine (line, type, name, value)) continue; // comment + NS_LOG_DEBUG ("type=" << type << ", name=" << name << ", value=" << value); value = Strip (value); if (type == "default") - { - Config::SetDefault (name, StringValue (value)); - } - *m_is >> type >> name >> value; + Config::SetDefault (name, StringValue (value)); + name.clear (); + type.clear (); } } -void +void RawTextConfigLoad::Global (void) { NS_LOG_FUNCTION (this); m_is->clear (); m_is->seekg (0); std::string type, name, value; - *m_is >> type >> name >> value; - while (m_is->good ()) + for (std::string line; std::getline (*m_is, line);) { + if (!ParseLine (line, type, name, value)) continue; // comment + NS_LOG_DEBUG ("type=" << type << ", name=" << name << ", value=" << value); value = Strip (value); if (type == "global") - { - Config::SetGlobal (name, StringValue (value)); - } - *m_is >> type >> name >> value; + Config::SetGlobal (name, StringValue (value)); + name.clear (); + type.clear (); } } -void +void RawTextConfigLoad::Attributes (void) { NS_LOG_FUNCTION (this); m_is->clear (); m_is->seekg (0); - std::string type, path, value; - *m_is >> type >> path >> value; - while (m_is->good ()) + std::string type, name, value; + for (std::string line; std::getline (*m_is, line);) { - NS_LOG_DEBUG ("type=" << type << ", path=" << path << ", value=" << value); + if (!ParseLine (line, type, name, value)) continue; + + NS_LOG_DEBUG ("type=" << type << ", name=" << name << ", value=" << value); value = Strip (value); if (type == "value") - { - Config::Set (path, StringValue (value)); - } - *m_is >> type >> path >> value; + Config::Set (name, StringValue (value)); + name.clear (); + type.clear (); } } +bool +RawTextConfigLoad::ParseLine (const std::string &line, std::string &type, std::string &name, std::string &value) +{ + if (line.front () == '#') + return false; // comment line + if (line.empty () || line == std::string (line.size (), ' ')) + return false; // blank line + + // for multiline values, append line to value if type and name not empty + if (type.empty () || name.empty ()) + { + std::istringstream iss (line); + std::ostringstream rem; + iss >> type >> name >> rem.rdbuf (); + value = rem.str (); // remaining line, includes embedded spaces + } + else + { + value.append (line); + } + + // look for two quotes + return std::count (value.begin (), value.end (), '"') == 2; +} + } // namespace ns3 diff --git a/src/config-store/model/raw-text-config.h b/src/config-store/model/raw-text-config.h index 35e4f33f6..e005531a7 100644 --- a/src/config-store/model/raw-text-config.h +++ b/src/config-store/model/raw-text-config.h @@ -61,6 +61,8 @@ public: virtual void Global (void); virtual void Attributes (void); private: + virtual bool ParseLine (const std::string &line, std::string &type, std::string &name, std::string &value); + /** * Strip out attribute value * \param value the input string