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