A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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
35namespace ns3
36{
37
38NS_LOG_COMPONENT_DEFINE("XmlConfig");
39
41 : m_writer(nullptr)
42{
43 NS_LOG_FUNCTION(this);
44}
45
46void
47XmlConfigSave::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
107void
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
181 xmlTextWriterPtr m_writer;
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
191void
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
261 xmlTextWriterPtr m_writer;
262 bool m_saveDeprecated;
263 };
264
265 XmlTextAttributeIterator iter = XmlTextAttributeIterator(m_writer);
266 iter.SetSaveDeprecated(m_saveDeprecated);
267 iter.Iterate();
268}
269
270void
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
313void
314XmlConfigLoad::SetFilename(std::string filename)
315{
316 NS_LOG_FUNCTION(filename);
317 m_filename = filename;
318}
319
320void
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
359void
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
398void
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.
bool m_saveDeprecated
save deprecated attributes
Definition: file-config.h:61
static Iterator Begin()
The Begin iterator.
static Iterator End()
The End iterator.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
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
std::size_t GetAttributeN() const
Get the number of attributes.
Definition: type-id.cc:1101
TypeId::AttributeInformation GetAttribute(std::size_t i) const
Get Attribute information by index.
Definition: type-id.cc:1109
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:940
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:894
void Set(std::string path, const AttributeValue &value)
Definition: config.cc:880
#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