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