bug 284: cannot use config paths to get a handle on an object.
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Fri, 24 Oct 2008 12:35:28 +0200
changeset 3787985324e2caaa
parent 3786 9f384deadb46
child 3788 eb2748908cc6
bug 284: cannot use config paths to get a handle on an object.
src/core/config.cc
src/core/config.h
     1.1 --- a/src/core/config.cc	Fri Oct 24 12:31:57 2008 +0200
     1.2 +++ b/src/core/config.cc	Fri Oct 24 12:35:28 2008 +0200
     1.3 @@ -30,6 +30,100 @@
     1.4  
     1.5  namespace ns3 {
     1.6  
     1.7 +namespace Config {
     1.8 +
     1.9 +MatchContainer::MatchContainer ()
    1.10 +{}
    1.11 +MatchContainer::MatchContainer (const std::vector<Ptr<Object> > &objects, 
    1.12 +                                const std::vector<std::string> &contexts,
    1.13 +                                std::string path)
    1.14 +  : m_objects (objects),
    1.15 +    m_contexts (contexts),
    1.16 +    m_path (path)
    1.17 +{}
    1.18 +MatchContainer::Iterator 
    1.19 +MatchContainer::Begin (void) const
    1.20 +{
    1.21 +  return m_objects.begin ();
    1.22 +}
    1.23 +MatchContainer::Iterator 
    1.24 +MatchContainer::End (void) const
    1.25 +{
    1.26 +  return m_objects.end ();
    1.27 +}
    1.28 +uint32_t 
    1.29 +MatchContainer::GetN (void) const
    1.30 +{
    1.31 +  return m_objects.size ();
    1.32 +}
    1.33 +Ptr<Object> 
    1.34 +MatchContainer::Get (uint32_t i) const
    1.35 +{
    1.36 +  return m_objects[i];
    1.37 +}
    1.38 +std::string 
    1.39 +MatchContainer::GetMatchedPath (uint32_t i) const
    1.40 +{
    1.41 +  return m_contexts[i];
    1.42 +}
    1.43 +std::string 
    1.44 +MatchContainer::GetPath (void) const
    1.45 +{
    1.46 +  return m_path;
    1.47 +}
    1.48 +
    1.49 +void 
    1.50 +MatchContainer::Set (std::string name, const AttributeValue &value)
    1.51 +{
    1.52 +  for (Iterator tmp = Begin (); tmp != End (); ++tmp)
    1.53 +    {
    1.54 +      Ptr<Object> object = *tmp;
    1.55 +      object->SetAttribute (name, value);
    1.56 +    }
    1.57 +}
    1.58 +void 
    1.59 +MatchContainer::Connect (std::string name, const CallbackBase &cb)
    1.60 +{
    1.61 +  NS_ASSERT (m_objects.size () == m_contexts.size ());
    1.62 +  for (uint32_t i = 0; i < m_objects.size (); ++i)
    1.63 +    {
    1.64 +      Ptr<Object> object = m_objects[i];
    1.65 +      std::string ctx = m_contexts[i] + name;
    1.66 +      object->TraceConnect (name, ctx, cb);
    1.67 +    }
    1.68 +}
    1.69 +void 
    1.70 +MatchContainer::ConnectWithoutContext (std::string name, const CallbackBase &cb)
    1.71 +{
    1.72 +  for (Iterator tmp = Begin (); tmp != End (); ++tmp)
    1.73 +    {
    1.74 +      Ptr<Object> object = *tmp;
    1.75 +      object->TraceConnectWithoutContext (name, cb);
    1.76 +    }
    1.77 +}
    1.78 +void 
    1.79 +MatchContainer::Disconnect (std::string name, const CallbackBase &cb)
    1.80 +{
    1.81 +  NS_ASSERT (m_objects.size () == m_contexts.size ());
    1.82 +  for (uint32_t i = 0; i < m_objects.size (); ++i)
    1.83 +    {
    1.84 +      Ptr<Object> object = m_objects[i];
    1.85 +      std::string ctx = m_contexts[i] + name;
    1.86 +      object->TraceDisconnect (name, ctx, cb);
    1.87 +    }
    1.88 +}
    1.89 +void 
    1.90 +MatchContainer::DisconnectWithoutContext (std::string name, const CallbackBase &cb)
    1.91 +{
    1.92 +  for (Iterator tmp = Begin (); tmp != End (); ++tmp)
    1.93 +    {
    1.94 +      Ptr<Object> object = *tmp;
    1.95 +      object->TraceDisconnectWithoutContext (name, cb);
    1.96 +    }
    1.97 +}
    1.98 +
    1.99 +} // namespace Config
   1.100 +
   1.101  class ArrayMatcher
   1.102  {
   1.103  public:
   1.104 @@ -125,20 +219,40 @@
   1.105  
   1.106    void Resolve (Ptr<Object> root);
   1.107  private:
   1.108 +  void Canonicalize (void);
   1.109    void DoResolve (std::string path, Ptr<Object> root);
   1.110    void DoArrayResolve (std::string path, const ObjectVectorValue &vector);
   1.111 -  void DoResolveOne (Ptr<Object> object, std::string name);
   1.112 -  std::string GetResolvedPath (std::string name) const;
   1.113 -  virtual void DoOne (Ptr<Object> object, std::string path, std::string name) = 0;
   1.114 +  void DoResolveOne (Ptr<Object> object);
   1.115 +  std::string GetResolvedPath (void) const;
   1.116 +  virtual void DoOne (Ptr<Object> object, std::string path) = 0;
   1.117    std::vector<std::string> m_workStack;
   1.118    std::string m_path;
   1.119  };
   1.120  
   1.121  Resolver::Resolver (std::string path)
   1.122    : m_path (path)
   1.123 -{}
   1.124 +{
   1.125 +  Canonicalize ();
   1.126 +}
   1.127  Resolver::~Resolver ()
   1.128  {}
   1.129 +void
   1.130 +Resolver::Canonicalize (void)
   1.131 +{
   1.132 +  // ensure that we start and end with a '/'
   1.133 +  std::string::size_type tmp = m_path.find ("/");
   1.134 +  if (tmp != 0)
   1.135 +    {
   1.136 +      // no slash at start
   1.137 +      m_path = "/" + m_path;
   1.138 +    }
   1.139 +  tmp = m_path.find_last_of ("/");
   1.140 +  if (tmp != (m_path.size () - 1))
   1.141 +    {
   1.142 +      // no slash at end
   1.143 +      m_path = m_path + "/";
   1.144 +    }
   1.145 +}
   1.146  
   1.147  void 
   1.148  Resolver::Resolve (Ptr<Object> root)
   1.149 @@ -147,40 +261,34 @@
   1.150  }
   1.151  
   1.152  std::string
   1.153 -Resolver::GetResolvedPath (std::string name) const
   1.154 +Resolver::GetResolvedPath (void) const
   1.155  {
   1.156 -  std::string fullPath = "";
   1.157 +  std::string fullPath = "/";
   1.158    for (std::vector<std::string>::const_iterator i = m_workStack.begin (); i != m_workStack.end (); i++)
   1.159      {
   1.160 -      fullPath += "/" + *i;
   1.161 +      fullPath += *i + "/";
   1.162      }
   1.163 -  fullPath += "/" + name;
   1.164    return fullPath;
   1.165  }
   1.166  
   1.167  void 
   1.168 -Resolver::DoResolveOne (Ptr<Object> object, std::string name)
   1.169 +Resolver::DoResolveOne (Ptr<Object> object)
   1.170  {
   1.171 -  NS_LOG_DEBUG ("resolved="<<GetResolvedPath (name));
   1.172 -  DoOne (object, GetResolvedPath (name), name);
   1.173 +  NS_LOG_DEBUG ("resolved="<<GetResolvedPath ());
   1.174 +  DoOne (object, GetResolvedPath ());
   1.175  }
   1.176  
   1.177  void
   1.178  Resolver::DoResolve (std::string path, Ptr<Object> root)
   1.179  {
   1.180 -  NS_ASSERT (path != "");
   1.181 -  std::string::size_type pos = path.find ("/");
   1.182 -  if (pos != 0)
   1.183 -    {
   1.184 -      NS_FATAL_ERROR ("path does not start with a \"/\": \""<<path<<"\"");
   1.185 -      return;
   1.186 -    }
   1.187 +  NS_LOG_FUNCTION (path << root);
   1.188 +  std::string::size_type tmp;
   1.189 +  tmp = path.find ("/");
   1.190 +  NS_ASSERT (tmp == 0);
   1.191    std::string::size_type next = path.find ("/", 1);
   1.192    if (next == std::string::npos)
   1.193      {
   1.194 -      std::string attributeName = path.substr (1, path.size ()-1);
   1.195 -      NS_LOG_DEBUG ("handle attr="<<attributeName);
   1.196 -      DoOne (root, GetResolvedPath (attributeName), attributeName);
   1.197 +      DoResolveOne (root);
   1.198        return;
   1.199      }
   1.200    std::string item = path.substr (1, next-1);
   1.201 @@ -191,12 +299,12 @@
   1.202      {
   1.203        // This is a call to GetObject
   1.204        std::string tidString = item.substr (1, item.size () - 1);
   1.205 -      NS_LOG_DEBUG ("GetObject="<<tidString<<" on path="<<GetResolvedPath (""));
   1.206 +      NS_LOG_DEBUG ("GetObject="<<tidString<<" on path="<<GetResolvedPath ());
   1.207        TypeId tid = TypeId::LookupByName (tidString);
   1.208        Ptr<Object> object = root->GetObject<Object> (tid);
   1.209        if (object == 0)
   1.210  	{
   1.211 -	  NS_LOG_DEBUG ("GetObject ("<<tidString<<") failed on path="<<GetResolvedPath (""));
   1.212 +	  NS_LOG_DEBUG ("GetObject ("<<tidString<<") failed on path="<<GetResolvedPath ());
   1.213  	  return;
   1.214  	}
   1.215        m_workStack.push_back (item);
   1.216 @@ -210,21 +318,21 @@
   1.217        struct TypeId::AttributeInfo info;
   1.218        if (!tid.LookupAttributeByName (item, &info))
   1.219  	{
   1.220 -	  NS_LOG_DEBUG ("Requested item="<<item<<" does not exist on path="<<GetResolvedPath (""));
   1.221 +	  NS_LOG_DEBUG ("Requested item="<<item<<" does not exist on path="<<GetResolvedPath ());
   1.222  	  return;
   1.223  	}
   1.224        // attempt to cast to a pointer checker.
   1.225        const PointerChecker *ptr = dynamic_cast<const PointerChecker *> (PeekPointer (info.checker));
   1.226        if (ptr != 0)
   1.227  	{
   1.228 -	  NS_LOG_DEBUG ("GetAttribute(ptr)="<<item<<" on path="<<GetResolvedPath (""));
   1.229 +	  NS_LOG_DEBUG ("GetAttribute(ptr)="<<item<<" on path="<<GetResolvedPath ());
   1.230            PointerValue ptr;
   1.231            root->GetAttribute (item, ptr);
   1.232  	  Ptr<Object> object = ptr.Get<Object> ();
   1.233  	  if (object == 0)
   1.234  	    {
   1.235  	      NS_LOG_ERROR ("Requested object name=\""<<item<<
   1.236 -			    "\" exists on path=\""<<GetResolvedPath ("")<<"\""
   1.237 +			    "\" exists on path=\""<<GetResolvedPath ()<<"\""
   1.238  			    " but is null.");
   1.239  	      return;
   1.240  	    }
   1.241 @@ -236,7 +344,7 @@
   1.242        const ObjectVectorChecker *vectorChecker = dynamic_cast<const ObjectVectorChecker *> (PeekPointer (info.checker));
   1.243        if (vectorChecker != 0)
   1.244  	{
   1.245 -	  NS_LOG_DEBUG ("GetAttribute(vector)="<<item<<" on path="<<GetResolvedPath (""));
   1.246 +	  NS_LOG_DEBUG ("GetAttribute(vector)="<<item<<" on path="<<GetResolvedPath ());
   1.247  	  ObjectVectorValue vector;
   1.248            root->GetAttribute (item, vector);
   1.249  	  m_workStack.push_back (item);
   1.250 @@ -252,17 +360,13 @@
   1.251  Resolver::DoArrayResolve (std::string path, const ObjectVectorValue &vector)
   1.252  {
   1.253    NS_ASSERT (path != "");
   1.254 -  std::string::size_type pos = path.find ("/");
   1.255 -  if (pos != 0)
   1.256 -    {
   1.257 -      NS_FATAL_ERROR ("path does not start with a \"/\": \""<<path<<"\"");
   1.258 -      return;
   1.259 -    }
   1.260 +  std::string::size_type tmp;
   1.261 +  tmp = path.find ("/");
   1.262 +  NS_ASSERT (tmp == 0);
   1.263    std::string::size_type next = path.find ("/", 1);
   1.264    if (next == std::string::npos)
   1.265      {
   1.266 -      NS_LOG_DEBUG ("vector path includes no index data on path=\""<<path<<"\"");
   1.267 -      return;
   1.268 +      NS_FATAL_ERROR ("vector path includes no index data on path=\""<<path<<"\"");
   1.269      }
   1.270    std::string item = path.substr (1, next-1);
   1.271    std::string pathLeft = path.substr (next, path.size ()-next);
   1.272 @@ -290,6 +394,7 @@
   1.273    void Connect (std::string path, const CallbackBase &cb);
   1.274    void DisconnectWithoutContext (std::string path, const CallbackBase &cb);
   1.275    void Disconnect (std::string path, const CallbackBase &cb);
   1.276 +  Config::MatchContainer LookupMatches (std::string path);
   1.277  
   1.278    void RegisterRootNamespaceObject (Ptr<Object> obj);
   1.279    void UnregisterRootNamespaceObject (Ptr<Object> obj);
   1.280 @@ -298,110 +403,86 @@
   1.281    Ptr<Object> GetRootNamespaceObject (uint32_t i) const;
   1.282    
   1.283  private:
   1.284 +  void ParsePath (std::string path, std::string *root, std::string *leaf) const;
   1.285    typedef std::vector<Ptr<Object> > Roots;
   1.286    Roots m_roots;
   1.287  };
   1.288  
   1.289  void 
   1.290 +ConfigImpl::ParsePath (std::string path, std::string *root, std::string *leaf) const
   1.291 +{
   1.292 +  std::string::size_type slash = path.find_last_of ("/");
   1.293 +  NS_ASSERT (slash != std::string::npos);
   1.294 +  *root = path.substr (0, slash);
   1.295 +  *leaf = path.substr (slash+1, path.size ()-(slash+1));
   1.296 +  NS_LOG_FUNCTION (path << *root << *leaf);
   1.297 +}
   1.298 +
   1.299 +void 
   1.300  ConfigImpl::Set (std::string path, const AttributeValue &value)
   1.301  {
   1.302 -  class SetResolver : public Resolver 
   1.303 +  std::string root, leaf;
   1.304 +  ParsePath (path, &root, &leaf);
   1.305 +  Config::MatchContainer container = LookupMatches (root);
   1.306 +  container.Set (leaf, value);
   1.307 +}
   1.308 +void 
   1.309 +ConfigImpl::ConnectWithoutContext (std::string path, const CallbackBase &cb)
   1.310 +{
   1.311 +  std::string root, leaf;
   1.312 +  ParsePath (path, &root, &leaf);
   1.313 +  Config::MatchContainer container = LookupMatches (root);
   1.314 +  container.ConnectWithoutContext (leaf, cb);
   1.315 +}
   1.316 +void 
   1.317 +ConfigImpl::DisconnectWithoutContext (std::string path, const CallbackBase &cb)
   1.318 +{
   1.319 +  std::string root, leaf;
   1.320 +  ParsePath (path, &root, &leaf);
   1.321 +  Config::MatchContainer container = LookupMatches (root);
   1.322 +  container.DisconnectWithoutContext (leaf, cb);
   1.323 +}
   1.324 +void 
   1.325 +ConfigImpl::Connect (std::string path, const CallbackBase &cb)
   1.326 +{
   1.327 +  std::string root, leaf;
   1.328 +  ParsePath (path, &root, &leaf);
   1.329 +  Config::MatchContainer container = LookupMatches (root);
   1.330 +  container.Connect (leaf, cb);
   1.331 +}
   1.332 +void 
   1.333 +ConfigImpl::Disconnect (std::string path, const CallbackBase &cb)
   1.334 +{
   1.335 +  std::string root, leaf;
   1.336 +  ParsePath (path, &root, &leaf);
   1.337 +  Config::MatchContainer container = LookupMatches (root);
   1.338 +  container.Disconnect (leaf, cb);
   1.339 +}
   1.340 +
   1.341 +Config::MatchContainer 
   1.342 +ConfigImpl::LookupMatches (std::string path)
   1.343 +{
   1.344 +  NS_LOG_FUNCTION (path);
   1.345 +  class LookupMatchesResolver : public Resolver 
   1.346    {
   1.347    public:
   1.348 -    SetResolver (std::string path, const AttributeValue &value)
   1.349 -      : Resolver (path),
   1.350 -	m_value (value.Copy ()) {}
   1.351 -  private:
   1.352 -    virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
   1.353 -      object->SetAttribute (name, *m_value);
   1.354 +    LookupMatchesResolver (std::string path)
   1.355 +      : Resolver (path)
   1.356 +    {}
   1.357 +    virtual void DoOne (Ptr<Object> object, std::string path) {
   1.358 +      m_objects.push_back (object);
   1.359 +      m_contexts.push_back (path);
   1.360      }
   1.361 -    Ptr<const AttributeValue> m_value;
   1.362 -  } resolver = SetResolver (path, value);
   1.363 +    std::vector<Ptr<Object> > m_objects;
   1.364 +    std::vector<std::string> m_contexts;
   1.365 +  } resolver = LookupMatchesResolver (path);
   1.366    for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
   1.367      {
   1.368        resolver.Resolve (*i);
   1.369      }
   1.370 +  return Config::MatchContainer (resolver.m_objects, resolver.m_contexts, path);
   1.371  }
   1.372 -void 
   1.373 -ConfigImpl::ConnectWithoutContext (std::string path, const CallbackBase &cb)
   1.374 -{
   1.375 -  class ConnectResolver : public Resolver 
   1.376 -  {
   1.377 -  public:
   1.378 -    ConnectResolver (std::string path, const CallbackBase &cb)
   1.379 -      : Resolver (path),
   1.380 -	m_cb (cb) {}
   1.381 -  private:
   1.382 -    virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
   1.383 -      object->TraceConnectWithoutContext (name, m_cb);
   1.384 -    }
   1.385 -    CallbackBase m_cb;
   1.386 -  } resolver = ConnectResolver (path, cb);
   1.387 -  for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
   1.388 -    {
   1.389 -      resolver.Resolve (*i);
   1.390 -    }
   1.391 -}
   1.392 -void 
   1.393 -ConfigImpl::DisconnectWithoutContext (std::string path, const CallbackBase &cb)
   1.394 -{
   1.395 -  class DisconnectResolver : public Resolver 
   1.396 -  {
   1.397 -  public:
   1.398 -    DisconnectResolver (std::string path, const CallbackBase &cb)
   1.399 -      : Resolver (path),
   1.400 -	m_cb (cb) {}
   1.401 -  private:
   1.402 -    virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
   1.403 -      object->TraceDisconnectWithoutContext (name, m_cb);
   1.404 -    }
   1.405 -    CallbackBase m_cb;
   1.406 -  } resolver = DisconnectResolver (path, cb);
   1.407 -  for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
   1.408 -    {
   1.409 -      resolver.Resolve (*i);
   1.410 -    }
   1.411 -}
   1.412 -void 
   1.413 -ConfigImpl::Connect (std::string path, const CallbackBase &cb)
   1.414 -{
   1.415 -  class ConnectWithContextResolver : public Resolver 
   1.416 -  {
   1.417 -  public:
   1.418 -    ConnectWithContextResolver (std::string path, const CallbackBase &cb)
   1.419 -      : Resolver (path),
   1.420 -	m_cb (cb) {}
   1.421 -  private:
   1.422 -    virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
   1.423 -      object->TraceConnect (name, path, m_cb);
   1.424 -    }
   1.425 -    CallbackBase m_cb;
   1.426 -  } resolver = ConnectWithContextResolver (path, cb);
   1.427 -  for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
   1.428 -    {
   1.429 -      resolver.Resolve (*i);
   1.430 -    }
   1.431 -}
   1.432 -void 
   1.433 -ConfigImpl::Disconnect (std::string path, const CallbackBase &cb)
   1.434 -{
   1.435 -  class DisconnectWithContextResolver : public Resolver 
   1.436 -  {
   1.437 -  public:
   1.438 -    DisconnectWithContextResolver (std::string path, const CallbackBase &cb)
   1.439 -      : Resolver (path),
   1.440 -	m_cb (cb) {}
   1.441 -  private:
   1.442 -    virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
   1.443 -      object->TraceDisconnect (name, path, m_cb);
   1.444 -    }
   1.445 -    CallbackBase m_cb;
   1.446 -  } resolver = DisconnectWithContextResolver (path, cb);
   1.447 -  for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
   1.448 -    {
   1.449 -      resolver.Resolve (*i);
   1.450 -    }
   1.451 -}
   1.452 +
   1.453  void 
   1.454  ConfigImpl::RegisterRootNamespaceObject (Ptr<Object> obj)
   1.455  {
   1.456 @@ -472,6 +553,10 @@
   1.457  {
   1.458    Singleton<ConfigImpl>::Get ()->Disconnect (path, cb);
   1.459  }
   1.460 +Config::MatchContainer LookupMatches (std::string path)
   1.461 +{
   1.462 +  return Singleton<ConfigImpl>::Get ()->LookupMatches (path);
   1.463 +}
   1.464  
   1.465  void RegisterRootNamespaceObject (Ptr<Object> obj)
   1.466  {
     2.1 --- a/src/core/config.h	Fri Oct 24 12:31:57 2008 +0200
     2.2 +++ b/src/core/config.h	Fri Oct 24 12:35:28 2008 +0200
     2.3 @@ -22,6 +22,7 @@
     2.4  
     2.5  #include "ptr.h"
     2.6  #include <string>
     2.7 +#include <vector>
     2.8  
     2.9  namespace ns3 {
    2.10  
    2.11 @@ -110,6 +111,35 @@
    2.12   */
    2.13  void Disconnect (std::string path, const CallbackBase &cb);
    2.14  
    2.15 +class MatchContainer
    2.16 +{
    2.17 +public:
    2.18 +  typedef std::vector<Ptr<Object> >::const_iterator Iterator;
    2.19 +  MatchContainer ();
    2.20 +  MatchContainer (const std::vector<Ptr<Object> > &objects, 
    2.21 +                  const std::vector<std::string> &contexts, 
    2.22 +                  std::string path);
    2.23 +
    2.24 +  MatchContainer::Iterator Begin (void) const;
    2.25 +  MatchContainer::Iterator End (void) const;
    2.26 +  uint32_t GetN (void) const;
    2.27 +  Ptr<Object> Get (uint32_t i) const;
    2.28 +  std::string GetMatchedPath (uint32_t i) const;
    2.29 +  std::string GetPath (void) const;
    2.30 +
    2.31 +  void Set (std::string name, const AttributeValue &value);
    2.32 +  void Connect (std::string name, const CallbackBase &cb);
    2.33 +  void ConnectWithoutContext (std::string name, const CallbackBase &cb);
    2.34 +  void Disconnect (std::string name, const CallbackBase &cb);
    2.35 +  void DisconnectWithoutContext (std::string name, const CallbackBase &cb);
    2.36 +private:
    2.37 +  std::vector<Ptr<Object> > m_objects;
    2.38 +  std::vector<std::string> m_contexts;
    2.39 +  std::string m_path;
    2.40 +};
    2.41 +
    2.42 +MatchContainer LookupMatches (std::string path);
    2.43 +
    2.44  /**
    2.45   * \param obj a new root object
    2.46   *