A Config class which hooks into the Object Attribute/Tracing system.
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/core/config.cc Tue Feb 26 01:07:16 2008 +0100
1.3 @@ -0,0 +1,615 @@
1.4 +#include "config.h"
1.5 +#include "singleton.h"
1.6 +#include "object.h"
1.7 +#include "global-value.h"
1.8 +#include "object-vector.h"
1.9 +#include "log.h"
1.10 +#include <sstream>
1.11 +
1.12 +NS_LOG_COMPONENT_DEFINE ("Config");
1.13 +
1.14 +namespace ns3 {
1.15 +
1.16 +class ArrayMatcher
1.17 +{
1.18 +public:
1.19 + ArrayMatcher (std::string element);
1.20 + bool Matches (uint32_t i) const;
1.21 +private:
1.22 + bool StringToUint32 (std::string str, uint32_t *value) const;
1.23 + std::string m_element;
1.24 +};
1.25 +
1.26 +
1.27 +ArrayMatcher::ArrayMatcher (std::string element)
1.28 + : m_element (element)
1.29 +{}
1.30 +bool
1.31 +ArrayMatcher::Matches (uint32_t i) const
1.32 +{
1.33 + if (m_element == "*")
1.34 + {
1.35 + NS_LOG_DEBUG ("Array "<<i<<" matches *");
1.36 + return true;
1.37 + }
1.38 + std::string::size_type tmp;
1.39 + tmp = m_element.find ("|");
1.40 + if (tmp != std::string::npos)
1.41 + {
1.42 + std::string left = m_element.substr (0, tmp-0);
1.43 + std::string right = m_element.substr (tmp+1, m_element.size () - (tmp + 1));
1.44 + ArrayMatcher matcher = ArrayMatcher (left);
1.45 + if (matcher.Matches (i))
1.46 + {
1.47 + NS_LOG_DEBUG ("Array "<<i<<" matches "<<left);
1.48 + return true;
1.49 + }
1.50 + matcher = ArrayMatcher (right);
1.51 + if (matcher.Matches (i))
1.52 + {
1.53 + NS_LOG_DEBUG ("Array "<<i<<" matches "<<right);
1.54 + return true;
1.55 + }
1.56 + NS_LOG_DEBUG ("Array "<<i<<" does not match "<<m_element);
1.57 + return false;
1.58 + }
1.59 + std::string::size_type leftBracket = m_element.find ("[");
1.60 + std::string::size_type rightBracket = m_element.find ("]");
1.61 + std::string::size_type dash = m_element.find ("-");
1.62 + if (leftBracket == 0 && rightBracket == m_element.size () - 1 &&
1.63 + dash > leftBracket && dash < rightBracket)
1.64 + {
1.65 + std::string lowerBound = m_element.substr (leftBracket + 1, dash - (leftBracket + 1));
1.66 + std::string upperBound = m_element.substr (dash + 1, rightBracket - (dash + 1));
1.67 + uint32_t min;
1.68 + uint32_t max;
1.69 + if (StringToUint32 (lowerBound, &min) &&
1.70 + StringToUint32 (upperBound, &max) &&
1.71 + i >= min && i <= max)
1.72 + {
1.73 + NS_LOG_DEBUG ("Array "<<i<<" matches "<<m_element);
1.74 + return true;
1.75 + }
1.76 + else
1.77 + {
1.78 + NS_LOG_DEBUG ("Array "<<i<<" does not "<<m_element);
1.79 + return false;
1.80 + }
1.81 + }
1.82 + uint32_t value;
1.83 + if (StringToUint32 (m_element, &value) &&
1.84 + i == value)
1.85 + {
1.86 + NS_LOG_DEBUG ("Array "<<i<<" matches "<<m_element);
1.87 + return true;
1.88 + }
1.89 + NS_LOG_DEBUG ("Array "<<i<<" does not match "<<m_element);
1.90 + return false;
1.91 +}
1.92 +
1.93 +bool
1.94 +ArrayMatcher::StringToUint32 (std::string str, uint32_t *value) const
1.95 +{
1.96 + std::istringstream iss;
1.97 + iss.str (str);
1.98 + iss >> (*value);
1.99 + return !iss.bad () && !iss.fail ();
1.100 +}
1.101 +
1.102 +
1.103 +class Resolver
1.104 +{
1.105 +public:
1.106 + Resolver (std::string path);
1.107 + virtual ~Resolver ();
1.108 +
1.109 + void Resolve (Ptr<Object> root);
1.110 +private:
1.111 + void DoResolve (std::string path, Ptr<Object> root);
1.112 + void DoArrayResolve (std::string path, const ObjectVector &vector);
1.113 + void DoResolveOne (Ptr<Object> object, std::string name);
1.114 + std::string GetResolvedPath (std::string name) const;
1.115 + virtual void DoOne (Ptr<Object> object, std::string name) = 0;
1.116 + std::vector<std::string> m_workStack;
1.117 + std::string m_path;
1.118 +};
1.119 +
1.120 +Resolver::Resolver (std::string path)
1.121 + : m_path (path)
1.122 +{}
1.123 +Resolver::~Resolver ()
1.124 +{}
1.125 +
1.126 +void
1.127 +Resolver::Resolve (Ptr<Object> root)
1.128 +{
1.129 + DoResolve (m_path, root);
1.130 +}
1.131 +
1.132 +std::string
1.133 +Resolver::GetResolvedPath (std::string name) const
1.134 +{
1.135 + std::string fullPath = "";
1.136 + for (std::vector<std::string>::const_iterator i = m_workStack.begin (); i != m_workStack.end (); i++)
1.137 + {
1.138 + fullPath += "/" + *i;
1.139 + }
1.140 + fullPath += "/" + name;
1.141 + return fullPath;
1.142 +}
1.143 +
1.144 +void
1.145 +Resolver::DoResolveOne (Ptr<Object> object, std::string name)
1.146 +{
1.147 + NS_LOG_DEBUG ("resolved="<<GetResolvedPath (name));
1.148 + DoOne (object, name);
1.149 +}
1.150 +
1.151 +void
1.152 +Resolver::DoResolve (std::string path, Ptr<Object> root)
1.153 +{
1.154 + NS_ASSERT (path != "");
1.155 + std::string::size_type pos = path.find ("/");
1.156 + if (pos != 0)
1.157 + {
1.158 + NS_FATAL_ERROR ("path does not start with a \"/\": \""<<path<<"\"");
1.159 + return;
1.160 + }
1.161 + std::string::size_type next = path.find ("/", 1);
1.162 + if (next == std::string::npos)
1.163 + {
1.164 + std::string attributeName = path.substr (1, path.size ()-1);
1.165 + NS_LOG_DEBUG ("handle attr="<<attributeName);
1.166 + DoOne (root, attributeName);
1.167 + return;
1.168 + }
1.169 + std::string item = path.substr (1, next-1);
1.170 + std::string pathLeft = path.substr (next, path.size ()-next);
1.171 +
1.172 + std::string::size_type dollarPos = item.find ("$");
1.173 + if (dollarPos == 0)
1.174 + {
1.175 + // This is a call to GetObject
1.176 + std::string tidString = item.substr (1, item.size () - 1);
1.177 + NS_LOG_DEBUG ("GetObject="<<tidString<<"on path="<<GetResolvedPath (""));
1.178 + TypeId tid = TypeId::LookupByName (tidString);
1.179 + Ptr<Object> object = root->GetObject<Object> (tid);
1.180 + if (object == 0)
1.181 + {
1.182 + NS_LOG_DEBUG ("GetObject ("<<tidString<<") failed on path="<<GetResolvedPath (""));
1.183 + return;
1.184 + }
1.185 + m_workStack.push_back (item);
1.186 + DoResolve (pathLeft, object);
1.187 + m_workStack.pop_back ();
1.188 + }
1.189 + else
1.190 + {
1.191 + // this is a normal attribute.
1.192 + TypeId tid = root->GetRealTypeId ();
1.193 + struct TypeId::AttributeInfo info;
1.194 + if (!tid.LookupAttributeByName (item, &info))
1.195 + {
1.196 + NS_LOG_DEBUG ("Requested item="<<item<<" does not exist on path="<<GetResolvedPath (""));
1.197 + return;
1.198 + }
1.199 + // attempt to cast to a pointer checker.
1.200 + const PtrChecker *ptr = dynamic_cast<const PtrChecker *> (PeekPointer (info.checker));
1.201 + if (ptr != 0)
1.202 + {
1.203 + NS_LOG_DEBUG ("GetAttribute(ptr)="<<item<<" on path="<<GetResolvedPath (""));
1.204 + // XXX: This is not completely right because anything could be stored in a
1.205 + // Ptr<>. We really need to fix this by thinking seriously about our
1.206 + // object hierarchy.
1.207 + Ptr<Object> object = root->GetAttribute (item);
1.208 + if (object == 0)
1.209 + {
1.210 + NS_LOG_ERROR ("Requested object name=\""<<item<<
1.211 + "\" exists on path=\""<<GetResolvedPath ("")<<"\""
1.212 + " but is null.");
1.213 + return;
1.214 + }
1.215 + m_workStack.push_back (item);
1.216 + DoResolve (pathLeft, object);
1.217 + m_workStack.pop_back ();
1.218 + }
1.219 + // attempt to cast to an object vector.
1.220 + const ObjectVectorChecker *vectorChecker = dynamic_cast<const ObjectVectorChecker *> (PeekPointer (info.checker));
1.221 + if (vectorChecker != 0)
1.222 + {
1.223 + NS_LOG_DEBUG ("GetAttribute(vector)="<<item<<" on path="<<GetResolvedPath (""));
1.224 + ObjectVector vector = root->GetAttribute (item);
1.225 + m_workStack.push_back (item);
1.226 + DoArrayResolve (pathLeft, vector);
1.227 + m_workStack.pop_back ();
1.228 + }
1.229 + // this could be anything else and we don't know what to do with it.
1.230 + // So, we just ignore it.
1.231 + }
1.232 +}
1.233 +
1.234 +void
1.235 +Resolver::DoArrayResolve (std::string path, const ObjectVector &vector)
1.236 +{
1.237 + NS_ASSERT (path != "");
1.238 + std::string::size_type pos = path.find ("/");
1.239 + if (pos != 0)
1.240 + {
1.241 + NS_FATAL_ERROR ("path does not start with a \"/\": \""<<path<<"\"");
1.242 + return;
1.243 + }
1.244 + std::string::size_type next = path.find ("/", 1);
1.245 + if (next == std::string::npos)
1.246 + {
1.247 + NS_LOG_DEBUG ("vector path includes no index data on path=\""<<path<<"\"");
1.248 + return;
1.249 + }
1.250 + std::string item = path.substr (1, next-1);
1.251 + std::string pathLeft = path.substr (next, path.size ()-next);
1.252 +
1.253 + ArrayMatcher matcher = ArrayMatcher (item);
1.254 + for (uint32_t i = 0; i < vector.GetN (); i++)
1.255 + {
1.256 + if (matcher.Matches (i))
1.257 + {
1.258 + std::ostringstream oss;
1.259 + oss << i;
1.260 + m_workStack.push_back (oss.str ());
1.261 + DoResolve (pathLeft, vector.Get (i));
1.262 + m_workStack.pop_back ();
1.263 + }
1.264 + }
1.265 +}
1.266 +
1.267 +
1.268 +class ConfigImpl
1.269 +{
1.270 +public:
1.271 + void Set (std::string path, Attribute value);
1.272 + void Connect (std::string path, const CallbackBase &cb);
1.273 + void Disconnect (std::string path, const CallbackBase &cb);
1.274 +
1.275 + void RegisterRootNamespaceObject (Ptr<Object> obj);
1.276 + void UnregisterRootNamespaceObject (Ptr<Object> obj);
1.277 +
1.278 +private:
1.279 + typedef std::vector<Ptr<Object> > Roots;
1.280 + Roots m_roots;
1.281 +};
1.282 +
1.283 +void
1.284 +ConfigImpl::Set (std::string path, Attribute value)
1.285 +{
1.286 + class SetResolver : public Resolver
1.287 + {
1.288 + public:
1.289 + SetResolver (std::string path, Attribute value)
1.290 + : Resolver (path),
1.291 + m_value (value) {}
1.292 + private:
1.293 + virtual void DoOne (Ptr<Object> object, std::string name) {
1.294 + object->SetAttribute (name, m_value);
1.295 + }
1.296 + Attribute m_value;
1.297 + } resolver = SetResolver (path, value);
1.298 + for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
1.299 + {
1.300 + resolver.Resolve (*i);
1.301 + }
1.302 +}
1.303 +void
1.304 +ConfigImpl::Connect (std::string path, const CallbackBase &cb)
1.305 +{
1.306 + class ConnectResolver : public Resolver
1.307 + {
1.308 + public:
1.309 + ConnectResolver (std::string path, const CallbackBase &cb)
1.310 + : Resolver (path),
1.311 + m_cb (cb) {}
1.312 + private:
1.313 + virtual void DoOne (Ptr<Object> object, std::string name) {
1.314 + object->TraceSourceConnect (name, m_cb);
1.315 + }
1.316 + CallbackBase m_cb;
1.317 + } resolver = ConnectResolver (path, cb);
1.318 + for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
1.319 + {
1.320 + resolver.Resolve (*i);
1.321 + }
1.322 +}
1.323 +void
1.324 +ConfigImpl::Disconnect (std::string path, const CallbackBase &cb)
1.325 +{
1.326 + class DisconnectResolver : public Resolver
1.327 + {
1.328 + public:
1.329 + DisconnectResolver (std::string path, const CallbackBase &cb)
1.330 + : Resolver (path),
1.331 + m_cb (cb) {}
1.332 + private:
1.333 + virtual void DoOne (Ptr<Object> object, std::string name) {
1.334 + object->TraceSourceDisconnect (name, m_cb);
1.335 + }
1.336 + CallbackBase m_cb;
1.337 + } resolver = DisconnectResolver (path, cb);
1.338 + for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
1.339 + {
1.340 + resolver.Resolve (*i);
1.341 + }
1.342 +}
1.343 +void
1.344 +ConfigImpl::RegisterRootNamespaceObject (Ptr<Object> obj)
1.345 +{
1.346 + m_roots.push_back (obj);
1.347 +}
1.348 +
1.349 +void
1.350 +ConfigImpl::UnregisterRootNamespaceObject (Ptr<Object> obj)
1.351 +{
1.352 + for (std::vector<Ptr<Object> >::iterator i = m_roots.begin (); i != m_roots.end (); i++)
1.353 + {
1.354 + if (*i == obj)
1.355 + {
1.356 + m_roots.erase (i);
1.357 + return;
1.358 + }
1.359 + }
1.360 +}
1.361 +
1.362 +
1.363 +namespace Config {
1.364 +
1.365 +void Set (std::string path, Attribute value)
1.366 +{
1.367 + Singleton<ConfigImpl>::Get ()->Set (path, value);
1.368 +}
1.369 +void SetDefault (std::string name, Attribute value)
1.370 +{
1.371 + AttributeList::GetGlobal ()->Set (name, value);
1.372 +}
1.373 +void SetGlobal (std::string name, Attribute value)
1.374 +{
1.375 + GlobalValue::Bind (name, value);
1.376 +}
1.377 +void Connect (std::string path, const CallbackBase &cb)
1.378 +{
1.379 + Singleton<ConfigImpl>::Get ()->Connect (path, cb);
1.380 +}
1.381 +void Disconnect (std::string path, const CallbackBase &cb)
1.382 +{
1.383 + Singleton<ConfigImpl>::Get ()->Disconnect (path, cb);
1.384 +}
1.385 +
1.386 +void RegisterRootNamespaceObject (Ptr<Object> obj)
1.387 +{
1.388 + Singleton<ConfigImpl>::Get ()->RegisterRootNamespaceObject (obj);
1.389 +}
1.390 +
1.391 +void Unregister (Ptr<Object> obj)
1.392 +{
1.393 + Singleton<ConfigImpl>::Get ()->UnregisterRootNamespaceObject (obj);
1.394 +}
1.395 +
1.396 +} // namespace Config
1.397 +
1.398 +} // namespace ns3
1.399 +
1.400 +#ifdef RUN_SELF_TESTS
1.401 +
1.402 +#include "test.h"
1.403 +#include "integer.h"
1.404 +
1.405 +namespace ns3 {
1.406 +
1.407 +class MyNode : public Object
1.408 +{
1.409 +public:
1.410 + static TypeId GetTypeId (void);
1.411 +
1.412 + void AddNodeA (Ptr<MyNode> a);
1.413 + void AddNodeB (Ptr<MyNode> b);
1.414 +
1.415 + void SetNodeA (Ptr<MyNode> a);
1.416 + void SetNodeB (Ptr<MyNode> b);
1.417 +
1.418 + int8_t GetA (void) const;
1.419 + int8_t GetB (void) const;
1.420 +
1.421 +private:
1.422 + std::vector<Ptr<MyNode> > m_nodesA;
1.423 + std::vector<Ptr<MyNode> > m_nodesB;
1.424 + Ptr<MyNode> m_nodeA;
1.425 + Ptr<MyNode> m_nodeB;
1.426 + int8_t m_a;
1.427 + int8_t m_b;
1.428 +};
1.429 +
1.430 +TypeId MyNode::GetTypeId (void)
1.431 +{
1.432 + static TypeId tid = TypeId ("MyNode")
1.433 + .SetParent<Object> ()
1.434 + .AddAttribute ("NodesA", "",
1.435 + ObjectVector (),
1.436 + MakeObjectVectorAccessor (&MyNode::m_nodesA),
1.437 + MakeObjectVectorChecker ())
1.438 + .AddAttribute ("NodesB", "",
1.439 + ObjectVector (),
1.440 + MakeObjectVectorAccessor (&MyNode::m_nodesB),
1.441 + MakeObjectVectorChecker ())
1.442 + .AddAttribute ("NodeA", "",
1.443 + Ptr<MyNode> (0),
1.444 + MakePtrAccessor (&MyNode::m_nodeA),
1.445 + MakePtrChecker<MyNode> ())
1.446 + .AddAttribute ("NodeB", "",
1.447 + Ptr<MyNode> (0),
1.448 + MakePtrAccessor (&MyNode::m_nodeB),
1.449 + MakePtrChecker<MyNode> ())
1.450 + .AddAttribute ("A", "",
1.451 + Integer (10),
1.452 + MakeIntegerAccessor (&MyNode::m_a),
1.453 + MakeIntegerChecker<int8_t> ())
1.454 + .AddAttribute ("B", "",
1.455 + Integer (9),
1.456 + MakeIntegerAccessor (&MyNode::m_b),
1.457 + MakeIntegerChecker<int8_t> ())
1.458 + ;
1.459 + return tid;
1.460 +}
1.461 +
1.462 +void
1.463 +MyNode::SetNodeA (Ptr<MyNode> a)
1.464 +{
1.465 + m_nodeA = a;
1.466 +}
1.467 +void
1.468 +MyNode::SetNodeB (Ptr<MyNode> b)
1.469 +{
1.470 + m_nodeB = b;
1.471 +}
1.472 +void
1.473 +MyNode::AddNodeA (Ptr<MyNode> a)
1.474 +{
1.475 + m_nodesA.push_back (a);
1.476 +}
1.477 +void
1.478 +MyNode::AddNodeB (Ptr<MyNode> b)
1.479 +{
1.480 + m_nodesB.push_back (b);
1.481 +}
1.482 +int8_t
1.483 +MyNode::GetA (void) const
1.484 +{
1.485 + return m_a;
1.486 +}
1.487 +int8_t
1.488 +MyNode::GetB (void) const
1.489 +{
1.490 + return m_b;
1.491 +}
1.492 +
1.493 +
1.494 +class ConfigTest : public Test
1.495 +{
1.496 +public:
1.497 + ConfigTest ();
1.498 + virtual bool RunTests (void);
1.499 +};
1.500 +
1.501 +static ConfigTest g_configTestUnique;
1.502 +
1.503 +ConfigTest::ConfigTest ()
1.504 + : Test ("Config")
1.505 +{}
1.506 +
1.507 +bool
1.508 +ConfigTest::RunTests (void)
1.509 +{
1.510 + bool result = true;
1.511 +
1.512 + Ptr<MyNode> root = CreateObject<MyNode> ();
1.513 + Config::RegisterRootNamespaceObject (root);
1.514 + Config::Set ("/A", Integer (1));
1.515 + Config::Set ("/B", Integer (-1));
1.516 + Integer v = root->GetAttribute ("A");
1.517 + NS_TEST_ASSERT_EQUAL (v.Get (), 1);
1.518 + v = root->GetAttribute ("B");
1.519 + NS_TEST_ASSERT_EQUAL (v.Get (), -1);
1.520 +
1.521 + Ptr<MyNode> a = CreateObject<MyNode> ();
1.522 + root->SetNodeA (a);
1.523 + Config::Set ("/NodeA/A", Integer (2));
1.524 + Config::Set ("/NodeA/B", Integer (-2));
1.525 + v = a->GetAttribute ("A");
1.526 + NS_TEST_ASSERT_EQUAL (v.Get (), 2);
1.527 + v = a->GetAttribute ("B");
1.528 + NS_TEST_ASSERT_EQUAL (v.Get (), -2);
1.529 + Config::Set ("/NodeB/A", Integer (3));
1.530 + Config::Set ("/NodeB/B", Integer (-3));
1.531 + v = a->GetAttribute ("A");
1.532 + NS_TEST_ASSERT_EQUAL (v.Get (), 2);
1.533 + v = a->GetAttribute ("B");
1.534 + NS_TEST_ASSERT_EQUAL (v.Get (), -2);
1.535 +
1.536 + Ptr<MyNode> b = CreateObject<MyNode> ();
1.537 + a->SetNodeB (b);
1.538 + Config::Set ("/NodeA/NodeB/A", Integer (4));
1.539 + Config::Set ("/NodeA/NodeB/B", Integer (-4));
1.540 + v = b->GetAttribute ("A");
1.541 + NS_TEST_ASSERT_EQUAL (v.Get (), 4);
1.542 + v = b->GetAttribute ("B");
1.543 + NS_TEST_ASSERT_EQUAL (v.Get (), -4);
1.544 +
1.545 + Ptr<MyNode> c = CreateObject<MyNode> ();
1.546 + root->SetNodeB (c);
1.547 + Config::Set ("/NodeB/A", Integer (5));
1.548 + Config::Set ("/NodeB/B", Integer (-5));
1.549 + v = c->GetAttribute ("A");
1.550 + NS_TEST_ASSERT_EQUAL (v.Get (), 5);
1.551 + v = c->GetAttribute ("B");
1.552 + NS_TEST_ASSERT_EQUAL (v.Get (), -5);
1.553 +
1.554 +
1.555 + Ptr<MyNode> d0 = CreateObject<MyNode> ();
1.556 + Ptr<MyNode> d1 = CreateObject<MyNode> ();
1.557 + Ptr<MyNode> d2 = CreateObject<MyNode> ();
1.558 + Ptr<MyNode> d3 = CreateObject<MyNode> ();
1.559 + b->AddNodeB (d0);
1.560 + b->AddNodeB (d1);
1.561 + b->AddNodeB (d2);
1.562 + b->AddNodeB (d3);
1.563 + Config::Set ("/NodeA/NodeB/NodesB/0/A", Integer (-11));
1.564 + v = d0->GetAttribute ("A");
1.565 + NS_TEST_ASSERT_EQUAL (v.Get (), -11);
1.566 + v = d0->GetAttribute ("B");
1.567 + NS_TEST_ASSERT_EQUAL (v.Get (), 9);
1.568 + v = d1->GetAttribute ("A");
1.569 + NS_TEST_ASSERT_EQUAL (v.Get (), 10);
1.570 + v = d1->GetAttribute ("B");
1.571 + NS_TEST_ASSERT_EQUAL (v.Get (), 9);
1.572 + Config::Set ("/NodeA/NodeB/NodesB/0|1/A", Integer (-12));
1.573 + v = d0->GetAttribute ("A");
1.574 + NS_TEST_ASSERT_EQUAL (v.Get (), -12);
1.575 + v = d1->GetAttribute ("A");
1.576 + NS_TEST_ASSERT_EQUAL (v.Get (), -12);
1.577 + Config::Set ("/NodeA/NodeB/NodesB/|0|1|/A", Integer (-13));
1.578 + v = d0->GetAttribute ("A");
1.579 + NS_TEST_ASSERT_EQUAL (v.Get (), -13);
1.580 + v = d1->GetAttribute ("A");
1.581 + NS_TEST_ASSERT_EQUAL (v.Get (), -13);
1.582 + Config::Set ("/NodeA/NodeB/NodesB/[0-2]/A", Integer (-14));
1.583 + v = d0->GetAttribute ("A");
1.584 + NS_TEST_ASSERT_EQUAL (v.Get (), -14);
1.585 + v = d1->GetAttribute ("A");
1.586 + NS_TEST_ASSERT_EQUAL (v.Get (), -14);
1.587 + v = d2->GetAttribute ("A");
1.588 + NS_TEST_ASSERT_EQUAL (v.Get (), -14);
1.589 + Config::Set ("/NodeA/NodeB/NodesB/[1-3]/A", Integer (-15));
1.590 + v = d0->GetAttribute ("A");
1.591 + NS_TEST_ASSERT_EQUAL (v.Get (), -14);
1.592 + v = d1->GetAttribute ("A");
1.593 + NS_TEST_ASSERT_EQUAL (v.Get (), -15);
1.594 + v = d2->GetAttribute ("A");
1.595 + NS_TEST_ASSERT_EQUAL (v.Get (), -15);
1.596 + v = d3->GetAttribute ("A");
1.597 + NS_TEST_ASSERT_EQUAL (v.Get (), -15);
1.598 + Config::Set ("/NodeA/NodeB/NodesB/[0-1]|3/A", Integer (-16));
1.599 + v = d0->GetAttribute ("A");
1.600 + NS_TEST_ASSERT_EQUAL (v.Get (), -16);
1.601 + v = d1->GetAttribute ("A");
1.602 + NS_TEST_ASSERT_EQUAL (v.Get (), -15);
1.603 + v = d2->GetAttribute ("A");
1.604 + NS_TEST_ASSERT_EQUAL (v.Get (), -16);
1.605 + v = d3->GetAttribute ("A");
1.606 + NS_TEST_ASSERT_EQUAL (v.Get (), -16);
1.607 +
1.608 +
1.609 +
1.610 +
1.611 +
1.612 + return result;
1.613 +}
1.614 +
1.615 +} // namespace ns3
1.616 +
1.617 +
1.618 +#endif /* RUN_SELF_TEST */
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/src/core/config.h Tue Feb 26 01:07:16 2008 +0100
2.3 @@ -0,0 +1,25 @@
2.4 +#ifndef CONFIG_H
2.5 +#define CONFIG_H
2.6 +
2.7 +#include "attribute.h"
2.8 +#include "ptr.h"
2.9 +#include "object.h"
2.10 +#include <string>
2.11 +
2.12 +namespace ns3 {
2.13 +
2.14 +namespace Config {
2.15 +
2.16 +void Set (std::string path, Attribute value);
2.17 +void SetDefault (std::string name, Attribute value);
2.18 +void SetGlobal (std::string name, Attribute value);
2.19 +void Connect (std::string path, const CallbackBase &cb);
2.20 +void Disconnect (std::string path, const CallbackBase &cb);
2.21 +
2.22 +void RegisterRootNamespaceObject (Ptr<Object> obj);
2.23 +
2.24 +} // namespace Config
2.25 +
2.26 +} // namespace ns3
2.27 +
2.28 +#endif /* CONFIG_H */
3.1 --- a/src/core/wscript Mon Feb 25 22:08:56 2008 +0100
3.2 +++ b/src/core/wscript Tue Feb 26 01:07:16 2008 +0100
3.3 @@ -65,6 +65,7 @@
3.4 'global-value.cc',
3.5 'event-trace-source.cc',
3.6 'trace-source-accessor.cc',
3.7 + 'config.cc',
3.8 ]
3.9
3.10 if sys.platform == 'win32':
3.11 @@ -122,5 +123,6 @@
3.12 'event-trace-source.h',
3.13 'value-trace-source.h',
3.14 'trace-source-accessor.h',
3.15 + 'config.h',
3.16 ]
3.17