X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fhla%2FHLAPropertyDataElement.cxx;h=0b9e354ea0ab496a24b786833ddb14e6331a82fe;hb=ba83177019da0c941f55b6ef3b709ed7a57d4155;hp=db4f00ba84a571a3f6330dd6650435caa80b9f8b;hpb=3a0fbae4d90187d96eb991a7d7dccc339a3bcb48;p=simgear.git diff --git a/simgear/hla/HLAPropertyDataElement.cxx b/simgear/hla/HLAPropertyDataElement.cxx index db4f00ba..0b9e354e 100644 --- a/simgear/hla/HLAPropertyDataElement.cxx +++ b/simgear/hla/HLAPropertyDataElement.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 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 @@ -15,197 +15,424 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + #include "HLAPropertyDataElement.hxx" +#include "HLAArrayDataElement.hxx" +#include "HLABasicDataElement.hxx" +#include "HLADataElementVisitor.hxx" #include "HLADataTypeVisitor.hxx" +#include "HLAFixedRecordDataElement.hxx" +#include "HLAVariantRecordDataElement.hxx" namespace simgear { -class HLAPropertyDataElement::DecodeVisitor : public HLADataTypeDecodeVisitor { +class HLAPropertyDataElement::ScalarDecodeVisitor : public HLADataTypeDecodeVisitor { public: - DecodeVisitor(HLADecodeStream& stream, HLAPropertyReference& propertyReference) : + ScalarDecodeVisitor(HLADecodeStream& stream, SGPropertyNode& propertyNode) : HLADataTypeDecodeVisitor(stream), - _propertyReference(propertyReference) + _propertyNode(propertyNode) + { } + virtual ~ScalarDecodeVisitor() { } virtual void apply(const HLAInt8DataType& dataType) { int8_t value = 0; dataType.decode(_stream, value); - _propertyReference.setIntValue(value); + _propertyNode.setIntValue(value); } virtual void apply(const HLAUInt8DataType& dataType) { uint8_t value = 0; dataType.decode(_stream, value); - _propertyReference.setIntValue(value); + _propertyNode.setIntValue(value); } virtual void apply(const HLAInt16DataType& dataType) { int16_t value = 0; dataType.decode(_stream, value); - _propertyReference.setIntValue(value); + _propertyNode.setIntValue(value); } virtual void apply(const HLAUInt16DataType& dataType) { uint16_t value = 0; dataType.decode(_stream, value); - _propertyReference.setIntValue(value); + _propertyNode.setIntValue(value); } virtual void apply(const HLAInt32DataType& dataType) { int32_t value = 0; dataType.decode(_stream, value); - _propertyReference.setIntValue(value); + _propertyNode.setIntValue(value); } virtual void apply(const HLAUInt32DataType& dataType) { uint32_t value = 0; dataType.decode(_stream, value); - _propertyReference.setIntValue(value); + _propertyNode.setIntValue(value); } virtual void apply(const HLAInt64DataType& dataType) { int64_t value = 0; dataType.decode(_stream, value); - _propertyReference.setLongValue(value); + _propertyNode.setLongValue(value); } virtual void apply(const HLAUInt64DataType& dataType) { uint64_t value = 0; dataType.decode(_stream, value); - _propertyReference.setLongValue(value); + _propertyNode.setLongValue(value); } virtual void apply(const HLAFloat32DataType& dataType) { float value = 0; dataType.decode(_stream, value); - _propertyReference.setFloatValue(value); + _propertyNode.setFloatValue(value); } virtual void apply(const HLAFloat64DataType& dataType) { double value = 0; dataType.decode(_stream, value); - _propertyReference.setDoubleValue(value); + _propertyNode.setDoubleValue(value); } - virtual void apply(const HLAFixedArrayDataType& dataType) +protected: + SGPropertyNode& _propertyNode; +}; + +class HLAPropertyDataElement::ScalarEncodeVisitor : public HLADataTypeEncodeVisitor { +public: + ScalarEncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) : + HLADataTypeEncodeVisitor(stream), + _propertyNode(propertyNode) + { } + virtual ~ScalarEncodeVisitor() + { } + + virtual void apply(const HLAInt8DataType& 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()); - } - _propertyReference.setStringValue(value); + dataType.encode(_stream, _propertyNode.getIntValue()); } - virtual void apply(const HLAVariableArrayDataType& dataType) + virtual void apply(const HLAUInt8DataType& dataType) { - HLATemplateDecodeVisitor numElementsVisitor(_stream); - dataType.getSizeDataType()->accept(numElementsVisitor); - unsigned numElements = numElementsVisitor.getValue(); - 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()); - } - _propertyReference.setStringValue(value); + dataType.encode(_stream, _propertyNode.getIntValue()); + } + virtual void apply(const HLAInt16DataType& dataType) + { + dataType.encode(_stream, _propertyNode.getIntValue()); + } + virtual void apply(const HLAUInt16DataType& dataType) + { + dataType.encode(_stream, _propertyNode.getIntValue()); + } + virtual void apply(const HLAInt32DataType& dataType) + { + dataType.encode(_stream, _propertyNode.getIntValue()); + } + virtual void apply(const HLAUInt32DataType& dataType) + { + dataType.encode(_stream, _propertyNode.getIntValue()); + } + virtual void apply(const HLAInt64DataType& dataType) + { + dataType.encode(_stream, _propertyNode.getLongValue()); + } + virtual void apply(const HLAUInt64DataType& dataType) + { + dataType.encode(_stream, _propertyNode.getLongValue()); + } + virtual void apply(const HLAFloat32DataType& dataType) + { + dataType.encode(_stream, _propertyNode.getFloatValue()); + } + virtual void apply(const HLAFloat64DataType& dataType) + { + dataType.encode(_stream, _propertyNode.getDoubleValue()); } protected: - HLAPropertyReference& _propertyReference; + const SGPropertyNode& _propertyNode; }; -class HLAPropertyDataElement::EncodeVisitor : public HLADataTypeEncodeVisitor { +class HLAPropertyDataElement::ScalarDataElement : public HLABasicDataElement { public: - EncodeVisitor(HLAEncodeStream& stream, const HLAPropertyReference& propertyReference) : - HLADataTypeEncodeVisitor(stream), - _propertyReference(propertyReference) + ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode); + virtual ~ScalarDataElement(); + + virtual bool encode(HLAEncodeStream& stream) const; + virtual bool decode(HLADecodeStream& stream); + +private: + SGSharedPtr _propertyNode; +}; + +HLAPropertyDataElement::ScalarDataElement::ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode) : + HLABasicDataElement(dataType), + _propertyNode(propertyNode) +{ +} + +HLAPropertyDataElement::ScalarDataElement::~ScalarDataElement() +{ +} + +bool +HLAPropertyDataElement::ScalarDataElement::encode(HLAEncodeStream& stream) const +{ + ScalarEncodeVisitor visitor(stream, *_propertyNode); + _dataType->accept(visitor); + return true; +} + +bool +HLAPropertyDataElement::ScalarDataElement::decode(HLADecodeStream& stream) +{ + ScalarDecodeVisitor visitor(stream, *_propertyNode); + _dataType->accept(visitor); + return true; +} + +class HLAPropertyDataElement::StringDataElement : public HLAStringDataElement { +public: + StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode); + virtual ~StringDataElement(); + + virtual bool decodeElement(HLADecodeStream& stream, unsigned i); + + class Listener : public SGPropertyChangeListener { + public: + Listener(StringDataElement* stringDataElement); + virtual ~Listener(); + virtual void valueChanged (SGPropertyNode * node); + private: + StringDataElement* _stringDataElement; + }; + +private: + SGSharedPtr _propertyNode; + Listener* _listener; +}; + +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::decodeElement(HLADecodeStream& stream, unsigned i) +{ + if (!HLAStringDataElement::decodeElement(stream, i)) + return false; + if (i + 1 == getValue().size()) + _propertyNode->setStringValue(getValue()); + return true; +} + +class HLAPropertyDataElement::DataElementFactoryVisitor : public HLADataTypeVisitor { +public: + DataElementFactoryVisitor(SGPropertyNode* propertyNode) : + _propertyNode(propertyNode) + { } + virtual ~DataElementFactoryVisitor() { } + virtual void apply(const HLADataType& dataType) + { + SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \"" + << dataType.getName() << "\""); + } + virtual void apply(const HLAInt8DataType& dataType) { - dataType.encode(_stream, _propertyReference.getIntValue()); + _dataElement = new ScalarDataElement(&dataType, _propertyNode.get()); } virtual void apply(const HLAUInt8DataType& dataType) { - dataType.encode(_stream, _propertyReference.getIntValue()); + _dataElement = new ScalarDataElement(&dataType, _propertyNode.get()); } virtual void apply(const HLAInt16DataType& dataType) { - dataType.encode(_stream, _propertyReference.getIntValue()); + _dataElement = new ScalarDataElement(&dataType, _propertyNode.get()); } virtual void apply(const HLAUInt16DataType& dataType) { - dataType.encode(_stream, _propertyReference.getIntValue()); + _dataElement = new ScalarDataElement(&dataType, _propertyNode.get()); } virtual void apply(const HLAInt32DataType& dataType) { - dataType.encode(_stream, _propertyReference.getIntValue()); + _dataElement = new ScalarDataElement(&dataType, _propertyNode.get()); } virtual void apply(const HLAUInt32DataType& dataType) { - dataType.encode(_stream, _propertyReference.getIntValue()); + _dataElement = new ScalarDataElement(&dataType, _propertyNode.get()); } virtual void apply(const HLAInt64DataType& dataType) { - dataType.encode(_stream, _propertyReference.getLongValue()); + _dataElement = new ScalarDataElement(&dataType, _propertyNode.get()); } virtual void apply(const HLAUInt64DataType& dataType) { - dataType.encode(_stream, _propertyReference.getLongValue()); + _dataElement = new ScalarDataElement(&dataType, _propertyNode.get()); } virtual void apply(const HLAFloat32DataType& dataType) { - dataType.encode(_stream, _propertyReference.getFloatValue()); + _dataElement = new ScalarDataElement(&dataType, _propertyNode.get()); } virtual void apply(const HLAFloat64DataType& dataType) { - dataType.encode(_stream, _propertyReference.getDoubleValue()); + _dataElement = new ScalarDataElement(&dataType, _propertyNode.get()); } + class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory { + public: + ArrayDataElementFactory(SGPropertyNode* propertyNode) : + _propertyNode(propertyNode) + { } + virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index) + { + const HLADataType* dataType = element.getElementDataType(); + if (!dataType) + return 0; + + SGPropertyNode* parent = _propertyNode->getParent(); + DataElementFactoryVisitor visitor(parent->getChild(_propertyNode->getNameString(), index, true)); + dataType->accept(visitor); + return visitor.getDataElement(); + } + private: + SGSharedPtr _propertyNode; + }; + virtual void apply(const HLAFixedArrayDataType& dataType) { - unsigned numElements = dataType.getNumElements(); - std::string value = _propertyReference.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); - } + if (dataType.getIsString()) { + _dataElement = new StringDataElement(&dataType, _propertyNode.get()); + } else { + SGSharedPtr arrayDataElement; + arrayDataElement = new HLAArrayDataElement(&dataType); + arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get())); + arrayDataElement->setNumElements(dataType.getNumElements()); + _dataElement = arrayDataElement; } } virtual void apply(const HLAVariableArrayDataType& dataType) { - std::string value = _propertyReference.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); + if (dataType.getIsString()) { + _dataElement = new StringDataElement(&dataType, _propertyNode.get()); + } else { + SGSharedPtr arrayDataElement; + arrayDataElement = new HLAArrayDataElement(&dataType); + arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get())); + _dataElement = arrayDataElement; } } -protected: - const HLAPropertyReference& _propertyReference; + virtual void apply(const HLAEnumeratedDataType& dataType) + { + _dataElement = new ScalarDataElement(dataType.getRepresentation(), _propertyNode.get()); + } + + virtual void apply(const HLAFixedRecordDataType& dataType) + { + SGSharedPtr recordDataElement; + recordDataElement = new HLAFixedRecordDataElement(&dataType); + + unsigned numFields = dataType.getNumFields(); + for (unsigned i = 0; i < numFields; ++i) { + DataElementFactoryVisitor visitor(_propertyNode->getChild(dataType.getFieldName(i), 0, true)); + dataType.getFieldDataType(i)->accept(visitor); + recordDataElement->setField(i, visitor._dataElement.get()); + } + + _dataElement = recordDataElement; + } + + class VariantRecordDataElementFactory : public HLAVariantRecordDataElement::DataElementFactory { + public: + VariantRecordDataElementFactory(SGPropertyNode* propertyNode) : + _propertyNode(propertyNode) + { } + virtual HLADataElement* createElement(const HLAVariantRecordDataElement& element, unsigned index) + { + const HLAVariantRecordDataType* dataType = element.getDataType(); + if (!dataType) + return 0; + const HLADataType* alternativeDataType = element.getAlternativeDataType(); + if (!alternativeDataType) + return 0; + DataElementFactoryVisitor visitor(_propertyNode->getChild(dataType->getAlternativeName(index), 0, true)); + alternativeDataType->accept(visitor); + return visitor.getDataElement(); + } + private: + SGSharedPtr _propertyNode; + }; + + virtual void apply(const HLAVariantRecordDataType& dataType) + { + SGSharedPtr variantRecordDataElement; + variantRecordDataElement = new HLAVariantRecordDataElement(&dataType); + variantRecordDataElement->setDataElementFactory(new VariantRecordDataElementFactory(_propertyNode.get())); + _dataElement = variantRecordDataElement; + } + + HLADataElement* getDataElement() + { return _dataElement.release(); } + +private: + SGSharedPtr _propertyNode; + SGSharedPtr _dataElement; }; -HLAPropertyDataElement::HLAPropertyDataElement(HLAPropertyReference* propertyReference) : - _propertyReference(propertyReference) +HLAPropertyDataElement::HLAPropertyDataElement() +{ +} + +HLAPropertyDataElement::HLAPropertyDataElement(SGPropertyNode* propertyNode) +{ + setPropertyNode(propertyNode); +} + +HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType, SGPropertyNode* propertyNode) : + _dataType(dataType) { + setPropertyNode(propertyNode); } -HLAPropertyDataElement::HLAPropertyDataElement(const simgear::HLADataType* dataType, HLAPropertyReference* propertyReference) : - _dataType(dataType), - _propertyReference(propertyReference) +HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType) : + _dataType(dataType) { } @@ -213,34 +440,72 @@ 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 { - if (!_dataType.valid()) - return false; - if (_propertyReference.valid()) { - EncodeVisitor visitor(stream, *_propertyReference); - _dataType->accept(visitor); + if (_dataElement.valid()) { + return _dataElement->encode(stream); } else { + if (!_dataType.valid()) + return false; HLADataTypeEncodeVisitor visitor(stream); _dataType->accept(visitor); + return true; } - return true; } bool HLAPropertyDataElement::decode(HLADecodeStream& stream) { - if (!_dataType.valid()) + if (_dataElement.valid()) { + return _dataElement->decode(stream); + } else if (!_dataType.valid()) { + // We cant do anything if the data type is not valid return false; - if (_propertyReference.valid()) { - DecodeVisitor visitor(stream, *_propertyReference); - _dataType->accept(visitor); } else { - HLADataTypeDecodeVisitor visitor(stream); + HLADataElementFactoryVisitor visitor; _dataType->accept(visitor); + _dataElement = visitor.getDataElement(); + if (_dataElement.valid()) { + return _dataElement->decode(stream); + } else { + HLADataTypeDecodeVisitor visitor(stream); + _dataType->accept(visitor); + return true; + } } - return true; } const HLADataType* @@ -252,18 +517,52 @@ HLAPropertyDataElement::getDataType() const bool HLAPropertyDataElement::setDataType(const HLADataType* dataType) { - if (dataType->toBasicDataType()) { - _dataType = dataType; - return true; - } else { - const HLAArrayDataType* arrayDataType = dataType->toArrayDataType(); - if (arrayDataType && arrayDataType->getElementDataType() && - arrayDataType->getElementDataType()->toBasicDataType()) { - _dataType = dataType; - return true; + _dataType = dataType; + if (_dataType.valid() && _propertyNode.valid()) + _dataElement = createDataElement(_dataType, _propertyNode); + return true; +} + +void +HLAPropertyDataElement::setPropertyNode(SGPropertyNode* propertyNode) +{ + _propertyNode = propertyNode; + if (_dataType.valid() && _propertyNode.valid()) + _dataElement = createDataElement(_dataType, _propertyNode); +} + +SGPropertyNode* +HLAPropertyDataElement::getPropertyNode() +{ + return _propertyNode.get(); +} + +const SGPropertyNode* +HLAPropertyDataElement::getPropertyNode() const +{ + return _propertyNode.get(); +} + +HLADataElement* +HLAPropertyDataElement::createDataElement(const SGSharedPtr& dataType, + const SGSharedPtr& propertyNode) +{ + DataElementFactoryVisitor visitor(propertyNode); + dataType->accept(visitor); + SGSharedPtr dataElement = visitor.getDataElement(); + + // Copy over the content of the previous data element if there is any. + if (_dataElement.valid()) { + // FIXME is encode/decode the right tool here?? + RTIData data; + HLAEncodeStream encodeStream(data); + if (_dataElement->encode(encodeStream)) { + HLADecodeStream decodeStream(data); + dataElement->decode(decodeStream); } } - return false; + + return dataElement.release(); } } // namespace simgear