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  {
135  struct TypeId::AttributeInformation tmp = tid.GetAttribute(i);
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) &&
149  (m_saveDeprecated == false))
150  {
151  NS_LOG_WARN("Global attribute " << m_typeid << "::" << name
152  << " was not saved because it is DEPRECATED");
153  return;
154  }
155 
156  int rc;
157  rc = xmlTextWriterStartElement(m_writer, BAD_CAST "default");
158  if (rc < 0)
159  {
160  NS_FATAL_ERROR("Error at xmlTextWriterStartElement");
161  }
162  std::string fullname = m_typeid + "::" + name;
163  rc = xmlTextWriterWriteAttribute(m_writer, BAD_CAST "name", BAD_CAST fullname.c_str());
164  if (rc < 0)
165  {
166  NS_FATAL_ERROR("Error at xmlTextWriterWriteAttribute");
167  }
168  rc = xmlTextWriterWriteAttribute(m_writer,
169  BAD_CAST "value",
170  BAD_CAST defaultValue.c_str());
171  if (rc < 0)
172  {
173  NS_FATAL_ERROR("Error at xmlTextWriterWriteAttribute");
174  }
175  rc = xmlTextWriterEndElement(m_writer);
176  if (rc < 0)
177  {
178  NS_FATAL_ERROR("Error at xmlTextWriterEndElement");
179  }
180  }
181 
183  std::string m_typeid;
184  bool m_saveDeprecated;
185  };
186 
187  XmlDefaultIterator iterator = XmlDefaultIterator(m_writer);
188  iterator.SetSaveDeprecated(m_saveDeprecated);
189  iterator.Iterate();
190 }
191 
192 void
194 {
195  class XmlTextAttributeIterator : public AttributeIterator
196  {
197  public:
198  XmlTextAttributeIterator(xmlTextWriterPtr writer)
199  : m_writer(writer)
200  {
201  }
202 
203  void SetSaveDeprecated(bool saveDeprecated)
204  {
205  m_saveDeprecated = saveDeprecated;
206  }
207 
208  private:
209  void DoVisitAttribute(Ptr<Object> object, std::string name) override
210  {
211  TypeId tid = object->GetInstanceTypeId();
212  ns3::TypeId::SupportLevel supportLevel = TypeId::SupportLevel::SUPPORTED;
213  for (std::size_t i = 0; i < tid.GetAttributeN(); i++)
214  {
215  struct TypeId::AttributeInformation tmp = tid.GetAttribute(i);
216  if (tmp.name == name)
217  {
218  supportLevel = tmp.supportLevel;
219  break;
220  }
221  }
222  if (supportLevel == TypeId::SupportLevel::OBSOLETE)
223  {
224  NS_LOG_WARN("Attribute " << GetCurrentPath()
225  << " was not saved because it is OBSOLETE");
226  return;
227  }
228  else if ((supportLevel == TypeId::SupportLevel::DEPRECATED) &&
229  (m_saveDeprecated == false))
230  {
231  NS_LOG_WARN("Attribute " << GetCurrentPath()
232  << " was not saved because it is DEPRECATED");
233  return;
234  }
235  StringValue str;
236  object->GetAttribute(name, str);
237  int rc;
238  rc = xmlTextWriterStartElement(m_writer, BAD_CAST "value");
239  if (rc < 0)
240  {
241  NS_FATAL_ERROR("Error at xmlTextWriterStartElement");
242  }
243  rc = xmlTextWriterWriteAttribute(m_writer,
244  BAD_CAST "path",
245  BAD_CAST GetCurrentPath().c_str());
246  if (rc < 0)
247  {
248  NS_FATAL_ERROR("Error at xmlTextWriterWriteAttribute");
249  }
250  rc =
251  xmlTextWriterWriteAttribute(m_writer, BAD_CAST "value", BAD_CAST str.Get().c_str());
252  if (rc < 0)
253  {
254  NS_FATAL_ERROR("Error at xmlTextWriterWriteAttribute");
255  }
256  rc = xmlTextWriterEndElement(m_writer);
257  if (rc < 0)
258  {
259  NS_FATAL_ERROR("Error at xmlTextWriterEndElement");
260  }
261  }
262 
264  bool m_saveDeprecated;
265  };
266 
267  XmlTextAttributeIterator iter = XmlTextAttributeIterator(m_writer);
268  iter.SetSaveDeprecated(m_saveDeprecated);
269  iter.Iterate();
270 }
271 
272 void
274 {
275  int rc;
277  {
279  (*i)->GetValue(value);
280 
281  rc = xmlTextWriterStartElement(m_writer, BAD_CAST "global");
282  if (rc < 0)
283  {
284  NS_FATAL_ERROR("Error at xmlTextWriterStartElement");
285  }
286  rc =
287  xmlTextWriterWriteAttribute(m_writer, BAD_CAST "name", BAD_CAST(*i)->GetName().c_str());
288  if (rc < 0)
289  {
290  NS_FATAL_ERROR("Error at xmlTextWriterWriteAttribute");
291  }
292  rc = xmlTextWriterWriteAttribute(m_writer, BAD_CAST "value", BAD_CAST value.Get().c_str());
293  if (rc < 0)
294  {
295  NS_FATAL_ERROR("Error at xmlTextWriterWriteAttribute");
296  }
297  rc = xmlTextWriterEndElement(m_writer);
298  if (rc < 0)
299  {
300  NS_FATAL_ERROR("Error at xmlTextWriterEndElement");
301  }
302  }
303 }
304 
306 {
307  NS_LOG_FUNCTION(this);
308 }
309 
311 {
312  NS_LOG_FUNCTION(this);
313 }
314 
315 void
316 XmlConfigLoad::SetFilename(std::string filename)
317 {
318  NS_LOG_FUNCTION(filename);
319  m_filename = filename;
320 }
321 
322 void
324 {
325  xmlTextReaderPtr reader = xmlNewTextReaderFilename(m_filename.c_str());
326  if (reader == nullptr)
327  {
328  NS_FATAL_ERROR("Error at xmlReaderForFile");
329  }
330  int rc;
331  rc = xmlTextReaderRead(reader);
332  while (rc > 0)
333  {
334  const xmlChar* type = xmlTextReaderConstName(reader);
335  if (type == nullptr)
336  {
337  NS_FATAL_ERROR("Invalid value");
338  }
339  if (std::string((char*)type) == "default")
340  {
341  xmlChar* name = xmlTextReaderGetAttribute(reader, BAD_CAST "name");
342  if (name == nullptr)
343  {
344  NS_FATAL_ERROR("Error getting attribute 'name'");
345  }
346  xmlChar* value = xmlTextReaderGetAttribute(reader, BAD_CAST "value");
347  if (value == nullptr)
348  {
349  NS_FATAL_ERROR("Error getting attribute 'value'");
350  }
351  NS_LOG_DEBUG("default=" << (char*)name << ", value=" << value);
352  Config::SetDefault((char*)name, StringValue((char*)value));
353  xmlFree(name);
354  xmlFree(value);
355  }
356  rc = xmlTextReaderRead(reader);
357  }
358  xmlFreeTextReader(reader);
359 }
360 
361 void
363 {
364  xmlTextReaderPtr reader = xmlNewTextReaderFilename(m_filename.c_str());
365  if (reader == nullptr)
366  {
367  NS_FATAL_ERROR("Error at xmlReaderForFile");
368  }
369  int rc;
370  rc = xmlTextReaderRead(reader);
371  while (rc > 0)
372  {
373  const xmlChar* type = xmlTextReaderConstName(reader);
374  if (type == nullptr)
375  {
376  NS_FATAL_ERROR("Invalid value");
377  }
378  if (std::string((char*)type) == "global")
379  {
380  xmlChar* name = xmlTextReaderGetAttribute(reader, BAD_CAST "name");
381  if (name == nullptr)
382  {
383  NS_FATAL_ERROR("Error getting attribute 'name'");
384  }
385  xmlChar* value = xmlTextReaderGetAttribute(reader, BAD_CAST "value");
386  if (value == nullptr)
387  {
388  NS_FATAL_ERROR("Error getting attribute 'value'");
389  }
390  NS_LOG_DEBUG("global=" << (char*)name << ", value=" << value);
391  Config::SetGlobal((char*)name, StringValue((char*)value));
392  xmlFree(name);
393  xmlFree(value);
394  }
395  rc = xmlTextReaderRead(reader);
396  }
397  xmlFreeTextReader(reader);
398 }
399 
400 void
402 {
403  xmlTextReaderPtr reader = xmlNewTextReaderFilename(m_filename.c_str());
404  if (reader == nullptr)
405  {
406  NS_FATAL_ERROR("Error at xmlReaderForFile");
407  }
408  int rc;
409  rc = xmlTextReaderRead(reader);
410  while (rc > 0)
411  {
412  const xmlChar* type = xmlTextReaderConstName(reader);
413  if (type == nullptr)
414  {
415  NS_FATAL_ERROR("Invalid value");
416  }
417  if (std::string((char*)type) == "value")
418  {
419  xmlChar* path = xmlTextReaderGetAttribute(reader, BAD_CAST "path");
420  if (path == nullptr)
421  {
422  NS_FATAL_ERROR("Error getting attribute 'path'");
423  }
424  xmlChar* value = xmlTextReaderGetAttribute(reader, BAD_CAST "value");
425  if (value == nullptr)
426  {
427  NS_FATAL_ERROR("Error getting attribute 'value'");
428  }
429  NS_LOG_DEBUG("path=" << (char*)path << ", value=" << (char*)value);
430  Config::Set((char*)path, StringValue((char*)value));
431  xmlFree(path);
432  xmlFree(value);
433  }
434  rc = xmlTextReaderRead(reader);
435  }
436  xmlFreeTextReader(reader);
437 }
438 
439 } // 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
Vector::const_iterator Iterator
Iterator type for the list of all global values.
Definition: global-value.h:82
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:60
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:839
struct TypeId::AttributeInformation GetAttribute(std::size_t i) const
Get Attribute information by index.
Definition: type-id.cc:1112
std::size_t GetAttributeN() const
Get the number of attributes.
Definition: type-id.cc:1104
SupportLevel
The level of support or deprecation for attributes or trace sources.
Definition: type-id.h:74
void Global() override
Load or save the global values.
Definition: xml-config.cc:362
void SetFilename(std::string filename) override
Set the file name.
Definition: xml-config.cc:316
void Default() override
Load or save the default values.
Definition: xml-config.cc:323
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:401
~XmlConfigLoad() override
Definition: xml-config.cc:310
void Global() override
Load or save the global values.
Definition: xml-config.cc:273
void Attributes() override
Load or save the attributes values.
Definition: xml-config.cc:193
~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:937
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:891
void Set(std::string path, const AttributeValue &value)
Definition: config.cc:877
#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.
value
Definition: second.py:41
Attribute implementation.
Definition: type-id.h:82
TypeId::SupportLevel supportLevel
Support level/deprecation.
Definition: type-id.h:98
std::string name
Attribute name.
Definition: type-id.h:84
xmlTextWriter * xmlTextWriterPtr
Definition: xml-config.h:30