--- a/src/core/object.cc Wed Jan 30 17:28:18 2008 +0100
+++ b/src/core/object.cc Wed Jan 30 19:13:06 2008 +0100
@@ -22,8 +22,11 @@
#include "assert.h"
#include "singleton.h"
#include "trace-resolver.h"
+#include "value.h"
+#include "param-spec.h"
#include "log.h"
#include <vector>
+#include <sstream>
NS_LOG_COMPONENT_DEFINE ("Object");
@@ -36,25 +39,51 @@
class IidManager
{
public:
+ IidManager ();
uint16_t AllocateUid (std::string name);
void SetParent (uint16_t uid, uint16_t parent);
+ void SetTypeName (uint16_t uid, std::string typeName);
+ void SetGroupName (uint16_t uid, std::string groupName);
void AddConstructor (uint16_t uid, ns3::CallbackBase callback, uint32_t nArguments);
uint16_t GetUid (std::string name) const;
std::string GetName (uint16_t uid) const;
uint16_t GetParent (uint16_t uid) const;
+ std::string GetTypeName (uint16_t uid) const;
+ std::string GetGroupName (uint16_t uid) const;
ns3::CallbackBase GetConstructor (uint16_t uid, uint32_t nArguments);
bool HasConstructor (uint16_t uid);
uint32_t GetRegisteredN (void);
uint16_t GetRegistered (uint32_t i);
+ void AddParameter (uint16_t uid,
+ std::string name,
+ std::string help,
+ uint32_t flags,
+ ns3::Ptr<const ns3::ParamSpec> spec);
+ 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:
struct ConstructorInformation {
ns3::CallbackBase cb;
uint32_t nArguments;
};
+ struct ParameterInformation {
+ std::string name;
+ std::string help;
+ uint32_t flags;
+ uint32_t uid;
+ ns3::Ptr<const ns3::ParamSpec> param;
+ };
struct IidInformation {
std::string name;
uint16_t parent;
+ std::string typeName;
+ std::string groupName;
std::vector<struct ConstructorInformation> constructors;
+ std::vector<struct ParameterInformation> parameters;
};
typedef std::vector<struct IidInformation>::const_iterator Iterator;
@@ -63,6 +92,9 @@
std::vector<struct IidInformation> m_information;
};
+IidManager::IidManager ()
+{}
+
uint16_t
IidManager::AllocateUid (std::string name)
{
@@ -79,6 +111,8 @@
struct IidInformation information;
information.name = name;
information.parent = 0;
+ information.typeName = "";
+ information.groupName = "";
m_information.push_back (information);
uint32_t uid = m_information.size ();
NS_ASSERT (uid <= 0xffff);
@@ -100,6 +134,19 @@
information->parent = parent;
}
void
+IidManager::SetTypeName (uint16_t uid, std::string typeName)
+{
+ struct IidInformation *information = LookupInformation (uid);
+ information->typeName = typeName;
+}
+void
+IidManager::SetGroupName (uint16_t uid, std::string groupName)
+{
+ struct IidInformation *information = LookupInformation (uid);
+ information->groupName = groupName;
+}
+
+void
IidManager::AddConstructor (uint16_t uid, ns3::CallbackBase callback, uint32_t nArguments)
{
struct IidInformation *information = LookupInformation (uid);
@@ -145,6 +192,19 @@
struct IidInformation *information = LookupInformation (uid);
return information->parent;
}
+std::string
+IidManager::GetTypeName (uint16_t uid) const
+{
+ struct IidInformation *information = LookupInformation (uid);
+ return information->typeName;
+}
+std::string
+IidManager::GetGroupName (uint16_t uid) const
+{
+ struct IidInformation *information = LookupInformation (uid);
+ return information->groupName;
+}
+
ns3::CallbackBase
IidManager::GetConstructor (uint16_t uid, uint32_t nArguments)
{
@@ -179,6 +239,60 @@
return i + 1;
}
+void
+IidManager::AddParameter (uint16_t uid,
+ std::string name,
+ std::string help,
+ uint32_t flags,
+ ns3::Ptr<const ns3::ParamSpec> spec)
+{
+ struct IidInformation *information = LookupInformation (uid);
+ for (std::vector<struct ParameterInformation>::const_iterator j = information->parameters.begin ();
+ j != information->parameters.end (); j++)
+ {
+ if (j->name == name)
+ {
+ NS_FATAL_ERROR ("Registered the same parameter twice name=\""<<name<<"\" in TypeId=\""<<information->name<<"\"");
+ return;
+ }
+ }
+ struct ParameterInformation param;
+ param.name = name;
+ param.help = help;
+ param.flags = flags;
+ param.param = spec;
+ information->parameters.push_back (param);
+}
+
+
+uint32_t
+IidManager::GetParametersN (uint16_t uid) const
+{
+ struct IidInformation *information = LookupInformation (uid);
+ return information->parameters.size ();
+}
+std::string
+IidManager::GetParameterName (uint16_t uid, uint32_t i) const
+{
+ struct IidInformation *information = LookupInformation (uid);
+ NS_ASSERT (i < information->parameters.size ());
+ return information->parameters[i].name;
+}
+uint32_t
+IidManager::GetParameterFlags (uint16_t uid, uint32_t i) const
+{
+ struct IidInformation *information = LookupInformation (uid);
+ NS_ASSERT (i < information->parameters.size ());
+ return information->parameters[i].flags;
+}
+ns3::Ptr<const ns3::ParamSpec>
+IidManager::GetParameterParamSpec (uint16_t uid, uint32_t i) const
+{
+ struct IidInformation *information = LookupInformation (uid);
+ NS_ASSERT (i < information->parameters.size ());
+ return information->parameters[i].param;
+}
+
} // anonymous namespace
@@ -273,6 +387,19 @@
NS_ASSERT (uid != 0);
return TypeId (uid);
}
+Ptr<const ParamSpec>
+TypeId::LookupParamSpecByFullName (std::string fullName)
+{
+ std::string::size_type pos = fullName.find ("::");
+ if (pos == std::string::npos)
+ {
+ return 0;
+ }
+ std::string tidName = fullName.substr (0, pos);
+ std::string paramName = fullName.substr (pos+2, fullName.size () - (pos+2));
+ TypeId tid = LookupByName (tidName);
+ return tid.LookupParamSpecByName (paramName);
+}
uint32_t
TypeId::GetRegisteredN (void)
{
@@ -284,6 +411,41 @@
return TypeId (Singleton<IidManager>::Get ()->GetRegistered (i));
}
+Ptr<const ParamSpec>
+TypeId::LookupParamSpecByName (std::string name) const
+{
+ for (uint32_t i = 0; i < GetParametersN (); i++)
+ {
+ std::string paramName = GetParameterName (i);
+ if (paramName == name)
+ {
+ return GetParameterParamSpec (i);
+ }
+ }
+ return 0;
+}
+Ptr<const ParamSpec>
+TypeId::LookupParamSpecByPosition (uint32_t i) const
+{
+ uint32_t cur = 0;
+ TypeId tid = TypeId (0);
+ TypeId nextTid = *this;
+ do {
+ tid = nextTid;
+ for (uint32_t j = 0; j < tid.GetParametersN (); j++)
+ {
+ if (cur == i)
+ {
+ return tid.GetParameterParamSpec (j);
+ }
+ cur++;
+ }
+ nextTid = tid.GetParent ();
+ } while (nextTid != tid);
+ return 0;
+}
+
+
TypeId
TypeId::SetParent (TypeId tid)
{
@@ -291,12 +453,37 @@
return *this;
}
TypeId
+TypeId::SetGroupName (std::string groupName)
+{
+ Singleton<IidManager>::Get ()->SetGroupName (m_tid, groupName);
+ return *this;
+}
+TypeId
+TypeId::SetTypeName (std::string typeName)
+{
+ Singleton<IidManager>::Get ()->SetTypeName (m_tid, typeName);
+ return *this;
+}
+TypeId
TypeId::GetParent (void) const
{
uint16_t parent = Singleton<IidManager>::Get ()->GetParent (m_tid);
return TypeId (parent);
}
std::string
+TypeId::GetGroupName (void) const
+{
+ std::string groupName = Singleton<IidManager>::Get ()->GetGroupName (m_tid);
+ return groupName;
+}
+std::string
+TypeId::GetTypeName (void) const
+{
+ std::string typeName = Singleton<IidManager>::Get ()->GetTypeName (m_tid);
+ return typeName;
+}
+
+std::string
TypeId::GetName (void) const
{
std::string name = Singleton<IidManager>::Get ()->GetName (m_tid);
@@ -316,22 +503,73 @@
Singleton<IidManager>::Get ()->AddConstructor (m_tid, cb, nArguments);
}
+TypeId
+TypeId::AddParameter (std::string name,
+ std::string help,
+ Ptr<const ParamSpec> param)
+{
+ Singleton<IidManager>::Get ()->AddParameter (m_tid, name, help, 0, param);
+ return *this;
+}
+
+TypeId
+TypeId::AddParameter (std::string name,
+ std::string help,
+ uint32_t flags,
+ Ptr<const ParamSpec> param)
+{
+ Singleton<IidManager>::Get ()->AddParameter (m_tid, name, help, flags, param);
+ return *this;
+}
+
+
CallbackBase
-TypeId::LookupConstructor (uint32_t nArguments)
+TypeId::LookupConstructor (uint32_t nArguments) const
{
CallbackBase constructor = Singleton<IidManager>::Get ()->GetConstructor (m_tid, nArguments);
return constructor;
}
Ptr<Object>
-TypeId::CreateObject (void)
+TypeId::CreateObject (void) const
+{
+ return CreateObject (Parameters ());
+}
+Ptr<Object>
+TypeId::CreateObject (const Parameters ¶meters) const
{
CallbackBase cb = LookupConstructor (0);
- Callback<Ptr<Object> > realCb;
+ Callback<Ptr<Object>,const Parameters &> realCb;
realCb.Assign (cb);
- Ptr<Object> object = realCb ();
- return object;
+ Ptr<Object> object = realCb (parameters);
+ return object;
+}
+
+uint32_t
+TypeId::GetParametersN (void) const
+{
+ uint32_t n = Singleton<IidManager>::Get ()->GetParametersN (m_tid);
+ return n;
}
+std::string
+TypeId::GetParameterName (uint32_t i) const
+{
+ std::string name = Singleton<IidManager>::Get ()->GetParameterName (m_tid, i);
+ return name;
+}
+std::string
+TypeId::GetParameterFullName (uint32_t i) const
+{
+ return GetName () + "::" + GetParameterName (i);
+}
+Ptr<const ParamSpec>
+TypeId::GetParameterParamSpec (uint32_t i) const
+{
+ // Used exclusively by the Object class.
+ Ptr<const ParamSpec> param = Singleton<IidManager>::Get ()->GetParameterParamSpec (m_tid, i);
+ return param;
+}
+
bool operator == (TypeId a, TypeId b)
{
@@ -344,6 +582,236 @@
}
/*********************************************************************
+ * The Parameters container implementation
+ *********************************************************************/
+
+Parameters::Parameters ()
+{}
+
+Parameters::Parameters (const Parameters &o)
+{
+ for (Params::const_iterator i = o.m_parameters.begin (); i != o.m_parameters.end (); i++)
+ {
+ struct Param param;
+ param.spec = i->spec;
+ param.value = i->value->Copy ();
+ m_parameters.push_back (param);
+ }
+}
+Parameters &
+Parameters::operator = (const Parameters &o)
+{
+ Reset ();
+ for (Params::const_iterator i = o.m_parameters.begin (); i != o.m_parameters.end (); i++)
+ {
+ struct Param param;
+ param.spec = i->spec;
+ param.value = i->value->Copy ();
+ m_parameters.push_back (param);
+ }
+ return *this;
+}
+Parameters::~Parameters ()
+{
+ Reset ();
+}
+
+bool
+Parameters::Set (std::string name, Ptr<const Value> value)
+{
+ Ptr<const ParamSpec> spec = TypeId::LookupParamSpecByFullName (name);
+ bool ok = DoSet (spec, value);
+ return ok;
+}
+bool
+Parameters::Set (std::string name, std::string value)
+{
+ Ptr<const ParamSpec> spec = TypeId::LookupParamSpecByFullName (name);
+ bool ok = DoSet (spec,value);
+ return ok;
+}
+void
+Parameters::SetWithTid (TypeId tid, std::string name, std::string value)
+{
+ Ptr<const ParamSpec> spec = tid.LookupParamSpecByName (name);
+ DoSet (spec, value);
+}
+void
+Parameters::SetWithTid (TypeId tid, std::string name, Ptr<const Value> value)
+{
+ Ptr<const ParamSpec> spec = tid.LookupParamSpecByName (name);
+ DoSet (spec, value);
+}
+void
+Parameters::SetWithTid (TypeId tid, uint32_t position, std::string value)
+{
+ Ptr<const ParamSpec> spec = tid.LookupParamSpecByPosition (position);
+ DoSet (spec, value);
+}
+void
+Parameters::SetWithTid (TypeId tid, uint32_t position, Ptr<const Value> value)
+{
+ Ptr<const ParamSpec> spec = tid.LookupParamSpecByPosition (position);
+ DoSet (spec, value);
+}
+
+void
+Parameters::DoSetOne (Ptr<const ParamSpec> spec, Ptr<const Value> value)
+{
+ // get rid of any previous value stored in this
+ // vector of values.
+ for (Params::iterator k = m_parameters.begin (); k != m_parameters.end (); k++)
+ {
+ if (k->spec == spec)
+ {
+ m_parameters.erase (k);
+ break;
+ }
+ }
+ // store the new value.
+ struct Param p;
+ p.spec = spec;
+ p.value = value->Copy ();
+ m_parameters.push_back (p);
+}
+bool
+Parameters::DoSet (Ptr<const ParamSpec> spec, Ptr<const Value> value)
+{
+ if (spec == 0)
+ {
+ return false;
+ }
+ bool ok = spec->Check (value);
+ if (!ok)
+ {
+ return false;
+ }
+ DoSetOne (spec, value);
+ return true;
+}
+bool
+Parameters::DoSet (Ptr<const ParamSpec> spec, std::string value)
+{
+ if (spec == 0)
+ {
+ return false;
+ }
+ Ptr<Value> v = spec->CreateInitialValue ();
+ bool ok = v->DeserializeFromString (value, spec);
+ if (!ok)
+ {
+ return false;
+ }
+ ok = spec->Check (v);
+ if (!ok)
+ {
+ return false;
+ }
+ DoSetOne (spec, v);
+ return true;
+}
+void
+Parameters::Reset (void)
+{
+ m_parameters.clear ();
+}
+Parameters *
+Parameters::GetGlobal (void)
+{
+ return Singleton<Parameters>::Get ();
+}
+
+std::string
+Parameters::LookupParameterFullNameByParamSpec (Ptr<const ParamSpec> spec) const
+{
+ for (uint32_t i = 0; i < TypeId::GetRegisteredN (); i++)
+ {
+ TypeId tid = TypeId::GetRegistered (i);
+ for (uint32_t j = 0; j < tid.GetParametersN (); j++)
+ {
+ if (spec == tid.GetParameterParamSpec (j))
+ {
+ return tid.GetParameterFullName (j);
+ }
+ }
+ }
+ NS_FATAL_ERROR ("Could not find requested ParamSpec.");
+ // quiet compiler.
+ return "";
+}
+
+std::string
+Parameters::SerializeToString (void) const
+{
+ std::ostringstream oss;
+ 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));
+ if (i != m_parameters.end ())
+ {
+ oss << "|";
+ }
+ }
+ return oss.str ();
+}
+bool
+Parameters::DeserializeFromString (std::string str)
+{
+ Reset ();
+
+ std::string::size_type cur;
+ cur = 0;
+ do {
+ std::string::size_type equal = str.find ("=", cur);
+ if (equal == std::string::npos)
+ {
+ // XXX: invalid parameter.
+ break;
+ }
+ else
+ {
+ std::string name = str.substr (cur, equal-cur);
+ Ptr<const ParamSpec> spec = TypeId::LookupParamSpecByFullName (name);
+ if (spec == 0)
+ {
+ // XXX invalid name.
+ break;
+ }
+ else
+ {
+ std::string::size_type next = str.find ("|", cur);
+ std::string value;
+ if (next == std::string::npos)
+ {
+ value = str.substr (equal+1, str.size () - (equal+1));
+ cur = str.size ();
+ }
+ else
+ {
+ value = str.substr (equal+1, next - (equal+1));
+ cur++;
+ }
+ Ptr<Value> val = spec->CreateInitialValue ();
+ bool ok = val->DeserializeFromString (value, spec);
+ if (!ok)
+ {
+ // XXX invalid value
+ break;
+ }
+ else
+ {
+ DoSetOne (spec, val);
+ }
+ }
+ }
+ } while (cur != str.size ());
+
+ return true;
+}
+
+
+/*********************************************************************
* The Object implementation
*********************************************************************/
@@ -376,6 +844,152 @@
{
m_next = 0;
}
+void
+Object::Construct (const Parameters ¶meters)
+{
+ // loop over the inheritance tree back to the Object base class.
+ TypeId tid = m_tid;
+ do {
+ // loop over all parameters in object type
+ NS_LOG_DEBUG ("construct tid="<<tid.GetName ()<<", params="<<tid.GetParametersN ());
+ for (uint32_t i = 0; i < tid.GetParametersN (); i++)
+ {
+ Ptr<const ParamSpec> paramSpec = tid.GetParameterParamSpec (i);
+ NS_LOG_DEBUG ("try to construct \""<< tid.GetName ()<<"::"<<
+ tid.GetParameterName (i)<<"\"");
+ bool found = false;
+ // is this parameter stored in this Parameters instance ?
+ for (Parameters::Params::const_iterator j = parameters.m_parameters.begin ();
+ j != parameters.m_parameters.end (); j++)
+ {
+ if (j->spec == paramSpec)
+ {
+ // We have a matching parameter value.
+ paramSpec->Set (this, j->value);
+ NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
+ tid.GetParameterName (i)<<"\"");
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ // is this parameter stored in the global instance instance ?
+ for (Parameters::Params::const_iterator j = Parameters::GetGlobal ()->m_parameters.begin ();
+ j != Parameters::GetGlobal ()->m_parameters.end (); j++)
+ {
+ if (j->spec == paramSpec)
+ {
+ // We have a matching parameter value.
+ paramSpec->Set (this, j->value);
+ NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
+ tid.GetParameterName (i)<<"\" from global");
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found)
+ {
+ // No matching parameter value so we set the default value.
+ Ptr<Value> initial = paramSpec->CreateInitialValue ();
+ paramSpec->Set (this, initial);
+ NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
+ tid.GetParameterName (i)<<"\" from local");
+ }
+ }
+ tid = tid.GetParent ();
+ } while (tid != Object::GetTypeId ());
+ NotifyConstructionCompleted ();
+}
+bool
+Object::DoSet (std::string name, Ptr<const Value> value)
+{
+ Ptr<const ParamSpec> spec = m_tid.LookupParamSpecByName (name);
+ if (spec == 0)
+ {
+ return false;
+ }
+ bool ok = spec->Set (this, value);
+ if (!ok)
+ {
+ return false;
+ }
+ return true;
+}
+bool
+Object::Set (std::string name, Ptr<const Value> value)
+{
+ return DoSet (name, value);
+}
+bool
+Object::Set (std::string name, std::string value)
+{
+ Ptr<const ParamSpec> spec = m_tid.LookupParamSpecByName (name);
+ if (spec == 0)
+ {
+ return false;
+ }
+ Ptr<Value> parameter = spec->CreateInitialValue ();
+ bool ok = parameter->DeserializeFromString (value, spec);
+ if (!ok)
+ {
+ return false;
+ }
+ spec->Set (this, parameter);
+ if (!ok)
+ {
+ return false;
+ }
+ return true;
+}
+bool
+Object::Get (std::string name, std::string &value) const
+{
+ Ptr<const ParamSpec> paramSpec = m_tid.LookupParamSpecByName (name);
+ if (paramSpec == 0)
+ {
+ return false;
+ }
+ Ptr<Value> parameter = paramSpec->CreateInitialValue ();
+ bool ok = paramSpec->Get (this, parameter);
+ if (ok)
+ {
+ value = parameter->SerializeToString (paramSpec);
+ }
+ return ok;
+}
+
+Ptr<const Value>
+Object::Get (std::string name) const
+{
+ Ptr<const ParamSpec> paramSpec = m_tid.LookupParamSpecByName (name);
+ if (paramSpec == 0)
+ {
+ return 0;
+ }
+ Ptr<Value> value = paramSpec->CreateInitialValue ();
+ bool ok = paramSpec->Get (this, value);
+ if (!ok)
+ {
+ return 0;
+ }
+ return value;
+}
+
+bool
+Object::DoGet (std::string name, Ptr<Value> parameter) const
+{
+ Ptr<const ParamSpec> paramSpec = m_tid.LookupParamSpecByName (name);
+ if (paramSpec == 0)
+ {
+ return false;
+ }
+ bool ok = paramSpec->Get (this, parameter);
+ return ok;
+}
+
+
Ptr<Object>
Object::DoQueryInterface (TypeId tid) const
{
@@ -408,7 +1022,9 @@
current = current->m_next;
} while (current != this);
}
-
+void
+Object::NotifyConstructionCompleted (void)
+{}
void
Object::AddInterface (Ptr<Object> o)
{
@@ -619,10 +1235,10 @@
static ns3::TypeId GetTypeId (void) {
static ns3::TypeId tid = ns3::TypeId ("DerivedA")
.SetParent (BaseA::GetTypeId ())
- .AddConstructor<DerivedA,int> ();
+ .AddConstructor<DerivedA> ();
return tid;
}
- DerivedA (int v)
+ DerivedA ()
{}
void DerivedGenerateTrace (int16_t v)
{ m_sourceDerived = v; }
@@ -671,13 +1287,10 @@
static ns3::TypeId GetTypeId (void) {
static ns3::TypeId tid = ns3::TypeId ("DerivedB")
.SetParent (BaseB::GetTypeId ())
- .AddConstructor<DerivedB,int> ()
- .AddConstructor<DerivedB,int,int &> ();
+ .AddConstructor<DerivedB> ();
return tid;
}
- DerivedB (int v)
- {}
- DerivedB (int v1, int &v2)
+ DerivedB ()
{}
void DerivedGenerateTrace (int16_t v)
{ m_sourceDerived = v; }
@@ -754,7 +1367,7 @@
NS_TEST_ASSERT_EQUAL (baseA->QueryInterface<BaseA> (), baseA);
NS_TEST_ASSERT_EQUAL (baseA->QueryInterface<BaseA> (DerivedA::GetTypeId ()), 0);
NS_TEST_ASSERT_EQUAL (baseA->QueryInterface<DerivedA> (), 0);
- baseA = CreateObject<DerivedA> (10);
+ baseA = CreateObject<DerivedA> ();
NS_TEST_ASSERT_EQUAL (baseA->QueryInterface<BaseA> (), baseA);
NS_TEST_ASSERT_EQUAL (baseA->QueryInterface<BaseA> (DerivedA::GetTypeId ()), baseA);
NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface<DerivedA> (), 0);
@@ -773,8 +1386,8 @@
NS_TEST_ASSERT_EQUAL (baseB->QueryInterface<DerivedA> (), 0);
NS_TEST_ASSERT_UNEQUAL (baseBCopy->QueryInterface<BaseA> (), 0);
- baseA = CreateObject<DerivedA> (1);
- baseB = CreateObject<DerivedB> (1);
+ baseA = CreateObject<DerivedA> ();
+ baseB = CreateObject<DerivedB> ();
baseBCopy = baseB;
baseA->AddInterface (baseB);
NS_TEST_ASSERT_UNEQUAL (baseA->QueryInterface<DerivedB> (), 0);
@@ -836,7 +1449,7 @@
baseA->TraceDisconnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
Ptr<DerivedA> derivedA;
- derivedA = CreateObject<DerivedA> (1);
+ derivedA = CreateObject<DerivedA> ();
baseB = CreateObject<BaseB> ();
derivedA->AddInterface (baseB);
baseB->TraceConnect ("/$DerivedA/deriveda-x", MakeCallback (&ObjectTest::DerivedATrace, this));
@@ -866,7 +1479,7 @@
NS_TEST_ASSERT_EQUAL (a->QueryInterface<BaseA> (), a);
NS_TEST_ASSERT_EQUAL (a->QueryInterface<BaseA> (DerivedA::GetTypeId ()), 0);
NS_TEST_ASSERT_EQUAL (a->QueryInterface<DerivedA> (), 0);
- a = DerivedA::GetTypeId ().CreateObject (10);
+ a = DerivedA::GetTypeId ().CreateObject ();
NS_TEST_ASSERT_EQUAL (a->QueryInterface<BaseA> (), a);
NS_TEST_ASSERT_EQUAL (a->QueryInterface<BaseA> (DerivedA::GetTypeId ()), a);
NS_TEST_ASSERT_UNEQUAL (a->QueryInterface<DerivedA> (), 0);
--- a/src/core/object.h Wed Jan 30 17:28:18 2008 +0100
+++ b/src/core/object.h Wed Jan 30 19:13:06 2008 +0100
@@ -26,13 +26,14 @@
#include "ptr.h"
#include "trace-resolver.h"
#include "callback.h"
-#include "empty.h"
+#include "value.h"
+#include "object-base.h"
#define NS_OBJECT_ENSURE_REGISTERED(type) \
static struct X##type##RegistrationClass \
{ \
X##type##RegistrationClass () { \
- ns3::TypeId tid = type::GetTypeId (); \
+ ns3::TypeId tid = type::GetTypeId (); \
tid.GetParent (); \
} \
} x_##type##RegistrationVariable
@@ -43,14 +44,32 @@
class TraceContext;
class CallbackBase;
class Object;
+class ParamSpec;
+class Value;
+class Parameters;
/**
* \brief a unique identifier for an interface.
*
+ * This class records a lot of meta-information about a
+ * subclass of the Object base class:
+ * - the base class of the subclass
+ * - the set of accessible constructors in the subclass
+ * - the set of 'parameters' accessible in the subclass
*/
class TypeId
{
public:
+ enum {
+ PARAM_READ = 1<<0,
+ PARAM_WRITE = 1<<1,
+ PARAM_CONSTRUCT = 1<<2,
+ PARAM_RWC = PARAM_READ | PARAM_WRITE | PARAM_CONSTRUCT,
+ PARAM_NO_READ = 0,
+ PARAM_NO_WRITE = 0,
+ PARAM_NO_CONSTRUCT = 0,
+ };
+
/**
* \param name the name of the requested interface
* \returns the unique id associated with the requested
@@ -60,11 +79,26 @@
* name is not a valid interface name.
*/
static TypeId LookupByName (std::string name);
+
+ /**
+ * \returns the number of TypeId instances constructed
+ */
static uint32_t GetRegisteredN (void);
- static TypeId GetRegistered (uint32_t i);
/**
- * \param tid a unique id
- * \returns the parent of the requested id
+ * \param i index
+ * \returns the TypeId instance whose index is \i.
+ */
+ static TypeId GetRegistered (uint32_t i);
+
+ /**
+ * \param name the name of the interface to construct.
+ *
+ * No two instances can share the same name.
+ */
+ TypeId (std::string name);
+
+ /**
+ * \returns the parent of this TypeId
*
* This method cannot fail: it will crash if the input
* id is not a valid interface id.
@@ -72,6 +106,15 @@
TypeId GetParent (void) const;
/**
+ * \returns the name of the group associated to this TypeId.
+ */
+ std::string GetGroupName (void) const;
+ /**
+ * \returns the fully-qualified C++ typename of this TypeId.
+ */
+ std::string GetTypeName (void) const;
+
+ /**
* \returns the name of this interface.
*/
std::string GetName (void) const;
@@ -81,56 +124,219 @@
*/
bool HasConstructor (void) const;
- TypeId (std::string);
+ /**
+ * \returns the number of parameters associated to this TypeId
+ */
+ uint32_t GetParametersN (void) const;
+ /**
+ * \param i index into parameter array
+ * \returns the name associated to the parameter whose
+ * index is \i i.
+ */
+ std::string GetParameterName (uint32_t i) const;
+ /**
+ * \param i index into parameter array
+ * \returns the full name associated to the parameter whose
+ * index is \i i.
+ */
+ std::string GetParameterFullName (uint32_t i) const;
+ /**
+ * \param i index into parameter array
+ * \param value the value to validate
+ * \returns true if the input value is a valid value
+ * associated to the parameter whose index is \i i.
+ */
+ bool CheckParameterValue (uint32_t i, std::string value) const;
+ Ptr<Object> CreateObject (const Parameters ¶meters) const;
+
+
+ Ptr<Object> CreateObject (void) const;
+ template <typename T1>
+ Ptr<Object> CreateObject (T1 a1) const;
+ template <typename T1, typename T2>
+ Ptr<Object> CreateObject (T1 a1, T2 a2) const;
+
+
+ /**
+ * \param tid the TypeId of the base class.
+ * \return this TypeId instance.
+ *
+ * Record in this TypeId which TypeId is the TypeId
+ * of the base class of the subclass.
+ */
TypeId SetParent (TypeId tid);
+ /**
+ * \return this TypeId instance.
+ *
+ * Record in this TypeId which TypeId is the TypeId
+ * of the base class of the subclass.
+ */
template <typename T>
TypeId SetParent (void);
+ /**
+ * \param groupName the name of the group this TypeId belongs to.
+ * \returns this TypeId instance.
+ *
+ * The group name is purely an advisory information used to
+ * group together types according to a user-specific grouping
+ * scheme.
+ */
+ TypeId SetGroupName (std::string groupName);
+
+ /**
+ * \param typeName the fully-qualified C++ typename of this TypeId.
+ * \returns this TypeId instance.
+ */
+ TypeId SetTypeName (std::string typeName);
+
+ /**
+ * \returns this TypeId instance
+ *
+ * Record in this TypeId the fact that the default constructor
+ * is accessible.
+ */
template <typename T>
TypeId AddConstructor (void);
+
template <typename T, typename T1>
TypeId AddConstructor (void);
- template <typename T, typename T1, typename T2>
- TypeId AddConstructor (void);
- template <typename T, typename T1, typename T2, typename T3>
- TypeId AddConstructor (void);
- template <typename T, typename T1, typename T2, typename T3, typename T4>
- TypeId AddConstructor (void);
- template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
- TypeId AddConstructor (void);
+ template <typename T, typename T1, typename T2>
+ TypeId AddConstructor (void);
- Ptr<Object> CreateObject (void);
- template <typename T1>
- Ptr<Object> CreateObject (T1 a1);
- template <typename T1, typename T2>
- Ptr<Object> CreateObject (T1 a1, T2 a2);
- template <typename T1, typename T2, typename T3>
- Ptr<Object> CreateObject (T1 a1, T2 a2, T3 a3);
- template <typename T1, typename T2, typename T3, typename T4>
- Ptr<Object> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4);
- template <typename T1, typename T2, typename T3, typename T4, typename T5>
- Ptr<Object> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
+ /**
+ * \param name the name of the new parameter
+ * \param help some help text which describes the purpose of this
+ * parameter
+ * \param param an instance of the associated ParamSpec subclass
+ * \returns this TypeId instance
+ *
+ * Record in this TypeId the fact that a new parameter exists.
+ */
+ TypeId AddParameter (std::string name,
+ std::string help, Ptr<const ParamSpec> spec);
+
+ /**
+ * \param name the name of the new parameter
+ * \param help some help text which describes the purpose of this
+ * parameter
+ * \param flags flags which describe how this parameter can be read and/or written.
+ * \param param an instance of the associated ParamSpec subclass
+ * \returns this TypeId instance
+ *
+ * Record in this TypeId the fact that a new parameter exists.
+ */
+ TypeId AddParameter (std::string name,
+ std::string help,
+ uint32_t flags,
+ Ptr<const ParamSpec> spec);
~TypeId ();
private:
+ friend class Object;
+ friend class Parameters;
friend bool operator == (TypeId a, TypeId b);
friend bool operator != (TypeId a, TypeId b);
+ /**
+ * \param name the name of the requested parameter
+ * \returns the ParamSpec associated to the requested parameter
+ */
+ Ptr<const ParamSpec> LookupParamSpecByName (std::string name) const;
+ /**
+ * \param i the position of the requested parameter
+ * \returns the ParamSpec associated to the requested parameter
+ */
+ Ptr<const ParamSpec> LookupParamSpecByPosition (uint32_t i) const;
+ /**
+ * \param fullName the full name of the requested parameter
+ * \returns the ParamSpec associated to the requested parameter
+ */
+ static Ptr<const ParamSpec> LookupParamSpecByFullName (std::string fullName);
+
explicit TypeId (uint16_t tid);
void DoAddConstructor (CallbackBase callback, uint32_t nArguments);
- CallbackBase LookupConstructor (uint32_t nArguments);
+ CallbackBase LookupConstructor (uint32_t nArguments) const;
+ Ptr<const ParamSpec> GetParameterParamSpec (uint32_t i) const;
uint16_t m_tid;
};
+
+/**
+ * \brief a container of parameters to be used during object's construction
+ * and in ns3::Object::Set.
+ *
+ */
+class Parameters
+{
+public:
+ Parameters ();
+ Parameters (const Parameters &o);
+ Parameters &operator = (const Parameters &o);
+ ~Parameters ();
+ /**
+ * \param name the name of the parameter to set
+ * \param value the value to set
+ *
+ * This method checks that a parameter with the requested
+ * name exists and that the value specified is an acceptable
+ * value of that parameter. If any of these checks fails,
+ * the program terminates with a message.
+ */
+ bool Set (std::string name, std::string value);
+ bool Set (std::string name, Ptr<const Value> 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, uint32_t position, std::string value);
+ void SetWithTid (TypeId tid, uint32_t position, Ptr<const Value> value);
+
+ /**
+ * Clear the content of this instance.
+ */
+ void Reset (void);
+
+ /**
+ * \returns the global parameter container
+ *
+ * The global parameter container can be used to specify
+ * a set of parameter values without having to re-specify
+ * them for each object when it is created. This container
+ * is checked only during object construction and
+ * it is always checked last, after any per-object
+ * container is checked.
+ */
+ static Parameters *GetGlobal (void);
+
+ std::string SerializeToString (void) const;
+ bool DeserializeFromString (std::string value);
+private:
+ friend class Object;
+ struct Param {
+ Ptr<const ParamSpec> spec;
+ Ptr<const Value> value;
+ };
+ typedef std::vector<struct Param> Params;
+ typedef Params::iterator Iterator;
+ typedef Params::const_iterator CIterator;
+
+
+
+ bool DoSet (Ptr<const ParamSpec> spec, Ptr<const Value> param);
+ bool DoSet (Ptr<const ParamSpec> spec, std::string value);
+ void DoSetOne (Ptr<const ParamSpec> spec, Ptr<const Value> param);
+ std::string LookupParameterFullNameByParamSpec (Ptr<const ParamSpec> spec) const;
+
+ Params m_parameters;
+};
+
+
/**
* \brief a base class which provides memory management and object aggregation
*
- * Note: This base class is quite similar in spirit to IUnknown in COM or
- * BonoboObject in Bonobo: it provides three main methods: Ref, Unref and
- * QueryInterface.
*/
class Object : public ObjectBase
{
@@ -139,6 +345,30 @@
Object ();
virtual ~Object ();
+
+ /**
+ * \param name the name of the parameter to set
+ * \param value the name of the parameter to set
+ *
+ * Set a single parameter.
+ */
+ bool Set (std::string name, std::string value);
+ bool Set (std::string name, Ptr<const Value> value);
+ /**
+ * \param name the name of the parameter to read
+ * \param value a reference to the string where the value of the
+ * parameter should be stored.
+ * \returns true if the requested parameter was found, false otherwise.
+ */
+ bool Get (std::string name, std::string &value) const;
+ /**
+ * \param name the name of the parameter to read
+ * \param value a reference to the object where the value of the
+ * parameter should be stored.
+ * \returns true if the requested parameter was found, false otherwise.
+ */
+ Ptr<const Value> Get (std::string name) const;
+
/**
* Increment the reference count. This method should not be called
* by user code. Object instances are expected to be used in conjunction
@@ -212,8 +442,13 @@
* up to their parent's implementation once they are done.
*/
virtual void DoDispose (void);
+ virtual void NotifyConstructionCompleted (void);
private:
friend class TypeIdTraceResolver;
+
+ template <typename T>
+ friend Ptr<T> CreateObject (const Parameters ¶meters);
+
template <typename T>
friend Ptr<T> CreateObject (void);
template <typename T, typename T1>
@@ -231,57 +466,76 @@
template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
friend Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7);
+
Ptr<Object> DoQueryInterface (TypeId tid) const;
void DoCollectSources (std::string path, const TraceContext &context,
TraceResolver::SourceCollection *collection) const;
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;
+ /**
+ * Attempt to delete this object. This method iterates
+ * over all aggregated objects to check if they all
+ * have a zero refcount. If yes, the object and all
+ * its aggregates are deleted. If not, nothing is done.
+ */
void MaybeDelete (void) const;
/**
* \param tid an TypeId
*
- * Every subclass which defines a new TypeId for itself
- * should register this TypeId by calling this method
- * from its constructor.
+ * Invoked from ns3::CreateObject only.
+ * Initialize the m_tid member variable to
+ * keep track of the type of this object instance.
*/
void SetTypeId (TypeId tid);
+ /**
+ * \param parameters the parameter values used to initialize
+ * the member variables of this object's instance.
+ *
+ * Invoked from ns3::CreateObject only.
+ * Initialize all the member variables which were
+ * registered with the associated TypeId.
+ */
+ void Construct (const Parameters ¶meters);
+ /**
+ * The reference count for this object. Each aggregate
+ * has an individual reference count. When the global
+ * reference count (the sum of all reference counts)
+ * reaches zero, the object and all its aggregates is
+ * deleted.
+ */
mutable uint32_t m_count;
+ /**
+ * Identifies the type of this object instance.
+ */
TypeId m_tid;
+ /**
+ * Set to true when the DoDispose method of the object
+ * has run, false otherwise.
+ */
bool m_disposed;
mutable bool m_collecting;
+ /**
+ * A pointer to the next aggregate object. This is a circular
+ * linked list of aggregated objects: the last one points
+ * back to the first one. If an object is not aggregated to
+ * any other object, the value of this field is equal to the
+ * value of the 'this' pointer.
+ */
Object *m_next;
};
-template <typename T>
-Ptr<T> CreateObject (void);
-
-template <typename T, typename T1>
-Ptr<T> CreateObject (T1 a1);
-
-template <typename T, typename T1, typename T2>
-Ptr<T> CreateObject (T1 a1, T2 a2);
-
-template <typename T, typename T1, typename T2, typename T3>
-Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3);
-
-template <typename T, typename T1, typename T2, typename T3, typename T4>
-Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4);
-
-template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
-Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
-
-template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
-Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6);
-
-template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
-Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7);
-
} // namespace ns3
namespace ns3 {
+/*************************************************************************
+ * The TypeId implementation which depends on templates
+ *************************************************************************/
+
template <typename T>
TypeId
TypeId::SetParent (void)
@@ -294,8 +548,8 @@
TypeId::AddConstructor (void)
{
struct Maker {
- static Ptr<Object> Create (void) {
- return ns3::CreateObject<T> ();
+ static Ptr<Object> Create (const Parameters ¶meters) {
+ return ns3::CreateObject<T> (parameters);
}
};
CallbackBase cb = MakeCallback (&Maker::Create);
@@ -328,49 +582,9 @@
DoAddConstructor (cb, 2);
return *this;
}
-template <typename T, typename T1, typename T2, typename T3>
-TypeId
-TypeId::AddConstructor (void)
-{
- struct Maker {
- static Ptr<Object> Create (T1 a1, T2 a2, T3 a3) {
- return ns3::CreateObject<T,T1,T2,T3> (a1, a2, a3);
- }
- };
- CallbackBase cb = MakeCallback (&Maker::Create);
- DoAddConstructor (cb, 3);
- return *this;
-}
-template <typename T, typename T1, typename T2, typename T3, typename T4>
-TypeId
-TypeId::AddConstructor (void)
-{
- struct Maker {
- static Ptr<Object> Create (T1 a1, T2 a2, T3 a3, T4 a4) {
- return ns3::CreateObject<T,T1,T2,T3,T4> (a1, a2, a3, a4);
- }
- };
- CallbackBase cb = MakeCallback (&Maker::Create);
- DoAddConstructor (cb, 4);
- return *this;
-}
-template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
-TypeId
-TypeId::AddConstructor (void)
-{
- struct Maker {
- static Ptr<Object> Create (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) {
- return ns3::CreateObject<T,T1,T2,T3,T4,T5> (a1, a2, a3, a4, a5);
- }
- };
- CallbackBase cb = MakeCallback (&Maker::Create);
- DoAddConstructor (cb, 5);
- return *this;
-}
-
template <typename T1>
Ptr<Object>
-TypeId::CreateObject (T1 a1)
+TypeId::CreateObject (T1 a1) const
{
CallbackBase cb = LookupConstructor (1);
Callback<Ptr<Object>,T1> realCb;
@@ -380,7 +594,7 @@
}
template <typename T1, typename T2>
Ptr<Object>
-TypeId::CreateObject (T1 a1, T2 a2)
+TypeId::CreateObject (T1 a1, T2 a2) const
{
CallbackBase cb = LookupConstructor (2);
Callback<Ptr<Object>,T1,T2> realCb;
@@ -388,38 +602,10 @@
Ptr<Object> object = realCb (a1,a2);
return object;
}
-template <typename T1, typename T2, typename T3>
-Ptr<Object>
-TypeId::CreateObject (T1 a1, T2 a2, T3 a3)
-{
- CallbackBase cb = LookupConstructor (3);
- Callback<Ptr<Object>,T1,T2,T3> realCb;
- realCb.Assign (cb);
- Ptr<Object> object = realCb (a1,a2,a3);
- return object;
-}
-template <typename T1, typename T2, typename T3, typename T4>
-Ptr<Object>
-TypeId::CreateObject (T1 a1, T2 a2, T3 a3, T4 a4)
-{
- CallbackBase cb = LookupConstructor (4);
- Callback<Ptr<Object>,T1,T2,T3,T4> realCb;
- realCb.Assign (cb);
- Ptr<Object> object = realCb (a1,a2,a3,a4);
- return object;
-}
- template <typename T1, typename T2, typename T3, typename T4, typename T5>
-Ptr<Object>
-TypeId::CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
-{
- CallbackBase cb = LookupConstructor (5);
- Callback<Ptr<Object>,T1,T2,T3,T4,T5> realCb;
- realCb.Assign (cb);
- Ptr<Object> object = realCb (a1,a2,a3,a4,a5);
- return object;
-}
-
+/*************************************************************************
+ * The Object implementation which depends on templates
+ *************************************************************************/
void
Object::Ref (void) const
@@ -461,11 +647,26 @@
return 0;
}
+/*************************************************************************
+ * The helper functions which need templates.
+ *************************************************************************/
+
+
+template <typename T>
+Ptr<T> CreateObject (const Parameters ¶meters)
+{
+ Ptr<T> p = Ptr<T> (new T (), false);
+ p->SetTypeId (T::GetTypeId ());
+ p->Object::Construct (parameters);
+ return p;
+}
+
template <typename T>
Ptr<T> CreateObject (void)
{
Ptr<T> p = Ptr<T> (new T (), false);
p->SetTypeId (T::GetTypeId ());
+ p->Object::Construct (Parameters ());
return p;
}
@@ -474,6 +675,7 @@
{
Ptr<T> p = Ptr<T> (new T (a1), false);
p->SetTypeId (T::GetTypeId ());
+ p->Object::Construct (Parameters ());
return p;
}
@@ -482,9 +684,9 @@
{
Ptr<T> p = Ptr<T> (new T (a1, a2), false);
p->SetTypeId (T::GetTypeId ());
+ p->Object::Construct (Parameters ());
return p;
}
-
template <typename T, typename T1, typename T2, typename T3>
Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3)
{
@@ -526,6 +728,30 @@
}
+template <typename T>
+Ptr<T>
+CreateObjectWith (std::string n1, Ptr<const Value> v1,
+ std::string n2 = "", Ptr<const Value> v2 = 0)
+
+{
+ Parameters parameters;
+ parameters.SetWithTid (T::GetTypeId (), n1, v1);
+ parameters.SetWithTid (T::GetTypeId (), n2, v2);
+ return CreateObject<T> (parameters);
+}
+
+template <typename T>
+Ptr<T>
+CreateObjectWith (std::string n1, std::string v1,
+ std::string n2 = "", std::string v2 = "")
+
+{
+ Parameters parameters;
+ parameters.SetWithTid (T::GetTypeId (), n1, v1);
+ parameters.SetWithTid (T::GetTypeId (), n2, v2);
+ return CreateObject<T> (parameters);
+}
+
} // namespace ns3
#endif /* OBJECT_H */