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 
34 namespace ns3 {
35 
36 NS_LOG_COMPONENT_DEFINE ("Names");
37 
42 class NameNode
43 {
44 public:
46  NameNode ();
52  NameNode (const NameNode &nameNode);
60  NameNode (NameNode *parent, std::string name, Ptr<Object> object);
67  NameNode &operator = (const NameNode &rhs);
68 
70  ~NameNode ();
71 
75  std::string m_name;
78 
80  std::map<std::string, NameNode *> m_nameMap;
81 };
82 
84  : m_parent (0), m_name (""), m_object (0)
85 {
86 }
87 
88 NameNode::NameNode (const NameNode &nameNode)
89 {
90  m_parent = nameNode.m_parent;
91  m_name = nameNode.m_name;
92  m_object = nameNode.m_object;
93  m_nameMap = nameNode.m_nameMap;
94 }
95 
96 NameNode &
98 {
99  m_parent = rhs.m_parent;
100  m_name = rhs.m_name;
101  m_object = rhs.m_object;
102  m_nameMap = rhs.m_nameMap;
103  return *this;
104 }
105 
106 NameNode::NameNode (NameNode *parent, std::string name, Ptr<Object> object)
107  : m_parent (parent), m_name (name), m_object (object)
108 {
109  NS_LOG_FUNCTION (this << parent << name << object);
110 }
111 
113 {
114  NS_LOG_FUNCTION (this);
115 }
116 
121 class NamesPriv : public Singleton<NamesPriv>
122 {
123 public:
125  NamesPriv ();
127  ~NamesPriv ();
128 
133  bool Add (std::string name, Ptr<Object> object);
138  bool Add (std::string path, std::string name, Ptr<Object> object);
143  bool Add (Ptr<Object> context, std::string name, Ptr<Object> object);
144 
149  bool Rename (std::string oldpath, std::string newname);
154  bool Rename (std::string path, std::string oldname, std::string newname);
159  bool Rename (Ptr<Object> context, std::string oldname, std::string newname);
160 
162  std::string FindName (Ptr<Object> object);
164  std::string FindPath (Ptr<Object> object);
165 
167  void Clear (void);
168 
170  Ptr<Object> Find (std::string path);
172  Ptr<Object> Find (std::string path, std::string name);
174  Ptr<Object> Find (Ptr<Object> context, std::string name);
175 
176 private:
177  friend class Names;
178 
185  NameNode *IsNamed (Ptr<Object> object);
193  bool IsDuplicateName (NameNode *node, std::string name);
194 
197 
199  std::map<Ptr<Object>, NameNode *> m_objectMap;
200 };
201 
203 {
204  NS_LOG_FUNCTION (this);
205 
206  m_root.m_parent = 0;
207  m_root.m_name = "Names";
208  m_root.m_object = 0;
209 }
210 
212 {
213  NS_LOG_FUNCTION (this);
214  Clear ();
215  m_root.m_name = "";
216 }
217 
218 void
220 {
221  NS_LOG_FUNCTION (this);
222  //
223  // Every name is associated with an object in the object map, so freeing the
224  // NameNodes in this map will free all of the memory allocated for the NameNodes
225  //
226  for (std::map<Ptr<Object>, NameNode *>::iterator i = m_objectMap.begin (); i != m_objectMap.end (); ++i)
227  {
228  delete i->second;
229  i->second = 0;
230  }
231 
232  m_objectMap.clear ();
233 
234  m_root.m_parent = 0;
235  m_root.m_name = "Names";
236  m_root.m_object = 0;
237  m_root.m_nameMap.clear ();
238 }
239 
240 bool
241 NamesPriv::Add (std::string name, Ptr<Object> object)
242 {
243  NS_LOG_FUNCTION (this << name << object);
244  //
245  // This is the simple, easy to use version of Add, so we want it to be flexible.
246  // We don't want to force a user to always type the fully qualified namespace
247  // name, so we allow the namespace name to be omitted. For example, calling
248  // Add ("Client/ath0", obj) should result in exactly the same behavior as
249  // Add ("/Names/Client/ath0", obj). Calling Add ("Client", obj) should have
250  // the same effect as Add ("Names/Client", obj)
251  //
252  // The first thing to do, then, is to "canonicalize" the input string to always
253  // be a fully qualified name.
254  //
255  // If we are given a name that begins with "/Names/" we assume that this is a
256  // fully qualified path name to the object we want to create. We split the name
257  // into a path string and and a final segment (name) and then call the "Real" Add.
258  //
259  std::string namespaceName = "/Names";
260  std::string::size_type offset = name.find (namespaceName);
261  if (offset != 0)
262  {
263  //
264  // This must be a name that has the "/Names" namespace prefix omitted.
265  // Do some reasonableness checking on the rest of the name.
266  //
267  offset = name.find ("/");
268  if (offset == 0)
269  {
270  NS_ASSERT_MSG (false, "NamesPriv::Add(): Name begins with '/' but not \"/Names\"");
271  return false;
272  }
273 
274  name = "/Names/" + name;
275  }
276 
277  //
278  // There must now be a fully qualified path in the string. All fully
279  // qualified names begin with "/Names". We have to split off the final
280  // segment which will become the name of the object. A '/' that
281  // separates the path from the final segment had better be there since
282  // we just made sure that at least the namespace name was there.
283  //
284  std::string::size_type i = name.rfind ("/");
285  NS_ASSERT_MSG (i != std::string::npos, "NamesPriv::Add(): Internal error. Can't find '/' in name");
286 
287  //
288  // The slash we found cannot be the slash at the start of the namespaceName.
289  // This would indicate there is no name in the path at all. It can be
290  // any other index.
291  //
292  NS_ASSERT_MSG (i != 0, "NamesPriv::Add(): Can't find a name in the path string");
293 
294  //
295  // We now know where the path string starts and ends, and where the
296  // name starts and ends. All we have to do is to call our available
297  // function for adding a name under a path string.
298  //
299  return Add (name.substr (0, i), name.substr (i + 1), object);
300 }
301 
302 bool
303 NamesPriv::Add (std::string path, std::string name, Ptr<Object> object)
304 {
305  NS_LOG_FUNCTION (this << path << name << object);
306  if (path == "/Names")
307  {
308  return Add (Ptr<Object> (0, false), name, object);
309  }
310  return Add (Find (path), name, object);
311 }
312 
313 bool
314 NamesPriv::Add (Ptr<Object> context, std::string name, Ptr<Object> object)
315 {
316  NS_LOG_FUNCTION (this << context << name << object);
317 
318  if (IsNamed (object))
319  {
320  NS_LOG_LOGIC ("Object is already named");
321  return false;
322  }
323 
324  NameNode *node = 0;
325  if (context)
326  {
327  node = IsNamed (context);
328  NS_ASSERT_MSG (node, "NamesPriv::Name(): context must point to a previously named node");
329  }
330  else
331  {
332  node = &m_root;
333  }
334 
335  if (IsDuplicateName (node, name))
336  {
337  NS_LOG_LOGIC ("Name is already taken");
338  return false;
339  }
340 
341  NameNode *newNode = new NameNode (node, name, object);
342  node->m_nameMap[name] = newNode;
343  m_objectMap[object] = newNode;
344 
345  return true;
346 }
347 
348 bool
349 NamesPriv::Rename (std::string oldpath, std::string newname)
350 {
351  NS_LOG_FUNCTION (this << oldpath << newname);
352  //
353  // This is the simple, easy to use version of Rename, so we want it to be
354  // flexible. We don't want to force a user to always type the fully
355  // qualified namespace name, so we allow the namespace name to be omitted.
356  // For example, calling Rename ("Client/ath0", "eth0") should result in
357  // exactly the same behavior as Rename ("/Names/Client/ath0", "eth0").
358  // Calling Rename ("Client", "Router") should have the same effect as
359  // Rename ("Names/Client", "Router")
360  //
361  // The first thing to do, then, is to "canonicalize" the input string to always
362  // be a fully qualified path.
363  //
364  // If we are given a name that begins with "/Names/" we assume that this is a
365  // fully qualified path to the object we want to change. We split the path into
366  // path string (cf directory) and and a final segment (cf filename) and then call
367  // the "Real" Rename.
368  //
369  std::string namespaceName = "/Names";
370  std::string::size_type offset = oldpath.find (namespaceName);
371  if (offset != 0)
372  {
373  //
374  // This must be a name that has the "/Names" namespace prefix omitted.
375  // Do some reasonableness checking on the rest of the name.
376  //
377  offset = oldpath.find ("/");
378  if (offset == 0)
379  {
380  NS_ASSERT_MSG (false, "NamesPriv::Add(): Name begins with '/' but not \"/Names\"");
381  return false;
382  }
383 
384  oldpath = "/Names/" + oldpath;
385  }
386 
387  //
388  // There must now be a fully qualified path in the oldpath string. All
389  // fully qualified names begin with "/Names". We have to split off the final
390  // segment which will become the name we want to rename. A '/' that
391  // separates the path from the final segment (name) had better be there since
392  // we just made sure that at least the namespace name was there.
393  //
394  std::string::size_type i = oldpath.rfind ("/");
395  NS_ASSERT_MSG (i != std::string::npos, "NamesPriv::Add(): Internal error. Can't find '/' in name");
396 
397  //
398  // The slash we found cannot be the slash at the start of the namespaceName.
399  // This would indicate there is no name in the path at all. It can be
400  // any other index.
401  //
402  NS_ASSERT_MSG (i != 0, "NamesPriv::Add(): Can't find a name in the path string");
403 
404  //
405  // We now know where the path part of the string starts and ends, and where the
406  // name part starts and ends. All we have to do is to call our available
407  // function for creating adding a name under a path string.
408  //
409  return Rename (oldpath.substr (0, i), oldpath.substr (i + 1), newname);
410 }
411 
412 bool
413 NamesPriv::Rename (std::string path, std::string oldname, std::string newname)
414 {
415  NS_LOG_FUNCTION (this << path << oldname << newname);
416  if (path == "/Names")
417  {
418  return Rename (Ptr<Object> (0, false), oldname, newname);
419  }
420  return Rename (Find (path), oldname, newname);
421 }
422 
423 bool
424 NamesPriv::Rename (Ptr<Object> context, std::string oldname, std::string newname)
425 {
426  NS_LOG_FUNCTION (this << context << oldname << newname);
427 
428  NameNode *node = 0;
429  if (context)
430  {
431  node = IsNamed (context);
432  NS_ASSERT_MSG (node, "NamesPriv::Name(): context must point to a previously named node");
433  }
434  else
435  {
436  node = &m_root;
437  }
438 
439  if (IsDuplicateName (node, newname))
440  {
441  NS_LOG_LOGIC ("New name is already taken");
442  return false;
443  }
444 
445  std::map<std::string, NameNode *>::iterator i = node->m_nameMap.find (oldname);
446  if (i == node->m_nameMap.end ())
447  {
448  NS_LOG_LOGIC ("Old name does not exist in name map");
449  return false;
450  }
451  else
452  {
453  NS_LOG_LOGIC ("Old name exists in name map");
454 
455  //
456  // The rename process consists of:
457  // 1. Geting the pointer to the name node from the map and remembering it;
458  // 2. Removing the map entry corresponding to oldname from the map;
459  // 3. Changing the name string in the name node;
460  // 4. Adding the name node back in the map under the newname.
461  //
462  NameNode *changeNode = i->second;
463  node->m_nameMap.erase (i);
464  changeNode->m_name = newname;
465  node->m_nameMap[newname] = changeNode;
466  return true;
467  }
468 }
469 
470 std::string
472 {
473  NS_LOG_FUNCTION (this << object);
474 
475  std::map<Ptr<Object>, NameNode *>::iterator i = m_objectMap.find (object);
476  if (i == m_objectMap.end ())
477  {
478  NS_LOG_LOGIC ("Object does not exist in object map");
479  return "";
480  }
481  else
482  {
483  NS_LOG_LOGIC ("Object exists in object map");
484  return i->second->m_name;
485  }
486 }
487 
488 std::string
490 {
491  NS_LOG_FUNCTION (this << object);
492 
493  std::map<Ptr<Object>, NameNode *>::iterator i = m_objectMap.find (object);
494  if (i == m_objectMap.end ())
495  {
496  NS_LOG_LOGIC ("Object does not exist in object map");
497  return "";
498  }
499 
500  NameNode *p = i->second;
501  NS_ASSERT_MSG (p, "NamesPriv::FindFullName(): Internal error: Invalid NameNode pointer from map");
502 
503  std::string path;
504 
505  do
506  {
507  path = "/" + p->m_name + path;
508  NS_LOG_LOGIC ("path is " << path);
509  }
510  while ((p = p->m_parent) != 0);
511 
512  return path;
513 }
514 
515 
517 NamesPriv::Find (std::string path)
518 {
519  //
520  // This is hooked in from simple, easy to use version of Find, so we want it
521  // to be flexible.
522  //
523  // If we are provided a path that doesn't begin with "/Names", we assume
524  // that the caller has simply given us a path starting with a name that
525  // is in the root namespace. This allows peole to omit the "/Names" prefix.
526  // and simply do a Find ("Client/eth0") instead of having to always do a
527  // Find ("/Names/Client/eth0");
528  //
529  // So, if we are given a name that begins with "/Names/" the upshot is that we
530  // just remove that prefix and treat the rest of the string as starting with a
531  // name in the root namespace.
532  //
533 
534  NS_LOG_FUNCTION (this << path);
535  std::string namespaceName = "/Names/";
536  std::string remaining;
537 
538  std::string::size_type offset = path.find (namespaceName);
539  if (offset == 0)
540  {
541  NS_LOG_LOGIC (path << " is a fully qualified name");
542  remaining = path.substr (namespaceName.size ());
543  }
544  else
545  {
546  NS_LOG_LOGIC (path << " begins with a relative name");
547  remaining = path;
548  }
549 
550  NameNode *node = &m_root;
551 
552  //
553  // The string <remaining> is now composed entirely of path segments in
554  // the /Names name space and we have eaten the leading slash. e.g.,
555  // remaining = "ClientNode/eth0"
556  //
557  // The start of the search is always at the root of the name space.
558  //
559  for (;;)
560  {
561  NS_LOG_LOGIC ("Looking for the object of name " << remaining);
562  offset = remaining.find ("/");
563  if (offset == std::string::npos)
564  {
565  //
566  // There are no remaining slashes so this is the last segment of the
567  // specified name. We're done when we find it
568  //
569  std::map<std::string, NameNode *>::iterator i = node->m_nameMap.find (remaining);
570  if (i == node->m_nameMap.end ())
571  {
572  NS_LOG_LOGIC ("Name does not exist in name map");
573  return 0;
574  }
575  else
576  {
577  NS_LOG_LOGIC ("Name parsed, found object");
578  return i->second->m_object;
579  }
580  }
581  else
582  {
583  //
584  // There are more slashes so this is an intermediate segment of the
585  // specified name. We need to "recurse" when we find this segment.
586  //
587  offset = remaining.find ("/");
588  std::string segment = remaining.substr (0, offset);
589 
590  std::map<std::string, NameNode *>::iterator i = node->m_nameMap.find (segment);
591  if (i == node->m_nameMap.end ())
592  {
593  NS_LOG_LOGIC ("Name does not exist in name map");
594  return 0;
595  }
596  else
597  {
598  node = i->second;
599  remaining = remaining.substr (offset + 1);
600  NS_LOG_LOGIC ("Intermediate segment parsed");
601  continue;
602  }
603  }
604  }
605 
606  NS_ASSERT_MSG (node, "NamesPriv::Find(): Internal error: this can't happen");
607  return 0;
608 }
609 
611 NamesPriv::Find (std::string path, std::string name)
612 {
613  NS_LOG_FUNCTION (this << path << name);
614 
615  if (path == "/Names")
616  {
617  return Find (Ptr<Object> (0, false), name);
618  }
619  return Find (Find (path), name);
620 }
621 
623 NamesPriv::Find (Ptr<Object> context, std::string name)
624 {
625  NS_LOG_FUNCTION (this << context << name);
626 
627  NameNode *node = 0;
628 
629  if (context == 0)
630  {
631  NS_LOG_LOGIC ("Zero context implies root NameNode");
632  node = &m_root;
633  }
634  else
635  {
636  node = IsNamed (context);
637  if (node == 0)
638  {
639  NS_LOG_LOGIC ("Context does not point to a previously named node");
640  return 0;
641  }
642  }
643 
644  std::map<std::string, NameNode *>::iterator i = node->m_nameMap.find (name);
645  if (i == node->m_nameMap.end ())
646  {
647  NS_LOG_LOGIC ("Name does not exist in name map");
648  return 0;
649  }
650  else
651  {
652  NS_LOG_LOGIC ("Name exists in name map");
653  return i->second->m_object;
654  }
655 }
656 
657 NameNode *
659 {
660  NS_LOG_FUNCTION (this << object);
661 
662  std::map<Ptr<Object>, NameNode *>::iterator i = m_objectMap.find (object);
663  if (i == m_objectMap.end ())
664  {
665  NS_LOG_LOGIC ("Object does not exist in object map, returning NameNode 0");
666  return 0;
667  }
668  else
669  {
670  NS_LOG_LOGIC ("Object exists in object map, returning NameNode " << &i->second);
671  return i->second;
672  }
673 }
674 
675 bool
676 NamesPriv::IsDuplicateName (NameNode *node, std::string name)
677 {
678  NS_LOG_FUNCTION (this << node << name);
679 
680  std::map<std::string, NameNode *>::iterator i = node->m_nameMap.find (name);
681  if (i == node->m_nameMap.end ())
682  {
683  NS_LOG_LOGIC ("Name does not exist in name map");
684  return false;
685  }
686  else
687  {
688  NS_LOG_LOGIC ("Name exists in name map");
689  return true;
690  }
691 }
692 
693 void
694 Names::Add (std::string name, Ptr<Object> object)
695 {
696  NS_LOG_FUNCTION (name << object);
697  bool result = NamesPriv::Get ()->Add (name, object);
698  NS_ABORT_MSG_UNLESS (result, "Names::Add(): Error adding name " << name);
699 }
700 
701 void
702 Names::Rename (std::string oldpath, std::string newname)
703 {
704  NS_LOG_FUNCTION (oldpath << newname);
705  bool result = NamesPriv::Get ()->Rename (oldpath, newname);
706  NS_ABORT_MSG_UNLESS (result, "Names::Rename(): Error renaming " << oldpath << " to " << newname);
707 }
708 
709 void
710 Names::Add (std::string path, std::string name, Ptr<Object> object)
711 {
712  NS_LOG_FUNCTION (path << name << object);
713  bool result = NamesPriv::Get ()->Add (path, name, object);
714  NS_ABORT_MSG_UNLESS (result, "Names::Add(): Error adding " << path << " " << name);
715 }
716 
717 void
718 Names::Rename (std::string path, std::string oldname, std::string newname)
719 {
720  NS_LOG_FUNCTION (path << oldname << newname);
721  bool result = NamesPriv::Get ()->Rename (path, oldname, newname);
722  NS_ABORT_MSG_UNLESS (result, "Names::Rename (): Error renaming " << path << " " << oldname << " to " << newname);
723 }
724 
725 void
726 Names::Add (Ptr<Object> context, std::string name, Ptr<Object> object)
727 {
728  NS_LOG_FUNCTION (context << name << object);
729  bool result = NamesPriv::Get ()->Add (context, name, object);
730  NS_ABORT_MSG_UNLESS (result, "Names::Add(): Error adding name " << name << " under context " << &context);
731 }
732 
733 void
734 Names::Rename (Ptr<Object> context, std::string oldname, std::string newname)
735 {
736  NS_LOG_FUNCTION (context << oldname << newname);
737  bool result = NamesPriv::Get ()->Rename (context, oldname, newname);
738  NS_ABORT_MSG_UNLESS (result, "Names::Rename (): Error renaming " << oldname << " to " << newname << " under context " <<
739  &context);
740 }
741 
742 std::string
744 {
745  NS_LOG_FUNCTION (object);
746  return NamesPriv::Get ()->FindName (object);
747 }
748 
749 std::string
751 {
752  NS_LOG_FUNCTION (object);
753  return NamesPriv::Get ()->FindPath (object);
754 }
755 
756 void
758 {
760  return NamesPriv::Get ()->Clear ();
761 }
762 
764 Names::FindInternal (std::string name)
765 {
766  NS_LOG_FUNCTION (name);
767  return NamesPriv::Get ()->Find (name);
768 }
769 
771 Names::FindInternal (std::string path, std::string name)
772 {
773  NS_LOG_FUNCTION (path << name);
774  return NamesPriv::Get ()->Find (path, name);
775 }
776 
778 Names::FindInternal (Ptr<Object> context, std::string name)
779 {
780  NS_LOG_FUNCTION (context << name);
781  return NamesPriv::Get ()->Find (context, name);
782 }
783 
784 } // namespace ns3
Ptr< Object > m_object
The object corresponding to this NameNode.
Definition: names.cc:77
The singleton root Names object.
Definition: names.cc:121
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
ns3::Singleton declaration and template implementation.
std::map< std::string, NameNode * > m_nameMap
Children of this NameNode.
Definition: names.cc:80
Node in the naming tree.
Definition: names.cc:42
NameNode * IsNamed(Ptr< Object > object)
Check if an object has a name.
Definition: names.cc:658
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
~NameNode()
Destructor.
Definition: names.cc:112
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
NameNode * m_parent
The parent NameNode.
Definition: names.cc:73
static NamesPriv * Get(void)
Get a pointer to the singleton instance.
Ptr< Object > Find(std::string path)
Given a name path string, look to see if there's an object in the system with that associated to it...
Definition: names.cc:517
~NamesPriv()
Destructor.
Definition: names.cc:211
static void Add(std::string name, Ptr< Object > object)
Add the association between the string "name" and the Ptr obj.
Definition: names.cc:694
A template singleton.
Definition: singleton.h:63
A directory of name and Ptr associations that allows us to give any ns3 Object a name...
Definition: names.h:38
static void Clear(void)
Clear the list of objects associated with names.
Definition: names.cc:757
bool Rename(std::string oldpath, std::string newname)
Rename a previously associated name.
Definition: names.cc:349
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:489
Definition of assertion macros NS_ASSERT() and NS_ASSERT_MSG().
std::string m_name
The name of this NameNode.
Definition: names.cc:75
void Clear(void)
Clear the list of objects associated with names.
Definition: names.cc:219
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:471
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:252
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static void Rename(std::string oldpath, std::string newname)
Rename a previously associated name.
Definition: names.cc:702
NameNode & operator=(const NameNode &rhs)
Assignment operator.
Definition: names.cc:97
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:750
#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:90
ns3::Object class declaration, which is the root of the Object hierarchy and Aggregation.
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition: abort.h:144
std::map< Ptr< Object >, NameNode * > m_objectMap
Map from object pointers to their NameNodes.
Definition: names.cc:199
NameNode m_root
The root NameNode.
Definition: names.cc:196
NameNode()
Default constructor.
Definition: names.cc:83
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:743
Declaration of class ns3::Names.
bool Add(std::string name, Ptr< Object > object)
Add the association between the string "name" and the Ptr obj.
Definition: names.cc:241
Debug message logging.
NamesPriv()
Constructor.
Definition: names.cc:202
static Ptr< Object > FindInternal(std::string path)
Non-templated internal version of Names::Find.
Definition: names.cc:764
bool IsDuplicateName(NameNode *node, std::string name)
Check if a name already exists as a child of a NameNode.
Definition: names.cc:676
NS_ABORT_x macro definitions.