src/core/object.cc
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sun, 02 Mar 2008 21:00:37 +0100
changeset 2531 b451b5fc8b57
parent 2529 d5f8bee5fcbd
child 2542 a9b88fdc09d6
permissions -rw-r--r--
implement context-based trace connection
mathieu@699
     1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
mathieu@699
     2
/*
mathieu@699
     3
 * Copyright (c) 2007 INRIA, Gustavo Carneiro
mathieu@699
     4
 *
mathieu@699
     5
 * This program is free software; you can redistribute it and/or modify
mathieu@699
     6
 * it under the terms of the GNU General Public License version 2 as
mathieu@699
     7
 * published by the Free Software Foundation;
mathieu@699
     8
 *
mathieu@699
     9
 * This program is distributed in the hope that it will be useful,
mathieu@699
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
mathieu@699
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mathieu@699
    12
 * GNU General Public License for more details.
mathieu@699
    13
 *
mathieu@699
    14
 * You should have received a copy of the GNU General Public License
mathieu@699
    15
 * along with this program; if not, write to the Free Software
mathieu@699
    16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
mathieu@699
    17
 *
mathieu@699
    18
 * Authors: Gustavo Carneiro <gjcarneiro@gmail.com>,
mathieu@699
    19
 *          Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
mathieu@699
    20
 */
mathieu@706
    21
#include "object.h"
mathieu@699
    22
#include "assert.h"
mathieu@699
    23
#include "singleton.h"
mathieu@1351
    24
#include "trace-resolver.h"
mathieu@2438
    25
#include "attribute.h"
mathieu@2463
    26
#include "trace-source-accessor.h"
craigdo@1504
    27
#include "log.h"
mathieu@2502
    28
#include "string.h"
mathieu@699
    29
#include <vector>
mathieu@2372
    30
#include <sstream>
mathieu@699
    31
craigdo@1504
    32
NS_LOG_COMPONENT_DEFINE ("Object");
mathieu@1374
    33
mathieu@2233
    34
/*********************************************************************
mathieu@2233
    35
 *         Helper code
mathieu@2233
    36
 *********************************************************************/
mathieu@2233
    37
mathieu@699
    38
namespace {
mathieu@699
    39
mathieu@2235
    40
class IidManager
mathieu@699
    41
{
mathieu@699
    42
public:
mathieu@2372
    43
  IidManager ();
mathieu@2235
    44
  uint16_t AllocateUid (std::string name);
mathieu@2235
    45
  void SetParent (uint16_t uid, uint16_t parent);
mathieu@2372
    46
  void SetTypeName (uint16_t uid, std::string typeName);
mathieu@2372
    47
  void SetGroupName (uint16_t uid, std::string groupName);
mathieu@2237
    48
  void AddConstructor (uint16_t uid, ns3::CallbackBase callback, uint32_t nArguments);
mathieu@2235
    49
  uint16_t GetUid (std::string name) const;
mathieu@2235
    50
  std::string GetName (uint16_t uid) const;
mathieu@2235
    51
  uint16_t GetParent (uint16_t uid) const;
mathieu@2372
    52
  std::string GetTypeName (uint16_t uid) const;
mathieu@2372
    53
  std::string GetGroupName (uint16_t uid) const;
mathieu@2237
    54
  ns3::CallbackBase GetConstructor (uint16_t uid, uint32_t nArguments);
mathieu@2241
    55
  bool HasConstructor (uint16_t uid);
mathieu@2239
    56
  uint32_t GetRegisteredN (void);
mathieu@2239
    57
  uint16_t GetRegistered (uint32_t i);
mathieu@2458
    58
  void AddAttribute (uint16_t uid, 
mathieu@2372
    59
                     std::string name,
mathieu@2372
    60
                     std::string help, 
mathieu@2372
    61
                     uint32_t flags,
mathieu@2433
    62
                     ns3::Attribute initialValue,
mathieu@2436
    63
                     ns3::Ptr<const ns3::AttributeAccessor> spec,
mathieu@2427
    64
                     ns3::Ptr<const ns3::AttributeChecker> checker);
mathieu@2459
    65
  uint32_t GetAttributeListN (uint16_t uid) const;
mathieu@2458
    66
  std::string GetAttributeName (uint16_t uid, uint32_t i) const;
mathieu@2458
    67
  uint32_t GetAttributeFlags (uint16_t uid, uint32_t i) const;
mathieu@2458
    68
  ns3::Attribute GetAttributeInitialValue (uint16_t uid, uint32_t i) const;
mathieu@2458
    69
  ns3::Ptr<const ns3::AttributeAccessor> GetAttributeAccessor (uint16_t uid, uint32_t i) const;
mathieu@2458
    70
  ns3::Ptr<const ns3::AttributeChecker> GetAttributeChecker (uint16_t uid, uint32_t i) const;
mathieu@2463
    71
  void AddTraceSource (uint16_t uid,
mathieu@2463
    72
                       std::string name, 
mathieu@2463
    73
                       std::string help,
mathieu@2463
    74
                       ns3::Ptr<const ns3::TraceSourceAccessor> accessor);
mathieu@2463
    75
  uint32_t GetTraceSourceN (uint16_t uid) const;
mathieu@2463
    76
  std::string GetTraceSourceName (uint16_t uid, uint32_t i) const;
mathieu@2463
    77
  std::string GetTraceSourceHelp (uint16_t uid, uint32_t i) const;
mathieu@2463
    78
  ns3::Ptr<const ns3::TraceSourceAccessor> GetTraceSourceAccessor (uint16_t uid, uint32_t i) const;
mathieu@2463
    79
mathieu@2235
    80
private:
mathieu@2237
    81
  struct ConstructorInformation {
mathieu@2237
    82
    ns3::CallbackBase cb;
mathieu@2237
    83
    uint32_t nArguments;
mathieu@2237
    84
  };
mathieu@2458
    85
  struct AttributeInformation {
mathieu@2372
    86
    std::string name;
mathieu@2372
    87
    std::string help;
mathieu@2372
    88
    uint32_t flags;
mathieu@2433
    89
    ns3::Attribute initialValue;
mathieu@2436
    90
    ns3::Ptr<const ns3::AttributeAccessor> param;
mathieu@2427
    91
    ns3::Ptr<const ns3::AttributeChecker> checker;
mathieu@2372
    92
  };
mathieu@2463
    93
  struct TraceSourceInformation {
mathieu@2463
    94
    std::string name;
mathieu@2463
    95
    std::string help;
mathieu@2463
    96
    ns3::Ptr<const ns3::TraceSourceAccessor> accessor;
mathieu@2463
    97
  };
mathieu@2235
    98
  struct IidInformation {
mathieu@2235
    99
    std::string name;
mathieu@2235
   100
    uint16_t parent;
mathieu@2372
   101
    std::string typeName;
mathieu@2372
   102
    std::string groupName;
mathieu@2237
   103
    std::vector<struct ConstructorInformation> constructors;
mathieu@2458
   104
    std::vector<struct AttributeInformation> attributes;
mathieu@2463
   105
    std::vector<struct TraceSourceInformation> traceSources;
mathieu@2235
   106
  };
mathieu@2235
   107
  typedef std::vector<struct IidInformation>::const_iterator Iterator;
mathieu@1346
   108
mathieu@2235
   109
  struct IidManager::IidInformation *LookupInformation (uint16_t uid) const;
mathieu@2235
   110
mathieu@2235
   111
  std::vector<struct IidInformation> m_information;
mathieu@699
   112
};
mathieu@699
   113
mathieu@2372
   114
IidManager::IidManager ()
mathieu@2372
   115
{}
mathieu@2372
   116
mathieu@2235
   117
uint16_t 
mathieu@2235
   118
IidManager::AllocateUid (std::string name)
mathieu@2235
   119
{
mathieu@2235
   120
  uint16_t j = 1;
mathieu@2235
   121
  for (Iterator i = m_information.begin (); i != m_information.end (); i++)
mathieu@2235
   122
    {
mathieu@2235
   123
      if (i->name == name)
mathieu@2235
   124
        {
mathieu@2235
   125
          NS_FATAL_ERROR ("Trying to allocate twice the same uid: " << name);
mathieu@2235
   126
          return 0;
mathieu@2235
   127
        }
mathieu@2235
   128
      j++;
mathieu@2235
   129
    }
mathieu@2235
   130
  struct IidInformation information;
mathieu@2235
   131
  information.name = name;
mathieu@2235
   132
  information.parent = 0;
mathieu@2372
   133
  information.typeName = "";
mathieu@2372
   134
  information.groupName = "";
mathieu@2235
   135
  m_information.push_back (information);
mathieu@2235
   136
  uint32_t uid = m_information.size ();
mathieu@2235
   137
  NS_ASSERT (uid <= 0xffff);
mathieu@2235
   138
  return uid;
mathieu@2235
   139
}
mathieu@2235
   140
mathieu@2235
   141
struct IidManager::IidInformation *
mathieu@2235
   142
IidManager::LookupInformation (uint16_t uid) const
mathieu@2235
   143
{
mathieu@2235
   144
  NS_ASSERT (uid <= m_information.size ());
mathieu@2235
   145
  return const_cast<struct IidInformation *> (&m_information[uid-1]);
mathieu@2235
   146
}
mathieu@2235
   147
mathieu@699
   148
void 
mathieu@2235
   149
IidManager::SetParent (uint16_t uid, uint16_t parent)
mathieu@699
   150
{
mathieu@2235
   151
  NS_ASSERT (parent <= m_information.size ());
mathieu@2235
   152
  struct IidInformation *information = LookupInformation (uid);
mathieu@2235
   153
  information->parent = parent;
mathieu@2235
   154
}
mathieu@2237
   155
void 
mathieu@2372
   156
IidManager::SetTypeName (uint16_t uid, std::string typeName)
mathieu@2372
   157
{
mathieu@2372
   158
  struct IidInformation *information = LookupInformation (uid);
mathieu@2372
   159
  information->typeName = typeName;
mathieu@2372
   160
}
mathieu@2372
   161
void 
mathieu@2372
   162
IidManager::SetGroupName (uint16_t uid, std::string groupName)
mathieu@2372
   163
{
mathieu@2372
   164
  struct IidInformation *information = LookupInformation (uid);
mathieu@2372
   165
  information->groupName = groupName;
mathieu@2372
   166
}
mathieu@2372
   167
mathieu@2372
   168
void 
mathieu@2237
   169
IidManager::AddConstructor (uint16_t uid, ns3::CallbackBase callback, uint32_t nArguments)
mathieu@2237
   170
{
mathieu@2237
   171
  struct IidInformation *information = LookupInformation (uid);
mathieu@2237
   172
  struct ConstructorInformation constructor;
mathieu@2237
   173
  constructor.cb = callback;
mathieu@2237
   174
  constructor.nArguments = nArguments;
mathieu@2237
   175
  for (std::vector<struct ConstructorInformation>::const_iterator i = information->constructors.begin ();
mathieu@2237
   176
       i != information->constructors.end (); i++)
mathieu@2237
   177
    {
mathieu@2237
   178
      if (i->nArguments == nArguments)
mathieu@2237
   179
        {
mathieu@2237
   180
          NS_FATAL_ERROR ("registered two constructors on the same type with the same number of arguments.");
mathieu@2237
   181
          break;
mathieu@2237
   182
        }
mathieu@2237
   183
    }
mathieu@2237
   184
  information->constructors.push_back (constructor);
mathieu@2237
   185
}
mathieu@2235
   186
mathieu@2235
   187
uint16_t 
mathieu@2235
   188
IidManager::GetUid (std::string name) const
mathieu@2235
   189
{
mathieu@2235
   190
  uint32_t j = 1;
mathieu@2235
   191
  for (Iterator i = m_information.begin (); i != m_information.end (); i++)
mathieu@2235
   192
    {
mathieu@2235
   193
      if (i->name == name)
mathieu@2235
   194
        {
mathieu@2235
   195
          NS_ASSERT (j <= 0xffff);
mathieu@2235
   196
          return j;
mathieu@2235
   197
        }
mathieu@2235
   198
      j++;
mathieu@2235
   199
    }
mathieu@2235
   200
  return 0;
mathieu@2235
   201
}
mathieu@2235
   202
std::string 
mathieu@2235
   203
IidManager::GetName (uint16_t uid) const
mathieu@2235
   204
{
mathieu@2235
   205
  struct IidInformation *information = LookupInformation (uid);
mathieu@2235
   206
  return information->name;
mathieu@699
   207
}
mathieu@712
   208
uint16_t 
mathieu@2235
   209
IidManager::GetParent (uint16_t uid) const
mathieu@699
   210
{
mathieu@2235
   211
  struct IidInformation *information = LookupInformation (uid);
mathieu@2235
   212
  return information->parent;
mathieu@699
   213
}
mathieu@2372
   214
std::string 
mathieu@2372
   215
IidManager::GetTypeName (uint16_t uid) const
mathieu@2372
   216
{
mathieu@2372
   217
  struct IidInformation *information = LookupInformation (uid);
mathieu@2372
   218
  return information->typeName;
mathieu@2372
   219
}
mathieu@2372
   220
std::string 
mathieu@2372
   221
IidManager::GetGroupName (uint16_t uid) const
mathieu@2372
   222
{
mathieu@2372
   223
  struct IidInformation *information = LookupInformation (uid);
mathieu@2372
   224
  return information->groupName;
mathieu@2372
   225
}
mathieu@2372
   226
mathieu@2237
   227
ns3::CallbackBase 
mathieu@2237
   228
IidManager::GetConstructor (uint16_t uid, uint32_t nArguments)
mathieu@2237
   229
{
mathieu@2237
   230
  struct IidInformation *information = LookupInformation (uid);
mathieu@2237
   231
  for (std::vector<struct ConstructorInformation>::const_iterator i = information->constructors.begin ();
mathieu@2237
   232
       i != information->constructors.end (); i++)
mathieu@2237
   233
    {
mathieu@2237
   234
      if (i->nArguments == nArguments)
mathieu@2237
   235
        {
mathieu@2237
   236
          return i->cb;
mathieu@2237
   237
        } 
mathieu@2237
   238
    }
mathieu@2237
   239
  NS_FATAL_ERROR ("Requested constructor with "<<nArguments<<" arguments not found");
mathieu@2237
   240
  return ns3::CallbackBase ();
mathieu@2237
   241
}
mathieu@699
   242
mathieu@2241
   243
bool 
mathieu@2241
   244
IidManager::HasConstructor (uint16_t uid)
mathieu@2241
   245
{
mathieu@2241
   246
  struct IidInformation *information = LookupInformation (uid);
mathieu@2241
   247
  return !information->constructors.empty ();
mathieu@2241
   248
}
mathieu@2241
   249
mathieu@2239
   250
uint32_t 
mathieu@2239
   251
IidManager::GetRegisteredN (void)
mathieu@2239
   252
{
mathieu@2239
   253
  return m_information.size ();
mathieu@2239
   254
}
mathieu@2239
   255
uint16_t 
mathieu@2239
   256
IidManager::GetRegistered (uint32_t i)
mathieu@2239
   257
{
mathieu@2247
   258
  return i + 1;
mathieu@2239
   259
}
mathieu@2239
   260
mathieu@2372
   261
void 
mathieu@2458
   262
IidManager::AddAttribute (uint16_t uid, 
mathieu@2372
   263
                          std::string name,
mathieu@2372
   264
                          std::string help, 
mathieu@2372
   265
                          uint32_t flags,
mathieu@2433
   266
                          ns3::Attribute initialValue,
mathieu@2436
   267
                          ns3::Ptr<const ns3::AttributeAccessor> spec,
mathieu@2427
   268
                          ns3::Ptr<const ns3::AttributeChecker> checker)
mathieu@2372
   269
{
mathieu@2372
   270
  struct IidInformation *information = LookupInformation (uid);
mathieu@2458
   271
  for (std::vector<struct AttributeInformation>::const_iterator j = information->attributes.begin ();
mathieu@2458
   272
       j != information->attributes.end (); j++)
mathieu@2372
   273
    {
mathieu@2372
   274
      if (j->name == name)
mathieu@2372
   275
        {
mathieu@2458
   276
          NS_FATAL_ERROR ("Registered the same attribute twice name=\""<<name<<"\" in TypeId=\""<<information->name<<"\"");
mathieu@2372
   277
          return;
mathieu@2372
   278
        }
mathieu@2372
   279
    }
mathieu@2458
   280
  struct AttributeInformation param;
mathieu@2372
   281
  param.name = name;
mathieu@2372
   282
  param.help = help;
mathieu@2372
   283
  param.flags = flags;
mathieu@2424
   284
  param.initialValue = initialValue;
mathieu@2372
   285
  param.param = spec;
mathieu@2427
   286
  param.checker = checker;
mathieu@2458
   287
  information->attributes.push_back (param);
mathieu@2372
   288
}
mathieu@2372
   289
mathieu@2372
   290
mathieu@2372
   291
uint32_t 
mathieu@2459
   292
IidManager::GetAttributeListN (uint16_t uid) const
mathieu@2372
   293
{
mathieu@2372
   294
  struct IidInformation *information = LookupInformation (uid);
mathieu@2458
   295
  return information->attributes.size ();
mathieu@2372
   296
}
mathieu@2372
   297
std::string 
mathieu@2458
   298
IidManager::GetAttributeName (uint16_t uid, uint32_t i) const
mathieu@2372
   299
{
mathieu@2372
   300
  struct IidInformation *information = LookupInformation (uid);
mathieu@2458
   301
  NS_ASSERT (i < information->attributes.size ());
mathieu@2458
   302
  return information->attributes[i].name;
mathieu@2372
   303
}
mathieu@2372
   304
uint32_t
mathieu@2458
   305
IidManager::GetAttributeFlags (uint16_t uid, uint32_t i) const
mathieu@2372
   306
{
mathieu@2372
   307
  struct IidInformation *information = LookupInformation (uid);
mathieu@2458
   308
  NS_ASSERT (i < information->attributes.size ());
mathieu@2458
   309
  return information->attributes[i].flags;
mathieu@2372
   310
}
mathieu@2433
   311
ns3::Attribute 
mathieu@2458
   312
IidManager::GetAttributeInitialValue (uint16_t uid, uint32_t i) const
mathieu@2424
   313
{
mathieu@2424
   314
  struct IidInformation *information = LookupInformation (uid);
mathieu@2458
   315
  NS_ASSERT (i < information->attributes.size ());
mathieu@2458
   316
  return information->attributes[i].initialValue;
mathieu@2424
   317
}
mathieu@2436
   318
ns3::Ptr<const ns3::AttributeAccessor>
mathieu@2458
   319
IidManager::GetAttributeAccessor (uint16_t uid, uint32_t i) const
mathieu@2372
   320
{
mathieu@2372
   321
  struct IidInformation *information = LookupInformation (uid);
mathieu@2458
   322
  NS_ASSERT (i < information->attributes.size ());
mathieu@2458
   323
  return information->attributes[i].param;
mathieu@2372
   324
}
mathieu@2427
   325
ns3::Ptr<const ns3::AttributeChecker>
mathieu@2458
   326
IidManager::GetAttributeChecker (uint16_t uid, uint32_t i) const
mathieu@2427
   327
{
mathieu@2427
   328
  struct IidInformation *information = LookupInformation (uid);
mathieu@2458
   329
  NS_ASSERT (i < information->attributes.size ());
mathieu@2458
   330
  return information->attributes[i].checker;
mathieu@2427
   331
}
mathieu@2372
   332
mathieu@2463
   333
void 
mathieu@2463
   334
IidManager::AddTraceSource (uint16_t uid,
mathieu@2463
   335
                            std::string name, 
mathieu@2463
   336
                            std::string help,
mathieu@2463
   337
                            ns3::Ptr<const ns3::TraceSourceAccessor> accessor)
mathieu@2463
   338
{
mathieu@2463
   339
  struct IidInformation *information  = LookupInformation (uid);
mathieu@2463
   340
  struct TraceSourceInformation source;
mathieu@2463
   341
  source.name = name;
mathieu@2463
   342
  source.help = help;
mathieu@2463
   343
  source.accessor = accessor;
mathieu@2463
   344
  information->traceSources.push_back (source);
mathieu@2463
   345
}
mathieu@2463
   346
uint32_t 
mathieu@2463
   347
IidManager::GetTraceSourceN (uint16_t uid) const
mathieu@2463
   348
{
mathieu@2463
   349
  struct IidInformation *information = LookupInformation (uid);
mathieu@2463
   350
  return information->traceSources.size ();
mathieu@2463
   351
}
mathieu@2463
   352
std::string 
mathieu@2463
   353
IidManager::GetTraceSourceName (uint16_t uid, uint32_t i) const
mathieu@2463
   354
{
mathieu@2463
   355
  struct IidInformation *information = LookupInformation (uid);
mathieu@2463
   356
  NS_ASSERT (i < information->traceSources.size ());
mathieu@2463
   357
  return information->traceSources[i].name;
mathieu@2463
   358
}
mathieu@2463
   359
std::string 
mathieu@2463
   360
IidManager::GetTraceSourceHelp (uint16_t uid, uint32_t i) const
mathieu@2463
   361
{
mathieu@2463
   362
  struct IidInformation *information = LookupInformation (uid);
mathieu@2463
   363
  NS_ASSERT (i < information->traceSources.size ());
mathieu@2463
   364
  return information->traceSources[i].help;
mathieu@2463
   365
}
mathieu@2463
   366
ns3::Ptr<const ns3::TraceSourceAccessor> 
mathieu@2463
   367
IidManager::GetTraceSourceAccessor (uint16_t uid, uint32_t i) const
mathieu@2463
   368
{
mathieu@2463
   369
  struct IidInformation *information = LookupInformation (uid);
mathieu@2463
   370
  NS_ASSERT (i < information->traceSources.size ());
mathieu@2463
   371
  return information->traceSources[i].accessor;
mathieu@2463
   372
}
mathieu@2463
   373
mathieu@699
   374
} // anonymous namespace
mathieu@699
   375
mathieu@2233
   376
/*********************************************************************
mathieu@2250
   377
 *         The TypeId TraceResolver
mathieu@2233
   378
 *********************************************************************/
mathieu@2233
   379
mathieu@699
   380
namespace ns3 {
mathieu@699
   381
mathieu@2250
   382
class TypeIdTraceResolver : public TraceResolver
mathieu@1346
   383
{
mathieu@1346
   384
public:
mathieu@2250
   385
  TypeIdTraceResolver (Ptr<const Object> aggregate);
mathieu@1346
   386
  virtual void Connect (std::string path, CallbackBase const &cb, const TraceContext &context);
mathieu@1346
   387
  virtual void Disconnect (std::string path, CallbackBase const &cb);
mathieu@1371
   388
  virtual void CollectSources (std::string path, const TraceContext &context, 
mathieu@1371
   389
                               SourceCollection *collection);
mathieu@1420
   390
  virtual void TraceAll (std::ostream &os, const TraceContext &context);
mathieu@1346
   391
private:
mathieu@1383
   392
  Ptr<const Object> ParseForInterface (std::string path);
mathieu@1383
   393
  Ptr<const Object> m_aggregate;
mathieu@1346
   394
};
mathieu@1346
   395
mathieu@2250
   396
TypeIdTraceResolver::TypeIdTraceResolver (Ptr<const Object> aggregate)
mathieu@1346
   397
  : m_aggregate (aggregate)
mathieu@1346
   398
{}
mathieu@1383
   399
Ptr<const Object>
mathieu@2250
   400
TypeIdTraceResolver::ParseForInterface (std::string path)
mathieu@1346
   401
{
mathieu@1346
   402
  std::string element = GetElement (path);
mathieu@1346
   403
  std::string::size_type dollar_pos = element.find ("$");
mathieu@1346
   404
  if (dollar_pos != 0)
mathieu@1346
   405
    {
mathieu@1346
   406
      return 0;
mathieu@1346
   407
    }
mathieu@1346
   408
  std::string interfaceName = element.substr (1, std::string::npos);
mathieu@2250
   409
  TypeId interfaceId = TypeId::LookupByName (interfaceName);
mathieu@2257
   410
  Ptr<Object> interface = m_aggregate->GetObject<Object> (interfaceId);
mathieu@1346
   411
  return interface;
mathieu@1346
   412
}
mathieu@2231
   413
void  
mathieu@2250
   414
TypeIdTraceResolver::Connect (std::string path, CallbackBase const &cb, const TraceContext &context)
mathieu@1346
   415
{
mathieu@1383
   416
  Ptr<const Object> interface = ParseForInterface (path);
mathieu@1346
   417
  if (interface != 0)
mathieu@1346
   418
    {
mathieu@1368
   419
      interface->GetTraceResolver ()->Connect (GetSubpath (path), cb, context);
mathieu@1346
   420
    }
mathieu@1346
   421
}
mathieu@1346
   422
void 
mathieu@2250
   423
TypeIdTraceResolver::Disconnect (std::string path, CallbackBase const &cb)
mathieu@1346
   424
{
mathieu@1383
   425
  Ptr<const Object> interface = ParseForInterface (path);
mathieu@1346
   426
  if (interface != 0)
mathieu@1346
   427
    {
mathieu@1346
   428
      interface->TraceDisconnect (GetSubpath (path), cb);
mathieu@1346
   429
    }
mathieu@1346
   430
}
mathieu@1368
   431
void 
mathieu@2250
   432
TypeIdTraceResolver::CollectSources (std::string path, const TraceContext &context, 
mathieu@1371
   433
                                          SourceCollection *collection)
mathieu@1368
   434
{
mathieu@1371
   435
  m_aggregate->DoCollectSources (path, context, collection);
mathieu@1368
   436
}
mathieu@1419
   437
void 
mathieu@2250
   438
TypeIdTraceResolver::TraceAll (std::ostream &os, const TraceContext &context)
mathieu@1419
   439
{
mathieu@1420
   440
  m_aggregate->DoTraceAll (os, context);
mathieu@1419
   441
}
mathieu@1346
   442
mathieu@2233
   443
/*********************************************************************
mathieu@2250
   444
 *         The TypeId class
mathieu@2233
   445
 *********************************************************************/
mathieu@2233
   446
mathieu@2394
   447
TypeId::TypeId ()
mathieu@2394
   448
  : m_tid (0)
mathieu@2394
   449
{}
mathieu@2394
   450
mathieu@2489
   451
TypeId::TypeId (const char * name)
mathieu@2237
   452
{
mathieu@2237
   453
  uint16_t uid = Singleton<IidManager>::Get ()->AllocateUid (name);
mathieu@2237
   454
  NS_ASSERT (uid != 0);
mathieu@2252
   455
  m_tid = uid;
mathieu@2237
   456
}
mathieu@2237
   457
mathieu@1346
   458
mathieu@2252
   459
TypeId::TypeId (uint16_t tid)
mathieu@2252
   460
  : m_tid (tid)
mathieu@699
   461
{}
mathieu@2250
   462
TypeId::~TypeId ()
mathieu@706
   463
{}
mathieu@2250
   464
TypeId 
mathieu@2250
   465
TypeId::LookupByName (std::string name)
mathieu@699
   466
{
mathieu@2235
   467
  uint16_t uid = Singleton<IidManager>::Get ()->GetUid (name);
mathieu@2235
   468
  NS_ASSERT (uid != 0);
mathieu@2250
   469
  return TypeId (uid);
mathieu@699
   470
}
mathieu@2382
   471
bool
mathieu@2458
   472
TypeId::LookupAttributeByFullName (std::string fullName, struct TypeId::AttributeInfo *info)
mathieu@2372
   473
{
mathieu@2372
   474
  std::string::size_type pos = fullName.find ("::");
mathieu@2372
   475
  if (pos == std::string::npos)
mathieu@2372
   476
    {
mathieu@2372
   477
      return 0;
mathieu@2372
   478
    }
mathieu@2372
   479
  std::string tidName = fullName.substr (0, pos);
mathieu@2372
   480
  std::string paramName = fullName.substr (pos+2, fullName.size () - (pos+2));
mathieu@2372
   481
  TypeId tid = LookupByName (tidName);
mathieu@2458
   482
  return tid.LookupAttributeByName (paramName, info);
mathieu@2372
   483
}
mathieu@2239
   484
uint32_t 
mathieu@2250
   485
TypeId::GetRegisteredN (void)
mathieu@2239
   486
{
mathieu@2239
   487
  return Singleton<IidManager>::Get ()->GetRegisteredN ();
mathieu@2239
   488
}
mathieu@2250
   489
TypeId 
mathieu@2250
   490
TypeId::GetRegistered (uint32_t i)
mathieu@2239
   491
{
mathieu@2250
   492
  return TypeId (Singleton<IidManager>::Get ()->GetRegistered (i));
mathieu@2239
   493
}
mathieu@2239
   494
mathieu@2382
   495
bool
mathieu@2458
   496
TypeId::LookupAttributeByName (std::string name, struct TypeId::AttributeInfo *info) const
mathieu@2372
   497
{
mathieu@2489
   498
  TypeId tid;
mathieu@2382
   499
  TypeId nextTid = *this;
mathieu@2382
   500
  do {
mathieu@2382
   501
    tid = nextTid;
mathieu@2465
   502
    for (uint32_t i = 0; i < tid.GetAttributeListN (); i++)
mathieu@2382
   503
      {
mathieu@2465
   504
        std::string paramName = tid.GetAttributeName (i);
mathieu@2382
   505
        if (paramName == name)
mathieu@2382
   506
          {
mathieu@2465
   507
            info->accessor = tid.GetAttributeAccessor (i);
mathieu@2465
   508
            info->flags = tid.GetAttributeFlags (i);
mathieu@2458
   509
            info->initialValue = tid.GetAttributeInitialValue (i);
mathieu@2458
   510
            info->checker = tid.GetAttributeChecker (i);
mathieu@2382
   511
            return true;
mathieu@2382
   512
          }
mathieu@2382
   513
      }
mathieu@2382
   514
    nextTid = tid.GetParent ();
mathieu@2382
   515
  } while (nextTid != tid);
mathieu@2382
   516
  return false;
mathieu@2372
   517
}
mathieu@2382
   518
bool
mathieu@2458
   519
TypeId::LookupAttributeByPosition (uint32_t i, struct TypeId::AttributeInfo *info) const
mathieu@2372
   520
{
mathieu@2372
   521
  uint32_t cur = 0;
mathieu@2489
   522
  TypeId tid;
mathieu@2372
   523
  TypeId nextTid = *this;
mathieu@2372
   524
  do {
mathieu@2372
   525
    tid = nextTid;
mathieu@2459
   526
    for (uint32_t j = 0; j < tid.GetAttributeListN (); j++)
mathieu@2372
   527
      {
mathieu@2372
   528
        if (cur == i)
mathieu@2372
   529
          {
mathieu@2458
   530
            info->accessor = tid.GetAttributeAccessor (j);
mathieu@2458
   531
            info->flags = tid.GetAttributeFlags (j);
mathieu@2458
   532
            info->initialValue = tid.GetAttributeInitialValue (j);
mathieu@2458
   533
            info->checker = tid.GetAttributeChecker (j);
mathieu@2382
   534
            return true;
mathieu@2372
   535
          }
mathieu@2372
   536
        cur++;
mathieu@2372
   537
      }
mathieu@2372
   538
    nextTid = tid.GetParent ();
mathieu@2372
   539
  } while (nextTid != tid);
mathieu@2382
   540
  return false;
mathieu@2372
   541
}
mathieu@2372
   542
mathieu@2372
   543
mathieu@2250
   544
TypeId 
mathieu@2252
   545
TypeId::SetParent (TypeId tid)
mathieu@2237
   546
{
mathieu@2252
   547
  Singleton<IidManager>::Get ()->SetParent (m_tid, tid.m_tid);
mathieu@2237
   548
  return *this;
mathieu@2237
   549
}
mathieu@2250
   550
TypeId 
mathieu@2372
   551
TypeId::SetGroupName (std::string groupName)
mathieu@2372
   552
{
mathieu@2372
   553
  Singleton<IidManager>::Get ()->SetGroupName (m_tid, groupName);
mathieu@2372
   554
  return *this;
mathieu@2372
   555
}
mathieu@2372
   556
TypeId 
mathieu@2372
   557
TypeId::SetTypeName (std::string typeName)
mathieu@2372
   558
{
mathieu@2372
   559
  Singleton<IidManager>::Get ()->SetTypeName (m_tid, typeName);
mathieu@2372
   560
  return *this;
mathieu@2372
   561
}
mathieu@2372
   562
TypeId 
mathieu@2250
   563
TypeId::GetParent (void) const
mathieu@699
   564
{
mathieu@2252
   565
  uint16_t parent = Singleton<IidManager>::Get ()->GetParent (m_tid);
mathieu@2250
   566
  return TypeId (parent);
mathieu@699
   567
}
mathieu@1371
   568
std::string 
mathieu@2372
   569
TypeId::GetGroupName (void) const
mathieu@2372
   570
{
mathieu@2372
   571
  std::string groupName = Singleton<IidManager>::Get ()->GetGroupName (m_tid);
mathieu@2372
   572
  return groupName;
mathieu@2372
   573
}
mathieu@2372
   574
std::string 
mathieu@2372
   575
TypeId::GetTypeName (void) const
mathieu@2372
   576
{
mathieu@2372
   577
  std::string typeName = Singleton<IidManager>::Get ()->GetTypeName (m_tid);
mathieu@2372
   578
  return typeName;
mathieu@2372
   579
}
mathieu@2372
   580
mathieu@2372
   581
std::string 
mathieu@2250
   582
TypeId::GetName (void) const
mathieu@1371
   583
{
mathieu@2252
   584
  std::string name = Singleton<IidManager>::Get ()->GetName (m_tid);
mathieu@1371
   585
  return name;
mathieu@1371
   586
}
mathieu@699
   587
mathieu@2241
   588
bool 
mathieu@2250
   589
TypeId::HasConstructor (void) const
mathieu@2241
   590
{
mathieu@2252
   591
  bool hasConstructor = Singleton<IidManager>::Get ()->HasConstructor (m_tid);
mathieu@2241
   592
  return hasConstructor;
mathieu@2241
   593
}
mathieu@2241
   594
mathieu@2237
   595
void
mathieu@2250
   596
TypeId::DoAddConstructor (CallbackBase cb, uint32_t nArguments)
mathieu@2237
   597
{
mathieu@2252
   598
  Singleton<IidManager>::Get ()->AddConstructor (m_tid, cb, nArguments);
mathieu@2237
   599
}
mathieu@2237
   600
mathieu@2372
   601
TypeId 
mathieu@2458
   602
TypeId::AddAttribute (std::string name,
mathieu@2372
   603
                      std::string help, 
mathieu@2433
   604
                      Attribute initialValue,
mathieu@2436
   605
                      Ptr<const AttributeAccessor> param,
mathieu@2427
   606
                      Ptr<const AttributeChecker> checker)
mathieu@2372
   607
{
mathieu@2458
   608
  Singleton<IidManager>::Get ()->AddAttribute (m_tid, name, help, ATTR_SGC, initialValue, param, checker);
mathieu@2372
   609
  return *this;
mathieu@2372
   610
}
mathieu@2372
   611
mathieu@2372
   612
TypeId 
mathieu@2458
   613
TypeId::AddAttribute (std::string name,
mathieu@2372
   614
                      std::string help, 
mathieu@2372
   615
                      uint32_t flags,
mathieu@2433
   616
                      Attribute initialValue,
mathieu@2436
   617
                      Ptr<const AttributeAccessor> param,
mathieu@2427
   618
                      Ptr<const AttributeChecker> checker)
mathieu@2372
   619
{
mathieu@2458
   620
  Singleton<IidManager>::Get ()->AddAttribute (m_tid, name, help, flags, initialValue, param, checker);
mathieu@2372
   621
  return *this;
mathieu@2372
   622
}
mathieu@2372
   623
mathieu@2372
   624
mathieu@2237
   625
CallbackBase
mathieu@2372
   626
TypeId::LookupConstructor (uint32_t nArguments) const
mathieu@2237
   627
{
mathieu@2252
   628
  CallbackBase constructor = Singleton<IidManager>::Get ()->GetConstructor (m_tid, nArguments);
mathieu@2237
   629
  return constructor;
mathieu@2237
   630
}
mathieu@2237
   631
mathieu@2237
   632
Ptr<Object> 
mathieu@2372
   633
TypeId::CreateObject (void) const
mathieu@2372
   634
{
mathieu@2459
   635
  return CreateObject (AttributeList ());
mathieu@2372
   636
}
mathieu@2372
   637
Ptr<Object> 
mathieu@2459
   638
TypeId::CreateObject (const AttributeList &attributes) const
mathieu@2237
   639
{
mathieu@2237
   640
  CallbackBase cb = LookupConstructor (0);
mathieu@2459
   641
  Callback<Ptr<Object>,const AttributeList &> realCb;
mathieu@2237
   642
  realCb.Assign (cb);
mathieu@2458
   643
  Ptr<Object> object = realCb (attributes);
mathieu@2372
   644
  return object;  
mathieu@2237
   645
}
mathieu@2237
   646
mathieu@2372
   647
uint32_t 
mathieu@2459
   648
TypeId::GetAttributeListN (void) const
mathieu@2372
   649
{
mathieu@2459
   650
  uint32_t n = Singleton<IidManager>::Get ()->GetAttributeListN (m_tid);
mathieu@2372
   651
  return n;
mathieu@2372
   652
}
mathieu@2372
   653
std::string 
mathieu@2458
   654
TypeId::GetAttributeName (uint32_t i) const
mathieu@2372
   655
{
mathieu@2458
   656
  std::string name = Singleton<IidManager>::Get ()->GetAttributeName (m_tid, i);
mathieu@2372
   657
  return name;
mathieu@2372
   658
}
mathieu@2372
   659
std::string 
mathieu@2458
   660
TypeId::GetAttributeFullName (uint32_t i) const
mathieu@2372
   661
{
mathieu@2458
   662
  return GetName () + "::" + GetAttributeName (i);
mathieu@2372
   663
}
mathieu@2433
   664
Attribute 
mathieu@2458
   665
TypeId::GetAttributeInitialValue (uint32_t i) const
mathieu@2424
   666
{
mathieu@2458
   667
  Attribute value = Singleton<IidManager>::Get ()->GetAttributeInitialValue (m_tid, i);
mathieu@2424
   668
  return value;
mathieu@2424
   669
}
mathieu@2436
   670
Ptr<const AttributeAccessor>
mathieu@2458
   671
TypeId::GetAttributeAccessor (uint32_t i) const
mathieu@2372
   672
{
mathieu@2372
   673
  // Used exclusively by the Object class.
mathieu@2458
   674
  Ptr<const AttributeAccessor> param = Singleton<IidManager>::Get ()->GetAttributeAccessor (m_tid, i);
mathieu@2372
   675
  return param;
mathieu@2372
   676
}
mathieu@2382
   677
uint32_t 
mathieu@2458
   678
TypeId::GetAttributeFlags (uint32_t i) const
mathieu@2382
   679
{
mathieu@2382
   680
  // Used exclusively by the Object class.
mathieu@2458
   681
  uint32_t flags = Singleton<IidManager>::Get ()->GetAttributeFlags (m_tid, i);
mathieu@2382
   682
  return flags;
mathieu@2382
   683
}
mathieu@2427
   684
Ptr<const AttributeChecker>
mathieu@2458
   685
TypeId::GetAttributeChecker (uint32_t i) const
mathieu@2427
   686
{
mathieu@2427
   687
  // Used exclusively by the Object class.
mathieu@2458
   688
  Ptr<const AttributeChecker> checker = Singleton<IidManager>::Get ()->GetAttributeChecker (m_tid, i);
mathieu@2427
   689
  return checker;
mathieu@2427
   690
}
mathieu@2372
   691
mathieu@2463
   692
uint32_t 
mathieu@2463
   693
TypeId::GetTraceSourceN (void) const
mathieu@2463
   694
{
mathieu@2463
   695
  return Singleton<IidManager>::Get ()->GetTraceSourceN (m_tid);
mathieu@2463
   696
}
mathieu@2463
   697
std::string 
mathieu@2463
   698
TypeId::GetTraceSourceName (uint32_t i) const
mathieu@2463
   699
{
mathieu@2463
   700
  return Singleton<IidManager>::Get ()->GetTraceSourceName (m_tid, i);
mathieu@2463
   701
}
mathieu@2463
   702
std::string 
mathieu@2463
   703
TypeId::GetTraceSourceHelp (uint32_t i) const
mathieu@2463
   704
{
mathieu@2463
   705
  return Singleton<IidManager>::Get ()->GetTraceSourceHelp (m_tid, i);
mathieu@2463
   706
}
mathieu@2463
   707
Ptr<const TraceSourceAccessor> 
mathieu@2463
   708
TypeId::GetTraceSourceAccessor (uint32_t i) const
mathieu@2463
   709
{
mathieu@2463
   710
  return Singleton<IidManager>::Get ()->GetTraceSourceAccessor (m_tid, i);
mathieu@2463
   711
}
mathieu@2463
   712
mathieu@2463
   713
TypeId 
mathieu@2463
   714
TypeId::AddTraceSource (std::string name,
mathieu@2463
   715
                        std::string help,
mathieu@2463
   716
                        Ptr<const TraceSourceAccessor> accessor)
mathieu@2463
   717
{
mathieu@2463
   718
  Singleton<IidManager>::Get ()->AddTraceSource (m_tid, name, help, accessor);
mathieu@2463
   719
  return *this;
mathieu@2463
   720
}
mathieu@2463
   721
mathieu@2463
   722
mathieu@2463
   723
Ptr<const TraceSourceAccessor> 
mathieu@2463
   724
TypeId::LookupTraceSourceByName (std::string name) const
mathieu@2463
   725
{
mathieu@2489
   726
  TypeId tid;
mathieu@2463
   727
  TypeId nextTid = *this;
mathieu@2463
   728
  do {
mathieu@2463
   729
    tid = nextTid;
mathieu@2463
   730
    for (uint32_t i = 0; i < tid.GetTraceSourceN (); i++)
mathieu@2463
   731
      {
mathieu@2463
   732
        std::string srcName = tid.GetTraceSourceName (i);
mathieu@2463
   733
        if (srcName == name)
mathieu@2463
   734
          {
mathieu@2463
   735
            return tid.GetTraceSourceAccessor (i);
mathieu@2463
   736
          }
mathieu@2463
   737
      }
mathieu@2463
   738
    nextTid = tid.GetParent ();
mathieu@2463
   739
  } while (nextTid != tid);
mathieu@2463
   740
  return 0;
mathieu@2463
   741
}
mathieu@2372
   742
mathieu@2489
   743
std::ostream & operator << (std::ostream &os, TypeId tid)
mathieu@2489
   744
{
mathieu@2489
   745
  os << tid.GetName ();
mathieu@2489
   746
  return os;
mathieu@2489
   747
}
mathieu@2489
   748
std::istream & operator >> (std::istream &is, TypeId &tid)
mathieu@2489
   749
{
mathieu@2489
   750
  std::string tidString;
mathieu@2489
   751
  is >> tidString;
mathieu@2489
   752
  tid = TypeId::LookupByName (tidString);
mathieu@2489
   753
  return is;
mathieu@2489
   754
}
mathieu@2489
   755
mathieu@2489
   756
mathieu@2489
   757
VALUE_HELPER_CPP (TypeId);
mathieu@2489
   758
mathieu@2250
   759
bool operator == (TypeId a, TypeId b)
mathieu@699
   760
{
mathieu@2252
   761
  return a.m_tid == b.m_tid;
mathieu@699
   762
}
mathieu@699
   763
mathieu@2250
   764
bool operator != (TypeId a, TypeId b)
mathieu@699
   765
{
mathieu@2252
   766
  return a.m_tid != b.m_tid;
mathieu@699
   767
}
mathieu@699
   768
mathieu@2233
   769
/*********************************************************************
mathieu@2459
   770
 *         The AttributeList container implementation
mathieu@2372
   771
 *********************************************************************/
mathieu@2372
   772
mathieu@2459
   773
AttributeList::AttributeList ()
mathieu@2372
   774
{}
mathieu@2372
   775
mathieu@2459
   776
AttributeList::AttributeList (const AttributeList &o)
mathieu@2372
   777
{
mathieu@2458
   778
  for (Attrs::const_iterator i = o.m_attributes.begin (); i != o.m_attributes.end (); i++)
mathieu@2372
   779
    {
mathieu@2458
   780
      struct Attr attr;
mathieu@2458
   781
      attr.checker = i->checker;
mathieu@2458
   782
      attr.value = i->value.Copy ();
mathieu@2458
   783
      m_attributes.push_back (attr);
mathieu@2372
   784
    }
mathieu@2372
   785
}
mathieu@2459
   786
AttributeList &
mathieu@2459
   787
AttributeList::operator = (const AttributeList &o)
mathieu@2372
   788
{
mathieu@2372
   789
  Reset ();
mathieu@2458
   790
  for (Attrs::const_iterator i = o.m_attributes.begin (); i != o.m_attributes.end (); i++)
mathieu@2372
   791
    {
mathieu@2458
   792
      struct Attr attr;
mathieu@2458
   793
      attr.checker = i->checker;
mathieu@2458
   794
      attr.value = i->value.Copy ();
mathieu@2458
   795
      m_attributes.push_back (attr);
mathieu@2372
   796
    }
mathieu@2372
   797
  return *this;
mathieu@2372
   798
}
mathieu@2459
   799
AttributeList::~AttributeList ()
mathieu@2372
   800
{
mathieu@2372
   801
  Reset ();
mathieu@2372
   802
}
mathieu@2372
   803
mathieu@2372
   804
bool 
mathieu@2459
   805
AttributeList::Set (std::string name, Attribute value)
mathieu@2372
   806
{
mathieu@2458
   807
  struct TypeId::AttributeInfo info;
mathieu@2458
   808
  TypeId::LookupAttributeByFullName (name, &info);
mathieu@2424
   809
  bool ok = DoSet (&info, value);
mathieu@2372
   810
  return ok;
mathieu@2372
   811
}
mathieu@2522
   812
bool
mathieu@2459
   813
AttributeList::SetWithTid (TypeId tid, std::string name, Attribute value)
mathieu@2372
   814
{
mathieu@2458
   815
  struct TypeId::AttributeInfo info;
mathieu@2458
   816
  tid.LookupAttributeByName (name, &info);
mathieu@2522
   817
  bool ok = DoSet (&info, value);
mathieu@2522
   818
  return ok;
mathieu@2372
   819
}
mathieu@2522
   820
bool
mathieu@2459
   821
AttributeList::SetWithTid (TypeId tid, uint32_t position, Attribute value)
mathieu@2372
   822
{
mathieu@2458
   823
  struct TypeId::AttributeInfo info;
mathieu@2458
   824
  tid.LookupAttributeByPosition (position, &info);
mathieu@2522
   825
  bool ok = DoSet (&info, value);
mathieu@2522
   826
  return ok;
mathieu@2372
   827
}
mathieu@2372
   828
mathieu@2372
   829
void
mathieu@2459
   830
AttributeList::DoSetOne (Ptr<const AttributeChecker> checker, Attribute value)
mathieu@2372
   831
{
mathieu@2372
   832
  // get rid of any previous value stored in this
mathieu@2372
   833
  // vector of values.
mathieu@2458
   834
  for (Attrs::iterator k = m_attributes.begin (); k != m_attributes.end (); k++)
mathieu@2372
   835
    {
mathieu@2427
   836
      if (k->checker == checker)
mathieu@2372
   837
        {
mathieu@2458
   838
          m_attributes.erase (k);
mathieu@2372
   839
          break;
mathieu@2372
   840
        }
mathieu@2372
   841
    }
mathieu@2372
   842
  // store the new value.
mathieu@2458
   843
  struct Attr attr;
mathieu@2458
   844
  attr.checker = checker;
mathieu@2458
   845
  attr.value = value.Copy ();
mathieu@2458
   846
  m_attributes.push_back (attr);
mathieu@2372
   847
}
mathieu@2372
   848
bool
mathieu@2459
   849
AttributeList::DoSet (struct TypeId::AttributeInfo *info, Attribute value)
mathieu@2372
   850
{
mathieu@2427
   851
  if (info->checker == 0)
mathieu@2372
   852
    {
mathieu@2372
   853
      return false;
mathieu@2372
   854
    }
mathieu@2427
   855
  bool ok = info->checker->Check (value);
mathieu@2372
   856
  if (!ok)
mathieu@2372
   857
    {
mathieu@2421
   858
      // attempt to convert to string.
mathieu@2424
   859
      const StringValue *str = value.DynCast<const StringValue *> ();
mathieu@2424
   860
      if (str == 0)
mathieu@2424
   861
        {
mathieu@2424
   862
          return false;
mathieu@2424
   863
        }
mathieu@2421
   864
      // attempt to convert back to value.
mathieu@2520
   865
      Attribute v = info->checker->Create ();
mathieu@2502
   866
      ok = v.DeserializeFromString (str->Get ().Get (), info->checker);
mathieu@2397
   867
      if (!ok)
mathieu@2397
   868
        {
mathieu@2397
   869
          return false;
mathieu@2397
   870
        }
mathieu@2427
   871
      ok = info->checker->Check (v);
mathieu@2421
   872
      if (!ok)
mathieu@2421
   873
        {
mathieu@2421
   874
          return false;
mathieu@2421
   875
        }
mathieu@2421
   876
      value = v;
mathieu@2372
   877
    }
mathieu@2427
   878
  DoSetOne (info->checker, value);
mathieu@2372
   879
  return true;
mathieu@2372
   880
}
mathieu@2372
   881
void 
mathieu@2459
   882
AttributeList::Reset (void)
mathieu@2372
   883
{
mathieu@2458
   884
  m_attributes.clear ();
mathieu@2372
   885
}
mathieu@2459
   886
AttributeList *
mathieu@2459
   887
AttributeList::GetGlobal (void)
mathieu@2372
   888
{
mathieu@2459
   889
  return Singleton<AttributeList>::Get ();
mathieu@2372
   890
}
mathieu@2372
   891
mathieu@2372
   892
std::string
mathieu@2459
   893
AttributeList::LookupAttributeFullNameByChecker (Ptr<const AttributeChecker> checker) const
mathieu@2372
   894
{
mathieu@2372
   895
  for (uint32_t i = 0; i < TypeId::GetRegisteredN (); i++)
mathieu@2372
   896
    {
mathieu@2372
   897
      TypeId tid = TypeId::GetRegistered (i);
mathieu@2459
   898
      for (uint32_t j = 0; j < tid.GetAttributeListN (); j++)
mathieu@2372
   899
        {
mathieu@2458
   900
          if (checker == tid.GetAttributeChecker (j))
mathieu@2372
   901
            {
mathieu@2458
   902
              return tid.GetAttributeFullName (j);
mathieu@2372
   903
            }
mathieu@2372
   904
        }
mathieu@2372
   905
    }
mathieu@2435
   906
  NS_FATAL_ERROR ("Could not find requested Accessor.");
mathieu@2372
   907
  // quiet compiler.
mathieu@2372
   908
  return "";
mathieu@2372
   909
}
mathieu@2372
   910
mathieu@2372
   911
std::string 
mathieu@2459
   912
AttributeList::SerializeToString (void) const
mathieu@2372
   913
{
mathieu@2372
   914
  std::ostringstream oss;
mathieu@2458
   915
  for (Attrs::const_iterator i = m_attributes.begin (); i != m_attributes.end (); i++)
mathieu@2372
   916
    {
mathieu@2458
   917
      std::string name = LookupAttributeFullNameByChecker (i->checker);
mathieu@2427
   918
      oss << name << "=" << i->value.SerializeToString (i->checker);
mathieu@2458
   919
      if (i != m_attributes.end ())
mathieu@2372
   920
        {
mathieu@2372
   921
          oss << "|";
mathieu@2372
   922
        }
mathieu@2372
   923
    }  
mathieu@2372
   924
  return oss.str ();
mathieu@2372
   925
}
mathieu@2372
   926
bool 
mathieu@2459
   927
AttributeList::DeserializeFromString (std::string str)
mathieu@2372
   928
{
mathieu@2372
   929
  Reset ();
mathieu@2372
   930
mathieu@2372
   931
  std::string::size_type cur;
mathieu@2372
   932
  cur = 0;
mathieu@2372
   933
  do {
mathieu@2372
   934
    std::string::size_type equal = str.find ("=", cur);
mathieu@2372
   935
    if (equal == std::string::npos)
mathieu@2372
   936
      {
mathieu@2458
   937
        // XXX: invalid attribute.
mathieu@2372
   938
        break;
mathieu@2372
   939
      }
mathieu@2372
   940
    else
mathieu@2372
   941
      {
mathieu@2372
   942
        std::string name = str.substr (cur, equal-cur);
mathieu@2458
   943
        struct TypeId::AttributeInfo info;
mathieu@2458
   944
        if (!TypeId::LookupAttributeByFullName (name, &info))
mathieu@2372
   945
          {
mathieu@2372
   946
            // XXX invalid name.
mathieu@2372
   947
            break;
mathieu@2372
   948
          }
mathieu@2372
   949
        else
mathieu@2372
   950
          {
mathieu@2372
   951
            std::string::size_type next = str.find ("|", cur);
mathieu@2372
   952
            std::string value;
mathieu@2372
   953
            if (next == std::string::npos)
mathieu@2372
   954
              {
mathieu@2372
   955
                value = str.substr (equal+1, str.size () - (equal+1));
mathieu@2372
   956
                cur = str.size ();
mathieu@2372
   957
              }
mathieu@2372
   958
            else
mathieu@2372
   959
              {
mathieu@2372
   960
                value = str.substr (equal+1, next - (equal+1));
mathieu@2372
   961
                cur++;
mathieu@2372
   962
              }
mathieu@2520
   963
            Attribute val = info.checker->Create ();
mathieu@2427
   964
            bool ok = val.DeserializeFromString (value, info.checker);
mathieu@2372
   965
            if (!ok)
mathieu@2372
   966
              {
mathieu@2372
   967
                // XXX invalid value
mathieu@2372
   968
                break;
mathieu@2372
   969
              }
mathieu@2372
   970
            else
mathieu@2372
   971
              {
mathieu@2427
   972
                DoSetOne (info.checker, val);
mathieu@2372
   973
              }
mathieu@2372
   974
          }
mathieu@2372
   975
      }
mathieu@2372
   976
  } while (cur != str.size ());
mathieu@2372
   977
mathieu@2372
   978
  return true;
mathieu@2372
   979
}
mathieu@2372
   980
mathieu@2372
   981
mathieu@2372
   982
/*********************************************************************
mathieu@2233
   983
 *         The Object implementation
mathieu@2233
   984
 *********************************************************************/
mathieu@2233
   985
mathieu@2247
   986
NS_OBJECT_ENSURE_REGISTERED (Object);
mathieu@2247
   987
mathieu@2250
   988
static TypeId
mathieu@2238
   989
GetObjectIid (void)
mathieu@2238
   990
{
mathieu@2252
   991
  TypeId tid = TypeId ("Object");
mathieu@2252
   992
  tid.SetParent (tid);
mathieu@2252
   993
  return tid;
mathieu@2238
   994
}
mathieu@2233
   995
mathieu@2250
   996
TypeId 
mathieu@2251
   997
Object::GetTypeId (void)
mathieu@2232
   998
{
mathieu@2252
   999
  static TypeId tid = GetObjectIid ();
mathieu@2252
  1000
  return tid;
mathieu@2232
  1001
}
mathieu@699
  1002
mathieu@699
  1003
mathieu@706
  1004
Object::Object ()
mathieu@699
  1005
  : m_count (1),
mathieu@2252
  1006
    m_tid (Object::GetTypeId ()),
mathieu@713
  1007
    m_disposed (false),
mathieu@1374
  1008
    m_collecting (false),
mathieu@702
  1009
    m_next (this)
mathieu@699
  1010
{}
mathieu@706
  1011
Object::~Object () 
mathieu@706
  1012
{
mathieu@706
  1013
  m_next = 0;
mathieu@706
  1014
}
mathieu@2372
  1015
void
mathieu@2459
  1016
Object::Construct (const AttributeList &attributes)
mathieu@2372
  1017
{
mathieu@2372
  1018
  // loop over the inheritance tree back to the Object base class.
mathieu@2372
  1019
  TypeId tid = m_tid;
mathieu@2372
  1020
  do {
mathieu@2458
  1021
    // loop over all attributes in object type
mathieu@2459
  1022
    NS_LOG_DEBUG ("construct tid="<<tid.GetName ()<<", params="<<tid.GetAttributeListN ());
mathieu@2459
  1023
    for (uint32_t i = 0; i < tid.GetAttributeListN (); i++)
mathieu@2372
  1024
      {
mathieu@2458
  1025
        Ptr<const AttributeAccessor> paramSpec = tid.GetAttributeAccessor (i);
mathieu@2458
  1026
        Attribute initial = tid.GetAttributeInitialValue (i);
mathieu@2458
  1027
        Ptr<const AttributeChecker> checker = tid.GetAttributeChecker (i);
mathieu@2372
  1028
        NS_LOG_DEBUG ("try to construct \""<< tid.GetName ()<<"::"<<
mathieu@2458
  1029
                      tid.GetAttributeName (i)<<"\"");
mathieu@2458
  1030
        if (!(tid.GetAttributeFlags (i) & TypeId::ATTR_CONSTRUCT))
mathieu@2382
  1031
          {
mathieu@2382
  1032
            continue;
mathieu@2382
  1033
          }
mathieu@2372
  1034
        bool found = false;
mathieu@2459
  1035
        // is this attribute stored in this AttributeList instance ?
mathieu@2459
  1036
        for (AttributeList::Attrs::const_iterator j = attributes.m_attributes.begin ();
mathieu@2458
  1037
             j != attributes.m_attributes.end (); j++)
mathieu@2372
  1038
          {
mathieu@2427
  1039
            if (j->checker == checker)
mathieu@2372
  1040
              {
mathieu@2458
  1041
                // We have a matching attribute value.
mathieu@2427
  1042
                DoSet (paramSpec, initial, checker, j->value);
mathieu@2372
  1043
                NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
mathieu@2458
  1044
                              tid.GetAttributeName (i)<<"\"");
mathieu@2372
  1045
                found = true;
mathieu@2372
  1046
                break;
mathieu@2372
  1047
              }
mathieu@2372
  1048
          }
mathieu@2372
  1049
        if (!found)
mathieu@2372
  1050
          {
mathieu@2458
  1051
            // is this attribute stored in the global instance instance ?
mathieu@2459
  1052
            for (AttributeList::Attrs::const_iterator j = AttributeList::GetGlobal ()->m_attributes.begin ();
mathieu@2459
  1053
                 j != AttributeList::GetGlobal ()->m_attributes.end (); j++)
mathieu@2372
  1054
              {
mathieu@2427
  1055
                if (j->checker == checker)
mathieu@2372
  1056
                  {
mathieu@2458
  1057
                    // We have a matching attribute value.
mathieu@2427
  1058
                    DoSet (paramSpec, initial, checker, j->value);
mathieu@2372
  1059
                    NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
mathieu@2458
  1060
                                  tid.GetAttributeName (i)<<"\" from global");
mathieu@2372
  1061
                    found = true;
mathieu@2372
  1062
                    break;
mathieu@2372
  1063
                  }
mathieu@2372
  1064
              }
mathieu@2372
  1065
          }
mathieu@2372
  1066
        if (!found)
mathieu@2372
  1067
          {
mathieu@2458
  1068
            // No matching attribute value so we set the default value.
mathieu@2372
  1069
            paramSpec->Set (this, initial);
mathieu@2372
  1070
            NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
mathieu@2523
  1071
                          tid.GetAttributeName (i)<<"\" from initial value.");
mathieu@2372
  1072
          }
mathieu@2372
  1073
      }
mathieu@2372
  1074
    tid = tid.GetParent ();
mathieu@2372
  1075
  } while (tid != Object::GetTypeId ());
mathieu@2372
  1076
  NotifyConstructionCompleted ();
mathieu@2372
  1077
}
mathieu@2372
  1078
bool
mathieu@2436
  1079
Object::DoSet (Ptr<const AttributeAccessor> spec, Attribute initialValue, 
mathieu@2433
  1080
               Ptr<const AttributeChecker> checker, Attribute value)
mathieu@2397
  1081
{
mathieu@2427
  1082
  bool ok = checker->Check (value);
mathieu@2397
  1083
  if (!ok)
mathieu@2397
  1084
    {
mathieu@2421
  1085
      // attempt to convert to string
mathieu@2424
  1086
      const StringValue *str = value.DynCast<const StringValue *> ();
mathieu@2424
  1087
      if (str == 0)
mathieu@2424
  1088
        {
mathieu@2424
  1089
          return false;
mathieu@2424
  1090
        }
mathieu@2421
  1091
      // attempt to convert back from string.
mathieu@2520
  1092
      Attribute v = checker->Create ();
mathieu@2502
  1093
      ok = v.DeserializeFromString (str->Get ().Get (), checker);
mathieu@2421
  1094
      if (!ok)
mathieu@2421
  1095
        {
mathieu@2421
  1096
          return false;
mathieu@2421
  1097
        }
mathieu@2427
  1098
      ok = checker->Check (v);
mathieu@2397
  1099
      if (!ok)
mathieu@2397
  1100
        {
mathieu@2397
  1101
          return false;
mathieu@2397
  1102
        }
mathieu@2397
  1103
      value = v;
mathieu@2397
  1104
    }
mathieu@2397
  1105
  ok = spec->Set (this, value);
mathieu@2397
  1106
  return ok;
mathieu@2397
  1107
}
mathieu@2397
  1108
bool
mathieu@2460
  1109
Object::SetAttribute (std::string name, Attribute value)
mathieu@2372
  1110
{
mathieu@2458
  1111
  struct TypeId::AttributeInfo info;
mathieu@2458
  1112
  if (!m_tid.LookupAttributeByName (name, &info))
mathieu@2372
  1113
    {
mathieu@2372
  1114
      return false;
mathieu@2372
  1115
    }
mathieu@2432
  1116
  if (!(info.flags & TypeId::ATTR_SET))
mathieu@2382
  1117
    {
mathieu@2382
  1118
      return false;
mathieu@2382
  1119
    }
mathieu@2458
  1120
  return DoSet (info.accessor, info.initialValue, info.checker, value);
mathieu@2372
  1121
}
mathieu@2372
  1122
bool 
mathieu@2460
  1123
Object::GetAttribute (std::string name, std::string &value) const
mathieu@2372
  1124
{
mathieu@2458
  1125
  struct TypeId::AttributeInfo info;
mathieu@2458
  1126
  if (!m_tid.LookupAttributeByName (name, &info))
mathieu@2372
  1127
    {
mathieu@2372
  1128
      return false;
mathieu@2372
  1129
    }
mathieu@2432
  1130
  if (!(info.flags & TypeId::ATTR_GET))
mathieu@2382
  1131
    {
mathieu@2382
  1132
      return false;
mathieu@2382
  1133
    }
mathieu@2520
  1134
  Attribute v = info.checker->Create ();
mathieu@2458
  1135
  bool ok = info.accessor->Get (this, v);
mathieu@2372
  1136
  if (ok)
mathieu@2372
  1137
    {
mathieu@2427
  1138
      value = v.SerializeToString (info.checker);
mathieu@2372
  1139
    }
mathieu@2372
  1140
  return ok;
mathieu@2372
  1141
}
mathieu@2372
  1142
mathieu@2433
  1143
Attribute
mathieu@2460
  1144
Object::GetAttribute (std::string name) const
mathieu@2372
  1145
{
mathieu@2458
  1146
  struct TypeId::AttributeInfo info;
mathieu@2458
  1147
  if (!m_tid.LookupAttributeByName (name, &info))
mathieu@2372
  1148
    {
mathieu@2433
  1149
      return Attribute ();
mathieu@2372
  1150
    }
mathieu@2432
  1151
  if (!(info.flags & TypeId::ATTR_GET))
mathieu@2382
  1152
    {
mathieu@2433
  1153
      return Attribute ();
mathieu@2382
  1154
    }
mathieu@2520
  1155
  Attribute value = info.checker->Create ();
mathieu@2458
  1156
  bool ok = info.accessor->Get (this, value);
mathieu@2372
  1157
  if (!ok)
mathieu@2372
  1158
    {
mathieu@2433
  1159
      return Attribute ();
mathieu@2372
  1160
    }
mathieu@2372
  1161
  return value;
mathieu@2372
  1162
}
mathieu@2372
  1163
mathieu@2463
  1164
bool 
mathieu@2463
  1165
Object::TraceSourceConnect (std::string name, const CallbackBase &cb)
mathieu@2463
  1166
{
mathieu@2463
  1167
  Ptr<const TraceSourceAccessor> accessor = m_tid.LookupTraceSourceByName (name);
mathieu@2463
  1168
  if (accessor == 0)
mathieu@2463
  1169
    {
mathieu@2463
  1170
      return false;
mathieu@2463
  1171
    }
mathieu@2463
  1172
  bool ok = accessor->Connect (this, cb);
mathieu@2463
  1173
  return ok;
mathieu@2463
  1174
}
mathieu@2463
  1175
bool 
mathieu@2531
  1176
Object::TraceSourceConnectWithContext (std::string name, std::string context, const CallbackBase &cb)
mathieu@2531
  1177
{
mathieu@2531
  1178
  Ptr<const TraceSourceAccessor> accessor = m_tid.LookupTraceSourceByName (name);
mathieu@2531
  1179
  if (accessor == 0)
mathieu@2531
  1180
    {
mathieu@2531
  1181
      return false;
mathieu@2531
  1182
    }
mathieu@2531
  1183
  bool ok = accessor->ConnectWithContext (this, context, cb);
mathieu@2531
  1184
  return ok;
mathieu@2531
  1185
}
mathieu@2531
  1186
bool 
mathieu@2463
  1187
Object::TraceSourceDisconnect (std::string name, const CallbackBase &cb)
mathieu@2463
  1188
{
mathieu@2463
  1189
  Ptr<const TraceSourceAccessor> accessor = m_tid.LookupTraceSourceByName (name);
mathieu@2463
  1190
  if (accessor == 0)
mathieu@2463
  1191
    {
mathieu@2463
  1192
      return false;
mathieu@2463
  1193
    }
mathieu@2463
  1194
  bool ok = accessor->Disconnect (this, cb);
mathieu@2463
  1195
  return ok;
mathieu@2463
  1196
}
mathieu@2463
  1197
mathieu@2471
  1198
TypeId 
mathieu@2471
  1199
Object::GetRealTypeId (void) const
mathieu@2471
  1200
{
mathieu@2471
  1201
  return m_tid;
mathieu@2471
  1202
}
mathieu@2471
  1203
mathieu@2463
  1204
mathieu@706
  1205
Ptr<Object>
mathieu@2257
  1206
Object::DoGetObject (TypeId tid) const
mathieu@699
  1207
{
gjc@1534
  1208
  NS_ASSERT (CheckLoose ());
mathieu@709
  1209
  const Object *currentObject = this;
mathieu@702
  1210
  do {
mathieu@702
  1211
    NS_ASSERT (currentObject != 0);
mathieu@2252
  1212
    TypeId cur = currentObject->m_tid;
mathieu@2252
  1213
    while (cur != tid && cur != Object::GetTypeId ())
mathieu@702
  1214
      {
mathieu@2235
  1215
        cur = cur.GetParent ();
mathieu@702
  1216
      }
mathieu@2252
  1217
    if (cur == tid)
mathieu@702
  1218
      {
mathieu@709
  1219
        return const_cast<Object *> (currentObject);
mathieu@702
  1220
      }
mathieu@702
  1221
    currentObject = currentObject->m_next;
mathieu@702
  1222
  } while (currentObject != this);
mathieu@699
  1223
  return 0;
mathieu@699
  1224
}
mathieu@699
  1225
void 
mathieu@706
  1226
Object::Dispose (void)
mathieu@699
  1227
{
mathieu@706
  1228
  Object *current = this;
mathieu@702
  1229
  do {
mathieu@702
  1230
    NS_ASSERT (current != 0);
mathieu@713
  1231
    NS_ASSERT (!current->m_disposed);
mathieu@702
  1232
    current->DoDispose ();
mathieu@713
  1233
    current->m_disposed = true;
mathieu@702
  1234
    current = current->m_next;
mathieu@702
  1235
  } while (current != this);
mathieu@699
  1236
}
mathieu@2372
  1237
void
mathieu@2372
  1238
Object::NotifyConstructionCompleted (void)
mathieu@2372
  1239
{}
mathieu@699
  1240
void 
mathieu@2258
  1241
Object::AggregateObject (Ptr<Object> o)
mathieu@699
  1242
{
mathieu@718
  1243
  NS_ASSERT (!m_disposed);
mathieu@718
  1244
  NS_ASSERT (!o->m_disposed);
gjc@1534
  1245
  NS_ASSERT (CheckLoose ());
gjc@1534
  1246
  NS_ASSERT (o->CheckLoose ());
mathieu@706
  1247
  Object *other = PeekPointer (o);
mathieu@706
  1248
  Object *next = m_next;
mathieu@702
  1249
  m_next = other->m_next;
mathieu@702
  1250
  other->m_next = next;
gjc@1534
  1251
  NS_ASSERT (CheckLoose ());
gjc@1534
  1252
  NS_ASSERT (o->CheckLoose ());
mathieu@699
  1253
}
mathieu@699
  1254
mathieu@699
  1255
void 
mathieu@1383
  1256
Object::TraceConnect (std::string path, const CallbackBase &cb) const
mathieu@1336
  1257
{
gjc@1534
  1258
  NS_ASSERT (CheckLoose ());
mathieu@1368
  1259
  GetTraceResolver ()->Connect (path, cb, TraceContext ());
mathieu@1336
  1260
}
mathieu@1336
  1261
void 
mathieu@1383
  1262
Object::TraceDisconnect (std::string path, const CallbackBase &cb) const
mathieu@1336
  1263
{
gjc@1534
  1264
  NS_ASSERT (CheckLoose ());
mathieu@1336
  1265
  GetTraceResolver ()->Disconnect (path, cb);
mathieu@1336
  1266
}
mathieu@1336
  1267
mathieu@1336
  1268
void 
mathieu@2252
  1269
Object::SetTypeId (TypeId tid)
mathieu@699
  1270
{
mathieu@699
  1271
  NS_ASSERT (Check ());
mathieu@2252
  1272
  m_tid = tid;
mathieu@699
  1273
}
mathieu@699
  1274
mathieu@699
  1275
void
mathieu@706
  1276
Object::DoDispose (void)
mathieu@713
  1277
{
mathieu@713
  1278
  NS_ASSERT (!m_disposed);
mathieu@713
  1279
}
mathieu@699
  1280
mathieu@1336
  1281
Ptr<TraceResolver>
mathieu@1383
  1282
Object::GetTraceResolver (void) const
mathieu@1336
  1283
{
gjc@1534
  1284
  NS_ASSERT (CheckLoose ());
mathieu@2250
  1285
  Ptr<TypeIdTraceResolver> resolver =
mathieu@2250
  1286
    Create<TypeIdTraceResolver> (this);
mathieu@1346
  1287
  return resolver;
mathieu@1336
  1288
}
mathieu@1336
  1289
mathieu@699
  1290
bool 
mathieu@706
  1291
Object::Check (void) const
mathieu@699
  1292
{
mathieu@701
  1293
  return (m_count > 0);
mathieu@701
  1294
}
mathieu@701
  1295
gjc@1534
  1296
/* In some cases, when an event is scheduled against a subclass of
gjc@1534
  1297
 * Object, and if no one owns a reference directly to this object, the
gjc@1534
  1298
 * object is alive, has a refcount of zero and the method ran when the
gjc@1534
  1299
 * event expires runs against the raw pointer which means that we are
gjc@1534
  1300
 * manipulating an object with a refcount of zero.  So, instead we
gjc@1534
  1301
 * check the aggregate reference count.
gjc@1534
  1302
 */
gjc@1534
  1303
bool 
gjc@1534
  1304
Object::CheckLoose (void) const
gjc@1534
  1305
{
gjc@1534
  1306
  uint32_t refcount = 0;
gjc@1534
  1307
  const Object *current = this;
gjc@1534
  1308
  do
gjc@1534
  1309
    {
gjc@1534
  1310
      refcount += current->m_count;
gjc@1534
  1311
      current = current->m_next;
gjc@1534
  1312
    }
gjc@1534
  1313
  while (current != this);
gjc@1534
  1314
gjc@1534
  1315
  return (refcount > 0);
gjc@1534
  1316
}
gjc@1534
  1317
mathieu@701
  1318
void
mathieu@706
  1319
Object::MaybeDelete (void) const
mathieu@701
  1320
{
mathieu@702
  1321
  // First, check if any of the attached
mathieu@702
  1322
  // Object has a non-zero count.
mathieu@706
  1323
  const Object *current = this;
mathieu@702
  1324
  do {
mathieu@702
  1325
    NS_ASSERT (current != 0);
mathieu@702
  1326
    if (current->m_count != 0)
mathieu@702
  1327
      {
mathieu@702
  1328
        return;
mathieu@702
  1329
      }
mathieu@702
  1330
    current = current->m_next;
mathieu@702
  1331
  } while (current != this);
mathieu@702
  1332
mathieu@2529
  1333
  // Ensure we are disposed.
mathieu@2529
  1334
  Object *tmp = const_cast<Object *> (this);
mathieu@2529
  1335
  const Object *end = this;
mathieu@2529
  1336
  do {
mathieu@2529
  1337
    NS_ASSERT (current != 0);
mathieu@2529
  1338
    Object *next = tmp->m_next;
mathieu@2529
  1339
    if (!tmp->m_disposed)
mathieu@2529
  1340
      {
mathieu@2529
  1341
        tmp->DoDispose ();
mathieu@2529
  1342
      }
mathieu@2529
  1343
    tmp = next;
mathieu@2529
  1344
  } while (tmp != end);
mathieu@2529
  1345
mathieu@702
  1346
  // all attached objects have a zero count so, 
mathieu@702
  1347
  // we can delete all attached objects.
mathieu@702
  1348
  current = this;
mathieu@702
  1349
  do {
mathieu@702
  1350
    NS_ASSERT (current != 0);
mathieu@706
  1351
    Object *next = current->m_next;
mathieu@702
  1352
    delete current;
mathieu@702
  1353
    current = next;
mathieu@702
  1354
  } while (current != end);
mathieu@699
  1355
}
mathieu@699
  1356
mathieu@1371
  1357
void 
mathieu@1371
  1358
Object::DoCollectSources (std::string path, const TraceContext &context, 
mathieu@1383
  1359
                          TraceResolver::SourceCollection *collection) const
mathieu@1371
  1360
{
mathieu@1383
  1361
  const Object *current;
mathieu@1374
  1362
  current = this;
mathieu@1374
  1363
  do {
mathieu@1374
  1364
    if (current->m_collecting)
mathieu@1374
  1365
      {
mathieu@1374
  1366
        return;
mathieu@1374
  1367
      }
mathieu@1374
  1368
    current = current->m_next;
mathieu@1374
  1369
  } while (current != this);
mathieu@1374
  1370
mathieu@1374
  1371
  m_collecting = true;
mathieu@1374
  1372
mathieu@1374
  1373
  current = this->m_next;
mathieu@1371
  1374
  while (current != this)
mathieu@1371
  1375
    {
mathieu@1371
  1376
      NS_ASSERT (current != 0);
craigdo@1504
  1377
      NS_LOG_LOGIC ("collect current=" << current);
mathieu@2252
  1378
      TypeId cur = current->m_tid;
mathieu@2251
  1379
      while (cur != Object::GetTypeId ())
mathieu@1371
  1380
        {
mathieu@1371
  1381
          std::string name = cur.GetName ();
mathieu@1371
  1382
          std::string fullpath = path;
mathieu@1371
  1383
          fullpath.append ("/$");
mathieu@1371
  1384
          fullpath.append (name);
craigdo@1504
  1385
          NS_LOG_LOGIC("collect: " << fullpath);
mathieu@1371
  1386
          current->GetTraceResolver ()->CollectSources (fullpath, context, collection);
mathieu@2235
  1387
          cur = cur.GetParent ();
mathieu@1371
  1388
        }
mathieu@1371
  1389
      current = current->m_next;
mathieu@1371
  1390
    }
mathieu@1374
  1391
mathieu@1374
  1392
  m_collecting = false;
mathieu@1371
  1393
}
mathieu@1419
  1394
void 
mathieu@1420
  1395
Object::DoTraceAll (std::ostream &os, const TraceContext &context) const
mathieu@1419
  1396
{
mathieu@1419
  1397
  const Object *current;
mathieu@1419
  1398
  current = this;
mathieu@1419
  1399
  do {
mathieu@1419
  1400
    if (current->m_collecting)
mathieu@1419
  1401
      {
mathieu@1419
  1402
        return;
mathieu@1419
  1403
      }
mathieu@1419
  1404
    current = current->m_next;
mathieu@1419
  1405
  } while (current != this);
mathieu@1419
  1406
mathieu@1419
  1407
  m_collecting = true;
mathieu@1419
  1408
mathieu@1419
  1409
  current = this->m_next;
mathieu@1419
  1410
  while (current != this)
mathieu@1419
  1411
    {
mathieu@1419
  1412
      NS_ASSERT (current != 0);
mathieu@1420
  1413
      current->GetTraceResolver ()->TraceAll (os, context);
mathieu@1419
  1414
      current = current->m_next;
mathieu@1419
  1415
    }
mathieu@1419
  1416
mathieu@1419
  1417
  m_collecting = false;
mathieu@1419
  1418
}
mathieu@1371
  1419
mathieu@699
  1420
} // namespace ns3
mathieu@699
  1421
mathieu@699
  1422
mathieu@699
  1423
#ifdef RUN_SELF_TESTS
mathieu@699
  1424
mathieu@699
  1425
#include "test.h"
mathieu@1358
  1426
#include "sv-trace-source.h"
mathieu@1358
  1427
#include "composite-trace-resolver.h"
mathieu@699
  1428
mathieu@699
  1429
namespace {
mathieu@699
  1430
mathieu@706
  1431
class BaseA : public ns3::Object
mathieu@699
  1432
{
mathieu@699
  1433
public:
mathieu@2251
  1434
  static ns3::TypeId GetTypeId (void) {
mathieu@2252
  1435
    static ns3::TypeId tid = ns3::TypeId ("BaseA")
mathieu@2251
  1436
      .SetParent (Object::GetTypeId ())
mathieu@2237
  1437
      .AddConstructor<BaseA> ();
mathieu@2252
  1438
    return tid;
mathieu@2232
  1439
  }
mathieu@699
  1440
  BaseA ()
mathieu@2230
  1441
  {}
mathieu@1351
  1442
  void BaseGenerateTrace (int16_t v)
mathieu@1351
  1443
  { m_source = v; }
mathieu@699
  1444
  virtual void Dispose (void) {}
mathieu@1406
  1445
  virtual ns3::Ptr<ns3::TraceResolver> GetTraceResolver (void) const
mathieu@1351
  1446
  {
mathieu@1351
  1447
    ns3::Ptr<ns3::CompositeTraceResolver> resolver = 
mathieu@1351
  1448
      ns3::Create<ns3::CompositeTraceResolver> ();
mathieu@1379
  1449
    resolver->AddSource ("basea-x", ns3::TraceDoc ("test source"), m_source);
mathieu@1386
  1450
    resolver->SetParentResolver (Object::GetTraceResolver ());
mathieu@1351
  1451
    return resolver;
mathieu@1351
  1452
  }
mathieu@1351
  1453
  ns3::SVTraceSource<int16_t> m_source;
mathieu@699
  1454
};
mathieu@699
  1455
mathieu@699
  1456
class DerivedA : public BaseA
mathieu@699
  1457
{
mathieu@699
  1458
public:
mathieu@2251
  1459
  static ns3::TypeId GetTypeId (void) {
mathieu@2252
  1460
    static ns3::TypeId tid = ns3::TypeId ("DerivedA")
mathieu@2251
  1461
      .SetParent (BaseA::GetTypeId ())
mathieu@2372
  1462
      .AddConstructor<DerivedA> ();
mathieu@2252
  1463
    return tid;
mathieu@2232
  1464
  }
mathieu@2372
  1465
  DerivedA ()
mathieu@2230
  1466
  {}
mathieu@1351
  1467
  void DerivedGenerateTrace (int16_t v)
mathieu@1351
  1468
  { m_sourceDerived = v; }
mathieu@699
  1469
  virtual void Dispose (void) {
mathieu@699
  1470
    BaseA::Dispose ();
mathieu@699
  1471
  }
mathieu@1406
  1472
  virtual ns3::Ptr<ns3::TraceResolver> GetTraceResolver (void) const
mathieu@1351
  1473
  {
mathieu@1351
  1474
    ns3::Ptr<ns3::CompositeTraceResolver> resolver = 
mathieu@1351
  1475
      ns3::Create<ns3::CompositeTraceResolver> ();
mathieu@1379
  1476
    resolver->AddSource ("deriveda-x", ns3::TraceDoc ("test source"), m_sourceDerived);
mathieu@1386
  1477
    resolver->SetParentResolver (BaseA::GetTraceResolver ());
mathieu@1351
  1478
    return resolver;
mathieu@1351
  1479
  }
mathieu@1351
  1480
  ns3::SVTraceSource<int16_t> m_sourceDerived;
mathieu@699
  1481
};
mathieu@699
  1482
mathieu@706
  1483
class BaseB : public ns3::Object
mathieu@699
  1484
{
mathieu@699
  1485
public:
mathieu@2251
  1486
  static ns3::TypeId GetTypeId (void) {
mathieu@2252
  1487
    static ns3::TypeId tid = ns3::TypeId ("BaseB")
mathieu@2251
  1488
      .SetParent (Object::GetTypeId ())
mathieu@2237
  1489
      .AddConstructor<BaseB> ();
mathieu@2252
  1490
    return tid;
mathieu@2232
  1491
  }
mathieu@699
  1492
  BaseB ()
mathieu@2230
  1493
  {}
mathieu@1351
  1494
  void BaseGenerateTrace (int16_t v)
mathieu@1351
  1495
  { m_source = v; }
mathieu@699
  1496
  virtual void Dispose (void) {}
mathieu@1406
  1497
  virtual ns3::Ptr<ns3::TraceResolver> GetTraceResolver (void) const
mathieu@1351
  1498
  {
mathieu@1351
  1499
    ns3::Ptr<ns3::CompositeTraceResolver> resolver = 
mathieu@1351
  1500
      ns3::Create<ns3::CompositeTraceResolver> ();
mathieu@1379
  1501
    resolver->AddSource ("baseb-x", ns3::TraceDoc ("test source"), m_source);
mathieu@1386
  1502
    resolver->SetParentResolver (Object::GetTraceResolver ());
mathieu@1351
  1503
    return resolver;
mathieu@1351
  1504
  }
mathieu@1351
  1505
  ns3::SVTraceSource<int16_t> m_source;
mathieu@699
  1506
};
mathieu@699
  1507
mathieu@699
  1508
class DerivedB : public BaseB
mathieu@699
  1509
{
mathieu@699
  1510
public:
mathieu@2251
  1511
  static ns3::TypeId GetTypeId (void) {
mathieu@2252
  1512
    static ns3::TypeId tid = ns3::TypeId ("DerivedB")
mathieu@2251
  1513
      .SetParent (BaseB::GetTypeId ())
mathieu@2372
  1514
      .AddConstructor<DerivedB> ();
mathieu@2252
  1515
    return tid;
mathieu@2232
  1516
  }
mathieu@2372
  1517
  DerivedB ()
mathieu@2243
  1518
  {}
mathieu@1351
  1519
  void DerivedGenerateTrace (int16_t v)
mathieu@1351
  1520
  { m_sourceDerived = v; }
mathieu@699
  1521
  virtual void Dispose (void) {
mathieu@699
  1522
    BaseB::Dispose ();
mathieu@699
  1523
  }
mathieu@1406
  1524
  virtual ns3::Ptr<ns3::TraceResolver> GetTraceResolver (void) const
mathieu@1351
  1525
  {
mathieu@1351
  1526
    ns3::Ptr<ns3::CompositeTraceResolver> resolver = 
mathieu@1351
  1527
      ns3::Create<ns3::CompositeTraceResolver> ();
mathieu@1379
  1528
    resolver->AddSource ("derivedb-x", ns3::TraceDoc ("test source"), m_sourceDerived);
mathieu@1386
  1529
    resolver->SetParentResolver (BaseB::GetTraceResolver ());
mathieu@1351
  1530
    return resolver;
mathieu@1351
  1531
  }
mathieu@1351
  1532
  ns3::SVTraceSource<int16_t> m_sourceDerived;
mathieu@699
  1533
};
mathieu@699
  1534
mathieu@2247
  1535
NS_OBJECT_ENSURE_REGISTERED (BaseA);
mathieu@2247
  1536
NS_OBJECT_ENSURE_REGISTERED (DerivedA);
mathieu@2247
  1537
NS_OBJECT_ENSURE_REGISTERED (BaseB);
mathieu@2247
  1538
NS_OBJECT_ENSURE_REGISTERED (DerivedB);
mathieu@2247
  1539
mathieu@699
  1540
} // namespace anonymous
mathieu@699
  1541
mathieu@699
  1542
namespace ns3 {
mathieu@699
  1543
mathieu@706
  1544
class ObjectTest : public Test
mathieu@699
  1545
{
mathieu@699
  1546
public:
mathieu@706
  1547
  ObjectTest ();
mathieu@699
  1548
  virtual bool RunTests (void);
mathieu@1351
  1549
private:
mathieu@1351
  1550
  void BaseATrace (const TraceContext &context, int64_t oldValue, int64_t newValue);
mathieu@1351
  1551
  void DerivedATrace (const TraceContext &context, int64_t oldValue, int64_t newValue);
mathieu@1351
  1552
  void BaseBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue);
mathieu@1351
  1553
  void DerivedBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue);
mathieu@1351
  1554
mathieu@1351
  1555
  bool m_baseATrace;
mathieu@1351
  1556
  bool m_derivedATrace;
mathieu@1351
  1557
  bool m_baseBTrace;
mathieu@1351
  1558
  bool m_derivedBTrace;
mathieu@699
  1559
};
mathieu@699
  1560
mathieu@706
  1561
ObjectTest::ObjectTest ()
mathieu@706
  1562
  : Test ("Object")
mathieu@699
  1563
{}
mathieu@1351
  1564
void 
mathieu@1351
  1565
ObjectTest::BaseATrace (const TraceContext &context, int64_t oldValue, int64_t newValue)
mathieu@1351
  1566
{
mathieu@1351
  1567
  m_baseATrace = true;
mathieu@1351
  1568
}
mathieu@1351
  1569
void 
mathieu@1351
  1570
ObjectTest::DerivedATrace (const TraceContext &context, int64_t oldValue, int64_t newValue)
mathieu@1351
  1571
{
mathieu@1351
  1572
  m_derivedATrace = true;
mathieu@1351
  1573
}
mathieu@1351
  1574
void 
mathieu@1351
  1575
ObjectTest::BaseBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue)
mathieu@1351
  1576
{
mathieu@1351
  1577
  m_baseBTrace = true;
mathieu@1351
  1578
}
mathieu@1351
  1579
void 
mathieu@1351
  1580
ObjectTest::DerivedBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue)
mathieu@1351
  1581
{
mathieu@1351
  1582
  m_derivedBTrace = true;
mathieu@1351
  1583
}
mathieu@1351
  1584
mathieu@699
  1585
bool 
mathieu@706
  1586
ObjectTest::RunTests (void)
mathieu@699
  1587
{
mathieu@1349
  1588
  bool result = true;
mathieu@699
  1589
mathieu@2230
  1590
  Ptr<BaseA> baseA = CreateObject<BaseA> ();
mathieu@2257
  1591
  NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (), baseA);
mathieu@2257
  1592
  NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), 0);
mathieu@2257
  1593
  NS_TEST_ASSERT_EQUAL (baseA->GetObject<DerivedA> (), 0);
mathieu@2372
  1594
  baseA = CreateObject<DerivedA> ();
mathieu@2257
  1595
  NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (), baseA);
mathieu@2257
  1596
  NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), baseA);
mathieu@2257
  1597
  NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<DerivedA> (), 0);
mathieu@699
  1598
mathieu@2230
  1599
  baseA = CreateObject<BaseA> ();
mathieu@2230
  1600
  Ptr<BaseB> baseB = CreateObject<BaseB> ();
mathieu@699
  1601
  Ptr<BaseB> baseBCopy = baseB;
mathieu@2258
  1602
  baseA->AggregateObject (baseB);
mathieu@2257
  1603
  NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<BaseA> (), 0);
mathieu@2257
  1604
  NS_TEST_ASSERT_EQUAL (baseA->GetObject<DerivedA> (), 0);
mathieu@2257
  1605
  NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<BaseB> (), 0);
mathieu@2257
  1606
  NS_TEST_ASSERT_EQUAL (baseA->GetObject<DerivedB> (), 0);
mathieu@2257
  1607
  NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseB> (), 0);
mathieu@2257
  1608
  NS_TEST_ASSERT_EQUAL (baseB->GetObject<DerivedB> (), 0);
mathieu@2257
  1609
  NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseA> (), 0);
mathieu@2257
  1610
  NS_TEST_ASSERT_EQUAL (baseB->GetObject<DerivedA> (), 0);
mathieu@2257
  1611
  NS_TEST_ASSERT_UNEQUAL (baseBCopy->GetObject<BaseA> (), 0);
mathieu@699
  1612
mathieu@2372
  1613
  baseA = CreateObject<DerivedA> ();
mathieu@2372
  1614
  baseB = CreateObject<DerivedB> ();
mathieu@699
  1615
  baseBCopy = baseB;
mathieu@2258
  1616
  baseA->AggregateObject (baseB);
mathieu@2257
  1617
  NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<DerivedB> (), 0);
mathieu@2257
  1618
  NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<BaseB> (), 0);
mathieu@2257
  1619
  NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<DerivedA> (), 0);
mathieu@2257
  1620
  NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseA> (), 0);
mathieu@2257
  1621
  NS_TEST_ASSERT_UNEQUAL (baseBCopy->GetObject<DerivedA> (), 0);
mathieu@2257
  1622
  NS_TEST_ASSERT_UNEQUAL (baseBCopy->GetObject<BaseA> (), 0);
mathieu@2257
  1623
  NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<DerivedB> (), 0);
mathieu@2257
  1624
  NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseB> (), 0)
mathieu@699
  1625
mathieu@2230
  1626
  baseA = CreateObject<BaseA> ();
mathieu@2230
  1627
  baseB = CreateObject<BaseB> ();
mathieu@2258
  1628
  baseA->AggregateObject (baseB);
mathieu@701
  1629
  baseA = 0;
mathieu@2257
  1630
  baseA = baseB->GetObject<BaseA> ();
mathieu@699
  1631
mathieu@2230
  1632
  baseA = CreateObject<BaseA> ();
mathieu@1351
  1633
  baseA->TraceConnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
mathieu@1351
  1634
  m_baseATrace = false;
mathieu@1351
  1635
  baseA->BaseGenerateTrace (1);
mathieu@1351
  1636
  NS_TEST_ASSERT (m_baseATrace);
mathieu@1351
  1637
  baseA->TraceDisconnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
mathieu@1351
  1638
mathieu@2230
  1639
  baseB = CreateObject<BaseB> ();
mathieu@1351
  1640
  baseB->TraceConnect ("/baseb-x",  MakeCallback (&ObjectTest::BaseBTrace, this));
mathieu@1351
  1641
  m_baseBTrace = false;
mathieu@1351
  1642
  baseB->BaseGenerateTrace (2);
mathieu@1351
  1643
  NS_TEST_ASSERT (m_baseBTrace);
mathieu@1351
  1644
  baseB->TraceDisconnect ("/baseb-x",  MakeCallback (&ObjectTest::BaseBTrace, this));
mathieu@1351
  1645
mathieu@2258
  1646
  baseA->AggregateObject (baseB);
mathieu@1351
  1647
mathieu@1351
  1648
  baseA->TraceConnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
mathieu@1351
  1649
  m_baseATrace = false;
mathieu@1351
  1650
  baseA->BaseGenerateTrace (3);
mathieu@1351
  1651
  NS_TEST_ASSERT (m_baseATrace);
mathieu@1351
  1652
  baseA->TraceDisconnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
mathieu@1351
  1653
mathieu@1351
  1654
  baseA->TraceConnect ("/$BaseB/baseb-x",  MakeCallback (&ObjectTest::BaseBTrace, this));
mathieu@1351
  1655
  m_baseBTrace = false;
mathieu@1351
  1656
  baseB->BaseGenerateTrace (4);
mathieu@1351
  1657
  NS_TEST_ASSERT (m_baseBTrace);
mathieu@1351
  1658
  baseA->TraceDisconnect ("/$BaseB/baseb-x",  MakeCallback (&ObjectTest::BaseBTrace, this));
mathieu@1351
  1659
  m_baseBTrace = false;
mathieu@1351
  1660
  baseB->BaseGenerateTrace (5);
mathieu@1351
  1661
  NS_TEST_ASSERT (!m_baseBTrace);
mathieu@1351
  1662
mathieu@1351
  1663
  baseB->TraceConnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
mathieu@1351
  1664
  m_baseATrace = false;
mathieu@1351
  1665
  baseA->BaseGenerateTrace (6);
mathieu@1351
  1666
  NS_TEST_ASSERT (m_baseATrace);
mathieu@1351
  1667
  baseB->TraceDisconnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
mathieu@1351
  1668
mathieu@1351
  1669
  baseA->TraceConnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
mathieu@1351
  1670
  m_baseATrace = false;
mathieu@1351
  1671
  baseA->BaseGenerateTrace (7);
mathieu@1351
  1672
  NS_TEST_ASSERT (m_baseATrace);
mathieu@1351
  1673
  baseA->TraceDisconnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
mathieu@1351
  1674
mathieu@1357
  1675
  Ptr<DerivedA> derivedA;
mathieu@2372
  1676
  derivedA = CreateObject<DerivedA> ();
mathieu@2230
  1677
  baseB = CreateObject<BaseB> ();
mathieu@2258
  1678
  derivedA->AggregateObject (baseB);
mathieu@1357
  1679
  baseB->TraceConnect ("/$DerivedA/deriveda-x", MakeCallback (&ObjectTest::DerivedATrace, this));
mathieu@1357
  1680
  baseB->TraceConnect ("/$DerivedA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
mathieu@1357
  1681
  m_derivedATrace = false;
mathieu@1357
  1682
  m_baseATrace = false;
mathieu@1357
  1683
  derivedA->DerivedGenerateTrace (8);
mathieu@1357
  1684
  derivedA->BaseGenerateTrace (9);
mathieu@1357
  1685
  NS_TEST_ASSERT (m_derivedATrace);
mathieu@1357
  1686
  NS_TEST_ASSERT (m_baseATrace);
mathieu@1357
  1687
  baseB->TraceDisconnect ("/$DerivedA/deriveda-x", MakeCallback (&ObjectTest::BaseATrace, this));
mathieu@1357
  1688
  baseB->TraceDisconnect ("/$DerivedA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
mathieu@1357
  1689
mathieu@1357
  1690
  baseB->TraceConnect ("/$DerivedA/*", MakeCallback (&ObjectTest::DerivedATrace, this));
mathieu@1357
  1691
  m_derivedATrace = false;
mathieu@1357
  1692
  derivedA->DerivedGenerateTrace (10);
mathieu@1357
  1693
  NS_TEST_ASSERT (m_derivedATrace);
mathieu@1357
  1694
  // here, we have connected the derived trace sink to all 
mathieu@1357
  1695
  // trace sources, including the base trace source.
mathieu@1357
  1696
  m_derivedATrace = false;
mathieu@1357
  1697
  derivedA->BaseGenerateTrace (11);
mathieu@1357
  1698
  NS_TEST_ASSERT (m_derivedATrace);
mathieu@1357
  1699
  baseB->TraceDisconnect ("/$DerivedA/*", MakeCallback (&ObjectTest::BaseATrace, this));
mathieu@1351
  1700
mathieu@2250
  1701
  // Test the object creation code of TypeId
mathieu@2251
  1702
  Ptr<Object> a = BaseA::GetTypeId ().CreateObject ();
mathieu@2257
  1703
  NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (), a);
mathieu@2257
  1704
  NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (DerivedA::GetTypeId ()), 0);
mathieu@2257
  1705
  NS_TEST_ASSERT_EQUAL (a->GetObject<DerivedA> (), 0);
mathieu@2372
  1706
  a = DerivedA::GetTypeId ().CreateObject ();
mathieu@2257
  1707
  NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (), a);
mathieu@2257
  1708
  NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (DerivedA::GetTypeId ()), a);
mathieu@2257
  1709
  NS_TEST_ASSERT_UNEQUAL (a->GetObject<DerivedA> (), 0);
mathieu@2237
  1710
mathieu@2237
  1711
mathieu@1349
  1712
  return result;
mathieu@699
  1713
}
mathieu@699
  1714
mathieu@706
  1715
static ObjectTest g_interfaceObjectTests;
mathieu@699
  1716
mathieu@699
  1717
mathieu@699
  1718
} // namespace ns3
mathieu@699
  1719
mathieu@699
  1720
#endif /* RUN_SELF_TESTS */
mathieu@699
  1721
mathieu@699
  1722