]> git.mxchange.org Git - simgear.git/commitdiff
hla: Introduce HLADataElementIndex.
authorMathias Froehlich <Mathias.Froehlich@web.de>
Thu, 8 Nov 2012 20:31:16 +0000 (21:31 +0100)
committerMathias Froehlich <Mathias.Froehlich@web.de>
Thu, 8 Nov 2012 21:51:02 +0000 (22:51 +0100)
15 files changed:
simgear/hla/HLAArrayDataElement.cxx
simgear/hla/HLAArrayDataElement.hxx
simgear/hla/HLADataElement.cxx
simgear/hla/HLADataElement.hxx
simgear/hla/HLADataType.cxx
simgear/hla/HLADataType.hxx
simgear/hla/HLAFixedRecordDataElement.cxx
simgear/hla/HLAFixedRecordDataElement.hxx
simgear/hla/HLAObjectClass.cxx
simgear/hla/HLAObjectClass.hxx
simgear/hla/HLAObjectInstance.cxx
simgear/hla/HLAObjectInstance.hxx
simgear/hla/HLATypes.hxx
simgear/hla/HLAVariantRecordDataElement.cxx
simgear/hla/HLAVariantRecordDataElement.hxx

index 47cebb58bc566bf994be8590f7e353aa8c81f85b..191a84eb1d766130bcbe0c789c710526d1c923e5 100644 (file)
@@ -108,6 +108,54 @@ HLAArrayDataElement::~HLAArrayDataElement()
     clearStamp();
 }
 
+bool
+HLAArrayDataElement::setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement)
+{
+    // Must have happened in the parent
+    if (begin == end)
+        return false;
+    unsigned index = *begin;
+    if (++begin != end) {
+        if (getNumElements() <= index && !setNumElements(index + 1))
+            return false;
+        if (!getElement(index) && getElementDataType()) {
+            HLADataElementFactoryVisitor visitor;
+            getElementDataType()->accept(visitor);
+            setElement(index, visitor.getDataElement());
+        }
+        if (!getElement(index))
+            return false;
+        return getElement(index)->setDataElement(begin, end, dataElement);
+    } else {
+        if (!dataElement->setDataType(getElementDataType()))
+            return false;
+        setElement(index, dataElement);
+        return true;
+    }
+}
+
+HLADataElement*
+HLAArrayDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end)
+{
+    if (begin == end)
+        return this;
+    HLADataElement* dataElement = getElement(*begin);
+    if (!dataElement)
+        return 0;
+    return dataElement->getDataElement(++begin, end);
+}
+
+const HLADataElement*
+HLAArrayDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const
+{
+    if (begin == end)
+        return this;
+    const HLADataElement* dataElement = getElement(*begin);
+    if (!dataElement)
+        return 0;
+    return dataElement->getDataElement(++begin, end);
+}
+
 bool
 HLAArrayDataElement::setNumElements(unsigned size)
 {
index 72f1478b878476d99ae371868cc1e0819a7b197c..9bdd71054f87be3cc5ffea6629eac86497b423c9 100644 (file)
@@ -59,6 +59,10 @@ public:
     HLAArrayDataElement(const HLAArrayDataType* dataType = 0);
     virtual ~HLAArrayDataElement();
 
+    virtual bool setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement);
+    virtual HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end);
+    virtual const HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const;
+
     virtual bool setNumElements(unsigned size);
     virtual bool decodeElement(HLADecodeStream& stream, unsigned i);
     virtual unsigned getNumElements() const;
index bdccf5d8612a27a48607143e1da63d222e9dc74e..69a32d1e0b674beb3cabcb6b3a21141922d80acd 100644 (file)
@@ -137,6 +137,28 @@ HLADataElement::~HLADataElement()
 {
 }
 
+bool
+HLADataElement::setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement)
+{
+    return false;
+}
+
+HLADataElement*
+HLADataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end)
+{
+    if (begin != end)
+        return 0;
+    return this;
+}
+
+const HLADataElement*
+HLADataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const
+{
+    if (begin != end)
+        return 0;
+    return this;
+}
+
 void
 HLADataElement::setTimeStamp(const SGTimeStamp& timeStamp)
 {
index 079c5cecd4625074023dda4653b02a5598a86832..ffbaf5df8dade297be8249e6bd569358d9a29cfd 100644 (file)
@@ -25,6 +25,7 @@
 #include <simgear/timing/timestamp.hxx>
 #include "RTIData.hxx"
 #include "HLADataType.hxx"
+#include "HLATypes.hxx"
 
 class SGTimeStamp;
 
@@ -46,6 +47,17 @@ public:
     virtual const HLADataType* getDataType() const = 0;
     virtual bool setDataType(const HLADataType* dataType) = 0;
 
+    bool setDataElement(const HLADataElementIndex& index, HLADataElement* dataElement)
+    { return setDataElement(index.begin(), index.end(), dataElement); }
+    HLADataElement* getDataElement(const HLADataElementIndex& index)
+    { return getDataElement(index.begin(), index.end()); }
+    const HLADataElement* getDataElement(const HLADataElementIndex& index) const
+    { return getDataElement(index.begin(), index.end()); }
+
+    virtual bool setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement);
+    virtual HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end);
+    virtual const HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const;
+
     /// Returns the time stamp if this data element.
     /// Do not access this getter if the getTimeStampValid() method returns false.
     const SGTimeStamp& getTimeStamp() const
index ec3359338c81e3cc5f36db6e75ed9b5cc3beccdc..ff9b2f19ada5afc88178f16d92500b757c11a3f6 100644 (file)
@@ -88,6 +88,161 @@ HLADataType::releaseDataTypeReferences()
 {
 }
 
+class HLADataType::_DataElementIndexVisitor : public HLADataTypeVisitor {
+public:
+    _DataElementIndexVisitor(HLADataElementIndex& index, const std::string& path, size_t offset) :
+        _index(index),
+        _path(path),
+        _offset(offset),
+        _success(false)
+    { }
+    virtual ~_DataElementIndexVisitor()
+    { }
+
+    virtual void apply(const HLADataType& dataType)
+    {
+        if (_path.size() == _offset)
+            _success = true;
+    }
+    virtual void apply(const HLAArrayDataType& dataType)
+    {
+        if (_path.size() <= _offset) {
+            SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+                   << "Expected array subscript at the end of the path!");
+            return;
+        }
+        if (_path[_offset] != '[') {
+            SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+                   << "Expected array subscript at the end of the path!");
+            return;
+        }
+        ++_offset;
+        if (_path.size() <= _offset) {
+            SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+                   << "Expected closing array subscript at the end of the path!");
+            return;
+        }
+        unsigned index = 0;
+        bool closed = false;
+        while (_offset <= _path.size()) {
+            if (_path[_offset] == ']') {
+                ++_offset;
+                closed = true;
+                break;
+            }
+            unsigned v = _path[_offset] - '0';
+            // Error, no number
+            if (10 <= v) {
+                SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+                       << "Array subscript is not a number!");
+                return;
+            }
+            index *= 10;
+            index += v;
+            ++_offset;
+        }
+        if (!closed) {
+            SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+                   << "Expected closing array subscript at the end of the path!");
+            return;
+        }
+        if (!dataType.getElementDataType()) {
+            SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+                   << "Undefined array element data type!");
+            return;
+        }
+        _index.push_back(index);
+        _success = dataType.getElementDataType()->getDataElementIndex(_index, _path, _offset);
+    }
+
+    virtual void apply(const HLAFixedRecordDataType& dataType)
+    {
+        if (_path.size() <= _offset) {
+            SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+                   << "Expected field name at the end of the path!");
+            return;
+        }
+        if (_path[_offset] == '.')
+            ++_offset;
+        if (_path.size() <= _offset) {
+            SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+                   << "Expected field name at the end of the path!");
+            return;
+        }
+        size_t len = _path.find_first_of("[.", _offset) - _offset;
+        unsigned index = 0;
+        while (index < dataType.getNumFields()) {
+            if (_path.compare(_offset, len, dataType.getFieldName(index)) == 0)
+                break;
+            ++index;
+        }
+        if (dataType.getNumFields() <= index) {
+            SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+                   << "Field \"" << _path.substr(_offset, len) << "\" not found in fixed record data type \""
+                   << dataType.getName() << "\"!");
+            return;
+        }
+        if (!dataType.getFieldDataType(index)) {
+            SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+                   << "Undefined field data type in variant record data type \""
+                   << dataType.getName() << "\" at field \"" << dataType.getFieldName(index) << "\"!");
+            return;
+        }
+        _index.push_back(index);
+        _success = dataType.getFieldDataType(index)->getDataElementIndex(_index, _path, _offset + len);
+    }
+
+    virtual void apply(const HLAVariantRecordDataType& dataType)
+    {
+        if (_path.size() <= _offset) {
+            SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+                   << "Expected alternative name at the end of the path!");
+            return;
+        }
+        if (_path[_offset] == '.')
+            ++_offset;
+        if (_path.size() <= _offset) {
+            SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+                   << "Expected alternative name at the end of the path!");
+            return;
+        }
+        size_t len = _path.find_first_of("[.", _offset) - _offset;
+        unsigned index = 0;
+        while (index < dataType.getNumAlternatives()) {
+            if (_path.compare(_offset, len, dataType.getAlternativeName(index)) == 0)
+                break;
+            ++index;
+        }
+        if (dataType.getNumAlternatives() <= index) {
+            SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+                   << "Alternative \"" << _path.substr(_offset, len) << "\" not found in variant record data type \""
+                   << dataType.getName() << "\"!");
+            return;
+        }
+        if (!dataType.getAlternativeDataType(index)) {
+            SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+                   << "Undefined alternative data type in variant record data type \""
+                   << dataType.getName() << "\" at alternative \"" << dataType.getAlternativeName(index) << "\"!");
+            return;
+        }
+        _index.push_back(index);
+        _success = dataType.getAlternativeDataType(index)->getDataElementIndex(_index, _path, _offset + len);
+    }
+
+    HLADataElementIndex& _index;
+    const std::string& _path;
+    size_t _offset;
+    bool _success;
+};
+
+bool
+HLADataType::getDataElementIndex(HLADataElementIndex& index, const std::string& path, size_t offset) const
+{
+    _DataElementIndexVisitor visitor(index, path, offset);
+    accept(visitor);
+    return visitor._success;
+}
+
 void
 HLADataType::setAlignment(unsigned alignment)
 {
index 6e15aade4c7e3daf2f86cb53bde0b8ee545b3621..7d045d9da84801acdd3b0dd77f36c1862d807d17 100644 (file)
@@ -22,6 +22,7 @@
 #include <simgear/structure/SGWeakPtr.hxx>
 #include <simgear/structure/SGWeakReferenced.hxx>
 #include "RTIData.hxx"
+#include "HLATypes.hxx"
 
 namespace simgear {
 
@@ -63,6 +64,8 @@ public:
     /// required for propper feeing of memory.
     virtual void releaseDataTypeReferences();
 
+    bool getDataElementIndex(HLADataElementIndex& index, const std::string& path, size_t offset) const;
+
 protected:
     HLADataType(const std::string& name, unsigned alignment = 1);
     void setAlignment(unsigned alignment);
@@ -70,6 +73,8 @@ protected:
     virtual void _recomputeAlignmentImplementation();
 
 private:
+    class _DataElementIndexVisitor;
+
     std::string _name;
     std::string _semantics;
     unsigned _alignment;
index 000339823eda0fa58a9b5c2edc0b6cef397fc6b1..f1275808537b384a1c583652958438a2eb30d81d 100644 (file)
@@ -146,6 +146,54 @@ HLAFixedRecordDataElement::setDataType(const HLADataType* dataType)
     return true;
 }
 
+bool
+HLAFixedRecordDataElement::setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement)
+{
+    // Must have happened in the parent
+    if (begin == end)
+        return false;
+    unsigned index = *begin;
+    if (++begin != end) {
+        if (getNumFields() <= index)
+            return false;
+        if (!getField(index) && getFieldDataType(index)) {
+            HLADataElementFactoryVisitor visitor;
+            getFieldDataType(index)->accept(visitor);
+            setField(index, visitor.getDataElement());
+        }
+        if (!getField(index))
+            return false;
+        return getField(index)->setDataElement(begin, end, dataElement);
+    } else {
+        if (!dataElement->setDataType(getFieldDataType(index)))
+            return false;
+        setField(index, dataElement);
+        return true;
+    }
+}
+
+HLADataElement*
+HLAFixedRecordDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end)
+{
+    if (begin == end)
+        return this;
+    HLADataElement* dataElement = getField(*begin);
+    if (!dataElement)
+        return 0;
+    return dataElement->getDataElement(++begin, end);
+}
+
+const HLADataElement*
+HLAFixedRecordDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const
+{
+    if (begin == end)
+        return this;
+    const HLADataElement* dataElement = getField(*begin);
+    if (!dataElement)
+        return 0;
+    return dataElement->getDataElement(++begin, end);
+}
+
 bool
 HLAFixedRecordDataElement::decodeField(HLADecodeStream& stream, unsigned i)
 {
index ef1f2c440cffe3ca4cc814fa32aa2ee472fa19ff..a614d619b2d06007056a0809a4cbf951d29ad8f5 100644 (file)
@@ -60,6 +60,10 @@ public:
 
     virtual bool setDataType(const HLADataType* dataType);
 
+    virtual bool setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement);
+    virtual HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end);
+    virtual const HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const;
+
     virtual bool decodeField(HLADecodeStream& stream, unsigned i);
     virtual bool encodeField(HLAEncodeStream& stream, unsigned i) const;
 
index aa9e7856f2889fc57dfc3fc7d182f3e8c4d9d4a9..06287c38a28e3cf5b622eb96616e4f865d20e162 100644 (file)
@@ -210,6 +210,36 @@ HLAObjectClass::getIndexPathPair(const std::string& path) const
     return getIndexPathPair(HLADataElement::toStringPathPair(path));
 }
 
+bool
+HLAObjectClass::getAttributeIndex(HLADataElementIndex& dataElementIndex, const std::string& path) const
+{
+    if (path.empty()) {
+        SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: failed to parse empty element path!");
+        return false;
+    }
+    size_t len = path.find_first_of("[.");
+    unsigned index = 0;
+    while (index < getNumAttributes()) {
+        if (path.compare(0, len, getAttributeName(index)) == 0)
+            break;
+        ++index;
+    }
+    if (getNumAttributes() <= index) {
+        SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: faild to parse data element index \"" << path << "\":\n"
+               << "Attribute \"" << path.substr(0, len) << "\" not found in object class \""
+               << getName() << "\"!");
+        return false;
+    }
+    if (!getAttributeDataType(index)) {
+        SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: faild to parse data element index \"" << path << "\":\n"
+               << "Undefined attribute data type in variant record data type \""
+               << getAttributeName(index) << "\"!");
+        return false;
+    }
+    dataElementIndex.push_back(index);
+    return getAttributeDataType(index)->getDataElementIndex(dataElementIndex, path, len);
+}
+
 bool
 HLAObjectClass::subscribe()
 {
index d80e4f8d5988d9527e39dde7be1f85471f2bbd7b..10767cf99c3d9705cc7422386817e2f649afa9a7 100644 (file)
@@ -77,6 +77,9 @@ public:
     /// Return the index, path pair for the given string path
     HLADataElement::IndexPathPair getIndexPathPair(const std::string& path) const;
 
+    /// Get the attribute data element index for the given path, return true if successful
+    bool getAttributeIndex(HLADataElementIndex& dataElementIndex, const std::string& path) const;
+
     virtual bool subscribe();
     virtual bool unsubscribe();
 
index 4b32ca084b3af1b3bd6aa730e6c87dff24caf781..ea8114a2bda1e402358915987ad13f0676dae2a0 100644 (file)
@@ -442,6 +442,87 @@ HLAObjectInstance::setAttributes(const HLAAttributePathElementMap& attributePath
     }
 }
 
+bool
+HLAObjectInstance::getAttributeIndex(HLADataElementIndex& index, const std::string& path) const
+{
+    HLAObjectClass* objectClass = getObjectClass().get();
+    if (!objectClass) {
+        SG_LOG(SG_IO, SG_ALERT, "Could not get the data element index of an object instance with unknown class!");
+        return false;
+    }
+    return objectClass->getAttributeIndex(index, path);
+}
+
+HLADataElement*
+HLAObjectInstance::getAttributeDataElement(const HLADataElementIndex& index)
+{
+    if (index.empty())
+        return 0;
+    HLADataElement* dataElement = getAttributeDataElement(index[0]);
+    if (!dataElement)
+        return 0;
+    return dataElement->getDataElement(index.begin() + 1, index.end());
+}
+
+const HLADataElement*
+HLAObjectInstance::getAttributeDataElement(const HLADataElementIndex& index) const
+{
+    if (index.empty())
+        return 0;
+    const HLADataElement* dataElement = getAttributeDataElement(index[0]);
+    if (!dataElement)
+        return 0;
+    return dataElement->getDataElement(index.begin() + 1, index.end());
+}
+
+void
+HLAObjectInstance::setAttributeDataElement(const HLADataElementIndex& index, const SGSharedPtr<HLADataElement>& dataElement)
+{
+    if (index.empty())
+        return;
+    if (index.size() == 1) {
+        if (!getAttributeDataType(index[0]))
+            return;
+        if (dataElement.valid() && !dataElement->setDataType(getAttributeDataType(index[0])))
+            return;
+        setAttributeDataElement(index[0], dataElement);
+    } else {
+        SGSharedPtr<HLADataElement> attributeDataElement = getAttributeDataElement(index[0]);
+        if (!attributeDataElement.valid())
+            attributeDataElement = createAttributeDataElement(index[0]);
+        if (!attributeDataElement.valid())
+            return;
+        attributeDataElement->setDataElement(index.begin() + 1, index.end(), dataElement.get());
+    }
+}
+
+HLADataElement*
+HLAObjectInstance::getAttributeDataElement(const std::string& path)
+{
+    HLADataElementIndex index;
+    if (!getAttributeIndex(index, path))
+        return 0;
+    return getAttributeDataElement(index); 
+}
+
+const HLADataElement*
+HLAObjectInstance::getAttributeDataElement(const std::string& path) const
+{
+    HLADataElementIndex index;
+    if (!getAttributeIndex(index, path))
+        return 0;
+    return getAttributeDataElement(index); 
+}
+
+void
+HLAObjectInstance::setAttributeDataElement(const std::string& path, const SGSharedPtr<HLADataElement>& dataElement)
+{
+    HLADataElementIndex index;
+    if (!getAttributeIndex(index, path))
+        return;
+    setAttributeDataElement(index, dataElement); 
+}
+
 void
 HLAObjectInstance::discoverInstance(const RTIData& tag)
 {
index bc78ada43f733146fb047118470657de9881efc7..cd18d06f7710af262861d3192e3243ccfe56ded3 100644 (file)
@@ -77,6 +77,25 @@ public:
     void setAttribute(unsigned index, const HLAPathElementMap& pathElementMap);
     void setAttributes(const HLAAttributePathElementMap& attributePathElementMap);
 
+    /// Retrieve the data element index for the given path.
+    bool getAttributeIndex(HLADataElementIndex& index, const std::string& path) const;
+
+    /// Return the data element of the attribute with the given index
+    HLADataElement* getAttributeDataElement(const HLADataElementIndex& index);
+    const HLADataElement* getAttributeDataElement(const HLADataElementIndex& index) const;
+    /// Set the data element of the attribute with the given index
+    void setAttributeDataElement(const HLADataElementIndex& index, const SGSharedPtr<HLADataElement>& dataElement);
+
+    /// Return the data element of the attribute with the given path.
+    /// The method is only for convenience as parsing the path is expensive.
+    /// Precompute the index and use the index instead if you use this method more often.
+    HLADataElement* getAttributeDataElement(const std::string& path);
+    const HLADataElement* getAttributeDataElement(const std::string& path) const;
+    /// Set the data element of the attribute with the given path
+    /// The method is only for convenience as parsing the path is expensive.
+    /// Precompute the index and use the index instead if you use this method more often.
+    void setAttributeDataElement(const std::string& path, const SGSharedPtr<HLADataElement>& dataElement);
+
     /// Gets called on discovering this object instance.
     virtual void discoverInstance(const RTIData& tag);
     /// Gets called on remove this object instance.
index b968b1cf0a0b88ba26e86235b919659ba31f2a56..dcbc6dd53f19ed23e91e7f3c6cc3dcff23b25014 100644 (file)
@@ -19,6 +19,7 @@
 #define HLATypes_hxx
 
 #include <list>
+#include <vector>
 
 namespace simgear {
 
@@ -42,6 +43,8 @@ enum HLAUpdateType {
 
 typedef std::list<unsigned> HLAIndexList;
 
+typedef std::vector<unsigned> HLADataElementIndex;
+
 } // namespace simgear
 
 #endif
index 6acb9fd521f969235de98c13224fc8025e331c79..704d4360d459e0e71f72627ea1f4e4e370979c00 100644 (file)
@@ -26,6 +26,7 @@
 #include <simgear/debug/logstream.hxx>
 
 #include "HLADataElementVisitor.hxx"
+#include "HLADataTypeVisitor.hxx"
 
 namespace simgear {
 
@@ -122,6 +123,58 @@ HLAVariantRecordDataElement::~HLAVariantRecordDataElement()
     clearStamp();
 }
 
+bool
+HLAVariantRecordDataElement::setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement)
+{
+    // Must have happened in the parent
+    if (begin == end)
+        return false;
+    unsigned index = *begin;
+    if (++begin != end) {
+        if (!setAlternativeIndex(index))
+            return false;
+        if (!_dataElement.valid() && getAlternativeDataType()) {
+            HLADataElementFactoryVisitor visitor;
+            getAlternativeDataType()->accept(visitor);
+            _dataElement = visitor.getDataElement();
+        }
+        if (!_dataElement.valid())
+            return false;
+        return _dataElement->setDataElement(begin, end, dataElement);
+    } else {
+        if (!setAlternativeIndex(index))
+            return false;
+        if (!dataElement->setDataType(getAlternativeDataType()))
+            return false;
+        _dataElement = dataElement;
+        return true;
+    }
+}
+
+HLADataElement*
+HLAVariantRecordDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end)
+{
+    if (begin == end)
+        return this;
+    if (getAlternativeIndex() != *begin)
+        return 0;
+    if (!_dataElement.valid())
+        return 0;
+    return _dataElement->getDataElement(++begin, end);
+}
+
+const HLADataElement*
+HLAVariantRecordDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const
+{
+    if (begin == end)
+        return this;
+    if (getAlternativeIndex() != *begin)
+        return 0;
+    if (!_dataElement.valid())
+        return 0;
+    return _dataElement->getDataElement(++begin, end);
+}
+
 bool
 HLAVariantRecordDataElement::setAlternativeIndex(unsigned index)
 {
index cc76efbb46bf7d926278c1731acdcd4719b14a70..0c6bcdde3728f24a5e08272d26fd9589fea933dd 100644 (file)
@@ -57,6 +57,10 @@ public:
     HLAVariantRecordDataElement(const HLAVariantRecordDataType* dataType);
     virtual ~HLAVariantRecordDataElement();
 
+    virtual bool setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement);
+    virtual HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end);
+    virtual const HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const;
+
     virtual bool setAlternativeIndex(unsigned index);
     virtual bool decodeAlternative(HLADecodeStream& stream);
     virtual unsigned getAlternativeIndex() const;