diff --git a/simgear/hla/CMakeLists.txt b/simgear/hla/CMakeLists.txt index a822fc24..f9c35c5e 100644 --- a/simgear/hla/CMakeLists.txt +++ b/simgear/hla/CMakeLists.txt @@ -7,6 +7,7 @@ set(HLA_HEADERS HLABasicDataElement.hxx HLABasicDataType.hxx HLADataElement.hxx + HLADataElementVisitor.hxx HLADataType.hxx HLADataTypeVisitor.hxx HLAEnumeratedDataElement.hxx diff --git a/simgear/hla/HLAArrayDataElement.cxx b/simgear/hla/HLAArrayDataElement.cxx index e2a7fc73..01e40243 100644 --- a/simgear/hla/HLAArrayDataElement.cxx +++ b/simgear/hla/HLAArrayDataElement.cxx @@ -19,6 +19,8 @@ #include +#include "HLADataElementVisitor.hxx" + namespace simgear { HLAAbstractArrayDataElement::HLAAbstractArrayDataElement(const HLAArrayDataType* dataType) : @@ -30,6 +32,18 @@ HLAAbstractArrayDataElement::~HLAAbstractArrayDataElement() { } +void +HLAAbstractArrayDataElement::accept(HLADataElementVisitor& visitor) +{ + visitor.apply(*this); +} + +void +HLAAbstractArrayDataElement::accept(HLAConstDataElementVisitor& visitor) const +{ + visitor.apply(*this); +} + bool HLAAbstractArrayDataElement::decode(HLADecodeStream& stream) { diff --git a/simgear/hla/HLAArrayDataElement.hxx b/simgear/hla/HLAArrayDataElement.hxx index b7c9c1e3..c236c4e4 100644 --- a/simgear/hla/HLAArrayDataElement.hxx +++ b/simgear/hla/HLAArrayDataElement.hxx @@ -33,6 +33,9 @@ public: HLAAbstractArrayDataElement(const HLAArrayDataType* dataType); virtual ~HLAAbstractArrayDataElement(); + virtual void accept(HLADataElementVisitor& visitor); + virtual void accept(HLAConstDataElementVisitor& visitor) const; + virtual bool decode(HLADecodeStream& stream); virtual bool encode(HLAEncodeStream& stream) const; diff --git a/simgear/hla/HLABasicDataElement.cxx b/simgear/hla/HLABasicDataElement.cxx index 69401104..f68cad36 100644 --- a/simgear/hla/HLABasicDataElement.cxx +++ b/simgear/hla/HLABasicDataElement.cxx @@ -17,6 +17,7 @@ #include "HLABasicDataElement.hxx" +#include "HLADataElementVisitor.hxx" #include "HLADataTypeVisitor.hxx" namespace simgear { @@ -30,6 +31,18 @@ HLABasicDataElement::~HLABasicDataElement() { } +void +HLABasicDataElement::accept(HLADataElementVisitor& visitor) +{ + visitor.apply(*this); +} + +void +HLABasicDataElement::accept(HLAConstDataElementVisitor& visitor) const +{ + visitor.apply(*this); +} + const HLABasicDataType* HLABasicDataElement::getDataType() const { diff --git a/simgear/hla/HLABasicDataElement.hxx b/simgear/hla/HLABasicDataElement.hxx index e38499df..70c275be 100644 --- a/simgear/hla/HLABasicDataElement.hxx +++ b/simgear/hla/HLABasicDataElement.hxx @@ -28,6 +28,12 @@ public: HLABasicDataElement(const HLABasicDataType* dataType); virtual ~HLABasicDataElement(); + virtual void accept(HLADataElementVisitor& visitor); + virtual void accept(HLAConstDataElementVisitor& visitor) const; + + virtual bool encode(HLAEncodeStream& stream) const = 0; + virtual bool decode(HLADecodeStream& stream) = 0; + virtual const HLABasicDataType* getDataType() const; virtual bool setDataType(const HLADataType* dataType); void setDataType(const HLABasicDataType* dataType); @@ -41,6 +47,7 @@ class HLAAbstract##type##DataElement : public HLABasicDataElement { \ public: \ HLAAbstract##type##DataElement(const HLABasicDataType* dataType = 0); \ virtual ~HLAAbstract##type##DataElement(); \ + \ virtual bool encode(HLAEncodeStream& stream) const; \ virtual bool decode(HLADecodeStream& stream); \ \ diff --git a/simgear/hla/HLADataElement.cxx b/simgear/hla/HLADataElement.cxx index ae981128..8245bddd 100644 --- a/simgear/hla/HLADataElement.cxx +++ b/simgear/hla/HLADataElement.cxx @@ -19,6 +19,8 @@ #include +#include "HLADataElementVisitor.hxx" + namespace simgear { HLADataElement::PathElement::Data::~Data() @@ -129,6 +131,18 @@ HLADataElement::~HLADataElement() { } +void +HLADataElement::accept(HLADataElementVisitor& visitor) +{ + visitor.apply(*this); +} + +void +HLADataElement::accept(HLAConstDataElementVisitor& visitor) const +{ + visitor.apply(*this); +} + std::string HLADataElement::toString(const Path& path) { diff --git a/simgear/hla/HLADataElement.hxx b/simgear/hla/HLADataElement.hxx index 284422b8..e3d52933 100644 --- a/simgear/hla/HLADataElement.hxx +++ b/simgear/hla/HLADataElement.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2011 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -30,10 +30,16 @@ class SGTimeStamp; namespace simgear { +class HLADataElementVisitor; +class HLAConstDataElementVisitor; + class HLADataElement : public SGReferenced { public: virtual ~HLADataElement(); + virtual void accept(HLADataElementVisitor& visitor) = 0; + virtual void accept(HLAConstDataElementVisitor& visitor) const = 0; + virtual bool encode(HLAEncodeStream& stream) const = 0; virtual bool decode(HLADecodeStream& stream) = 0; diff --git a/simgear/hla/HLADataElementVisitor.hxx b/simgear/hla/HLADataElementVisitor.hxx new file mode 100644 index 00000000..938f7302 --- /dev/null +++ b/simgear/hla/HLADataElementVisitor.hxx @@ -0,0 +1,57 @@ +// Copyright (C) 2009 - 2011 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLADataElementVisitor_hxx +#define HLADataElementVisitor_hxx + +namespace simgear { + +class HLABasicDataElement; +class HLAAbstractEnumeratedDataElement; +class HLAAbstractFixedRecordDataElement; +class HLAAbstractArrayDataElement; +class HLAAbstractVariantDataElement; + +class HLADataElementVisitor { +public: + virtual ~HLADataElementVisitor() {} + + virtual void apply(HLADataElement&); + + virtual void apply(HLABasicDataElement&); + virtual void apply(HLAAbstractEnumeratedDataElement&); + virtual void apply(HLAAbstractArrayDataElement&); + virtual void apply(HLAAbstractFixedRecordDataElement&); + virtual void apply(HLAAbstractVariantDataElement&); +}; + +class HLAConstDataElementVisitor { +public: + virtual ~HLAConstDataElementVisitor() {} + + virtual void apply(const HLADataElement&); + + virtual void apply(const HLABasicDataElement&); + virtual void apply(const HLAAbstractEnumeratedDataElement&); + virtual void apply(const HLAAbstractArrayDataElement&); + virtual void apply(const HLAAbstractFixedRecordDataElement&); + virtual void apply(const HLAAbstractVariantDataElement&); +}; + +} + +#endif diff --git a/simgear/hla/HLAEnumeratedDataElement.cxx b/simgear/hla/HLAEnumeratedDataElement.cxx index a09e0dec..d5af6d41 100644 --- a/simgear/hla/HLAEnumeratedDataElement.cxx +++ b/simgear/hla/HLAEnumeratedDataElement.cxx @@ -19,6 +19,8 @@ #include +#include "HLADataElementVisitor.hxx" + namespace simgear { HLAAbstractEnumeratedDataElement::HLAAbstractEnumeratedDataElement(const HLAEnumeratedDataType* dataType) : @@ -30,6 +32,18 @@ HLAAbstractEnumeratedDataElement::~HLAAbstractEnumeratedDataElement() { } +void +HLAAbstractEnumeratedDataElement::accept(HLADataElementVisitor& visitor) +{ + visitor.apply(*this); +} + +void +HLAAbstractEnumeratedDataElement::accept(HLAConstDataElementVisitor& visitor) const +{ + visitor.apply(*this); +} + bool HLAAbstractEnumeratedDataElement::decode(HLADecodeStream& stream) { diff --git a/simgear/hla/HLAEnumeratedDataElement.hxx b/simgear/hla/HLAEnumeratedDataElement.hxx index f7dfbd38..10d8f105 100644 --- a/simgear/hla/HLAEnumeratedDataElement.hxx +++ b/simgear/hla/HLAEnumeratedDataElement.hxx @@ -28,6 +28,9 @@ public: HLAAbstractEnumeratedDataElement(const HLAEnumeratedDataType* dataType); virtual ~HLAAbstractEnumeratedDataElement(); + virtual void accept(HLADataElementVisitor& visitor); + virtual void accept(HLAConstDataElementVisitor& visitor) const; + virtual bool decode(HLADecodeStream& stream); virtual bool encode(HLAEncodeStream& stream) const; diff --git a/simgear/hla/HLAFixedRecordDataElement.cxx b/simgear/hla/HLAFixedRecordDataElement.cxx index d0980b95..c4c0c8b2 100644 --- a/simgear/hla/HLAFixedRecordDataElement.cxx +++ b/simgear/hla/HLAFixedRecordDataElement.cxx @@ -20,6 +20,8 @@ #include #include #include + +#include "HLADataElementVisitor.hxx" #include "HLADataTypeVisitor.hxx" namespace simgear { @@ -33,6 +35,18 @@ HLAAbstractFixedRecordDataElement::~HLAAbstractFixedRecordDataElement() { } +void +HLAAbstractFixedRecordDataElement::accept(HLADataElementVisitor& visitor) +{ + visitor.apply(*this); +} + +void +HLAAbstractFixedRecordDataElement::accept(HLAConstDataElementVisitor& visitor) const +{ + visitor.apply(*this); +} + bool HLAAbstractFixedRecordDataElement::decode(HLADecodeStream& stream) { diff --git a/simgear/hla/HLAFixedRecordDataElement.hxx b/simgear/hla/HLAFixedRecordDataElement.hxx index d99719d0..ca8ed997 100644 --- a/simgear/hla/HLAFixedRecordDataElement.hxx +++ b/simgear/hla/HLAFixedRecordDataElement.hxx @@ -30,6 +30,9 @@ public: HLAAbstractFixedRecordDataElement(const HLAFixedRecordDataType* dataType); virtual ~HLAAbstractFixedRecordDataElement(); + virtual void accept(HLADataElementVisitor& visitor); + virtual void accept(HLAConstDataElementVisitor& visitor) const; + virtual bool decode(HLADecodeStream& stream); virtual bool encode(HLAEncodeStream& stream) const; diff --git a/simgear/hla/HLAPropertyDataElement.cxx b/simgear/hla/HLAPropertyDataElement.cxx index e8a931ee..af19ff4d 100644 --- a/simgear/hla/HLAPropertyDataElement.cxx +++ b/simgear/hla/HLAPropertyDataElement.cxx @@ -18,6 +18,8 @@ #include "HLAPropertyDataElement.hxx" #include "HLAArrayDataElement.hxx" +#include "HLABasicDataElement.hxx" +#include "HLADataElementVisitor.hxx" #include "HLADataTypeVisitor.hxx" #include "HLAFixedRecordDataElement.hxx" #include "HLAVariantDataElement.hxx" @@ -152,7 +154,7 @@ protected: const SGPropertyNode& _propertyNode; }; -class HLAPropertyDataElement::ScalarDataElement : public HLADataElement { +class HLAPropertyDataElement::ScalarDataElement : public HLABasicDataElement { public: ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode); virtual ~ScalarDataElement(); @@ -160,16 +162,12 @@ public: virtual bool encode(HLAEncodeStream& stream) const; virtual bool decode(HLADecodeStream& stream); - virtual const HLADataType* getDataType() const; - virtual bool setDataType(const HLADataType* dataType); - private: - SGSharedPtr _dataType; SGSharedPtr _propertyNode; }; HLAPropertyDataElement::ScalarDataElement::ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode) : - _dataType(dataType), + HLABasicDataElement(dataType), _propertyNode(propertyNode) { } @@ -194,162 +192,64 @@ HLAPropertyDataElement::ScalarDataElement::decode(HLADecodeStream& stream) return true; } -const HLADataType* -HLAPropertyDataElement::ScalarDataElement::getDataType() const -{ - return _dataType.get(); -} - -bool -HLAPropertyDataElement::ScalarDataElement::setDataType(const HLADataType* dataType) -{ - if (!dataType) - return false; - const HLABasicDataType* basicDataType = dataType->toBasicDataType(); - if (!basicDataType) - return false; - _dataType = basicDataType; - return true; -} - - -class HLAPropertyDataElement::StringDecodeVisitor : public HLADataTypeDecodeVisitor { -public: - StringDecodeVisitor(HLADecodeStream& stream, SGPropertyNode& propertyNode) : - HLADataTypeDecodeVisitor(stream), - _propertyNode(propertyNode) - { } - - virtual void apply(const HLAFixedArrayDataType& dataType) - { - unsigned numElements = dataType.getNumElements(); - std::string value; - value.reserve(numElements); - for (unsigned i = 0; i < numElements; ++i) { - HLATemplateDecodeVisitor visitor(_stream); - dataType.getElementDataType()->accept(visitor); - value.push_back(visitor.getValue()); - } - _propertyNode.setStringValue(value); - } - virtual void apply(const HLAVariableArrayDataType& dataType) - { - HLATemplateDecodeVisitor numElementsVisitor(_stream); - dataType.getSizeDataType()->accept(numElementsVisitor); - std::string::size_type numElements = numElementsVisitor.getValue(); - std::string value; - value.reserve(numElements); - for (std::string::size_type i = 0; i < numElements; ++i) { - HLATemplateDecodeVisitor visitor(_stream); - dataType.getElementDataType()->accept(visitor); - value.push_back(visitor.getValue()); - } - _propertyNode.setStringValue(value); - } - -protected: - SGPropertyNode& _propertyNode; -}; - -class HLAPropertyDataElement::StringEncodeVisitor : public HLADataTypeEncodeVisitor { -public: - StringEncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) : - HLADataTypeEncodeVisitor(stream), - _propertyNode(propertyNode) - { } - - virtual void apply(const HLAFixedArrayDataType& dataType) - { - unsigned numElements = dataType.getNumElements(); - std::string value = _propertyNode.getStringValue(); - for (unsigned i = 0; i < numElements; ++i) { - if (i < value.size()) { - HLATemplateEncodeVisitor visitor(_stream, value[i]); - dataType.getElementDataType()->accept(visitor); - } else { - HLADataTypeEncodeVisitor visitor(_stream); - dataType.getElementDataType()->accept(visitor); - } - } - } - - virtual void apply(const HLAVariableArrayDataType& dataType) - { - std::string value = _propertyNode.getStringValue(); - HLATemplateEncodeVisitor numElementsVisitor(_stream, value.size()); - dataType.getSizeDataType()->accept(numElementsVisitor); - for (unsigned i = 0; i < value.size(); ++i) { - HLATemplateEncodeVisitor visitor(_stream, value[i]); - dataType.getElementDataType()->accept(visitor); - } - } - -protected: - const SGPropertyNode& _propertyNode; -}; - -class HLAPropertyDataElement::StringDataElement : public HLADataElement { +class HLAPropertyDataElement::StringDataElement : public HLAStringDataElement { public: StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode); virtual ~StringDataElement(); - virtual bool encode(HLAEncodeStream& stream) const; - virtual bool decode(HLADecodeStream& stream); + virtual bool decodeElement(HLADecodeStream& stream, unsigned i); - virtual const HLADataType* getDataType() const; - virtual bool setDataType(const HLADataType* dataType); + class Listener : public SGPropertyChangeListener { + public: + Listener(StringDataElement* stringDataElement); + virtual ~Listener(); + virtual void valueChanged (SGPropertyNode * node); + private: + StringDataElement* _stringDataElement; + }; private: - SGSharedPtr _dataType; SGSharedPtr _propertyNode; + Listener* _listener; }; -HLAPropertyDataElement::StringDataElement::StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode) : - _dataType(dataType), - _propertyNode(propertyNode) +HLAPropertyDataElement::StringDataElement::Listener::Listener(StringDataElement* stringDataElement) : + _stringDataElement(stringDataElement) { } +HLAPropertyDataElement::StringDataElement::Listener::~Listener() +{ +} + +void +HLAPropertyDataElement::StringDataElement::Listener::valueChanged (SGPropertyNode * node) +{ + _stringDataElement->setValue(node->getStringValue()); +} + +HLAPropertyDataElement::StringDataElement::StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode) : + HLAStringDataElement(dataType), + _propertyNode(propertyNode), + _listener(new Listener(this)) +{ + _propertyNode->addChangeListener(_listener, true); +} + HLAPropertyDataElement::StringDataElement::~StringDataElement() { + _propertyNode->removeChangeListener(_listener); + delete _listener; + _listener = 0; } bool -HLAPropertyDataElement::StringDataElement::encode(HLAEncodeStream& stream) const +HLAPropertyDataElement::StringDataElement::decodeElement(HLADecodeStream& stream, unsigned i) { - StringEncodeVisitor visitor(stream, *_propertyNode); - _dataType->accept(visitor); - return true; -} - -bool -HLAPropertyDataElement::StringDataElement::decode(HLADecodeStream& stream) -{ - StringDecodeVisitor visitor(stream, *_propertyNode); - _dataType->accept(visitor); - return true; -} - -const HLADataType* -HLAPropertyDataElement::StringDataElement::getDataType() const -{ - return _dataType.get(); -} - -bool -HLAPropertyDataElement::StringDataElement::setDataType(const HLADataType* dataType) -{ - if (!dataType) + if (!HLAStringDataElement::decodeElement(stream, i)) return false; - const HLAArrayDataType* arrayDataType = dataType->toArrayDataType(); - if (!arrayDataType) - return false; - const HLADataType* elementDataType = arrayDataType->getElementDataType(); - if (!elementDataType) - return false; - if (!elementDataType->toBasicDataType()) - return false; - _dataType = arrayDataType; + if (i + 1 == getValue().size()) + _propertyNode->setStringValue(getValue()); return true; } @@ -534,6 +434,38 @@ HLAPropertyDataElement::~HLAPropertyDataElement() { } +void +HLAPropertyDataElement::accept(HLADataElementVisitor& visitor) +{ + if (_dataElement.valid()) { + visitor.apply(*_dataElement); + } else { + // We cant do anything if the data type is not valid + if (_dataType.valid()) { + HLADataElementFactoryVisitor factoryVisitor; + _dataType->accept(factoryVisitor); + _dataElement = factoryVisitor.getDataElement(); + if (_dataElement.valid()) { + visitor.apply(*_dataElement); + } else { + HLADataElement::accept(visitor); + } + } else { + HLADataElement::accept(visitor); + } + } +} + +void +HLAPropertyDataElement::accept(HLAConstDataElementVisitor& visitor) const +{ + if (_dataElement.valid()) { + visitor.apply(*_dataElement); + } else { + HLADataElement::accept(visitor); + } +} + bool HLAPropertyDataElement::encode(HLAEncodeStream& stream) const { diff --git a/simgear/hla/HLAPropertyDataElement.hxx b/simgear/hla/HLAPropertyDataElement.hxx index 4354a1d9..da21b2ab 100644 --- a/simgear/hla/HLAPropertyDataElement.hxx +++ b/simgear/hla/HLAPropertyDataElement.hxx @@ -31,6 +31,9 @@ public: HLAPropertyDataElement(const HLADataType* dataType); virtual ~HLAPropertyDataElement(); + virtual void accept(HLADataElementVisitor& visitor); + virtual void accept(HLAConstDataElementVisitor& visitor) const; + virtual bool encode(HLAEncodeStream& stream) const; virtual bool decode(HLADecodeStream& stream); diff --git a/simgear/hla/HLAVariantDataElement.cxx b/simgear/hla/HLAVariantDataElement.cxx index 98c22f78..2eca369a 100644 --- a/simgear/hla/HLAVariantDataElement.cxx +++ b/simgear/hla/HLAVariantDataElement.cxx @@ -19,6 +19,8 @@ #include +#include "HLADataElementVisitor.hxx" + namespace simgear { HLAAbstractVariantDataElement::HLAAbstractVariantDataElement(const HLAVariantDataType* dataType) : @@ -30,6 +32,18 @@ HLAAbstractVariantDataElement::~HLAAbstractVariantDataElement() { } +void +HLAAbstractVariantDataElement::accept(HLADataElementVisitor& visitor) +{ + visitor.apply(*this); +} + +void +HLAAbstractVariantDataElement::accept(HLAConstDataElementVisitor& visitor) const +{ + visitor.apply(*this); +} + bool HLAAbstractVariantDataElement::decode(HLADecodeStream& stream) { diff --git a/simgear/hla/HLAVariantDataElement.hxx b/simgear/hla/HLAVariantDataElement.hxx index b3ced7ca..0b14ef45 100644 --- a/simgear/hla/HLAVariantDataElement.hxx +++ b/simgear/hla/HLAVariantDataElement.hxx @@ -30,6 +30,9 @@ public: HLAAbstractVariantDataElement(const HLAVariantDataType* dataType); virtual ~HLAAbstractVariantDataElement(); + virtual void accept(HLADataElementVisitor& visitor); + virtual void accept(HLAConstDataElementVisitor& visitor) const; + virtual bool decode(HLADecodeStream& stream); virtual bool encode(HLAEncodeStream& stream) const; diff --git a/simgear/hla/Makefile.am b/simgear/hla/Makefile.am index e214e6a0..3bb38603 100644 --- a/simgear/hla/Makefile.am +++ b/simgear/hla/Makefile.am @@ -11,6 +11,7 @@ libsghla_a_HEADERS = \ HLABasicDataElement.hxx \ HLABasicDataType.hxx \ HLADataElement.hxx \ + HLADataElementVisitor.hxx \ HLADataType.hxx \ HLADataTypeVisitor.hxx \ HLAEnumeratedDataElement.hxx \