diff --git a/src/core/config.cc b/src/core/config.cc index db12d72a4..0b42ad0b9 100644 --- a/src/core/config.cc +++ b/src/core/config.cc @@ -30,6 +30,100 @@ NS_LOG_COMPONENT_DEFINE ("Config"); namespace ns3 { +namespace Config { + +MatchContainer::MatchContainer () +{} +MatchContainer::MatchContainer (const std::vector > &objects, + const std::vector &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 +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 = *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 = 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 = *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 = 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 = *tmp; + object->TraceDisconnectWithoutContext (name, cb); + } +} + +} // namespace Config + class ArrayMatcher { public: @@ -125,20 +219,40 @@ public: void Resolve (Ptr root); private: + void Canonicalize (void); void DoResolve (std::string path, Ptr root); void DoArrayResolve (std::string path, const ObjectVectorValue &vector); - void DoResolveOne (Ptr object, std::string name); - std::string GetResolvedPath (std::string name) const; - virtual void DoOne (Ptr object, std::string path, std::string name) = 0; + void DoResolveOne (Ptr object); + std::string GetResolvedPath (void) const; + virtual void DoOne (Ptr object, std::string path) = 0; std::vector 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 root) @@ -147,40 +261,34 @@ Resolver::Resolve (Ptr root) } std::string -Resolver::GetResolvedPath (std::string name) const +Resolver::GetResolvedPath (void) const { - std::string fullPath = ""; + std::string fullPath = "/"; for (std::vector::const_iterator i = m_workStack.begin (); i != m_workStack.end (); i++) { - fullPath += "/" + *i; + fullPath += *i + "/"; } - fullPath += "/" + name; return fullPath; } void -Resolver::DoResolveOne (Ptr object, std::string name) +Resolver::DoResolveOne (Ptr object) { - NS_LOG_DEBUG ("resolved="< root) const ObjectVectorChecker *vectorChecker = dynamic_cast (PeekPointer (info.checker)); if (vectorChecker != 0) { - NS_LOG_DEBUG ("GetAttribute(vector)="< obj); void UnregisterRootNamespaceObject (Ptr obj); @@ -298,110 +403,86 @@ public: Ptr GetRootNamespaceObject (uint32_t i) const; private: + void ParsePath (std::string path, std::string *root, std::string *leaf) const; typedef std::vector > 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, std::string path, std::string name) { - object->SetAttribute (name, *m_value); - } - Ptr 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, 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, 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 - { - public: - ConnectWithContextResolver (std::string path, const CallbackBase &cb) - : Resolver (path), - m_cb (cb) {} - private: - virtual void DoOne (Ptr object, std::string path, std::string name) { - object->TraceConnect (name, path, m_cb); - } - CallbackBase m_cb; - } resolver = ConnectWithContextResolver (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.Connect (leaf, cb); } void ConfigImpl::Disconnect (std::string path, const CallbackBase &cb) { - class DisconnectWithContextResolver : public Resolver + 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: - DisconnectWithContextResolver (std::string path, const CallbackBase &cb) - : Resolver (path), - m_cb (cb) {} - private: - virtual void DoOne (Ptr object, std::string path, std::string name) { - object->TraceDisconnect (name, path, m_cb); + LookupMatchesResolver (std::string path) + : Resolver (path) + {} + virtual void DoOne (Ptr object, std::string path) { + m_objects.push_back (object); + m_contexts.push_back (path); } - CallbackBase m_cb; - } resolver = DisconnectWithContextResolver (path, cb); + std::vector > m_objects; + std::vector 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::RegisterRootNamespaceObject (Ptr obj) { @@ -472,6 +553,10 @@ Disconnect (std::string path, const CallbackBase &cb) { Singleton::Get ()->Disconnect (path, cb); } +Config::MatchContainer LookupMatches (std::string path) +{ + return Singleton::Get ()->LookupMatches (path); +} void RegisterRootNamespaceObject (Ptr obj) { diff --git a/src/core/config.h b/src/core/config.h index 256b491ef..9da9b03b9 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -22,6 +22,7 @@ #include "ptr.h" #include +#include namespace ns3 { @@ -110,6 +111,35 @@ void Connect (std::string path, const CallbackBase &cb); */ void Disconnect (std::string path, const CallbackBase &cb); +class MatchContainer +{ +public: + typedef std::vector >::const_iterator Iterator; + MatchContainer (); + MatchContainer (const std::vector > &objects, + const std::vector &contexts, + std::string path); + + MatchContainer::Iterator Begin (void) const; + MatchContainer::Iterator End (void) const; + uint32_t GetN (void) const; + Ptr Get (uint32_t i) const; + std::string GetMatchedPath (uint32_t i) const; + std::string GetPath (void) const; + + void Set (std::string name, const AttributeValue &value); + void Connect (std::string name, const CallbackBase &cb); + void ConnectWithoutContext (std::string name, const CallbackBase &cb); + void Disconnect (std::string name, const CallbackBase &cb); + void DisconnectWithoutContext (std::string name, const CallbackBase &cb); +private: + std::vector > m_objects; + std::vector m_contexts; + std::string m_path; +}; + +MatchContainer LookupMatches (std::string path); + /** * \param obj a new root object *