src/core/names.cc
changeset 4151 682a4cae7a5f
parent 4149 6a3dbc49cfa9
child 4153 93bb91eae5cd
equal deleted inserted replaced
4150:682eb88ed29e 4151:682a4cae7a5f
    82 public:
    82 public:
    83   NamesPriv ();
    83   NamesPriv ();
    84   ~NamesPriv ();
    84   ~NamesPriv ();
    85 
    85 
    86   bool Add (std::string name, Ptr<Object> obj);
    86   bool Add (std::string name, Ptr<Object> obj);
       
    87   bool Add (std::string context, std::string name, Ptr<Object> object);
    87   bool Add (Ptr<Object> context, std::string name, Ptr<Object> object);
    88   bool Add (Ptr<Object> context, std::string name, Ptr<Object> object);
    88   bool Add (std::string context, std::string name, Ptr<Object> object);
       
    89   std::string FindShortName (Ptr<Object> object);
    89   std::string FindShortName (Ptr<Object> object);
    90   std::string FindFullName (Ptr<Object> object);
    90   std::string FindFullName (Ptr<Object> object);
    91   Ptr<Object> FindObjectFromFullName (std::string name);
    91   Ptr<Object> FindObjectFromFullName (std::string name);
    92   Ptr<Object> FindObjectFromShortName (Ptr<Object> context, std::string name);
    92   Ptr<Object> FindObjectFromShortName (Ptr<Object> context, std::string name);
    93 
    93 
   165 NamesPriv::Add (std::string name, Ptr<Object> object)
   165 NamesPriv::Add (std::string name, Ptr<Object> object)
   166 {
   166 {
   167   NS_LOG_FUNCTION (name << object);
   167   NS_LOG_FUNCTION (name << object);
   168   //
   168   //
   169   // This is the simple, easy to use version of Add, so we want it to be flexible.
   169   // This is the simple, easy to use version of Add, so we want it to be flexible.
   170   //
   170   // We don't want to force a user to always type the fully qualified namespace 
   171   // If we are provided a name that doesn't begin with "/Names", we assume 
   171   // name, so we allow the namespace name to be omitted.  For example, calling
   172   // that the caller has given us a shortname that she wants added to the root
   172   // Add ("Client/ath0", obj) should result in exactly the same behavior as
   173   // namespace.  This results in a call to the "real" Add with context set to 
   173   // Add ("/Names/Client/ath0", obj).  Calling Add ("Client", obj) should have
   174   // zero, indicating what we want to do.
   174   // the same effect as Add ("Names/Client", obj)
       
   175   //
       
   176   // The first thing to do, then, is to "canonicalize" the input string to always
       
   177   // be a fully qualified name.
   175   //
   178   //
   176   // If we are given a name that begins with "/Names/" we assume that this is a
   179   // If we are given a name that begins with "/Names/" we assume that this is a
   177   // fullname to the object we want to create.  We split the fullname into a 
   180   // fullname to the object we want to create.  We split the fullname into a 
   178   // context string and and a final segment and then call the "Real" Add.
   181   // context string and and a final segment and then call the "Real" Add.
   179   //
   182   //
   180   std::string namespaceName = "/Names";
   183   std::string namespaceName = "/Names";
   181   std::string::size_type offset = name.find (namespaceName);
   184   std::string::size_type offset = name.find (namespaceName);
   182   if (offset == 0)
   185   if (offset != 0)
   183     {
   186     {
   184       //
   187       //
   185       // This must be a fully qualified longname.  All fully qualified names begin
   188       // This must be a name that has the "/Names" namespace prefix omitted.  
   186       // with "/Names".  We have to split off the final segment which will become
   189       // Do some reasonableness checking on the rest of the name.
   187       // the shortname of the object.
       
   188       //
   190       //
   189       std::string::size_type i = name.rfind ("/");
   191       offset = name.find ("/");
   190       NS_ASSERT_MSG (i != std::string::npos, "NamesPriv::Add(): Internal error.  Can't find '/' in name");
   192       if (offset == 0)
   191 
   193         {
   192       //
   194           NS_ASSERT_MSG (false, "NamesPriv::Add(): Name begins with '/' but not \"/Names\"");
   193       // The slash we found cannot be the slash at the start of the namespaceName.
   195           return false;
   194       // This would indicate there is no shortname in the path at all.
   196         }
   195       //
   197 
   196       NS_ASSERT_MSG (i != 0, "NamesPriv::Add(): Can't find a shortname in the name string");
   198       name = "/Names/" + name;
   197 
   199     }
   198       //
   200   
   199       // We now know where the context string starts and ends, and where the
   201   //
   200       // shortname starts and ends.  All we have to do is to call our available
   202   // There must now be a fully qualified longname in the string.  All fully 
   201       // function for creating addubg a shortname under a context string.
   203   // qualified names begin with "/Names".  We have to split off the final 
   202       //
   204   // segment which will become the shortname of the object.  A '/' that
   203       return Add (name.substr (0, i), name.substr (i + 1), object);
   205   // separates the context from the final segment had better be there since
   204     }
   206   // we just made sure that at least the namespace name was there.
   205   else
   207   //
   206     {
   208   std::string::size_type i = name.rfind ("/");
   207       //
   209   NS_ASSERT_MSG (i != std::string::npos, "NamesPriv::Add(): Internal error.  Can't find '/' in name");
   208       // This must be a shortname.  Shortnames can't have ANY '/' characters in
   210 
   209       // them since they are interpreted as a final segment of a fullname.  A 
   211   //
   210       // shortname in this context means creating a name in the root namespace.
   212   // The slash we found cannot be the slash at the start of the namespaceName.
   211       // We indicate this by passing a zero context to the "real" add.
   213   // This would indicate there is no shortname in the path at all.  It can be
   212       //
   214   // any other index.
   213       NS_ASSERT_MSG (offset == std::string::npos, "NamesPriv::Add(): Unexpected '/' in shortname");
   215   //
   214       return Add (Ptr<Object> (0, false), name, object);
   216   NS_ASSERT_MSG (i != 0, "NamesPriv::Add(): Can't find a shortname in the name string");
   215     }
   217 
       
   218   //
       
   219   // We now know where the context string starts and ends, and where the
       
   220   // shortname starts and ends.  All we have to do is to call our available
       
   221   // function for creating addubg a shortname under a context string.
       
   222   //
       
   223   return Add (name.substr (0, i), name.substr (i + 1), object);
   216 }
   224 }
   217 
   225 
   218 bool
   226 bool
   219 NamesPriv::Add (std::string context, std::string name, Ptr<Object> object)
   227 NamesPriv::Add (std::string context, std::string name, Ptr<Object> object)
   220 {
   228 {
   681 
   689 
   682   foundObject = Names::Find<TestObject> ("Server/eth0");
   690   foundObject = Names::Find<TestObject> ("Server/eth0");
   683   NS_TEST_ASSERT_EQUAL (foundObject, serverEth0);
   691   NS_TEST_ASSERT_EQUAL (foundObject, serverEth0);
   684 
   692 
   685   //
   693   //
       
   694   // We should be able to add objects while including the root of the namespace
       
   695   // in the name.
       
   696   //
       
   697   Ptr<TestObject> router1 = CreateObject<TestObject> ();
       
   698   result = Names::Add ("/Names/Router1", router1);
       
   699   NS_TEST_ASSERT_EQUAL (result, true);
       
   700 
       
   701   //
       
   702   // We should be able to add objects while not including the root of the namespace
       
   703   // in the name.
       
   704   //
       
   705   Ptr<TestObject> router2 = CreateObject<TestObject> ();
       
   706   result = Names::Add ("Router2", router2);
       
   707   NS_TEST_ASSERT_EQUAL (result, true);
       
   708 
       
   709   //
       
   710   // We should be able to add sub-objects while including the root of the namespace
       
   711   // in the name.
       
   712   //
       
   713   Ptr<TestObject> router1Eth0 = CreateObject<TestObject> ();
       
   714   result = Names::Add ("/Names/Router1/eth0", router1Eth0);
       
   715   NS_TEST_ASSERT_EQUAL (result, true);
       
   716 
       
   717   //
       
   718   // We should be able to add sub-objects while not including the root of the namespace
       
   719   // in the name.
       
   720   //
       
   721   Ptr<TestObject> router2Eth0 = CreateObject<TestObject> ();
       
   722   result = Names::Add ("Router2/eth0", router2Eth0);
       
   723   NS_TEST_ASSERT_EQUAL (result, true);
       
   724 
       
   725   //
       
   726   // We should be able to find these objects in the same two ways
       
   727   //
       
   728   foundObject = Names::Find<TestObject> ("/Names/Router1");
       
   729   NS_TEST_ASSERT_EQUAL (foundObject, router1);
       
   730 
       
   731   foundObject = Names::Find<TestObject> ("Router1");
       
   732   NS_TEST_ASSERT_EQUAL (foundObject, router1);
       
   733 
       
   734   foundObject = Names::Find<TestObject> ("/Names/Router2");
       
   735   NS_TEST_ASSERT_EQUAL (foundObject, router2);
       
   736 
       
   737   foundObject = Names::Find<TestObject> ("Router2");
       
   738   NS_TEST_ASSERT_EQUAL (foundObject, router2);
       
   739 
       
   740   foundObject = Names::Find<TestObject> ("/Names/Router1/eth0");
       
   741   NS_TEST_ASSERT_EQUAL (foundObject, router1Eth0);
       
   742 
       
   743   foundObject = Names::Find<TestObject> ("Router1/eth0");
       
   744   NS_TEST_ASSERT_EQUAL (foundObject, router1Eth0);
       
   745 
       
   746   foundObject = Names::Find<TestObject> ("/Names/Router2/eth0");
       
   747   NS_TEST_ASSERT_EQUAL (foundObject, router2Eth0);
       
   748 
       
   749   foundObject = Names::Find<TestObject> ("Router2/eth0");
       
   750   NS_TEST_ASSERT_EQUAL (foundObject, router2Eth0);
       
   751 
       
   752   //
   686   // We also have some syntactically sugary methods, so make sure they do what
   753   // We also have some syntactically sugary methods, so make sure they do what
   687   // they should as well.
   754   // they should as well.
   688   //
   755   //
   689   Ptr<TestObject> bridge = CreateObject<TestObject> ();
   756   Ptr<TestObject> bridge = CreateObject<TestObject> ();
   690   result = Names::Add ("/Names", "Bridge", bridge);
   757   result = Names::Add ("/Names", "Bridge", bridge);