View | Details | Raw Unified | Return to bug 284
Collapse All | Expand All

(-)a/src/core/config.cc (-124 / +207 lines)
 Lines 29-34    Link Here 
29
NS_LOG_COMPONENT_DEFINE ("Config");
29
NS_LOG_COMPONENT_DEFINE ("Config");
30
30
31
namespace ns3 {
31
namespace ns3 {
32
33
namespace Config {
34
35
MatchContainer::MatchContainer ()
36
{}
37
MatchContainer::MatchContainer (const std::vector<Ptr<Object> > &objects, 
38
                                const std::vector<std::string> &contexts,
39
                                std::string path)
40
  : m_objects (objects),
41
    m_contexts (contexts),
42
    m_path (path)
43
{}
44
MatchContainer::Iterator 
45
MatchContainer::Begin (void) const
46
{
47
  return m_objects.begin ();
48
}
49
MatchContainer::Iterator 
50
MatchContainer::End (void) const
51
{
52
  return m_objects.end ();
53
}
54
uint32_t 
55
MatchContainer::GetN (void) const
56
{
57
  return m_objects.size ();
58
}
59
Ptr<Object> 
60
MatchContainer::Get (uint32_t i) const
61
{
62
  return m_objects[i];
63
}
64
std::string 
65
MatchContainer::GetMatchedPath (uint32_t i) const
66
{
67
  return m_contexts[i];
68
}
69
std::string 
70
MatchContainer::GetPath (void) const
71
{
72
  return m_path;
73
}
74
75
void 
76
MatchContainer::Set (std::string name, const AttributeValue &value)
77
{
78
  for (Iterator tmp = Begin (); tmp != End (); ++tmp)
79
    {
80
      Ptr<Object> object = *tmp;
81
      object->SetAttribute (name, value);
82
    }
83
}
84
void 
85
MatchContainer::Connect (std::string name, const CallbackBase &cb)
86
{
87
  NS_ASSERT (m_objects.size () == m_contexts.size ());
88
  for (uint32_t i = 0; i < m_objects.size (); ++i)
89
    {
90
      Ptr<Object> object = m_objects[i];
91
      std::string ctx = m_contexts[i] + name;
92
      object->TraceConnect (name, ctx, cb);
93
    }
94
}
95
void 
96
MatchContainer::ConnectWithoutContext (std::string name, const CallbackBase &cb)
97
{
98
  for (Iterator tmp = Begin (); tmp != End (); ++tmp)
99
    {
100
      Ptr<Object> object = *tmp;
101
      object->TraceConnectWithoutContext (name, cb);
102
    }
103
}
104
void 
105
MatchContainer::Disconnect (std::string name, const CallbackBase &cb)
106
{
107
  NS_ASSERT (m_objects.size () == m_contexts.size ());
108
  for (uint32_t i = 0; i < m_objects.size (); ++i)
109
    {
110
      Ptr<Object> object = m_objects[i];
111
      std::string ctx = m_contexts[i] + name;
112
      object->TraceDisconnect (name, ctx, cb);
113
    }
114
}
115
void 
116
MatchContainer::DisconnectWithoutContext (std::string name, const CallbackBase &cb)
117
{
118
  for (Iterator tmp = Begin (); tmp != End (); ++tmp)
119
    {
120
      Ptr<Object> object = *tmp;
121
      object->TraceDisconnectWithoutContext (name, cb);
122
    }
123
}
124
125
} // namespace Config
32
126
33
class ArrayMatcher
127
class ArrayMatcher
34
{
128
{
 Lines 125-144    Link Here 
125
219
126
  void Resolve (Ptr<Object> root);
220
  void Resolve (Ptr<Object> root);
127
private:
221
private:
222
  void Canonicalize (void);
128
  void DoResolve (std::string path, Ptr<Object> root);
223
  void DoResolve (std::string path, Ptr<Object> root);
129
  void DoArrayResolve (std::string path, const ObjectVectorValue &vector);
224
  void DoArrayResolve (std::string path, const ObjectVectorValue &vector);
130
  void DoResolveOne (Ptr<Object> object, std::string name);
225
  void DoResolveOne (Ptr<Object> object);
131
  std::string GetResolvedPath (std::string name) const;
226
  std::string GetResolvedPath (void) const;
132
  virtual void DoOne (Ptr<Object> object, std::string path, std::string name) = 0;
227
  virtual void DoOne (Ptr<Object> object, std::string path) = 0;
133
  std::vector<std::string> m_workStack;
228
  std::vector<std::string> m_workStack;
134
  std::string m_path;
229
  std::string m_path;
135
};
230
};
136
231
137
Resolver::Resolver (std::string path)
232
Resolver::Resolver (std::string path)
138
  : m_path (path)
233
  : m_path (path)
139
{}
234
{
235
  Canonicalize ();
236
}
140
Resolver::~Resolver ()
237
Resolver::~Resolver ()
141
{}
238
{}
239
void
240
Resolver::Canonicalize (void)
241
{
242
  // ensure that we start and end with a '/'
243
  std::string::size_type tmp = m_path.find ("/");
244
  if (tmp != 0)
245
    {
246
      m_path = "/" + m_path;
247
    }
248
  tmp = m_path.find_last_of ("/", 1);
249
  if (tmp != (m_path.size () - 1))
250
    {
251
      m_path = m_path + "/";
252
    }
253
}
142
254
143
void 
255
void 
144
Resolver::Resolve (Ptr<Object> root)
256
Resolver::Resolve (Ptr<Object> root)
 Lines 147-186    Link Here 
147
}
259
}
148
260
149
std::string
261
std::string
150
Resolver::GetResolvedPath (std::string name) const
262
Resolver::GetResolvedPath (void) const
151
{
263
{
152
  std::string fullPath = "";
264
  std::string fullPath = "/";
153
  for (std::vector<std::string>::const_iterator i = m_workStack.begin (); i != m_workStack.end (); i++)
265
  for (std::vector<std::string>::const_iterator i = m_workStack.begin (); i != m_workStack.end (); i++)
154
    {
266
    {
155
      fullPath += "/" + *i;
267
      fullPath += *i + "/";
156
    }
268
    }
157
  fullPath += "/" + name;
158
  return fullPath;
269
  return fullPath;
159
}
270
}
160
271
161
void 
272
void 
162
Resolver::DoResolveOne (Ptr<Object> object, std::string name)
273
Resolver::DoResolveOne (Ptr<Object> object)
163
{
274
{
164
  NS_LOG_DEBUG ("resolved="<<GetResolvedPath (name));
275
  NS_LOG_DEBUG ("resolved="<<GetResolvedPath ());
165
  DoOne (object, GetResolvedPath (name), name);
276
  DoOne (object, GetResolvedPath ());
166
}
277
}
167
278
168
void
279
void
169
Resolver::DoResolve (std::string path, Ptr<Object> root)
280
Resolver::DoResolve (std::string path, Ptr<Object> root)
170
{
281
{
171
  NS_ASSERT (path != "");
282
  NS_LOG_FUNCTION (path << root);
172
  std::string::size_type pos = path.find ("/");
283
  std::string::size_type tmp;
173
  if (pos != 0)
284
  tmp = path.find ("/");
174
    {
285
  NS_ASSERT (tmp == 0);
175
      NS_FATAL_ERROR ("path does not start with a \"/\": \""<<path<<"\"");
176
      return;
177
    }
178
  std::string::size_type next = path.find ("/", 1);
286
  std::string::size_type next = path.find ("/", 1);
179
  if (next == std::string::npos)
287
  if (next == std::string::npos)
180
    {
288
    {
181
      std::string attributeName = path.substr (1, path.size ()-1);
289
      DoResolveOne (root);
182
      NS_LOG_DEBUG ("handle attr="<<attributeName);
183
      DoOne (root, GetResolvedPath (attributeName), attributeName);
184
      return;
290
      return;
185
    }
291
    }
186
  std::string item = path.substr (1, next-1);
292
  std::string item = path.substr (1, next-1);
 Lines 191-202    Link Here 
191
    {
297
    {
192
      // This is a call to GetObject
298
      // This is a call to GetObject
193
      std::string tidString = item.substr (1, item.size () - 1);
299
      std::string tidString = item.substr (1, item.size () - 1);
194
      NS_LOG_DEBUG ("GetObject="<<tidString<<" on path="<<GetResolvedPath (""));
300
      NS_LOG_DEBUG ("GetObject="<<tidString<<" on path="<<GetResolvedPath ());
195
      TypeId tid = TypeId::LookupByName (tidString);
301
      TypeId tid = TypeId::LookupByName (tidString);
196
      Ptr<Object> object = root->GetObject<Object> (tid);
302
      Ptr<Object> object = root->GetObject<Object> (tid);
197
      if (object == 0)
303
      if (object == 0)
198
	{
304
	{
199
	  NS_LOG_DEBUG ("GetObject ("<<tidString<<") failed on path="<<GetResolvedPath (""));
305
	  NS_LOG_DEBUG ("GetObject ("<<tidString<<") failed on path="<<GetResolvedPath ());
200
	  return;
306
	  return;
201
	}
307
	}
202
      m_workStack.push_back (item);
308
      m_workStack.push_back (item);
 Lines 210-230    Link Here 
210
      struct TypeId::AttributeInfo info;
316
      struct TypeId::AttributeInfo info;
211
      if (!tid.LookupAttributeByName (item, &info))
317
      if (!tid.LookupAttributeByName (item, &info))
212
	{
318
	{
213
	  NS_LOG_DEBUG ("Requested item="<<item<<" does not exist on path="<<GetResolvedPath (""));
319
	  NS_LOG_DEBUG ("Requested item="<<item<<" does not exist on path="<<GetResolvedPath ());
214
	  return;
320
	  return;
215
	}
321
	}
216
      // attempt to cast to a pointer checker.
322
      // attempt to cast to a pointer checker.
217
      const PointerChecker *ptr = dynamic_cast<const PointerChecker *> (PeekPointer (info.checker));
323
      const PointerChecker *ptr = dynamic_cast<const PointerChecker *> (PeekPointer (info.checker));
218
      if (ptr != 0)
324
      if (ptr != 0)
219
	{
325
	{
220
	  NS_LOG_DEBUG ("GetAttribute(ptr)="<<item<<" on path="<<GetResolvedPath (""));
326
	  NS_LOG_DEBUG ("GetAttribute(ptr)="<<item<<" on path="<<GetResolvedPath ());
221
          PointerValue ptr;
327
          PointerValue ptr;
222
          root->GetAttribute (item, ptr);
328
          root->GetAttribute (item, ptr);
223
	  Ptr<Object> object = ptr.Get<Object> ();
329
	  Ptr<Object> object = ptr.Get<Object> ();
224
	  if (object == 0)
330
	  if (object == 0)
225
	    {
331
	    {
226
	      NS_LOG_ERROR ("Requested object name=\""<<item<<
332
	      NS_LOG_ERROR ("Requested object name=\""<<item<<
227
			    "\" exists on path=\""<<GetResolvedPath ("")<<"\""
333
			    "\" exists on path=\""<<GetResolvedPath ()<<"\""
228
			    " but is null.");
334
			    " but is null.");
229
	      return;
335
	      return;
230
	    }
336
	    }
 Lines 236-242    Link Here 
236
      const ObjectVectorChecker *vectorChecker = dynamic_cast<const ObjectVectorChecker *> (PeekPointer (info.checker));
342
      const ObjectVectorChecker *vectorChecker = dynamic_cast<const ObjectVectorChecker *> (PeekPointer (info.checker));
237
      if (vectorChecker != 0)
343
      if (vectorChecker != 0)
238
	{
344
	{
239
	  NS_LOG_DEBUG ("GetAttribute(vector)="<<item<<" on path="<<GetResolvedPath (""));
345
	  NS_LOG_DEBUG ("GetAttribute(vector)="<<item<<" on path="<<GetResolvedPath ());
240
	  ObjectVectorValue vector;
346
	  ObjectVectorValue vector;
241
          root->GetAttribute (item, vector);
347
          root->GetAttribute (item, vector);
242
	  m_workStack.push_back (item);
348
	  m_workStack.push_back (item);
 Lines 252-268    Link Here 
252
Resolver::DoArrayResolve (std::string path, const ObjectVectorValue &vector)
358
Resolver::DoArrayResolve (std::string path, const ObjectVectorValue &vector)
253
{
359
{
254
  NS_ASSERT (path != "");
360
  NS_ASSERT (path != "");
255
  std::string::size_type pos = path.find ("/");
361
  std::string::size_type tmp;
256
  if (pos != 0)
362
  tmp = path.find ("/");
257
    {
363
  NS_ASSERT (tmp == 0);
258
      NS_FATAL_ERROR ("path does not start with a \"/\": \""<<path<<"\"");
259
      return;
260
    }
261
  std::string::size_type next = path.find ("/", 1);
364
  std::string::size_type next = path.find ("/", 1);
262
  if (next == std::string::npos)
365
  if (next == std::string::npos)
263
    {
366
    {
264
      NS_LOG_DEBUG ("vector path includes no index data on path=\""<<path<<"\"");
367
      NS_FATAL_ERROR ("vector path includes no index data on path=\""<<path<<"\"");
265
      return;
266
    }
368
    }
267
  std::string item = path.substr (1, next-1);
369
  std::string item = path.substr (1, next-1);
268
  std::string pathLeft = path.substr (next, path.size ()-next);
370
  std::string pathLeft = path.substr (next, path.size ()-next);
 Lines 290-295    Link Here 
290
  void Connect (std::string path, const CallbackBase &cb);
392
  void Connect (std::string path, const CallbackBase &cb);
291
  void DisconnectWithoutContext (std::string path, const CallbackBase &cb);
393
  void DisconnectWithoutContext (std::string path, const CallbackBase &cb);
292
  void Disconnect (std::string path, const CallbackBase &cb);
394
  void Disconnect (std::string path, const CallbackBase &cb);
395
  Config::MatchContainer LookupMatches (std::string path);
293
396
294
  void RegisterRootNamespaceObject (Ptr<Object> obj);
397
  void RegisterRootNamespaceObject (Ptr<Object> obj);
295
  void UnregisterRootNamespaceObject (Ptr<Object> obj);
398
  void UnregisterRootNamespaceObject (Ptr<Object> obj);
 Lines 298-407    Link Here 
298
  Ptr<Object> GetRootNamespaceObject (uint32_t i) const;
401
  Ptr<Object> GetRootNamespaceObject (uint32_t i) const;
299
  
402
  
300
private:
403
private:
404
  void ParsePath (std::string path, std::string *root, std::string *leaf) const;
301
  typedef std::vector<Ptr<Object> > Roots;
405
  typedef std::vector<Ptr<Object> > Roots;
302
  Roots m_roots;
406
  Roots m_roots;
303
};
407
};
304
408
305
void 
409
void 
410
ConfigImpl::ParsePath (std::string path, std::string *root, std::string *leaf) const
411
{
412
  std::string::size_type slash = path.find_last_of ("/");
413
  NS_ASSERT (slash != std::string::npos);
414
  *root = path.substr (0, slash);
415
  *leaf = path.substr (slash+1, path.size ()-(slash+1));
416
  NS_LOG_FUNCTION (path << *root << *leaf);
417
}
418
419
void 
306
ConfigImpl::Set (std::string path, const AttributeValue &value)
420
ConfigImpl::Set (std::string path, const AttributeValue &value)
307
{
421
{
308
  class SetResolver : public Resolver 
422
  std::string root, leaf;
423
  ParsePath (path, &root, &leaf);
424
  Config::MatchContainer container = LookupMatches (root);
425
  container.Set (leaf, value);
426
}
427
void 
428
ConfigImpl::ConnectWithoutContext (std::string path, const CallbackBase &cb)
429
{
430
  std::string root, leaf;
431
  ParsePath (path, &root, &leaf);
432
  Config::MatchContainer container = LookupMatches (root);
433
  container.ConnectWithoutContext (leaf, cb);
434
}
435
void 
436
ConfigImpl::DisconnectWithoutContext (std::string path, const CallbackBase &cb)
437
{
438
  std::string root, leaf;
439
  ParsePath (path, &root, &leaf);
440
  Config::MatchContainer container = LookupMatches (root);
441
  container.DisconnectWithoutContext (leaf, cb);
442
}
443
void 
444
ConfigImpl::Connect (std::string path, const CallbackBase &cb)
445
{
446
  std::string root, leaf;
447
  ParsePath (path, &root, &leaf);
448
  Config::MatchContainer container = LookupMatches (root);
449
  container.Connect (leaf, cb);
450
}
451
void 
452
ConfigImpl::Disconnect (std::string path, const CallbackBase &cb)
453
{
454
  std::string root, leaf;
455
  ParsePath (path, &root, &leaf);
456
  Config::MatchContainer container = LookupMatches (root);
457
  container.Disconnect (leaf, cb);
458
}
459
460
Config::MatchContainer 
461
ConfigImpl::LookupMatches (std::string path)
462
{
463
  NS_LOG_FUNCTION (path);
464
  class LookupMatchesResolver : public Resolver 
309
  {
465
  {
310
  public:
466
  public:
311
    SetResolver (std::string path, const AttributeValue &value)
467
    LookupMatchesResolver (std::string path)
312
      : Resolver (path),
468
      : Resolver (path)
313
	m_value (value.Copy ()) {}
469
    {}
314
  private:
470
    virtual void DoOne (Ptr<Object> object, std::string path) {
315
    virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
471
      m_objects.push_back (object);
316
      object->SetAttribute (name, *m_value);
472
      m_contexts.push_back (path);
317
    }
473
    }
318
    Ptr<const AttributeValue> m_value;
474
    std::vector<Ptr<Object> > m_objects;
319
  } resolver = SetResolver (path, value);
475
    std::vector<std::string> m_contexts;
476
  } resolver = LookupMatchesResolver (path);
320
  for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
477
  for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
321
    {
478
    {
322
      resolver.Resolve (*i);
479
      resolver.Resolve (*i);
323
    }
480
    }
481
  return Config::MatchContainer (resolver.m_objects, resolver.m_contexts, path);
324
}
482
}
325
void 
483
326
ConfigImpl::ConnectWithoutContext (std::string path, const CallbackBase &cb)
327
{
328
  class ConnectResolver : public Resolver 
329
  {
330
  public:
331
    ConnectResolver (std::string path, const CallbackBase &cb)
332
      : Resolver (path),
333
	m_cb (cb) {}
334
  private:
335
    virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
336
      object->TraceConnectWithoutContext (name, m_cb);
337
    }
338
    CallbackBase m_cb;
339
  } resolver = ConnectResolver (path, cb);
340
  for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
341
    {
342
      resolver.Resolve (*i);
343
    }
344
}
345
void 
346
ConfigImpl::DisconnectWithoutContext (std::string path, const CallbackBase &cb)
347
{
348
  class DisconnectResolver : public Resolver 
349
  {
350
  public:
351
    DisconnectResolver (std::string path, const CallbackBase &cb)
352
      : Resolver (path),
353
	m_cb (cb) {}
354
  private:
355
    virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
356
      object->TraceDisconnectWithoutContext (name, m_cb);
357
    }
358
    CallbackBase m_cb;
359
  } resolver = DisconnectResolver (path, cb);
360
  for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
361
    {
362
      resolver.Resolve (*i);
363
    }
364
}
365
void 
366
ConfigImpl::Connect (std::string path, const CallbackBase &cb)
367
{
368
  class ConnectWithContextResolver : public Resolver 
369
  {
370
  public:
371
    ConnectWithContextResolver (std::string path, const CallbackBase &cb)
372
      : Resolver (path),
373
	m_cb (cb) {}
374
  private:
375
    virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
376
      object->TraceConnect (name, path, m_cb);
377
    }
378
    CallbackBase m_cb;
379
  } resolver = ConnectWithContextResolver (path, cb);
380
  for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
381
    {
382
      resolver.Resolve (*i);
383
    }
384
}
385
void 
386
ConfigImpl::Disconnect (std::string path, const CallbackBase &cb)
387
{
388
  class DisconnectWithContextResolver : public Resolver 
389
  {
390
  public:
391
    DisconnectWithContextResolver (std::string path, const CallbackBase &cb)
392
      : Resolver (path),
393
	m_cb (cb) {}
394
  private:
395
    virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
396
      object->TraceDisconnect (name, path, m_cb);
397
    }
398
    CallbackBase m_cb;
399
  } resolver = DisconnectWithContextResolver (path, cb);
400
  for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
401
    {
402
      resolver.Resolve (*i);
403
    }
404
}
405
void 
484
void 
406
ConfigImpl::RegisterRootNamespaceObject (Ptr<Object> obj)
485
ConfigImpl::RegisterRootNamespaceObject (Ptr<Object> obj)
407
{
486
{
 Lines 471-476    Link Here 
471
Disconnect (std::string path, const CallbackBase &cb)
550
Disconnect (std::string path, const CallbackBase &cb)
472
{
551
{
473
  Singleton<ConfigImpl>::Get ()->Disconnect (path, cb);
552
  Singleton<ConfigImpl>::Get ()->Disconnect (path, cb);
553
}
554
Config::MatchContainer LookupMatches (std::string path)
555
{
556
  return Singleton<ConfigImpl>::Get ()->LookupMatches (path);
474
}
557
}
475
558
476
void RegisterRootNamespaceObject (Ptr<Object> obj)
559
void RegisterRootNamespaceObject (Ptr<Object> obj)
(-)a/src/core/config.h (+30 lines)
 Lines 22-27    Link Here 
22
22
23
#include "ptr.h"
23
#include "ptr.h"
24
#include <string>
24
#include <string>
25
#include <vector>
25
26
26
namespace ns3 {
27
namespace ns3 {
27
28
 Lines 110-115    Link Here 
110
 */
111
 */
111
void Disconnect (std::string path, const CallbackBase &cb);
112
void Disconnect (std::string path, const CallbackBase &cb);
112
113
114
class MatchContainer
115
{
116
public:
117
  typedef std::vector<Ptr<Object> >::const_iterator Iterator;
118
  MatchContainer ();
119
  MatchContainer (const std::vector<Ptr<Object> > &objects, 
120
                  const std::vector<std::string> &contexts, 
121
                  std::string path);
122
123
  MatchContainer::Iterator Begin (void) const;
124
  MatchContainer::Iterator End (void) const;
125
  uint32_t GetN (void) const;
126
  Ptr<Object> Get (uint32_t i) const;
127
  std::string GetMatchedPath (uint32_t i) const;
128
  std::string GetPath (void) const;
129
130
  void Set (std::string name, const AttributeValue &value);
131
  void Connect (std::string name, const CallbackBase &cb);
132
  void ConnectWithoutContext (std::string name, const CallbackBase &cb);
133
  void Disconnect (std::string name, const CallbackBase &cb);
134
  void DisconnectWithoutContext (std::string name, const CallbackBase &cb);
135
private:
136
  std::vector<Ptr<Object> > m_objects;
137
  std::vector<std::string> m_contexts;
138
  std::string m_path;
139
};
140
141
MatchContainer LookupMatches (std::string path);
142
113
/**
143
/**
114
 * \param obj a new root object
144
 * \param obj a new root object
115
 *
145
 *

Return to bug 284