make Ptr<T> convertible to a Value.
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Thu, 31 Jan 2008 15:10:21 +0100
changeset 2374 570f3c6c6142
parent 2373 73983ba47afc
child 2375 6f8733409b3b
make Ptr<T> convertible to a Value.
src/core/boolean-value.cc
src/core/boolean-value.h
src/core/object.cc
src/core/object.h
src/core/param-spec-helper.h
src/core/param-spec.cc
src/core/param-spec.h
src/core/value-test.cc
src/core/value.cc
src/core/value.h
src/core/wscript
--- a/src/core/boolean-value.cc	Wed Jan 30 19:13:21 2008 +0100
+++ b/src/core/boolean-value.cc	Thu Jan 31 15:10:21 2008 +0100
@@ -16,10 +16,10 @@
 {
   return m_value;
 }
-Ptr<Value>
+PValue
 BooleanValue::Copy (void) const
 {
-  return Create<BooleanValue> (*this);
+  return PValue::Create<BooleanValue> (*this);
 }
 std::string 
 BooleanValue::SerializeToString (Ptr<const ParamSpec> spec) const
@@ -57,22 +57,18 @@
       return false;
     }  
 }
-BooleanValue::BooleanValue (Ptr<const Value> value)
+BooleanValue::BooleanValue (PValue value)
 {
-  const BooleanValue *v = dynamic_cast<const BooleanValue *> (PeekPointer (value));
+  const BooleanValue *v = value.DynCast<const BooleanValue *> ();
   if (v == 0)
     {
       NS_FATAL_ERROR ("assigning non-Boolean value to Boolean value.");
     }
   m_value = v->m_value;
 }
-BooleanValue::operator Ptr<Value> () const
+BooleanValue::operator PValue () const
 {
-  return Create<BooleanValue> (*this);
-}
-BooleanValue::operator Ptr<const Value> () const
-{
-  return Create<BooleanValue> (*this);
+  return PValue::Create<BooleanValue> (*this);
 }
 
 } // namespace ns3
--- a/src/core/boolean-value.h	Wed Jan 30 19:13:21 2008 +0100
+++ b/src/core/boolean-value.h	Thu Jan 31 15:10:21 2008 +0100
@@ -2,7 +2,6 @@
 #define BOOLEAN_VALUE_H
 
 #include "value.h"
-#include "param-spec.h"
 #include "param-spec-helper.h"
 #include "ptr.h"
 
@@ -15,13 +14,12 @@
   void Set (bool value);
   bool Get (void) const;
 
-  virtual Ptr<Value> Copy (void) const;
+  virtual PValue Copy (void) const;
   virtual std::string SerializeToString (Ptr<const ParamSpec> spec) const;
   virtual bool DeserializeFromString (std::string value, Ptr<const ParamSpec> spec);
 
-  BooleanValue (Ptr<const Value> value);
-  operator Ptr<Value> () const;
-  operator Ptr<const Value> () const;
+  BooleanValue (PValue value);
+  operator PValue () const;
 private:
   bool m_value;
 };
--- a/src/core/object.cc	Wed Jan 30 19:13:21 2008 +0100
+++ b/src/core/object.cc	Thu Jan 31 15:10:21 2008 +0100
@@ -23,7 +23,6 @@
 #include "singleton.h"
 #include "trace-resolver.h"
 #include "value.h"
-#include "param-spec.h"
 #include "log.h"
 #include <vector>
 #include <sstream>
@@ -62,7 +61,6 @@
   uint32_t GetParametersN (uint16_t uid) const;
   std::string GetParameterName (uint16_t uid, uint32_t i) const;
   uint32_t GetParameterFlags (uint16_t uid, uint32_t i) const;
-  const ns3::Value *GetParameterInitialValue (uint16_t uid, uint32_t i) const;
   uint32_t GetParameterUid (uint16_t uid, uint32_t i) const;
   ns3::Ptr<const ns3::ParamSpec> GetParameterParamSpec (uint16_t uid, uint32_t i) const;
 private:
@@ -594,7 +592,7 @@
     {
       struct Param param;
       param.spec = i->spec;
-      param.value = i->value->Copy ();
+      param.value = i->value.Copy ();
       m_parameters.push_back (param);
     }
 }
@@ -606,7 +604,7 @@
     {
       struct Param param;
       param.spec = i->spec;
-      param.value = i->value->Copy ();
+      param.value = i->value.Copy ();
       m_parameters.push_back (param);
     }
   return *this;
@@ -617,7 +615,7 @@
 }
 
 bool 
-Parameters::Set (std::string name, Ptr<const Value> value)
+Parameters::Set (std::string name, PValue value)
 {
   Ptr<const ParamSpec> spec = TypeId::LookupParamSpecByFullName (name);
   bool ok = DoSet (spec, value);
@@ -637,7 +635,7 @@
   DoSet (spec, value);
 }
 void 
-Parameters::SetWithTid (TypeId tid, std::string name, Ptr<const Value> value)
+Parameters::SetWithTid (TypeId tid, std::string name, PValue value)
 {
   Ptr<const ParamSpec> spec = tid.LookupParamSpecByName (name);
   DoSet (spec, value);
@@ -649,14 +647,14 @@
   DoSet (spec, value);
 }
 void 
-Parameters::SetWithTid (TypeId tid, uint32_t position, Ptr<const Value> value)
+Parameters::SetWithTid (TypeId tid, uint32_t position, PValue value)
 {
   Ptr<const ParamSpec> spec = tid.LookupParamSpecByPosition (position);
   DoSet (spec, value);
 }
 
 void
-Parameters::DoSetOne (Ptr<const ParamSpec> spec, Ptr<const Value> value)
+Parameters::DoSetOne (Ptr<const ParamSpec> spec, PValue value)
 {
   // get rid of any previous value stored in this
   // vector of values.
@@ -671,11 +669,11 @@
   // store the new value.
   struct Param p;
   p.spec = spec;
-  p.value = value->Copy ();
+  p.value = value.Copy ();
   m_parameters.push_back (p);
 }
 bool
-Parameters::DoSet (Ptr<const ParamSpec> spec, Ptr<const Value> value)
+Parameters::DoSet (Ptr<const ParamSpec> spec, PValue value)
 {
   if (spec == 0)
     {
@@ -696,8 +694,8 @@
     {
       return false;
     }
-  Ptr<Value> v = spec->CreateInitialValue ();
-  bool ok = v->DeserializeFromString (value, spec);
+  PValue v = spec->CreateInitialValue ();
+  bool ok = v.DeserializeFromString (value, spec);
   if (!ok)
     {
       return false;
@@ -747,7 +745,7 @@
   for (Params::const_iterator i = m_parameters.begin (); i != m_parameters.end (); i++)
     {
       std::string name = LookupParameterFullNameByParamSpec (i->spec);
-      oss << name << "=" << i->value->SerializeToString (PeekPointer (i->spec));
+      oss << name << "=" << i->value.SerializeToString (PeekPointer (i->spec));
       if (i != m_parameters.end ())
         {
           oss << "|";
@@ -792,8 +790,8 @@
                 value = str.substr (equal+1, next - (equal+1));
                 cur++;
               }
-            Ptr<Value> val = spec->CreateInitialValue ();
-            bool ok = val->DeserializeFromString (value, spec);
+            PValue val = spec->CreateInitialValue ();
+            bool ok = val.DeserializeFromString (value, spec);
             if (!ok)
               {
                 // XXX invalid value
@@ -892,7 +890,7 @@
         if (!found)
           {
             // No matching parameter value so we set the default value.
-            Ptr<Value> initial = paramSpec->CreateInitialValue ();
+            PValue initial = paramSpec->CreateInitialValue ();
             paramSpec->Set (this, initial);
             NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
                           tid.GetParameterName (i)<<"\" from local");
@@ -903,7 +901,7 @@
   NotifyConstructionCompleted ();
 }
 bool
-Object::DoSet (std::string name, Ptr<const Value> value)
+Object::DoSet (std::string name, PValue value)
 {
   Ptr<const ParamSpec> spec = m_tid.LookupParamSpecByName (name);
   if (spec == 0)
@@ -918,7 +916,7 @@
   return true;
 }
 bool
-Object::Set (std::string name, Ptr<const Value> value)
+Object::Set (std::string name, PValue value)
 {
   return DoSet (name, value);
 }
@@ -930,13 +928,13 @@
     {
       return false;
     }
-  Ptr<Value> parameter = spec->CreateInitialValue ();
-  bool ok = parameter->DeserializeFromString (value, spec);
+  PValue v = spec->CreateInitialValue ();
+  bool ok = v.DeserializeFromString (value, spec);
   if (!ok)
     {
       return false;
     }
-  spec->Set (this, parameter);
+  spec->Set (this, v);
   if (!ok)
     {
       return false;
@@ -951,34 +949,34 @@
     {
       return false;
     }
-  Ptr<Value> parameter = paramSpec->CreateInitialValue ();
-  bool ok = paramSpec->Get (this, parameter);
+  PValue v = paramSpec->CreateInitialValue ();
+  bool ok = paramSpec->Get (this, v);
   if (ok)
     {
-      value = parameter->SerializeToString (paramSpec);
+      value = v.SerializeToString (paramSpec);
     }
   return ok;
 }
 
-Ptr<const Value>
+PValue
 Object::Get (std::string name) const
 {
   Ptr<const ParamSpec> paramSpec = m_tid.LookupParamSpecByName (name);
   if (paramSpec == 0)
     {
-      return 0;
+      return PValue ();
     }
-  Ptr<Value> value = paramSpec->CreateInitialValue ();
+  PValue value = paramSpec->CreateInitialValue ();
   bool ok = paramSpec->Get (this, value);
   if (!ok)
     {
-      return 0;
+      return PValue ();
     }
   return value;
 }
 
 bool 
-Object::DoGet (std::string name, Ptr<Value> parameter) const
+Object::DoGet (std::string name, PValue parameter) const
 {
   Ptr<const ParamSpec> paramSpec = m_tid.LookupParamSpecByName (name);
   if (paramSpec == 0)
--- a/src/core/object.h	Wed Jan 30 19:13:21 2008 +0100
+++ b/src/core/object.h	Thu Jan 31 15:10:21 2008 +0100
@@ -287,12 +287,12 @@
    * the program terminates with a message.
    */
   bool Set (std::string name, std::string value);
-  bool Set (std::string name, Ptr<const Value> value);
+  bool Set (std::string name, PValue value);
 
   void SetWithTid (TypeId tid, std::string name, std::string value);
-  void SetWithTid (TypeId tid, std::string name, Ptr<const Value> value);
+  void SetWithTid (TypeId tid, std::string name, PValue value);
   void SetWithTid (TypeId tid, uint32_t position, std::string value);
-  void SetWithTid (TypeId tid, uint32_t position, Ptr<const Value> value);
+  void SetWithTid (TypeId tid, uint32_t position, PValue value);
 
   /**
    * Clear the content of this instance.
@@ -317,7 +317,7 @@
   friend class Object;
   struct Param {
     Ptr<const ParamSpec> spec;
-    Ptr<const Value> value;
+    PValue value;
   };
   typedef std::vector<struct Param> Params;
   typedef Params::iterator Iterator;
@@ -325,9 +325,9 @@
 
 
 
-  bool DoSet (Ptr<const ParamSpec> spec, Ptr<const Value> param);
+  bool DoSet (Ptr<const ParamSpec> spec, PValue param);
   bool DoSet (Ptr<const ParamSpec> spec, std::string value);
-  void DoSetOne (Ptr<const ParamSpec> spec, Ptr<const Value> param);
+  void DoSetOne (Ptr<const ParamSpec> spec, PValue param);
   std::string LookupParameterFullNameByParamSpec (Ptr<const ParamSpec> spec) const;
 
   Params m_parameters;
@@ -353,7 +353,7 @@
    * Set a single parameter.
    */
   bool Set (std::string name, std::string value);
-  bool Set (std::string name, Ptr<const Value> value);
+  bool Set (std::string name, PValue value);
   /**
    * \param name the name of the parameter to read
    * \param value a reference to the string where the value of the 
@@ -367,7 +367,7 @@
    *        parameter should be stored.
    * \returns true if the requested parameter was found, false otherwise.
    */
-  Ptr<const Value> Get (std::string name) const;
+  PValue Get (std::string name) const;
 
   /**
    * Increment the reference count. This method should not be called
@@ -473,8 +473,8 @@
   void DoTraceAll (std::ostream &os, const TraceContext &context) const;
   bool Check (void) const;
   bool CheckLoose (void) const;
-  bool DoSet (std::string name, Ptr<const Value> value);
-  bool DoGet (std::string name, Ptr<Value> value) const;
+  bool DoSet (std::string name, PValue value);
+  bool DoGet (std::string name, PValue value) const;
   /**
    * Attempt to delete this object. This method iterates
    * over all aggregated objects to check if they all 
@@ -730,8 +730,8 @@
 
 template <typename T>
 Ptr<T> 
-CreateObjectWith (std::string n1, Ptr<const Value> v1,
-                  std::string n2 = "", Ptr<const Value> v2 = 0)
+CreateObjectWith (std::string n1, PValue v1,
+                  std::string n2 = "", PValue v2 = PValue ())
               
 {
   Parameters parameters;
--- a/src/core/param-spec-helper.h	Wed Jan 30 19:13:21 2008 +0100
+++ b/src/core/param-spec-helper.h	Thu Jan 31 15:10:21 2008 +0100
@@ -8,10 +8,10 @@
 {
 public:
   ParamSpecHelper (V initialValue);
-  virtual bool Set (ObjectBase * object, Ptr<const Value> parameter) const;
-  virtual bool Get (const ObjectBase * object, Ptr<Value> parameter) const;
-  virtual bool Check (Ptr<const Value> parameter) const;
-  virtual Ptr<Value> CreateInitialValue (void) const;
+  virtual bool Set (ObjectBase * object, PValue value) const;
+  virtual bool Get (const ObjectBase * object, PValue value) const;
+  virtual bool Check (PValue value) const;
+  virtual PValue CreateInitialValue (void) const;
 
 private:
   virtual void DoSet (T *object, const V &v) const = 0;
@@ -87,9 +87,9 @@
 {}
 template <typename T, typename U, typename V>
 bool 
-ParamSpecHelper<T,U,V>::Set (ObjectBase * object, Ptr<const Value> parameter) const
+ParamSpecHelper<T,U,V>::Set (ObjectBase * object, PValue val) const
 {
-  const U *value = dynamic_cast<const U*> (PeekPointer (parameter));
+  const U *value = val.DynCast<const U*> ();
   if (value == 0)
     {
       return false;
@@ -105,9 +105,9 @@
 }
 template <typename T, typename U, typename V>
 bool 
-ParamSpecHelper<T,U,V>::Get (const ObjectBase * object, Ptr<Value> parameter) const
+ParamSpecHelper<T,U,V>::Get (const ObjectBase * object, PValue val) const
 {
-  U *value = dynamic_cast<U*> (PeekPointer (parameter));
+  U *value = val.DynCast<U*> ();
   if (value == 0)
     {
       return false;
@@ -123,14 +123,14 @@
 }
 template <typename T, typename U, typename V>
 bool 
-ParamSpecHelper<T,U,V>::Check (Ptr<const Value> parameter) const
+ParamSpecHelper<T,U,V>::Check (PValue value) const
 {
-  const U *value = dynamic_cast<const U*> (PeekPointer (parameter));
-  if (value == 0)
+  const U *val = value.DynCast<const U*> ();
+  if (val == 0)
     {
       return false;
     }
-  V v = value->Get ();
+  V v = val->Get ();
   DoCheck (v);
   return true;
 }
@@ -141,10 +141,10 @@
   return true;
 }
 template <typename T, typename U, typename V>
-Ptr<Value>
+PValue
 ParamSpecHelper<T,U,V>::CreateInitialValue (void) const
 {
-  return Create<U> (m_initialValue);
+  return PValue::Create<U> (m_initialValue);
 }
 
 
--- a/src/core/param-spec.cc	Wed Jan 30 19:13:21 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-#include "param-spec.h"
-
-namespace ns3 {
-
-ParamSpec::ParamSpec ()
-  : m_count (1)
-{}
-void 
-ParamSpec::Ref (void) const
-{
-  m_count++;
-}
-void 
-ParamSpec::Unref (void) const
-{
-  m_count--;
-  if (m_count == 0)
-    {
-      delete this;
-    }
-}
-ParamSpec::~ParamSpec ()
-{}
-
-} // namespace ns3
--- a/src/core/param-spec.h	Wed Jan 30 19:13:21 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-#ifndef PARAM_SPEC_H
-#define PARAM_SPEC_H
-
-#include <string>
-#include <stdint.h>
-#include "object-base.h"
-#include "ptr.h"
-
-namespace ns3 {
-
-class Value;
-
-class ParamSpec : public ObjectBase
-{
-public:
-  ParamSpec ();
-  void Ref (void) const;
-  void Unref (void) const;
-  virtual ~ParamSpec ();
-
-  /**
-   * \param object the object instance to set the value in
-   * \param value the value to set
-   * \returns true if the value is valid and it could be set
-   *          successfully, false otherwise.
-   */
-  virtual bool Set (ObjectBase * object, Ptr<const Value> parameter) const = 0;
-  virtual bool Get (const ObjectBase * object, Ptr<Value> parameter) const = 0;
-  virtual bool Check (Ptr<const Value> parameter) const = 0;
-  virtual Ptr<Value> CreateInitialValue (void) const = 0;
-private:
-  mutable uint32_t m_count;
-};
-
-} // namespace ns3
-
-#endif /* PARAM_SPEC_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/value-test.cc	Thu Jan 31 15:10:21 2008 +0100
@@ -0,0 +1,291 @@
+#ifdef RUN_SELF_TESTS
+#include "test.h"
+#include "object.h"
+#include "boolean-value.h"
+#if 0
+#include "int-value.h"
+#include "uint-value.h"
+#include "fp-value.h"
+#include "enum-value.h"
+#endif
+namespace ns3 {
+
+class ParamSpecTest : public Test
+{
+public:
+  ParamSpecTest ();
+  virtual bool RunTests (void);
+private:
+};
+
+class Derived : public Object
+{
+public:
+  static TypeId GetTypeId (void) {
+    static TypeId tid = TypeId ("Derived")
+      .SetParent<Object> ()
+      ;
+    return tid;
+  }
+};
+
+class ParamSpecObjectTest : public Object
+{
+public:
+  enum TestEnum {
+    TEST_A,
+    TEST_B,
+    TEST_C
+  };
+  static TypeId GetTypeId (void) {
+    static TypeId tid = TypeId ("ParamSpecObjectTest")
+      .SetParent<Object> ()
+      .AddParameter ("TestBoolName", "help text",
+		     MakeBooleanParamSpec (&ParamSpecObjectTest::m_boolTest, false))
+      .AddParameter ("TestBoolA", "help text",
+		     MakeBooleanParamSpec (&ParamSpecObjectTest::DoSetTestB,
+					   &ParamSpecObjectTest::DoGetTestB, 
+					   false))
+      .AddParameter ("TestPtr", "help text", 
+		     MakePtrParamSpec (&ParamSpecObjectTest::m_derived))
+#if 0
+      .AddParameter ("TestInt16", "help text",
+		     MakeIntParamSpec (-2, &ParamSpecObjectTest::m_int16))
+      .AddParameter ("TestInt16WithBounds", "help text",
+		     MakeIntParamSpec (-2, -5, 10, 
+				       &ParamSpecObjectTest::m_int16WithBounds))
+      .AddParameter ("TestInt16SetGet", "help text",
+		     MakeIntParamSpec (6, &ParamSpecObjectTest::DoSetInt16,
+				       &ParamSpecObjectTest::DoGetInt16))
+      .AddParameter ("TestUint8", "help text",
+		     MakeUintParamSpec (1, &ParamSpecObjectTest::m_uint8))
+      .AddParameter ("TestFloat", "help text",
+		     MakeFpParamSpec (-1.1, &ParamSpecObjectTest::m_float))
+      .AddParameter ("TestEnum", "help text",
+		     MakeEnumParamSpec (&ParamSpecObjectTest::m_enum,
+					TEST_A, "TestA",
+					TEST_B, "TestB",
+					TEST_C, "TestC"))
+#endif
+      ;
+        
+    return tid;
+  }
+
+private:
+  void DoSetTestB (bool v) {
+    m_boolTestA = v;
+  }
+  bool DoGetTestB (void) const {
+    return m_boolTestA;
+  }
+  int16_t DoGetInt16 (void) const {
+    return m_int16SetGet;
+  }
+  void DoSetInt16 (int16_t v) {
+    m_int16SetGet = v;
+  }
+  bool m_boolTestA;
+  bool m_boolTest;
+  Ptr<Derived> m_derived;
+  int16_t m_int16;
+  int16_t m_int16WithBounds;
+  int16_t m_int16SetGet;
+  uint8_t m_uint8;
+  float m_float;
+  enum TestEnum m_enum;
+};
+
+
+#define CHECK_GET_STR(p,name,value)		\
+  {						\
+    std::string expected = value;		\
+    std::string got;				\
+    bool ok = p->Get (name, got);		\
+    NS_TEST_ASSERT (ok);			\
+    NS_TEST_ASSERT_EQUAL (got, expected);	\
+  }
+#define CHECK_GET_PARAM(p,name,type,value)		\
+  {							\
+    const type expected = value;			\
+    type got = value;					\
+    PValue v = p->Get (name);				\
+    NS_TEST_ASSERT (v.DynCast<type *> () != 0);		\
+    got = v;						\
+    NS_TEST_ASSERT_EQUAL (got.Get (), expected.Get ());	\
+  }
+
+
+NS_OBJECT_ENSURE_REGISTERED (ParamSpecObjectTest);
+
+ParamSpecTest::ParamSpecTest ()
+  : Test ("ParamSpec")
+{}
+bool 
+ParamSpecTest::RunTests (void)
+{
+  bool result = true;
+
+  Parameters params;
+  Ptr<ParamSpecObjectTest> p;
+  NS_TEST_ASSERT (params.Set ("ParamSpecObjectTest::TestBoolName", "false"));
+  p = CreateObject<ParamSpecObjectTest> (params);
+  CHECK_GET_STR (p, "TestBoolName", "false");
+  CHECK_GET_PARAM (p, "TestBoolName", BooleanValue, false);
+
+  NS_TEST_ASSERT (p->Set ("TestBoolName", "true"));
+  CHECK_GET_STR (p, "TestBoolName", "true");
+  CHECK_GET_PARAM (p, "TestBoolName", BooleanValue, true);
+
+  NS_TEST_ASSERT (p->Set ("TestBoolName", BooleanValue (false)));
+  CHECK_GET_STR (p, "TestBoolName", "false");
+  CHECK_GET_PARAM (p, "TestBoolName", BooleanValue, false);
+
+  p = CreateObjectWith<ParamSpecObjectTest> ("TestBoolName", "true");
+  CHECK_GET_STR (p, "TestBoolName", "true");
+  CHECK_GET_PARAM (p, "TestBoolName", BooleanValue, true);
+
+  p = CreateObjectWith<ParamSpecObjectTest> ("TestBoolName", BooleanValue (true));
+  CHECK_GET_STR (p, "TestBoolName", "true");
+  CHECK_GET_PARAM (p, "TestBoolName", BooleanValue, true);
+
+  NS_TEST_ASSERT (p->Set ("TestBoolA", "false"));
+  CHECK_GET_STR (p, "TestBoolA", "false");
+  CHECK_GET_PARAM (p, "TestBoolA", BooleanValue, false);
+
+  NS_TEST_ASSERT (p->Set ("TestBoolA", "true"));
+  CHECK_GET_STR (p, "TestBoolA", "true");
+  CHECK_GET_PARAM (p, "TestBoolA", BooleanValue, true);
+
+
+  Ptr<Derived> derived = p->Get ("TestPtr");
+  NS_TEST_ASSERT (derived == 0);
+  derived = Create<Derived> ();
+  NS_TEST_ASSERT (p->Set ("TestPtr", derived));
+  Ptr<Derived> stored = p->Get ("TestPtr");
+  NS_TEST_ASSERT (stored == derived);
+  Ptr<Object> storedBase = p->Get ("TestPtr");
+  NS_TEST_ASSERT (stored == storedBase);
+  Ptr<ParamSpecObjectTest> x = p->Get ("TestPtr");
+  NS_TEST_ASSERT (x == 0);
+
+  p = CreateObjectWith<ParamSpecObjectTest> ("TestPtr", Create<Derived> ());
+  NS_TEST_ASSERT (p != 0);
+  derived = 0;
+  derived = p->Get ("TestPtr");
+  NS_TEST_ASSERT (derived != 0);
+
+#if 0
+  CHECK_GET_STR (p, "TestInt16", "-2");
+  CHECK_GET_PARAM (p, "TestInt16", IntValue, -2);
+
+  NS_TEST_ASSERT (p->Set ("TestInt16", "-5"));
+  CHECK_GET_STR (p, "TestInt16", "-5");
+  CHECK_GET_PARAM (p, "TestInt16", IntValue, -5);
+
+  NS_TEST_ASSERT (p->Set ("TestInt16", IntValue (+2)));
+  CHECK_GET_STR (p, "TestInt16", "2");
+  CHECK_GET_PARAM (p, "TestInt16", IntValue, +2);
+
+  NS_TEST_ASSERT (p->Set ("TestInt16", IntValue (-32768)));
+  CHECK_GET_STR (p, "TestInt16", "-32768");
+  CHECK_GET_PARAM (p, "TestInt16", IntValue, -32768);
+
+  NS_TEST_ASSERT (!p->Set ("TestInt16", IntValue (-32769)));
+  CHECK_GET_STR (p, "TestInt16", "-32768");
+  CHECK_GET_PARAM (p, "TestInt16", IntValue, -32768);
+
+  NS_TEST_ASSERT (p->Set ("TestInt16", IntValue (32767)));
+  CHECK_GET_STR (p, "TestInt16", "32767");
+  CHECK_GET_PARAM (p, "TestInt16", IntValue, 32767);
+
+  NS_TEST_ASSERT (!p->Set ("TestInt16", IntValue (32768)));
+  CHECK_GET_STR (p, "TestInt16", "32767");
+  CHECK_GET_PARAM (p, "TestInt16", IntValue, 32767);
+
+  NS_TEST_ASSERT (p->Set ("TestInt16WithBounds", IntValue (10)));
+  CHECK_GET_STR (p, "TestInt16WithBounds", "10");
+  CHECK_GET_PARAM (p, "TestInt16WithBounds", IntValue, 10);
+  NS_TEST_ASSERT (!p->Set ("TestInt16WithBounds", IntValue (11)));
+  CHECK_GET_STR (p, "TestInt16WithBounds", "10");
+  CHECK_GET_PARAM (p, "TestInt16WithBounds", IntValue, 10);
+
+  NS_TEST_ASSERT (p->Set ("TestInt16WithBounds", IntValue (-5)));
+  CHECK_GET_STR (p, "TestInt16WithBounds", "-5");
+  CHECK_GET_PARAM (p, "TestInt16WithBounds", IntValue, -5);
+  NS_TEST_ASSERT (!p->Set ("TestInt16WithBounds", IntValue (-6)));
+  CHECK_GET_STR (p, "TestInt16WithBounds", "-5");
+  CHECK_GET_PARAM (p, "TestInt16WithBounds", IntValue, -5);
+
+  CHECK_GET_STR (p, "TestInt16SetGet", "6");
+  CHECK_GET_PARAM (p, "TestInt16SetGet", IntValue, 6);
+  NS_TEST_ASSERT (p->Set ("TestInt16SetGet", IntValue (0)));
+  CHECK_GET_STR (p, "TestInt16SetGet", "0");
+  CHECK_GET_PARAM (p, "TestInt16SetGet", IntValue, 0);
+  
+  CHECK_GET_STR (p, "TestUint8", "1");
+  CHECK_GET_PARAM (p, "TestUint8", UintValue, 1);
+  NS_TEST_ASSERT (p->Set ("TestUint8", UintValue (0)));
+  CHECK_GET_STR (p, "TestUint8", "0");
+  CHECK_GET_PARAM (p, "TestUint8", UintValue, 0);
+  NS_TEST_ASSERT (p->Set ("TestUint8", UintValue (255)));
+  CHECK_GET_STR (p, "TestUint8", "255");
+  CHECK_GET_PARAM (p, "TestUint8", UintValue, 255);
+  NS_TEST_ASSERT (p->Set ("TestUint8", "255"));
+  CHECK_GET_STR (p, "TestUint8", "255");
+  CHECK_GET_PARAM (p, "TestUint8", UintValue, 255);
+  NS_TEST_ASSERT (!p->Set ("TestUint8", "256"));
+  CHECK_GET_STR (p, "TestUint8", "255");
+  CHECK_GET_PARAM (p, "TestUint8", UintValue, 255);
+  NS_TEST_ASSERT (!p->Set ("TestUint8", "-1"));
+  CHECK_GET_STR (p, "TestUint8", "255");
+  CHECK_GET_PARAM (p, "TestUint8", UintValue, 255);
+  NS_TEST_ASSERT (!p->Set ("TestUint8", UintValue (-1)));
+  CHECK_GET_STR (p, "TestUint8", "255");
+  CHECK_GET_PARAM (p, "TestUint8", UintValue, 255);
+
+  CHECK_GET_STR (p, "TestFloat", "-1.1");
+  NS_TEST_ASSERT (p->Set ("TestFloat", FpValue ((float)+2.3)));
+  CHECK_GET_PARAM (p, "TestFloat", FpValue, (float)+2.3);
+
+  CHECK_GET_STR (p, "TestEnum", "TestA");
+  CHECK_GET_PARAM (p, "TestEnum", EnumValue, ParamSpecObjectTest::TEST_A);
+  NS_TEST_ASSERT (p->Set ("TestEnum", EnumValue (ParamSpecObjectTest::TEST_C)));
+  CHECK_GET_STR (p, "TestEnum", "TestC");
+  CHECK_GET_PARAM (p, "TestEnum", EnumValue, ParamSpecObjectTest::TEST_C);
+  NS_TEST_ASSERT (p->Set ("TestEnum", "TestB"));
+  CHECK_GET_STR (p, "TestEnum", "TestB");
+  CHECK_GET_PARAM (p, "TestEnum", EnumValue, ParamSpecObjectTest::TEST_B);
+  NS_TEST_ASSERT (!p->Set ("TestEnum", "TestD"));
+  CHECK_GET_STR (p, "TestEnum", "TestB");
+  CHECK_GET_PARAM (p, "TestEnum", EnumValue, ParamSpecObjectTest::TEST_B);
+  NS_TEST_ASSERT (!p->Set ("TestEnum", EnumValue (5)));
+  CHECK_GET_STR (p, "TestEnum", "TestB");
+  CHECK_GET_PARAM (p, "TestEnum", EnumValue, ParamSpecObjectTest::TEST_B);
+#endif
+
+#if 0
+  p->Set ("TestBoolName", "true");
+  NS_TEST_ASSERT_EQUAL (p->Get ("TestBoolName"), "true");
+  p->Set ("TestBoolName", "false");
+  NS_TEST_ASSERT_EQUAL (p->Get ("TestBoolName"), "false");
+
+  Parameters::GetGlobal ()->Set ("TestBoolName", "true");
+  p = CreateObjectWith<ParamSpecObjectTest> ();
+  NS_TEST_ASSERT_EQUAL (p->Get ("TestBoolName"), "true");
+
+  Parameters::GetGlobal ()->Set ("TestBoolName", "false");
+  p = CreateObjectWith<ParamSpecObjectTest> ();
+  NS_TEST_ASSERT_EQUAL (p->Get ("TestBoolName"), "false");
+#endif
+  return result;
+}
+
+
+
+static ParamSpecTest g_parameterTest;
+
+} // namespace ns3
+
+
+#endif /* RUN_SELF_TESTS */
--- a/src/core/value.cc	Wed Jan 30 19:13:21 2008 +0100
+++ b/src/core/value.cc	Thu Jan 31 15:10:21 2008 +0100
@@ -1,17 +1,106 @@
 #include "value.h"
+#include "log.h"
+#include <sstream>
+
+NS_LOG_COMPONENT_DEFINE ("Value");
 
 namespace ns3 {
 
 Value::Value ()
   : m_count (1)
 {}
+Value::Value (const Value &o)
+  : m_count (1)
+{}
+Value &
+Value::operator = (const Value &o)
+{
+  return *this;
+}
+Value::~Value ()
+{}
+
+PValue::PValue ()
+  : m_value (0)
+{}
+PValue::PValue (const PValue &o)
+  : m_value (o.m_value)
+{
+  if (m_value != 0)
+    {
+      m_value->m_count++;
+      NS_LOG_DEBUG ("this="<<m_value<<" ++count="<<m_value->m_count);
+    }
+}
+PValue &
+PValue::operator = (const PValue &o)
+{
+  if (&o != this)
+    {
+      if (m_value != 0)
+	{
+	  m_value->m_count--;
+	  NS_LOG_DEBUG ("this="<<m_value<<" --count="<<m_value->m_count);
+	  if (m_value->m_count == 0)
+	    {
+	      delete m_value;
+	      m_value = 0;
+	    }
+	}
+      m_value = o.m_value;
+      if (m_value != 0)
+	{
+	  m_value->m_count++;
+	  NS_LOG_DEBUG ("this="<<m_value<<" ++count="<<m_value->m_count);
+	}
+    }
+  return *this;
+}
+PValue::~PValue ()
+{
+  if (m_value != 0) 
+    {
+      m_value->m_count--;
+      NS_LOG_DEBUG ("this="<<m_value<<" --count="<<m_value->m_count);
+      if (m_value->m_count == 0)
+	{
+	  delete m_value;
+	  m_value = 0;
+	}
+    }
+}
+PValue::PValue (Value *value)
+  : m_value (value)
+{
+  NS_LOG_DEBUG ("this="<<m_value<<" count="<<((m_value!=0)?m_value->m_count:666));
+}
+
+PValue 
+PValue::Copy (void) const
+{
+  return m_value->Copy ();
+}
+std::string 
+PValue::SerializeToString (Ptr<const ParamSpec> spec) const
+{
+  return m_value->SerializeToString (spec);
+}
+bool 
+PValue::DeserializeFromString (std::string value, Ptr<const ParamSpec> spec)
+{
+  return m_value->DeserializeFromString (value, spec);
+}
+
+ParamSpec::ParamSpec ()
+  : m_count (1)
+{}
 void 
-Value::Ref (void) const
+ParamSpec::Ref (void) const
 {
   m_count++;
 }
 void 
-Value::Unref (void) const
+ParamSpec::Unref (void) const
 {
   m_count--;
   if (m_count == 0)
@@ -19,7 +108,22 @@
       delete this;
     }
 }
-Value::~Value ()
+ParamSpec::~ParamSpec ()
 {}
 
+std::string 
+PtrValueBase::SerializeToString (Ptr<const ParamSpec> spec) const
+{
+  std::ostringstream oss;
+  oss << PeekObjectBase ();
+  return oss.str ();
+}
+
+bool 
+PtrValueBase::DeserializeFromString (std::string value, Ptr<const ParamSpec> spec)
+{
+  // XXX
+  return false;
+}
+
 } // namespace ns3
--- a/src/core/value.h	Wed Jan 30 19:13:21 2008 +0100
+++ b/src/core/value.h	Thu Jan 31 15:10:21 2008 +0100
@@ -3,28 +3,322 @@
 
 #include <string>
 #include <stdint.h>
+#include "ptr.h"
 #include "object-base.h"
-#include "ptr.h"
 
 namespace ns3 {
 
 class ParamSpec;
+class PValue;
 
-class Value : public ObjectBase
+class Value
 {
 public:
   Value ();
-  void Ref (void) const;
-  void Unref (void) const;
+  Value (const Value &o);
+  Value &operator = (const Value &o);
   virtual ~Value ();
 
-  virtual Ptr<Value> Copy (void) const = 0;
+  virtual PValue Copy (void) const = 0;
   virtual std::string SerializeToString (Ptr<const ParamSpec> spec) const = 0;
   virtual bool DeserializeFromString (std::string value, Ptr<const ParamSpec> spec) = 0;
 private:
+  friend class PValue;
+  uint32_t m_count;
+};
+
+class PValue
+{
+public:
+  PValue ();
+  PValue (const PValue &o);
+  PValue &operator = (const PValue &o);
+  ~PValue ();
+
+  PValue Copy (void) const;
+  std::string SerializeToString (Ptr<const ParamSpec> spec) const;
+  bool DeserializeFromString (std::string value, Ptr<const ParamSpec> spec);
+
+  template <typename T>
+  static PValue Create (void);
+  template <typename T, typename T1>
+  static PValue Create (T1 a1);
+
+  template <typename T>
+  T DynCast (void) const;
+
+  template <typename T>
+  PValue (Ptr<T> pointer);
+  template <typename T>
+  operator Ptr<T> ();
+
+private:
+  PValue (Value *value);
+  Value *m_value;
+};
+
+class ParamSpec : public ObjectBase
+{
+public:
+  ParamSpec ();
+  void Ref (void) const;
+  void Unref (void) const;
+  virtual ~ParamSpec ();
+
+  /**
+   * \param object the object instance to set the value in
+   * \param value the value to set
+   * \returns true if the value is valid and it could be set
+   *          successfully, false otherwise.
+   */
+  virtual bool Set (ObjectBase * object, PValue value) const = 0;
+  virtual bool Get (const ObjectBase * object, PValue value) const = 0;
+  virtual bool Check (PValue value) const = 0;
+  virtual PValue CreateInitialValue (void) const = 0;
+private:
   mutable uint32_t m_count;
 };
 
+
+template <typename T, typename U>
+Ptr<const ParamSpec>
+MakePtrParamSpec (Ptr<U> T::*memberVariable);
+
+template <typename T, typename U>
+Ptr<const ParamSpec>
+MakePtrParamSpec (void (T::*setter) (Ptr<U>));
+template <typename T, typename U>
+Ptr<const ParamSpec>
+MakePtrParamSpec (Ptr<U> (T::*getter) (void) const);
+
+
+} // namespace ns3
+
+namespace ns3 {
+
+/********************************************************
+ *   The class used to access the pointer stored in a
+ *   PtrValue<T> Value instance.
+ ********************************************************/
+
+class PtrValueBase : public Value
+{
+public:
+  virtual ObjectBase *PeekObjectBase (void) const = 0;
+  virtual bool SetObjectBase (ObjectBase *object) = 0;
+  virtual std::string SerializeToString (Ptr<const ParamSpec> spec) const;
+  virtual bool DeserializeFromString (std::string value, Ptr<const ParamSpec> spec);
+};
+
+/********************************************************
+ *        Store the content of a Ptr<T> in a Value
+ ********************************************************/
+
+template <typename T>
+class PtrValue : public PtrValueBase
+{
+public:
+  PtrValue (Ptr<T> pointer) 
+    : m_pointer (pointer) {}
+
+  virtual ObjectBase *PeekObjectBase (void) const {
+    return PeekPointer (m_pointer);
+  }
+  virtual bool SetObjectBase (ObjectBase *object) {
+    T *ptr = dynamic_cast<T *> (object);
+    if (ptr == 0)
+      {
+	return false;
+      }
+    m_pointer = ptr;
+    return true;
+  }
+  virtual PValue Copy (void) const {
+    return PValue::Create<PtrValue<T> > (*this);
+  }
+private:
+  Ptr<T> m_pointer;
+};
+
+/********************************************************
+ *        The implementation of the PValue 
+ *          class template methods.
+ ********************************************************/
+
+
+template <typename T>
+PValue 
+PValue::Create (void)
+{
+  return PValue (new T ());
+}
+template <typename T, typename T1>
+PValue 
+PValue::Create (T1 a1)
+{
+  return PValue (new T (a1));
+}
+
+template <typename T>
+T
+PValue::DynCast (void) const
+{
+  return dynamic_cast<T> (m_value);
+}
+
+template <typename T>
+PValue::PValue (Ptr<T> pointer)
+  : m_value (new PtrValue<T> (pointer))
+{}
+template <typename T>
+PValue::operator Ptr<T> ()
+{
+  PtrValueBase *value = DynCast<PtrValueBase *> ();
+  if (value == 0)
+    {
+      return 0;
+    }
+  ObjectBase *objectBase = value->PeekObjectBase ();
+  T *obj = dynamic_cast<T *> (objectBase);
+  if (obj == 0)
+    {
+      return 0;
+    }
+  return obj;
+}
+
+/********************************************************
+ *              The ParamSpec associated to 
+ *               PtrValue<T>
+ ********************************************************/
+
+template <typename T, typename U>
+class PtrParamSpec : public ParamSpec
+{
+public:
+  virtual ~PtrParamSpec () {}
+  virtual bool Set (ObjectBase * object, PValue val) const {
+      T *obj = dynamic_cast<T *> (object);
+      if (obj == 0)
+        {
+          return false;
+        }
+      const PtrValueBase *value = val.DynCast<const PtrValueBase *> ();
+      if (value == 0)
+        {
+          return false;
+        }
+      Ptr<U> ptr = dynamic_cast<U*> (value->PeekObjectBase ());
+      if (ptr == 0)
+        {
+          return false;
+        }
+      DoSet (obj, ptr);
+      return true;
+    }
+    virtual bool Get (const ObjectBase * object, PValue val) const {
+      const T *obj = dynamic_cast<const T *> (object);
+      if (obj == 0)
+        {
+          return false;
+        }
+      PtrValueBase *value = val.DynCast<PtrValueBase *> ();
+      if (value == 0)
+        {
+          return false;
+        }
+      return value->SetObjectBase (PeekPointer (DoGet (obj)));
+    }
+    virtual bool Check (PValue val) const {
+      const PtrValueBase *value = val.DynCast<const PtrValueBase *> ();
+      if (value == 0)
+        {
+          return false;
+        }
+      if (value->PeekObjectBase () == 0)
+        {
+          return true;
+        }
+      U *ptr = dynamic_cast<U*> (value->PeekObjectBase ());
+      if (ptr == 0)
+        {
+          return false;
+        }
+      return true;
+    }
+    virtual PValue CreateInitialValue (void) const {
+      return PValue::Create<PtrValue<U> > (Ptr<U> (0));
+    }
+private:
+  virtual void DoSet (T *object, Ptr<U> value) const = 0;
+  virtual Ptr<U> DoGet (const T *object) const = 0;
+};
+
+
+template <typename T, typename U>
+Ptr<const ParamSpec>
+MakePtrParamSpec (Ptr<U> T::*memberVariable)
+{
+  struct MemberVariable : public PtrParamSpec<T,U>
+  {
+    Ptr<U> T::*m_memberVariable;
+    virtual MemberVariable *Copy (void) const {
+      return new MemberVariable (*this);
+    }
+    virtual void DoSet (T *object, Ptr<U> value) const {
+      (object->*m_memberVariable) = value;
+    }
+    virtual Ptr<U> DoGet (const T *object) const {
+      return object->*m_memberVariable;
+    }
+  } *spec = new MemberVariable ();
+  spec->m_memberVariable = memberVariable;
+  return Ptr<const ParamSpec> (spec, false);
+}
+
+template <typename T, typename U>
+Ptr<const ParamSpec>
+MakePtrParamSpec (void (T::*setter) (Ptr<U>))
+{
+  struct MemberMethod : public PtrParamSpec<T,U>
+  {
+    void (T::*m_setter) (Ptr<U>);
+    virtual MemberMethod *Copy (void) const {
+      return new MemberMethod (*this);
+    }
+    virtual void DoSet (T *object, Ptr<U> value) const {
+      (object->*m_setter) (value);
+    }
+    virtual Ptr<U> DoGet (const T *object) const {
+      return 0;
+      //return (object->*m_getter) ();
+    }
+  } *spec = new MemberMethod ();
+  spec->m_setter = setter;
+  return Ptr<const ParamSpec> (spec, false);
+}
+
+template <typename T, typename U>
+Ptr<const ParamSpec>
+MakePtrParamSpec (Ptr<U> (T::*getter) (void) const)
+{
+  struct MemberMethod : public PtrParamSpec<T,U>
+  {
+    void (T::*m_getter) (Ptr<U>);
+    virtual MemberMethod *Copy (void) const {
+      return new MemberMethod (*this);
+    }
+    virtual void DoSet (T *object, Ptr<U> value) const {
+      //(object->*m_setter) (value);
+    }
+    virtual Ptr<U> DoGet (const T *object) const {
+      return (object->*m_getter) ();
+    }
+  } *spec = new MemberMethod ();
+  spec->m_getter = getter;
+  return Ptr<const ParamSpec> (spec, false);
+}
+
 } // namespace ns3
 
 #endif /* VALUE_H */
--- a/src/core/wscript	Wed Jan 30 19:13:21 2008 +0100
+++ b/src/core/wscript	Thu Jan 31 15:10:21 2008 +0100
@@ -54,7 +54,6 @@
         'array-trace-resolver.cc',
         'type-id-default-value.cc',
         'value.cc',
-        'param-spec.cc',
         'boolean-value.cc',
         'value-test.cc',
         ]
@@ -102,6 +101,5 @@
         'int-to-type.h',
         'type-id-default-value.h',
         'value.h',
-        'param-spec.h',
         ]