--- a/src/core/config.cc Fri Oct 24 12:31:57 2008 +0200
+++ b/src/core/config.cc Fri Oct 24 12:35:28 2008 +0200
@@ -30,6 +30,100 @@
namespace ns3 {
+namespace Config {
+
+MatchContainer::MatchContainer ()
+{}
+MatchContainer::MatchContainer (const std::vector<Ptr<Object> > &objects,
+ const std::vector<std::string> &contexts,
+ std::string path)
+ : m_objects (objects),
+ m_contexts (contexts),
+ m_path (path)
+{}
+MatchContainer::Iterator
+MatchContainer::Begin (void) const
+{
+ return m_objects.begin ();
+}
+MatchContainer::Iterator
+MatchContainer::End (void) const
+{
+ return m_objects.end ();
+}
+uint32_t
+MatchContainer::GetN (void) const
+{
+ return m_objects.size ();
+}
+Ptr<Object>
+MatchContainer::Get (uint32_t i) const
+{
+ return m_objects[i];
+}
+std::string
+MatchContainer::GetMatchedPath (uint32_t i) const
+{
+ return m_contexts[i];
+}
+std::string
+MatchContainer::GetPath (void) const
+{
+ return m_path;
+}
+
+void
+MatchContainer::Set (std::string name, const AttributeValue &value)
+{
+ for (Iterator tmp = Begin (); tmp != End (); ++tmp)
+ {
+ Ptr<Object> object = *tmp;
+ object->SetAttribute (name, value);
+ }
+}
+void
+MatchContainer::Connect (std::string name, const CallbackBase &cb)
+{
+ NS_ASSERT (m_objects.size () == m_contexts.size ());
+ for (uint32_t i = 0; i < m_objects.size (); ++i)
+ {
+ Ptr<Object> object = m_objects[i];
+ std::string ctx = m_contexts[i] + name;
+ object->TraceConnect (name, ctx, cb);
+ }
+}
+void
+MatchContainer::ConnectWithoutContext (std::string name, const CallbackBase &cb)
+{
+ for (Iterator tmp = Begin (); tmp != End (); ++tmp)
+ {
+ Ptr<Object> object = *tmp;
+ object->TraceConnectWithoutContext (name, cb);
+ }
+}
+void
+MatchContainer::Disconnect (std::string name, const CallbackBase &cb)
+{
+ NS_ASSERT (m_objects.size () == m_contexts.size ());
+ for (uint32_t i = 0; i < m_objects.size (); ++i)
+ {
+ Ptr<Object> object = m_objects[i];
+ std::string ctx = m_contexts[i] + name;
+ object->TraceDisconnect (name, ctx, cb);
+ }
+}
+void
+MatchContainer::DisconnectWithoutContext (std::string name, const CallbackBase &cb)
+{
+ for (Iterator tmp = Begin (); tmp != End (); ++tmp)
+ {
+ Ptr<Object> object = *tmp;
+ object->TraceDisconnectWithoutContext (name, cb);
+ }
+}
+
+} // namespace Config
+
class ArrayMatcher
{
public:
@@ -125,20 +219,40 @@
void Resolve (Ptr<Object> root);
private:
+ void Canonicalize (void);
void DoResolve (std::string path, Ptr<Object> root);
void DoArrayResolve (std::string path, const ObjectVectorValue &vector);
- void DoResolveOne (Ptr<Object> object, std::string name);
- std::string GetResolvedPath (std::string name) const;
- virtual void DoOne (Ptr<Object> object, std::string path, std::string name) = 0;
+ void DoResolveOne (Ptr<Object> object);
+ std::string GetResolvedPath (void) const;
+ virtual void DoOne (Ptr<Object> object, std::string path) = 0;
std::vector<std::string> m_workStack;
std::string m_path;
};
Resolver::Resolver (std::string path)
: m_path (path)
-{}
+{
+ Canonicalize ();
+}
Resolver::~Resolver ()
{}
+void
+Resolver::Canonicalize (void)
+{
+ // ensure that we start and end with a '/'
+ std::string::size_type tmp = m_path.find ("/");
+ if (tmp != 0)
+ {
+ // no slash at start
+ m_path = "/" + m_path;
+ }
+ tmp = m_path.find_last_of ("/");
+ if (tmp != (m_path.size () - 1))
+ {
+ // no slash at end
+ m_path = m_path + "/";
+ }
+}
void
Resolver::Resolve (Ptr<Object> root)
@@ -147,40 +261,34 @@
}
std::string
-Resolver::GetResolvedPath (std::string name) const
+Resolver::GetResolvedPath (void) const
{
- std::string fullPath = "";
+ std::string fullPath = "/";
for (std::vector<std::string>::const_iterator i = m_workStack.begin (); i != m_workStack.end (); i++)
{
- fullPath += "/" + *i;
+ fullPath += *i + "/";
}
- fullPath += "/" + name;
return fullPath;
}
void
-Resolver::DoResolveOne (Ptr<Object> object, std::string name)
+Resolver::DoResolveOne (Ptr<Object> object)
{
- NS_LOG_DEBUG ("resolved="<<GetResolvedPath (name));
- DoOne (object, GetResolvedPath (name), name);
+ NS_LOG_DEBUG ("resolved="<<GetResolvedPath ());
+ DoOne (object, GetResolvedPath ());
}
void
Resolver::DoResolve (std::string path, Ptr<Object> root)
{
- NS_ASSERT (path != "");
- std::string::size_type pos = path.find ("/");
- if (pos != 0)
- {
- NS_FATAL_ERROR ("path does not start with a \"/\": \""<<path<<"\"");
- return;
- }
+ NS_LOG_FUNCTION (path << root);
+ std::string::size_type tmp;
+ tmp = path.find ("/");
+ NS_ASSERT (tmp == 0);
std::string::size_type next = path.find ("/", 1);
if (next == std::string::npos)
{
- std::string attributeName = path.substr (1, path.size ()-1);
- NS_LOG_DEBUG ("handle attr="<<attributeName);
- DoOne (root, GetResolvedPath (attributeName), attributeName);
+ DoResolveOne (root);
return;
}
std::string item = path.substr (1, next-1);
@@ -191,12 +299,12 @@
{
// This is a call to GetObject
std::string tidString = item.substr (1, item.size () - 1);
- NS_LOG_DEBUG ("GetObject="<<tidString<<" on path="<<GetResolvedPath (""));
+ NS_LOG_DEBUG ("GetObject="<<tidString<<" on path="<<GetResolvedPath ());
TypeId tid = TypeId::LookupByName (tidString);
Ptr<Object> object = root->GetObject<Object> (tid);
if (object == 0)
{
- NS_LOG_DEBUG ("GetObject ("<<tidString<<") failed on path="<<GetResolvedPath (""));
+ NS_LOG_DEBUG ("GetObject ("<<tidString<<") failed on path="<<GetResolvedPath ());
return;
}
m_workStack.push_back (item);
@@ -210,21 +318,21 @@
struct TypeId::AttributeInfo info;
if (!tid.LookupAttributeByName (item, &info))
{
- NS_LOG_DEBUG ("Requested item="<<item<<" does not exist on path="<<GetResolvedPath (""));
+ NS_LOG_DEBUG ("Requested item="<<item<<" does not exist on path="<<GetResolvedPath ());
return;
}
// attempt to cast to a pointer checker.
const PointerChecker *ptr = dynamic_cast<const PointerChecker *> (PeekPointer (info.checker));
if (ptr != 0)
{
- NS_LOG_DEBUG ("GetAttribute(ptr)="<<item<<" on path="<<GetResolvedPath (""));
+ NS_LOG_DEBUG ("GetAttribute(ptr)="<<item<<" on path="<<GetResolvedPath ());
PointerValue ptr;
root->GetAttribute (item, ptr);
Ptr<Object> object = ptr.Get<Object> ();
if (object == 0)
{
NS_LOG_ERROR ("Requested object name=\""<<item<<
- "\" exists on path=\""<<GetResolvedPath ("")<<"\""
+ "\" exists on path=\""<<GetResolvedPath ()<<"\""
" but is null.");
return;
}
@@ -236,7 +344,7 @@
const ObjectVectorChecker *vectorChecker = dynamic_cast<const ObjectVectorChecker *> (PeekPointer (info.checker));
if (vectorChecker != 0)
{
- NS_LOG_DEBUG ("GetAttribute(vector)="<<item<<" on path="<<GetResolvedPath (""));
+ NS_LOG_DEBUG ("GetAttribute(vector)="<<item<<" on path="<<GetResolvedPath ());
ObjectVectorValue vector;
root->GetAttribute (item, vector);
m_workStack.push_back (item);
@@ -252,17 +360,13 @@
Resolver::DoArrayResolve (std::string path, const ObjectVectorValue &vector)
{
NS_ASSERT (path != "");
- std::string::size_type pos = path.find ("/");
- if (pos != 0)
- {
- NS_FATAL_ERROR ("path does not start with a \"/\": \""<<path<<"\"");
- return;
- }
+ std::string::size_type tmp;
+ tmp = path.find ("/");
+ NS_ASSERT (tmp == 0);
std::string::size_type next = path.find ("/", 1);
if (next == std::string::npos)
{
- NS_LOG_DEBUG ("vector path includes no index data on path=\""<<path<<"\"");
- return;
+ NS_FATAL_ERROR ("vector path includes no index data on path=\""<<path<<"\"");
}
std::string item = path.substr (1, next-1);
std::string pathLeft = path.substr (next, path.size ()-next);
@@ -290,6 +394,7 @@
void Connect (std::string path, const CallbackBase &cb);
void DisconnectWithoutContext (std::string path, const CallbackBase &cb);
void Disconnect (std::string path, const CallbackBase &cb);
+ Config::MatchContainer LookupMatches (std::string path);
void RegisterRootNamespaceObject (Ptr<Object> obj);
void UnregisterRootNamespaceObject (Ptr<Object> obj);
@@ -298,110 +403,86 @@
Ptr<Object> GetRootNamespaceObject (uint32_t i) const;
private:
+ void ParsePath (std::string path, std::string *root, std::string *leaf) const;
typedef std::vector<Ptr<Object> > Roots;
Roots m_roots;
};
void
+ConfigImpl::ParsePath (std::string path, std::string *root, std::string *leaf) const
+{
+ std::string::size_type slash = path.find_last_of ("/");
+ NS_ASSERT (slash != std::string::npos);
+ *root = path.substr (0, slash);
+ *leaf = path.substr (slash+1, path.size ()-(slash+1));
+ NS_LOG_FUNCTION (path << *root << *leaf);
+}
+
+void
ConfigImpl::Set (std::string path, const AttributeValue &value)
{
- class SetResolver : public Resolver
- {
- public:
- SetResolver (std::string path, const AttributeValue &value)
- : Resolver (path),
- m_value (value.Copy ()) {}
- private:
- virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
- object->SetAttribute (name, *m_value);
- }
- Ptr<const AttributeValue> m_value;
- } resolver = SetResolver (path, value);
- for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
- {
- resolver.Resolve (*i);
- }
+ std::string root, leaf;
+ ParsePath (path, &root, &leaf);
+ Config::MatchContainer container = LookupMatches (root);
+ container.Set (leaf, value);
}
void
ConfigImpl::ConnectWithoutContext (std::string path, const CallbackBase &cb)
{
- class ConnectResolver : public Resolver
- {
- public:
- ConnectResolver (std::string path, const CallbackBase &cb)
- : Resolver (path),
- m_cb (cb) {}
- private:
- virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
- object->TraceConnectWithoutContext (name, m_cb);
- }
- CallbackBase m_cb;
- } resolver = ConnectResolver (path, cb);
- for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
- {
- resolver.Resolve (*i);
- }
+ std::string root, leaf;
+ ParsePath (path, &root, &leaf);
+ Config::MatchContainer container = LookupMatches (root);
+ container.ConnectWithoutContext (leaf, cb);
}
void
ConfigImpl::DisconnectWithoutContext (std::string path, const CallbackBase &cb)
{
- class DisconnectResolver : public Resolver
- {
- public:
- DisconnectResolver (std::string path, const CallbackBase &cb)
- : Resolver (path),
- m_cb (cb) {}
- private:
- virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
- object->TraceDisconnectWithoutContext (name, m_cb);
- }
- CallbackBase m_cb;
- } resolver = DisconnectResolver (path, cb);
- for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
- {
- resolver.Resolve (*i);
- }
+ std::string root, leaf;
+ ParsePath (path, &root, &leaf);
+ Config::MatchContainer container = LookupMatches (root);
+ container.DisconnectWithoutContext (leaf, cb);
}
void
ConfigImpl::Connect (std::string path, const CallbackBase &cb)
{
- class ConnectWithContextResolver : public Resolver
+ std::string root, leaf;
+ ParsePath (path, &root, &leaf);
+ Config::MatchContainer container = LookupMatches (root);
+ container.Connect (leaf, cb);
+}
+void
+ConfigImpl::Disconnect (std::string path, const CallbackBase &cb)
+{
+ std::string root, leaf;
+ ParsePath (path, &root, &leaf);
+ Config::MatchContainer container = LookupMatches (root);
+ container.Disconnect (leaf, cb);
+}
+
+Config::MatchContainer
+ConfigImpl::LookupMatches (std::string path)
+{
+ NS_LOG_FUNCTION (path);
+ class LookupMatchesResolver : public Resolver
{
public:
- ConnectWithContextResolver (std::string path, const CallbackBase &cb)
- : Resolver (path),
- m_cb (cb) {}
- private:
- virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
- object->TraceConnect (name, path, m_cb);
+ LookupMatchesResolver (std::string path)
+ : Resolver (path)
+ {}
+ virtual void DoOne (Ptr<Object> object, std::string path) {
+ m_objects.push_back (object);
+ m_contexts.push_back (path);
}
- CallbackBase m_cb;
- } resolver = ConnectWithContextResolver (path, cb);
+ std::vector<Ptr<Object> > m_objects;
+ std::vector<std::string> m_contexts;
+ } resolver = LookupMatchesResolver (path);
for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
{
resolver.Resolve (*i);
}
+ return Config::MatchContainer (resolver.m_objects, resolver.m_contexts, path);
}
-void
-ConfigImpl::Disconnect (std::string path, const CallbackBase &cb)
-{
- class DisconnectWithContextResolver : public Resolver
- {
- public:
- DisconnectWithContextResolver (std::string path, const CallbackBase &cb)
- : Resolver (path),
- m_cb (cb) {}
- private:
- virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
- object->TraceDisconnect (name, path, m_cb);
- }
- CallbackBase m_cb;
- } resolver = DisconnectWithContextResolver (path, cb);
- for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
- {
- resolver.Resolve (*i);
- }
-}
+
void
ConfigImpl::RegisterRootNamespaceObject (Ptr<Object> obj)
{
@@ -472,6 +553,10 @@
{
Singleton<ConfigImpl>::Get ()->Disconnect (path, cb);
}
+Config::MatchContainer LookupMatches (std::string path)
+{
+ return Singleton<ConfigImpl>::Get ()->LookupMatches (path);
+}
void RegisterRootNamespaceObject (Ptr<Object> obj)
{