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