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

(-)a/src/core/config.cc (-124 / +209 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
      // no slash at start
247
      m_path = "/" + m_path;
248
    }
249
  tmp = m_path.find_last_of ("/");
250
  if (tmp != (m_path.size () - 1))
251
    {
252
      // no slash at end
253
      m_path = m_path + "/";
254
    }
255
}
142
256
143
void 
257
void 
144
Resolver::Resolve (Ptr<Object> root)
258
Resolver::Resolve (Ptr<Object> root)
 Lines 147-186    Link Here 
147
}
261
}
148
262
149
std::string
263
std::string
150
Resolver::GetResolvedPath (std::string name) const
264
Resolver::GetResolvedPath (void) const
151
{
265
{
152
  std::string fullPath = "";
266
  std::string fullPath = "/";
153
  for (std::vector<std::string>::const_iterator i = m_workStack.begin (); i != m_workStack.end (); i++)
267
  for (std::vector<std::string>::const_iterator i = m_workStack.begin (); i != m_workStack.end (); i++)
154
    {
268
    {
155
      fullPath += "/" + *i;
269
      fullPath += *i + "/";
156
    }
270
    }
157
  fullPath += "/" + name;
158
  return fullPath;
271
  return fullPath;
159
}
272
}
160
273
161
void 
274
void 
162
Resolver::DoResolveOne (Ptr<Object> object, std::string name)
275
Resolver::DoResolveOne (Ptr<Object> object)
163
{
276
{
164
  NS_LOG_DEBUG ("resolved="<<GetResolvedPath (name));
277
  NS_LOG_DEBUG ("resolved="<<GetResolvedPath ());
165
  DoOne (object, GetResolvedPath (name), name);
278
  DoOne (object, GetResolvedPath ());
166
}
279
}
167
280
168
void
281
void
169
Resolver::DoResolve (std::string path, Ptr<Object> root)
282
Resolver::DoResolve (std::string path, Ptr<Object> root)
170
{
283
{
171
  NS_ASSERT (path != "");
284
  NS_LOG_FUNCTION (path << root);
172
  std::string::size_type pos = path.find ("/");
285
  std::string::size_type tmp;
173
  if (pos != 0)
286
  tmp = path.find ("/");
174
    {
287
  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);
288
  std::string::size_type next = path.find ("/", 1);
179
  if (next == std::string::npos)
289
  if (next == std::string::npos)
180
    {
290
    {
181
      std::string attributeName = path.substr (1, path.size ()-1);
291
      DoResolveOne (root);
182
      NS_LOG_DEBUG ("handle attr="<<attributeName);
183
      DoOne (root, GetResolvedPath (attributeName), attributeName);
184
      return;
292
      return;
185
    }
293
    }
186
  std::string item = path.substr (1, next-1);
294
  std::string item = path.substr (1, next-1);
 Lines 191-202    Link Here 
191
    {
299
    {
192
      // This is a call to GetObject
300
      // This is a call to GetObject
193
      std::string tidString = item.substr (1, item.size () - 1);
301
      std::string tidString = item.substr (1, item.size () - 1);
194
      NS_LOG_DEBUG ("GetObject="<<tidString<<" on path="<<GetResolvedPath (""));
302
      NS_LOG_DEBUG ("GetObject="<<tidString<<" on path="<<GetResolvedPath ());
195
      TypeId tid = TypeId::LookupByName (tidString);
303
      TypeId tid = TypeId::LookupByName (tidString);
196
      Ptr<Object> object = root->GetObject<Object> (tid);
304
      Ptr<Object> object = root->GetObject<Object> (tid);
197
      if (object == 0)
305
      if (object == 0)
198
	{
306
	{
199
	  NS_LOG_DEBUG ("GetObject ("<<tidString<<") failed on path="<<GetResolvedPath (""));
307
	  NS_LOG_DEBUG ("GetObject ("<<tidString<<") failed on path="<<GetResolvedPath ());
200
	  return;
308
	  return;
201
	}
309
	}
202
      m_workStack.push_back (item);
310
      m_workStack.push_back (item);
 Lines 210-230    Link Here 
210
      struct TypeId::AttributeInfo info;
318
      struct TypeId::AttributeInfo info;
211
      if (!tid.LookupAttributeByName (item, &info))
319
      if (!tid.LookupAttributeByName (item, &info))
212
	{
320
	{
213
	  NS_LOG_DEBUG ("Requested item="<<item<<" does not exist on path="<<GetResolvedPath (""));
321
	  NS_LOG_DEBUG ("Requested item="<<item<<" does not exist on path="<<GetResolvedPath ());
214
	  return;
322
	  return;
215
	}
323
	}
216
      // attempt to cast to a pointer checker.
324
      // attempt to cast to a pointer checker.
217
      const PointerChecker *ptr = dynamic_cast<const PointerChecker *> (PeekPointer (info.checker));
325
      const PointerChecker *ptr = dynamic_cast<const PointerChecker *> (PeekPointer (info.checker));
218
      if (ptr != 0)
326
      if (ptr != 0)
219
	{
327
	{
220
	  NS_LOG_DEBUG ("GetAttribute(ptr)="<<item<<" on path="<<GetResolvedPath (""));
328
	  NS_LOG_DEBUG ("GetAttribute(ptr)="<<item<<" on path="<<GetResolvedPath ());
221
          PointerValue ptr;
329
          PointerValue ptr;
222
          root->GetAttribute (item, ptr);
330
          root->GetAttribute (item, ptr);
223
	  Ptr<Object> object = ptr.Get<Object> ();
331
	  Ptr<Object> object = ptr.Get<Object> ();
224
	  if (object == 0)
332
	  if (object == 0)
225
	    {
333
	    {
226
	      NS_LOG_ERROR ("Requested object name=\""<<item<<
334
	      NS_LOG_ERROR ("Requested object name=\""<<item<<
227
			    "\" exists on path=\""<<GetResolvedPath ("")<<"\""
335
			    "\" exists on path=\""<<GetResolvedPath ()<<"\""
228
			    " but is null.");
336
			    " but is null.");
229
	      return;
337
	      return;
230
	    }
338
	    }
 Lines 236-242    Link Here 
236
      const ObjectVectorChecker *vectorChecker = dynamic_cast<const ObjectVectorChecker *> (PeekPointer (info.checker));
344
      const ObjectVectorChecker *vectorChecker = dynamic_cast<const ObjectVectorChecker *> (PeekPointer (info.checker));
237
      if (vectorChecker != 0)
345
      if (vectorChecker != 0)
238
	{
346
	{
239
	  NS_LOG_DEBUG ("GetAttribute(vector)="<<item<<" on path="<<GetResolvedPath (""));
347
	  NS_LOG_DEBUG ("GetAttribute(vector)="<<item<<" on path="<<GetResolvedPath ());
240
	  ObjectVectorValue vector;
348
	  ObjectVectorValue vector;
241
          root->GetAttribute (item, vector);
349
          root->GetAttribute (item, vector);
242
	  m_workStack.push_back (item);
350
	  m_workStack.push_back (item);
 Lines 252-268    Link Here 
252
Resolver::DoArrayResolve (std::string path, const ObjectVectorValue &vector)
360
Resolver::DoArrayResolve (std::string path, const ObjectVectorValue &vector)
253
{
361
{
254
  NS_ASSERT (path != "");
362
  NS_ASSERT (path != "");
255
  std::string::size_type pos = path.find ("/");
363
  std::string::size_type tmp;
256
  if (pos != 0)
364
  tmp = path.find ("/");
257
    {
365
  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);
366
  std::string::size_type next = path.find ("/", 1);
262
  if (next == std::string::npos)
367
  if (next == std::string::npos)
263
    {
368
    {
264
      NS_LOG_DEBUG ("vector path includes no index data on path=\""<<path<<"\"");
369
      NS_FATAL_ERROR ("vector path includes no index data on path=\""<<path<<"\"");
265
      return;
266
    }
370
    }
267
  std::string item = path.substr (1, next-1);
371
  std::string item = path.substr (1, next-1);
268
  std::string pathLeft = path.substr (next, path.size ()-next);
372
  std::string pathLeft = path.substr (next, path.size ()-next);
 Lines 290-295    Link Here 
290
  void Connect (std::string path, const CallbackBase &cb);
394
  void Connect (std::string path, const CallbackBase &cb);
291
  void DisconnectWithoutContext (std::string path, const CallbackBase &cb);
395
  void DisconnectWithoutContext (std::string path, const CallbackBase &cb);
292
  void Disconnect (std::string path, const CallbackBase &cb);
396
  void Disconnect (std::string path, const CallbackBase &cb);
397
  Config::MatchContainer LookupMatches (std::string path);
293
398
294
  void RegisterRootNamespaceObject (Ptr<Object> obj);
399
  void RegisterRootNamespaceObject (Ptr<Object> obj);
295
  void UnregisterRootNamespaceObject (Ptr<Object> obj);
400
  void UnregisterRootNamespaceObject (Ptr<Object> obj);
 Lines 298-407    Link Here 
298
  Ptr<Object> GetRootNamespaceObject (uint32_t i) const;
403
  Ptr<Object> GetRootNamespaceObject (uint32_t i) const;
299
  
404
  
300
private:
405
private:
406
  void ParsePath (std::string path, std::string *root, std::string *leaf) const;
301
  typedef std::vector<Ptr<Object> > Roots;
407
  typedef std::vector<Ptr<Object> > Roots;
302
  Roots m_roots;
408
  Roots m_roots;
303
};
409
};
304
410
305
void 
411
void 
412
ConfigImpl::ParsePath (std::string path, std::string *root, std::string *leaf) const
413
{
414
  std::string::size_type slash = path.find_last_of ("/");
415
  NS_ASSERT (slash != std::string::npos);
416
  *root = path.substr (0, slash);
417
  *leaf = path.substr (slash+1, path.size ()-(slash+1));
418
  NS_LOG_FUNCTION (path << *root << *leaf);
419
}
420
421
void 
306
ConfigImpl::Set (std::string path, const AttributeValue &value)
422
ConfigImpl::Set (std::string path, const AttributeValue &value)
307
{
423
{
308
  class SetResolver : public Resolver 
424
  std::string root, leaf;
425
  ParsePath (path, &root, &leaf);
426
  Config::MatchContainer container = LookupMatches (root);
427
  container.Set (leaf, value);
428
}
429
void 
430
ConfigImpl::ConnectWithoutContext (std::string path, const CallbackBase &cb)
431
{
432
  std::string root, leaf;
433
  ParsePath (path, &root, &leaf);
434
  Config::MatchContainer container = LookupMatches (root);
435
  container.ConnectWithoutContext (leaf, cb);
436
}
437
void 
438
ConfigImpl::DisconnectWithoutContext (std::string path, const CallbackBase &cb)
439
{
440
  std::string root, leaf;
441
  ParsePath (path, &root, &leaf);
442
  Config::MatchContainer container = LookupMatches (root);
443
  container.DisconnectWithoutContext (leaf, cb);
444
}
445
void 
446
ConfigImpl::Connect (std::string path, const CallbackBase &cb)
447
{
448
  std::string root, leaf;
449
  ParsePath (path, &root, &leaf);
450
  Config::MatchContainer container = LookupMatches (root);
451
  container.Connect (leaf, cb);
452
}
453
void 
454
ConfigImpl::Disconnect (std::string path, const CallbackBase &cb)
455
{
456
  std::string root, leaf;
457
  ParsePath (path, &root, &leaf);
458
  Config::MatchContainer container = LookupMatches (root);
459
  container.Disconnect (leaf, cb);
460
}
461
462
Config::MatchContainer 
463
ConfigImpl::LookupMatches (std::string path)
464
{
465
  NS_LOG_FUNCTION (path);
466
  class LookupMatchesResolver : public Resolver 
309
  {
467
  {
310
  public:
468
  public:
311
    SetResolver (std::string path, const AttributeValue &value)
469
    LookupMatchesResolver (std::string path)
312
      : Resolver (path),
470
      : Resolver (path)
313
	m_value (value.Copy ()) {}
471
    {}
314
  private:
472
    virtual void DoOne (Ptr<Object> object, std::string path) {
315
    virtual void DoOne (Ptr<Object> object, std::string path, std::string name) {
473
      m_objects.push_back (object);
316
      object->SetAttribute (name, *m_value);
474
      m_contexts.push_back (path);
317
    }
475
    }
318
    Ptr<const AttributeValue> m_value;
476
    std::vector<Ptr<Object> > m_objects;
319
  } resolver = SetResolver (path, value);
477
    std::vector<std::string> m_contexts;
478
  } resolver = LookupMatchesResolver (path);
320
  for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
479
  for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
321
    {
480
    {
322
      resolver.Resolve (*i);
481
      resolver.Resolve (*i);
323
    }
482
    }
483
  return Config::MatchContainer (resolver.m_objects, resolver.m_contexts, path);
324
}
484
}
325
void 
485
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 
486
void 
406
ConfigImpl::RegisterRootNamespaceObject (Ptr<Object> obj)
487
ConfigImpl::RegisterRootNamespaceObject (Ptr<Object> obj)
407
{
488
{
 Lines 471-476    Link Here 
471
Disconnect (std::string path, const CallbackBase &cb)
552
Disconnect (std::string path, const CallbackBase &cb)
472
{
553
{
473
  Singleton<ConfigImpl>::Get ()->Disconnect (path, cb);
554
  Singleton<ConfigImpl>::Get ()->Disconnect (path, cb);
555
}
556
Config::MatchContainer LookupMatches (std::string path)
557
{
558
  return Singleton<ConfigImpl>::Get ()->LookupMatches (path);
474
}
559
}
475
560
476
void RegisterRootNamespaceObject (Ptr<Object> obj)
561
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