src/core/global-value.cc
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sat, 04 Jul 2009 08:15:48 +0200
changeset 4654 2eaebe77d66b
parent 4214 49039ae7bc3d
permissions -rw-r--r--
Added tag ns-3.5 for changeset c975274c9707
mathieu@2581
     1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
mathieu@2581
     2
/*
mathieu@2581
     3
 * Copyright (c) 2008 INRIA
mathieu@2581
     4
 *
mathieu@2581
     5
 * This program is free software; you can redistribute it and/or modify
mathieu@2581
     6
 * it under the terms of the GNU General Public License version 2 as
mathieu@2581
     7
 * published by the Free Software Foundation;
mathieu@2581
     8
 *
mathieu@2581
     9
 * This program is distributed in the hope that it will be useful,
mathieu@2581
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
mathieu@2581
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mathieu@2581
    12
 * GNU General Public License for more details.
mathieu@2581
    13
 *
mathieu@2581
    14
 * You should have received a copy of the GNU General Public License
mathieu@2581
    15
 * along with this program; if not, write to the Free Software
mathieu@2581
    16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
mathieu@2581
    17
 *
mathieu@2581
    18
 * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
mathieu@2581
    19
 */
mathieu@2467
    20
#include "global-value.h"
mathieu@2429
    21
#include "fatal-error.h"
mathieu@2472
    22
#include "attribute.h"
mathieu@2576
    23
#include "string.h"
mathieu@4214
    24
#include "ns3/core-config.h"
mathieu@4214
    25
#ifdef HAVE_STDLIB_H
mathieu@4214
    26
#include <stdlib.h>
mathieu@4214
    27
#endif
mathieu@2429
    28
mathieu@2429
    29
namespace ns3 {
mathieu@2429
    30
mathieu@2467
    31
GlobalValue::GlobalValue (std::string name, std::string help,
mathieu@2965
    32
			  const AttributeValue &initialValue,
mathieu@2472
    33
			  Ptr<const AttributeChecker> checker)
mathieu@2429
    34
  : m_name (name),
mathieu@2429
    35
    m_help (help),
mathieu@2965
    36
    m_initialValue (initialValue.Copy ()),
mathieu@2429
    37
    m_checker (checker)
mathieu@2429
    38
{
mathieu@2429
    39
  if (m_checker == 0)
mathieu@2429
    40
    {
mathieu@4213
    41
      NS_FATAL_ERROR ("Checker should not be zero.");
mathieu@2429
    42
    }
mathieu@2429
    43
  GetVector ()->push_back (this);
mathieu@4214
    44
  InitializeFromEnv ();
mathieu@4214
    45
}
mathieu@4214
    46
mathieu@4214
    47
void
mathieu@4214
    48
GlobalValue::InitializeFromEnv (void)
mathieu@4214
    49
{
mathieu@4214
    50
#ifdef HAVE_GETENV
mathieu@4214
    51
  char *envVar = getenv ("NS_GLOBAL_VALUE");
mathieu@4214
    52
  if (envVar == 0)
mathieu@4214
    53
    {
mathieu@4214
    54
      return;
mathieu@4214
    55
    }
mathieu@4214
    56
  std::string env = std::string (envVar);
mathieu@4214
    57
  std::string::size_type cur = 0;
mathieu@4214
    58
  std::string::size_type next = 0;
mathieu@4214
    59
  while (next != std::string::npos)
mathieu@4214
    60
    {
mathieu@4214
    61
      next = env.find (";", cur);
mathieu@4214
    62
      std::string tmp = std::string (env, cur, next-cur);
mathieu@4214
    63
      std::string::size_type equal = tmp.find ("=");
mathieu@4214
    64
      if (equal != std::string::npos)
mathieu@4214
    65
        {
mathieu@4214
    66
          std::string name = tmp.substr (0, equal);
mathieu@4214
    67
          std::string value = tmp.substr (equal+1, tmp.size () - equal - 1);
mathieu@4214
    68
          if (name == m_name)
mathieu@4214
    69
            {
mathieu@4214
    70
              SetValue (StringValue (value));
mathieu@4214
    71
            }
mathieu@4214
    72
        }
mathieu@4214
    73
      cur = next + 1;
mathieu@4214
    74
    }
mathieu@4214
    75
#endif /* HAVE_GETENV */
mathieu@2429
    76
}
mathieu@2429
    77
mathieu@2429
    78
std::string 
mathieu@2467
    79
GlobalValue::GetName (void) const
mathieu@2429
    80
{
mathieu@2429
    81
  return m_name;
mathieu@2429
    82
}
mathieu@2429
    83
std::string 
mathieu@2467
    84
GlobalValue::GetHelp (void) const
mathieu@2429
    85
{
mathieu@2429
    86
  return m_help;
mathieu@2429
    87
}
mathieu@2965
    88
void
mathieu@2965
    89
GlobalValue::GetValue (AttributeValue &value) const
mathieu@2429
    90
{
mathieu@2965
    91
  bool ok = m_checker->Copy (*m_initialValue, value);
mathieu@2965
    92
  if (ok)
mathieu@2965
    93
    {
mathieu@2965
    94
      return;
mathieu@2965
    95
    }
mathieu@2965
    96
  StringValue *str = dynamic_cast<StringValue *> (&value);
mathieu@2965
    97
  if (str == 0)
mathieu@2965
    98
    {
mathieu@2965
    99
      NS_FATAL_ERROR ("GlobalValue name="<<m_name<<": input value is not a string");
mathieu@2965
   100
    }
mathieu@2965
   101
  str->Set (m_initialValue->SerializeToString (m_checker));
mathieu@2429
   102
}
mathieu@2429
   103
Ptr<const AttributeChecker> 
mathieu@2467
   104
GlobalValue::GetChecker (void) const
mathieu@2429
   105
{
mathieu@2429
   106
  return m_checker;
mathieu@2429
   107
}
mathieu@2429
   108
  
mathieu@2570
   109
bool
mathieu@2965
   110
GlobalValue::SetValue (const AttributeValue &value)
mathieu@2429
   111
{
mathieu@2576
   112
  if (m_checker->Check (value))
mathieu@2576
   113
    {
mathieu@2965
   114
      m_initialValue = value.Copy ();
mathieu@2576
   115
      return true;
mathieu@2576
   116
    }
mathieu@2576
   117
  // attempt to convert to string.
mathieu@2965
   118
  const StringValue *str = dynamic_cast<const StringValue *> (&value);
mathieu@2576
   119
  if (str == 0)
mathieu@2429
   120
    {
mathieu@2570
   121
      return false;
mathieu@2429
   122
    }
mathieu@2576
   123
  // attempt to convert back to value.
mathieu@2965
   124
  Ptr<AttributeValue> v = m_checker->Create ();
mathieu@2965
   125
  bool ok = v->DeserializeFromString (str->Get (), m_checker);
mathieu@2576
   126
  if (!ok)
mathieu@2576
   127
    {
mathieu@2576
   128
      return false;
mathieu@2576
   129
    }
mathieu@2965
   130
  ok = m_checker->Check (*v);
mathieu@2576
   131
  if (!ok)
mathieu@2576
   132
    {
mathieu@2576
   133
      return false;
mathieu@2576
   134
    }
mathieu@2965
   135
  m_checker->Copy (*v, *PeekPointer (m_initialValue));
mathieu@2570
   136
  return true;
mathieu@2429
   137
}
mathieu@2429
   138
mathieu@2429
   139
void 
mathieu@2965
   140
GlobalValue::Bind (std::string name, const AttributeValue &value)
mathieu@2429
   141
{
mathieu@2429
   142
  for (Iterator i = Begin (); i != End (); i++)
mathieu@2429
   143
    {
mathieu@2429
   144
      if ((*i)->GetName () == name)
mathieu@2429
   145
	{
mathieu@2570
   146
	  if (!(*i)->SetValue (value))
mathieu@2570
   147
	    {
mathieu@2570
   148
	      NS_FATAL_ERROR ("Invalid new value for global value: "<<name);
mathieu@2570
   149
	    }
mathieu@2429
   150
	  return;
mathieu@2429
   151
	}
mathieu@2429
   152
    }
mathieu@2570
   153
  NS_FATAL_ERROR ("Non-existant global value: "<<name);
mathieu@2570
   154
}
mathieu@2570
   155
bool 
mathieu@2965
   156
GlobalValue::BindFailSafe (std::string name, const AttributeValue &value)
mathieu@2570
   157
{
mathieu@2570
   158
  for (Iterator i = Begin (); i != End (); i++)
mathieu@2570
   159
    {
mathieu@2570
   160
      if ((*i)->GetName () == name)
mathieu@2570
   161
	{
mathieu@2570
   162
	  return (*i)->SetValue (value);
mathieu@2570
   163
	}
mathieu@2570
   164
    }
mathieu@2570
   165
  return false;
mathieu@2429
   166
}
mathieu@2467
   167
GlobalValue::Iterator 
mathieu@2467
   168
GlobalValue::Begin (void)
mathieu@2429
   169
{
mathieu@2429
   170
  return GetVector ()->begin ();
mathieu@2429
   171
}
mathieu@2467
   172
GlobalValue::Iterator 
mathieu@2467
   173
GlobalValue::End (void)
mathieu@2429
   174
{
mathieu@2429
   175
  return GetVector ()->end ();
mathieu@2429
   176
}
mathieu@2467
   177
GlobalValue::Vector *
mathieu@2467
   178
GlobalValue::GetVector (void)
mathieu@2429
   179
{
mathieu@2429
   180
  static Vector vector;
mathieu@2429
   181
  return &vector;
mathieu@2429
   182
}
mathieu@2429
   183
mathieu@2429
   184
} // namespace ns3
mathieu@2429
   185
mathieu@2429
   186
#ifdef RUN_SELF_TESTS
mathieu@2429
   187
mathieu@2429
   188
#include "test.h"
mathieu@2455
   189
#include "uinteger.h"
mathieu@2429
   190
mathieu@2429
   191
namespace ns3 {
mathieu@2429
   192
mathieu@2467
   193
class GlobalValueTests : public Test
mathieu@2429
   194
{
mathieu@2429
   195
public:
mathieu@2467
   196
  GlobalValueTests ();
mathieu@2429
   197
  virtual bool RunTests (void);
mathieu@2429
   198
private:
mathieu@2429
   199
};
mathieu@2429
   200
mathieu@2467
   201
GlobalValueTests::GlobalValueTests ()
mathieu@2467
   202
  : Test ("GlobalValue")
mathieu@2429
   203
{}
mathieu@2429
   204
bool 
mathieu@2467
   205
GlobalValueTests::RunTests (void)
mathieu@2429
   206
{
mathieu@2429
   207
  bool result = true;
mathieu@2576
   208
  GlobalValue uint = GlobalValue ("TestUint", "help text",
mathieu@2965
   209
				  UintegerValue (10),
mathieu@2576
   210
				  MakeUintegerChecker<uint32_t> ());
mathieu@2429
   211
mathieu@2576
   212
mathieu@2965
   213
  UintegerValue v;
mathieu@2965
   214
  uint.GetValue (v);
mathieu@2965
   215
  NS_TEST_ASSERT_EQUAL (10, v.Get ());
mathieu@2576
   216
mathieu@2576
   217
  GlobalValue::Vector *vector = GlobalValue::GetVector ();
mathieu@2576
   218
  for (GlobalValue::Vector::iterator i = vector->begin (); i != vector->end (); ++i)
mathieu@2576
   219
    {
mathieu@2576
   220
      if ((*i) == &uint)
mathieu@2576
   221
	{
mathieu@2576
   222
	  vector->erase (i);
mathieu@2576
   223
	  break;
mathieu@2576
   224
	}
mathieu@2576
   225
    }
mathieu@2429
   226
mathieu@2429
   227
  return result;
mathieu@2429
   228
}
mathieu@2429
   229
mathieu@2467
   230
static GlobalValueTests g_initialValueTests;
mathieu@2429
   231
mathieu@2429
   232
} // namespace ns3
mathieu@2429
   233
mathieu@2429
   234
#endif /* RUN_SELF_TESTS */