src/core/attribute-list.cc
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sat, 04 Jul 2009 08:15:48 +0200
changeset 4654 2eaebe77d66b
parent 4252 c82988c68a35
permissions -rw-r--r--
Added tag ns-3.5 for changeset c975274c9707
mathieu@2671
     1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
mathieu@2671
     2
/*
mathieu@2671
     3
 * Copyright (c) 2008 INRIA
mathieu@2671
     4
 *
mathieu@2671
     5
 * This program is free software; you can redistribute it and/or modify
mathieu@2671
     6
 * it under the terms of the GNU General Public License version 2 as
mathieu@2671
     7
 * published by the Free Software Foundation;
mathieu@2671
     8
 *
mathieu@2671
     9
 * This program is distributed in the hope that it will be useful,
mathieu@2671
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
mathieu@2671
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mathieu@2671
    12
 * GNU General Public License for more details.
mathieu@2671
    13
 *
mathieu@2671
    14
 * You should have received a copy of the GNU General Public License
mathieu@2671
    15
 * along with this program; if not, write to the Free Software
mathieu@2671
    16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
mathieu@2671
    17
 *
mathieu@2671
    18
 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
mathieu@2671
    19
 */
mathieu@2633
    20
#include "attribute-list.h"
mathieu@2633
    21
#include "string.h"
mathieu@2633
    22
#include "singleton.h"
mathieu@2633
    23
mathieu@2633
    24
namespace ns3 {
mathieu@2633
    25
mathieu@2633
    26
/*********************************************************************
mathieu@2633
    27
 *         The AttributeList container implementation
mathieu@2633
    28
 *********************************************************************/
mathieu@2633
    29
mathieu@2633
    30
AttributeList::AttributeList ()
mathieu@2633
    31
{}
mathieu@2633
    32
mathieu@2633
    33
AttributeList::AttributeList (const AttributeList &o)
mathieu@2633
    34
{
mathieu@2633
    35
  for (Attrs::const_iterator i = o.m_attributes.begin (); i != o.m_attributes.end (); i++)
mathieu@2633
    36
    {
mathieu@2633
    37
      struct Attr attr;
mathieu@2633
    38
      attr.checker = i->checker;
mathieu@2965
    39
      attr.value = i->value->Copy ();
mathieu@2633
    40
      m_attributes.push_back (attr);
mathieu@2633
    41
    }
mathieu@2633
    42
}
mathieu@2633
    43
AttributeList &
mathieu@2633
    44
AttributeList::operator = (const AttributeList &o)
mathieu@2633
    45
{
mathieu@2633
    46
  Reset ();
mathieu@2633
    47
  for (Attrs::const_iterator i = o.m_attributes.begin (); i != o.m_attributes.end (); i++)
mathieu@2633
    48
    {
mathieu@2633
    49
      struct Attr attr;
mathieu@2633
    50
      attr.checker = i->checker;
mathieu@2965
    51
      attr.value = i->value->Copy ();
mathieu@2633
    52
      m_attributes.push_back (attr);
mathieu@2633
    53
    }
mathieu@2633
    54
  return *this;
mathieu@2633
    55
}
mathieu@2633
    56
AttributeList::~AttributeList ()
mathieu@2633
    57
{
mathieu@2633
    58
  Reset ();
mathieu@2633
    59
}
mathieu@2633
    60
mathieu@2633
    61
void
mathieu@2965
    62
AttributeList::Set (std::string name, const AttributeValue &value)
mathieu@2633
    63
{
mathieu@2633
    64
  struct TypeId::AttributeInfo info;
mathieu@2633
    65
  bool ok = TypeId::LookupAttributeByFullName (name, &info);
mathieu@2633
    66
  if (!ok)
mathieu@2633
    67
    {
mathieu@2633
    68
      NS_FATAL_ERROR ("Could not find attribute "<<name);
mathieu@2633
    69
    }
mathieu@2633
    70
  ok = DoSet (&info, value);
mathieu@2633
    71
  if (!ok)
mathieu@2633
    72
    {
mathieu@2633
    73
      NS_FATAL_ERROR ("Could not set value for attribute "<<name);
mathieu@2633
    74
    }
mathieu@2633
    75
}
mathieu@2633
    76
bool 
mathieu@2965
    77
AttributeList::SetFailSafe (std::string name, const AttributeValue &value)
mathieu@2633
    78
{
mathieu@2633
    79
  struct TypeId::AttributeInfo info;
mathieu@2633
    80
  bool ok = TypeId::LookupAttributeByFullName (name, &info);
mathieu@2633
    81
  if (!ok)
mathieu@2633
    82
    {
mathieu@2633
    83
      return false;
mathieu@2633
    84
    }
mathieu@2633
    85
  ok = DoSet (&info, value);
mathieu@2633
    86
  return ok;
mathieu@2633
    87
}
mathieu@2633
    88
void
mathieu@2965
    89
AttributeList::SetWithTid (TypeId tid, std::string name, const AttributeValue & value)
mathieu@2633
    90
{
mathieu@2633
    91
  struct TypeId::AttributeInfo info;
mathieu@2633
    92
  bool ok = tid.LookupAttributeByName (name, &info);
mathieu@2633
    93
  if (!ok)
mathieu@2633
    94
    {
mathieu@2633
    95
      NS_FATAL_ERROR ("Could not find attribute "<<tid.GetName ()<<"::"<<name);
mathieu@2633
    96
    }
mathieu@2633
    97
  ok = DoSet (&info, value);
mathieu@2633
    98
  if (!ok)
mathieu@2633
    99
    {
mathieu@2633
   100
      NS_FATAL_ERROR ("Could not set value for attribute "<<tid.GetName ()<<"::"<<name);
mathieu@2633
   101
    }
mathieu@2633
   102
}
mathieu@2633
   103
mathieu@2633
   104
void
mathieu@2965
   105
AttributeList::DoSetOne (Ptr<const AttributeChecker> checker, const AttributeValue &value)
mathieu@2633
   106
{
mathieu@2633
   107
  // get rid of any previous value stored in this
mathieu@2633
   108
  // vector of values.
mathieu@2633
   109
  for (Attrs::iterator k = m_attributes.begin (); k != m_attributes.end (); k++)
mathieu@2633
   110
    {
mathieu@2633
   111
      if (k->checker == checker)
mathieu@2633
   112
        {
mathieu@2633
   113
          m_attributes.erase (k);
mathieu@2633
   114
          break;
mathieu@2633
   115
        }
mathieu@2633
   116
    }
mathieu@2633
   117
  // store the new value.
mathieu@2633
   118
  struct Attr attr;
mathieu@2633
   119
  attr.checker = checker;
mathieu@2633
   120
  attr.value = value.Copy ();
mathieu@2633
   121
  m_attributes.push_back (attr);
mathieu@2633
   122
}
mathieu@2633
   123
bool
mathieu@2965
   124
AttributeList::DoSet (struct TypeId::AttributeInfo *info, const AttributeValue &value)
mathieu@2633
   125
{
mathieu@2633
   126
  if (info->checker == 0)
mathieu@2633
   127
    {
mathieu@2633
   128
      return false;
mathieu@2633
   129
    }
mathieu@2633
   130
  bool ok = info->checker->Check (value);
mathieu@2965
   131
  if (ok)
mathieu@2965
   132
    {
mathieu@2965
   133
      DoSetOne (info->checker, value);
mathieu@2965
   134
      return true;
mathieu@2965
   135
    }
mathieu@2965
   136
mathieu@2965
   137
  // attempt to convert to string.
mathieu@2965
   138
  const StringValue *str = dynamic_cast<const StringValue *> (&value);
mathieu@2965
   139
  if (str == 0)
mathieu@2965
   140
    {
mathieu@2965
   141
      return false;
mathieu@2965
   142
    }
mathieu@2965
   143
  // attempt to convert back to value.
mathieu@2965
   144
  Ptr<AttributeValue> v = info->checker->Create ();
mathieu@2965
   145
  ok = v->DeserializeFromString (str->Get (), info->checker);
mathieu@2633
   146
  if (!ok)
mathieu@2633
   147
    {
mathieu@2965
   148
      return false;
mathieu@2633
   149
    }
mathieu@2965
   150
  ok = info->checker->Check (*v);
mathieu@2965
   151
  if (!ok)
mathieu@2965
   152
    {
mathieu@2965
   153
      return false;
mathieu@2965
   154
    }
mathieu@2965
   155
  DoSetOne (info->checker, *v);
mathieu@2633
   156
  return true;
mathieu@2633
   157
}
mathieu@2633
   158
void 
mathieu@2633
   159
AttributeList::Reset (void)
mathieu@2633
   160
{
mathieu@2633
   161
  m_attributes.clear ();
mathieu@2633
   162
}
mathieu@2633
   163
AttributeList *
mathieu@2633
   164
AttributeList::GetGlobal (void)
mathieu@2633
   165
{
mathieu@2633
   166
  return Singleton<AttributeList>::Get ();
mathieu@2633
   167
}
mathieu@2633
   168
mathieu@2633
   169
std::string
mathieu@2633
   170
AttributeList::LookupAttributeFullNameByChecker (Ptr<const AttributeChecker> checker) const
mathieu@2633
   171
{
mathieu@2633
   172
  for (uint32_t i = 0; i < TypeId::GetRegisteredN (); i++)
mathieu@2633
   173
    {
mathieu@2633
   174
      TypeId tid = TypeId::GetRegistered (i);
mathieu@2693
   175
      for (uint32_t j = 0; j < tid.GetAttributeN (); j++)
mathieu@2633
   176
        {
mathieu@2633
   177
          if (checker == tid.GetAttributeChecker (j))
mathieu@2633
   178
            {
mathieu@2633
   179
              return tid.GetAttributeFullName (j);
mathieu@2633
   180
            }
mathieu@2633
   181
        }
mathieu@2633
   182
    }
mathieu@2633
   183
  NS_FATAL_ERROR ("Could not find requested Accessor.");
mathieu@2633
   184
  // quiet compiler.
mathieu@2633
   185
  return "";
mathieu@2633
   186
}
mathieu@2633
   187
mathieu@2633
   188
std::string 
mathieu@2633
   189
AttributeList::SerializeToString (void) const
mathieu@2633
   190
{
mathieu@2633
   191
  std::ostringstream oss;
mathieu@2957
   192
  for (Attrs::const_iterator i = m_attributes.begin (); i != m_attributes.end ();)
mathieu@2633
   193
    {
mathieu@2633
   194
      std::string name = LookupAttributeFullNameByChecker (i->checker);
mathieu@2965
   195
      oss << name << "=" << i->value->SerializeToString (i->checker);
mathieu@2957
   196
      i++;
mathieu@2633
   197
      if (i != m_attributes.end ())
mathieu@2633
   198
        {
mathieu@2633
   199
          oss << "|";
mathieu@2633
   200
        }
mathieu@2633
   201
    }  
mathieu@2633
   202
  return oss.str ();
mathieu@2633
   203
}
mathieu@2633
   204
bool 
mathieu@2633
   205
AttributeList::DeserializeFromString (std::string str)
mathieu@2633
   206
{
mathieu@2633
   207
  Reset ();
mathieu@2633
   208
mathieu@2633
   209
  std::string::size_type cur;
mathieu@2633
   210
  cur = 0;
mathieu@4252
   211
  while (cur != str.size ())
mathieu@4252
   212
    {
mathieu@4252
   213
      std::string::size_type equal = str.find ("=", cur);
mathieu@4252
   214
      if (equal == std::string::npos)
mathieu@4252
   215
        {
mathieu@4252
   216
          NS_FATAL_ERROR ("Error while parsing serialized attribute: \"" << str << "\"");
mathieu@4252
   217
          break;
mathieu@4252
   218
        }
mathieu@4252
   219
      else
mathieu@4252
   220
        {
mathieu@4252
   221
          std::string name = str.substr (cur, equal-cur);
mathieu@4252
   222
          struct TypeId::AttributeInfo info;
mathieu@4252
   223
          if (!TypeId::LookupAttributeByFullName (name, &info))
mathieu@4252
   224
            {
mathieu@4252
   225
              NS_FATAL_ERROR ("Error while parsing serialized attribute: name does not exist: \"" << name << "\"");
mathieu@4252
   226
              break;
mathieu@4252
   227
            }
mathieu@4252
   228
          else
mathieu@4252
   229
            {
mathieu@4252
   230
              std::string::size_type next = str.find ("|", cur);
mathieu@4252
   231
              std::string value;
mathieu@4252
   232
              if (next == std::string::npos)
mathieu@4252
   233
                {
mathieu@4252
   234
                  value = str.substr (equal+1, str.size () - (equal+1));
mathieu@4252
   235
                  cur = str.size ();
mathieu@4252
   236
                }
mathieu@4252
   237
              else
mathieu@4252
   238
                {
mathieu@4252
   239
                  value = str.substr (equal+1, next - (equal+1));
keith@4600
   240
                  cur = next + 1;
mathieu@4252
   241
                }
mathieu@4252
   242
              Ptr<AttributeValue> val = info.checker->Create ();
mathieu@4252
   243
              bool ok = val->DeserializeFromString (value, info.checker);
mathieu@4252
   244
              if (!ok)
mathieu@4252
   245
                {
mathieu@4252
   246
                  NS_FATAL_ERROR ("Error while parsing serialized attribute: value invalid: \"" << value << "\"");
mathieu@4252
   247
                  break;
mathieu@4252
   248
                }
mathieu@4252
   249
              else
mathieu@4252
   250
                {
mathieu@4252
   251
                  DoSetOne (info.checker, *val);
mathieu@4252
   252
                }
mathieu@4252
   253
            }
mathieu@4252
   254
        }
mathieu@4252
   255
    }
mathieu@2633
   256
mathieu@2633
   257
  return true;
mathieu@2633
   258
}
mathieu@2633
   259
mathieu@3892
   260
UnsafeAttributeList::UnsafeAttributeList ()
mathieu@3892
   261
{}
mathieu@3892
   262
UnsafeAttributeList::UnsafeAttributeList (const UnsafeAttributeList &o)
mathieu@3892
   263
{
mathieu@3892
   264
  for (uint32_t i = 0; i < o.m_attributes.size (); ++i)
mathieu@3892
   265
    {
mathieu@3892
   266
      Set (o.m_attributes[i].first, *(o.m_attributes[i].second));
mathieu@3892
   267
    }
mathieu@3892
   268
}
mathieu@3892
   269
UnsafeAttributeList &
mathieu@3892
   270
UnsafeAttributeList::operator = (const UnsafeAttributeList &o)
mathieu@3892
   271
{
mathieu@3892
   272
  m_attributes.clear ();
mathieu@3892
   273
  for (uint32_t i = 0; i < o.m_attributes.size (); ++i)
mathieu@3892
   274
    {
mathieu@3892
   275
      Set (o.m_attributes[i].first, *(o.m_attributes[i].second));
mathieu@3892
   276
    }
mathieu@3892
   277
  return *this;
mathieu@3892
   278
}
mathieu@3892
   279
mathieu@3892
   280
UnsafeAttributeList::~UnsafeAttributeList ()
mathieu@3892
   281
{
mathieu@3892
   282
  m_attributes.clear ();
mathieu@3892
   283
}
mathieu@3892
   284
void 
mathieu@3892
   285
UnsafeAttributeList::Set (std::string name, const AttributeValue &param)
mathieu@3892
   286
{
mathieu@3892
   287
  if (name == "")
mathieu@3892
   288
    {
mathieu@3892
   289
      return;
mathieu@3892
   290
    }
mathieu@3892
   291
  for (uint32_t i = 0; i < m_attributes.size (); ++i)
mathieu@3892
   292
    {
mathieu@3892
   293
      if (m_attributes[i].first == name)
mathieu@3892
   294
        {
mathieu@3892
   295
          m_attributes[i].second = param.Copy ();
mathieu@3892
   296
          return;
mathieu@3892
   297
        }
mathieu@3892
   298
    }
mathieu@3892
   299
  m_attributes.push_back (std::make_pair (name, param.Copy ()));
mathieu@3892
   300
}
mathieu@3892
   301
mathieu@3892
   302
AttributeList 
mathieu@3892
   303
UnsafeAttributeList::GetSafe (std::string tidName) const
mathieu@3892
   304
{
mathieu@3892
   305
  AttributeList list;
mathieu@3892
   306
  for (uint32_t i = 0; i < m_attributes.size (); ++i)
mathieu@3892
   307
    {
mathieu@3892
   308
      TypeId tid = TypeId::LookupByName (tidName);
mathieu@3892
   309
      list.SetWithTid (tid, m_attributes[i].first, *m_attributes[i].second);
mathieu@3892
   310
    }
mathieu@3892
   311
  return list;
mathieu@3892
   312
}
mathieu@3892
   313
mathieu@3892
   314
mathieu@2633
   315
} // namespace ns3