A Discrete-Event Network Simulator
API
names.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2009 University of Washington
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19#include <map>
20#include "object.h"
21#include "log.h"
22#include "assert.h"
23#include "abort.h"
24#include "names.h"
25#include "singleton.h"
26
33namespace ns3 {
34
36
42{
43public:
45 NameNode ();
51 NameNode (const NameNode &nameNode);
59 NameNode (NameNode *parent, std::string name, Ptr<Object> object);
66 NameNode &operator = (const NameNode &rhs);
67
69 ~NameNode ();
70
74 std::string m_name;
77
79 std::map<std::string, NameNode *> m_nameMap;
80};
81
83 : m_parent (0), m_name (""), m_object (0)
84{}
85
87{
88 m_parent = nameNode.m_parent;
89 m_name = nameNode.m_name;
90 m_object = nameNode.m_object;
91 m_nameMap = nameNode.m_nameMap;
92}
93
96{
97 m_parent = rhs.m_parent;
98 m_name = rhs.m_name;
99 m_object = rhs.m_object;
100 m_nameMap = rhs.m_nameMap;
101 return *this;
102}
103
104NameNode::NameNode (NameNode *parent, std::string name, Ptr<Object> object)
105 : m_parent (parent), m_name (name), m_object (object)
106{
107 NS_LOG_FUNCTION (this << parent << name << object);
108}
109
111{
112 NS_LOG_FUNCTION (this);
113}
114
119class NamesPriv : public Singleton<NamesPriv>
120{
121public:
123 NamesPriv ();
125 ~NamesPriv ();
126
127 // Doxygen \copydoc bug: won't copy these docs, so we repeat them.
128
137 bool Add (std::string name, Ptr<Object> object);
147 bool Add (std::string path, std::string name, Ptr<Object> object);
158 bool Add (Ptr<Object> context, std::string name, Ptr<Object> object);
159
168 bool Rename (std::string oldpath, std::string newname);
180 bool Rename (std::string path, std::string oldname, std::string newname);
194 bool Rename (Ptr<Object> context, std::string oldname, std::string newname);
195
204 std::string FindName (Ptr<Object> object);
213 std::string FindPath (Ptr<Object> object);
214
218 void Clear (void);
219
228 Ptr<Object> Find (std::string path);
238 Ptr<Object> Find (std::string path, std::string name);
249 Ptr<Object> Find (Ptr<Object> context, std::string name);
250
251private:
252
259 NameNode * IsNamed (Ptr<Object> object);
267 bool IsDuplicateName (NameNode *node, std::string name);
268
271
273 std::map<Ptr<Object>, NameNode *> m_objectMap;
274};
275
277{
278 NS_LOG_FUNCTION (this);
279
280 m_root.m_parent = 0;
281 m_root.m_name = "Names";
282 m_root.m_object = 0;
283}
284
286{
287 NS_LOG_FUNCTION (this);
288 Clear ();
289 m_root.m_name = "";
290}
291
292void
294{
295 NS_LOG_FUNCTION (this);
296 //
297 // Every name is associated with an object in the object map, so freeing the
298 // NameNodes in this map will free all of the memory allocated for the NameNodes
299 //
300 for (std::map<Ptr<Object>, NameNode *>::iterator i = m_objectMap.begin (); i != m_objectMap.end (); ++i)
301 {
302 delete i->second;
303 i->second = 0;
304 }
305
306 m_objectMap.clear ();
307
308 m_root.m_parent = 0;
309 m_root.m_name = "Names";
310 m_root.m_object = 0;
311 m_root.m_nameMap.clear ();
312}
313
314bool
315NamesPriv::Add (std::string name, Ptr<Object> object)
316{
317 NS_LOG_FUNCTION (this << name << object);
318 //
319 // This is the simple, easy to use version of Add, so we want it to be flexible.
320 // We don't want to force a user to always type the fully qualified namespace
321 // name, so we allow the namespace name to be omitted. For example, calling
322 // Add ("Client/ath0", obj) should result in exactly the same behavior as
323 // Add ("/Names/Client/ath0", obj). Calling Add ("Client", obj) should have
324 // the same effect as Add ("Names/Client", obj)
325 //
326 // The first thing to do, then, is to "canonicalize" the input string to always
327 // be a fully qualified name.
328 //
329 // If we are given a name that begins with "/Names/" we assume that this is a
330 // fully qualified path name to the object we want to create. We split the name
331 // into a path string and a final segment (name) and then call the "Real" Add.
332 //
333 std::string namespaceName = "/Names";
334 std::string::size_type offset = name.find (namespaceName);
335 if (offset != 0)
336 {
337 //
338 // This must be a name that has the "/Names" namespace prefix omitted.
339 // Do some reasonableness checking on the rest of the name.
340 //
341 offset = name.find ("/");
342 if (offset == 0)
343 {
344 NS_ASSERT_MSG (false, "NamesPriv::Add(): Name begins with '/' but not \"/Names\"");
345 return false;
346 }
347
348 name = "/Names/" + name;
349 }
350
351 //
352 // There must now be a fully qualified path in the string. All fully
353 // qualified names begin with "/Names". We have to split off the final
354 // segment which will become the name of the object. A '/' that
355 // separates the path from the final segment had better be there since
356 // we just made sure that at least the namespace name was there.
357 //
358 std::string::size_type i = name.rfind ("/");
359 NS_ASSERT_MSG (i != std::string::npos, "NamesPriv::Add(): Internal error. Can't find '/' in name");
360
361 //
362 // The slash we found cannot be the slash at the start of the namespaceName.
363 // This would indicate there is no name in the path at all. It can be
364 // any other index.
365 //
366 NS_ASSERT_MSG (i != 0, "NamesPriv::Add(): Can't find a name in the path string");
367
368 //
369 // We now know where the path string starts and ends, and where the
370 // name starts and ends. All we have to do is to call our available
371 // function for adding a name under a path string.
372 //
373 return Add (name.substr (0, i), name.substr (i + 1), object);
374}
375
376bool
377NamesPriv::Add (std::string path, std::string name, Ptr<Object> object)
378{
379 NS_LOG_FUNCTION (this << path << name << object);
380 if (path == "/Names")
381 {
382 return Add (Ptr<Object> (0, false), name, object);
383 }
384 return Add (Find (path), name, object);
385}
386
387bool
388NamesPriv::Add (Ptr<Object> context, std::string name, Ptr<Object> object)
389{
390 NS_LOG_FUNCTION (this << context << name << object);
391
392 if (IsNamed (object))
393 {
394 NS_LOG_LOGIC ("Object is already named");
395 return false;
396 }
397
398 NameNode *node = 0;
399 if (context)
400 {
401 node = IsNamed (context);
402 NS_ASSERT_MSG (node, "NamesPriv::Name(): context must point to a previously named node");
403 }
404 else
405 {
406 node = &m_root;
407 }
408
409 if (IsDuplicateName (node, name))
410 {
411 NS_LOG_LOGIC ("Name is already taken");
412 return false;
413 }
414
415 NameNode *newNode = new NameNode (node, name, object);
416 node->m_nameMap[name] = newNode;
417 m_objectMap[object] = newNode;
418
419 return true;
420}
421
422bool
423NamesPriv::Rename (std::string oldpath, std::string newname)
424{
425 NS_LOG_FUNCTION (this << oldpath << newname);
426 //
427 // This is the simple, easy to use version of Rename, so we want it to be
428 // flexible. We don't want to force a user to always type the fully
429 // qualified namespace name, so we allow the namespace name to be omitted.
430 // For example, calling Rename ("Client/ath0", "eth0") should result in
431 // exactly the same behavior as Rename ("/Names/Client/ath0", "eth0").
432 // Calling Rename ("Client", "Router") should have the same effect as
433 // Rename ("Names/Client", "Router")
434 //
435 // The first thing to do, then, is to "canonicalize" the input string to always
436 // be a fully qualified path.
437 //
438 // If we are given a name that begins with "/Names/" we assume that this is a
439 // fully qualified path to the object we want to change. We split the path into
440 // path string (cf directory) and a final segment (cf filename) and then call
441 // the "Real" Rename.
442 //
443 std::string namespaceName = "/Names";
444 std::string::size_type offset = oldpath.find (namespaceName);
445 if (offset != 0)
446 {
447 //
448 // This must be a name that has the "/Names" namespace prefix omitted.
449 // Do some reasonableness checking on the rest of the name.
450 //
451 offset = oldpath.find ("/");
452 if (offset == 0)
453 {
454 NS_ASSERT_MSG (false, "NamesPriv::Add(): Name begins with '/' but not \"/Names\"");
455 return false;
456 }
457
458 oldpath = "/Names/" + oldpath;
459 }
460
461 //
462 // There must now be a fully qualified path in the oldpath string. All
463 // fully qualified names begin with "/Names". We have to split off the final
464 // segment which will become the name we want to rename. A '/' that
465 // separates the path from the final segment (name) had better be there since
466 // we just made sure that at least the namespace name was there.
467 //
468 std::string::size_type i = oldpath.rfind ("/");
469 NS_ASSERT_MSG (i != std::string::npos, "NamesPriv::Add(): Internal error. Can't find '/' in name");
470
471 //
472 // The slash we found cannot be the slash at the start of the namespaceName.
473 // This would indicate there is no name in the path at all. It can be
474 // any other index.
475 //
476 NS_ASSERT_MSG (i != 0, "NamesPriv::Add(): Can't find a name in the path string");
477
478 //
479 // We now know where the path part of the string starts and ends, and where the
480 // name part starts and ends. All we have to do is to call our available
481 // function for creating adding a name under a path string.
482 //
483 return Rename (oldpath.substr (0, i), oldpath.substr (i + 1), newname);
484}
485
486bool
487NamesPriv::Rename (std::string path, std::string oldname, std::string newname)
488{
489 NS_LOG_FUNCTION (this << path << oldname << newname);
490 if (path == "/Names")
491 {
492 return Rename (Ptr<Object> (0, false), oldname, newname);
493 }
494 return Rename (Find (path), oldname, newname);
495}
496
497bool
498NamesPriv::Rename (Ptr<Object> context, std::string oldname, std::string newname)
499{
500 NS_LOG_FUNCTION (this << context << oldname << newname);
501
502 NameNode *node = 0;
503 if (context)
504 {
505 node = IsNamed (context);
506 NS_ASSERT_MSG (node, "NamesPriv::Name(): context must point to a previously named node");
507 }
508 else
509 {
510 node = &m_root;
511 }
512
513 if (IsDuplicateName (node, newname))
514 {
515 NS_LOG_LOGIC ("New name is already taken");
516 return false;
517 }
518
519 std::map<std::string, NameNode *>::iterator i = node->m_nameMap.find (oldname);
520 if (i == node->m_nameMap.end ())
521 {
522 NS_LOG_LOGIC ("Old name does not exist in name map");
523 return false;
524 }
525 else
526 {
527 NS_LOG_LOGIC ("Old name exists in name map");
528
529 //
530 // The rename process consists of:
531 // 1. Getting the pointer to the name node from the map and remembering it;
532 // 2. Removing the map entry corresponding to oldname from the map;
533 // 3. Changing the name string in the name node;
534 // 4. Adding the name node back in the map under the newname.
535 //
536 NameNode *changeNode = i->second;
537 node->m_nameMap.erase (i);
538 changeNode->m_name = newname;
539 node->m_nameMap[newname] = changeNode;
540 return true;
541 }
542}
543
544std::string
546{
547 NS_LOG_FUNCTION (this << object);
548
549 std::map<Ptr<Object>, NameNode *>::iterator i = m_objectMap.find (object);
550 if (i == m_objectMap.end ())
551 {
552 NS_LOG_LOGIC ("Object does not exist in object map");
553 return "";
554 }
555 else
556 {
557 NS_LOG_LOGIC ("Object exists in object map");
558 return i->second->m_name;
559 }
560}
561
562std::string
564{
565 NS_LOG_FUNCTION (this << object);
566
567 std::map<Ptr<Object>, NameNode *>::iterator i = m_objectMap.find (object);
568 if (i == m_objectMap.end ())
569 {
570 NS_LOG_LOGIC ("Object does not exist in object map");
571 return "";
572 }
573
574 NameNode *p = i->second;
575 NS_ASSERT_MSG (p, "NamesPriv::FindFullName(): Internal error: Invalid NameNode pointer from map");
576
577 std::string path;
578
579 do
580 {
581 path = "/" + p->m_name + path;
582 NS_LOG_LOGIC ("path is " << path);
583 }
584 while ((p = p->m_parent) != 0);
585
586 return path;
587}
588
589
591NamesPriv::Find (std::string path)
592{
593 //
594 // This is hooked in from simple, easy to use version of Find, so we want it
595 // to be flexible.
596 //
597 // If we are provided a path that doesn't begin with "/Names", we assume
598 // that the caller has simply given us a path starting with a name that
599 // is in the root namespace. This allows people to omit the "/Names" prefix.
600 // and simply do a Find ("Client/eth0") instead of having to always do a
601 // Find ("/Names/Client/eth0");
602 //
603 // So, if we are given a name that begins with "/Names/" the upshot is that we
604 // just remove that prefix and treat the rest of the string as starting with a
605 // name in the root namespace.
606 //
607
608 NS_LOG_FUNCTION (this << path);
609 std::string namespaceName = "/Names/";
610 std::string remaining;
611
612 std::string::size_type offset = path.find (namespaceName);
613 if (offset == 0)
614 {
615 NS_LOG_LOGIC (path << " is a fully qualified name");
616 remaining = path.substr (namespaceName.size ());
617 }
618 else
619 {
620 NS_LOG_LOGIC (path << " begins with a relative name");
621 remaining = path;
622 }
623
624 NameNode *node = &m_root;
625
626 //
627 // The string <remaining> is now composed entirely of path segments in
628 // the /Names name space and we have eaten the leading slash. e.g.,
629 // remaining = "ClientNode/eth0"
630 //
631 // The start of the search is always at the root of the name space.
632 //
633 for (;;)
634 {
635 NS_LOG_LOGIC ("Looking for the object of name " << remaining);
636 offset = remaining.find ("/");
637 if (offset == std::string::npos)
638 {
639 //
640 // There are no remaining slashes so this is the last segment of the
641 // specified name. We're done when we find it
642 //
643 std::map<std::string, NameNode *>::iterator i = node->m_nameMap.find (remaining);
644 if (i == node->m_nameMap.end ())
645 {
646 NS_LOG_LOGIC ("Name does not exist in name map");
647 return 0;
648 }
649 else
650 {
651 NS_LOG_LOGIC ("Name parsed, found object");
652 return i->second->m_object;
653 }
654 }
655 else
656 {
657 //
658 // There are more slashes so this is an intermediate segment of the
659 // specified name. We need to "recurse" when we find this segment.
660 //
661 offset = remaining.find ("/");
662 std::string segment = remaining.substr (0, offset);
663
664 std::map<std::string, NameNode *>::iterator i = node->m_nameMap.find (segment);
665 if (i == node->m_nameMap.end ())
666 {
667 NS_LOG_LOGIC ("Name does not exist in name map");
668 return 0;
669 }
670 else
671 {
672 node = i->second;
673 remaining = remaining.substr (offset + 1);
674 NS_LOG_LOGIC ("Intermediate segment parsed");
675 continue;
676 }
677 }
678 }
679
680 NS_ASSERT_MSG (node, "NamesPriv::Find(): Internal error: this can't happen");
681 return 0;
682}
683
685NamesPriv::Find (std::string path, std::string name)
686{
687 NS_LOG_FUNCTION (this << path << name);
688
689 if (path == "/Names")
690 {
691 return Find (Ptr<Object> (0, false), name);
692 }
693 return Find (Find (path), name);
694}
695
697NamesPriv::Find (Ptr<Object> context, std::string name)
698{
699 NS_LOG_FUNCTION (this << context << name);
700
701 NameNode *node = 0;
702
703 if (context == 0)
704 {
705 NS_LOG_LOGIC ("Zero context implies root NameNode");
706 node = &m_root;
707 }
708 else
709 {
710 node = IsNamed (context);
711 if (node == 0)
712 {
713 NS_LOG_LOGIC ("Context does not point to a previously named node");
714 return 0;
715 }
716 }
717
718 std::map<std::string, NameNode *>::iterator i = node->m_nameMap.find (name);
719 if (i == node->m_nameMap.end ())
720 {
721 NS_LOG_LOGIC ("Name does not exist in name map");
722 return 0;
723 }
724 else
725 {
726 NS_LOG_LOGIC ("Name exists in name map");
727 return i->second->m_object;
728 }
729}
730
731NameNode *
733{
734 NS_LOG_FUNCTION (this << object);
735
736 std::map<Ptr<Object>, NameNode *>::iterator i = m_objectMap.find (object);
737 if (i == m_objectMap.end ())
738 {
739 NS_LOG_LOGIC ("Object does not exist in object map, returning NameNode 0");
740 return 0;
741 }
742 else
743 {
744 NS_LOG_LOGIC ("Object exists in object map, returning NameNode " << &i->second);
745 return i->second;
746 }
747}
748
749bool
750NamesPriv::IsDuplicateName (NameNode *node, std::string name)
751{
752 NS_LOG_FUNCTION (this << node << name);
753
754 std::map<std::string, NameNode *>::iterator i = node->m_nameMap.find (name);
755 if (i == node->m_nameMap.end ())
756 {
757 NS_LOG_LOGIC ("Name does not exist in name map");
758 return false;
759 }
760 else
761 {
762 NS_LOG_LOGIC ("Name exists in name map");
763 return true;
764 }
765}
766
767void
768Names::Add (std::string name, Ptr<Object> object)
769{
770 NS_LOG_FUNCTION (name << object);
771 bool result = NamesPriv::Get ()->Add (name, object);
772 NS_ABORT_MSG_UNLESS (result, "Names::Add(): Error adding name " << name);
773}
774
775void
776Names::Rename (std::string oldpath, std::string newname)
777{
778 NS_LOG_FUNCTION (oldpath << newname);
779 bool result = NamesPriv::Get ()->Rename (oldpath, newname);
780 NS_ABORT_MSG_UNLESS (result, "Names::Rename(): Error renaming " << oldpath << " to " << newname);
781}
782
783void
784Names::Add (std::string path, std::string name, Ptr<Object> object)
785{
786 NS_LOG_FUNCTION (path << name << object);
787 bool result = NamesPriv::Get ()->Add (path, name, object);
788 NS_ABORT_MSG_UNLESS (result, "Names::Add(): Error adding " << path << " " << name);
789}
790
791void
792Names::Rename (std::string path, std::string oldname, std::string newname)
793{
794 NS_LOG_FUNCTION (path << oldname << newname);
795 bool result = NamesPriv::Get ()->Rename (path, oldname, newname);
796 NS_ABORT_MSG_UNLESS (result, "Names::Rename (): Error renaming " << path << " " << oldname << " to " << newname);
797}
798
799void
800Names::Add (Ptr<Object> context, std::string name, Ptr<Object> object)
801{
802 NS_LOG_FUNCTION (context << name << object);
803 bool result = NamesPriv::Get ()->Add (context, name, object);
804 NS_ABORT_MSG_UNLESS (result, "Names::Add(): Error adding name " << name << " under context " << &context);
805}
806
807void
808Names::Rename (Ptr<Object> context, std::string oldname, std::string newname)
809{
810 NS_LOG_FUNCTION (context << oldname << newname);
811 bool result = NamesPriv::Get ()->Rename (context, oldname, newname);
812 NS_ABORT_MSG_UNLESS (result, "Names::Rename (): Error renaming " << oldname << " to " << newname << " under context " <<
813 &context);
814}
815
816std::string
818{
819 NS_LOG_FUNCTION (object);
820 return NamesPriv::Get ()->FindName (object);
821}
822
823std::string
825{
826 NS_LOG_FUNCTION (object);
827 return NamesPriv::Get ()->FindPath (object);
828}
829
830void
832{
834 return NamesPriv::Get ()->Clear ();
835}
836
838Names::FindInternal (std::string name)
839{
840 NS_LOG_FUNCTION (name);
841 return NamesPriv::Get ()->Find (name);
842}
843
845Names::FindInternal (std::string path, std::string name)
846{
847 NS_LOG_FUNCTION (path << name);
848 return NamesPriv::Get ()->Find (path, name);
849}
850
852Names::FindInternal (Ptr<Object> context, std::string name)
853{
854 NS_LOG_FUNCTION (context << name);
855 return NamesPriv::Get ()->Find (context, name);
856}
857
858} // namespace ns3
NS_ABORT_x macro definitions.
NS_ASSERT() and NS_ASSERT_MSG() macro definitions.
Node in the naming tree.
Definition: names.cc:42
NameNode * m_parent
The parent NameNode.
Definition: names.cc:72
std::map< std::string, NameNode * > m_nameMap
Children of this NameNode.
Definition: names.cc:79
~NameNode()
Destructor.
Definition: names.cc:110
NameNode()
Default constructor.
Definition: names.cc:82
Ptr< Object > m_object
The object corresponding to this NameNode.
Definition: names.cc:76
NameNode & operator=(const NameNode &rhs)
Assignment operator.
Definition: names.cc:95
std::string m_name
The name of this NameNode.
Definition: names.cc:74
static void Rename(std::string oldpath, std::string newname)
Rename a previously associated name.
Definition: names.cc:776
static Ptr< Object > FindInternal(std::string path)
Non-templated internal version of Names::Find.
Definition: names.cc:838
static void Add(std::string name, Ptr< Object > object)
Add the association between the string "name" and the Ptr<Object> obj.
Definition: names.cc:768
static std::string FindName(Ptr< Object > object)
Given a pointer to an object, look to see if that object has a name associated with it and,...
Definition: names.cc:817
static void Clear(void)
Clear the list of objects associated with names.
Definition: names.cc:831
static std::string FindPath(Ptr< Object > object)
Given a pointer to an object, look to see if that object has a name associated with it and return the...
Definition: names.cc:824
The singleton root Names object.
Definition: names.cc:120
std::map< Ptr< Object >, NameNode * > m_objectMap
Map from object pointers to their NameNodes.
Definition: names.cc:273
bool Add(std::string name, Ptr< Object > object)
Internal implementation for Names::Add(std::string,Ptr<Object>)
Definition: names.cc:315
NameNode m_root
The root NameNode.
Definition: names.cc:270
bool IsDuplicateName(NameNode *node, std::string name)
Check if a name already exists as a child of a NameNode.
Definition: names.cc:750
std::string FindPath(Ptr< Object > object)
Internal implementation of Names::FindPath()
Definition: names.cc:563
bool Rename(std::string oldpath, std::string newname)
Internal implementation for Names::Rename(std::string,std::string)
Definition: names.cc:423
void Clear(void)
Internal implementation for Names::Clear()
Definition: names.cc:293
std::string FindName(Ptr< Object > object)
Internal implementation for Names::FindName()
Definition: names.cc:545
~NamesPriv()
Destructor.
Definition: names.cc:285
NameNode * IsNamed(Ptr< Object > object)
Check if an object has a name.
Definition: names.cc:732
NamesPriv()
Constructor.
Definition: names.cc:276
Ptr< Object > Find(std::string path)
Internal implementation for ns3::Names::Find(std::string)
Definition: names.cc:591
A template singleton.
Definition: singleton.h:61
static NamesPriv * Get(void)
Get a pointer to the singleton instance.
Definition: singleton.h:100
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition: abort.h:144
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#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 ",...
Debug message logging.
Declaration of class ns3::Names.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
ns3::Object class declaration, which is the root of the Object hierarchy and Aggregation.
ns3::Singleton declaration and template implementation.