A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
config.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2008 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 * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18 */
19#include "config.h"
20
21#include "global-value.h"
22#include "log.h"
23#include "names.h"
25#include "object.h"
26#include "pointer.h"
27#include "singleton.h"
28
29#include <sstream>
30
31/**
32 * \file
33 * \ingroup config-impl
34 * ns3::Config implementations.
35 */
36
37/**
38 * \defgroup config-impl Config implementations
39 * \ingroup config
40 */
41namespace ns3
42{
43
45
46namespace Config
47{
48
50{
51 NS_LOG_FUNCTION(this);
52}
53
54MatchContainer::MatchContainer(const std::vector<Ptr<Object>>& objects,
55 const std::vector<std::string>& contexts,
56 std::string path)
57 : m_objects(objects),
58 m_contexts(contexts),
59 m_path(path)
60{
61 NS_LOG_FUNCTION(this << &objects << &contexts << path);
62}
63
66{
67 NS_LOG_FUNCTION(this);
68 return m_objects.begin();
69}
70
73{
74 NS_LOG_FUNCTION(this);
75 return m_objects.end();
76}
77
78std::size_t
80{
81 NS_LOG_FUNCTION(this);
82 return m_objects.size();
83}
84
86MatchContainer::Get(std::size_t i) const
87{
88 NS_LOG_FUNCTION(this << i);
89 return m_objects[i];
90}
91
92std::string
94{
95 NS_LOG_FUNCTION(this << i);
96 return m_contexts[i];
97}
98
99std::string
101{
102 NS_LOG_FUNCTION(this);
103 return m_path;
104}
105
106void
107MatchContainer::Set(std::string name, const AttributeValue& value)
108{
109 NS_LOG_FUNCTION(this << name << &value);
110 for (auto tmp = Begin(); tmp != End(); ++tmp)
111 {
112 Ptr<Object> object = *tmp;
113 // Let ObjectBase::SetAttribute raise any errors
114 object->SetAttribute(name, value);
115 }
116}
117
118bool
119MatchContainer::SetFailSafe(std::string name, const AttributeValue& value)
120{
121 NS_LOG_FUNCTION(this << name << &value);
122 bool ok = false;
123 for (auto tmp = Begin(); tmp != End(); ++tmp)
124 {
125 Ptr<Object> object = *tmp;
126 ok |= object->SetAttributeFailSafe(name, value);
127 }
128 return ok;
129}
130
131void
132MatchContainer::Connect(std::string name, const CallbackBase& cb)
133{
134 if (!ConnectFailSafe(name, cb))
135 {
136 NS_FATAL_ERROR("Could not connect callback to " << name);
137 }
138}
139
140bool
142{
143 NS_LOG_FUNCTION(this << name << &cb);
144 NS_ASSERT(m_objects.size() == m_contexts.size());
145 bool ok = false;
146 for (uint32_t i = 0; i < m_objects.size(); ++i)
147 {
148 Ptr<Object> object = m_objects[i];
149 std::string ctx = m_contexts[i] + name;
150 ok |= object->TraceConnect(name, ctx, cb);
151 }
152 return ok;
153}
154
155void
157{
158 if (!ConnectWithoutContextFailSafe(name, cb))
159 {
160 NS_FATAL_ERROR("Could not connect callback to " << name);
161 }
162}
163
164bool
166{
167 NS_LOG_FUNCTION(this << name << &cb);
168 bool ok = false;
169 for (auto tmp = Begin(); tmp != End(); ++tmp)
170 {
171 Ptr<Object> object = *tmp;
172 ok |= object->TraceConnectWithoutContext(name, cb);
173 }
174 return ok;
175}
176
177void
178MatchContainer::Disconnect(std::string name, const CallbackBase& cb)
179{
180 NS_LOG_FUNCTION(this << name << &cb);
181 NS_ASSERT(m_objects.size() == m_contexts.size());
182 for (uint32_t i = 0; i < m_objects.size(); ++i)
183 {
184 Ptr<Object> object = m_objects[i];
185 std::string ctx = m_contexts[i] + name;
186 object->TraceDisconnect(name, ctx, cb);
187 }
188}
189
190void
192{
193 NS_LOG_FUNCTION(this << name << &cb);
194 for (auto tmp = Begin(); tmp != End(); ++tmp)
195 {
196 Ptr<Object> object = *tmp;
197 object->TraceDisconnectWithoutContext(name, cb);
198 }
199}
200
201/**
202 * \ingroup config-impl
203 * Helper to test if an array entry matches a config path specification.
204 */
206{
207 public:
208 /**
209 * Construct from a Config path specification.
210 *
211 * \param [in] element The Config path specification.
212 */
213 ArrayMatcher(std::string element);
214 /**
215 * Test if a specific index matches the Config Path.
216 *
217 * \param [in] i The index.
218 * \returns \c true if the index matches the Config Path.
219 */
220 bool Matches(std::size_t i) const;
221
222 private:
223 /**
224 * Convert a string to an \c uint32_t.
225 *
226 * \param [in] str The string.
227 * \param [in] value The location to store the \c uint32_t.
228 * \returns \c true if the string could be converted.
229 */
230 bool StringToUint32(std::string str, uint32_t* value) const;
231 /** The Config path element. */
232 std::string m_element;
233
234}; // class ArrayMatcher
235
236ArrayMatcher::ArrayMatcher(std::string element)
237 : m_element(element)
238{
239 NS_LOG_FUNCTION(this << element);
240}
241
242bool
243ArrayMatcher::Matches(std::size_t i) const
244{
245 NS_LOG_FUNCTION(this << i);
246 if (m_element == "*")
247 {
248 NS_LOG_DEBUG("Array " << i << " matches *");
249 return true;
250 }
251 std::string::size_type tmp;
252 tmp = m_element.find('|');
253 if (tmp != std::string::npos)
254 {
255 std::string left = m_element.substr(0, tmp - 0);
256 std::string right = m_element.substr(tmp + 1, m_element.size() - (tmp + 1));
257 ArrayMatcher matcher = ArrayMatcher(left);
258 if (matcher.Matches(i))
259 {
260 NS_LOG_DEBUG("Array " << i << " matches " << left);
261 return true;
262 }
263 matcher = ArrayMatcher(right);
264 if (matcher.Matches(i))
265 {
266 NS_LOG_DEBUG("Array " << i << " matches " << right);
267 return true;
268 }
269 NS_LOG_DEBUG("Array " << i << " does not match " << m_element);
270 return false;
271 }
272 std::string::size_type leftBracket = m_element.find('[');
273 std::string::size_type rightBracket = m_element.find(']');
274 std::string::size_type dash = m_element.find('-');
275 if (leftBracket == 0 && rightBracket == m_element.size() - 1 && dash > leftBracket &&
276 dash < rightBracket)
277 {
278 std::string lowerBound = m_element.substr(leftBracket + 1, dash - (leftBracket + 1));
279 std::string upperBound = m_element.substr(dash + 1, rightBracket - (dash + 1));
280 uint32_t min;
281 uint32_t max;
282 if (StringToUint32(lowerBound, &min) && StringToUint32(upperBound, &max) && i >= min &&
283 i <= max)
284 {
285 NS_LOG_DEBUG("Array " << i << " matches " << m_element);
286 return true;
287 }
288 else
289 {
290 NS_LOG_DEBUG("Array " << i << " does not " << m_element);
291 return false;
292 }
293 }
294 uint32_t value;
295 if (StringToUint32(m_element, &value) && i == value)
296 {
297 NS_LOG_DEBUG("Array " << i << " matches " << m_element);
298 return true;
299 }
300 NS_LOG_DEBUG("Array " << i << " does not match " << m_element);
301 return false;
302}
303
304bool
305ArrayMatcher::StringToUint32(std::string str, uint32_t* value) const
306{
307 NS_LOG_FUNCTION(this << str << value);
308 std::istringstream iss;
309 iss.str(str);
310 iss >> (*value);
311 return !iss.bad() && !iss.fail();
312}
313
314/**
315 * \ingroup config-impl
316 * Abstract class to parse Config paths into object references.
317 */
319{
320 public:
321 /**
322 * Construct from a base Config path.
323 *
324 * \param [in] path The Config path.
325 */
326 Resolver(std::string path);
327 /** Destructor. */
328 virtual ~Resolver();
329
330 /**
331 * Parse the stored Config path into an object reference,
332 * beginning at the indicated root object.
333 *
334 * \param [in] root The object corresponding to the current position in
335 * in the Config path.
336 */
337 void Resolve(Ptr<Object> root);
338
339 private:
340 /** Ensure the Config path starts and ends with a '/'. */
341 void Canonicalize();
342 /**
343 * Parse the next element in the Config path.
344 *
345 * \param [in] path The remaining portion of the Config path.
346 * \param [in] root The object corresponding to the current position
347 * in the Config path.
348 */
349 void DoResolve(std::string path, Ptr<Object> root);
350 /**
351 * Parse an index on the Config path.
352 *
353 * \param [in] path The remaining Config path.
354 * \param [in,out] vector The resulting list of matching objects.
355 */
356 void DoArrayResolve(std::string path, const ObjectPtrContainerValue& vector);
357 /**
358 * Handle one object found on the path.
359 *
360 * \param [in] object The current object on the Config path.
361 */
362 void DoResolveOne(Ptr<Object> object);
363 /**
364 * Get the current Config path.
365 *
366 * \returns The current Config path.
367 */
368 std::string GetResolvedPath() const;
369 /**
370 * Handle one found object.
371 *
372 * \param [in] object The found object.
373 * \param [in] path The matching Config path context.
374 */
375 virtual void DoOne(Ptr<Object> object, std::string path) = 0;
376
377 /** Current list of path tokens. */
378 std::vector<std::string> m_workStack;
379 /** The Config path. */
380 std::string m_path;
381
382}; // class Resolver
383
384Resolver::Resolver(std::string path)
385 : m_path(path)
386{
387 NS_LOG_FUNCTION(this << path);
388 Canonicalize();
389}
390
392{
393 NS_LOG_FUNCTION(this);
394}
395
396void
398{
399 NS_LOG_FUNCTION(this);
400
401 // ensure that we start and end with a '/'
402 std::string::size_type tmp = m_path.find('/');
403 if (tmp != 0)
404 {
405 // no slash at start
406 m_path = "/" + m_path;
407 }
408 tmp = m_path.find_last_of('/');
409 if (tmp != (m_path.size() - 1))
410 {
411 // no slash at end
412 m_path = m_path + "/";
413 }
414}
415
416void
418{
419 NS_LOG_FUNCTION(this << root);
420
421 DoResolve(m_path, root);
422}
423
424std::string
426{
427 NS_LOG_FUNCTION(this);
428
429 std::string fullPath = "/";
430 for (auto i = m_workStack.begin(); i != m_workStack.end(); i++)
431 {
432 fullPath += *i + "/";
433 }
434 return fullPath;
435}
436
437void
439{
440 NS_LOG_FUNCTION(this << object);
441
442 NS_LOG_DEBUG("resolved=" << GetResolvedPath());
443 DoOne(object, GetResolvedPath());
444}
445
446void
447Resolver::DoResolve(std::string path, Ptr<Object> root)
448{
449 NS_LOG_FUNCTION(this << path << root);
450 NS_ASSERT((path.find('/')) == 0);
451 std::string::size_type next = path.find('/', 1);
452
453 if (next == std::string::npos)
454 {
455 //
456 // If root is zero, we're beginning to see if we can use the object name
457 // service to resolve this path. It is impossible to have a object name
458 // associated with the root of the object name service since that root
459 // is not an object. This path must be referring to something in another
460 // namespace and it will have been found already since the name service
461 // is always consulted last.
462 //
463 if (root)
464 {
465 DoResolveOne(root);
466 }
467 return;
468 }
469 std::string item = path.substr(1, next - 1);
470 std::string pathLeft = path.substr(next, path.size() - next);
471
472 //
473 // If root is zero, we're beginning to see if we can use the object name
474 // service to resolve this path. In this case, we must see the name space
475 // "/Names" on the front of this path. There is no object associated with
476 // the root of the "/Names" namespace, so we just ignore it and move on to
477 // the next segment.
478 //
479 if (!root)
480 {
481 std::string::size_type offset = path.find("/Names");
482 if (offset == 0)
483 {
484 m_workStack.push_back(item);
485 DoResolve(pathLeft, root);
486 m_workStack.pop_back();
487 return;
488 }
489 }
490
491 //
492 // We have an item (possibly a segment of a namespace path. Check to see if
493 // we can determine that this segment refers to a named object. If root is
494 // zero, this means to look in the root of the "/Names" name space, otherwise
495 // it refers to a name space context (level).
496 //
497 Ptr<Object> namedObject = Names::Find<Object>(root, item);
498 if (namedObject)
499 {
500 NS_LOG_DEBUG("Name system resolved item = " << item << " to " << namedObject);
501 m_workStack.push_back(item);
502 DoResolve(pathLeft, namedObject);
503 m_workStack.pop_back();
504 return;
505 }
506
507 //
508 // We're done with the object name service hooks, so proceed down the path
509 // of types and attributes; but only if root is nonzero. If root is zero
510 // and we find ourselves here, we are trying to check in the namespace for
511 // a path that is not in the "/Names" namespace. We will have previously
512 // found any matches, so we just bail out.
513 //
514 if (!root)
515 {
516 return;
517 }
518 std::string::size_type dollarPos = item.find('$');
519 if (dollarPos == 0)
520 {
521 // This is a call to GetObject
522 std::string tidString = item.substr(1, item.size() - 1);
523 NS_LOG_DEBUG("GetObject=" << tidString << " on path=" << GetResolvedPath());
524 TypeId tid = TypeId::LookupByName(tidString);
525 Ptr<Object> object = root->GetObject<Object>(tid);
526 if (!object)
527 {
528 NS_LOG_DEBUG("GetObject (" << tidString << ") failed on path=" << GetResolvedPath());
529 return;
530 }
531 m_workStack.push_back(item);
532 DoResolve(pathLeft, object);
533 m_workStack.pop_back();
534 }
535 else
536 {
537 // this is a normal attribute.
538 TypeId tid;
539 TypeId nextTid = root->GetInstanceTypeId();
540 bool foundMatch = false;
541
542 do
543 {
544 tid = nextTid;
545
546 for (uint32_t i = 0; i < tid.GetAttributeN(); i++)
547 {
549 info = tid.GetAttribute(i);
550 if (info.name != item && item != "*")
551 {
552 continue;
553 }
554 // attempt to cast to a pointer checker.
555 const auto pChecker =
556 dynamic_cast<const PointerChecker*>(PeekPointer(info.checker));
557 if (pChecker != nullptr)
558 {
559 NS_LOG_DEBUG("GetAttribute(ptr)=" << info.name
560 << " on path=" << GetResolvedPath());
561 PointerValue pValue;
562 root->GetAttribute(info.name, pValue);
563 Ptr<Object> object = pValue.Get<Object>();
564 if (!object)
565 {
566 NS_LOG_ERROR("Requested object name=\"" << item << "\" exists on path=\""
567 << GetResolvedPath()
568 << "\""
569 " but is null.");
570 continue;
571 }
572 foundMatch = true;
573 m_workStack.push_back(info.name);
574 DoResolve(pathLeft, object);
575 m_workStack.pop_back();
576 }
577 // attempt to cast to an object vector.
578 const auto vectorChecker =
579 dynamic_cast<const ObjectPtrContainerChecker*>(PeekPointer(info.checker));
580 if (vectorChecker != nullptr)
581 {
582 NS_LOG_DEBUG("GetAttribute(vector)=" << info.name << " on path="
583 << GetResolvedPath() << pathLeft);
584 foundMatch = true;
586 root->GetAttribute(info.name, vector);
587 m_workStack.push_back(info.name);
588 DoArrayResolve(pathLeft, vector);
589 m_workStack.pop_back();
590 }
591 // this could be anything else and we don't know what to do with it.
592 // So, we just ignore it.
593 }
594
595 nextTid = tid.GetParent();
596 } while (nextTid != tid);
597
598 if (!foundMatch)
599 {
600 NS_LOG_DEBUG("Requested item=" << item
601 << " does not exist on path=" << GetResolvedPath());
602 return;
603 }
604 }
605}
606
607void
608Resolver::DoArrayResolve(std::string path, const ObjectPtrContainerValue& container)
609{
610 NS_LOG_FUNCTION(this << path << &container);
611 NS_ASSERT(!path.empty());
612 NS_ASSERT((path.find('/')) == 0);
613 std::string::size_type next = path.find('/', 1);
614 if (next == std::string::npos)
615 {
616 return;
617 }
618 std::string item = path.substr(1, next - 1);
619 std::string pathLeft = path.substr(next, path.size() - next);
620
621 ArrayMatcher matcher = ArrayMatcher(item);
623 for (it = container.Begin(); it != container.End(); ++it)
624 {
625 if (matcher.Matches((*it).first))
626 {
627 std::ostringstream oss;
628 oss << (*it).first;
629 m_workStack.push_back(oss.str());
630 DoResolve(pathLeft, (*it).second);
631 m_workStack.pop_back();
632 }
633 }
634}
635
636/**
637 * \ingroup config-impl
638 * Config system implementation class.
639 */
640class ConfigImpl : public Singleton<ConfigImpl>
641{
642 public:
643 // Keep Set and SetFailSafe since their errors are triggered
644 // by the underlying ObjectBase functions.
645 /** \copydoc ns3::Config::Set() */
646 void Set(std::string path, const AttributeValue& value);
647 /** \copydoc ns3::Config::SetFailSafe() */
648 bool SetFailSafe(std::string path, const AttributeValue& value);
649 /** \copydoc ns3::Config::ConnectWithoutContextFailSafe() */
650 bool ConnectWithoutContextFailSafe(std::string path, const CallbackBase& cb);
651 /** \copydoc ns3::Config::ConnectFailSafe() */
652 bool ConnectFailSafe(std::string path, const CallbackBase& cb);
653 /** \copydoc ns3::Config::DisconnectWithoutContext() */
654 void DisconnectWithoutContext(std::string path, const CallbackBase& cb);
655 /** \copydoc ns3::Config::Disconnect() */
656 void Disconnect(std::string path, const CallbackBase& cb);
657 /** \copydoc ns3::Config::LookupMatches() */
658 MatchContainer LookupMatches(std::string path);
659
660 /** \copydoc ns3::Config::RegisterRootNamespaceObject() */
662 /** \copydoc ns3::Config::UnregisterRootNamespaceObject() */
664
665 /** \copydoc ns3::Config::GetRootNamespaceObjectN() */
666 std::size_t GetRootNamespaceObjectN() const;
667 /** \copydoc ns3::Config::GetRootNamespaceObject() */
668 Ptr<Object> GetRootNamespaceObject(std::size_t i) const;
669
670 private:
671 /**
672 * Break a Config path into the leading path and the last leaf token.
673 * \param [in] path The Config path.
674 * \param [in,out] root The leading part of the \pname{path},
675 * up to the final slash.
676 * \param [in,out] leaf The trailing part of the \pname{path}.
677 */
678 void ParsePath(std::string path, std::string* root, std::string* leaf) const;
679
680 /** Container type to hold the root Config path tokens. */
681 typedef std::vector<Ptr<Object>> Roots;
682
683 /** The list of Config path roots. */
685
686}; // class ConfigImpl
687
688void
689ConfigImpl::ParsePath(std::string path, std::string* root, std::string* leaf) const
690{
691 NS_LOG_FUNCTION(this << path << root << leaf);
692
693 std::string::size_type slash = path.find_last_of('/');
694 NS_ASSERT(slash != std::string::npos);
695 *root = path.substr(0, slash);
696 *leaf = path.substr(slash + 1, path.size() - (slash + 1));
697 NS_LOG_FUNCTION(path << *root << *leaf);
698}
699
700void
701ConfigImpl::Set(std::string path, const AttributeValue& value)
702{
703 NS_LOG_FUNCTION(this << path << &value);
704
705 std::string root;
706 std::string leaf;
707 ParsePath(path, &root, &leaf);
708 MatchContainer container = LookupMatches(root);
709 container.Set(leaf, value);
710}
711
712bool
713ConfigImpl::SetFailSafe(std::string path, const AttributeValue& value)
714{
715 NS_LOG_FUNCTION(this << path << &value);
716
717 std::string root;
718 std::string leaf;
719 ParsePath(path, &root, &leaf);
720 MatchContainer container = LookupMatches(root);
721 return container.SetFailSafe(leaf, value);
722}
723
724bool
726{
727 NS_LOG_FUNCTION(this << path << &cb);
728 std::string root;
729 std::string leaf;
730 ParsePath(path, &root, &leaf);
731 MatchContainer container = LookupMatches(root);
732 return container.ConnectWithoutContextFailSafe(leaf, cb);
733}
734
735void
737{
738 NS_LOG_FUNCTION(this << path << &cb);
739 std::string root;
740 std::string leaf;
741 ParsePath(path, &root, &leaf);
742 MatchContainer container = LookupMatches(root);
743 if (container.GetN() == 0)
744 {
745 std::size_t lastFwdSlash = root.rfind('/');
746 NS_LOG_WARN("Failed to disconnect "
747 << leaf << ", the Requested object name = " << root.substr(lastFwdSlash + 1)
748 << " does not exits on path " << root.substr(0, lastFwdSlash));
749 }
750 container.DisconnectWithoutContext(leaf, cb);
751}
752
753bool
754ConfigImpl::ConnectFailSafe(std::string path, const CallbackBase& cb)
755{
756 NS_LOG_FUNCTION(this << path << &cb);
757
758 std::string root;
759 std::string leaf;
760 ParsePath(path, &root, &leaf);
761 MatchContainer container = LookupMatches(root);
762 return container.ConnectFailSafe(leaf, cb);
763}
764
765void
766ConfigImpl::Disconnect(std::string path, const CallbackBase& cb)
767{
768 NS_LOG_FUNCTION(this << path << &cb);
769
770 std::string root;
771 std::string leaf;
772 ParsePath(path, &root, &leaf);
773 MatchContainer container = LookupMatches(root);
774 if (container.GetN() == 0)
775 {
776 std::size_t lastFwdSlash = root.rfind('/');
777 NS_LOG_WARN("Failed to disconnect "
778 << leaf << ", the Requested object name = " << root.substr(lastFwdSlash + 1)
779 << " does not exits on path " << root.substr(0, lastFwdSlash));
780 }
781 container.Disconnect(leaf, cb);
782}
783
786{
787 NS_LOG_FUNCTION(this << path);
788
789 class LookupMatchesResolver : public Resolver
790 {
791 public:
792 LookupMatchesResolver(std::string path)
793 : Resolver(path)
794 {
795 }
796
797 void DoOne(Ptr<Object> object, std::string path) override
798 {
799 m_objects.push_back(object);
800 m_contexts.push_back(path);
801 }
802
803 std::vector<Ptr<Object>> m_objects;
804 std::vector<std::string> m_contexts;
805 } resolver = LookupMatchesResolver(path);
806
807 for (auto i = m_roots.begin(); i != m_roots.end(); i++)
808 {
809 resolver.Resolve(*i);
810 }
811
812 //
813 // See if we can do something with the object name service. Starting with
814 // the root pointer zeroed indicates to the resolver that it should start
815 // looking at the root of the "/Names" namespace during this go.
816 //
817 resolver.Resolve(nullptr);
818
819 return MatchContainer(resolver.m_objects, resolver.m_contexts, path);
820}
821
822void
824{
825 NS_LOG_FUNCTION(this << obj);
826 m_roots.push_back(obj);
827}
828
829void
831{
832 NS_LOG_FUNCTION(this << obj);
833
834 for (auto i = m_roots.begin(); i != m_roots.end(); i++)
835 {
836 if (*i == obj)
837 {
838 m_roots.erase(i);
839 return;
840 }
841 }
842}
843
844std::size_t
846{
847 NS_LOG_FUNCTION(this);
848 return m_roots.size();
849}
850
853{
854 NS_LOG_FUNCTION(this << i);
855 return m_roots[i];
856}
857
858void
860{
862 // First, let's reset the initial value of every attribute
863 for (uint16_t i = 0; i < TypeId::GetRegisteredN(); i++)
864 {
866 for (uint32_t j = 0; j < tid.GetAttributeN(); j++)
867 {
870 }
871 }
872 // now, let's reset the initial value of every global value.
873 for (auto i = GlobalValue::Begin(); i != GlobalValue::End(); ++i)
874 {
875 (*i)->ResetInitialValue();
876 }
877}
878
879void
880Set(std::string path, const AttributeValue& value)
881{
882 NS_LOG_FUNCTION(path << &value);
883 ConfigImpl::Get()->Set(path, value);
884}
885
886bool
887SetFailSafe(std::string path, const AttributeValue& value)
888{
889 NS_LOG_FUNCTION(path << &value);
890 return ConfigImpl::Get()->SetFailSafe(path, value);
891}
892
893void
894SetDefault(std::string name, const AttributeValue& value)
895{
896 NS_LOG_FUNCTION(name << &value);
897 if (!SetDefaultFailSafe(name, value))
898 {
899 NS_FATAL_ERROR("Could not set default value for " << name);
900 }
901}
902
903bool
904SetDefaultFailSafe(std::string fullName, const AttributeValue& value)
905{
906 NS_LOG_FUNCTION(fullName << &value);
907 std::string::size_type pos = fullName.rfind("::");
908 if (pos == std::string::npos)
909 {
910 return false;
911 }
912 std::string tidName = fullName.substr(0, pos);
913 std::string paramName = fullName.substr(pos + 2, fullName.size() - (pos + 2));
914 TypeId tid;
915 bool ok = TypeId::LookupByNameFailSafe(tidName, &tid);
916 if (!ok)
917 {
918 return false;
919 }
921 tid.LookupAttributeByName(paramName, &info);
922 for (uint32_t j = 0; j < tid.GetAttributeN(); j++)
923 {
925 if (tmp.name == paramName)
926 {
927 Ptr<AttributeValue> v = tmp.checker->CreateValidValue(value);
928 if (!v)
929 {
930 return false;
931 }
932 tid.SetAttributeInitialValue(j, v);
933 return true;
934 }
935 }
936 return false;
937}
938
939void
940SetGlobal(std::string name, const AttributeValue& value)
941{
942 NS_LOG_FUNCTION(name << &value);
943 GlobalValue::Bind(name, value);
944}
945
946bool
947SetGlobalFailSafe(std::string name, const AttributeValue& value)
948{
949 NS_LOG_FUNCTION(name << &value);
950 return GlobalValue::BindFailSafe(name, value);
951}
952
953void
954ConnectWithoutContext(std::string path, const CallbackBase& cb)
955{
956 NS_LOG_FUNCTION(path << &cb);
957 if (!ConnectWithoutContextFailSafe(path, cb))
958 {
959 NS_FATAL_ERROR("Could not connect callback to " << path);
960 }
961}
962
963bool
964ConnectWithoutContextFailSafe(std::string path, const CallbackBase& cb)
965{
966 NS_LOG_FUNCTION(path << &cb);
968}
969
970void
971DisconnectWithoutContext(std::string path, const CallbackBase& cb)
972{
973 NS_LOG_FUNCTION(path << &cb);
975}
976
977void
978Connect(std::string path, const CallbackBase& cb)
979{
980 NS_LOG_FUNCTION(path << &cb);
981 if (!ConnectFailSafe(path, cb))
982 {
983 NS_FATAL_ERROR("Could not connect callback to " << path);
984 }
985}
986
987bool
988ConnectFailSafe(std::string path, const CallbackBase& cb)
989{
990 NS_LOG_FUNCTION(path << &cb);
991 return ConfigImpl::Get()->ConnectFailSafe(path, cb);
992}
993
994void
995Disconnect(std::string path, const CallbackBase& cb)
996{
997 NS_LOG_FUNCTION(path << &cb);
998 ConfigImpl::Get()->Disconnect(path, cb);
999}
1000
1001MatchContainer
1002LookupMatches(std::string path)
1003{
1004 NS_LOG_FUNCTION(path);
1005 return ConfigImpl::Get()->LookupMatches(path);
1006}
1007
1008void
1010{
1011 NS_LOG_FUNCTION(obj);
1013}
1014
1015void
1017{
1018 NS_LOG_FUNCTION(obj);
1020}
1021
1022std::size_t
1024{
1027}
1028
1031{
1032 NS_LOG_FUNCTION(i);
1034}
1035
1036} // namespace Config
1037
1038} // namespace ns3
Hold a value for an Attribute.
Definition: attribute.h:70
Base class for Callback class.
Definition: callback.h:360
Helper to test if an array entry matches a config path specification.
Definition: config.cc:206
ArrayMatcher(std::string element)
Construct from a Config path specification.
Definition: config.cc:236
bool StringToUint32(std::string str, uint32_t *value) const
Convert a string to an uint32_t.
Definition: config.cc:305
bool Matches(std::size_t i) const
Test if a specific index matches the Config Path.
Definition: config.cc:243
std::string m_element
The Config path element.
Definition: config.cc:232
Config system implementation class.
Definition: config.cc:641
void UnregisterRootNamespaceObject(Ptr< Object > obj)
Definition: config.cc:830
void DisconnectWithoutContext(std::string path, const CallbackBase &cb)
Definition: config.cc:736
Roots m_roots
The list of Config path roots.
Definition: config.cc:684
Ptr< Object > GetRootNamespaceObject(std::size_t i) const
Definition: config.cc:852
bool ConnectFailSafe(std::string path, const CallbackBase &cb)
Definition: config.cc:754
std::size_t GetRootNamespaceObjectN() const
Definition: config.cc:845
bool SetFailSafe(std::string path, const AttributeValue &value)
Definition: config.cc:713
void Set(std::string path, const AttributeValue &value)
Definition: config.cc:701
void ParsePath(std::string path, std::string *root, std::string *leaf) const
Break a Config path into the leading path and the last leaf token.
Definition: config.cc:689
void Disconnect(std::string path, const CallbackBase &cb)
Definition: config.cc:766
std::vector< Ptr< Object > > Roots
Container type to hold the root Config path tokens.
Definition: config.cc:681
bool ConnectWithoutContextFailSafe(std::string path, const CallbackBase &cb)
Definition: config.cc:725
void RegisterRootNamespaceObject(Ptr< Object > obj)
Definition: config.cc:823
MatchContainer LookupMatches(std::string path)
Definition: config.cc:785
hold a set of objects which match a specific search string.
Definition: config.h:195
bool SetFailSafe(std::string name, const AttributeValue &value)
Definition: config.cc:119
void Connect(std::string name, const CallbackBase &cb)
Definition: config.cc:132
void DisconnectWithoutContext(std::string name, const CallbackBase &cb)
Definition: config.cc:191
void Set(std::string name, const AttributeValue &value)
Definition: config.cc:107
Ptr< Object > Get(std::size_t i) const
Definition: config.cc:86
void Disconnect(std::string name, const CallbackBase &cb)
Definition: config.cc:178
std::string GetMatchedPath(uint32_t i) const
Definition: config.cc:93
MatchContainer::Iterator End() const
Definition: config.cc:72
bool ConnectFailSafe(std::string name, const CallbackBase &cb)
Definition: config.cc:141
std::string GetPath() const
Definition: config.cc:100
bool ConnectWithoutContextFailSafe(std::string name, const CallbackBase &cb)
Definition: config.cc:165
std::string m_path
The path used to perform the object matching.
Definition: config.h:353
void ConnectWithoutContext(std::string name, const CallbackBase &cb)
Definition: config.cc:156
std::size_t GetN() const
Definition: config.cc:79
std::vector< Ptr< Object > >::const_iterator Iterator
Const iterator over the objects in this container.
Definition: config.h:198
std::vector< Ptr< Object > > m_objects
The list of objects in this container.
Definition: config.h:349
MatchContainer::Iterator Begin() const
Definition: config.cc:65
std::vector< std::string > m_contexts
The context for each object.
Definition: config.h:351
Abstract class to parse Config paths into object references.
Definition: config.cc:319
std::vector< std::string > m_workStack
Current list of path tokens.
Definition: config.cc:378
std::string GetResolvedPath() const
Get the current Config path.
Definition: config.cc:425
Resolver(std::string path)
Construct from a base Config path.
Definition: config.cc:384
void Resolve(Ptr< Object > root)
Parse the stored Config path into an object reference, beginning at the indicated root object.
Definition: config.cc:417
void DoResolveOne(Ptr< Object > object)
Handle one object found on the path.
Definition: config.cc:438
virtual void DoOne(Ptr< Object > object, std::string path)=0
Handle one found object.
void DoResolve(std::string path, Ptr< Object > root)
Parse the next element in the Config path.
Definition: config.cc:447
std::string m_path
The Config path.
Definition: config.cc:380
void Canonicalize()
Ensure the Config path starts and ends with a '/'.
Definition: config.cc:397
virtual ~Resolver()
Destructor.
Definition: config.cc:391
void DoArrayResolve(std::string path, const ObjectPtrContainerValue &vector)
Parse an index on the Config path.
Definition: config.cc:608
static void Bind(std::string name, const AttributeValue &value)
Iterate over the set of GlobalValues until a matching name is found and then set its value with Globa...
static Iterator Begin()
The Begin iterator.
static bool BindFailSafe(std::string name, const AttributeValue &value)
Iterate over the set of GlobalValues until a matching name is found and then set its value with Globa...
static Iterator End()
The End iterator.
A base class which provides memory management and object aggregation.
Definition: object.h:89
AttributeChecker implementation for ObjectPtrContainerValue.
Container for a set of ns3::Object pointers.
std::map< std::size_t, Ptr< Object > >::const_iterator Iterator
Iterator type for traversing this container.
AttributeChecker implementation for PointerValue.
Definition: pointer.h:125
AttributeValue implementation for Pointer.
Definition: pointer.h:48
Ptr< T > Get() const
Definition: pointer.h:234
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
A template singleton.
Definition: singleton.h:68
static ConfigImpl * Get()
Get a pointer to the singleton instance.
Definition: singleton.h:107
a unique identifier for an interface.
Definition: type-id.h:59
bool SetAttributeInitialValue(std::size_t i, Ptr< const AttributeValue > initialValue)
Set the initial value of an Attribute.
Definition: type-id.cc:1077
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:836
static uint16_t GetRegisteredN()
Get the number of registered TypeIds.
Definition: type-id.cc:880
std::size_t GetAttributeN() const
Get the number of attributes.
Definition: type-id.cc:1101
TypeId GetParent() const
Get the parent of this TypeId.
Definition: type-id.cc:956
static TypeId GetRegistered(uint16_t i)
Get a TypeId by index.
Definition: type-id.cc:887
TypeId::AttributeInformation GetAttribute(std::size_t i) const
Get Attribute information by index.
Definition: type-id.cc:1109
static bool LookupByNameFailSafe(std::string name, TypeId *tid)
Get a TypeId by name.
Definition: type-id.cc:845
bool LookupAttributeByName(std::string name, AttributeInformation *info) const
Find an Attribute by name, retrieving the associated AttributeInformation.
Definition: type-id.cc:894
Declaration of the various ns3::Config functions and classes.
ns3::GlobalValue declaration.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
void Reset()
Reset the initial value of every attribute as well as the value of every global to what they were bef...
Definition: config.cc:859
void SetGlobal(std::string name, const AttributeValue &value)
Definition: config.cc:940
bool SetFailSafe(std::string path, const AttributeValue &value)
Definition: config.cc:887
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:894
void Disconnect(std::string path, const CallbackBase &cb)
Definition: config.cc:995
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:978
MatchContainer LookupMatches(std::string path)
Definition: config.cc:1002
void DisconnectWithoutContext(std::string path, const CallbackBase &cb)
Definition: config.cc:971
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition: config.cc:954
bool ConnectFailSafe(std::string path, const CallbackBase &cb)
Definition: config.cc:988
void UnregisterRootNamespaceObject(Ptr< Object > obj)
Definition: config.cc:1016
Ptr< Object > GetRootNamespaceObject(uint32_t i)
Definition: config.cc:1030
bool SetGlobalFailSafe(std::string name, const AttributeValue &value)
Definition: config.cc:947
void Set(std::string path, const AttributeValue &value)
Definition: config.cc:880
void RegisterRootNamespaceObject(Ptr< Object > obj)
Definition: config.cc:1009
std::size_t GetRootNamespaceObjectN()
Definition: config.cc:1023
bool SetDefaultFailSafe(std::string fullName, const AttributeValue &value)
Definition: config.cc:904
bool ConnectWithoutContextFailSafe(std::string path, const CallbackBase &cb)
Definition: config.cc:964
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:254
#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_NOARGS()
Output the name of the function.
#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
Debug message logging.
Declaration of class ns3::Names.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:454
ns3::ObjectPtrContainerValue attribute value declarations and template implementations.
ns3::Object class declaration, which is the root of the Object hierarchy and Aggregation.
ns3::PointerValue attribute value declarations and template implementations.
ns3::Singleton declaration and template implementation.
Attribute implementation.
Definition: type-id.h:81
Ptr< const AttributeValue > originalInitialValue
Default initial value.
Definition: type-id.h:89
std::string name
Attribute name.
Definition: type-id.h:83
Ptr< const AttributeChecker > checker
Checker object.
Definition: type-id.h:95