]> git.mxchange.org Git - simgear.git/commitdiff
hla: provide a more general property data element implementation.
authorMathias Froehlich <Mathias.Froehlich@web.de>
Tue, 4 Oct 2011 18:32:34 +0000 (20:32 +0200)
committerMathias Froehlich <Mathias.Froehlich@web.de>
Tue, 4 Oct 2011 18:32:34 +0000 (20:32 +0200)
simgear/hla/HLAPropertyDataElement.cxx
simgear/hla/HLAPropertyDataElement.hxx

index 121edddab952eab6db7e047764487e816267b6ba..e8a931ee27c0ed8432553fef3c9432dfbbac60d6 100644 (file)
@@ -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
 
 #include "HLAPropertyDataElement.hxx"
 
+#include "HLAArrayDataElement.hxx"
 #include "HLADataTypeVisitor.hxx"
+#include "HLAFixedRecordDataElement.hxx"
+#include "HLAVariantDataElement.hxx"
 
 namespace simgear {
 
-class HLAPropertyDataElement::DecodeVisitor : public HLADataTypeDecodeVisitor {
+class HLAPropertyDataElement::ScalarDecodeVisitor : public HLADataTypeDecodeVisitor {
 public:
-    DecodeVisitor(HLADecodeStream& stream, SGPropertyNode& propertyNode) :
+    ScalarDecodeVisitor(HLADecodeStream& stream, SGPropertyNode& propertyNode) :
         HLADataTypeDecodeVisitor(stream),
         _propertyNode(propertyNode)
     { }
+    virtual ~ScalarDecodeVisitor()
+    { }
 
     virtual void apply(const HLAInt8DataType& dataType)
     {
@@ -89,43 +94,18 @@ public:
         _propertyNode.setDoubleValue(value);
     }
 
-    virtual void apply(const HLAFixedArrayDataType& dataType)
-    {
-        unsigned numElements = dataType.getNumElements();
-        std::string value;
-        value.reserve(numElements);
-        for (unsigned i = 0; i < numElements; ++i) {
-            HLATemplateDecodeVisitor<char> visitor(_stream);
-            dataType.getElementDataType()->accept(visitor);
-            value.push_back(visitor.getValue());
-        }
-        _propertyNode.setStringValue(value);
-    }
-    virtual void apply(const HLAVariableArrayDataType& dataType)
-    {
-        HLATemplateDecodeVisitor<unsigned> numElementsVisitor(_stream);
-        dataType.getSizeDataType()->accept(numElementsVisitor);
-        unsigned numElements = numElementsVisitor.getValue();
-        std::string value;
-        value.reserve(numElements);
-        for (unsigned i = 0; i < numElements; ++i) {
-            HLATemplateDecodeVisitor<char> visitor(_stream);
-            dataType.getElementDataType()->accept(visitor);
-            value.push_back(visitor.getValue());
-        }
-        _propertyNode.setStringValue(value);
-    }
-
 protected:
     SGPropertyNode& _propertyNode;
 };
 
-class HLAPropertyDataElement::EncodeVisitor : public HLADataTypeEncodeVisitor {
+class HLAPropertyDataElement::ScalarEncodeVisitor : public HLADataTypeEncodeVisitor {
 public:
-    EncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) :
+    ScalarEncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) :
         HLADataTypeEncodeVisitor(stream),
         _propertyNode(propertyNode)
     { }
+    virtual ~ScalarEncodeVisitor()
+    { }
 
     virtual void apply(const HLAInt8DataType& dataType)
     {
@@ -168,6 +148,116 @@ public:
         dataType.encode(_stream, _propertyNode.getDoubleValue());
     }
 
+protected:
+    const SGPropertyNode& _propertyNode;
+};
+
+class HLAPropertyDataElement::ScalarDataElement : public HLADataElement {
+public:
+    ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode);
+    virtual ~ScalarDataElement();
+
+    virtual bool encode(HLAEncodeStream& stream) const;
+    virtual bool decode(HLADecodeStream& stream);
+
+    virtual const HLADataType* getDataType() const;
+    virtual bool setDataType(const HLADataType* dataType);
+
+private:
+    SGSharedPtr<const HLABasicDataType> _dataType;
+    SGSharedPtr<SGPropertyNode> _propertyNode;
+};
+
+HLAPropertyDataElement::ScalarDataElement::ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode) :
+    _dataType(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;
+}
+
+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<char> visitor(_stream);
+            dataType.getElementDataType()->accept(visitor);
+            value.push_back(visitor.getValue());
+        }
+        _propertyNode.setStringValue(value);
+    }
+    virtual void apply(const HLAVariableArrayDataType& dataType)
+    {
+        HLATemplateDecodeVisitor<std::string::size_type> 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<char> 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();
@@ -198,6 +288,228 @@ protected:
     const SGPropertyNode& _propertyNode;
 };
 
+class HLAPropertyDataElement::StringDataElement : public HLADataElement {
+public:
+    StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode);
+    virtual ~StringDataElement();
+
+    virtual bool encode(HLAEncodeStream& stream) const;
+    virtual bool decode(HLADecodeStream& stream);
+
+    virtual const HLADataType* getDataType() const;
+    virtual bool setDataType(const HLADataType* dataType);
+
+private:
+    SGSharedPtr<const HLAArrayDataType> _dataType;
+    SGSharedPtr<SGPropertyNode> _propertyNode;
+};
+
+HLAPropertyDataElement::StringDataElement::StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode) :
+    _dataType(dataType),
+    _propertyNode(propertyNode)
+{
+}
+
+HLAPropertyDataElement::StringDataElement::~StringDataElement()
+{
+}
+
+bool
+HLAPropertyDataElement::StringDataElement::encode(HLAEncodeStream& stream) const
+{
+    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)
+        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;
+    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)
+    {
+        _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
+    }
+    virtual void apply(const HLAUInt8DataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
+    }
+    virtual void apply(const HLAInt16DataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
+    }
+    virtual void apply(const HLAUInt16DataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
+    }
+    virtual void apply(const HLAInt32DataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
+    }
+    virtual void apply(const HLAUInt32DataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
+    }
+    virtual void apply(const HLAInt64DataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
+    }
+    virtual void apply(const HLAUInt64DataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
+    }
+    virtual void apply(const HLAFloat32DataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
+    }
+    virtual void apply(const HLAFloat64DataType& dataType)
+    {
+        _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<SGPropertyNode> _propertyNode;
+    };
+
+    virtual void apply(const HLAFixedArrayDataType& dataType)
+    {
+        if (dataType.getIsString()) {
+            _dataElement = new StringDataElement(&dataType, _propertyNode.get());
+        } else {
+            SGSharedPtr<HLAArrayDataElement> arrayDataElement;
+            arrayDataElement = new HLAArrayDataElement(&dataType);
+            arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get()));
+            arrayDataElement->setNumElements(dataType.getNumElements());
+            _dataElement = arrayDataElement;
+        }
+    }
+
+    virtual void apply(const HLAVariableArrayDataType& dataType)
+    {
+        if (dataType.getIsString()) {
+            _dataElement = new StringDataElement(&dataType, _propertyNode.get());
+        } else {
+            SGSharedPtr<HLAArrayDataElement> arrayDataElement;
+            arrayDataElement = new HLAArrayDataElement(&dataType);
+            arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get()));
+            _dataElement = arrayDataElement;
+        }
+    }
+
+    virtual void apply(const HLAEnumeratedDataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(dataType.getRepresentation(), _propertyNode.get());
+    }
+
+    virtual void apply(const HLAFixedRecordDataType& dataType)
+    {
+        SGSharedPtr<HLAFixedRecordDataElement> 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 VariantDataElementFactory : public HLAVariantDataElement::DataElementFactory {
+    public:
+        VariantDataElementFactory(SGPropertyNode* propertyNode) :
+            _propertyNode(propertyNode)
+        { }
+        virtual HLADataElement* createElement(const HLAVariantDataElement& element, unsigned index)
+        {
+            const HLAVariantDataType* 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<SGPropertyNode> _propertyNode;
+    };
+
+    virtual void apply(const HLAVariantDataType& dataType)
+    {
+        SGSharedPtr<HLAVariantDataElement> variantDataElement;
+        variantDataElement = new HLAVariantDataElement(&dataType);
+        variantDataElement->setDataElementFactory(new VariantDataElementFactory(_propertyNode.get()));
+        _dataElement = variantDataElement;
+    }
+
+    HLADataElement* getDataElement()
+    { return _dataElement.release(); }
+
+private:
+    SGSharedPtr<SGPropertyNode> _propertyNode;
+    SGSharedPtr<HLADataElement> _dataElement;
+};
+
 HLAPropertyDataElement::HLAPropertyDataElement()
 {
 }
@@ -225,31 +537,37 @@ HLAPropertyDataElement::~HLAPropertyDataElement()
 bool
 HLAPropertyDataElement::encode(HLAEncodeStream& stream) const
 {
-    if (!_dataType.valid())
-        return false;
-    if (const SGPropertyNode* propertyNode = getPropertyNode()) {
-        EncodeVisitor visitor(stream, *propertyNode);
-        _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 (SGPropertyNode* propertyNode = getPropertyNode()) {
-        DecodeVisitor visitor(stream, *propertyNode);
-        _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*
@@ -261,24 +579,18 @@ 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;
-        }
-    }
-    return false;
+    _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*
@@ -293,4 +605,26 @@ HLAPropertyDataElement::getPropertyNode() const
     return _propertyNode.get();
 }
 
+HLADataElement*
+HLAPropertyDataElement::createDataElement(const SGSharedPtr<const HLADataType>& dataType,
+                                          const SGSharedPtr<SGPropertyNode>& propertyNode)
+{
+    DataElementFactoryVisitor visitor(propertyNode);
+    dataType->accept(visitor);
+    SGSharedPtr<HLADataElement> 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 dataElement.release();
+}
+
 } // namespace simgear
index 076d85ba5ce5e5c0aad1c39e365583bbc8dc297f..4354a1d9fa4802053c751bcb29a379d73796cf42 100644 (file)
@@ -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
@@ -42,10 +42,19 @@ public:
     const SGPropertyNode* getPropertyNode() const;
     
 private:
-    class DecodeVisitor;
-    class EncodeVisitor;
+    HLADataElement*
+    createDataElement(const SGSharedPtr<const HLADataType>& dataType, const SGSharedPtr<SGPropertyNode>& propertyNode);
+    
+    class ScalarDecodeVisitor;
+    class ScalarEncodeVisitor;
+    class ScalarDataElement;
+    class StringDecodeVisitor;
+    class StringEncodeVisitor;
+    class StringDataElement;
+    class DataElementFactoryVisitor;
 
     SGSharedPtr<const HLADataType> _dataType;
+    SGSharedPtr<HLADataElement> _dataElement;
     SGSharedPtr<SGPropertyNode> _propertyNode;
 };