A Discrete-Event Network Simulator
API
xml-config.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009 INRIA
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Mathieu Lacage <mathieu.lacage@cutebugs.net>
18  */
19 
20 #include "xml-config.h"
21 
23 #include "attribute-iterator.h"
24 
25 #include "ns3/config.h"
26 #include "ns3/fatal-error.h"
27 #include "ns3/global-value.h"
28 #include "ns3/log.h"
29 #include "ns3/string.h"
30 
31 #include <libxml/encoding.h>
32 #include <libxml/xmlreader.h>
33 #include <libxml/xmlwriter.h>
34 
35 namespace ns3
36 {
37 
38 NS_LOG_COMPONENT_DEFINE("XmlConfig");
39 
41  : m_writer(nullptr)
42 {
43  NS_LOG_FUNCTION(this);
44 }
45 
46 void
47 XmlConfigSave::SetFilename(std::string filename)
48 {
49  NS_LOG_FUNCTION(filename);
50  if (filename.empty())
51  {
52  return;
53  }
54  int rc;
55 
56  /* Create a new XmlWriter for uri, with no compression. */
57  m_writer = xmlNewTextWriterFilename(filename.c_str(), 0);
58  if (m_writer == nullptr)
59  {
60  NS_FATAL_ERROR("Error creating the XML writer");
61  }
62  rc = xmlTextWriterSetIndent(m_writer, 1);
63  if (rc < 0)
64  {
65  NS_FATAL_ERROR("Error at xmlTextWriterSetIndent");
66  }
67  /* Start the document with the XML default for the version,
68  * encoding utf-8 and the default for the standalone
69  * declaration. */
70  rc = xmlTextWriterStartDocument(m_writer, nullptr, "utf-8", nullptr);
71  if (rc < 0)
72  {
73  NS_FATAL_ERROR("Error at xmlTextWriterStartDocument");
74  }
75 
76  /* Start an element named "ns3". Since this is the first
77  * element, this will be the root element of the document. */
78  rc = xmlTextWriterStartElement(m_writer, BAD_CAST "ns3");
79  if (rc < 0)
80  {
81  NS_FATAL_ERROR("Error at xmlTextWriterStartElement\n");
82  }
83 }
84 
86 {
87  NS_LOG_FUNCTION(this);
88  if (m_writer == nullptr)
89  {
90  return;
91  }
92  int rc;
93  /* Here we could close the remaining elements using the
94  * function xmlTextWriterEndElement, but since we do not want to
95  * write any other elements, we simply call xmlTextWriterEndDocument,
96  * which will do all the work. */
97  rc = xmlTextWriterEndDocument(m_writer);
98  if (rc < 0)
99  {
100  NS_FATAL_ERROR("Error at xmlTextWriterEndDocument\n");
101  }
102 
103  xmlFreeTextWriter(m_writer);
104  m_writer = nullptr;
105 }
106 
107 void
109 {
110  class XmlDefaultIterator : public AttributeDefaultIterator
111  {
112  public:
113  XmlDefaultIterator(xmlTextWriterPtr writer)
114  {
115  m_writer = writer;
116  }
117 
118  void SetSaveDeprecated(bool saveDeprecated)
119  {
120  m_saveDeprecated = saveDeprecated;
121  }
122 
123  private:
124  void StartVisitTypeId(std::string name) override
125  {
126  m_typeid = name;
127  }
128 
129  void DoVisitAttribute(std::string name, std::string defaultValue) override
130  {
131  TypeId tid = TypeId::LookupByName(m_typeid);
132  ns3::TypeId::SupportLevel supportLevel = TypeId::SupportLevel::SUPPORTED;
133  for (std::size_t i = 0; i < tid.GetAttributeN(); i++)
134  {
136  if (tmp.name == name)
137  {
138  supportLevel = tmp.supportLevel;
139  break;
140  }
141  }
142  if (supportLevel == TypeId::SupportLevel::OBSOLETE)
143  {
144  NS_LOG_WARN("Global attribute " << m_typeid << "::" << name
145  << " was not saved because it is OBSOLETE");
146  return;
147  }
148  else if (supportLevel == TypeId::SupportLevel::DEPRECATED && !m_saveDeprecated)
149  {
150  NS_LOG_WARN("Global attribute " << m_typeid << "::" << name
151  << " was not saved because it is DEPRECATED");
152  return;
153  }
154 
155  int rc;
156  rc = xmlTextWriterStartElement(m_writer, BAD_CAST "default");
157  if (rc < 0)
158  {
159  NS_FATAL_ERROR("Error at xmlTextWriterStartElement");
160  }
161  std::string fullname = m_typeid + "::" + name;
162  rc = xmlTextWriterWriteAttribute(m_writer, BAD_CAST "name", BAD_CAST fullname.c_str());
163  if (rc < 0)
164  {
165  NS_FATAL_ERROR("Error at xmlTextWriterWriteAttribute");
166  }
167  rc = xmlTextWriterWriteAttribute(m_writer,
168  BAD_CAST "value",
169  BAD_CAST defaultValue.c_str());
170  if (rc < 0)
171  {
172  NS_FATAL_ERROR("Error at xmlTextWriterWriteAttribute");
173  }
174  rc = xmlTextWriterEndElement(m_writer);
175  if (rc < 0)
176  {
177  NS_FATAL_ERROR("Error at xmlTextWriterEndElement");
178  }
179  }
180 
182  std::string m_typeid;
183  bool m_saveDeprecated;
184  };
185 
186  XmlDefaultIterator iterator = XmlDefaultIterator(m_writer);
187  iterator.SetSaveDeprecated(m_saveDeprecated);
188  iterator.Iterate();
189 }
190 
191 void
193 {
194  class XmlTextAttributeIterator : public AttributeIterator
195  {
196  public:
197  XmlTextAttributeIterator(xmlTextWriterPtr writer)
198  : m_writer(writer)
199  {
200  }
201 
202  void SetSaveDeprecated(bool saveDeprecated)
203  {
204  m_saveDeprecated = saveDeprecated;
205  }
206 
207  private:
208  void DoVisitAttribute(Ptr<Object> object, std::string name) override
209  {
210  TypeId tid = object->GetInstanceTypeId();
211  ns3::TypeId::SupportLevel supportLevel = TypeId::SupportLevel::SUPPORTED;
212  for (std::size_t i = 0; i < tid.GetAttributeN(); i++)
213  {
215  if (tmp.name == name)
216  {
217  supportLevel = tmp.supportLevel;
218  break;
219  }
220  }
221  if (supportLevel == TypeId::SupportLevel::OBSOLETE)
222  {
223  NS_LOG_WARN("Attribute " << GetCurrentPath()
224  << " was not saved because it is OBSOLETE");
225  return;
226  }
227  else if (supportLevel == TypeId::SupportLevel::DEPRECATED && !m_saveDeprecated)
228  {
229  NS_LOG_WARN("Attribute " << GetCurrentPath()
230  << " was not saved because it is DEPRECATED");
231  return;
232  }
233  StringValue str;
234  object->GetAttribute(name, str);
235  int rc;
236  rc = xmlTextWriterStartElement(m_writer, BAD_CAST "value");
237  if (rc < 0)
238  {
239  NS_FATAL_ERROR("Error at xmlTextWriterStartElement");
240  }
241  rc = xmlTextWriterWriteAttribute(m_writer,
242  BAD_CAST "path",
243  BAD_CAST GetCurrentPath().c_str());
244  if (rc < 0)
245  {
246  NS_FATAL_ERROR("Error at xmlTextWriterWriteAttribute");
247  }
248  rc =
249  xmlTextWriterWriteAttribute(m_writer, BAD_CAST "value", BAD_CAST str.Get().c_str());
250  if (rc < 0)
251  {
252  NS_FATAL_ERROR("Error at xmlTextWriterWriteAttribute");
253  }
254  rc = xmlTextWriterEndElement(m_writer);
255  if (rc < 0)
256  {
257  NS_FATAL_ERROR("Error at xmlTextWriterEndElement");
258  }
259  }
260 
262  bool m_saveDeprecated;
263  };
264 
265  XmlTextAttributeIterator iter = XmlTextAttributeIterator(m_writer);
266  iter.SetSaveDeprecated(m_saveDeprecated);
267  iter.Iterate();
268 }
269 
270 void
272 {
273  int rc;
274  for (auto i = GlobalValue::Begin(); i != GlobalValue::End(); ++i)
275  {
276  StringValue value;
277  (*i)->GetValue(value);
278 
279  rc = xmlTextWriterStartElement(m_writer, BAD_CAST "global");
280  if (rc < 0)
281  {
282  NS_FATAL_ERROR("Error at xmlTextWriterStartElement");
283  }
284  rc =
285  xmlTextWriterWriteAttribute(m_writer, BAD_CAST "name", BAD_CAST(*i)->GetName().c_str());
286  if (rc < 0)
287  {
288  NS_FATAL_ERROR("Error at xmlTextWriterWriteAttribute");
289  }
290  rc = xmlTextWriterWriteAttribute(m_writer, BAD_CAST "value", BAD_CAST value.Get().c_str());
291  if (rc < 0)
292  {
293  NS_FATAL_ERROR("Error at xmlTextWriterWriteAttribute");
294  }
295  rc = xmlTextWriterEndElement(m_writer);
296  if (rc < 0)
297  {
298  NS_FATAL_ERROR("Error at xmlTextWriterEndElement");
299  }
300  }
301 }
302 
304 {
305  NS_LOG_FUNCTION(this);
306 }
307 
309 {
310  NS_LOG_FUNCTION(this);
311 }
312 
313 void
314 XmlConfigLoad::SetFilename(std::string filename)
315 {
316  NS_LOG_FUNCTION(filename);
317  m_filename = filename;
318 }
319 
320 void
322 {
323  xmlTextReaderPtr reader = xmlNewTextReaderFilename(m_filename.c_str());
324  if (reader == nullptr)
325  {
326  NS_FATAL_ERROR("Error at xmlReaderForFile");
327  }
328  int rc;
329  rc = xmlTextReaderRead(reader);
330  while (rc > 0)
331  {
332  const xmlChar* type = xmlTextReaderConstName(reader);
333  if (type == nullptr)
334  {
335  NS_FATAL_ERROR("Invalid value");
336  }
337  if (std::string((char*)type) == "default")
338  {
339  xmlChar* name = xmlTextReaderGetAttribute(reader, BAD_CAST "name");
340  if (name == nullptr)
341  {
342  NS_FATAL_ERROR("Error getting attribute 'name'");
343  }
344  xmlChar* value = xmlTextReaderGetAttribute(reader, BAD_CAST "value");
345  if (value == nullptr)
346  {
347  NS_FATAL_ERROR("Error getting attribute 'value'");
348  }
349  NS_LOG_DEBUG("default=" << (char*)name << ", value=" << value);
350  Config::SetDefault((char*)name, StringValue((char*)value));
351  xmlFree(name);
352  xmlFree(value);
353  }
354  rc = xmlTextReaderRead(reader);
355  }
356  xmlFreeTextReader(reader);
357 }
358 
359 void
361 {
362  xmlTextReaderPtr reader = xmlNewTextReaderFilename(m_filename.c_str());
363  if (reader == nullptr)
364  {
365  NS_FATAL_ERROR("Error at xmlReaderForFile");
366  }
367  int rc;
368  rc = xmlTextReaderRead(reader);
369  while (rc > 0)
370  {
371  const xmlChar* type = xmlTextReaderConstName(reader);
372  if (type == nullptr)
373  {
374  NS_FATAL_ERROR("Invalid value");
375  }
376  if (std::string((char*)type) == "global")
377  {
378  xmlChar* name = xmlTextReaderGetAttribute(reader, BAD_CAST "name");
379  if (name == nullptr)
380  {
381  NS_FATAL_ERROR("Error getting attribute 'name'");
382  }
383  xmlChar* value = xmlTextReaderGetAttribute(reader, BAD_CAST "value");
384  if (value == nullptr)
385  {
386  NS_FATAL_ERROR("Error getting attribute 'value'");
387  }
388  NS_LOG_DEBUG("global=" << (char*)name << ", value=" << value);
389  Config::SetGlobal((char*)name, StringValue((char*)value));
390  xmlFree(name);
391  xmlFree(value);
392  }
393  rc = xmlTextReaderRead(reader);
394  }
395  xmlFreeTextReader(reader);
396 }
397 
398 void
400 {
401  xmlTextReaderPtr reader = xmlNewTextReaderFilename(m_filename.c_str());
402  if (reader == nullptr)
403  {
404  NS_FATAL_ERROR("Error at xmlReaderForFile");
405  }
406  int rc;
407  rc = xmlTextReaderRead(reader);
408  while (rc > 0)
409  {
410  const xmlChar* type = xmlTextReaderConstName(reader);
411  if (type == nullptr)
412  {
413  NS_FATAL_ERROR("Invalid value");
414  }
415  if (std::string((char*)type) == "value")
416  {
417  xmlChar* path = xmlTextReaderGetAttribute(reader, BAD_CAST "path");
418  if (path == nullptr)
419  {
420  NS_FATAL_ERROR("Error getting attribute 'path'");
421  }
422  xmlChar* value = xmlTextReaderGetAttribute(reader, BAD_CAST "value");
423  if (value == nullptr)
424  {
425  NS_FATAL_ERROR("Error getting attribute 'value'");
426  }
427  NS_LOG_DEBUG("path=" << (char*)path << ", value=" << (char*)value);
428  Config::Set((char*)path, StringValue((char*)value));
429  xmlFree(path);
430  xmlFree(value);
431  }
432  rc = xmlTextReaderRead(reader);
433  }
434  xmlFreeTextReader(reader);
435 }
436 
437 } // namespace ns3
Iterator to iterate on the default values of attributes of an ns3::Object.
Iterator to iterate on the values of attributes of an ns3::Object.
void SetSaveDeprecated(bool saveDeprecated)
Set if to save deprecated attributes.
Definition: file-config.cc:30
bool m_saveDeprecated
save deprecated attributes
Definition: file-config.h:61
static Iterator Begin()
The Begin iterator.
static Iterator End()
The End iterator.
Hold variables of type string.
Definition: string.h:56
std::string Get() const
Definition: string.cc:31
a unique identifier for an interface.
Definition: type-id.h:59
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:835
std::size_t GetAttributeN() const
Get the number of attributes.
Definition: type-id.cc:1100
TypeId::AttributeInformation GetAttribute(std::size_t i) const
Get Attribute information by index.
Definition: type-id.cc:1108
SupportLevel
The level of support or deprecation for attributes or trace sources.
Definition: type-id.h:73
void Global() override
Load or save the global values.
Definition: xml-config.cc:360
void SetFilename(std::string filename) override
Set the file name.
Definition: xml-config.cc:314
void Default() override
Load or save the default values.
Definition: xml-config.cc:321
std::string m_filename
the file name
Definition: xml-config.h:71
void Attributes() override
Load or save the attributes values.
Definition: xml-config.cc:399
~XmlConfigLoad() override
Definition: xml-config.cc:308
void Global() override
Load or save the global values.
Definition: xml-config.cc:271
void Attributes() override
Load or save the attributes values.
Definition: xml-config.cc:192
~XmlConfigSave() override
Definition: xml-config.cc:85
xmlTextWriterPtr m_writer
XML writer.
Definition: xml-config.h:52
void SetFilename(std::string filename) override
Set the file name.
Definition: xml-config.cc:47
void Default() override
Load or save the default values.
Definition: xml-config.cc:108
void SetGlobal(std::string name, const AttributeValue &value)
Definition: config.cc:936
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:890
void Set(std::string path, const AttributeValue &value)
Definition: config.cc:876
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Attribute implementation.
Definition: type-id.h:81
TypeId::SupportLevel supportLevel
Support level/deprecation.
Definition: type-id.h:97
std::string name
Attribute name.
Definition: type-id.h:83
xmlTextWriter * xmlTextWriterPtr
Definition: xml-config.h:30