diff --git a/src/core/attribute-test.cc b/src/core/attribute-test.cc index 9a2a38a4a..bf8edf462 100644 --- a/src/core/attribute-test.cc +++ b/src/core/attribute-test.cc @@ -30,6 +30,7 @@ #include "object-vector.h" #include "traced-value.h" #include "trace-source-accessor.h" +#include "pointer.h" namespace ns3 { @@ -171,6 +172,10 @@ public: MakeTraceSourceAccessor (&AttributeObjectTest::m_cb)) .AddTraceSource ("ValueSource", "help text", MakeTraceSourceAccessor (&AttributeObjectTest::m_valueSrc)) + .AddAttribute ("Pointer", "XXX", + Pointer (), + MakePointerAccessor (&AttributeObjectTest::m_ptr), + MakePointerChecker ()) ; return tid; @@ -228,6 +233,7 @@ private: TracedValue m_intSrc2; TracedCallback m_cb; TracedValue m_valueSrc; + Ptr m_ptr; }; @@ -481,6 +487,24 @@ AttributeTest::RunTests (void) NS_TEST_ASSERT_EQUAL (m_got2, 1.0); NS_TEST_ASSERT (p->TraceConnectWithoutContext ("ValueSource", MakeCallback (&AttributeTest::NotifySourceValue, this))); + + + derived = Pointer (p->GetAttribute ("Pointer")); + NS_TEST_ASSERT (derived == 0); + derived = Create (); + NS_TEST_ASSERT (p->SetAttributeFailSafe("Pointer", Pointer (derived))); + stored = Pointer (p->GetAttribute ("Pointer")); + NS_TEST_ASSERT (stored == derived); + storedBase = Pointer (p->GetAttribute ("Pointer")); + NS_TEST_ASSERT (stored == storedBase); + x = Pointer (p->GetAttribute ("Pointer")); + NS_TEST_ASSERT (x == 0); + + p = CreateObject ("Pointer", Pointer (Create ())); + NS_TEST_ASSERT (p != 0); + derived = 0; + derived = Pointer (p->GetAttribute ("Pointer")); + NS_TEST_ASSERT (derived != 0); diff --git a/src/core/pointer.cc b/src/core/pointer.cc new file mode 100644 index 000000000..4af0de42a --- /dev/null +++ b/src/core/pointer.cc @@ -0,0 +1,59 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2008 INRIA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Mathieu Lacage + */ +#include "pointer.h" + +namespace ns3 { + +Pointer::Pointer () + : m_value () +{} + +Pointer::Pointer (Ptr object) + : m_value (object) +{} + +void +Pointer::SetObject (Ptr object) +{ + m_value = object; +} + +Ptr +Pointer::GetObject (void) const +{ + return m_value; +} + +ATTRIBUTE_VALUE_IMPLEMENT (Pointer); +ATTRIBUTE_CONVERTER_IMPLEMENT (Pointer); + +std::ostream & operator << (std::ostream &os, const Pointer &pointer) +{ + os << pointer.GetObject (); + return os; +} +std::istream & operator >> (std::istream &is, Pointer &pointer) +{ + // XXX: This cannot work; + return is; +} + + +} // namespace ns3 diff --git a/src/core/pointer.h b/src/core/pointer.h new file mode 100644 index 000000000..c9183f041 --- /dev/null +++ b/src/core/pointer.h @@ -0,0 +1,297 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2008 INRIA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Mathieu Lacage + */ +#ifndef NS_POINTER_H +#define NS_POINTER_H + +#include "attribute.h" +#include "object.h" + +namespace ns3 { + +class Pointer +{ +public: + Pointer (); + + Pointer (Ptr object); + + void SetObject (Ptr object); + + Ptr GetObject (void) const; + + template + Pointer (const Ptr &object); + + template + void Set (const Ptr &object); + + template + Ptr Get (void) const; + + template + operator Ptr () const; + + ATTRIBUTE_CONVERTER_DEFINE (Pointer); +private: + Ptr m_value; +}; + +std::ostream & operator << (std::ostream &os, const Pointer &pointer); +std::istream & operator >> (std::istream &is, Pointer &pointer); + +ATTRIBUTE_VALUE_DEFINE (Pointer); + +template +Ptr +MakePointerAccessor (Ptr T::*memberVariable); +template +Ptr +MakePointerAccessor (void (T::*setter) (Ptr)); +template +Ptr +MakePointerAccessor (Ptr (T::*getter) (void) const); +template +Ptr +MakePointerAccessor (void (T::*setter) (Ptr), + Ptr (T::*getter) (void) const); +template +Ptr +MakePointerAccessor (Ptr (T::*getter) (void) const, + void (T::*setter) (Ptr)); + +class PointerChecker : public AttributeChecker {}; +template +Ptr MakePointerChecker (void); + +} // namespace ns3 + +namespace ns3 { + + +namespace internal { + +template +class APointerChecker : public PtrChecker +{ + virtual bool Check (Attribute val) const { + const PointerValue *value = val.DynCast (); + if (value == 0) + { + return false; + } + if (value->Get ().GetObject () == 0) + { + return true; + } + T *ptr = dynamic_cast (PeekPointer (value->Get ().GetObject ())); + if (ptr == 0) + { + return false; + } + return true; + } + virtual std::string GetType (void) const { + // XXX: we should be able to return better information + TypeId tid = T::GetTypeId (); + return "Ptr<" + tid.GetName () + ">"; + } + virtual bool HasTypeConstraints (void) const { + return false; + } + virtual std::string GetTypeConstraints (void) const { + return ""; + } + virtual Attribute Create (void) const { + return Attribute::Create (); + } +}; + +/******************************************************** + * The Accessor associated to + * PointerValue + ********************************************************/ + +template +class PointerAccessor : public AttributeAccessor +{ +public: + virtual ~PointerAccessor () {} + virtual bool Set (ObjectBase * object, Attribute val) const { + T *obj = dynamic_cast (object); + if (obj == 0) + { + return false; + } + const PointerValue *value = val.DynCast (); + if (value == 0) + { + return false; + } + Ptr ptr = dynamic_cast (PeekPointer (value->Get ().GetObject ())); + if (ptr == 0) + { + return false; + } + DoSet (obj, ptr); + return true; + } + virtual bool Get (const ObjectBase * object, Attribute val) const { + const T *obj = dynamic_cast (object); + if (obj == 0) + { + return false; + } + PointerValue *value = val.DynCast (); + if (value == 0) + { + return false; + } + value->Set (Pointer (DoGet (obj))); + return true; + } +private: + virtual void DoSet (T *object, Ptr value) const = 0; + virtual Ptr DoGet (const T *object) const = 0; +}; + +} // namespace internal + + +template +Pointer::Pointer (const Ptr &object) +{ + m_value = object; +} + +template +void +Pointer::Set (const Ptr &object) +{ + m_value = object; +} + +template +Ptr +Pointer::Get (void) const +{ + T *v = dynamic_cast (PeekPointer (m_value)); + return v; +} + +template +Pointer::operator Ptr () const +{ + return Get (); +} + + +template +Ptr +MakePointerAccessor (Ptr T::*memberVariable) +{ + struct MemberVariable : public internal::PointerAccessor + { + Ptr T::*m_memberVariable; + virtual void DoSet (T *object, Ptr value) const { + (object->*m_memberVariable) = value; + } + virtual Ptr DoGet (const T *object) const { + return object->*m_memberVariable; + } + } *spec = new MemberVariable (); + spec->m_memberVariable = memberVariable; + return Ptr (spec, false); +} + +template +Ptr +MakePointerAccessor (void (T::*setter) (Ptr)) +{ + struct MemberMethod : public internal::PointerAccessor + { + void (T::*m_setter) (Ptr); + virtual void DoSet (T *object, Ptr value) const { + (object->*m_setter) (value); + } + virtual Ptr DoGet (const T *object) const { + return 0; + //return (object->*m_getter) (); + } + } *spec = new MemberMethod (); + spec->m_setter = setter; + return Ptr (spec, false); +} + +template +Ptr +MakePointerAccessor (Ptr (T::*getter) (void) const) +{ + struct MemberMethod : public internal::PointerAccessor + { + Ptr (T::*m_getter) (void) const; + virtual void DoSet (T *object, Ptr value) const { + //(object->*m_setter) (value); + } + virtual Ptr DoGet (const T *object) const { + return (object->*m_getter) (); + } + } *spec = new MemberMethod (); + spec->m_getter = getter; + return Ptr (spec, false); +} +template +Ptr +MakePointerAccessor (void (T::*setter) (Ptr), + Ptr (T::*getter) (void) const) +{ + return MakePointerAccessor (getter, setter); +} +template +Ptr +MakePointerAccessor (Ptr (T::*getter) (void) const, + void (T::*setter) (Ptr)) +{ + struct MemberMethod : public internal::PointerAccessor + { + void (T::*m_setter) (Ptr); + Ptr (T::*m_getter) (void) const; + virtual void DoSet (T *object, Ptr value) const { + (object->*m_setter) (value); + } + virtual Ptr DoGet (const T *object) const { + return (object->*m_getter) (); + } + } *spec = new MemberMethod (); + spec->m_setter = setter; + spec->m_getter = getter; + return Ptr (spec, false); +} + +template +Ptr +MakePointerChecker (void) +{ + return Create > (); +} + + +} // namespace ns3 + +#endif /* NS_POINTER_H */ diff --git a/src/core/wscript b/src/core/wscript index 97eed7fd8..21b63b143 100644 --- a/src/core/wscript +++ b/src/core/wscript @@ -52,6 +52,7 @@ def build(bld): 'enum.cc', 'double.cc', 'string.cc', + 'pointer.cc', 'object-factory.cc', 'object-vector.cc', 'global-value.cc', @@ -100,6 +101,7 @@ def build(bld): 'double.h', 'enum.h', 'string.h', + 'pointer.h', 'object-factory.h', 'attribute-helper.h', 'global-value.h',