src/core/object-base.cc
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sat, 04 Jul 2009 08:15:48 +0200
changeset 4654 2eaebe77d66b
parent 2965 4b28e9740e3b
permissions -rw-r--r--
Added tag ns-3.5 for changeset c975274c9707
mathieu@2718
     1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
mathieu@2718
     2
/*
mathieu@2718
     3
 * Copyright (c) 2008 INRIA
mathieu@2718
     4
 *
mathieu@2718
     5
 * This program is free software; you can redistribute it and/or modify
mathieu@2718
     6
 * it under the terms of the GNU General Public License version 2 as
mathieu@2718
     7
 * published by the Free Software Foundation;
mathieu@2718
     8
 *
mathieu@2718
     9
 * This program is distributed in the hope that it will be useful,
mathieu@2718
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
mathieu@2718
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mathieu@2718
    12
 * GNU General Public License for more details.
mathieu@2718
    13
 *
mathieu@2718
    14
 * You should have received a copy of the GNU General Public License
mathieu@2718
    15
 * along with this program; if not, write to the Free Software
mathieu@2718
    16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
mathieu@2718
    17
 *
mathieu@2718
    18
 * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
mathieu@2718
    19
 */
mathieu@2370
    20
#include "object-base.h"
mathieu@2637
    21
#include "log.h"
mathieu@2637
    22
#include "trace-source-accessor.h"
mathieu@2965
    23
#include "attribute-list.h"
mathieu@2637
    24
#include "string.h"
mathieu@4216
    25
#include "ns3/core-config.h"
mathieu@4216
    26
#ifdef HAVE_STDLIB_H
mathieu@4216
    27
#include <stdlib.h>
mathieu@4216
    28
#endif
mathieu@2370
    29
mathieu@2637
    30
NS_LOG_COMPONENT_DEFINE ("ObjectBase");
mathieu@2637
    31
mathieu@2637
    32
namespace ns3 {
mathieu@2637
    33
mathieu@2637
    34
static TypeId
mathieu@2637
    35
GetObjectIid (void)
mathieu@2637
    36
{
mathieu@2637
    37
  TypeId tid = TypeId ("ns3::ObjectBase");
mathieu@2637
    38
  tid.SetParent (tid);
mathieu@2637
    39
  return tid;
mathieu@2637
    40
}
mathieu@2637
    41
mathieu@2637
    42
TypeId 
mathieu@2637
    43
ObjectBase::GetTypeId (void)
mathieu@2637
    44
{
mathieu@2637
    45
  static TypeId tid = GetObjectIid ();
mathieu@2637
    46
  return tid;
mathieu@2637
    47
}
mathieu@2637
    48
mathieu@2637
    49
ObjectBase::~ObjectBase () 
mathieu@2637
    50
{}
mathieu@2637
    51
mathieu@2637
    52
void
mathieu@2637
    53
ObjectBase::NotifyConstructionCompleted (void)
mathieu@2637
    54
{}
mathieu@2637
    55
mathieu@2637
    56
void
mathieu@2637
    57
ObjectBase::ConstructSelf (const AttributeList &attributes)
mathieu@2637
    58
{
mathieu@2637
    59
  // loop over the inheritance tree back to the Object base class.
mathieu@2637
    60
  TypeId tid = GetInstanceTypeId ();
mathieu@2637
    61
  do {
mathieu@2637
    62
    // loop over all attributes in object type
mathieu@2693
    63
    NS_LOG_DEBUG ("construct tid="<<tid.GetName ()<<", params="<<tid.GetAttributeN ());
mathieu@2693
    64
    for (uint32_t i = 0; i < tid.GetAttributeN (); i++)
mathieu@2637
    65
      {
mathieu@2965
    66
        Ptr<const AttributeAccessor> accessor = tid.GetAttributeAccessor (i);
mathieu@2965
    67
        Ptr<const AttributeValue> initial = tid.GetAttributeInitialValue (i);
mathieu@2637
    68
        Ptr<const AttributeChecker> checker = tid.GetAttributeChecker (i);
mathieu@2637
    69
        NS_LOG_DEBUG ("try to construct \""<< tid.GetName ()<<"::"<<
mathieu@2637
    70
                      tid.GetAttributeName (i)<<"\"");
mathieu@2637
    71
        if (!(tid.GetAttributeFlags (i) & TypeId::ATTR_CONSTRUCT))
mathieu@2637
    72
          {
mathieu@2637
    73
            continue;
mathieu@2637
    74
          }
mathieu@2637
    75
        bool found = false;
mathieu@2637
    76
        // is this attribute stored in this AttributeList instance ?
mathieu@2637
    77
        for (AttributeList::Attrs::const_iterator j = attributes.m_attributes.begin ();
mathieu@2637
    78
             j != attributes.m_attributes.end (); j++)
mathieu@2637
    79
          {
mathieu@2637
    80
            if (j->checker == checker)
mathieu@2637
    81
              {
mathieu@2637
    82
                // We have a matching attribute value.
mathieu@4216
    83
                if (DoSet (accessor, checker, *j->value))
mathieu@2637
    84
                  {
mathieu@2637
    85
                    NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
mathieu@4216
    86
                                  tid.GetAttributeName (i)<<"\"");
mathieu@2637
    87
                    found = true;
mathieu@2637
    88
                    break;
mathieu@2637
    89
                  }
mathieu@2637
    90
              }
mathieu@2637
    91
          }
mathieu@2637
    92
        if (!found)
mathieu@2637
    93
          {
mathieu@4216
    94
            // is this attribute stored in the global instance ?
mathieu@4216
    95
            for (AttributeList::Attrs::const_iterator j = AttributeList::GetGlobal ()->m_attributes.begin ();
mathieu@4216
    96
                 j != AttributeList::GetGlobal ()->m_attributes.end (); j++)
mathieu@4216
    97
              {
mathieu@4216
    98
                if (j->checker == checker)
mathieu@4216
    99
                  {
mathieu@4216
   100
                    // We have a matching attribute value.
mathieu@4216
   101
                    if (DoSet (accessor, checker, *j->value))
mathieu@4216
   102
                      {
mathieu@4216
   103
                        NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
mathieu@4216
   104
                                      tid.GetAttributeName (i)<<"\" from global");
mathieu@4216
   105
                        found = true;
mathieu@4216
   106
                        break;
mathieu@4216
   107
                      }
mathieu@4216
   108
                  }
mathieu@4216
   109
              }
mathieu@4216
   110
          }
mathieu@4216
   111
        if (!found)
mathieu@4216
   112
          {
mathieu@4216
   113
            // No matching attribute value so we try to look at the env var.
mathieu@4216
   114
#ifdef HAVE_GETENV
mathieu@4216
   115
            char *envVar = getenv ("NS_ATTRIBUTE_DEFAULT");
mathieu@4216
   116
            if (envVar != 0)
mathieu@4216
   117
              {
mathieu@4216
   118
                std::string env = std::string (envVar);
mathieu@4216
   119
                std::string::size_type cur = 0;
mathieu@4216
   120
                std::string::size_type next = 0;
mathieu@4216
   121
                while (next != std::string::npos)
mathieu@4216
   122
                  {
mathieu@4216
   123
                    next = env.find (";", cur);
mathieu@4216
   124
                    std::string tmp = std::string (env, cur, next-cur);
mathieu@4216
   125
                    std::string::size_type equal = tmp.find ("=");
mathieu@4216
   126
                    if (equal != std::string::npos)
mathieu@4216
   127
                      {
mathieu@4216
   128
                        std::string name = tmp.substr (0, equal);
mathieu@4216
   129
                        std::string value = tmp.substr (equal+1, tmp.size () - equal - 1);
mathieu@4216
   130
                        if (name == tid.GetAttributeFullName (i))
mathieu@4216
   131
                          {
mathieu@4216
   132
                            if (DoSet (accessor, checker, StringValue (value)))
mathieu@4216
   133
                              {
mathieu@4216
   134
                                NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
mathieu@4216
   135
                                              tid.GetAttributeName (i)<<"\" from env var");
mathieu@4216
   136
                                found = true;
mathieu@4216
   137
                                break;
mathieu@4216
   138
                              }
mathieu@4216
   139
                          }
mathieu@4216
   140
                      }
mathieu@4216
   141
                    cur = next + 1;
mathieu@4216
   142
                  }
mathieu@4216
   143
              }
mathieu@4216
   144
#endif /* HAVE_GETENV */
mathieu@4216
   145
          }
mathieu@4216
   146
        if (!found)
mathieu@4216
   147
          {
mathieu@4216
   148
            // No matching attribute value so we try to set the default value.
mathieu@2965
   149
            DoSet (accessor, checker, *initial);
mathieu@2637
   150
            NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
mathieu@2637
   151
                          tid.GetAttributeName (i)<<"\" from initial value.");
mathieu@2637
   152
          }
mathieu@2637
   153
      }
mathieu@2637
   154
    tid = tid.GetParent ();
mathieu@2637
   155
  } while (tid != ObjectBase::GetTypeId ());
mathieu@2637
   156
  NotifyConstructionCompleted ();
mathieu@2637
   157
}
mathieu@2637
   158
mathieu@2637
   159
bool
mathieu@2965
   160
ObjectBase::DoSet (Ptr<const AttributeAccessor> spec, 
mathieu@2965
   161
		   Ptr<const AttributeChecker> checker, 
mathieu@2965
   162
                   const AttributeValue &value)
mathieu@2637
   163
{
mathieu@2637
   164
  bool ok = checker->Check (value);
mathieu@2965
   165
  if (ok)
mathieu@2965
   166
    {
mathieu@2965
   167
      ok = spec->Set (this, value);
mathieu@2965
   168
      return ok;
mathieu@2965
   169
    }
mathieu@2965
   170
  // attempt to convert to string
mathieu@2965
   171
  const StringValue *str = dynamic_cast<const StringValue *> (&value);
mathieu@2965
   172
  if (str == 0)
mathieu@2965
   173
    {
mathieu@2965
   174
      return false;
mathieu@2965
   175
    }
mathieu@2965
   176
  // attempt to convert back from string.
mathieu@2965
   177
  Ptr<AttributeValue> v = checker->Create ();
mathieu@2965
   178
  ok = v->DeserializeFromString (str->Get (), checker);
mathieu@2637
   179
  if (!ok)
mathieu@2637
   180
    {
mathieu@2965
   181
      return false;
mathieu@2637
   182
    }
mathieu@2965
   183
  ok = checker->Check (*v);
mathieu@2965
   184
  if (!ok)
mathieu@2965
   185
    {
mathieu@2965
   186
      return false;
mathieu@2965
   187
    }
mathieu@2965
   188
  ok = spec->Set (this, *v);
mathieu@2637
   189
  return ok;
mathieu@2637
   190
}
mathieu@2637
   191
void
mathieu@2965
   192
ObjectBase::SetAttribute (std::string name, const AttributeValue &value)
mathieu@2637
   193
{
mathieu@2637
   194
  struct TypeId::AttributeInfo info;
mathieu@2637
   195
  TypeId tid = GetInstanceTypeId ();
mathieu@2637
   196
  if (!tid.LookupAttributeByName (name, &info))
mathieu@2637
   197
    {
mathieu@2637
   198
      NS_FATAL_ERROR ("Attribute name="<<name<<" does not exist for this object: tid="<<tid.GetName ());
mathieu@2637
   199
    }
mathieu@2965
   200
  if (!(info.flags & TypeId::ATTR_SET) ||
mathieu@2965
   201
      !info.accessor->HasSetter ())
mathieu@2637
   202
    {
mathieu@2637
   203
      NS_FATAL_ERROR ("Attribute name="<<name<<" is not settable for this object: tid="<<tid.GetName ());
mathieu@2637
   204
    }
mathieu@2965
   205
  if (!DoSet (info.accessor, info.checker, value))
mathieu@2637
   206
    {
mathieu@2637
   207
      NS_FATAL_ERROR ("Attribute name="<<name<<" could not be set for this object: tid="<<tid.GetName ());
mathieu@2637
   208
    }
mathieu@2637
   209
}
mathieu@2637
   210
bool 
mathieu@2965
   211
ObjectBase::SetAttributeFailSafe (std::string name, const AttributeValue &value)
mathieu@2637
   212
{
mathieu@2637
   213
  struct TypeId::AttributeInfo info;
mathieu@2637
   214
  TypeId tid = GetInstanceTypeId ();
mathieu@2637
   215
  if (!tid.LookupAttributeByName (name, &info))
mathieu@2637
   216
    {
mathieu@2637
   217
      return false;
mathieu@2637
   218
    }
mathieu@2965
   219
  if (!(info.flags & TypeId::ATTR_SET) ||
mathieu@2965
   220
      !info.accessor->HasSetter ())
mathieu@2637
   221
    {
mathieu@2637
   222
      return false;
mathieu@2637
   223
    }
mathieu@2965
   224
  return DoSet (info.accessor, info.checker, value);
mathieu@2637
   225
}
mathieu@2965
   226
mathieu@2965
   227
void
mathieu@2965
   228
ObjectBase::GetAttribute (std::string name, AttributeValue &value) const
mathieu@2637
   229
{
mathieu@2637
   230
  struct TypeId::AttributeInfo info;
mathieu@2637
   231
  TypeId tid = GetInstanceTypeId ();
mathieu@2637
   232
  if (!tid.LookupAttributeByName (name, &info))
mathieu@2637
   233
    {
mathieu@2716
   234
      NS_FATAL_ERROR ("Attribute name="<<name<<" does not exist for this object: tid="<<tid.GetName ());
mathieu@2637
   235
    }
mathieu@2965
   236
  if (!(info.flags & TypeId::ATTR_GET) || 
mathieu@2965
   237
      !info.accessor->HasGetter ())
mathieu@2637
   238
    {
mathieu@2716
   239
      NS_FATAL_ERROR ("Attribute name="<<name<<" is not gettable for this object: tid="<<tid.GetName ());
mathieu@2637
   240
    }
mathieu@2965
   241
  bool ok = info.accessor->Get (this, value);
mathieu@2965
   242
  if (ok)
mathieu@2965
   243
    {
mathieu@2965
   244
      return;
mathieu@2965
   245
    }
mathieu@2965
   246
  StringValue *str = dynamic_cast<StringValue *> (&value);
mathieu@2965
   247
  if (str == 0)
mathieu@2965
   248
    {
mathieu@2965
   249
      NS_FATAL_ERROR ("Attribute name="<<name<<" tid="<<tid.GetName () << ": input value is not a string");
mathieu@2965
   250
    }
mathieu@2965
   251
  Ptr<AttributeValue> v = info.checker->Create ();
mathieu@2965
   252
  ok = info.accessor->Get (this, *PeekPointer (v));
mathieu@2716
   253
  if (!ok)
mathieu@2637
   254
    {
mathieu@2965
   255
      NS_FATAL_ERROR ("Attribute name="<<name<<" tid="<<tid.GetName () << ": could not get value");
mathieu@2637
   256
    }
mathieu@2965
   257
  str->Set (v->SerializeToString (info.checker));
mathieu@2637
   258
}
mathieu@2637
   259
mathieu@2637
   260
mathieu@2716
   261
bool
mathieu@2965
   262
ObjectBase::GetAttributeFailSafe (std::string name, AttributeValue &value) const
mathieu@2716
   263
{
mathieu@2716
   264
  struct TypeId::AttributeInfo info;
mathieu@2716
   265
  TypeId tid = GetInstanceTypeId ();
mathieu@2716
   266
  if (!tid.LookupAttributeByName (name, &info))
mathieu@2716
   267
    {
mathieu@2716
   268
      return false;
mathieu@2716
   269
    }
mathieu@2965
   270
  if (!(info.flags & TypeId::ATTR_GET) ||
mathieu@2965
   271
      !info.accessor->HasGetter ())
mathieu@2716
   272
    {
mathieu@2716
   273
      return false;
mathieu@2716
   274
    }
mathieu@2965
   275
  bool ok = info.accessor->Get (this, value);
mathieu@2716
   276
  if (ok)
mathieu@2716
   277
    {
mathieu@2965
   278
      return true;
mathieu@2716
   279
    }
mathieu@2965
   280
  StringValue *str = dynamic_cast<StringValue *> (&value);
mathieu@2965
   281
  if (str == 0)
mathieu@2716
   282
    {
mathieu@2716
   283
      return false;
mathieu@2716
   284
    }
mathieu@2965
   285
  Ptr<AttributeValue> v = info.checker->Create ();
mathieu@2965
   286
  ok = info.accessor->Get (this, *PeekPointer (v));
mathieu@2965
   287
  if (!ok)
mathieu@2716
   288
    {
mathieu@2716
   289
      return false;
mathieu@2716
   290
    }
mathieu@2965
   291
  str->Set (v->SerializeToString (info.checker));
mathieu@2965
   292
  return true;
mathieu@2716
   293
}
mathieu@2716
   294
mathieu@2637
   295
bool 
mathieu@2637
   296
ObjectBase::TraceConnectWithoutContext (std::string name, const CallbackBase &cb)
mathieu@2637
   297
{
mathieu@2637
   298
  TypeId tid = GetInstanceTypeId ();
mathieu@2637
   299
  Ptr<const TraceSourceAccessor> accessor = tid.LookupTraceSourceByName (name);
mathieu@2637
   300
  if (accessor == 0)
mathieu@2637
   301
    {
mathieu@2637
   302
      return false;
mathieu@2637
   303
    }
mathieu@2637
   304
  bool ok = accessor->ConnectWithoutContext (this, cb);
mathieu@2637
   305
  return ok;
mathieu@2637
   306
}
mathieu@2637
   307
bool 
mathieu@2718
   308
ObjectBase::TraceConnect (std::string name, std::string context, const CallbackBase &cb)
mathieu@2637
   309
{
mathieu@2637
   310
  TypeId tid = GetInstanceTypeId ();
mathieu@2637
   311
  Ptr<const TraceSourceAccessor> accessor = tid.LookupTraceSourceByName (name);
mathieu@2637
   312
  if (accessor == 0)
mathieu@2637
   313
    {
mathieu@2637
   314
      return false;
mathieu@2637
   315
    }
mathieu@2637
   316
  bool ok = accessor->Connect (this, context, cb);
mathieu@2637
   317
  return ok;
mathieu@2637
   318
}
mathieu@2637
   319
bool 
mathieu@2637
   320
ObjectBase::TraceDisconnectWithoutContext (std::string name, const CallbackBase &cb)
mathieu@2637
   321
{
mathieu@2637
   322
  TypeId tid = GetInstanceTypeId ();
mathieu@2637
   323
  Ptr<const TraceSourceAccessor> accessor = tid.LookupTraceSourceByName (name);
mathieu@2637
   324
  if (accessor == 0)
mathieu@2637
   325
    {
mathieu@2637
   326
      return false;
mathieu@2637
   327
    }
mathieu@2637
   328
  bool ok = accessor->DisconnectWithoutContext (this, cb);
mathieu@2637
   329
  return ok;
mathieu@2637
   330
}
mathieu@2637
   331
bool 
mathieu@2718
   332
ObjectBase::TraceDisconnect (std::string name, std::string context, const CallbackBase &cb)
mathieu@2637
   333
{
mathieu@2637
   334
  TypeId tid = GetInstanceTypeId ();
mathieu@2637
   335
  Ptr<const TraceSourceAccessor> accessor = tid.LookupTraceSourceByName (name);
mathieu@2637
   336
  if (accessor == 0)
mathieu@2637
   337
    {
mathieu@2637
   338
      return false;
mathieu@2637
   339
    }
mathieu@2637
   340
  bool ok = accessor->Disconnect (this, context, cb);
mathieu@2637
   341
  return ok;
mathieu@2637
   342
}
mathieu@2637
   343
mathieu@2637
   344
mathieu@2637
   345
mathieu@2637
   346
} // namespace ns3