]> git.mxchange.org Git - simgear.git/commitdiff
Add an initial implementation of a rti/hla dispatcher.
authorMathias Froehlich <Mathias.Froehlich@web.de>
Fri, 18 Jun 2010 21:28:14 +0000 (23:28 +0200)
committerMathias Froehlich <Mathias.Froehlich@web.de>
Mon, 17 Jan 2011 20:33:45 +0000 (21:33 +0100)
58 files changed:
configure.ac
simgear/hla/HLA13Federate.cxx [new file with mode: 0644]
simgear/hla/HLA13Federate.hxx [new file with mode: 0644]
simgear/hla/HLAArrayDataElement.cxx [new file with mode: 0644]
simgear/hla/HLAArrayDataElement.hxx [new file with mode: 0644]
simgear/hla/HLAArrayDataType.cxx [new file with mode: 0644]
simgear/hla/HLAArrayDataType.hxx [new file with mode: 0644]
simgear/hla/HLABasicDataElement.cxx [new file with mode: 0644]
simgear/hla/HLABasicDataElement.hxx [new file with mode: 0644]
simgear/hla/HLABasicDataType.cxx [new file with mode: 0644]
simgear/hla/HLABasicDataType.hxx [new file with mode: 0644]
simgear/hla/HLADataElement.cxx [new file with mode: 0644]
simgear/hla/HLADataElement.hxx [new file with mode: 0644]
simgear/hla/HLADataType.cxx [new file with mode: 0644]
simgear/hla/HLADataType.hxx [new file with mode: 0644]
simgear/hla/HLADataTypeVisitor.hxx [new file with mode: 0644]
simgear/hla/HLAEnumeratedDataElement.cxx [new file with mode: 0644]
simgear/hla/HLAEnumeratedDataElement.hxx [new file with mode: 0644]
simgear/hla/HLAEnumeratedDataType.cxx [new file with mode: 0644]
simgear/hla/HLAEnumeratedDataType.hxx [new file with mode: 0644]
simgear/hla/HLAFederate.cxx [new file with mode: 0644]
simgear/hla/HLAFederate.hxx [new file with mode: 0644]
simgear/hla/HLAFixedRecordDataElement.cxx [new file with mode: 0644]
simgear/hla/HLAFixedRecordDataElement.hxx [new file with mode: 0644]
simgear/hla/HLAFixedRecordDataType.cxx [new file with mode: 0644]
simgear/hla/HLAFixedRecordDataType.hxx [new file with mode: 0644]
simgear/hla/HLAInteractionClass.hxx [new file with mode: 0644]
simgear/hla/HLALocation.hxx [new file with mode: 0644]
simgear/hla/HLAOMTXmlVisitor.cxx [new file with mode: 0644]
simgear/hla/HLAOMTXmlVisitor.hxx [new file with mode: 0644]
simgear/hla/HLAObjectClass.cxx [new file with mode: 0644]
simgear/hla/HLAObjectClass.hxx [new file with mode: 0644]
simgear/hla/HLAObjectInstance.cxx [new file with mode: 0644]
simgear/hla/HLAObjectInstance.hxx [new file with mode: 0644]
simgear/hla/HLAPropertyDataElement.cxx [new file with mode: 0644]
simgear/hla/HLAPropertyDataElement.hxx [new file with mode: 0644]
simgear/hla/HLARawDataElement.cxx [new file with mode: 0644]
simgear/hla/HLARawDataElement.hxx [new file with mode: 0644]
simgear/hla/HLAVariantDataElement.cxx [new file with mode: 0644]
simgear/hla/HLAVariantDataElement.hxx [new file with mode: 0644]
simgear/hla/HLAVariantDataType.cxx [new file with mode: 0644]
simgear/hla/HLAVariantDataType.hxx [new file with mode: 0644]
simgear/hla/Makefile.am
simgear/hla/RTI13Ambassador.hxx [new file with mode: 0644]
simgear/hla/RTI13Federate.cxx [new file with mode: 0644]
simgear/hla/RTI13Federate.hxx [new file with mode: 0644]
simgear/hla/RTI13ObjectClass.cxx [new file with mode: 0644]
simgear/hla/RTI13ObjectClass.hxx [new file with mode: 0644]
simgear/hla/RTI13ObjectInstance.cxx [new file with mode: 0644]
simgear/hla/RTI13ObjectInstance.hxx [new file with mode: 0644]
simgear/hla/RTIData.hxx [new file with mode: 0644]
simgear/hla/RTIFederate.cxx [new file with mode: 0644]
simgear/hla/RTIFederate.hxx [new file with mode: 0644]
simgear/hla/RTIInteractionClass.hxx [new file with mode: 0644]
simgear/hla/RTIObjectClass.cxx [new file with mode: 0644]
simgear/hla/RTIObjectClass.hxx [new file with mode: 0644]
simgear/hla/RTIObjectInstance.cxx [new file with mode: 0644]
simgear/hla/RTIObjectInstance.hxx [new file with mode: 0644]

index 094c5b1b2d8db2e48e20b9fab5632e6967ae16cf..da1a6b1b798fc68e5388269b034a47b82685f607 100644 (file)
@@ -162,6 +162,14 @@ if test "x$with_rti13" != "x" ; then
     EXTRA_DIRS="${EXTRA_DIRS} $with_rti13"
 fi
 
+# specify the rti13 location
+AC_ARG_WITH(rti1516, [  --with-rti1516=PREFIX     Specify the prefix path to a HLA1516 rti])
+
+if test "x$with_rti1516" != "x" ; then
+    echo "rti1516 prefix is $with_rti1516"
+    EXTRA_DIRS="${EXTRA_DIRS} $with_rti1516"
+fi
+
 dnl Determine an extra directories to add to include/lib search paths
 case "${host}" in
 *-apple-darwin* | *-*-cygwin* | *-*-mingw32*)
diff --git a/simgear/hla/HLA13Federate.cxx b/simgear/hla/HLA13Federate.cxx
new file mode 100644 (file)
index 0000000..4f78344
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "HLA13Federate.hxx"
+
+#include "RTI13Federate.hxx"
+
+namespace simgear {
+
+HLA13Federate::HLA13Federate() :
+    HLAFederate(new RTI13Federate)
+{
+}
+
+HLA13Federate::~HLA13Federate()
+{
+}
+
+} // namespace simgear
diff --git a/simgear/hla/HLA13Federate.hxx b/simgear/hla/HLA13Federate.hxx
new file mode 100644 (file)
index 0000000..dc3fa0b
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright (C) 2009 - 2010  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 HLA13Federate_hxx
+#define HLA13Federate_hxx
+
+#include "HLAFederate.hxx"
+
+namespace simgear {
+
+class HLA13Federate : public HLAFederate {
+public:
+    HLA13Federate();
+    virtual ~HLA13Federate();
+};
+
+} // namespace simgear
+
+#endif
diff --git a/simgear/hla/HLAArrayDataElement.cxx b/simgear/hla/HLAArrayDataElement.cxx
new file mode 100644 (file)
index 0000000..e2a7fc7
--- /dev/null
@@ -0,0 +1,313 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "HLAArrayDataElement.hxx"
+
+#include <simgear/debug/logstream.hxx>
+
+namespace simgear {
+
+HLAAbstractArrayDataElement::HLAAbstractArrayDataElement(const HLAArrayDataType* dataType) :
+    _dataType(dataType)
+{
+}
+
+HLAAbstractArrayDataElement::~HLAAbstractArrayDataElement()
+{
+}
+
+bool
+HLAAbstractArrayDataElement::decode(HLADecodeStream& stream)
+{
+    if (!_dataType.valid())
+        return false;
+    return _dataType->decode(stream, *this);
+}
+
+bool
+HLAAbstractArrayDataElement::encode(HLAEncodeStream& stream) const
+{
+    if (!_dataType.valid())
+        return false;
+    return _dataType->encode(stream, *this);
+}
+
+const HLAArrayDataType*
+HLAAbstractArrayDataElement::getDataType() const
+{
+    return _dataType.get();
+}
+
+bool
+HLAAbstractArrayDataElement::setDataType(const HLADataType* dataType)
+{
+    const HLAArrayDataType* arrayDataType = dynamic_cast<const HLAArrayDataType*>(dataType);
+    if (!arrayDataType) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLAArrayDataType: unable to set data type!");
+        return false;
+    }
+    _dataType = arrayDataType;
+    return true;
+}
+
+const HLADataType*
+HLAAbstractArrayDataElement::getElementDataType() const
+{
+    if (!_dataType.valid())
+        return 0;
+    return _dataType->getElementDataType();
+}
+
+////////////////////////////////////////////////////////////////////////
+
+HLAArrayDataElement::DataElementFactory::~DataElementFactory()
+{
+}
+
+HLAArrayDataElement::HLAArrayDataElement(const HLAArrayDataType* dataType) :
+    HLAAbstractArrayDataElement(dataType)
+{
+}
+
+HLAArrayDataElement::~HLAArrayDataElement()
+{
+}
+
+bool
+HLAArrayDataElement::setNumElements(unsigned size)
+{
+    unsigned oldSize = _elementVector.size();
+    if (size == oldSize)
+        return true;
+    _elementVector.resize(size);
+    for (unsigned i = oldSize; i < size; ++i)
+        _elementVector[i] = newElement(i);
+    return true;
+}
+
+bool
+HLAArrayDataElement::decodeElement(HLADecodeStream& stream, unsigned i)
+{
+    HLADataElement* dataElement = getElement(i);
+    if (!dataElement)
+        return false;
+    return dataElement->decode(stream);
+}
+
+unsigned
+HLAArrayDataElement::getNumElements() const
+{
+    return _elementVector.size();
+}
+
+bool
+HLAArrayDataElement::encodeElement(HLAEncodeStream& stream, unsigned i) const
+{
+    const HLADataElement* dataElement = getElement(i);
+    if (!dataElement)
+        return false;
+    return dataElement->encode(stream);
+}
+
+const HLADataElement*
+HLAArrayDataElement::getElement(unsigned index) const
+{
+    if (_elementVector.size() <= index)
+        return 0;
+    return _elementVector[index].get();
+}
+
+HLADataElement*
+HLAArrayDataElement::getElement(unsigned index)
+{
+    if (_elementVector.size() <= index)
+        return 0;
+    return _elementVector[index].get();
+}
+
+HLADataElement*
+HLAArrayDataElement::getOrCreateElement(unsigned index)
+{
+    if (_elementVector.size() <= index)
+        if (!setNumElements(index + 1))
+            return 0;
+    return _elementVector[index].get();
+}
+
+void
+HLAArrayDataElement::setElement(unsigned index, HLADataElement* value)
+{
+    unsigned oldSize = _elementVector.size();
+    if (oldSize <= index) {
+        _elementVector.resize(index + 1);
+        for (unsigned j = oldSize; j < index; ++j)
+            _elementVector[j] = newElement(j);
+    }
+    _elementVector[index] = value;
+}
+
+void
+HLAArrayDataElement::setDataElementFactory(HLAArrayDataElement::DataElementFactory* dataElementFactory)
+{
+    _dataElementFactory = dataElementFactory;
+}
+
+HLAArrayDataElement::DataElementFactory*
+HLAArrayDataElement::getDataElementFactory()
+{
+    return _dataElementFactory.get();
+}
+
+HLADataElement*
+HLAArrayDataElement::newElement(unsigned index)
+{
+    if (!_dataElementFactory.valid())
+        return 0;
+    return _dataElementFactory->createElement(*this, index);
+}
+
+////////////////////////////////////////////////////////////////////////
+
+HLAVariantArrayDataElement::HLAVariantArrayDataElement() :
+    HLAAbstractArrayDataElement(0)
+{
+}
+
+HLAVariantArrayDataElement::~HLAVariantArrayDataElement()
+{
+}
+
+bool
+HLAVariantArrayDataElement::setDataType(const HLADataType* dataType)
+{
+    const HLAArrayDataType* arrayDataType = dataType->toArrayDataType();
+    if (!arrayDataType) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLAVariantArrayDataType: unable to set data type, dataType is not an array data type!");
+        return false;
+    }
+    const HLAVariantDataType* variantDataType = arrayDataType->getElementDataType()->toVariantDataType();
+    if (!variantDataType) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLAVariantArrayDataType: unable to set data type: arrayDataTypes element data type is no a variant data type!");
+        return false;
+    }
+    _dataType = arrayDataType;
+    return true;
+}
+
+bool
+HLAVariantArrayDataElement::setNumElements(unsigned size)
+{
+    unsigned oldSize = _elementVector.size();
+    if (size == oldSize)
+        return true;
+    _elementVector.resize(size);
+    for (unsigned i = oldSize; i < size; ++i)
+        _elementVector[i] = newElement();
+    return true;
+}
+
+bool
+HLAVariantArrayDataElement::decodeElement(HLADecodeStream& stream, unsigned i)
+{
+    HLAVariantDataElement* dataElement = getElement(i);
+    if (!dataElement)
+        return false;
+    return dataElement->decode(stream);
+}
+
+unsigned
+HLAVariantArrayDataElement::getNumElements() const
+{
+    return _elementVector.size();
+}
+
+bool
+HLAVariantArrayDataElement::encodeElement(HLAEncodeStream& stream, unsigned i) const
+{
+    const HLADataElement* dataElement = getElement(i);
+    if (!dataElement)
+        return false;
+    return dataElement->encode(stream);
+}
+
+const HLAVariantDataElement*
+HLAVariantArrayDataElement::getElement(unsigned index) const
+{
+    if (_elementVector.size() <= index)
+        return 0;
+    return _elementVector[index].get();
+}
+
+HLAVariantDataElement*
+HLAVariantArrayDataElement::getElement(unsigned index)
+{
+    if (_elementVector.size() <= index)
+        return 0;
+    return _elementVector[index].get();
+}
+
+HLAVariantDataElement*
+HLAVariantArrayDataElement::getOrCreateElement(unsigned index)
+{
+    if (_elementVector.size() <= index)
+        if (!setNumElements(index + 1))
+            return 0;
+    return _elementVector[index].get();
+}
+
+void
+HLAVariantArrayDataElement::setElement(unsigned index, HLAVariantDataElement* value)
+{
+    unsigned oldSize = _elementVector.size();
+    if (oldSize <= index) {
+        _elementVector.resize(index + 1);
+        for (unsigned j = oldSize; j < index; ++j)
+            _elementVector[j] = newElement();
+    }
+    _elementVector[index] = value;
+}
+
+void
+HLAVariantArrayDataElement::setAlternativeDataElementFactory(HLAVariantArrayDataElement::AlternativeDataElementFactory* alternativeDataElementFactory)
+{
+    _alternativeDataElementFactory = alternativeDataElementFactory;
+}
+
+HLAVariantArrayDataElement::AlternativeDataElementFactory*
+HLAVariantArrayDataElement::getAlternativeDataElementFactory()
+{
+    return _alternativeDataElementFactory.get();
+}
+
+HLAVariantDataElement*
+HLAVariantArrayDataElement::newElement()
+{
+    const HLAArrayDataType* arrayDataType = getDataType();
+    if (!arrayDataType)
+        return 0;
+    const HLADataType* elementDataType = arrayDataType->getElementDataType();
+    if (!elementDataType)
+        return 0;
+    const HLAVariantDataType* variantDataType = elementDataType->toVariantDataType();
+    if (!variantDataType)
+        return 0;
+    HLAVariantDataElement* variantDataElement = new HLAVariantDataElement(variantDataType);
+    variantDataElement->setDataElementFactory(_alternativeDataElementFactory.get());
+    return variantDataElement;
+}
+
+}
diff --git a/simgear/hla/HLAArrayDataElement.hxx b/simgear/hla/HLAArrayDataElement.hxx
new file mode 100644 (file)
index 0000000..f1acf8e
--- /dev/null
@@ -0,0 +1,418 @@
+// Copyright (C) 2009 - 2010  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 HLAArrayDataElement_hxx
+#define HLAArrayDataElement_hxx
+
+#include <string>
+#include <vector>
+#include <simgear/math/SGMath.hxx>
+#include "HLAArrayDataType.hxx"
+#include "HLADataElement.hxx"
+#include "HLAVariantDataElement.hxx"
+#include "HLADataTypeVisitor.hxx"
+
+namespace simgear {
+
+class HLAAbstractArrayDataElement : public HLADataElement {
+public:
+    HLAAbstractArrayDataElement(const HLAArrayDataType* dataType);
+    virtual ~HLAAbstractArrayDataElement();
+
+    virtual bool decode(HLADecodeStream& stream);
+    virtual bool encode(HLAEncodeStream& stream) const;
+
+    virtual const HLAArrayDataType* getDataType() const;
+    virtual bool setDataType(const HLADataType* dataType);
+
+    const HLADataType* getElementDataType() const;
+
+    virtual bool setNumElements(unsigned count) = 0;
+    virtual bool decodeElement(HLADecodeStream& stream, unsigned i) = 0;
+
+    virtual unsigned getNumElements() const = 0;
+    virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const = 0;
+
+protected:
+    SGSharedPtr<const HLAArrayDataType> _dataType;
+};
+
+class HLAArrayDataElement : public HLAAbstractArrayDataElement {
+public:
+    HLAArrayDataElement(const HLAArrayDataType* dataType = 0);
+    virtual ~HLAArrayDataElement();
+
+    virtual bool setNumElements(unsigned size);
+    virtual bool decodeElement(HLADecodeStream& stream, unsigned i);
+    virtual unsigned getNumElements() const;
+    virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const;
+
+    const HLADataElement* getElement(unsigned index) const;
+    HLADataElement* getElement(unsigned index);
+    HLADataElement* getOrCreateElement(unsigned index);
+    void setElement(unsigned i, HLADataElement* value);
+
+    class DataElementFactory : public SGReferenced {
+    public:
+        virtual ~DataElementFactory();
+        virtual HLADataElement* createElement(const HLAArrayDataElement&, unsigned) = 0;
+    };
+
+    void setDataElementFactory(DataElementFactory* dataElementFactory);
+    DataElementFactory* getDataElementFactory();
+
+private:
+    HLADataElement* newElement(unsigned index);
+
+    typedef std::vector<SGSharedPtr<HLADataElement> > ElementVector;
+    ElementVector _elementVector;
+
+    SGSharedPtr<DataElementFactory> _dataElementFactory;
+};
+
+// Holds an array of variants.
+// Factors out common code for that use case.
+class HLAVariantArrayDataElement : public HLAAbstractArrayDataElement {
+public:
+    HLAVariantArrayDataElement();
+    virtual ~HLAVariantArrayDataElement();
+
+    // Overwrite this from the abstract class, need some more checks here
+    virtual bool setDataType(const HLADataType* dataType);
+
+    virtual bool setNumElements(unsigned size);
+    virtual bool decodeElement(HLADecodeStream& stream, unsigned i);
+    virtual unsigned getNumElements() const;
+    virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const;
+
+    const HLAVariantDataElement* getElement(unsigned index) const;
+    HLAVariantDataElement* getElement(unsigned index);
+    HLAVariantDataElement* getOrCreateElement(unsigned index);
+    void setElement(unsigned index, HLAVariantDataElement* value);
+
+    typedef HLAVariantDataElement::DataElementFactory AlternativeDataElementFactory;
+
+    void setAlternativeDataElementFactory(AlternativeDataElementFactory* alternativeDataElementFactory);
+    AlternativeDataElementFactory* getAlternativeDataElementFactory();
+
+private:
+    HLAVariantDataElement* newElement();
+
+    typedef std::vector<SGSharedPtr<HLAVariantDataElement> > ElementVector;
+    ElementVector _elementVector;
+
+    SGSharedPtr<AlternativeDataElementFactory> _alternativeDataElementFactory;
+};
+
+class HLAStringDataElement : public HLAAbstractArrayDataElement {
+public:
+    HLAStringDataElement(const HLAArrayDataType* dataType = 0) :
+        HLAAbstractArrayDataElement(dataType)
+    {}
+    HLAStringDataElement(const HLAArrayDataType* dataType, const std::string& value) :
+        HLAAbstractArrayDataElement(dataType),
+        _value(value)
+    {}
+    const std::string& getValue() const
+    { return _value; }
+    void setValue(const std::string& value)
+    { _value = value; }
+
+    virtual bool setNumElements(unsigned count)
+    {
+        _value.resize(count);
+        return true;
+    }
+    virtual bool decodeElement(HLADecodeStream& stream, unsigned i)
+    {
+        HLATemplateDecodeVisitor<std::string::value_type> visitor(stream);
+        getElementDataType()->accept(visitor);
+        _value[i] = visitor.getValue();
+        return true;
+    }
+
+    virtual unsigned getNumElements() const
+    {
+        return _value.size();
+    }
+    virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const
+    {
+        HLATemplateEncodeVisitor<std::string::value_type> visitor(stream, _value[i]);
+        getElementDataType()->accept(visitor);
+        return true;
+    }
+
+private:
+    std::string _value;
+};
+
+class HLAStringData {
+public:
+    HLAStringData() :
+        _value(new HLAStringDataElement(0))
+    { }
+    HLAStringData(const std::string& value) :
+        _value(new HLAStringDataElement(0))
+    { _value->setValue(value); }
+
+    operator const std::string&() const
+    { return _value->getValue(); }
+    HLAStringData& operator=(const std::string& value)
+    { _value->setValue(value); return *this; }
+
+    const std::string& getValue() const
+    { return _value->getValue(); }
+    void setValue(const std::string& value)
+    { _value->setValue(value); }
+
+    const HLAStringDataElement* getDataElement() const
+    { return _value.get(); }
+    HLAStringDataElement* getDataElement()
+    { return _value.get(); }
+
+    const HLAArrayDataType* getDataType() const
+    { return _value->getDataType(); }
+    void setDataType(const HLAArrayDataType* dataType)
+    { _value->setDataType(dataType); }
+
+private:
+    SGSharedPtr<HLAStringDataElement> _value;
+};
+
+template<typename T>
+class HLAVec2DataElement : public HLAAbstractArrayDataElement {
+public:
+    HLAVec2DataElement(const HLAArrayDataType* dataType = 0) :
+        HLAAbstractArrayDataElement(dataType),
+        _value(SGVec2<T>::zeros())
+    {}
+    HLAVec2DataElement(const HLAArrayDataType* dataType, const SGVec2<T>& value) :
+        HLAAbstractArrayDataElement(dataType),
+        _value(value)
+    {}
+    const SGVec2<T>& getValue() const
+    { return _value; }
+    void setValue(const SGVec2<T>& value)
+    { _value = value; }
+
+    virtual bool setNumElements(unsigned count)
+    {
+        for (unsigned i = 2; i < count; ++i)
+            _value[i] = 0;
+        return true;
+    }
+    virtual bool decodeElement(HLADecodeStream& stream, unsigned i)
+    {
+        if (i < 2) {
+            HLATemplateDecodeVisitor<typename SGVec2<T>::value_type> visitor(stream);
+            getElementDataType()->accept(visitor);
+            _value[i] = visitor.getValue();
+        } else {
+            HLADataTypeDecodeVisitor visitor(stream);
+            getElementDataType()->accept(visitor);
+        }
+        return true;
+    }
+
+    virtual unsigned getNumElements() const
+    {
+        return 2;
+    }
+    virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const
+    {
+        if (i < 2) {
+            HLATemplateEncodeVisitor<typename SGVec2<T>::value_type> visitor(stream, _value[i]);
+            getElementDataType()->accept(visitor);
+        } else {
+            HLADataTypeEncodeVisitor visitor(stream);
+            getElementDataType()->accept(visitor);
+        }
+        return true;
+    }
+
+private:
+    SGVec2<T> _value;
+};
+
+template<typename T>
+class HLAVec3DataElement : public HLAAbstractArrayDataElement {
+public:
+    HLAVec3DataElement(const HLAArrayDataType* dataType = 0) :
+        HLAAbstractArrayDataElement(dataType),
+        _value(SGVec3<T>::zeros())
+    {}
+    HLAVec3DataElement(const HLAArrayDataType* dataType, const SGVec3<T>& value) :
+        HLAAbstractArrayDataElement(dataType),
+        _value(value)
+    {}
+    const SGVec3<T>& getValue() const
+    { return _value; }
+    void setValue(const SGVec3<T>& value)
+    { _value = value; }
+
+    virtual bool setNumElements(unsigned count)
+    {
+        for (unsigned i = 3; i < count; ++i)
+            _value[i] = 0;
+        return true;
+    }
+    virtual bool decodeElement(HLADecodeStream& stream, unsigned i)
+    {
+        if (i < 3) {
+            HLATemplateDecodeVisitor<typename SGVec3<T>::value_type> visitor(stream);
+            getElementDataType()->accept(visitor);
+            _value[i] = visitor.getValue();
+        } else {
+            HLADataTypeDecodeVisitor visitor(stream);
+            getElementDataType()->accept(visitor);
+        }
+        return true;
+    }
+
+    virtual unsigned getNumElements() const
+    {
+        return 3;
+    }
+    virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const
+    {
+        if (i < 3) {
+            HLATemplateEncodeVisitor<typename SGVec3<T>::value_type> visitor(stream, _value[i]);
+            getElementDataType()->accept(visitor);
+        } else {
+            HLADataTypeEncodeVisitor visitor(stream);
+            getElementDataType()->accept(visitor);
+        }
+        return true;
+    }
+
+private:
+    SGVec3<T> _value;
+};
+
+template<typename T>
+class HLAVec4DataElement : public HLAAbstractArrayDataElement {
+public:
+    HLAVec4DataElement(const HLAArrayDataType* dataType = 0) :
+        HLAAbstractArrayDataElement(dataType),
+        _value(SGVec4<T>::zeros())
+    {}
+    HLAVec4DataElement(const HLAArrayDataType* dataType, const SGVec4<T>& value) :
+        HLAAbstractArrayDataElement(dataType),
+        _value(value)
+    {}
+    const SGVec4<T>& getValue() const
+    { return _value; }
+    void setValue(const SGVec4<T>& value)
+    { _value = value; }
+
+    virtual bool setNumElements(unsigned count)
+    {
+        for (unsigned i = 4; i < count; ++i)
+            _value[i] = 0;
+        return true;
+    }
+    virtual bool decodeElement(HLADecodeStream& stream, unsigned i)
+    {
+        if (i < 4) {
+            HLATemplateDecodeVisitor<typename SGVec4<T>::value_type> visitor(stream);
+            getElementDataType()->accept(visitor);
+            _value[i] = visitor.getValue();
+        } else {
+            HLADataTypeDecodeVisitor visitor(stream);
+            getElementDataType()->accept(visitor);
+        }
+        return true;
+    }
+
+    virtual unsigned getNumElements() const
+    {
+        return 4;
+    }
+    virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const
+    {
+        if (i < 4) {
+            HLATemplateEncodeVisitor<typename SGVec4<T>::value_type> visitor(stream, _value[i]);
+            getElementDataType()->accept(visitor);
+        } else {
+            HLADataTypeEncodeVisitor visitor(stream);
+            getElementDataType()->accept(visitor);
+        }
+        return true;
+    }
+
+private:
+    SGVec4<T> _value;
+};
+
+template<typename T>
+class HLAQuatDataElement : public HLAAbstractArrayDataElement {
+public:
+    HLAQuatDataElement(const HLAArrayDataType* dataType = 0) :
+        HLAAbstractArrayDataElement(dataType),
+        _value(SGQuat<T>::zeros())
+    {}
+    HLAQuatDataElement(const HLAArrayDataType* dataType, const SGQuat<T>& value) :
+        HLAAbstractArrayDataElement(dataType),
+        _value(value)
+    {}
+    const SGQuat<T>& getValue() const
+    { return _value; }
+    void setValue(const SGQuat<T>& value)
+    { _value = value; }
+
+    virtual bool setNumElements(unsigned count)
+    {
+        for (unsigned i = 4; i < count; ++i)
+            _value[i] = 0;
+        return true;
+    }
+    virtual bool decodeElement(HLADecodeStream& stream, unsigned i)
+    {
+        if (i < 4) {
+            HLATemplateDecodeVisitor<typename SGQuat<T>::value_type> visitor(stream);
+            getElementDataType()->accept(visitor);
+            _value[i] = visitor.getValue();
+        } else {
+            HLADataTypeDecodeVisitor visitor(stream);
+            getElementDataType()->accept(visitor);
+        }
+        return true;
+    }
+
+    virtual unsigned getNumElements() const
+    {
+        return 4;
+    }
+    virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const
+    {
+        if (i < 4) {
+            HLATemplateEncodeVisitor<typename SGQuat<T>::value_type> visitor(stream, _value[i]);
+            getElementDataType()->accept(visitor);
+        } else {
+            HLADataTypeEncodeVisitor visitor(stream);
+            getElementDataType()->accept(visitor);
+        }
+        return true;
+    }
+
+private:
+    SGQuat<T> _value;
+};
+
+}
+
+#endif
diff --git a/simgear/hla/HLAArrayDataType.cxx b/simgear/hla/HLAArrayDataType.cxx
new file mode 100644 (file)
index 0000000..0eac236
--- /dev/null
@@ -0,0 +1,158 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "HLAArrayDataType.hxx"
+
+#include "HLAArrayDataElement.hxx"
+
+namespace simgear {
+
+HLAArrayDataType::HLAArrayDataType(const std::string& name) :
+    HLADataType(name)
+{
+}
+
+HLAArrayDataType::~HLAArrayDataType()
+{
+}
+
+void
+HLAArrayDataType::accept(HLADataTypeVisitor& visitor) const
+{
+    visitor.apply(*this);
+}
+
+const HLAArrayDataType*
+HLAArrayDataType::toArrayDataType() const
+{
+    return this;
+}
+
+void
+HLAArrayDataType::setElementDataType(const HLADataType* elementDataType)
+{
+    // FIXME this only works if we do not reset the alignment to something smaller
+    if (getAlignment() < elementDataType->getAlignment())
+        setAlignment(elementDataType->getAlignment());
+    _elementDataType = elementDataType;
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+
+HLAFixedArrayDataType::HLAFixedArrayDataType(const std::string& name) :
+    HLAArrayDataType(name)
+{
+}
+
+HLAFixedArrayDataType::~HLAFixedArrayDataType()
+{
+}
+
+void
+HLAFixedArrayDataType::accept(HLADataTypeVisitor& visitor) const
+{
+    visitor.apply(*this);
+}
+
+bool
+HLAFixedArrayDataType::decode(HLADecodeStream& stream, HLAAbstractArrayDataElement& value) const
+{
+    stream.alignOffsetForSize(getAlignment());
+    unsigned numElements = getNumElements();
+    if (!value.setNumElements(numElements))
+        return false;
+    for (unsigned i = 0; i < numElements; ++i)
+        if (!value.decodeElement(stream, i))
+            return false;
+    return true;
+}
+
+bool
+HLAFixedArrayDataType::encode(HLAEncodeStream& stream, const HLAAbstractArrayDataElement& value) const
+{
+    stream.alignOffsetForSize(getAlignment());
+    unsigned numElementsType = getNumElements();
+    unsigned numElementsValue = value.getNumElements();
+    unsigned numElements = SGMisc<unsigned>::min(numElementsType, numElementsValue);
+    unsigned i = 0;
+    for (; i < numElements; ++i)
+        if (!value.encodeElement(stream, i))
+            return false;
+    for (; i < numElementsType; ++i) {
+        HLADataTypeEncodeVisitor visitor(stream);
+        getElementDataType()->accept(visitor);
+    }
+    return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+
+HLAVariableArrayDataType::HLAVariableArrayDataType(const std::string& name) :
+    HLAArrayDataType(name)
+{
+    setSizeDataType(new HLAUInt32BEDataType);
+}
+
+HLAVariableArrayDataType::~HLAVariableArrayDataType()
+{
+}
+
+void
+HLAVariableArrayDataType::accept(HLADataTypeVisitor& visitor) const
+{
+    visitor.apply(*this);
+}
+
+bool
+HLAVariableArrayDataType::decode(HLADecodeStream& stream, HLAAbstractArrayDataElement& value) const
+{
+    stream.alignOffsetForSize(getAlignment());
+    HLATemplateDecodeVisitor<unsigned> numElementsVisitor(stream);
+    getSizeDataType()->accept(numElementsVisitor);
+    unsigned numElements = numElementsVisitor.getValue();
+    if (!value.setNumElements(numElements))
+        return false;
+    for (unsigned i = 0; i < numElements; ++i)
+        if (!value.decodeElement(stream, i))
+            return false;
+    return true;
+}
+
+bool
+HLAVariableArrayDataType::encode(HLAEncodeStream& stream, const HLAAbstractArrayDataElement& value) const
+{
+    stream.alignOffsetForSize(getAlignment());
+    unsigned numElements = value.getNumElements();
+    HLATemplateEncodeVisitor<unsigned> numElementsVisitor(stream, numElements);
+    getSizeDataType()->accept(numElementsVisitor);
+    for (unsigned i = 0; i < numElements; ++i)
+        if (!value.encodeElement(stream, i))
+            return false;
+    return true;
+}
+
+void
+HLAVariableArrayDataType::setSizeDataType(const HLADataType* sizeDataType)
+{
+    // FIXME this only works if we do not reset the alignment to something smaller
+    if (getAlignment() < sizeDataType->getAlignment())
+        setAlignment(sizeDataType->getAlignment());
+    _sizeDataType = sizeDataType;
+    // setAlignment(SGMisc<unsigned>::max(_sizeDataType->getAlignment(), _elementDataType->getAlignment());
+}
+
+} // namespace simgear
diff --git a/simgear/hla/HLAArrayDataType.hxx b/simgear/hla/HLAArrayDataType.hxx
new file mode 100644 (file)
index 0000000..eac645b
--- /dev/null
@@ -0,0 +1,88 @@
+// Copyright (C) 2009 - 2010  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 HLAArrayDataType_hxx
+#define HLAArrayDataType_hxx
+
+#include <string>
+#include <simgear/structure/SGSharedPtr.hxx>
+#include "HLADataType.hxx"
+
+namespace simgear {
+
+class HLAAbstractArrayDataElement;
+
+class HLAArrayDataType : public HLADataType {
+public:
+    HLAArrayDataType(const std::string& name = "HLAArrayDataType");
+    virtual ~HLAArrayDataType();
+
+    virtual void accept(HLADataTypeVisitor& visitor) const;
+
+    virtual const HLAArrayDataType* toArrayDataType() const;
+
+    virtual bool decode(HLADecodeStream& stream, HLAAbstractArrayDataElement& value) const = 0;
+    virtual bool encode(HLAEncodeStream& stream, const HLAAbstractArrayDataElement& value) const = 0;
+
+    void setElementDataType(const HLADataType* elementDataType);
+    const HLADataType* getElementDataType() const
+    { return _elementDataType.get(); }
+
+private:
+    SGSharedPtr<const HLADataType> _elementDataType;
+};
+
+class HLAFixedArrayDataType : public HLAArrayDataType {
+public:
+    HLAFixedArrayDataType(const std::string& name = "HLAFixedArrayDataType");
+    virtual ~HLAFixedArrayDataType();
+
+    virtual void accept(HLADataTypeVisitor& visitor) const;
+
+    virtual bool decode(HLADecodeStream& stream, HLAAbstractArrayDataElement& value) const;
+    virtual bool encode(HLAEncodeStream& stream, const HLAAbstractArrayDataElement& value) const;
+
+    void setNumElements(unsigned numElements)
+    { _numElements = numElements; }
+    unsigned getNumElements() const
+    { return _numElements; }
+
+private:
+    unsigned _numElements;
+};
+
+class HLAVariableArrayDataType : public HLAArrayDataType {
+public:
+    HLAVariableArrayDataType(const std::string& name = "HLAVariableArrayDataType");
+    virtual ~HLAVariableArrayDataType();
+
+    virtual void accept(HLADataTypeVisitor& visitor) const;
+
+    virtual bool decode(HLADecodeStream& stream, HLAAbstractArrayDataElement& value) const;
+    virtual bool encode(HLAEncodeStream& stream, const HLAAbstractArrayDataElement& value) const;
+
+    void setSizeDataType(const HLADataType* sizeDataType);
+    const HLADataType* getSizeDataType() const
+    { return _sizeDataType.get(); }
+
+private:
+    SGSharedPtr<const HLADataType> _sizeDataType;
+};
+
+} // namespace simgear
+
+#endif
diff --git a/simgear/hla/HLABasicDataElement.cxx b/simgear/hla/HLABasicDataElement.cxx
new file mode 100644 (file)
index 0000000..6940110
--- /dev/null
@@ -0,0 +1,132 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "HLABasicDataElement.hxx"
+
+#include "HLADataTypeVisitor.hxx"
+
+namespace simgear {
+
+HLABasicDataElement::HLABasicDataElement(const HLABasicDataType* dataType) :
+    _dataType(dataType)
+{
+}
+
+HLABasicDataElement::~HLABasicDataElement()
+{
+}
+
+const HLABasicDataType*
+HLABasicDataElement::getDataType() const
+{
+    return _dataType.get();
+}
+
+bool
+HLABasicDataElement::setDataType(const HLADataType* dataType)
+{
+    const HLABasicDataType* scalarDataType = dynamic_cast<const HLABasicDataType*>(dataType);
+    if (!scalarDataType) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLABasicDataType: unable to set data type!");
+        return false;
+    }
+    setDataType(scalarDataType);
+    return true;
+}
+
+void
+HLABasicDataElement::setDataType(const HLABasicDataType* dataType)
+{
+    _dataType = dataType;
+}
+
+#define IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(type, ctype)                                       \
+HLAAbstract##type##DataElement::HLAAbstract##type##DataElement(const HLABasicDataType* dataType) :\
+    HLABasicDataElement(dataType)                                                                 \
+{                                                                                                 \
+}                                                                                                 \
+                                                                                                  \
+HLAAbstract##type##DataElement::~HLAAbstract##type##DataElement()                                 \
+{                                                                                                 \
+}                                                                                                 \
+                                                                                                  \
+bool                                                                                              \
+HLAAbstract##type##DataElement::encode(HLAEncodeStream& stream) const                             \
+{                                                                                                 \
+    if (!_dataType.valid())                                                                       \
+        return false;                                                                             \
+    HLATemplateEncodeVisitor<ctype> visitor(stream, getValue());                                  \
+    _dataType->accept(visitor);                                                                   \
+    return true;                                                                                  \
+}                                                                                                 \
+                                                                                                  \
+bool                                                                                              \
+HLAAbstract##type##DataElement::decode(HLADecodeStream& stream)                                   \
+{                                                                                                 \
+    if (!_dataType.valid())                                                                       \
+        return false;                                                                             \
+    HLATemplateDecodeVisitor<ctype> visitor(stream);                                              \
+    _dataType->accept(visitor);                                                                   \
+    setValue(visitor.getValue());                                                                 \
+    return true;                                                                                  \
+}                                                                                                 \
+                                                                                                  \
+HLA##type##DataElement::HLA##type##DataElement(const HLABasicDataType* dataType) :                \
+    HLAAbstract##type##DataElement(dataType),                                                     \
+    _value(0)                                                                                     \
+{                                                                                                 \
+}                                                                                                 \
+                                                                                                  \
+HLA##type##DataElement::HLA##type##DataElement(const HLABasicDataType* dataType,                  \
+                                               const ctype& value) :                              \
+    HLAAbstract##type##DataElement(dataType),                                                     \
+    _value(value)                                                                                 \
+{                                                                                                 \
+}                                                                                                 \
+                                                                                                  \
+HLA##type##DataElement::~HLA##type##DataElement()                                                 \
+{                                                                                                 \
+}                                                                                                 \
+                                                                                                  \
+ctype                                                                                             \
+HLA##type##DataElement::getValue() const                                                          \
+{                                                                                                 \
+    return _value;                                                                                \
+}                                                                                                 \
+                                                                                                  \
+void                                                                                              \
+HLA##type##DataElement::setValue(ctype value)                                                     \
+{                                                                                                 \
+    _value = value;                                                                               \
+}
+
+IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(Char, char);
+IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(WChar, wchar_t);
+IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(SChar, signed char);
+IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(UChar, unsigned char);
+IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(Short, short);
+IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(UShort, unsigned short);
+IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(Int, int);
+IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(UInt, unsigned int);
+IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(Long, long);
+IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(ULong, unsigned long);
+IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(Float, float);
+IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(Double, double);
+
+#undef IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT
+
+}
diff --git a/simgear/hla/HLABasicDataElement.hxx b/simgear/hla/HLABasicDataElement.hxx
new file mode 100644 (file)
index 0000000..e38499d
--- /dev/null
@@ -0,0 +1,108 @@
+// Copyright (C) 2009 - 2010  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 HLABasicDataElement_hxx
+#define HLABasicDataElement_hxx
+
+#include "HLABasicDataType.hxx"
+#include "HLADataElement.hxx"
+
+namespace simgear {
+
+class HLABasicDataElement : public HLADataElement {
+public:
+    HLABasicDataElement(const HLABasicDataType* dataType);
+    virtual ~HLABasicDataElement();
+
+    virtual const HLABasicDataType* getDataType() const;
+    virtual bool setDataType(const HLADataType* dataType);
+    void setDataType(const HLABasicDataType* dataType);
+
+protected:
+    SGSharedPtr<const HLABasicDataType> _dataType;
+};
+
+#define TYPED_HLA_BASIC_DATA_ELEMENT(type, ctype)                             \
+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);                             \
+                                                                              \
+    virtual ctype getValue() const = 0;                                       \
+    virtual void setValue(ctype) = 0;                                         \
+};                                                                            \
+class HLA##type##DataElement : public HLAAbstract##type##DataElement {        \
+public:                                                                       \
+    HLA##type##DataElement(const HLABasicDataType* dataType = 0);             \
+    HLA##type##DataElement(const HLABasicDataType* dataType,                  \
+                           const ctype& value);                               \
+    virtual ~HLA##type##DataElement();                                        \
+    virtual ctype getValue() const;                                           \
+    virtual void setValue(ctype value);                                       \
+private:                                                                      \
+    ctype _value;                                                             \
+};                                                                            \
+class HLA##type##Data {                                                       \
+public:                                                                       \
+    HLA##type##Data() :                                                       \
+        _value(new HLA##type##DataElement(0))                                 \
+    { }                                                                       \
+    HLA##type##Data(const ctype& value) :                                     \
+        _value(new HLA##type##DataElement(0, value))                          \
+    { }                                                                       \
+    operator ctype() const                                                    \
+    { return _value->getValue(); }                                            \
+    HLA##type##Data& operator=(const ctype& value)                            \
+    { _value->setValue(value); return *this; }                                \
+    ctype getValue() const                                                    \
+    { return _value->getValue(); }                                            \
+    void setValue(const ctype& value)                                         \
+    { _value->setValue(value); }                                              \
+    const HLA##type##DataElement* getDataElement() const                      \
+    { return _value.get(); }                                                  \
+    HLA##type##DataElement* getDataElement()                                  \
+    { return _value.get(); }                                                  \
+    const HLABasicDataType* getDataType() const                               \
+    { return _value->getDataType(); }                                         \
+    void setDataType(const HLABasicDataType* dataType)                        \
+    { _value->setDataType(dataType); }                                        \
+                                                                              \
+private:                                                                      \
+    SGSharedPtr<HLA##type##DataElement> _value;                               \
+};
+
+
+TYPED_HLA_BASIC_DATA_ELEMENT(Char, char);
+TYPED_HLA_BASIC_DATA_ELEMENT(WChar, wchar_t);
+TYPED_HLA_BASIC_DATA_ELEMENT(SChar, signed char);
+TYPED_HLA_BASIC_DATA_ELEMENT(UChar, unsigned char);
+TYPED_HLA_BASIC_DATA_ELEMENT(Short, short);
+TYPED_HLA_BASIC_DATA_ELEMENT(UShort, unsigned short);
+TYPED_HLA_BASIC_DATA_ELEMENT(Int, int);
+TYPED_HLA_BASIC_DATA_ELEMENT(UInt, unsigned int);
+TYPED_HLA_BASIC_DATA_ELEMENT(Long, long);
+TYPED_HLA_BASIC_DATA_ELEMENT(ULong, unsigned long);
+TYPED_HLA_BASIC_DATA_ELEMENT(Float, float);
+TYPED_HLA_BASIC_DATA_ELEMENT(Double, double);
+
+#undef TYPED_HLA_BASIC_DATA_ELEMENT
+
+}
+
+#endif
diff --git a/simgear/hla/HLABasicDataType.cxx b/simgear/hla/HLABasicDataType.cxx
new file mode 100644 (file)
index 0000000..106e815
--- /dev/null
@@ -0,0 +1,170 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "HLABasicDataType.hxx"
+
+#include "HLADataType.hxx"
+#include "HLADataTypeVisitor.hxx"
+
+namespace simgear {
+
+HLABasicDataType::HLABasicDataType(const std::string& name) :
+    HLADataType(name)
+{
+}
+
+HLABasicDataType::~HLABasicDataType()
+{
+}
+
+void
+HLABasicDataType::accept(HLADataTypeVisitor& visitor) const
+{
+    visitor.apply(*this);
+}
+
+const HLABasicDataType*
+HLABasicDataType::toBasicDataType() const
+{
+    return this;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+HLAInt8DataType::HLAInt8DataType(const std::string& name) :
+    HLABasicDataType(name)
+{
+    setAlignment(sizeof(int8_t));
+}
+
+HLAInt8DataType::~HLAInt8DataType()
+{
+}
+
+void
+HLAInt8DataType::accept(HLADataTypeVisitor& visitor) const
+{
+    visitor.apply(*this);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+HLAUInt8DataType::HLAUInt8DataType(const std::string& name) :
+    HLABasicDataType(name)
+{
+    setAlignment(sizeof(uint8_t));
+}
+
+HLAUInt8DataType::~HLAUInt8DataType()
+{
+}
+
+void
+HLAUInt8DataType::accept(HLADataTypeVisitor& visitor) const
+{
+    visitor.apply(*this);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+#define BASIC_DATATYPE_IMPLEMENTATION(type, name)                       \
+HLA##name##DataType::HLA##name##DataType(const std::string& name) :     \
+    HLABasicDataType(name)                                              \
+{                                                                       \
+    setAlignment(sizeof(type));                                         \
+}                                                                       \
+                                                                        \
+HLA##name##DataType::~HLA##name##DataType()                             \
+{                                                                       \
+}                                                                       \
+                                                                        \
+void                                                                    \
+HLA##name##DataType::accept(HLADataTypeVisitor& visitor) const          \
+{                                                                       \
+    visitor.apply(*this);                                               \
+}                                                                       \
+                                                                        \
+                                                                        \
+                                                                        \
+HLA##name##LEDataType::HLA##name##LEDataType(const std::string& name) : \
+    HLA##name##DataType(name)                                           \
+{                                                                       \
+}                                                                       \
+                                                                        \
+HLA##name##LEDataType::~HLA##name##LEDataType()                         \
+{                                                                       \
+}                                                                       \
+                                                                        \
+bool                                                                    \
+HLA##name##LEDataType::decode(HLADecodeStream& stream,                  \
+                              type& value) const                        \
+{                                                                       \
+    if (!stream.alignOffsetForSize(getAlignment()))                     \
+        return false;                                                   \
+    return stream.decode##name##LE(value);                              \
+}                                                                       \
+                                                                        \
+bool                                                                    \
+HLA##name##LEDataType::encode(HLAEncodeStream& stream,                  \
+                              const type& value) const                  \
+{                                                                       \
+    if (!stream.alignOffsetForSize(getAlignment()))                     \
+        return false;                                                   \
+    return stream.encode##name##LE(value);                              \
+}                                                                       \
+                                                                        \
+                                                                        \
+                                                                        \
+HLA##name##BEDataType::HLA##name##BEDataType(const std::string& name) : \
+    HLA##name##DataType(name)                                           \
+{                                                                       \
+}                                                                       \
+                                                                        \
+HLA##name##BEDataType::~HLA##name##BEDataType()                         \
+{                                                                       \
+}                                                                       \
+                                                                        \
+bool                                                                    \
+HLA##name##BEDataType::decode(HLADecodeStream& stream,                  \
+                              type& value) const                        \
+{                                                                       \
+    if (!stream.alignOffsetForSize(getAlignment()))                     \
+        return false;                                                   \
+    return stream.decode##name##BE(value);                              \
+}                                                                       \
+                                                                        \
+bool                                                                    \
+HLA##name##BEDataType::encode(HLAEncodeStream& stream,                  \
+                              const type& value) const                  \
+{                                                                       \
+    if (!stream.alignOffsetForSize(getAlignment()))                     \
+        return false;                                                   \
+    return stream.encode##name##BE(value);                              \
+}
+
+BASIC_DATATYPE_IMPLEMENTATION(int16_t, Int16)
+BASIC_DATATYPE_IMPLEMENTATION(uint16_t, UInt16)
+BASIC_DATATYPE_IMPLEMENTATION(int32_t, Int32)
+BASIC_DATATYPE_IMPLEMENTATION(uint32_t, UInt32)
+BASIC_DATATYPE_IMPLEMENTATION(int64_t, Int64)
+BASIC_DATATYPE_IMPLEMENTATION(uint64_t, UInt64)
+BASIC_DATATYPE_IMPLEMENTATION(float, Float32)
+BASIC_DATATYPE_IMPLEMENTATION(double, Float64)
+
+#undef BASIC_DATATYPE_IMPLEMENTATION
+
+} // namespace simgear
diff --git a/simgear/hla/HLABasicDataType.hxx b/simgear/hla/HLABasicDataType.hxx
new file mode 100644 (file)
index 0000000..60f1ba7
--- /dev/null
@@ -0,0 +1,155 @@
+// Copyright (C) 2009 - 2010  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 HLABasicDataType_hxx
+#define HLABasicDataType_hxx
+
+#include <string>
+#include "HLADataType.hxx"
+
+namespace simgear {
+
+class HLABasicDataType : public HLADataType {
+public:
+    virtual ~HLABasicDataType();
+    virtual void accept(HLADataTypeVisitor& visitor) const;
+
+    virtual const HLABasicDataType* toBasicDataType() const;
+
+protected:
+    HLABasicDataType(const std::string& name);
+};
+
+class HLAInt8DataType : public HLABasicDataType {
+public:
+    HLAInt8DataType(const std::string& name = "HLAInt8DataType");
+    virtual ~HLAInt8DataType();
+
+    virtual void accept(HLADataTypeVisitor& visitor) const;
+
+    bool skip(HLADecodeStream& stream) const
+    {
+        if (!stream.alignOffsetForSize(getAlignment()))
+            return false;
+        return stream.skip(1);
+    }
+    bool skip(HLAEncodeStream& stream) const
+    {
+        if (!stream.alignOffsetForSize(getAlignment()))
+            return false;
+        return stream.skip(1);
+    }
+    bool decode(HLADecodeStream& stream, int8_t& value) const
+    {
+        if (!stream.alignOffsetForSize(getAlignment()))
+            return false;
+        return stream.decodeInt8(value);
+    }
+    bool encode(HLAEncodeStream& stream, const int8_t& value) const
+    {
+        if (!stream.alignOffsetForSize(getAlignment()))
+            return false;
+        return stream.encodeInt8(value);
+    }
+};
+
+class HLAUInt8DataType : public HLABasicDataType {
+public:
+    HLAUInt8DataType(const std::string& name = "HLAUInt8DataType");
+    virtual ~HLAUInt8DataType();
+
+    virtual void accept(HLADataTypeVisitor& visitor) const;
+
+    bool skip(HLADecodeStream& stream) const
+    {
+        if (!stream.alignOffsetForSize(getAlignment()))
+            return false;
+        return stream.skip(1);
+    }
+    bool skip(HLAEncodeStream& stream) const
+    {
+        if (!stream.alignOffsetForSize(getAlignment()))
+            return false;
+        return stream.skip(1);
+    }
+    bool decode(HLADecodeStream& stream, uint8_t& value) const
+    {
+        if (!stream.alignOffsetForSize(getAlignment()))
+            return false;
+        return stream.decodeUInt8(value);
+    }
+    bool encode(HLAEncodeStream& stream, const uint8_t& value) const
+    {
+        if (!stream.alignOffsetForSize(getAlignment()))
+            return false;
+        return stream.encodeUInt8(value);
+    }
+};
+
+#define BASIC_DATATYPE_IMPLEMENTATION(type, name)                          \
+class HLA##name##DataType : public HLABasicDataType {                      \
+public:                                                                    \
+ virtual ~HLA##name##DataType();                                           \
+                                                                           \
+ virtual void accept(HLADataTypeVisitor& visitor) const;                   \
+                                                                           \
+ bool skip(HLADecodeStream& stream) const                                  \
+ {                                                                         \
+   if (!stream.alignOffsetForSize(getAlignment()))                         \
+     return false;                                                         \
+   return stream.skip(sizeof(type));                                       \
+ }                                                                         \
+ bool skip(HLAEncodeStream& stream) const                                  \
+ {                                                                         \
+   if (!stream.alignOffsetForSize(getAlignment()))                         \
+     return false;                                                         \
+   return stream.skip(sizeof(type));                                       \
+ }                                                                         \
+ virtual bool decode(HLADecodeStream& stream, type& value) const = 0;      \
+ virtual bool encode(HLAEncodeStream& stream, const type& value) const = 0;\
+protected:                                                                 \
+ HLA##name##DataType(const std::string& name);                             \
+};                                                                         \
+class HLA##name##LEDataType : public HLA##name##DataType {                 \
+public:                                                                    \
+ HLA##name##LEDataType(const std::string& name = "HLA" #name "LEDataType");\
+ virtual ~HLA##name##LEDataType();                                         \
+ virtual bool decode(HLADecodeStream& stream, type& value) const;          \
+ virtual bool encode(HLAEncodeStream& stream, const type& value) const;    \
+};                                                                         \
+class HLA##name##BEDataType : public HLA##name##DataType {                 \
+public:                                                                    \
+ HLA##name##BEDataType(const std::string& name = "HLA" #name "BEDataType");\
+ virtual ~HLA##name##BEDataType();                                         \
+ virtual bool decode(HLADecodeStream& stream, type& value) const;          \
+ virtual bool encode(HLAEncodeStream& stream, const type& value) const;    \
+};
+
+BASIC_DATATYPE_IMPLEMENTATION(int16_t, Int16)
+BASIC_DATATYPE_IMPLEMENTATION(uint16_t, UInt16)
+BASIC_DATATYPE_IMPLEMENTATION(int32_t, Int32)
+BASIC_DATATYPE_IMPLEMENTATION(uint32_t, UInt32)
+BASIC_DATATYPE_IMPLEMENTATION(int64_t, Int64)
+BASIC_DATATYPE_IMPLEMENTATION(uint64_t, UInt64)
+BASIC_DATATYPE_IMPLEMENTATION(float, Float32)
+BASIC_DATATYPE_IMPLEMENTATION(double, Float64)
+
+#undef BASIC_DATATYPE_IMPLEMENTATION
+
+} // namespace simgear
+
+#endif
diff --git a/simgear/hla/HLADataElement.cxx b/simgear/hla/HLADataElement.cxx
new file mode 100644 (file)
index 0000000..ae98112
--- /dev/null
@@ -0,0 +1,187 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "HLADataElement.hxx"
+
+#include <simgear/debug/logstream.hxx>
+
+namespace simgear {
+
+HLADataElement::PathElement::Data::~Data()
+{
+}
+
+const HLADataElement::PathElement::FieldData*
+HLADataElement::PathElement::Data::toFieldData() const
+{
+    return 0;
+}
+
+const HLADataElement::PathElement::IndexData*
+HLADataElement::PathElement::Data::toIndexData() const
+{
+    return 0;
+}
+
+HLADataElement::PathElement::FieldData::FieldData(const std::string& name) :
+    _name(name)
+{
+}
+
+HLADataElement::PathElement::FieldData::~FieldData()
+{
+}
+
+const HLADataElement::PathElement::FieldData*
+HLADataElement::PathElement::FieldData::toFieldData() const
+{
+    return this;
+}
+
+bool
+HLADataElement::PathElement::FieldData::less(const Data* data) const
+{
+    const FieldData* fieldData = data->toFieldData();
+    // IndexData is allways smaller than FieldData
+    if (!fieldData)
+        return false;
+    return _name < fieldData->_name;
+}
+
+bool
+HLADataElement::PathElement::FieldData::equal(const Data* data) const
+{
+    const FieldData* fieldData = data->toFieldData();
+    // IndexData is allways smaller than FieldData
+    if (!fieldData)
+        return false;
+    return _name == fieldData->_name;
+}
+
+void
+HLADataElement::PathElement::FieldData::append(std::string& s) const
+{
+    s.append(1, std::string::value_type('.'));
+    s.append(_name);
+}
+
+HLADataElement::PathElement::IndexData::IndexData(unsigned index) :
+    _index(index)
+{
+}
+
+HLADataElement::PathElement::IndexData::~IndexData()
+{
+}
+
+const HLADataElement::PathElement::IndexData*
+HLADataElement::PathElement::IndexData::toIndexData() const
+{
+    return this;
+}
+
+bool
+HLADataElement::PathElement::IndexData::less(const Data* data) const
+{
+    const IndexData* indexData = data->toIndexData();
+    // IndexData is allways smaller than FieldData
+    if (!indexData)
+        return true;
+    return _index < indexData->_index;
+}
+
+bool
+HLADataElement::PathElement::IndexData::equal(const Data* data) const
+{
+    const IndexData* indexData = data->toIndexData();
+    // IndexData is allways smaller than FieldData
+    if (!indexData)
+        return false;
+    return _index == indexData->_index;
+}
+
+void
+HLADataElement::PathElement::IndexData::append(std::string& s) const
+{
+    s.append(1, std::string::value_type('['));
+    unsigned value = _index;
+    do {
+        s.append(1, std::string::value_type('0' + value % 10));
+    } while (value /= 10);
+    s.append(1, std::string::value_type(']'));
+}
+
+HLADataElement::~HLADataElement()
+{
+}
+
+std::string
+HLADataElement::toString(const Path& path)
+{
+    std::string s;
+    for (Path::const_iterator i = path.begin(); i != path.end(); ++i)
+        i->append(s);
+    return s;
+}
+
+HLADataElement::AttributePathPair
+HLADataElement::toAttributePathPair(const std::string& s)
+{
+    Path path;
+    // Skip the initial attribute name if given
+    std::string::size_type i = s.find_first_of("[.");
+    std::string attribute = s.substr(0, i);
+    while (i < s.size()) {
+        if (s[i] == '[') {
+            ++i;
+            unsigned index = 0;
+            while (i < s.size()) {
+                if (s[i] == ']')
+                    break;
+                unsigned v = s[i] - '0';
+                // Error, no number
+                if (10 <= v) {
+                    SG_LOG(SG_NETWORK, SG_WARN, "HLADataElement: invalid character in array subscript for \""
+                           << s << "\" at \"" << attribute << toString(path) << "\"!");
+                    return AttributePathPair();
+                }
+                index *= 10;
+                index += v;
+                ++i;
+            }
+            path.push_back(index);
+            ++i;
+            continue;
+        }
+        if (s[i] == '.') {
+            // Error, . cannot be last
+            if (s.size() <= ++i) {
+                SG_LOG(SG_NETWORK, SG_WARN, "HLADataElement: invalid terminating '.' for \""
+                       << s << "\"!");
+                return AttributePathPair();
+            }
+            std::string::size_type e = s.find_first_of("[.", i);
+            path.push_back(s.substr(i, e - i));
+            i = e;
+            continue;
+        }
+    }
+
+    return AttributePathPair(attribute, path);
+}
+
+}
diff --git a/simgear/hla/HLADataElement.hxx b/simgear/hla/HLADataElement.hxx
new file mode 100644 (file)
index 0000000..284422b
--- /dev/null
@@ -0,0 +1,217 @@
+// Copyright (C) 2009 - 2010  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 HLADataElement_hxx
+#define HLADataElement_hxx
+
+#include <list>
+#include <map>
+#include <simgear/structure/SGReferenced.hxx>
+#include <simgear/structure/SGSharedPtr.hxx>
+#include <simgear/timing/timestamp.hxx>
+#include "RTIData.hxx"
+#include "HLADataType.hxx"
+
+class SGTimeStamp;
+
+namespace simgear {
+
+class HLADataElement : public SGReferenced {
+public:
+    virtual ~HLADataElement();
+
+    virtual bool encode(HLAEncodeStream& stream) const = 0;
+    virtual bool decode(HLADecodeStream& stream) = 0;
+
+    virtual const HLADataType* getDataType() const = 0;
+    virtual bool setDataType(const HLADataType* dataType) = 0;
+
+    // Container for the timestamp the originating attribute was last updated for
+    // class TimeStamp : public SGReferenced {
+    // public:
+    //     const SGTimeStamp& getTimeStamp() const
+    //     { return _timeStamp; }
+    //     void setTimeStamp(const SGTimeStamp& timeStamp)
+    //     { _timeStamp = timeStamp; }
+    // private:
+    //     SGTimeStamp _timeStamp;
+    // };
+
+    // const TimeStamp* getTimeStamp() const
+    // { return _timeStamp.get(); }
+    // void setTimeStamp(const TimeStamp* timeStamp)
+    // { _timeStamp = timeStamp; }
+
+    // struct ChangeCount : public SGReferenced {
+    //     ChangeCount() : _value(0) {}
+    //     unsigned _value;
+    // };
+    // SGSharedPtr<ChangeCount> _changeCount;
+    // unsigned getChangeCount() const
+    // {
+    //     // If we don't have return allways the same
+    //     if (!_changeCount.valid())
+    //         return 0;
+    //     return _changeCount->_value;
+    // }
+
+    /// HLADataElements could be identified by path
+    /// These paths are composed of structure field names and array indices in the
+    /// order they appear while walking to the data element.
+    /// So provide here some tool functions to access these elements
+    /// Note that these functions are relatively expensive in execution time.
+    /// So only use them once at object creation time and store direct references to the values
+
+    class PathElement {
+    public:
+        PathElement(unsigned index) : _data(new IndexData(index)) {}
+        PathElement(const std::string& name) : _data(new FieldData(name)) {}
+
+        bool isFieldValue() const
+        { return _data->toFieldData(); }
+        bool isIndexValue() const
+        { return _data->toIndexData(); }
+
+        unsigned getIndexValue() const
+        {
+            const IndexData* indexData = _data->toIndexData();
+            if (!indexData)
+                return ~unsigned(0);
+            return indexData->_index;
+        }
+
+        std::string getFieldValue() const
+        {
+            const FieldData* fieldData = _data->toFieldData();
+            if (!fieldData)
+                return std::string();
+            return fieldData->_name;
+        }
+
+        // Want to be able to use that in std::map and std::set
+        bool operator<(const PathElement& pathElement) const
+        { return _data->less(pathElement._data.get()); }
+        bool operator==(const PathElement& pathElement) const
+        { return _data->equal(pathElement._data.get()); }
+
+        void append(std::string& s) const
+        { _data->append(s); }
+
+    private:
+        struct FieldData;
+        struct IndexData;
+        struct Data : public SGReferenced {
+            virtual ~Data();
+            virtual const FieldData* toFieldData() const;
+            virtual const IndexData* toIndexData() const;
+            virtual bool less(const Data*) const = 0;
+            virtual bool equal(const Data*) const = 0;
+            virtual void append(std::string&) const = 0;
+        };
+        struct FieldData : public Data {
+            FieldData(const std::string& name);
+            virtual ~FieldData();
+            virtual const FieldData* toFieldData() const;
+            virtual bool less(const Data* data) const;
+            virtual bool equal(const Data* data) const;
+            virtual void append(std::string& s) const;
+            std::string _name;
+        };
+        struct IndexData : public Data {
+            IndexData(unsigned index);
+            virtual ~IndexData();
+            virtual const IndexData* toIndexData() const;
+            virtual bool less(const Data* data) const;
+            virtual bool equal(const Data* data) const;
+            virtual void append(std::string& s) const;
+            unsigned _index;
+        };
+
+        SGSharedPtr<Data> _data;
+    };
+    typedef std::list<PathElement> Path;
+    typedef std::pair<std::string, Path> AttributePathPair;
+    typedef std::pair<unsigned, Path> IndexPathPair;
+
+    static std::string toString(const Path& path);
+    static std::string toString(const AttributePathPair& path)
+    { return path.first + toString(path.second); }
+    static AttributePathPair toAttributePathPair(const std::string& s);
+    static Path toPath(const std::string& s)
+    { return toAttributePathPair(s).second; }
+
+private:
+    // SGSharedPtr<const TimeStamp> _timeStamp;
+};
+
+class HLADataElementProvider {
+public:
+    class AbstractProvider : public SGReferenced {
+    public:
+        virtual ~AbstractProvider() { }
+        virtual HLADataElement* getDataElement(const HLADataElement::Path& path) = 0;
+        // virtual HLADataElement* getDataElement(const HLADataElement::Path& path, const HLADataType* dataType)
+        // {
+        //     SGSharedPtr<HLADataElement> dataElement = getDataElement(path);
+        //     if (!dataElement.valid())
+        //         return 0;
+        //     if (!dataElement->setDataType(dataType))
+        //         return 0;
+        //     return dataElement.release();
+        // }
+    };
+
+    HLADataElementProvider()
+    { }
+    HLADataElementProvider(HLADataElement* dataElement) :
+        _provider(new ConcreteProvider(dataElement))
+    { }
+    HLADataElementProvider(const SGSharedPtr<HLADataElement>& dataElement) :
+        _provider(new ConcreteProvider(dataElement))
+    { }
+    HLADataElementProvider(AbstractProvider* provider) :
+        _provider(provider)
+    { }
+
+    HLADataElement* getDataElement(const HLADataElement::Path& path) const
+    {
+        if (!_provider.valid())
+            return 0;
+        return _provider->getDataElement(path);
+    }
+
+private:
+    class ConcreteProvider : public AbstractProvider {
+    public:
+        ConcreteProvider(const SGSharedPtr<HLADataElement>& dataElement) :
+            _dataElement(dataElement)
+        { }
+        virtual HLADataElement* getDataElement(const HLADataElement::Path&)
+        { return _dataElement.get(); }
+    private:
+        SGSharedPtr<HLADataElement> _dataElement;
+    };
+
+    SGSharedPtr<AbstractProvider> _provider;
+};
+
+typedef std::map<HLADataElement::Path, HLADataElementProvider> HLAPathElementMap;
+typedef std::map<unsigned, HLAPathElementMap> HLAAttributePathElementMap;
+
+}
+
+#endif
diff --git a/simgear/hla/HLADataType.cxx b/simgear/hla/HLADataType.cxx
new file mode 100644 (file)
index 0000000..b22fb21
--- /dev/null
@@ -0,0 +1,104 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "HLADataType.hxx"
+
+#include "HLADataElement.hxx"
+#include "HLADataTypeVisitor.hxx"
+
+namespace simgear {
+
+HLADataType::HLADataType(const std::string& name, unsigned alignment) :
+    _name(name),
+    _alignment(1)
+{
+    setAlignment(alignment);
+}
+
+HLADataType::~HLADataType()
+{
+}
+
+void
+HLADataType::accept(HLADataTypeVisitor& visitor) const
+{
+    visitor.apply(*this);
+}
+
+const HLADataTypeReference*
+HLADataType::toDataTypeReference() const
+{
+    return 0;
+}
+
+const HLABasicDataType*
+HLADataType::toBasicDataType() const
+{
+    return 0;
+}
+
+const HLAArrayDataType*
+HLADataType::toArrayDataType() const
+{
+    return 0;
+}
+
+const HLAEnumeratedDataType*
+HLADataType::toEnumeratedDataType() const
+{
+    return 0;
+}
+
+const HLAFixedRecordDataType*
+HLADataType::toFixedRecordDataType() const
+{
+    return 0;
+}
+
+const HLAVariantDataType*
+HLADataType::toVariantDataType() const
+{
+    return 0;
+}
+
+void
+HLADataType::setAlignment(unsigned alignment)
+{
+    /// FIXME: more checks
+    if (alignment == 0)
+        _alignment = 1;
+    else
+        _alignment = alignment;
+}
+
+HLADataTypeReference::~HLADataTypeReference()
+{
+}
+
+void
+HLADataTypeReference::accept(HLADataTypeVisitor& visitor) const
+{
+    visitor.apply(*this);
+}
+
+const HLADataTypeReference*
+HLADataTypeReference::toDataTypeReference() const
+{
+    return this;
+}
+
+}
diff --git a/simgear/hla/HLADataType.hxx b/simgear/hla/HLADataType.hxx
new file mode 100644 (file)
index 0000000..23fb507
--- /dev/null
@@ -0,0 +1,99 @@
+// Copyright (C) 2009 - 2010  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 HLADataType_hxx
+#define HLADataType_hxx
+
+#include <string>
+#include <simgear/structure/SGWeakPtr.hxx>
+#include <simgear/structure/SGWeakReferenced.hxx>
+#include "RTIData.hxx"
+
+namespace simgear {
+
+class HLADataTypeVisitor;
+
+class HLADataTypeReference;
+class HLABasicDataType;
+class HLAArrayDataType;
+class HLAEnumeratedDataType;
+class HLAFixedRecordDataType;
+class HLAVariantDataType;
+
+enum HLAUpdateType {
+    HLAStaticUpdate,
+    HLAPeriodicUpdate,
+    HLAConditionalUpdate,
+    HLAUndefinedUpdate
+};
+
+class HLADataType : public SGWeakReferenced {
+public:
+    virtual ~HLADataType();
+
+    const std::string& getName() const
+    { return _name; }
+
+    const std::string& getSemantics() const
+    { return _semantics; }
+    void setSemantics(const std::string& semantics)
+    { _semantics = semantics; }
+
+    unsigned getAlignment() const
+    { return _alignment; }
+
+    virtual void accept(HLADataTypeVisitor& visitor) const;
+
+    virtual const HLADataTypeReference* toDataTypeReference() const;
+    virtual const HLABasicDataType* toBasicDataType() const;
+    virtual const HLAArrayDataType* toArrayDataType() const;
+    virtual const HLAEnumeratedDataType* toEnumeratedDataType() const;
+    virtual const HLAFixedRecordDataType* toFixedRecordDataType() const;
+    virtual const HLAVariantDataType* toVariantDataType() const;
+
+protected:
+    HLADataType(const std::string& name, unsigned alignment = 1);
+    void setAlignment(unsigned alignment);
+
+private:
+    std::string _name;
+    std::string _semantics;
+    unsigned _alignment;
+};
+
+// Weak reference to a data type. Used to implement self referencing data types
+class HLADataTypeReference : public HLADataType {
+public:
+    HLADataTypeReference(const SGSharedPtr<HLADataType>& dataType) :
+        HLADataType(dataType->getName(), dataType->getAlignment()),
+        _dataType(dataType)
+    { }
+    virtual ~HLADataTypeReference();
+
+    SGSharedPtr<const HLADataType> getDataType() const
+    { return _dataType.lock(); }
+
+    virtual void accept(HLADataTypeVisitor& visitor) const;
+    virtual const HLADataTypeReference* toDataTypeReference() const;
+
+private:
+    SGWeakPtr<const HLADataType> _dataType;
+};
+
+} // namespace simgear
+
+#endif
diff --git a/simgear/hla/HLADataTypeVisitor.hxx b/simgear/hla/HLADataTypeVisitor.hxx
new file mode 100644 (file)
index 0000000..d3cd9b2
--- /dev/null
@@ -0,0 +1,634 @@
+// Copyright (C) 2009 - 2010  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 HLADataTypeVisitor_hxx
+#define HLADataTypeVisitor_hxx
+
+#include <cassert>
+#include <string>
+#include <simgear/debug/logstream.hxx>
+#include <simgear/math/SGMath.hxx>
+#include "HLAArrayDataType.hxx"
+#include "HLABasicDataType.hxx"
+#include "HLADataTypeVisitor.hxx"
+#include "HLAEnumeratedDataType.hxx"
+#include "HLAFixedRecordDataType.hxx"
+#include "HLAVariantDataType.hxx"
+
+namespace simgear {
+
+class HLADataTypeVisitor {
+public:
+    virtual ~HLADataTypeVisitor() {}
+
+    virtual void apply(const HLADataType& dataType)
+    { }
+
+    virtual void apply(const HLADataTypeReference& dataType)
+    {
+        SGSharedPtr<const HLADataType> dataTypeReference = dataType.getDataType();
+        if (!dataTypeReference.valid()) {
+            SG_LOG(SG_NETWORK, SG_WARN, "HLADataTypeReference weak reference vanished!");
+            return;
+        }
+        dataTypeReference->accept(*this);
+    }
+
+    virtual void apply(const HLABasicDataType& dataType)
+    { apply(static_cast<const HLADataType&>(dataType)); }
+    virtual void apply(const HLAInt8DataType& dataType)
+    { apply(static_cast<const HLABasicDataType&>(dataType)); }
+    virtual void apply(const HLAUInt8DataType& dataType)
+    { apply(static_cast<const HLABasicDataType&>(dataType)); }
+    virtual void apply(const HLAInt16DataType& dataType)
+    { apply(static_cast<const HLABasicDataType&>(dataType)); }
+    virtual void apply(const HLAUInt16DataType& dataType)
+    { apply(static_cast<const HLABasicDataType&>(dataType)); }
+    virtual void apply(const HLAInt32DataType& dataType)
+    { apply(static_cast<const HLABasicDataType&>(dataType)); }
+    virtual void apply(const HLAUInt32DataType& dataType)
+    { apply(static_cast<const HLABasicDataType&>(dataType)); }
+    virtual void apply(const HLAInt64DataType& dataType)
+    { apply(static_cast<const HLABasicDataType&>(dataType)); }
+    virtual void apply(const HLAUInt64DataType& dataType)
+    { apply(static_cast<const HLABasicDataType&>(dataType)); }
+    virtual void apply(const HLAFloat32DataType& dataType)
+    { apply(static_cast<const HLABasicDataType&>(dataType)); }
+    virtual void apply(const HLAFloat64DataType& dataType)
+    { apply(static_cast<const HLABasicDataType&>(dataType)); }
+
+    virtual void apply(const HLAArrayDataType& dataType)
+    { apply(static_cast<const HLADataType&>(dataType)); }
+    virtual void apply(const HLAFixedArrayDataType& dataType)
+    { apply(static_cast<const HLAArrayDataType&>(dataType)); }
+    virtual void apply(const HLAVariableArrayDataType& dataType)
+    { apply(static_cast<const HLAArrayDataType&>(dataType)); }
+
+    virtual void apply(const HLAEnumeratedDataType& dataType)
+    { apply(static_cast<const HLADataType&>(dataType)); }
+
+    virtual void apply(const HLAFixedRecordDataType& dataType)
+    { apply(static_cast<const HLADataType&>(dataType)); }
+
+    virtual void apply(const HLAVariantDataType& dataType)
+    { apply(static_cast<const HLADataType&>(dataType)); }
+};
+
+/// Walks the datatype tree and checks if it is completely defined
+class HLADataTypeCheckVisitor : public HLADataTypeVisitor {
+public:
+    HLADataTypeCheckVisitor() : _valid(true) {}
+
+    bool valid() const { return _valid; }
+
+    virtual void apply(const HLAInt8DataType& dataType) { }
+    virtual void apply(const HLAUInt8DataType& dataType) { }
+    virtual void apply(const HLAInt16DataType& dataType) { }
+    virtual void apply(const HLAUInt16DataType& dataType) { }
+    virtual void apply(const HLAInt32DataType& dataType) { }
+    virtual void apply(const HLAUInt32DataType& dataType) { }
+    virtual void apply(const HLAInt64DataType& dataType) { }
+    virtual void apply(const HLAUInt64DataType& dataType) { }
+    virtual void apply(const HLAFloat32DataType& dataType) { }
+    virtual void apply(const HLAFloat64DataType& dataType) { }
+
+    virtual void apply(const HLAFixedArrayDataType& dataType)
+    {
+        if (!dataType.getElementDataType())
+            _valid = false;
+        else
+            dataType.getElementDataType()->accept(*this);
+    }
+    virtual void apply(const HLAVariableArrayDataType& dataType)
+    {
+        if (!dataType.getElementDataType())
+            _valid = false;
+        else
+            dataType.getElementDataType()->accept(*this);
+
+        if (!dataType.getSizeDataType())
+            _valid = false;
+        else
+            dataType.getSizeDataType()->accept(*this);
+    }
+
+    virtual void apply(const HLAEnumeratedDataType& dataType)
+    {
+        if (!dataType.getRepresentation())
+            _valid = false;
+        else
+            dataType.getRepresentation()->accept(*this);
+    }
+
+    virtual void apply(const HLAFixedRecordDataType& dataType)
+    {
+        unsigned numFields = dataType.getNumFields();
+        for (unsigned i = 0; i < numFields; ++i) {
+            if (!dataType.getFieldDataType(i))
+                _valid = false;
+            else
+                dataType.getFieldDataType(i)->accept(*this);
+        }
+    }
+
+    virtual void apply(const HLAVariantDataType& dataType)
+    { assert(0); }
+
+protected:
+    bool _valid;
+};
+
+class HLADataTypeDecodeVisitor : public HLADataTypeVisitor {
+public:
+    HLADataTypeDecodeVisitor(HLADecodeStream& stream) : _stream(stream) {}
+    virtual ~HLADataTypeDecodeVisitor() {}
+
+    virtual void apply(const HLAInt8DataType& dataType) { dataType.skip(_stream); }
+    virtual void apply(const HLAUInt8DataType& dataType) { dataType.skip(_stream); }
+    virtual void apply(const HLAInt16DataType& dataType) { dataType.skip(_stream); }
+    virtual void apply(const HLAUInt16DataType& dataType) { dataType.skip(_stream); }
+    virtual void apply(const HLAInt32DataType& dataType) { dataType.skip(_stream); }
+    virtual void apply(const HLAUInt32DataType& dataType) { dataType.skip(_stream); }
+    virtual void apply(const HLAInt64DataType& dataType) { dataType.skip(_stream); }
+    virtual void apply(const HLAUInt64DataType& dataType) { dataType.skip(_stream); }
+    virtual void apply(const HLAFloat32DataType& dataType) { dataType.skip(_stream); }
+    virtual void apply(const HLAFloat64DataType& dataType) { dataType.skip(_stream); }
+
+    virtual void apply(const HLAFixedArrayDataType& dataType)
+    {
+        unsigned numElements = dataType.getNumElements();
+        for (unsigned i = 0; i < numElements; ++i)
+            dataType.getElementDataType()->accept(*this);
+    }
+    virtual void apply(const HLAVariableArrayDataType& dataType);
+
+    virtual void apply(const HLAEnumeratedDataType& dataType)
+    {
+        dataType.getRepresentation()->accept(*this);
+    }
+
+    virtual void apply(const HLAFixedRecordDataType& dataType)
+    {
+        unsigned numFields = dataType.getNumFields();
+        for (unsigned i = 0; i < numFields; ++i)
+            dataType.getFieldDataType(i)->accept(*this);
+    }
+
+    virtual void apply(const HLAVariantDataType& dataType) { assert(0); }
+
+protected:
+    HLADecodeStream& _stream;
+};
+
+class HLADataTypeEncodeVisitor : public HLADataTypeVisitor {
+public:
+    HLADataTypeEncodeVisitor(HLAEncodeStream& stream) : _stream(stream) {}
+    virtual ~HLADataTypeEncodeVisitor() {}
+
+    virtual void apply(const HLAInt8DataType& dataType) { dataType.skip(_stream); }
+    virtual void apply(const HLAUInt8DataType& dataType) { dataType.skip(_stream); }
+    virtual void apply(const HLAInt16DataType& dataType) { dataType.skip(_stream); }
+    virtual void apply(const HLAUInt16DataType& dataType) { dataType.skip(_stream); }
+    virtual void apply(const HLAInt32DataType& dataType) { dataType.skip(_stream); }
+    virtual void apply(const HLAUInt32DataType& dataType) { dataType.skip(_stream); }
+    virtual void apply(const HLAInt64DataType& dataType) { dataType.skip(_stream); }
+    virtual void apply(const HLAUInt64DataType& dataType) { dataType.skip(_stream); }
+    virtual void apply(const HLAFloat32DataType& dataType) { dataType.skip(_stream); }
+    virtual void apply(const HLAFloat64DataType& dataType) { dataType.skip(_stream); }
+
+    virtual void apply(const HLAFixedArrayDataType& dataType)
+    {
+        /// FIXME, might vanish in this sense ...
+        // dataType.encode(_stream, *this);
+        unsigned numElements = dataType.getNumElements();
+        for (unsigned i = 0; i < numElements; ++i)
+            dataType.getElementDataType()->accept(*this);
+    }
+    virtual void apply(const HLAVariableArrayDataType& dataType);
+
+    virtual void apply(const HLAEnumeratedDataType& dataType)
+    {
+        dataType.getRepresentation()->accept(*this);
+    }
+
+    virtual void apply(const HLAFixedRecordDataType& dataType)
+    {
+        unsigned numFields = dataType.getNumFields();
+        for (unsigned i = 0; i < numFields; ++i)
+            dataType.getFieldDataType(i)->accept(*this);
+    }
+
+    virtual void apply(const HLAVariantDataType& dataType) { assert(0); }
+
+protected:
+    HLAEncodeStream& _stream;
+};
+
+/// Begin implementation of some get/set visitors
+
+class HLAScalarDecodeVisitor : public HLADataTypeDecodeVisitor {
+public:
+    HLAScalarDecodeVisitor(HLADecodeStream& stream) :
+        HLADataTypeDecodeVisitor(stream)
+    {}
+
+    virtual void apply(const HLAFixedArrayDataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing scalar value");
+        HLADataTypeDecodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAVariableArrayDataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing scalar value");
+        HLADataTypeDecodeVisitor::apply(dataType);
+    }
+
+    virtual void apply(const HLAEnumeratedDataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing scalar value");
+        HLADataTypeDecodeVisitor::apply(dataType);
+    }
+
+    virtual void apply(const HLAFixedRecordDataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing scalar value");
+        HLADataTypeDecodeVisitor::apply(dataType);
+    }
+
+    virtual void apply(const HLAVariantDataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing scalar value");
+        HLADataTypeDecodeVisitor::apply(dataType);
+    }
+};
+
+class HLAScalarEncodeVisitor : public HLADataTypeEncodeVisitor {
+public:
+    HLAScalarEncodeVisitor(HLAEncodeStream& stream) :
+        HLADataTypeEncodeVisitor(stream)
+    {}
+
+    virtual void apply(const HLAFixedArrayDataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing scalar value");
+        HLADataTypeEncodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAVariableArrayDataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing scalar value");
+        HLADataTypeEncodeVisitor::apply(dataType);
+    }
+
+    virtual void apply(const HLAEnumeratedDataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing scalar value");
+        HLADataTypeEncodeVisitor::apply(dataType);
+    }
+
+    virtual void apply(const HLAFixedRecordDataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing scalar value");
+        HLADataTypeEncodeVisitor::apply(dataType);
+    }
+
+    virtual void apply(const HLAVariantDataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing scalar value");
+        HLADataTypeEncodeVisitor::apply(dataType);
+    }
+};
+
+class HLAFixedRecordDecodeVisitor : public HLADataTypeDecodeVisitor {
+public:
+    HLAFixedRecordDecodeVisitor(HLADecodeStream& stream) :
+        HLADataTypeDecodeVisitor(stream)
+    { }
+
+    virtual void apply(const HLAInt8DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value");
+        HLADataTypeDecodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAUInt8DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value");
+        HLADataTypeDecodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAInt16DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value");
+        HLADataTypeDecodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAUInt16DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value");
+        HLADataTypeDecodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAInt32DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value");
+        HLADataTypeDecodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAUInt32DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value");
+        HLADataTypeDecodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAInt64DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value");
+        HLADataTypeDecodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAUInt64DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value");
+        HLADataTypeDecodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAFloat32DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value");
+        HLADataTypeDecodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAFloat64DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value");
+        HLADataTypeDecodeVisitor::apply(dataType);
+    }
+
+    virtual void apply(const HLAFixedArrayDataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value");
+        HLADataTypeDecodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAVariableArrayDataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value");
+        HLADataTypeDecodeVisitor::apply(dataType);
+    }
+
+    virtual void apply(const HLAEnumeratedDataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value");
+        HLADataTypeDecodeVisitor::apply(dataType);
+    }
+
+    virtual void apply(const HLAVariantDataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value");
+        HLADataTypeDecodeVisitor::apply(dataType);
+    }
+};
+
+class HLAFixedRecordEncodeVisitor : public HLADataTypeEncodeVisitor {
+public:
+    HLAFixedRecordEncodeVisitor(HLAEncodeStream& stream) :
+        HLADataTypeEncodeVisitor(stream)
+    { }
+
+    virtual void apply(const HLAInt8DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value");
+        HLADataTypeEncodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAUInt8DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value");
+        HLADataTypeEncodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAInt16DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value");
+        HLADataTypeEncodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAUInt16DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value");
+        HLADataTypeEncodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAInt32DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value");
+        HLADataTypeEncodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAUInt32DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value");
+        HLADataTypeEncodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAInt64DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value");
+        HLADataTypeEncodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAUInt64DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value");
+        HLADataTypeEncodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAFloat32DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value");
+        HLADataTypeEncodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAFloat64DataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value");
+        HLADataTypeEncodeVisitor::apply(dataType);
+    }
+
+    virtual void apply(const HLAFixedArrayDataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value");
+        HLADataTypeEncodeVisitor::apply(dataType);
+    }
+    virtual void apply(const HLAVariableArrayDataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value");
+        HLADataTypeEncodeVisitor::apply(dataType);
+    }
+
+    virtual void apply(const HLAEnumeratedDataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value");
+        HLADataTypeEncodeVisitor::apply(dataType);
+    }
+
+    virtual void apply(const HLAVariantDataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value");
+        HLADataTypeEncodeVisitor::apply(dataType);
+    }
+};
+
+template<typename T>
+class HLATemplateDecodeVisitor : public HLAScalarDecodeVisitor {
+public:
+    typedef T value_type;
+
+    HLATemplateDecodeVisitor(HLADecodeStream& stream, const value_type& value = value_type()) :
+        HLAScalarDecodeVisitor(stream),
+        _value(value)
+    {}
+
+    void setValue(const value_type& value)
+    { _value = value; }
+    const value_type& getValue() const
+    { return _value; }
+
+    virtual void apply(const HLAInt8DataType& dataType)
+    {
+        int8_t value = 0;
+        dataType.decode(_stream, value);
+        _value = value_type(value);
+    }
+    virtual void apply(const HLAUInt8DataType& dataType)
+    {
+        uint8_t value = 0;
+        dataType.decode(_stream, value);
+        _value = value_type(value);
+    }
+    virtual void apply(const HLAInt16DataType& dataType)
+    {
+        int16_t value = 0;
+        dataType.decode(_stream, value);
+        _value = value_type(value);
+    }
+    virtual void apply(const HLAUInt16DataType& dataType)
+    {
+        uint16_t value = 0;
+        dataType.decode(_stream, value);
+        _value = value_type(value);
+    }
+    virtual void apply(const HLAInt32DataType& dataType)
+    {
+        int32_t value = 0;
+        dataType.decode(_stream, value);
+        _value = value_type(value);
+    }
+    virtual void apply(const HLAUInt32DataType& dataType)
+    {
+        uint32_t value = 0;
+        dataType.decode(_stream, value);
+        _value = value_type(value);
+    }
+    virtual void apply(const HLAInt64DataType& dataType)
+    {
+        int64_t value = 0;
+        dataType.decode(_stream, value);
+        _value = value_type(value);
+    }
+    virtual void apply(const HLAUInt64DataType& dataType)
+    {
+        uint64_t value = 0;
+        dataType.decode(_stream, value);
+        _value = value_type(value);
+    }
+    virtual void apply(const HLAFloat32DataType& dataType)
+    {
+        float value = 0;
+        dataType.decode(_stream, value);
+        _value = value_type(value);
+    }
+    virtual void apply(const HLAFloat64DataType& dataType)
+    {
+        double value = 0;
+        dataType.decode(_stream, value);
+        _value = value_type(value);
+    }
+
+private:
+    value_type _value;
+};
+
+template<typename T>
+class HLATemplateEncodeVisitor : public HLAScalarEncodeVisitor {
+public:
+    typedef T value_type;
+
+    HLATemplateEncodeVisitor(HLAEncodeStream& stream, const value_type& value = value_type()) :
+        HLAScalarEncodeVisitor(stream),
+        _value(value)
+    {}
+
+    void setValue(const value_type& value)
+    { _value = value; }
+    const value_type& getValue() const
+    { return _value; }
+
+    virtual void apply(const HLAInt8DataType& dataType)
+    {
+        dataType.encode(_stream, _value);
+    }
+    virtual void apply(const HLAUInt8DataType& dataType)
+    {
+        dataType.encode(_stream, _value);
+    }
+    virtual void apply(const HLAInt16DataType& dataType)
+    {
+        dataType.encode(_stream, _value);
+    }
+    virtual void apply(const HLAUInt16DataType& dataType)
+    {
+        dataType.encode(_stream, _value);
+    }
+    virtual void apply(const HLAInt32DataType& dataType)
+    {
+        dataType.encode(_stream, _value);
+    }
+    virtual void apply(const HLAUInt32DataType& dataType)
+    {
+        dataType.encode(_stream, _value);
+    }
+    virtual void apply(const HLAInt64DataType& dataType)
+    {
+        dataType.encode(_stream, _value);
+    }
+    virtual void apply(const HLAUInt64DataType& dataType)
+    {
+        dataType.encode(_stream, _value);
+    }
+    virtual void apply(const HLAFloat32DataType& dataType)
+    {
+        dataType.encode(_stream, _value);
+    }
+    virtual void apply(const HLAFloat64DataType& dataType)
+    {
+        dataType.encode(_stream, _value);
+    }
+
+private:
+    value_type _value;
+};
+
+inline void HLADataTypeDecodeVisitor::apply(const HLAVariableArrayDataType& dataType)
+{
+    HLATemplateDecodeVisitor<unsigned> numElementsVisitor(_stream);
+    dataType.getSizeDataType()->accept(numElementsVisitor);
+    unsigned numElements = numElementsVisitor.getValue();
+    for (unsigned i = 0; i < numElements; ++i)
+        dataType.getElementDataType()->accept(*this);
+}
+
+inline void HLADataTypeEncodeVisitor::apply(const HLAVariableArrayDataType& dataType)
+{
+    HLATemplateEncodeVisitor<unsigned> numElementsVisitor(_stream, 0);
+    dataType.getSizeDataType()->accept(numElementsVisitor);
+}
+
+} // namespace simgear
+
+#endif
diff --git a/simgear/hla/HLAEnumeratedDataElement.cxx b/simgear/hla/HLAEnumeratedDataElement.cxx
new file mode 100644 (file)
index 0000000..a09e0de
--- /dev/null
@@ -0,0 +1,128 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "HLAEnumeratedDataElement.hxx"
+
+#include <simgear/debug/logstream.hxx>
+
+namespace simgear {
+
+HLAAbstractEnumeratedDataElement::HLAAbstractEnumeratedDataElement(const HLAEnumeratedDataType* dataType) :
+    _dataType(dataType)
+{
+}
+
+HLAAbstractEnumeratedDataElement::~HLAAbstractEnumeratedDataElement()
+{
+}
+
+bool
+HLAAbstractEnumeratedDataElement::decode(HLADecodeStream& stream)
+{
+    if (!_dataType.valid())
+        return false;
+    unsigned index;
+    if (!_dataType->decode(stream, index))
+        return false;
+    setEnumeratorIndex(index);
+    return true;
+}
+
+bool
+HLAAbstractEnumeratedDataElement::encode(HLAEncodeStream& stream) const
+{
+    if (!_dataType.valid())
+        return false;
+    return _dataType->encode(stream, getEnumeratorIndex());
+}
+
+const HLAEnumeratedDataType*
+HLAAbstractEnumeratedDataElement::getDataType() const
+{
+    return _dataType.get();
+}
+
+bool
+HLAAbstractEnumeratedDataElement::setDataType(const HLADataType* dataType)
+{
+    const HLAEnumeratedDataType* enumeratedDataType = dataType->toEnumeratedDataType();
+    if (!enumeratedDataType) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLAEnumeratedDataType: unable to set data type!");
+        return false;
+    }
+    setDataType(enumeratedDataType);
+    return true;
+}
+
+void
+HLAAbstractEnumeratedDataElement::setDataType(const HLAEnumeratedDataType* dataType)
+{
+    _dataType = dataType;
+}
+
+const HLABasicDataType*
+HLAAbstractEnumeratedDataElement::getRepresentationDataType() const
+{
+    if (!_dataType.valid())
+        return 0;
+    return _dataType->getRepresentation();
+}
+
+std::string
+HLAAbstractEnumeratedDataElement::getStringRepresentation() const
+{
+    if (!_dataType.valid())
+        return std::string();
+    return _dataType->getString(getEnumeratorIndex());
+}
+
+bool
+HLAAbstractEnumeratedDataElement::setStringRepresentation(const std::string& name)
+{
+    if (!_dataType.valid())
+        return false;
+    unsigned index = _dataType->getIndex(name);
+    if (_dataType->getNumEnumerators() <= index)
+        return false;
+    setEnumeratorIndex(index);
+    return true;
+}
+
+
+HLAEnumeratedDataElement::HLAEnumeratedDataElement(const HLAEnumeratedDataType* dataType) :
+    HLAAbstractEnumeratedDataElement(dataType),
+    _enumeratorIndex(~unsigned(0))
+{
+}
+
+HLAEnumeratedDataElement::~HLAEnumeratedDataElement()
+{
+}
+
+unsigned
+HLAEnumeratedDataElement::getEnumeratorIndex() const
+{
+    return _enumeratorIndex;
+}
+
+void
+HLAEnumeratedDataElement::setEnumeratorIndex(unsigned index)
+{
+    _enumeratorIndex = index;
+}
+
+}
diff --git a/simgear/hla/HLAEnumeratedDataElement.hxx b/simgear/hla/HLAEnumeratedDataElement.hxx
new file mode 100644 (file)
index 0000000..f7dfbd3
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright (C) 2009 - 2010  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 HLAEnumeratedDataElement_hxx
+#define HLAEnumeratedDataElement_hxx
+
+#include "HLADataElement.hxx"
+#include "HLAEnumeratedDataType.hxx"
+
+namespace simgear {
+
+class HLAAbstractEnumeratedDataElement : public HLADataElement {
+public:
+    HLAAbstractEnumeratedDataElement(const HLAEnumeratedDataType* dataType);
+    virtual ~HLAAbstractEnumeratedDataElement();
+
+    virtual bool decode(HLADecodeStream& stream);
+    virtual bool encode(HLAEncodeStream& stream) const;
+
+    virtual const HLAEnumeratedDataType* getDataType() const;
+    virtual bool setDataType(const HLADataType* dataType);
+    void setDataType(const HLAEnumeratedDataType* dataType);
+
+    const HLABasicDataType* getRepresentationDataType() const;
+
+    std::string getStringRepresentation() const;
+    bool setStringRepresentation(const std::string& name);
+
+    virtual unsigned getEnumeratorIndex() const = 0;
+    virtual void setEnumeratorIndex(unsigned index) = 0;
+
+private:
+    SGSharedPtr<const HLAEnumeratedDataType> _dataType;
+};
+
+class HLAEnumeratedDataElement : public HLAAbstractEnumeratedDataElement {
+public:
+    HLAEnumeratedDataElement(const HLAEnumeratedDataType* dataType);
+    virtual ~HLAEnumeratedDataElement();
+
+    virtual unsigned getEnumeratorIndex() const;
+    virtual void setEnumeratorIndex(unsigned index);
+
+private:
+    unsigned _enumeratorIndex;
+};
+
+}
+
+#endif
diff --git a/simgear/hla/HLAEnumeratedDataType.cxx b/simgear/hla/HLAEnumeratedDataType.cxx
new file mode 100644 (file)
index 0000000..56fd34d
--- /dev/null
@@ -0,0 +1,180 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "HLAEnumeratedDataType.hxx"
+
+#include <map>
+#include <sstream>
+#include <vector>
+#include "HLAEnumeratedDataType.hxx"
+#include "HLADataTypeVisitor.hxx"
+
+namespace simgear {
+
+template<typename DataType, typename T>
+class HLAEnumeratedDataType::Map : public HLAEnumeratedDataType::AbstractMap {
+public:
+    typedef typename std::pair<std::string,T> RepresentationPair;
+    typedef typename std::map<T, unsigned> RepresentationIndexMap;
+    typedef typename std::vector<RepresentationPair> IndexRepresentationMap;
+    typedef typename std::map<std::string, unsigned> StringIndexMap;
+
+    Map(const DataType* dataType) :
+        _dataType(dataType)
+    { }
+    virtual bool encode(HLAEncodeStream& stream, unsigned index) const
+    {
+        T value = _otherRepresentation;
+        if (index < _indexRepresentationMap.size())
+            value = _indexRepresentationMap[index].second;
+        if (!_dataType->encode(stream, value))
+            return false;
+        return true;
+    }
+    virtual bool decode(HLADecodeStream& stream, unsigned& index) const
+    {
+        T value;
+        if (!_dataType->decode(stream, value))
+            return false;
+        typename RepresentationIndexMap::const_iterator i;
+        i = _representationIndexMap.find(value);
+        if (i == _representationIndexMap.end())
+            index = _indexRepresentationMap.size();
+        else
+            index = i->second;
+        return true;
+    }
+    virtual const HLABasicDataType* getDataType() const
+    { return _dataType.get(); }
+
+    virtual bool add(const std::string& name, const std::string& number)
+    {
+        std::stringstream ss(number);
+        T value;
+        ss >> value;
+        if (ss.fail())
+            return false;
+        if (_representationIndexMap.find(value) != _representationIndexMap.end())
+            return false;
+        if (_stringIndexMap.find(name) != _stringIndexMap.end())
+            return false;
+        _stringIndexMap[name] = _indexRepresentationMap.size();
+        _representationIndexMap[value] = _indexRepresentationMap.size();
+        _indexRepresentationMap.push_back(RepresentationPair(name, value));
+        return true;
+    }
+    virtual std::string getString(unsigned index) const
+    {
+        if (_indexRepresentationMap.size() <= index)
+            return std::string();
+        return _indexRepresentationMap[index].first;
+    }
+    virtual unsigned getIndex(const std::string& name) const
+    {
+        typename StringIndexMap::const_iterator i = _stringIndexMap.find(name);
+        if (i == _stringIndexMap.end())
+            return ~unsigned(0);
+        return i->second;
+    }
+    virtual unsigned getNumEnumerators() const
+    { return _indexRepresentationMap.size(); }
+
+private:
+    IndexRepresentationMap _indexRepresentationMap;
+    StringIndexMap _stringIndexMap;
+    RepresentationIndexMap _representationIndexMap;
+
+    T _otherRepresentation;
+    SGSharedPtr<const DataType> _dataType;
+};
+
+class HLAEnumeratedDataType::RepresentationVisitor : public HLADataTypeVisitor {
+public:
+    virtual void apply(const HLAInt8DataType& dataType)
+    { _map = new Map<HLAInt8DataType, int8_t>(&dataType); }
+    virtual void apply(const HLAUInt8DataType& dataType)
+    { _map = new Map<HLAUInt8DataType, uint8_t>(&dataType); }
+    virtual void apply(const HLAInt16DataType& dataType)
+    { _map = new Map<HLAInt16DataType, int16_t>(&dataType); }
+    virtual void apply(const HLAUInt16DataType& dataType)
+    { _map = new Map<HLAUInt16DataType, uint16_t>(&dataType); }
+    virtual void apply(const HLAInt32DataType& dataType)
+    { _map = new Map<HLAInt32DataType, int32_t>(&dataType); }
+    virtual void apply(const HLAUInt32DataType& dataType)
+    { _map = new Map<HLAUInt32DataType, uint32_t>(&dataType); }
+    virtual void apply(const HLAInt64DataType& dataType)
+    { _map = new Map<HLAInt64DataType, int64_t>(&dataType); }
+    virtual void apply(const HLAUInt64DataType& dataType)
+    { _map = new Map<HLAUInt64DataType, uint64_t>(&dataType); }
+
+    SGSharedPtr<AbstractMap> _map;
+};
+
+HLAEnumeratedDataType::HLAEnumeratedDataType(const std::string& name) :
+    HLADataType(name)
+{
+}
+
+HLAEnumeratedDataType::~HLAEnumeratedDataType()
+{
+}
+
+void
+HLAEnumeratedDataType::accept(HLADataTypeVisitor& visitor) const
+{
+    visitor.apply(*this);
+}
+
+const HLAEnumeratedDataType*
+HLAEnumeratedDataType::toEnumeratedDataType() const
+{
+    return this;
+}
+
+bool
+HLAEnumeratedDataType::decode(HLADecodeStream& stream, unsigned& index) const
+{
+    if (!_map.valid())
+        return false;
+
+    if (!_map->decode(stream, index))
+        return false;
+    return true;
+}
+
+bool
+HLAEnumeratedDataType::encode(HLAEncodeStream& stream, unsigned index) const
+{
+    if (!_map.valid())
+        return false;
+
+    return _map->encode(stream, index);
+}
+
+void
+HLAEnumeratedDataType::setRepresentation(HLABasicDataType* representation)
+{
+    if (!representation)
+        return;
+
+    RepresentationVisitor representationVisitor;
+    representation->accept(representationVisitor);
+    _map.swap(representationVisitor._map);
+}
+
+} // namespace simgear
+
diff --git a/simgear/hla/HLAEnumeratedDataType.hxx b/simgear/hla/HLAEnumeratedDataType.hxx
new file mode 100644 (file)
index 0000000..7066adb
--- /dev/null
@@ -0,0 +1,95 @@
+// Copyright (C) 2009 - 2010  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 HLAEnumeratedDataType_hxx
+#define HLAEnumeratedDataType_hxx
+
+#include <string>
+#include <simgear/structure/SGSharedPtr.hxx>
+#include "HLADataType.hxx"
+
+namespace simgear {
+
+class HLAEnumeratedDataType : public HLADataType {
+public:
+    HLAEnumeratedDataType(const std::string& name = "HLAEnumeratedDataType");
+    virtual ~HLAEnumeratedDataType();
+
+    virtual void accept(HLADataTypeVisitor& visitor) const;
+
+    virtual const HLAEnumeratedDataType* toEnumeratedDataType() const;
+
+    virtual bool decode(HLADecodeStream& stream, unsigned& index) const;
+    virtual bool encode(HLAEncodeStream& stream, unsigned index) const;
+
+    std::string getString(unsigned index) const
+    {
+        if (!_map.valid())
+            return std::string();
+        return _map->getString(index);
+    }
+    unsigned getIndex(const std::string& name) const
+    {
+        if (!_map.valid())
+            return ~unsigned(0);
+        return _map->getIndex(name);
+    }
+    unsigned getNumEnumerators() const
+    {
+        if (!_map.valid())
+            return 0;
+        return _map->getNumEnumerators();
+    }
+
+    bool addEnumerator(const std::string& name, const std::string& number)
+    {
+        if (!_map.valid())
+            return false;
+        return _map->add(name, number);
+    }
+
+    void setRepresentation(HLABasicDataType* representation);
+    const HLABasicDataType* getRepresentation() const
+    {
+        if (!_map.valid())
+            return 0;
+        return _map->getDataType();
+    }
+
+private:
+    class AbstractMap : public SGReferenced {
+    public:
+        virtual ~AbstractMap() {}
+        virtual bool encode(HLAEncodeStream& stream, unsigned index) const = 0;
+        virtual bool decode(HLADecodeStream& stream, unsigned& index) const = 0;
+        virtual const HLABasicDataType* getDataType() const = 0;
+        virtual bool add(const std::string& name, const std::string& number) = 0;
+        virtual std::string getString(unsigned index) const = 0;
+        virtual unsigned getIndex(const std::string& name) const = 0;
+        virtual unsigned getNumEnumerators() const = 0;
+    };
+
+    template<typename DataType, typename T>
+    class Map;
+    class RepresentationVisitor;
+
+    SGSharedPtr<AbstractMap> _map;
+};
+
+} // namespace simgear
+
+#endif
diff --git a/simgear/hla/HLAFederate.cxx b/simgear/hla/HLAFederate.cxx
new file mode 100644 (file)
index 0000000..14f6c0c
--- /dev/null
@@ -0,0 +1,246 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "HLAFederate.hxx"
+
+#include "RTIFederate.hxx"
+#include "RTIInteractionClass.hxx"
+#include "RTIObjectClass.hxx"
+#include "HLADataElement.hxx"
+#include "HLADataType.hxx"
+#include "HLAOMTXmlVisitor.hxx"
+
+namespace simgear {
+
+HLAFederate::HLAFederate(const SGSharedPtr<RTIFederate>& rtiFederate) :
+    _rtiFederate(rtiFederate)
+{
+}
+
+HLAFederate::~HLAFederate()
+{
+}
+
+const std::string&
+HLAFederate::getFederateType() const
+{
+    return _rtiFederate->getFederateType();
+}
+
+const std::string&
+HLAFederate::getFederationName() const
+{
+    return _rtiFederate->getFederationName();
+}
+
+bool
+HLAFederate::createFederationExecution(const std::string& federation, const std::string& objectModel)
+{
+    return _rtiFederate->createFederationExecution(federation, objectModel);
+}
+
+bool
+HLAFederate::destroyFederationExecution(const std::string& federation)
+{
+    return _rtiFederate->destroyFederationExecution(federation);
+}
+
+bool
+HLAFederate::join(const std::string& federateType, const std::string& federation)
+{
+    return _rtiFederate->join(federateType, federation);
+}
+
+bool
+HLAFederate::resign()
+{
+    return _rtiFederate->resign();
+}
+
+bool
+HLAFederate::enableTimeConstrained()
+{
+    return _rtiFederate->enableTimeConstrained();
+}
+
+bool
+HLAFederate::disableTimeConstrained()
+{
+    return _rtiFederate->disableTimeConstrained();
+}
+
+bool
+HLAFederate::enableTimeRegulation(const SGTimeStamp& lookahead)
+{
+    return _rtiFederate->enableTimeRegulation(lookahead);
+}
+
+bool
+HLAFederate::disableTimeRegulation()
+{
+    return _rtiFederate->disableTimeRegulation();
+}
+
+bool
+HLAFederate::timeAdvanceRequestBy(const SGTimeStamp& dt)
+{
+    return _rtiFederate->timeAdvanceRequestBy(dt);
+}
+
+bool
+HLAFederate::timeAdvanceRequest(const SGTimeStamp& dt)
+{
+    return _rtiFederate->timeAdvanceRequest(dt);
+}
+
+bool
+HLAFederate::tick()
+{
+    return _rtiFederate->tick();
+}
+
+bool
+HLAFederate::tick(const double& minimum, const double& maximum)
+{
+    return _rtiFederate->tick(minimum, maximum);
+}
+
+bool
+HLAFederate::readObjectModelTemplate(const std::string& objectModel,
+                                     HLAFederate::ObjectModelFactory& objectModelFactory)
+{
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_IO, SG_ALERT, "Could not process HLA XML object model file: "
+               "No rti federate available!");
+        return false;
+    }
+
+    // The XML version of the federate object model.
+    // This one covers the generic attributes, parameters and data types.
+    HLAOMTXmlVisitor omtXmlVisitor;
+    try {
+        readXML(objectModel, omtXmlVisitor);
+    } catch (const sg_throwable& e) {
+        SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file: "
+               << e.getMessage());
+        return false;
+    } catch (...) {
+        SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file");
+        return false;
+    }
+
+    unsigned numObjectClasses = omtXmlVisitor.getNumObjectClasses();
+    for (unsigned i = 0; i < numObjectClasses; ++i) {
+        const HLAOMTXmlVisitor::ObjectClass* objectClass = omtXmlVisitor.getObjectClass(i);
+        std::string objectClassName = objectClass->getName();
+
+        SGSharedPtr<HLAObjectClass> hlaObjectClass = objectModelFactory.createObjectClass(objectClassName, *this);
+        if (!hlaObjectClass.valid()) {
+            SG_LOG(SG_IO, SG_INFO, "Ignoring object class \"" << objectClassName << "\".");
+            continue;
+        }
+
+        bool publish = objectModelFactory.publishObjectClass(objectClassName, objectClass->getSharing());
+        bool subscribe = objectModelFactory.subscribeObjectClass(objectClassName, objectClass->getSharing());
+
+        std::set<unsigned> subscriptions;
+        std::set<unsigned> publications;
+
+        // process the attributes
+        for (unsigned j = 0; j < objectClass->getNumAttributes(); ++j) {
+            const simgear::HLAOMTXmlVisitor::Attribute* attribute;
+            attribute = objectClass->getAttribute(j);
+
+            std::string attributeName = attribute->getName();
+            unsigned index = hlaObjectClass->getAttributeIndex(attributeName);
+
+            if (index == ~0u) {
+                SG_LOG(SG_IO, SG_WARN, "RTI does not know the \"" << attributeName << "\" attribute!");
+                continue;
+            }
+
+            SGSharedPtr<HLADataType> dataType;
+            dataType = omtXmlVisitor.getAttributeDataType(objectClassName, attributeName);
+            if (!dataType.valid()) {
+                SG_LOG(SG_IO, SG_WARN, "Could not find data type for attribute \""
+                       << attributeName << "\" in object class \"" << objectClassName << "\"!");
+            }
+            hlaObjectClass->setAttributeDataType(index, dataType);
+
+            HLAUpdateType updateType = HLAUndefinedUpdate;
+            if (attribute->_updateType == "Periodic")
+                updateType = HLAPeriodicUpdate;
+            else if (attribute->_updateType == "Static")
+                updateType = HLAStaticUpdate;
+            else if (attribute->_updateType == "Conditional")
+                updateType = HLAConditionalUpdate;
+            hlaObjectClass->setAttributeUpdateType(index, updateType);
+
+            if (subscribe && objectModelFactory.subscribeAttribute(objectClassName, attributeName, attribute->_sharing))
+                subscriptions.insert(index);
+            if (publish && objectModelFactory.publishAttribute(objectClassName, attributeName, attribute->_sharing))
+                publications.insert(index);
+        }
+
+        if (publish)
+            hlaObjectClass->publish(publications);
+        if (subscribe)
+            hlaObjectClass->subscribe(subscriptions, true);
+
+        _objectClassMap[objectClassName] = hlaObjectClass;
+    }
+
+    return true;
+}
+
+HLAObjectClass*
+HLAFederate::getObjectClass(const std::string& name)
+{
+    ObjectClassMap::const_iterator i = _objectClassMap.find(name);
+    if (i == _objectClassMap.end())
+        return 0;
+    return i->second.get();
+}
+
+const HLAObjectClass*
+HLAFederate::getObjectClass(const std::string& name) const
+{
+    ObjectClassMap::const_iterator i = _objectClassMap.find(name);
+    if (i == _objectClassMap.end())
+        return 0;
+    return i->second.get();
+}
+
+HLAInteractionClass*
+HLAFederate::getInteractionClass(const std::string& name)
+{
+    InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
+    if (i == _interactionClassMap.end())
+        return 0;
+    return i->second.get();
+}
+
+const HLAInteractionClass*
+HLAFederate::getInteractionClass(const std::string& name) const
+{
+    InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
+    if (i == _interactionClassMap.end())
+        return 0;
+    return i->second.get();
+}
+
+} // namespace simgear
diff --git a/simgear/hla/HLAFederate.hxx b/simgear/hla/HLAFederate.hxx
new file mode 100644 (file)
index 0000000..64ea2b4
--- /dev/null
@@ -0,0 +1,111 @@
+// Copyright (C) 2009 - 2010  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 HLAFederate_hxx
+#define HLAFederate_hxx
+
+#include <map>
+
+#include "HLAObjectInstance.hxx"
+#include "HLAObjectClass.hxx"
+#include "HLAInteractionClass.hxx"
+
+class SGTimeStamp;
+
+namespace simgear {
+
+class RTIFederate;
+
+class HLAFederate : public SGWeakReferenced {
+public:
+    virtual ~HLAFederate();
+
+    /// Get the name of the joined federate/federation
+    const std::string& getFederateType() const;
+    const std::string& getFederationName() const;
+
+    /// Create a federation execution
+    /// Semantically this methods should be static,
+    /// but the nonstatic case could reuse the connection to the server
+    /// FIXME: cannot determine from the return value if we created the execution
+    bool createFederationExecution(const std::string& federation, const std::string& objectModel);
+    bool destroyFederationExecution(const std::string& federation);
+
+    /// Join with federateType the federation execution
+    bool join(const std::string& federateType, const std::string& federation);
+    bool resign();
+
+    bool enableTimeConstrained();
+    bool disableTimeConstrained();
+
+    bool enableTimeRegulation(const SGTimeStamp& lookahead);
+    bool disableTimeRegulation();
+
+    bool timeAdvanceRequestBy(const SGTimeStamp& dt);
+    bool timeAdvanceRequest(const SGTimeStamp& dt);
+
+    /// Process messages
+    bool tick();
+    bool tick(const double& minimum, const double& maximum);
+
+    class ObjectModelFactory {
+    public:
+        virtual ~ObjectModelFactory()
+        { }
+
+        virtual HLAObjectClass* createObjectClass(const std::string& name, HLAFederate& federate)
+        { return new HLAObjectClass(name, federate); }
+        virtual bool subscribeObjectClass(const std::string& objectClassName, const std::string& sharing)
+        { return sharing.find("Subscribe") != std::string::npos; }
+        virtual bool publishObjectClass(const std::string& objectClassName, const std::string& sharing)
+        { return sharing.find("Publish") != std::string::npos; }
+        virtual bool subscribeAttribute(const std::string& objectClassName, const std::string& attributeName, const std::string& sharing)
+        { return sharing.find("Subscribe") != std::string::npos; }
+        virtual bool publishAttribute(const std::string& objectClassName, const std::string& attributeName, const std::string& sharing)
+        { return sharing.find("Publish") != std::string::npos; }
+
+    };
+
+    /// Read an omt xml file
+    bool readObjectModelTemplate(const std::string& objectModel,
+                                 ObjectModelFactory& objectModelFactory);
+
+    HLAObjectClass* getObjectClass(const std::string& name);
+    const HLAObjectClass* getObjectClass(const std::string& name) const;
+
+    HLAInteractionClass* getInteractionClass(const std::string& name);
+    const HLAInteractionClass* getInteractionClass(const std::string& name) const;
+
+protected:
+    HLAFederate(const SGSharedPtr<RTIFederate>& rtiFederate);
+
+private:
+    SGSharedPtr<RTIFederate> _rtiFederate;
+
+    typedef std::map<std::string, SGSharedPtr<HLAObjectClass> > ObjectClassMap;
+    ObjectClassMap _objectClassMap;
+
+    typedef std::map<std::string, SGSharedPtr<HLAInteractionClass> > InteractionClassMap;
+    InteractionClassMap _interactionClassMap;
+
+    friend class HLAInteractionClass;
+    friend class HLAObjectClass;
+};
+
+} // namespace simgear
+
+#endif
diff --git a/simgear/hla/HLAFixedRecordDataElement.cxx b/simgear/hla/HLAFixedRecordDataElement.cxx
new file mode 100644 (file)
index 0000000..d0980b9
--- /dev/null
@@ -0,0 +1,179 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "HLAFixedRecordDataElement.hxx"
+
+#include <string>
+#include <vector>
+#include <simgear/debug/logstream.hxx>
+#include "HLADataTypeVisitor.hxx"
+
+namespace simgear {
+
+HLAAbstractFixedRecordDataElement::HLAAbstractFixedRecordDataElement(const HLAFixedRecordDataType* dataType) :
+    _dataType(dataType)
+{
+}
+
+HLAAbstractFixedRecordDataElement::~HLAAbstractFixedRecordDataElement()
+{
+}
+
+bool
+HLAAbstractFixedRecordDataElement::decode(HLADecodeStream& stream)
+{
+    if (!_dataType.valid())
+        return false;
+    return _dataType->decode(stream, *this);
+}
+
+bool
+HLAAbstractFixedRecordDataElement::encode(HLAEncodeStream& stream) const
+{
+    if (!_dataType.valid())
+        return false;
+    return _dataType->encode(stream, *this);
+}
+
+const HLAFixedRecordDataType*
+HLAAbstractFixedRecordDataElement::getDataType() const
+{
+    return _dataType.get();
+}
+
+bool
+HLAAbstractFixedRecordDataElement::setDataType(const HLADataType* dataType)
+{
+    const HLAFixedRecordDataType* fixedRecordDataType = dataType->toFixedRecordDataType();
+    if (!fixedRecordDataType) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLAFixedRecordDataType: unable to set data type!");
+        return false;
+    }
+    setDataType(fixedRecordDataType);
+    return true;
+}
+
+void
+HLAAbstractFixedRecordDataElement::setDataType(const HLAFixedRecordDataType* dataType)
+{
+    _dataType = dataType;
+}
+
+unsigned
+HLAAbstractFixedRecordDataElement::getNumFields() const
+{
+    return _dataType->getNumFields();
+}
+
+unsigned
+HLAAbstractFixedRecordDataElement::getFieldNumber(const std::string& name) const
+{
+    return _dataType->getFieldNumber(name);
+}
+
+const HLADataType*
+HLAAbstractFixedRecordDataElement::getFieldDataType(unsigned i) const
+{
+    return _dataType->getFieldDataType(i);
+}
+
+const HLADataType*
+HLAAbstractFixedRecordDataElement::getFieldDataType(const std::string& name) const
+{
+    return getFieldDataType(getFieldNumber(name));
+}
+
+
+HLAFixedRecordDataElement::HLAFixedRecordDataElement(const HLAFixedRecordDataType* dataType) :
+    HLAAbstractFixedRecordDataElement(dataType)
+{
+    _fieldVector.resize(getNumFields());
+}
+
+HLAFixedRecordDataElement::~HLAFixedRecordDataElement()
+{
+}
+
+bool
+HLAFixedRecordDataElement::decodeField(HLADecodeStream& stream, unsigned i)
+{
+    HLADataElement* dataElement = getField(i);
+    if (dataElement) {
+        return dataElement->decode(stream);
+    } else {
+        HLADataTypeDecodeVisitor visitor(stream);
+        getDataType()->getFieldDataType(i)->accept(visitor);
+        return true;
+    }
+}
+
+bool
+HLAFixedRecordDataElement::encodeField(HLAEncodeStream& stream, unsigned i) const
+{
+    const HLADataElement* dataElement = getField(i);
+    if (dataElement) {
+        return dataElement->encode(stream);
+    } else {
+        HLADataTypeEncodeVisitor visitor(stream);
+        getDataType()->getFieldDataType(i)->accept(visitor);
+        return true;
+    }
+}
+
+HLADataElement*
+HLAFixedRecordDataElement::getField(const std::string& name)
+{
+    return getField(getFieldNumber(name));
+}
+
+const HLADataElement*
+HLAFixedRecordDataElement::getField(const std::string& name) const
+{
+    return getField(getFieldNumber(name));
+}
+
+HLADataElement*
+HLAFixedRecordDataElement::getField(unsigned i)
+{
+    if (_fieldVector.size() <= i)
+        return 0;
+    return _fieldVector[i].get();
+}
+
+const HLADataElement*
+HLAFixedRecordDataElement::getField(unsigned i) const
+{
+    if (_fieldVector.size() <= i)
+        return 0;
+    return _fieldVector[i].get();
+}
+
+void
+HLAFixedRecordDataElement::setField(unsigned index, HLADataElement* value)
+{
+    if (getNumFields() <= index)
+        return;
+    _fieldVector[index] = value;
+}
+
+void
+HLAFixedRecordDataElement::setField(const std::string& name, HLADataElement* value)
+{
+    setField(getFieldNumber(name), value);
+}
+
+}
diff --git a/simgear/hla/HLAFixedRecordDataElement.hxx b/simgear/hla/HLAFixedRecordDataElement.hxx
new file mode 100644 (file)
index 0000000..d99719d
--- /dev/null
@@ -0,0 +1,77 @@
+// Copyright (C) 2009 - 2010  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 HLAFixedRecordDataElement_hxx
+#define HLAFixedRecordDataElement_hxx
+
+#include <string>
+#include <vector>
+#include "HLADataElement.hxx"
+#include "HLAFixedRecordDataType.hxx"
+
+namespace simgear {
+
+class HLAAbstractFixedRecordDataElement : public HLADataElement {
+public:
+    HLAAbstractFixedRecordDataElement(const HLAFixedRecordDataType* dataType);
+    virtual ~HLAAbstractFixedRecordDataElement();
+
+    virtual bool decode(HLADecodeStream& stream);
+    virtual bool encode(HLAEncodeStream& stream) const;
+
+    virtual const HLAFixedRecordDataType* getDataType() const;
+    virtual bool setDataType(const HLADataType* dataType);
+    void setDataType(const HLAFixedRecordDataType* dataType);
+
+    unsigned getNumFields() const;
+    unsigned getFieldNumber(const std::string& name) const;
+
+    const HLADataType* getFieldDataType(unsigned i) const;
+    const HLADataType* getFieldDataType(const std::string& name) const;
+
+    virtual bool decodeField(HLADecodeStream& stream, unsigned i) = 0;
+    virtual bool encodeField(HLAEncodeStream& stream, unsigned i) const = 0;
+
+private:
+    SGSharedPtr<const HLAFixedRecordDataType> _dataType;
+};
+
+class HLAFixedRecordDataElement : public HLAAbstractFixedRecordDataElement {
+public:
+    HLAFixedRecordDataElement(const HLAFixedRecordDataType* dataType);
+    virtual ~HLAFixedRecordDataElement();
+
+    virtual bool decodeField(HLADecodeStream& stream, unsigned i);
+    virtual bool encodeField(HLAEncodeStream& stream, unsigned i) const;
+
+    HLADataElement* getField(const std::string& name);
+    const HLADataElement* getField(const std::string& name) const;
+
+    HLADataElement* getField(unsigned i);
+    const HLADataElement* getField(unsigned i) const;
+
+    void setField(unsigned index, HLADataElement* value);
+    void setField(const std::string& name, HLADataElement* value);
+
+private:
+    typedef std::vector<SGSharedPtr<HLADataElement> > FieldVector;
+    FieldVector _fieldVector;
+};
+
+}
+
+#endif
diff --git a/simgear/hla/HLAFixedRecordDataType.cxx b/simgear/hla/HLAFixedRecordDataType.cxx
new file mode 100644 (file)
index 0000000..acec73a
--- /dev/null
@@ -0,0 +1,77 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "HLAFixedRecordDataType.hxx"
+
+#include "HLADataTypeVisitor.hxx"
+#include "HLAFixedRecordDataElement.hxx"
+
+namespace simgear {
+
+HLAFixedRecordDataType::HLAFixedRecordDataType(const std::string& name) :
+    HLADataType(name)
+{
+}
+
+HLAFixedRecordDataType::~HLAFixedRecordDataType()
+{
+}
+
+void
+HLAFixedRecordDataType::accept(HLADataTypeVisitor& visitor) const
+{
+    visitor.apply(*this);
+}
+
+const HLAFixedRecordDataType*
+HLAFixedRecordDataType::toFixedRecordDataType() const
+{
+    return this;
+}
+
+bool
+HLAFixedRecordDataType::decode(HLADecodeStream& stream, HLAAbstractFixedRecordDataElement& value) const
+{
+    stream.alignOffsetForSize(getAlignment());
+    unsigned numFields = getNumFields();
+    for (unsigned i = 0; i < numFields; ++i)
+        if (!value.decodeField(stream, i))
+            return false;
+    return true;
+}
+
+bool
+HLAFixedRecordDataType::encode(HLAEncodeStream& stream, const HLAAbstractFixedRecordDataElement& value) const
+{
+    stream.alignOffsetForSize(getAlignment());
+    unsigned numFields = getNumFields();
+    for (unsigned i = 0; i < numFields; ++i)
+        if (!value.encodeField(stream, i))
+            return false;
+    return true;
+}
+
+void
+HLAFixedRecordDataType::addField(const std::string& name, const HLADataType* dataType)
+{
+    // FIXME this only works if we do not reset the alignment to something smaller
+    if (getAlignment() < dataType->getAlignment())
+        setAlignment(dataType->getAlignment());
+    _fieldList.push_back(Field(name, dataType));
+}
+
+} // namespace simgear
diff --git a/simgear/hla/HLAFixedRecordDataType.hxx b/simgear/hla/HLAFixedRecordDataType.hxx
new file mode 100644 (file)
index 0000000..17c32ac
--- /dev/null
@@ -0,0 +1,91 @@
+// Copyright (C) 2009 - 2010  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 HLAFixedRecordDataType_hxx
+#define HLAFixedRecordDataType_hxx
+
+#include <string>
+#include <vector>
+#include <simgear/structure/SGSharedPtr.hxx>
+#include "HLADataType.hxx"
+
+namespace simgear {
+
+class HLAAbstractFixedRecordDataElement;
+
+class HLAFixedRecordDataType : public HLADataType {
+public:
+    HLAFixedRecordDataType(const std::string& name = "HLAFixedRecordDataType");
+    virtual ~HLAFixedRecordDataType();
+
+    virtual void accept(HLADataTypeVisitor& visitor) const;
+
+    virtual const HLAFixedRecordDataType* toFixedRecordDataType() const;
+
+    virtual bool decode(HLADecodeStream& stream, HLAAbstractFixedRecordDataElement& value) const;
+    virtual bool encode(HLAEncodeStream& stream, const HLAAbstractFixedRecordDataElement& value) const;
+
+    unsigned getNumFields() const
+    { return _fieldList.size(); }
+
+    std::string getFieldName(unsigned i) const
+    {
+        if (_fieldList.size() <= i)
+            return std::string();
+        return _fieldList[i].getName();
+    }
+    const HLADataType* getFieldDataType(unsigned i) const
+    {
+        if (_fieldList.size() <= i)
+            return 0;
+        return _fieldList[i].getDataType();
+    }
+
+    unsigned getFieldNumber(const std::string& name) const
+    {
+        for (unsigned i = 0; i < _fieldList.size(); ++i) {
+            if (_fieldList[i].getName() != name)
+                continue;
+            return i;
+        }
+        return ~0u;
+    }
+
+    void addField(const std::string& name, const HLADataType* dataType);
+
+private:
+    struct Field {
+        Field(const std::string& name, const HLADataType* dataType) :
+            _name(name), _dataType(dataType) {}
+        const std::string& getName() const
+        { return _name; }
+
+        const HLADataType* getDataType() const
+        { return _dataType.get(); }
+
+    private:
+        std::string _name;
+        SGSharedPtr<const HLADataType> _dataType;
+    };
+
+    typedef std::vector<Field> FieldList;
+    FieldList _fieldList;
+};
+
+} // namespace simgear
+
+#endif
diff --git a/simgear/hla/HLAInteractionClass.hxx b/simgear/hla/HLAInteractionClass.hxx
new file mode 100644 (file)
index 0000000..c45c22d
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright (C) 2009 - 2010  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 HLAInteractionClass_hxx
+#define HLAInteractionClass_hxx
+
+namespace simgear {
+
+class RTIInteractionClass;
+
+class HLAInteractionClass : public SGWeakReferenced {
+public:
+    virtual ~HLAInteractionClass() {}
+};
+
+} // namespace simgear
+
+#endif
diff --git a/simgear/hla/HLALocation.hxx b/simgear/hla/HLALocation.hxx
new file mode 100644 (file)
index 0000000..20aea83
--- /dev/null
@@ -0,0 +1,549 @@
+// Copyright (C) 2009 - 2010  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 HLALocation_hxx
+#define HLALocation_hxx
+
+#include "HLABasicDataElement.hxx"
+
+namespace simgear {
+
+class HLAAbstractLocation : public SGReferenced {
+public:
+    virtual ~HLAAbstractLocation() {}
+
+    virtual SGVec3d getCartPosition() const = 0;
+    virtual void setCartPosition(const SGVec3d&) = 0;
+
+    virtual SGQuatd getCartOrientation() const = 0;
+    virtual void setCartOrientation(const SGQuatd&) = 0;
+
+    virtual SGVec3d getAngularBodyVelocity() const = 0;
+    virtual void setAngularBodyVelocity(const SGVec3d& angular) = 0;
+
+    virtual SGVec3d getLinearBodyVelocity() const = 0;
+    virtual void setLinearBodyVelocity(const SGVec3d& linear) = 0;
+};
+
+class HLACartesianLocation : public HLAAbstractLocation {
+public:
+    HLACartesianLocation() :
+        _position(SGVec3d::zeros()),
+        _imag(SGVec3d::zeros()),
+        _angularVelocity(SGVec3d::zeros()),
+        _linearVelocity(SGVec3d::zeros())
+    { }
+
+    virtual SGVec3d getCartPosition() const
+    { return _position; }
+    virtual void setCartPosition(const SGVec3d& position)
+    { _position = position; }
+
+    virtual SGQuatd getCartOrientation() const
+    { return SGQuatd::fromPositiveRealImag(_imag); }
+    virtual void setCartOrientation(const SGQuatd& orientation)
+    { _imag = orientation.getPositiveRealImag(); }
+
+    virtual SGVec3d getAngularBodyVelocity() const
+    { return _angularVelocity; }
+    virtual void setAngularBodyVelocity(const SGVec3d& angularVelocity)
+    { _angularVelocity = angularVelocity; }
+
+    virtual SGVec3d getLinearBodyVelocity() const
+    { return _linearVelocity; }
+    virtual void setLinearBodyVelocity(const SGVec3d& linearVelocity)
+    { _linearVelocity = linearVelocity; }
+
+    HLADataElementProvider getPositionDataElement(unsigned i)
+    {
+        if (3 <= i)
+            return HLADataElementProvider();
+        return new PositionDataElement(this, i);
+    }
+    HLADataElementProvider getOrientationDataElement(unsigned i)
+    {
+        if (3 <= i)
+            return HLADataElementProvider();
+        return new OrientationDataElement(this, i);
+    }
+
+    HLADataElementProvider getAngularVelocityDataElement(unsigned i)
+    {
+        if (3 <= i)
+            return HLADataElementProvider();
+        return new AngularVelocityDataElement(this, i);
+    }
+    HLADataElementProvider getLinearVelocityDataElement(unsigned i)
+    {
+        if (3 <= i)
+            return HLADataElementProvider();
+        return new LinearVelocityDataElement(this, i);
+    }
+
+private:
+    class PositionDataElement : public HLAAbstractDoubleDataElement {
+    public:
+        PositionDataElement(HLACartesianLocation* data, unsigned index) :
+            _data(data), _index(index)
+        { }
+        virtual double getValue() const
+        { return _data->_position[_index]; }
+        virtual void setValue(double value)
+        { _data->_position[_index] = value; }
+
+    private:
+        SGSharedPtr<HLACartesianLocation> _data;
+        unsigned _index;
+    };
+
+    class OrientationDataElement : public HLAAbstractDoubleDataElement {
+    public:
+        OrientationDataElement(HLACartesianLocation* data, unsigned index) :
+            _data(data), _index(index)
+        { }
+        virtual double getValue() const
+        { return _data->_imag[_index]; }
+        virtual void setValue(double value)
+        { _data->_imag[_index] = value; }
+
+    private:
+        SGSharedPtr<HLACartesianLocation> _data;
+        unsigned _index;
+    };
+
+    class AngularVelocityDataElement : public HLAAbstractDoubleDataElement {
+    public:
+        AngularVelocityDataElement(HLACartesianLocation* data, unsigned index) :
+            _data(data), _index(index)
+        { }
+        virtual double getValue() const
+        { return _data->_angularVelocity[_index]; }
+        virtual void setValue(double value)
+        { _data->_angularVelocity[_index] = value; }
+
+    private:
+        SGSharedPtr<HLACartesianLocation> _data;
+        unsigned _index;
+    };
+
+    class LinearVelocityDataElement : public HLAAbstractDoubleDataElement {
+    public:
+        LinearVelocityDataElement(HLACartesianLocation* data, unsigned index) :
+            _data(data), _index(index)
+        { }
+        virtual double getValue() const
+        { return _data->_linearVelocity[_index]; }
+        virtual void setValue(double value)
+        { _data->_linearVelocity[_index] = value; }
+
+    private:
+        SGSharedPtr<HLACartesianLocation> _data;
+        unsigned _index;
+    };
+
+    SGVec3d _position;
+    SGVec3d _imag;
+
+    SGVec3d _angularVelocity;
+    SGVec3d _linearVelocity;
+};
+
+class HLALocationFactory : public SGReferenced {
+public:
+    virtual ~HLALocationFactory() {}
+    virtual HLAAbstractLocation* createLocation(HLAAttributePathElementMap&) const = 0;
+};
+
+class HLACartesianLocationFactory : public HLALocationFactory {
+public:
+    virtual HLAAbstractLocation* createLocation(HLAAttributePathElementMap& attributePathElementMap) const
+    {
+        HLACartesianLocation* location = new HLACartesianLocation;
+        for (unsigned i = 0; i < 3; ++i) {
+            const HLADataElement::IndexPathPair& indexPathPair = _positonIndexPathPair[i];
+            attributePathElementMap[indexPathPair.first][indexPathPair.second] = location->getPositionDataElement(i);
+        }
+        for (unsigned i = 0; i < 3; ++i) {
+            const HLADataElement::IndexPathPair& indexPathPair = _orientationIndexPathPair[i];
+            attributePathElementMap[indexPathPair.first][indexPathPair.second] = location->getOrientationDataElement(i);
+        }
+        for (unsigned i = 0; i < 3; ++i) {
+            const HLADataElement::IndexPathPair& indexPathPair = _angularVelocityIndexPathPair[i];
+            attributePathElementMap[indexPathPair.first][indexPathPair.second] = location->getAngularVelocityDataElement(i);
+        }
+        for (unsigned i = 0; i < 3; ++i) {
+            const HLADataElement::IndexPathPair& indexPathPair = _linearVelocityIndexPathPair[i];
+            attributePathElementMap[indexPathPair.first][indexPathPair.second] = location->getLinearVelocityDataElement(i);
+        }
+        return location;
+    }
+
+    void setPositionIndexPathPair(unsigned index, const HLADataElement::IndexPathPair& indexPathPair)
+    {
+        if (3 <= index)
+            return;
+        _positonIndexPathPair[index] = indexPathPair;
+    }
+    void setOrientationIndexPathPair(unsigned index, const HLADataElement::IndexPathPair& indexPathPair)
+    {
+        if (3 <= index)
+            return;
+        _orientationIndexPathPair[index] = indexPathPair;
+    }
+
+    void setAngularVelocityIndexPathPair(unsigned index, const HLADataElement::IndexPathPair& indexPathPair)
+    {
+        if (3 <= index)
+            return;
+        _angularVelocityIndexPathPair[index] = indexPathPair;
+    }
+    void setLinearVelocityIndexPathPair(unsigned index, const HLADataElement::IndexPathPair& indexPathPair)
+    {
+        if (3 <= index)
+            return;
+        _linearVelocityIndexPathPair[index] = indexPathPair;
+    }
+
+private:
+    HLADataElement::IndexPathPair _positonIndexPathPair[3];
+    HLADataElement::IndexPathPair _orientationIndexPathPair[3];
+
+    HLADataElement::IndexPathPair _angularVelocityIndexPathPair[3];
+    HLADataElement::IndexPathPair _linearVelocityIndexPathPair[3];
+};
+
+class HLAGeodeticLocation : public HLAAbstractLocation {
+public:
+    HLAGeodeticLocation() :
+        _dirty(true),
+        _cartPosition(SGVec3d::zeros()),
+        _cartOrientation(SGQuatd::unit()),
+        _cartBodyVelocity(SGVec3d::zeros()),
+        _geodPosition(),
+        _geodEulerRad(SGVec3d::zeros()),
+        _groundTrackRad(0),
+        _groundSpeedMPerSec(0),
+        _verticalSpeedMPerSec(0)
+    {
+        updateCartesianFromGeodetic();
+    }
+
+    virtual SGVec3d getCartPosition() const
+    { updateCartesianFromGeodetic(); return _cartPosition; }
+    virtual void setCartPosition(const SGVec3d& position)
+    { _cartPosition = position; _dirty = true; }
+
+    virtual SGQuatd getCartOrientation() const
+    { updateCartesianFromGeodetic(); return _cartOrientation; }
+    virtual void setCartOrientation(const SGQuatd& orientation)
+    { _cartOrientation = orientation; _dirty = true; }
+
+    virtual SGVec3d getAngularBodyVelocity() const
+    { return SGVec3d::zeros(); }
+    virtual void setAngularBodyVelocity(const SGVec3d& angular)
+    { }
+
+    virtual SGVec3d getLinearBodyVelocity() const
+    { updateCartesianFromGeodetic(); return _cartBodyVelocity; }
+    virtual void setLinearBodyVelocity(const SGVec3d& linear)
+    { _cartBodyVelocity = linear; _dirty = true; }
+
+    void setLatitudeDeg(double value)
+    { _geodPosition.setLatitudeDeg(value); _dirty = true; }
+    double getLatitudeDeg() const
+    { updateGeodeticFromCartesian(); return _geodPosition.getLatitudeDeg(); }
+    void setLatitudeRad(double value)
+    { _geodPosition.setLatitudeRad(value); _dirty = true; }
+    double getLatitudeRad() const
+    { updateGeodeticFromCartesian(); return _geodPosition.getLatitudeRad(); }
+    void setLongitudeDeg(double value)
+    { _geodPosition.setLongitudeDeg(value); _dirty = true; }
+    double getLongitudeDeg() const
+    { updateGeodeticFromCartesian(); return _geodPosition.getLongitudeDeg(); }
+    void setLongitudeRad(double value)
+    { _geodPosition.setLongitudeRad(value); _dirty = true; }
+    double getLongitudeRad() const
+    { updateGeodeticFromCartesian(); return _geodPosition.getLongitudeRad(); }
+    void setElevationFt(double value)
+    { _geodPosition.setElevationFt(value); _dirty = true; }
+    double getElevationFt() const
+    { updateGeodeticFromCartesian(); return _geodPosition.getElevationFt(); }
+    void setElevationM(double value)
+    { _geodPosition.setElevationM(value); _dirty = true; }
+    double getElevationM() const
+    { updateGeodeticFromCartesian(); return _geodPosition.getElevationM(); }
+
+    void setHeadingRad(double value)
+    { _geodEulerRad[2] = value; _dirty = true; }
+    double getHeadingRad() const
+    { updateGeodeticFromCartesian(); return _geodEulerRad[2]; }
+    void setHeadingDeg(double value)
+    { setHeadingRad(SGMiscd::deg2rad(value)); }
+    double getHeadingDeg() const
+    { return SGMiscd::rad2deg(getHeadingRad()); }
+    void setPitchRad(double value)
+    { _geodEulerRad[1] = value; _dirty = true; }
+    double getPitchRad() const
+    { updateGeodeticFromCartesian(); return _geodEulerRad[1]; }
+    void setPitchDeg(double value)
+    { setPitchRad(SGMiscd::deg2rad(value)); }
+    double getPitchDeg() const
+    { return SGMiscd::rad2deg(getPitchRad()); }
+    void setRollRad(double value)
+    { _geodEulerRad[0] = value; _dirty = true; }
+    double getRollRad() const
+    { updateGeodeticFromCartesian(); return _geodEulerRad[0]; }
+    void setRollDeg(double value)
+    { setRollRad(SGMiscd::deg2rad(value)); }
+    double getRollDeg() const
+    { return SGMiscd::rad2deg(getRollRad()); }
+
+    void setGroundTrackRad(double value)
+    { _groundTrackRad = value; _dirty = true; }
+    double getGroundTrackRad() const
+    { updateGeodeticFromCartesian(); return _groundTrackRad; }
+    void setGroundTrackDeg(double value)
+    { setGroundTrackRad(SGMiscd::deg2rad(value)); }
+    double getGroundTrackDeg() const
+    { return SGMiscd::rad2deg(getGroundTrackRad()); }
+
+
+    void setGroundSpeedMPerSec(double value)
+    { _groundSpeedMPerSec = value; _dirty = true; }
+    double getGroundSpeedMPerSec() const
+    { updateGeodeticFromCartesian(); return _groundSpeedMPerSec; }
+    void setGroundSpeedFtPerSec(double value)
+    { setGroundSpeedMPerSec(SG_FEET_TO_METER*value); }
+    double getGroundSpeedFtPerSec() const
+    { return SG_METER_TO_FEET*getGroundSpeedMPerSec(); }
+    void setGroundSpeedKnots(double value)
+    { setGroundSpeedMPerSec(SG_KT_TO_MPS*value); }
+    double getGroundSpeedKnots() const
+    { return SG_MPS_TO_KT*getGroundSpeedMPerSec(); }
+
+    void setVerticalSpeedMPerSec(double value)
+    { _verticalSpeedMPerSec = value; _dirty = true; }
+    double getVerticalSpeedMPerSec() const
+    { updateGeodeticFromCartesian(); return _verticalSpeedMPerSec; }
+    void setVerticalSpeedFtPerSec(double value)
+    { setVerticalSpeedMPerSec(SG_FEET_TO_METER*value); }
+    double getVerticalSpeedFtPerSec() const
+    { return SG_METER_TO_FEET*getVerticalSpeedMPerSec(); }
+    void setVerticalSpeedFtPerMin(double value)
+    { setVerticalSpeedFtPerSec(value/60); }
+    double getVerticalSpeedFtPerMin() const
+    { return 60*getVerticalSpeedFtPerSec(); }
+
+#define DATA_ELEMENT(name) \
+    HLADataElementProvider get## name ## DataElement()                  \
+    { return new DataElement<&HLAGeodeticLocation::get## name, &HLAGeodeticLocation::set ## name>(this); }
+
+    DATA_ELEMENT(LatitudeDeg)
+    DATA_ELEMENT(LatitudeRad)
+    DATA_ELEMENT(LongitudeDeg)
+    DATA_ELEMENT(LongitudeRad)
+    DATA_ELEMENT(ElevationFt)
+    DATA_ELEMENT(ElevationM)
+    DATA_ELEMENT(HeadingDeg)
+    DATA_ELEMENT(HeadingRad)
+    DATA_ELEMENT(PitchDeg)
+    DATA_ELEMENT(PitchRad)
+    DATA_ELEMENT(RollDeg)
+    DATA_ELEMENT(RollRad)
+
+    DATA_ELEMENT(GroundTrackDeg)
+    DATA_ELEMENT(GroundTrackRad)
+    DATA_ELEMENT(GroundSpeedMPerSec)
+    DATA_ELEMENT(GroundSpeedFtPerSec)
+    DATA_ELEMENT(GroundSpeedKnots)
+    DATA_ELEMENT(VerticalSpeedMPerSec)
+    DATA_ELEMENT(VerticalSpeedFtPerSec)
+    DATA_ELEMENT(VerticalSpeedFtPerMin)
+
+#undef DATA_ELEMENT
+
+private:
+    template<double (HLAGeodeticLocation::*getter)() const,
+             void (HLAGeodeticLocation::*setter)(double)>
+    class DataElement : public HLAAbstractDoubleDataElement {
+    public:
+        DataElement(HLAGeodeticLocation* data) :
+            _data(data)
+        { }
+        virtual double getValue() const
+        { return (_data->*getter)(); }
+        virtual void setValue(double value)
+        { (_data->*setter)(value); }
+
+    private:
+        SGSharedPtr<HLAGeodeticLocation> _data;
+    };
+
+    void updateGeodeticFromCartesian() const
+    {
+        if (!_dirty)
+            return;
+        _geodPosition = SGGeod::fromCart(_cartPosition);
+        SGQuatd geodOrientation = inverse(SGQuatd::fromLonLat(_geodPosition))*_cartOrientation;
+        geodOrientation.getEulerRad(_geodEulerRad[2], _geodEulerRad[1], _geodEulerRad[0]);
+        SGVec3d nedVel = geodOrientation.backTransform(_cartBodyVelocity);
+        if (SGLimitsd::min() < SGMiscd::max(fabs(nedVel[0]), fabs(nedVel[1])))
+            _groundTrackRad = atan2(nedVel[1], nedVel[0]);
+        else
+            _groundTrackRad = 0;
+        _groundSpeedMPerSec = sqrt(nedVel[0]*nedVel[0] + nedVel[1]*nedVel[1]);
+        _verticalSpeedMPerSec = -nedVel[2];
+        _dirty = false;
+    }
+    void updateCartesianFromGeodetic() const
+    {
+        if (!_dirty)
+            return;
+        _cartPosition = SGVec3d::fromGeod(_geodPosition);
+        SGQuatd geodOrientation = SGQuatd::fromEulerRad(_geodEulerRad[2], _geodEulerRad[1], _geodEulerRad[0]);
+        _cartOrientation = SGQuatd::fromLonLat(_geodPosition)*geodOrientation;
+        SGVec3d nedVel(cos(_groundTrackRad)*_groundSpeedMPerSec,
+                       sin(_groundTrackRad)*_groundSpeedMPerSec,
+                       -_verticalSpeedMPerSec);
+        _cartBodyVelocity = geodOrientation.transform(nedVel);
+        _dirty = false;
+    }
+
+    mutable bool _dirty;
+
+    // the cartesian values
+    mutable SGVec3d _cartPosition;
+    mutable SGQuatd _cartOrientation;
+    mutable SGVec3d _cartBodyVelocity;
+
+    // The geodetic values
+    mutable SGGeod _geodPosition;
+    mutable SGVec3d _geodEulerRad;
+    mutable double _groundTrackRad;
+    mutable double _groundSpeedMPerSec;
+    mutable double _verticalSpeedMPerSec;
+};
+
+class HLAGeodeticLocationFactory : public HLALocationFactory {
+public:
+    enum Semantic {
+        LatitudeDeg,
+        LatitudeRad,
+        LongitudeDeg,
+        LongitudeRad,
+        ElevationM,
+        ElevationFt,
+        HeadingDeg,
+        HeadingRad,
+        PitchDeg,
+        PitchRad,
+        RollDeg,
+        RollRad,
+        GroundTrackDeg,
+        GroundTrackRad,
+        GroundSpeedKnots,
+        GroundSpeedFtPerSec,
+        GroundSpeedMPerSec,
+        VerticalSpeedFtPerSec,
+        VerticalSpeedFtPerMin,
+        VerticalSpeedMPerSec
+    };
+
+    virtual HLAGeodeticLocation* createLocation(HLAAttributePathElementMap& attributePathElementMap) const
+    {
+        HLAGeodeticLocation* location = new HLAGeodeticLocation;
+
+        for (IndexPathPairSemanticMap::const_iterator i = _indexPathPairSemanticMap.begin();
+             i != _indexPathPairSemanticMap.end(); ++i) {
+            switch (i->second) {
+            case LatitudeDeg:
+                attributePathElementMap[i->first.first][i->first.second] = location->getLatitudeDegDataElement();
+                break;
+            case LatitudeRad:
+                attributePathElementMap[i->first.first][i->first.second] = location->getLatitudeRadDataElement();
+                break;
+            case LongitudeDeg:
+                attributePathElementMap[i->first.first][i->first.second] = location->getLongitudeDegDataElement();
+                break;
+            case LongitudeRad:
+                attributePathElementMap[i->first.first][i->first.second] = location->getLongitudeRadDataElement();
+                break;
+            case ElevationM:
+                attributePathElementMap[i->first.first][i->first.second] = location->getElevationMDataElement();
+                break;
+            case ElevationFt:
+                attributePathElementMap[i->first.first][i->first.second] = location->getElevationFtDataElement();
+                break;
+            case HeadingDeg:
+                attributePathElementMap[i->first.first][i->first.second] = location->getHeadingDegDataElement();
+                break;
+            case HeadingRad:
+                attributePathElementMap[i->first.first][i->first.second] = location->getHeadingRadDataElement();
+                break;
+            case PitchDeg:
+                attributePathElementMap[i->first.first][i->first.second] = location->getPitchDegDataElement();
+                break;
+            case PitchRad:
+                attributePathElementMap[i->first.first][i->first.second] = location->getPitchRadDataElement();
+                break;
+            case RollDeg:
+                attributePathElementMap[i->first.first][i->first.second] = location->getRollDegDataElement();
+                break;
+            case RollRad:
+                attributePathElementMap[i->first.first][i->first.second] = location->getRollRadDataElement();
+                break;
+            case GroundTrackDeg:
+                attributePathElementMap[i->first.first][i->first.second] = location->getGroundTrackDegDataElement();
+                break;
+            case GroundTrackRad:
+                attributePathElementMap[i->first.first][i->first.second] = location->getGroundTrackRadDataElement();
+                break;
+            case GroundSpeedKnots:
+                attributePathElementMap[i->first.first][i->first.second] = location->getGroundSpeedKnotsDataElement();
+                break;
+            case GroundSpeedFtPerSec:
+                attributePathElementMap[i->first.first][i->first.second] = location->getGroundSpeedFtPerSecDataElement();
+                break;
+            case GroundSpeedMPerSec:
+                attributePathElementMap[i->first.first][i->first.second] = location->getGroundSpeedMPerSecDataElement();
+                break;
+            case VerticalSpeedFtPerSec:
+                attributePathElementMap[i->first.first][i->first.second] = location->getVerticalSpeedFtPerSecDataElement();
+                break;
+            case VerticalSpeedFtPerMin:
+                attributePathElementMap[i->first.first][i->first.second] = location->getVerticalSpeedFtPerMinDataElement();
+                break;
+            case VerticalSpeedMPerSec:
+                attributePathElementMap[i->first.first][i->first.second] = location->getVerticalSpeedMPerSecDataElement();
+                break;
+            }
+        }
+
+        return location;
+    }
+
+    void setIndexPathPair(Semantic semantic, const HLADataElement::IndexPathPair& indexPathPair)
+    { _indexPathPairSemanticMap[indexPathPair] = semantic; }
+
+private:
+    typedef std::map<HLADataElement::IndexPathPair, Semantic> IndexPathPairSemanticMap;
+    IndexPathPairSemanticMap _indexPathPairSemanticMap;
+};
+
+} // namespace simgear
+
+#endif
diff --git a/simgear/hla/HLAOMTXmlVisitor.cxx b/simgear/hla/HLAOMTXmlVisitor.cxx
new file mode 100644 (file)
index 0000000..06351d6
--- /dev/null
@@ -0,0 +1,865 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "HLAOMTXmlVisitor.hxx"
+
+#include <map>
+#include <string>
+#include <sstream>
+
+#include <simgear/structure/exception.hxx>
+#include <simgear/xml/easyxml.hxx>
+#include "HLAArrayDataType.hxx"
+#include "HLABasicDataType.hxx"
+#include "HLADataTypeVisitor.hxx"
+#include "HLAEnumeratedDataType.hxx"
+#include "HLAFixedRecordDataType.hxx"
+#include "HLAVariantDataType.hxx"
+
+namespace simgear {
+
+HLAOMTXmlVisitor::ObjectClass::ObjectClass(const std::string& name, const std::string& sharing) :
+    _name(name),
+    _sharing(sharing)
+{
+}
+
+HLAOMTXmlVisitor::ObjectClass::~ObjectClass()
+{
+}
+
+const std::string&
+HLAOMTXmlVisitor::ObjectClass::getName() const
+{
+    return _name;
+}
+
+const std::string&
+HLAOMTXmlVisitor::ObjectClass::getSharing() const
+{
+    return _sharing;
+}
+
+unsigned
+HLAOMTXmlVisitor::ObjectClass::getNumAttributes() const
+{
+    return _attributes.size();
+}
+
+const HLAOMTXmlVisitor::Attribute*
+HLAOMTXmlVisitor::ObjectClass::getAttribute(unsigned index) const
+{
+    if (_attributes.size() <= index)
+        return 0;
+    return _attributes[index];
+}
+
+const HLAOMTXmlVisitor::Attribute*
+HLAOMTXmlVisitor::ObjectClass::getAttribute(const std::string& name) const
+{
+    for (AttributeList::const_iterator i = _attributes.begin(); i != _attributes.end(); ++i) {
+        if ((*i)->_name != name)
+            continue;
+        return i->get();
+    }
+    SG_LOG(SG_IO, SG_ALERT, "Could not find class attribute \"" << name << "\".");
+    return 0;
+}
+
+const HLAOMTXmlVisitor::ObjectClass*
+HLAOMTXmlVisitor::ObjectClass::getParentObjectClass() const
+{
+    return _parentObjectClass.get();
+}
+
+HLAOMTXmlVisitor::InteractionClass::InteractionClass(const std::string& name) :
+    _name(name)
+{
+}
+
+HLAOMTXmlVisitor::InteractionClass::~InteractionClass()
+{
+}
+
+const std::string&
+HLAOMTXmlVisitor::InteractionClass::getName() const
+{
+    return _name;
+}
+
+const std::string&
+HLAOMTXmlVisitor::InteractionClass::getDimensions() const
+{
+    return _dimensions;
+}
+
+const std::string&
+HLAOMTXmlVisitor::InteractionClass::getTransportation() const
+{
+    return _transportation;
+}
+
+const std::string&
+HLAOMTXmlVisitor::InteractionClass::getOrder() const
+{
+    return _order;
+}
+
+unsigned
+HLAOMTXmlVisitor::InteractionClass::getNumParameters() const
+{
+    return _parameters.size();
+}
+
+const HLAOMTXmlVisitor::Parameter*
+HLAOMTXmlVisitor::InteractionClass::getParameter(unsigned index) const
+{
+    if (_parameters.size() <= index)
+        return 0;
+    return _parameters[index];
+}
+
+const HLAOMTXmlVisitor::Parameter*
+HLAOMTXmlVisitor::InteractionClass::getParameter(const std::string& name) const
+{
+    for (ParameterList::const_iterator i = _parameters.begin(); i != _parameters.end(); ++i) {
+        if ((*i)->_name != name)
+            continue;
+        return i->get();
+    }
+    SG_LOG(SG_IO, SG_ALERT, "Could not find parameter \"" << name << "\".");
+    return 0;
+}
+
+const HLAOMTXmlVisitor::InteractionClass*
+HLAOMTXmlVisitor::InteractionClass::getParentInteractionClass() const
+{
+    return _parentInteractionClass.get();
+}
+
+HLAOMTXmlVisitor::HLAOMTXmlVisitor()
+{
+}
+
+HLAOMTXmlVisitor::~HLAOMTXmlVisitor()
+{
+}
+
+unsigned
+HLAOMTXmlVisitor::getNumObjectClasses() const
+{
+    return _objectClassList.size();
+}
+
+const HLAOMTXmlVisitor::ObjectClass*
+HLAOMTXmlVisitor::getObjectClass(unsigned i) const
+{
+    if (_objectClassList.size() <= i)
+        return 0;
+    return _objectClassList[i];
+}
+
+const HLAOMTXmlVisitor::ObjectClass*
+HLAOMTXmlVisitor::getObjectClass(const std::string& name) const
+{
+    for (ObjectClassList::const_iterator i = _objectClassList.begin(); i != _objectClassList.end(); ++i) {
+        if ((*i)->_name != name)
+            continue;
+        return i->get();
+    }
+    SG_LOG(SG_IO, SG_ALERT, "Could not resolve ObjectClass \"" << name << "\".");
+    return 0;
+}
+
+const HLAOMTXmlVisitor::Attribute*
+HLAOMTXmlVisitor::getAttribute(const std::string& objectClassName, const std::string& attributeName) const
+{
+    const ObjectClass* objectClass = getObjectClass(objectClassName);
+    if (!objectClass)
+        return 0;
+    return objectClass->getAttribute(attributeName);
+}
+
+HLADataType*
+HLAOMTXmlVisitor::getAttributeDataType(const std::string& objectClassName, const std::string& attributeName) const
+{
+    const Attribute* attribute = getAttribute(objectClassName, attributeName);
+    if (!attribute)
+        return 0;
+    return getDataType(attribute->_dataType);
+}
+
+unsigned
+HLAOMTXmlVisitor::getNumInteractionClasses() const
+{
+    return _interactionClassList.size();
+}
+
+const HLAOMTXmlVisitor::InteractionClass*
+HLAOMTXmlVisitor::getInteractionClass(unsigned i) const
+{
+    if (_interactionClassList.size() <= i)
+        return 0;
+    return _interactionClassList[i];
+}
+
+const HLAOMTXmlVisitor::InteractionClass*
+HLAOMTXmlVisitor::getInteractionClass(const std::string& name) const
+{
+    for (InteractionClassList::const_iterator i = _interactionClassList.begin(); i != _interactionClassList.end(); ++i) {
+        if ((*i)->_name != name)
+            continue;
+        return i->get();
+    }
+    SG_LOG(SG_IO, SG_ALERT, "Could not resolve InteractionClass \"" << name << "\".");
+    return 0;
+}
+
+const HLAOMTXmlVisitor::Parameter*
+HLAOMTXmlVisitor::getParameter(const std::string& interactionClassName, const std::string& parameterName) const
+{
+    const InteractionClass* interactionClass = getInteractionClass(interactionClassName);
+    if (!interactionClass)
+        return 0;
+    return interactionClass->getParameter(parameterName);
+}
+
+HLADataType*
+HLAOMTXmlVisitor::getParameterDataType(const std::string& interactionClassName, const std::string& parameterName) const
+{
+    const Parameter* parameter = getParameter(interactionClassName, parameterName);
+    if (!parameter)
+        return 0;
+    return getDataType(parameter->_dataType);
+}
+
+HLADataType*
+HLAOMTXmlVisitor::getDataType(const std::string& dataTypeName) const
+{
+    SGSharedPtr<HLADataType> dataType;
+    {
+        // Playing dirty things with reference counts
+        StringDataTypeMap dataTypeMap;
+        dataType = getDataType(dataTypeName, dataTypeMap);
+    }
+    return dataType.release();
+}
+
+SGSharedPtr<HLADataType>
+HLAOMTXmlVisitor::getDataType(const std::string& dataTypeName, HLAOMTXmlVisitor::StringDataTypeMap& dataTypeMap) const
+{
+    StringDataTypeMap::const_iterator i = dataTypeMap.find(dataTypeName);
+    if (i != dataTypeMap.end())
+        return new HLADataTypeReference(i->second);
+
+    SGSharedPtr<HLADataType> dataType;
+    dataType = getBasicDataType(dataTypeName);
+    if (dataType.valid())
+        return dataType;
+
+    dataType = getSimpleDataType(dataTypeName);
+    if (dataType.valid())
+        return dataType;
+
+    dataType = getEnumeratedDataType(dataTypeName);
+    if (dataType.valid())
+        return dataType;
+
+    dataType = getArrayDataType(dataTypeName, dataTypeMap);
+    if (dataType.valid())
+        return dataType;
+
+    dataType = getFixedRecordDataType(dataTypeName, dataTypeMap);
+    if (dataType.valid())
+        return dataType;
+
+    dataType = getVariantDataType(dataTypeName, dataTypeMap);
+    if (dataType.valid())
+        return dataType;
+
+    SG_LOG(SG_IO, SG_WARN, "Could not resolve dataType \"" << dataTypeName << "\".");
+    return 0;
+}
+
+SGSharedPtr<HLABasicDataType>
+HLAOMTXmlVisitor::getBasicDataType(const std::string& dataTypeName) const
+{
+    BasicDataMap::const_iterator i = _basicDataMap.find(dataTypeName);
+    if (i == _basicDataMap.end())
+        return 0;
+    if (i->second._size == "8") {
+        return new HLAUInt8DataType(dataTypeName);
+    } else if (i->second._size == "16") {
+        if (i->first.find("Unsigned") != std::string::npos) {
+            if (i->second._endian == "Little") {
+                return new HLAUInt16LEDataType(dataTypeName);
+            } else {
+                return new HLAUInt16BEDataType(dataTypeName);
+            }
+        } else if (i->first.find("octetPair") != std::string::npos) {
+            if (i->second._endian == "Little") {
+                return new HLAUInt16LEDataType(dataTypeName);
+            } else {
+                return new HLAUInt16BEDataType(dataTypeName);
+            }
+        } else {
+            if (i->second._endian == "Little") {
+                return new HLAInt16LEDataType(dataTypeName);
+            } else {
+                return new HLAInt16BEDataType(dataTypeName);
+            }
+        }
+    } else if (i->second._size == "32") {
+        if (i->first.find("Unsigned") != std::string::npos) {
+            if (i->second._endian == "Little") {
+                return new HLAUInt32LEDataType(dataTypeName);
+            } else {
+                return new HLAUInt32BEDataType(dataTypeName);
+            }
+        } else if (i->first.find("float") != std::string::npos) {
+            if (i->second._endian == "Little") {
+                return new HLAFloat32LEDataType(dataTypeName);
+            } else {
+                return new HLAFloat32BEDataType(dataTypeName);
+            }
+        } else {
+            if (i->second._endian == "Little") {
+                return new HLAInt32LEDataType(dataTypeName);
+            } else {
+                return new HLAInt32BEDataType(dataTypeName);
+            }
+        }
+    } else if (i->second._size == "64") {
+        if (i->first.find("Unsigned") != std::string::npos) {
+            if (i->second._endian == "Little") {
+                return new HLAUInt64LEDataType(dataTypeName);
+            } else {
+                return new HLAUInt64BEDataType(dataTypeName);
+            }
+        } else if (i->first.find("float") != std::string::npos) {
+            if (i->second._endian == "Little") {
+                return new HLAFloat64LEDataType(dataTypeName);
+            } else {
+                return new HLAFloat64BEDataType(dataTypeName);
+            }
+        } else {
+            if (i->second._endian == "Little") {
+                return new HLAInt64LEDataType(dataTypeName);
+            } else {
+                return new HLAInt64BEDataType(dataTypeName);
+            }
+        }
+    }
+
+    return 0;
+}
+
+SGSharedPtr<HLADataType>
+HLAOMTXmlVisitor::getSimpleDataType(const std::string& dataTypeName) const
+{
+    SimpleDataMap::const_iterator i = _simpleDataMap.find(dataTypeName);
+    if (i == _simpleDataMap.end())
+        return 0;
+    return getDataType(i->second._representation);
+}
+
+SGSharedPtr<HLAEnumeratedDataType>
+HLAOMTXmlVisitor::getEnumeratedDataType(const std::string& dataTypeName) const
+{
+    EnumeratedDataMap::const_iterator i = _enumeratedDataMap.find(dataTypeName);
+    if (i == _enumeratedDataMap.end())
+        return 0;
+
+    SGSharedPtr<HLAEnumeratedDataType> enumeratedDataType = new HLAEnumeratedDataType(dataTypeName);
+    enumeratedDataType->setRepresentation(getBasicDataType(i->second._representation));
+
+    for (EnumeratorList::const_iterator j = i->second._enumeratorList.begin();
+         j != i->second._enumeratorList.end(); ++j) {
+        if (!enumeratedDataType->addEnumerator(j->_name, j->_values)) {
+            SG_LOG(SG_IO, SG_ALERT, "Could not add enumerator \"" << j->_name
+                   << "\" to find enumerated data type \"" << dataTypeName << "\".");
+            return 0;
+        }
+    }
+
+    return enumeratedDataType;
+}
+
+SGSharedPtr<HLADataType>
+HLAOMTXmlVisitor::getArrayDataType(const std::string& dataTypeName, HLAOMTXmlVisitor::StringDataTypeMap& dataTypeMap) const
+{
+    ArrayDataMap::const_iterator i = _arrayDataMap.find(dataTypeName);
+    if (i == _arrayDataMap.end())
+        return 0;
+    SGSharedPtr<HLAArrayDataType> arrayDataType;
+    if (i->second._encoding == "HLAvariableArray") {
+        arrayDataType = new HLAVariableArrayDataType(dataTypeName);
+    } else if (i->second._encoding == "HLAfixedArray") {
+        std::stringstream ss(i->second._cardinality);
+        unsigned cardinality;
+        ss >> cardinality;
+        if (ss.fail()) {
+            SG_LOG(SG_IO, SG_ALERT, "Could not interpret cardinality \""
+                   << i->second._cardinality << "\" for dataType \""
+                   << dataTypeName << "\".");
+            return 0;
+        }
+        SGSharedPtr<HLAFixedArrayDataType> dataType = new HLAFixedArrayDataType(dataTypeName);
+        dataType->setNumElements(cardinality);
+        arrayDataType = dataType;
+    } else {
+        SG_LOG(SG_IO, SG_ALERT, "Can not interpret encoding \""
+               << i->second._encoding << "\" for dataType \""
+               << dataTypeName << "\".");
+        return 0;
+    }
+
+    dataTypeMap[dataTypeName] = arrayDataType;
+    SGSharedPtr<HLADataType> elementDataType = getDataType(i->second._dataType, dataTypeMap);
+    if (!elementDataType.valid()) {
+        SG_LOG(SG_IO, SG_ALERT, "Could not interpret dataType \""
+               << i->second._dataType << "\" for array data type \""
+               << dataTypeName << "\".");
+        dataTypeMap.erase(dataTypeName);
+        return 0;
+    }
+    arrayDataType->setElementDataType(elementDataType.get());
+
+    return arrayDataType;
+}
+
+SGSharedPtr<HLAFixedRecordDataType>
+HLAOMTXmlVisitor::getFixedRecordDataType(const std::string& dataTypeName, HLAOMTXmlVisitor::StringDataTypeMap& dataTypeMap) const
+{
+    FixedRecordDataMap::const_iterator i = _fixedRecordDataMap.find(dataTypeName);
+    if (i == _fixedRecordDataMap.end())
+        return 0;
+
+    SGSharedPtr<HLAFixedRecordDataType> dataType = new HLAFixedRecordDataType(dataTypeName);
+    dataTypeMap[dataTypeName] = dataType;
+    for (FieldList::size_type j = 0; j < i->second._fieldList.size(); ++j) {
+        SGSharedPtr<HLADataType> fieldDataType = getDataType(i->second._fieldList[j]._dataType, dataTypeMap);
+        if (!fieldDataType.valid()) {
+            SG_LOG(SG_IO, SG_ALERT, "Could not get data type \"" << i->second._fieldList[j]._dataType
+                   << "\" for field " << j << "of fixed record data type \"" << dataTypeName << "\".");
+            dataTypeMap.erase(dataTypeName);
+            return 0;
+        }
+        dataType->addField(i->second._fieldList[j]._name, fieldDataType.get());
+    }
+    return dataType;
+}
+
+SGSharedPtr<HLAVariantDataType>
+HLAOMTXmlVisitor::getVariantDataType(const std::string& dataTypeName, HLAOMTXmlVisitor::StringDataTypeMap& dataTypeMap) const
+{
+    VariantRecordDataMap::const_iterator i = _variantRecordDataMap.find(dataTypeName);
+    if (i == _variantRecordDataMap.end())
+        return 0;
+    SGSharedPtr<HLAVariantDataType> dataType = new HLAVariantDataType(dataTypeName);
+    dataTypeMap[dataTypeName] = dataType;
+
+    SGSharedPtr<HLAEnumeratedDataType> enumeratedDataType = getEnumeratedDataType(i->second._dataType);
+    if (!enumeratedDataType.valid()) {
+        SG_LOG(SG_IO, SG_ALERT, "Could not find enumerted data type \"" << i->second._dataType
+               << "\" for variant data type \"" << dataTypeName << "\".");
+        return 0;
+    }
+    dataType->setEnumeratedDataType(enumeratedDataType);
+
+    for (AlternativeList::const_iterator j = i->second._alternativeList.begin();
+         j != i->second._alternativeList.end(); ++j) {
+        SGSharedPtr<HLADataType> alternativeDataType = getDataType(j->_dataType, dataTypeMap);
+        if (!alternativeDataType.valid()) {
+            SG_LOG(SG_IO, SG_ALERT, "Could not resolve alternative dataType \"" << j->_dataType
+                   << "\" for alternative \"" << j->_name << "\".");
+            dataTypeMap.erase(dataTypeName);
+            return 0;
+        }
+        if (!dataType->addAlternative(j->_name, j->_enumerator, alternativeDataType.get(), j->_semantics)) {
+            SG_LOG(SG_IO, SG_ALERT, "Could not add alternative \"" << j->_name << "\".");
+            return 0;
+        }
+    }
+    return dataType;
+}
+
+HLAOMTXmlVisitor::Mode
+HLAOMTXmlVisitor::getCurrentMode()
+{
+    if (_modeStack.empty())
+        return UnknownMode;
+    return _modeStack.back();
+}
+
+void
+HLAOMTXmlVisitor::pushMode(HLAOMTXmlVisitor::Mode mode)
+{
+    _modeStack.push_back(mode);
+}
+
+void
+HLAOMTXmlVisitor::popMode()
+{
+    _modeStack.pop_back();
+}
+
+void
+HLAOMTXmlVisitor::startXML()
+{
+    _modeStack.clear();
+}
+
+void
+HLAOMTXmlVisitor::endXML()
+{
+    if (!_modeStack.empty())
+        throw sg_exception("Internal parse error!");
+
+    // propagate parent attributes to the derived classes
+    for (ObjectClassList::const_iterator i = _objectClassList.begin(); i != _objectClassList.end(); ++i) {
+        SGSharedPtr<const ObjectClass> objectClass = (*i)->_parentObjectClass;
+        while (objectClass) {
+            for (AttributeList::const_reverse_iterator j = objectClass->_attributes.rbegin();
+                 j != objectClass->_attributes.rend(); ++j) {
+                (*i)->_attributes.insert((*i)->_attributes.begin(), *j);
+            }
+            objectClass = objectClass->_parentObjectClass;
+        }
+    }
+
+    // propagate parent parameter to the derived interactions
+    for (InteractionClassList::const_iterator i = _interactionClassList.begin(); i != _interactionClassList.end(); ++i) {
+        SGSharedPtr<const InteractionClass> interactionClass = (*i)->_parentInteractionClass;
+        while (interactionClass) {
+            for (ParameterList::const_reverse_iterator j = interactionClass->_parameters.rbegin();
+                 j != interactionClass->_parameters.rend(); ++j) {
+                (*i)->_parameters.insert((*i)->_parameters.begin(), *j);
+            }
+            interactionClass = interactionClass->_parentInteractionClass;
+        }
+    }
+}
+
+void
+HLAOMTXmlVisitor::startElement(const char* name, const XMLAttributes& atts)
+{
+    if (strcmp(name, "attribute") == 0) {
+        if (getCurrentMode() != ObjectClassMode)
+            throw sg_exception("attribute tag outside objectClass!");
+        pushMode(AttributeMode);
+
+        if (_objectClassList.empty())
+            throw sg_exception("attribute tag outside of an objectClass");
+
+        std::string name = getAttribute("name", atts);
+        if (name.empty())
+            throw sg_exception("attribute tag without name attribute");
+
+        SGSharedPtr<Attribute> attribute = new Attribute(name);
+
+        attribute->_dataType = getAttribute("dataType", atts);
+        attribute->_updateType = getAttribute("updateType", atts);
+        attribute->_updateCondition = getAttribute("updateCondition", atts);
+        attribute->_ownership = getAttribute("ownership", atts);
+        attribute->_sharing = getAttribute("sharing", atts);
+        attribute->_dimensions = getAttribute("dimensions", atts);
+        attribute->_transportation = getAttribute("transportation", atts);
+        attribute->_order = getAttribute("order", atts);
+
+        _objectClassStack.back()->_attributes.push_back(attribute);
+
+    } else if (strcmp(name, "objectClass") == 0) {
+        if (getCurrentMode() != ObjectsMode && getCurrentMode() != ObjectClassMode)
+            throw sg_exception("objectClass tag outside objectClass or objects!");
+        pushMode(ObjectClassMode);
+
+        std::string name = getAttribute("name", atts);
+        if (name.empty())
+            throw sg_exception("objectClass tag without name attribute");
+
+        std::string sharing = getAttribute("sharing", atts);
+
+        // The new ObjectClass
+        ObjectClass* objectClass = new ObjectClass(name, sharing);
+
+        // Inherit all previous attributes
+        if (!_objectClassStack.empty())
+            objectClass->_parentObjectClass = _objectClassStack.back();
+
+        _objectClassStack.push_back(objectClass);
+        _objectClassList.push_back(objectClass);
+
+    } else if (strcmp(name, "objects") == 0) {
+        if (getCurrentMode() != ObjectModelMode)
+            throw sg_exception("objects tag outside objectModel!");
+        pushMode(ObjectsMode);
+
+    } else if (strcmp(name, "parameter") == 0) {
+        if (getCurrentMode() != InteractionClassMode)
+            throw sg_exception("parameter tag outside interactionClass!");
+        pushMode(ParameterMode);
+
+        if (_interactionClassList.empty())
+            throw sg_exception("parameter tag outside of an interactionClass");
+
+        std::string name = getAttribute("name", atts);
+        if (name.empty())
+            throw sg_exception("parameter tag without name parameter");
+
+        SGSharedPtr<Parameter> parameter = new Parameter(name);
+        parameter->_dataType = getAttribute("dataType", atts);
+
+        _interactionClassStack.back()->_parameters.push_back(parameter);
+
+    } else if (strcmp(name, "interactionClass") == 0) {
+        if (getCurrentMode() != InteractionsMode && getCurrentMode() != InteractionClassMode)
+            throw sg_exception("interactionClass tag outside interactions or interactionClass!");
+        pushMode(InteractionClassMode);
+
+        std::string name = getAttribute("name", atts);
+        if (name.empty())
+            throw sg_exception("interactionClass tag without name attribute");
+
+        // The new ObjectClass
+        InteractionClass* interactionClass = new InteractionClass(name);
+        interactionClass->_dimensions = getAttribute("dimensions", atts);
+        interactionClass->_transportation = getAttribute("transportation", atts);
+        interactionClass->_order = getAttribute("order", atts);
+
+        // Inherit all previous attributes
+        if (!_interactionClassStack.empty())
+            interactionClass->_parentInteractionClass = _interactionClassStack.back();
+
+        _interactionClassStack.push_back(interactionClass);
+        _interactionClassList.push_back(interactionClass);
+
+    } else if (strcmp(name, "interactions") == 0) {
+        if (getCurrentMode() != ObjectModelMode)
+            throw sg_exception("interactions tag outside objectModel!");
+        pushMode(InteractionsMode);
+
+    } else if (strcmp(name, "basicData") == 0) {
+        if (getCurrentMode() != BasicDataRepresentationsMode)
+            throw sg_exception("basicData tag outside basicDataRepresentations!");
+        pushMode(BasicDataMode);
+
+        std::string name = getAttribute("name", atts);
+        if (name.empty())
+            throw sg_exception("basicData tag without name attribute");
+
+        _basicDataMap[name]._size = getAttribute("size", atts);
+        _basicDataMap[name]._endian = getAttribute("endian", atts);
+
+    } else if (strcmp(name, "basicDataRepresentations") == 0) {
+        if (getCurrentMode() != DataTypesMode)
+            throw sg_exception("basicDataRepresentations tag outside dataTypes!");
+        pushMode(BasicDataRepresentationsMode);
+
+    } else if (strcmp(name, "simpleData") == 0) {
+        if (getCurrentMode() != SimpleDataTypesMode)
+            throw sg_exception("simpleData tag outside simpleDataTypes!");
+        pushMode(SimpleDataMode);
+
+        std::string name = getAttribute("name", atts);
+        if (name.empty())
+            throw sg_exception("simpleData tag without name attribute");
+
+        _simpleDataMap[name]._representation = getAttribute("representation", atts);
+        _simpleDataMap[name]._units = getAttribute("units", atts);
+        _simpleDataMap[name]._resolution = getAttribute("resolution", atts);
+        _simpleDataMap[name]._accuracy = getAttribute("accuracy", atts);
+
+    } else if (strcmp(name, "simpleDataTypes") == 0) {
+        if (getCurrentMode() != DataTypesMode)
+            throw sg_exception("simpleDataTypes tag outside dataTypes!");
+        pushMode(SimpleDataTypesMode);
+
+    } else if (strcmp(name, "enumerator") == 0) {
+        if (getCurrentMode() != EnumeratedDataMode)
+            throw sg_exception("enumerator tag outside enumeratedData!");
+        pushMode(EnumeratorMode);
+
+        std::string name = getAttribute("name", atts);
+        if (name.empty())
+            throw sg_exception("enumerator tag without name attribute");
+
+        Enumerator enumerator;
+        enumerator._name = name;
+        enumerator._values = getAttribute("values", atts);
+        _enumeratedDataMap[_enumeratedDataName]._enumeratorList.push_back(enumerator);
+
+    } else if (strcmp(name, "enumeratedData") == 0) {
+        if (getCurrentMode() != EnumeratedDataTypesMode)
+            throw sg_exception("enumeratedData tag outside enumeratedDataTypes!");
+        pushMode(EnumeratedDataMode);
+
+        std::string name = getAttribute("name", atts);
+        if (name.empty())
+            throw sg_exception("enumeratedData tag without name attribute");
+
+        _enumeratedDataName = name;
+        _enumeratedDataMap[_enumeratedDataName]._representation = getAttribute("representation", atts);
+
+    } else if (strcmp(name, "enumeratedDataTypes") == 0) {
+        if (getCurrentMode() != DataTypesMode)
+            throw sg_exception("enumeratedDataTypes tag outside dataTypes!");
+        pushMode(EnumeratedDataTypesMode);
+
+        Enumerator enumerator;
+        enumerator._name = getAttribute("name", atts);
+        enumerator._values = getAttribute("values", atts);
+        _enumeratedDataMap[_enumeratedDataName]._enumeratorList.push_back(enumerator);
+
+    } else if (strcmp(name, "arrayData") == 0) {
+        if (getCurrentMode() != ArrayDataTypesMode)
+            throw sg_exception("arrayData tag outside arrayDataTypes!");
+        pushMode(ArrayDataMode);
+
+        std::string name = getAttribute("name", atts);
+        if (name.empty())
+            throw sg_exception("arrayData tag without name attribute");
+
+        _arrayDataMap[name]._dataType = getAttribute("dataType", atts);
+        _arrayDataMap[name]._cardinality = getAttribute("cardinality", atts);
+        _arrayDataMap[name]._encoding = getAttribute("encoding", atts);
+
+    } else if (strcmp(name, "arrayDataTypes") == 0) {
+        if (getCurrentMode() != DataTypesMode)
+            throw sg_exception("arrayDataTypes tag outside dataTypes!");
+        pushMode(ArrayDataTypesMode);
+
+    } else if (strcmp(name, "field") == 0) {
+        if (getCurrentMode() != FixedRecordDataMode)
+            throw sg_exception("field tag outside fixedRecordData!");
+        pushMode(FieldMode);
+
+        std::string name = getAttribute("name", atts);
+        if (name.empty())
+            throw sg_exception("field tag without name attribute");
+
+        Field field;
+        field._name = name;
+        field._dataType = getAttribute("dataType", atts);
+        _fixedRecordDataMap[_fixedRecordDataName]._fieldList.push_back(field);
+
+    } else if (strcmp(name, "fixedRecordData") == 0) {
+        if (getCurrentMode() != FixedRecordDataTypesMode)
+            throw sg_exception("fixedRecordData tag outside fixedRecordDataTypes!");
+        pushMode(FixedRecordDataMode);
+
+        std::string name = getAttribute("name", atts);
+        if (name.empty())
+            throw sg_exception("fixedRecordData tag without name attribute");
+
+        _fixedRecordDataName = name;
+        _fixedRecordDataMap[name]._encoding = getAttribute("encoding", atts);
+
+    } else if (strcmp(name, "fixedRecordDataTypes") == 0) {
+        if (getCurrentMode() != DataTypesMode)
+            throw sg_exception("fixedRecordDataTypes tag outside dataTypes!");
+        pushMode(FixedRecordDataTypesMode);
+
+    } else if (strcmp(name, "alternative") == 0) {
+
+        if (getCurrentMode() != VariantRecordDataMode)
+            throw sg_exception("alternative tag outside variantRecordData!");
+        pushMode(AlternativeDataMode);
+
+        std::string name = getAttribute("name", atts);
+        if (name.empty())
+            throw sg_exception("alternative tag without name attribute");
+
+        Alternative alternative;
+        alternative._name = name;
+        alternative._dataType = getAttribute("dataType", atts);
+        alternative._semantics = getAttribute("semantics", atts);
+        alternative._enumerator = getAttribute("enumerator", atts);
+        _variantRecordDataMap[_variantRecordDataName]._alternativeList.push_back(alternative);
+
+    } else if (strcmp(name, "variantRecordData") == 0) {
+        if (getCurrentMode() != VariantRecordDataTypesMode)
+            throw sg_exception("variantRecordData tag outside variantRecordDataTypes!");
+        pushMode(VariantRecordDataMode);
+
+        std::string name = getAttribute("name", atts);
+        if (name.empty())
+            throw sg_exception("fixedRecordData tag without name attribute");
+
+        _variantRecordDataName = name;
+        _variantRecordDataMap[name]._encoding = getAttribute("encoding", atts);
+        _variantRecordDataMap[name]._dataType = getAttribute("dataType", atts);
+        _variantRecordDataMap[name]._semantics = getAttribute("semantics", atts);
+        _variantRecordDataMap[name]._discriminant = getAttribute("discriminant", atts);
+
+    } else if (strcmp(name, "variantRecordDataTypes") == 0) {
+        if (getCurrentMode() != DataTypesMode)
+            throw sg_exception("variantRecordDataTypes tag outside dataTypes!");
+        pushMode(VariantRecordDataTypesMode);
+
+    } else if (strcmp(name, "dataTypes") == 0) {
+        if (getCurrentMode() != ObjectModelMode)
+            throw sg_exception("dataTypes tag outside objectModel!");
+        pushMode(DataTypesMode);
+
+    } else if (strcmp(name, "objectModel") == 0) {
+        if (!_modeStack.empty())
+            throw sg_exception("objectModel tag not at top level!");
+        pushMode(ObjectModelMode);
+
+    } else {
+        _modeStack.push_back(UnknownMode);
+    }
+}
+
+void
+HLAOMTXmlVisitor::endElement(const char* name)
+{
+    if (strcmp(name, "objectClass") == 0) {
+        _objectClassStack.pop_back();
+    } else if (strcmp(name, "interactionClass") == 0) {
+        _interactionClassStack.pop_back();
+    } else if (strcmp(name, "enumeratedData") == 0) {
+        _enumeratedDataName.clear();
+    } else if (strcmp(name, "fixedRecordData") == 0) {
+        _fixedRecordDataName.clear();
+    } else if (strcmp(name, "variantRecordData") == 0) {
+        _variantRecordDataName.clear();
+    }
+
+    _modeStack.pop_back();
+}
+
+std::string
+HLAOMTXmlVisitor::getAttribute(const char* name, const XMLAttributes& atts)
+{
+    int index = atts.findAttribute(name);
+    if (index < 0 || atts.size() <= index)
+        return std::string();
+    return std::string(atts.getValue(index));
+}
+
+std::string
+HLAOMTXmlVisitor::getAttribute(const std::string& name, const XMLAttributes& atts)
+{
+    int index = atts.findAttribute(name.c_str());
+    if (index < 0 || atts.size() <= index)
+        return std::string();
+    return std::string(atts.getValue(index));
+}
+
+} // namespace simgear
diff --git a/simgear/hla/HLAOMTXmlVisitor.hxx b/simgear/hla/HLAOMTXmlVisitor.hxx
new file mode 100644 (file)
index 0000000..32a8cd6
--- /dev/null
@@ -0,0 +1,293 @@
+// Copyright (C) 2009 - 2010  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 HLAOMTXmlVisitor_hxx
+#define HLAOMTXmlVisitor_hxx
+
+#include <map>
+#include <string>
+
+#include <simgear/structure/exception.hxx>
+#include <simgear/structure/SGSharedPtr.hxx>
+#include <simgear/xml/easyxml.hxx>
+#include "HLADataType.hxx"
+
+namespace simgear {
+
+class HLAOMTXmlVisitor : public XMLVisitor {
+public:
+    /// structures representing the federate object model data
+    struct Attribute : public SGReferenced {
+        Attribute(const std::string& name) :
+            _name(name)
+        { }
+        const std::string& getName() const
+        { return _name; }
+        const std::string& getDimensions() const
+        { return _dimensions; }
+        const std::string& getTransportation() const
+        { return _transportation; }
+        const std::string& getOrder() const
+        { return _order; }
+
+        std::string _name;
+        std::string _dataType;
+        std::string _updateType;
+        std::string _updateCondition;
+        std::string _ownership;
+        std::string _sharing;
+        std::string _dimensions;
+        std::string _transportation;
+        std::string _order;
+        friend class HLAOMTXmlVisitor;
+    };
+    typedef std::vector<SGSharedPtr<Attribute> > AttributeList;
+
+    struct ObjectClass : public SGReferenced {
+        ObjectClass(const std::string& name, const std::string& sharing);
+        ~ObjectClass();
+
+        const std::string& getName() const;
+        const std::string& getSharing() const;
+
+        unsigned getNumAttributes() const;
+        const Attribute* getAttribute(unsigned index) const;
+        const Attribute* getAttribute(const std::string& name) const;
+
+        const ObjectClass* getParentObjectClass() const;
+
+    private:
+        friend class HLAOMTXmlVisitor;
+        std::string _name;
+        std::string _sharing;
+        AttributeList _attributes;
+        SGSharedPtr<ObjectClass> _parentObjectClass;
+    };
+    typedef std::vector<SGSharedPtr<ObjectClass> > ObjectClassList;
+
+    struct Parameter : public SGReferenced {
+        Parameter(const std::string& name) :
+            _name(name)
+        { }
+        const std::string& getName() const
+        { return _name; }
+        const std::string& getDataType() const
+        { return _dataType; }
+
+    private:
+        std::string _name;
+        std::string _dataType;
+        friend class HLAOMTXmlVisitor;
+    };
+    typedef std::vector<SGSharedPtr<Parameter> > ParameterList;
+
+    struct InteractionClass : public SGReferenced {
+        InteractionClass(const std::string& name);
+        ~InteractionClass();
+
+        const std::string& getName() const;
+        const std::string& getDimensions() const;
+        const std::string& getTransportation() const;
+        const std::string& getOrder() const;
+
+        unsigned getNumParameters() const;
+        const Parameter* getParameter(unsigned index) const;
+        const Parameter* getParameter(const std::string& name) const;
+
+        const InteractionClass* getParentInteractionClass() const;
+
+    private:
+        friend class HLAOMTXmlVisitor;
+        std::string _name;
+        std::string _dimensions;
+        std::string _transportation;
+        std::string _order;
+        ParameterList _parameters;
+        SGSharedPtr<InteractionClass> _parentInteractionClass;
+    };
+    typedef std::vector<SGSharedPtr<InteractionClass> > InteractionClassList;
+
+    HLAOMTXmlVisitor();
+    ~HLAOMTXmlVisitor();
+
+    unsigned getNumObjectClasses() const;
+    const ObjectClass* getObjectClass(unsigned i) const;
+    const ObjectClass* getObjectClass(const std::string& name) const;
+
+    /// Return the data type from the fom data
+    const Attribute* getAttribute(const std::string& objectClassName, const std::string& attributeName) const;
+    /// Return the data type from the fom data
+    HLADataType* getAttributeDataType(const std::string& objectClassName, const std::string& attributeName) const;
+
+    unsigned getNumInteractionClasses() const;
+    const InteractionClass* getInteractionClass(unsigned i) const;
+    const InteractionClass* getInteractionClass(const std::string& name) const;
+
+    /// Return the data type from the fom data
+    const Parameter* getParameter(const std::string& interactionClassName, const std::string& parameterName) const;
+
+    /// Return the data type from the fom data
+    HLADataType* getParameterDataType(const std::string& interactionClassName, const std::string& parameterName) const;
+
+    HLADataType* getDataType(const std::string& dataTypeName) const;
+
+private:
+    typedef std::map<std::string, SGSharedPtr<HLADataType> > StringDataTypeMap;
+    SGSharedPtr<HLADataType> getDataType(const std::string& dataTypeName, StringDataTypeMap& dataTypeMap) const;
+    SGSharedPtr<HLABasicDataType> getBasicDataType(const std::string& dataTypeName) const;
+    SGSharedPtr<HLADataType> getSimpleDataType(const std::string& dataTypeName) const;
+    SGSharedPtr<HLAEnumeratedDataType> getEnumeratedDataType(const std::string& dataTypeName) const;
+    SGSharedPtr<HLADataType> getArrayDataType(const std::string& dataTypeName, StringDataTypeMap& dataTypeMap) const;
+    SGSharedPtr<HLAFixedRecordDataType> getFixedRecordDataType(const std::string& dataTypeName, StringDataTypeMap& dataTypeMap) const;
+    SGSharedPtr<HLAVariantDataType> getVariantDataType(const std::string& dataTypeName, StringDataTypeMap& dataTypeMap) const;
+
+    enum Mode {
+        UnknownMode,
+
+        ObjectModelMode,
+
+        ObjectsMode,
+        ObjectClassMode,
+        AttributeMode,
+
+        InteractionsMode,
+        InteractionClassMode,
+        ParameterMode,
+
+        DataTypesMode,
+        BasicDataRepresentationsMode,
+        BasicDataMode,
+        SimpleDataTypesMode,
+        SimpleDataMode,
+        EnumeratedDataTypesMode,
+        EnumeratedDataMode,
+        EnumeratorMode,
+        ArrayDataTypesMode,
+        ArrayDataMode,
+        FixedRecordDataTypesMode,
+        FixedRecordDataMode,
+        FieldMode,
+        VariantRecordDataTypesMode,
+        VariantRecordDataMode,
+        AlternativeDataMode
+    };
+
+    Mode getCurrentMode();
+    void pushMode(Mode mode);
+    void popMode();
+
+    virtual void startXML();
+    virtual void endXML ();
+    virtual void startElement(const char* name, const XMLAttributes& atts);
+    virtual void endElement(const char* name);
+
+    std::string getAttribute(const char* name, const XMLAttributes& atts);
+    std::string getAttribute(const std::string& name, const XMLAttributes& atts);
+
+    struct BasicData {
+        // std::string _name;
+        std::string _size;
+        std::string _endian;
+    };
+    typedef std::map<std::string, BasicData> BasicDataMap;
+
+    struct SimpleData {
+        // std::string _name;
+        std::string _representation;
+        std::string _units;
+        std::string _resolution;
+        std::string _accuracy;
+    };
+    typedef std::map<std::string, SimpleData> SimpleDataMap;
+
+    struct Enumerator {
+        std::string _name;
+        std::string _values;
+    };
+    typedef std::vector<Enumerator> EnumeratorList;
+
+    struct EnumeratedData {
+        // std::string _name;
+        std::string _representation;
+        EnumeratorList _enumeratorList;
+    };
+    typedef std::map<std::string, EnumeratedData> EnumeratedDataMap;
+
+    struct ArrayData {
+        // std::string _name;
+        std::string _dataType;
+        std::string _cardinality;
+        std::string _encoding;
+    };
+    typedef std::map<std::string, ArrayData> ArrayDataMap;
+
+    struct Field {
+        std::string _name;
+        std::string _dataType;
+    };
+    typedef std::vector<Field> FieldList;
+
+    struct FixedRecordData {
+        // std::string _name;
+        std::string _encoding;
+        FieldList _fieldList;
+    };
+    typedef std::map<std::string, FixedRecordData> FixedRecordDataMap;
+
+    struct Alternative {
+        std::string _name;
+        std::string _dataType;
+        std::string _semantics;
+        std::string _enumerator;
+    };
+    typedef std::vector<Alternative> AlternativeList;
+
+    struct VariantRecordData {
+        // std::string _name;
+        std::string _encoding;
+        std::string _dataType;
+        std::string _discriminant;
+        std::string _semantics;
+        AlternativeList _alternativeList;
+    };
+    typedef std::map<std::string, VariantRecordData> VariantRecordDataMap;
+
+    std::vector<Mode> _modeStack;
+
+    /// The total list of object classes
+    ObjectClassList _objectClassList;
+    ObjectClassList _objectClassStack;
+
+    /// The total list of interaction classes
+    InteractionClassList _interactionClassList;
+    InteractionClassList _interactionClassStack;
+
+    /// DataType definitions
+    BasicDataMap _basicDataMap;
+    SimpleDataMap _simpleDataMap;
+    std::string _enumeratedDataName;
+    EnumeratedDataMap _enumeratedDataMap;
+    ArrayDataMap _arrayDataMap;
+    std::string _fixedRecordDataName;
+    FixedRecordDataMap _fixedRecordDataMap;
+    std::string _variantRecordDataName;
+    VariantRecordDataMap _variantRecordDataMap;
+};
+
+} // namespace simgear
+
+#endif
diff --git a/simgear/hla/HLAObjectClass.cxx b/simgear/hla/HLAObjectClass.cxx
new file mode 100644 (file)
index 0000000..4b82656
--- /dev/null
@@ -0,0 +1,302 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "HLAObjectClass.hxx"
+
+#include "RTIFederate.hxx"
+#include "RTIObjectClass.hxx"
+#include "RTIObjectInstance.hxx"
+#include "HLADataType.hxx"
+#include "HLAFederate.hxx"
+#include "HLAObjectInstance.hxx"
+
+namespace simgear {
+
+HLAObjectClass::InstanceCallback::~InstanceCallback()
+{
+}
+
+void
+HLAObjectClass::InstanceCallback::discoverInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance, const RTIData& tag)
+{
+}
+
+void
+HLAObjectClass::InstanceCallback::removeInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance, const RTIData& tag)
+{
+}
+
+void
+HLAObjectClass::InstanceCallback::registerInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance)
+{
+}
+
+void
+HLAObjectClass::InstanceCallback::deleteInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance)
+{
+}
+
+HLAObjectClass::RegistrationCallback::~RegistrationCallback()
+{
+}
+
+HLAObjectClass::HLAObjectClass(const std::string& name, HLAFederate& federate) :
+    _name(name)
+{
+    _rtiObjectClass = federate._rtiFederate->createObjectClass(name, this);
+    if (!_rtiObjectClass.valid())
+        SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::HLAObjectClass(): No RTIObjectClass found for \"" << name << "\"!");
+}
+
+HLAObjectClass::~HLAObjectClass()
+{
+}
+
+unsigned
+HLAObjectClass::getNumAttributes() const
+{
+    if (!_rtiObjectClass.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeIndex(): No RTIObject class for object class \"" << getName() << "\"!");
+        return 0;
+    }
+    return _rtiObjectClass->getNumAttributes();
+}
+
+unsigned
+HLAObjectClass::getAttributeIndex(const std::string& name) const
+{
+    if (!_rtiObjectClass.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeIndex(): No RTIObject class for object class \"" << getName() << "\"!");
+        return ~0u;
+    }
+    return _rtiObjectClass->getOrCreateAttributeIndex(name);
+}
+
+std::string
+HLAObjectClass::getAttributeName(unsigned index) const
+{
+    if (!_rtiObjectClass.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeIndex(): No RTIObject class for object class \"" << getName() << "\"!");
+        return 0;
+    }
+    return _rtiObjectClass->getAttributeName(index);
+}
+
+const HLADataType*
+HLAObjectClass::getAttributeDataType(unsigned index) const
+{
+    if (!_rtiObjectClass.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeDataType(): No RTIObject class for object class \"" << getName() << "\"!");
+        return 0;
+    }
+    return _rtiObjectClass->getAttributeDataType(index);
+}
+
+void
+HLAObjectClass::setAttributeDataType(unsigned index, const HLADataType* dataType)
+{
+    if (!_rtiObjectClass.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::setAttributeDataType(): No RTIObject class for object class \"" << getName() << "\"!");
+        return;
+    }
+    _rtiObjectClass->setAttributeDataType(index, dataType);
+}
+
+HLAUpdateType
+HLAObjectClass::getAttributeUpdateType(unsigned index) const
+{
+    if (!_rtiObjectClass.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeUpdateType(): No RTIObject class for object class \"" << getName() << "\"!");
+        return HLAUndefinedUpdate;
+    }
+    return _rtiObjectClass->getAttributeUpdateType(index);
+}
+
+void
+HLAObjectClass::setAttributeUpdateType(unsigned index, HLAUpdateType updateType)
+{
+    if (!_rtiObjectClass.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::setAttributeUpdateType(): "
+               "No RTIObject class for object class \"" << getName() << "\"!");
+        return;
+    }
+    _rtiObjectClass->setAttributeUpdateType(index, updateType);
+}
+
+HLADataElement::IndexPathPair
+HLAObjectClass::getIndexPathPair(const HLADataElement::AttributePathPair& attributePathPair) const
+{
+    unsigned index = getAttributeIndex(attributePathPair.first);
+    if (getNumAttributes() <= index) {
+        SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass::getIndexPathPair(\""
+               << HLADataElement::toString(attributePathPair)
+               << "\"): Could not resolve attribute \"" << attributePathPair.first
+               << "\" for object class \"" << getName() << "\"!");
+    }
+    return HLADataElement::IndexPathPair(index, attributePathPair.second);
+}
+
+HLADataElement::IndexPathPair
+HLAObjectClass::getIndexPathPair(const std::string& path) const
+{
+    return getIndexPathPair(HLADataElement::toAttributePathPair(path));
+}
+
+bool
+HLAObjectClass::subscribe(const std::set<unsigned>& indexSet, bool active)
+{
+    if (!_rtiObjectClass.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::subscribe(): No RTIObject class for object class \"" << getName() << "\"!");
+        return false;
+    }
+    return _rtiObjectClass->subscribe(indexSet, active);
+}
+
+bool
+HLAObjectClass::unsubscribe()
+{
+    if (!_rtiObjectClass.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unsubscribe(): No RTIObject class for object class \"" << getName() << "\"!");
+        return false;
+    }
+    return _rtiObjectClass->unsubscribe();
+}
+
+bool
+HLAObjectClass::publish(const std::set<unsigned>& indexSet)
+{
+    if (!_rtiObjectClass.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::publish(): No RTIObject class for object class \"" << getName() << "\"!");
+        return false;
+    }
+    return _rtiObjectClass->publish(indexSet);
+}
+
+bool
+HLAObjectClass::unpublish()
+{
+    if (!_rtiObjectClass.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unpublish(): No RTIObject class for object class \"" << getName() << "\"!");
+        return false;
+    }
+    return _rtiObjectClass->unpublish();
+}
+
+void
+HLAObjectClass::startRegistration() const
+{
+}
+
+void
+HLAObjectClass::stopRegistration() const
+{
+}
+
+HLAObjectInstance*
+HLAObjectClass::createObjectInstance(RTIObjectInstance* rtiObjectInstance)
+{
+    return new HLAObjectInstance(this, rtiObjectInstance);
+}
+
+void
+HLAObjectClass::discoverInstance(RTIObjectInstance* objectInstance, const RTIData& tag)
+{
+    SGSharedPtr<HLAObjectInstance> hlaObjectInstance = createObjectInstance(objectInstance);
+    if (hlaObjectInstance.valid()) {
+        SG_LOG(SG_NETWORK, SG_INFO, "RTI: create new object instance for discovered \""
+               << hlaObjectInstance->getName() << "\" object");
+        _objectInstanceSet.insert(hlaObjectInstance);
+        discoverInstanceCallback(*hlaObjectInstance, tag);
+    } else {
+        SG_LOG(SG_NETWORK, SG_INFO, "RTI: local delete of \"" << objectInstance->getName() << "\"");
+        objectInstance->localDeleteObjectInstance();
+    }
+}
+
+void
+HLAObjectClass::removeInstance(HLAObjectInstance& hlaObjectInstance, const RTIData& tag)
+{
+    SG_LOG(SG_NETWORK, SG_INFO, "RTI: remove object instance \"" << hlaObjectInstance.getName() << "\"");
+    removeInstanceCallback(hlaObjectInstance, tag);
+    _objectInstanceSet.erase(&hlaObjectInstance);
+}
+
+void
+HLAObjectClass::registerInstance(HLAObjectInstance& objectInstance)
+{
+    _objectInstanceSet.insert(&objectInstance);
+    registerInstanceCallback(objectInstance);
+}
+
+void
+HLAObjectClass::deleteInstance(HLAObjectInstance& objectInstance)
+{
+    deleteInstanceCallback(objectInstance);
+    _objectInstanceSet.erase(&objectInstance);
+}
+
+void
+HLAObjectClass::discoverInstanceCallback(HLAObjectInstance& objectInstance, const RTIData& tag) const
+{
+    if (!_instanceCallback.valid())
+        return;
+    _instanceCallback->discoverInstance(*this, objectInstance, tag);
+}
+
+void
+HLAObjectClass::removeInstanceCallback(HLAObjectInstance& objectInstance, const RTIData& tag) const
+{
+    if (!_instanceCallback.valid())
+        return;
+    _instanceCallback->removeInstance(*this, objectInstance, tag);
+}
+
+void
+HLAObjectClass::registerInstanceCallback(HLAObjectInstance& objectInstance) const
+{
+    if (!_instanceCallback.valid())
+        return;
+    _instanceCallback->registerInstance(*this, objectInstance);
+}
+
+void
+HLAObjectClass::deleteInstanceCallback(HLAObjectInstance& objectInstance) const
+{
+    if (!_instanceCallback.valid())
+        return;
+    _instanceCallback->deleteInstance(*this, objectInstance);
+}
+
+void
+HLAObjectClass::startRegistrationCallback()
+{
+    if (_registrationCallback.valid())
+        _registrationCallback->startRegistration(*this);
+    else
+        startRegistration();
+}
+
+void
+HLAObjectClass::stopRegistrationCallback()
+{
+    if (_registrationCallback.valid())
+        _registrationCallback->stopRegistration(*this);
+    else
+        stopRegistration();
+}
+
+} // namespace simgear
diff --git a/simgear/hla/HLAObjectClass.hxx b/simgear/hla/HLAObjectClass.hxx
new file mode 100644 (file)
index 0000000..b0db5ad
--- /dev/null
@@ -0,0 +1,131 @@
+// Copyright (C) 2009 - 2010  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 HLAObjectClass_hxx
+#define HLAObjectClass_hxx
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "HLADataType.hxx"
+#include "HLAObjectInstance.hxx"
+
+namespace simgear {
+
+class RTIObjectClass;
+class HLAFederate;
+
+class HLAObjectClass : public SGWeakReferenced {
+public:
+    HLAObjectClass(const std::string& name, HLAFederate& federate);
+    virtual ~HLAObjectClass();
+
+    const std::string& getName() const
+    { return _name; }
+
+    unsigned getNumAttributes() const;
+    unsigned getAttributeIndex(const std::string& name) const;
+    std::string getAttributeName(unsigned index) const;
+
+    const HLADataType* getAttributeDataType(unsigned index) const;
+    void setAttributeDataType(unsigned index, const HLADataType*);
+
+    HLAUpdateType getAttributeUpdateType(unsigned index) const;
+    void setAttributeUpdateType(unsigned index, HLAUpdateType updateType);
+
+    HLADataElement::IndexPathPair getIndexPathPair(const HLADataElement::AttributePathPair&) const;
+    HLADataElement::IndexPathPair getIndexPathPair(const std::string& path) const;
+
+    bool subscribe(const std::set<unsigned>& indexSet, bool active);
+    bool unsubscribe();
+
+    bool publish(const std::set<unsigned>& indexSet);
+    bool unpublish();
+
+    // Object instance creation and destruction
+    class InstanceCallback : public SGReferenced {
+    public:
+        virtual ~InstanceCallback();
+
+        virtual void discoverInstance(const HLAObjectClass& objectClass, HLAObjectInstance& objectInstance, const RTIData& tag);
+        virtual void removeInstance(const HLAObjectClass& objectClass, HLAObjectInstance& objectInstance, const RTIData& tag);
+
+        virtual void registerInstance(const HLAObjectClass& objectClass, HLAObjectInstance& objectInstance);
+        virtual void deleteInstance(const HLAObjectClass& objectClass, HLAObjectInstance& objectInstance);
+    };
+
+    void setInstanceCallback(const SGSharedPtr<InstanceCallback>& instanceCallback)
+    { _instanceCallback = instanceCallback; }
+    const SGSharedPtr<InstanceCallback>& getInstanceCallback() const
+    { return _instanceCallback; }
+
+    // Handles startRegistrationForObjectClass and stopRegistrationForObjectClass events
+    class RegistrationCallback : public SGReferenced {
+    public:
+        virtual ~RegistrationCallback();
+        virtual void startRegistration(HLAObjectClass& objectClass) = 0;
+        virtual void stopRegistration(HLAObjectClass& objectClass) = 0;
+    };
+
+    void setRegistrationCallback(const SGSharedPtr<RegistrationCallback>& registrationCallback)
+    { _registrationCallback = registrationCallback; }
+    const SGSharedPtr<RegistrationCallback>& getRegistrationCallback() const
+    { return _registrationCallback; }
+
+    // Is called by the default registration callback if installed
+    void startRegistration() const;
+    void stopRegistration() const;
+
+protected:
+    virtual HLAObjectInstance* createObjectInstance(RTIObjectInstance* rtiObjectInstance);
+
+private:
+    // The internal entry points from the RTILObjectClass callback functions
+    void discoverInstance(RTIObjectInstance* objectInstance, const RTIData& tag);
+    void removeInstance(HLAObjectInstance& objectInstance, const RTIData& tag);
+    void registerInstance(HLAObjectInstance& objectInstance);
+    void deleteInstance(HLAObjectInstance& objectInstance);
+
+    void discoverInstanceCallback(HLAObjectInstance& objectInstance, const RTIData& tag) const;
+    void removeInstanceCallback(HLAObjectInstance& objectInstance, const RTIData& tag) const;
+    void registerInstanceCallback(HLAObjectInstance& objectInstance) const;
+    void deleteInstanceCallback(HLAObjectInstance& objectInstance) const;
+
+    void startRegistrationCallback();
+    void stopRegistrationCallback();
+    friend class HLAObjectInstance;
+    friend class RTIObjectClass;
+
+    // The object class name
+    std::string _name;
+
+    // The underlying rti dispatcher class
+    SGSharedPtr<RTIObjectClass> _rtiObjectClass;
+
+    // Callback classes
+    SGSharedPtr<InstanceCallback> _instanceCallback;
+    SGSharedPtr<RegistrationCallback> _registrationCallback;
+
+    // The set of active objects
+    typedef std::set<SGSharedPtr<HLAObjectInstance> > ObjectInstanceSet;
+    ObjectInstanceSet _objectInstanceSet;
+};
+
+} // namespace simgear
+
+#endif
diff --git a/simgear/hla/HLAObjectInstance.cxx b/simgear/hla/HLAObjectInstance.cxx
new file mode 100644 (file)
index 0000000..0324d32
--- /dev/null
@@ -0,0 +1,544 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "HLAObjectInstance.hxx"
+
+#include <algorithm>
+#include "HLAArrayDataElement.hxx"
+#include "HLABasicDataElement.hxx"
+#include "HLADataElement.hxx"
+#include "HLAEnumeratedDataElement.hxx"
+#include "HLAFixedRecordDataElement.hxx"
+#include "HLAObjectClass.hxx"
+#include "HLAVariantDataElement.hxx"
+#include "RTIObjectClass.hxx"
+#include "RTIObjectInstance.hxx"
+
+namespace simgear {
+
+HLAObjectInstance::HLAObjectInstance(HLAObjectClass* objectClass) :
+    _objectClass(objectClass)
+{
+}
+
+HLAObjectInstance::HLAObjectInstance(HLAObjectClass* objectClass, RTIObjectInstance* rtiObjectInstance) :
+    _objectClass(objectClass),
+    _rtiObjectInstance(rtiObjectInstance)
+{
+    _rtiObjectInstance->_hlaObjectInstance = this;
+    _name = _rtiObjectInstance->getName();
+}
+
+HLAObjectInstance::~HLAObjectInstance()
+{
+}
+
+SGSharedPtr<HLAObjectClass>
+HLAObjectInstance::getObjectClass() const
+{
+    return _objectClass.lock();
+}
+
+unsigned
+HLAObjectInstance::getNumAttributes() const
+{
+    if (!_rtiObjectInstance.valid()) {
+        SG_LOG(SG_IO, SG_ALERT, "Trying to get number of attributes for inactive object!");
+        return 0;
+    }
+    return _rtiObjectInstance->getNumAttributes();
+}
+
+unsigned
+HLAObjectInstance::getAttributeIndex(const std::string& name) const
+{
+    if (!_rtiObjectInstance.valid()) {
+        SG_LOG(SG_IO, SG_ALERT, "Trying to get attribute index for inactive object!");
+        return 0;
+    }
+    return _rtiObjectInstance->getAttributeIndex(name);
+}
+
+std::string
+HLAObjectInstance::getAttributeName(unsigned index) const
+{
+    if (!_rtiObjectInstance.valid()) {
+        SG_LOG(SG_IO, SG_ALERT, "Trying to get attribute name for inactive object!");
+        return std::string();
+    }
+    return _rtiObjectInstance->getAttributeName(index);
+}
+
+const HLADataType*
+HLAObjectInstance::getAttributeDataType(unsigned index) const
+{
+    if (!_rtiObjectInstance.valid()) {
+        SG_LOG(SG_IO, SG_ALERT, "Trying to get attribute index for inactive object!");
+        return 0;
+    }
+    return _rtiObjectInstance->getAttributeDataType(index);
+}
+
+void
+HLAObjectInstance::setAttributeDataElement(unsigned index, SGSharedPtr<HLADataElement> dataElement)
+{
+    if (!_rtiObjectInstance.valid()) {
+        SG_LOG(SG_IO, SG_ALERT, "Trying to set data element for inactive object!");
+        return;
+    }
+    _rtiObjectInstance->setDataElement(index, dataElement);
+}
+
+HLADataElement*
+HLAObjectInstance::getAttributeDataElement(unsigned index)
+{
+    if (!_rtiObjectInstance.valid()) {
+        SG_LOG(SG_IO, SG_ALERT, "Trying to set data element for inactive object!");
+        return 0;
+    }
+    return _rtiObjectInstance->getDataElement(index);
+}
+
+const HLADataElement*
+HLAObjectInstance::getAttributeDataElement(unsigned index) const
+{
+    if (!_rtiObjectInstance.valid()) {
+        SG_LOG(SG_IO, SG_ALERT, "Trying to set data element for inactive object!");
+        return 0;
+    }
+    return _rtiObjectInstance->getDataElement(index);
+}
+
+class HLAObjectInstance::DataElementFactoryVisitor : public HLADataTypeVisitor {
+public:
+    DataElementFactoryVisitor(const HLAPathElementMap& pathElementMap) :
+        _pathElementMap(pathElementMap)
+    { }
+    DataElementFactoryVisitor(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
+        _pathElementMap(pathElementMap),
+        _path(path)
+    { }
+    virtual ~DataElementFactoryVisitor() {}
+
+    virtual void apply(const HLADataType& dataType)
+    {
+        _dataElement = createDataElement(_path, dataType);
+        if (_dataElement.valid())
+            return;
+
+        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 = createDataElement(_path, dataType);
+        if (_dataElement.valid())
+            return;
+
+        _dataElement = new HLASCharDataElement(&dataType);
+    }
+    virtual void apply(const HLAUInt8DataType& dataType)
+    {
+        _dataElement = createDataElement(_path, dataType);
+        if (_dataElement.valid())
+            return;
+
+        _dataElement = new HLAUCharDataElement(&dataType);
+    }
+    virtual void apply(const HLAInt16DataType& dataType)
+    {
+        _dataElement = createDataElement(_path, dataType);
+        if (_dataElement.valid())
+            return;
+
+        _dataElement = new HLAShortDataElement(&dataType);
+    }
+    virtual void apply(const HLAUInt16DataType& dataType)
+    {
+        _dataElement = createDataElement(_path, dataType);
+        if (_dataElement.valid())
+            return;
+
+        _dataElement = new HLAUShortDataElement(&dataType);
+    }
+    virtual void apply(const HLAInt32DataType& dataType)
+    {
+        _dataElement = createDataElement(_path, dataType);
+        if (_dataElement.valid())
+            return;
+
+        _dataElement = new HLAIntDataElement(&dataType);
+    }
+    virtual void apply(const HLAUInt32DataType& dataType)
+    {
+        _dataElement = createDataElement(_path, dataType);
+        if (_dataElement.valid())
+            return;
+
+        _dataElement = new HLAUIntDataElement(&dataType);
+    }
+    virtual void apply(const HLAInt64DataType& dataType)
+    {
+        _dataElement = createDataElement(_path, dataType);
+        if (_dataElement.valid())
+            return;
+
+        _dataElement = new HLALongDataElement(&dataType);
+    }
+    virtual void apply(const HLAUInt64DataType& dataType)
+    {
+        _dataElement = createDataElement(_path, dataType);
+        if (_dataElement.valid())
+            return;
+
+        _dataElement = new HLAULongDataElement(&dataType);
+    }
+    virtual void apply(const HLAFloat32DataType& dataType)
+    {
+        _dataElement = createDataElement(_path, dataType);
+        if (_dataElement.valid())
+            return;
+
+        _dataElement = new HLAFloatDataElement(&dataType);
+    }
+    virtual void apply(const HLAFloat64DataType& dataType)
+    {
+        _dataElement = createDataElement(_path, dataType);
+        if (_dataElement.valid())
+            return;
+
+        _dataElement = new HLADoubleDataElement(&dataType);
+    }
+
+    class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
+    public:
+        ArrayDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
+            _path(path)
+        {
+            for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
+                 i != pathElementMap.end(); ++i) {
+                if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
+                                                    path.begin(), path.end()))
+                    break;
+                _pathElementMap.insert(*i);
+            }
+        }
+        virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index)
+        {
+            const HLADataType* dataType = element.getElementDataType();
+            if (!dataType)
+                return 0;
+            HLADataElement::Path path = _path;
+            path.push_back(HLADataElement::PathElement(index));
+            DataElementFactoryVisitor visitor(path, _pathElementMap);
+            dataType->accept(visitor);
+            return visitor._dataElement.release();
+        }
+    private:
+        HLADataElement::Path _path;
+        HLAPathElementMap _pathElementMap;
+    };
+
+    virtual void apply(const HLAFixedArrayDataType& dataType)
+    {
+        _dataElement = createDataElement(_path, dataType);
+        if (_dataElement.valid())
+            return;
+
+        SGSharedPtr<HLAArrayDataElement> arrayDataElement;
+        arrayDataElement = new HLAArrayDataElement(&dataType);
+        arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
+        arrayDataElement->setNumElements(dataType.getNumElements());
+
+        _dataElement = arrayDataElement;
+    }
+
+    virtual void apply(const HLAVariableArrayDataType& dataType)
+    {
+        _dataElement = createDataElement(_path, dataType);
+        if (_dataElement.valid())
+            return;
+
+        SGSharedPtr<HLAArrayDataElement> arrayDataElement;
+        arrayDataElement = new HLAArrayDataElement(&dataType);
+        arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
+
+        _dataElement = arrayDataElement;
+    }
+
+    virtual void apply(const HLAEnumeratedDataType& dataType)
+    {
+        _dataElement = createDataElement(_path, dataType);
+        if (_dataElement.valid())
+            return;
+
+        _dataElement = new HLAEnumeratedDataElement(&dataType);
+    }
+
+    virtual void apply(const HLAFixedRecordDataType& dataType)
+    {
+        _dataElement = createDataElement(_path, dataType);
+        if (_dataElement.valid())
+            return;
+
+        SGSharedPtr<HLAFixedRecordDataElement> recordDataElement;
+        recordDataElement = new HLAFixedRecordDataElement(&dataType);
+
+        unsigned numFields = dataType.getNumFields();
+        for (unsigned i = 0; i < numFields; ++i) {
+
+            _path.push_back(HLADataElement::PathElement(dataType.getFieldName(i)));
+
+            dataType.getFieldDataType(i)->accept(*this);
+            recordDataElement->setField(i, _dataElement.release());
+
+            _path.pop_back();
+        }
+        _dataElement = recordDataElement;
+    }
+
+    class VariantDataElementFactory : public HLAVariantDataElement::DataElementFactory {
+    public:
+        VariantDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
+            _path(path)
+        {
+            for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
+                 i != pathElementMap.end(); ++i) {
+                if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
+                                                    path.begin(), path.end()))
+                    break;
+                _pathElementMap.insert(*i);
+            }
+        }
+        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;
+            HLADataElement::Path path = _path;
+            path.push_back(HLADataElement::PathElement(dataType->getAlternativeName(index)));
+            DataElementFactoryVisitor visitor(path, _pathElementMap);
+            alternativeDataType->accept(visitor);
+            return visitor._dataElement.release();
+        }
+    private:
+        HLADataElement::Path _path;
+        HLAPathElementMap _pathElementMap;
+    };
+
+    virtual void apply(const HLAVariantDataType& dataType)
+    {
+        _dataElement = createDataElement(_path, dataType);
+        if (_dataElement.valid())
+            return;
+
+        SGSharedPtr<HLAVariantDataElement> variantDataElement;
+        variantDataElement = new HLAVariantDataElement(&dataType);
+        variantDataElement->setDataElementFactory(new VariantDataElementFactory(_path, _pathElementMap));
+
+        _dataElement = variantDataElement;
+    }
+
+    const SGSharedPtr<HLADataElement>& getDataElement() const
+    { return _dataElement; }
+
+private:
+    SGSharedPtr<HLADataElement> createDataElement(const HLADataElement::Path& path, const HLADataType& dataType)
+    {
+        HLAPathElementMap::const_iterator i = _pathElementMap.find(path);
+        if (i == _pathElementMap.end()) {
+            SG_LOG(SG_IO, SG_WARN, "No dataElement provided for \""
+                   << HLADataElement::toString(path) << "\".");
+
+            return 0;
+        }
+        SGSharedPtr<HLADataElement> dataElement = i->second.getDataElement(path);
+        if (!dataElement->setDataType(&dataType)) {
+            SG_LOG(SG_IO, SG_ALERT, "Cannot set data type for data element at \""
+                   << HLADataElement::toString(path) <<  "\"!");
+            return 0;
+        }
+        SG_LOG(SG_IO, SG_DEBUG, "Using provided dataElement for \""
+               << HLADataElement::toString(path) << "\".");
+        return dataElement;
+    }
+
+    SGSharedPtr<HLADataElement> _dataElement;
+    const HLAPathElementMap& _pathElementMap;
+    HLADataElement::Path _path;
+};
+
+void
+HLAObjectInstance::setAttribute(unsigned index, const HLAPathElementMap& pathElementMap)
+{
+    const HLADataType* dataType = getAttributeDataType(index);
+    if (!dataType) {
+        SG_LOG(SG_IO, SG_ALERT, "Cannot get attribute data type for setting attribute at index "
+               << index << "!");
+        return;
+    }
+
+    SG_LOG(SG_IO, SG_DEBUG, "Setting DataElement for attribute \""
+           << getAttributeName(index) << "\".");
+
+    DataElementFactoryVisitor visitor(pathElementMap);
+    dataType->accept(visitor);
+    setAttributeDataElement(index, visitor.getDataElement());
+}
+
+void
+HLAObjectInstance::setAttributes(const HLAAttributePathElementMap& attributePathElementMap)
+{
+    for (HLAAttributePathElementMap::const_iterator i = attributePathElementMap.begin();
+         i != attributePathElementMap.end(); ++i) {
+        setAttribute(i->first, i->second);
+    }
+}
+
+void
+HLAObjectInstance::requestAttributeUpdate(unsigned index)
+{
+    if (!_rtiObjectInstance.valid()) {
+        SG_LOG(SG_IO, SG_ALERT, "Trying to request attribute update for inactive object!");
+        return;
+    }
+    _rtiObjectInstance->setRequestAttributeUpdate(index, true);
+}
+
+void
+HLAObjectInstance::requestAttributeUpdate()
+{
+    if (!_rtiObjectInstance.valid()) {
+        SG_LOG(SG_IO, SG_ALERT, "Trying to request attribute update for inactive object!");
+        return;
+    }
+    _rtiObjectInstance->setRequestAttributeUpdate(true);
+}
+
+void
+HLAObjectInstance::registerInstance()
+{
+    if (_rtiObjectInstance.valid()) {
+        SG_LOG(SG_IO, SG_ALERT, "Trying to register object " << getName() << " already known to the RTI!");
+        return;
+    }
+    SGSharedPtr<HLAObjectClass> objectClass = _objectClass.lock();
+    if (!objectClass.valid()) {
+        SG_LOG(SG_IO, SG_ALERT, "Could not register object with unknown object class!");
+        return;
+    }
+    // This error must have been flagged before
+    if (!objectClass->_rtiObjectClass.valid())
+        return;
+    _rtiObjectInstance = objectClass->_rtiObjectClass->registerObjectInstance(this);
+    if (!_rtiObjectInstance.valid()) {
+        SG_LOG(SG_IO, SG_ALERT, "Could not register object at the RTI!");
+        return;
+    }
+    _name = _rtiObjectInstance->getName();
+    objectClass->registerInstance(*this);
+}
+
+void
+HLAObjectInstance::deleteInstance(const RTIData& tag)
+{
+    if (!_rtiObjectInstance.valid()) {
+        SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!");
+        return;
+    }
+    SGSharedPtr<HLAObjectClass> objectClass = _objectClass.lock();
+    if (!objectClass.valid())
+        return;
+    objectClass->deleteInstance(*this);
+    _rtiObjectInstance->deleteObjectInstance(tag);
+}
+
+void
+HLAObjectInstance::localDeleteInstance()
+{
+    if (!_rtiObjectInstance.valid()) {
+        SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!");
+        return;
+    }
+   _rtiObjectInstance->localDeleteObjectInstance();
+}
+
+void
+HLAObjectInstance::updateAttributeValues(const RTIData& tag)
+{
+    if (!_rtiObjectInstance.valid()) {
+        SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
+        return;
+    }
+    if (_attributeCallback.valid())
+        _attributeCallback->updateAttributeValues(*this, tag);
+    _rtiObjectInstance->updateAttributeValues(tag);
+}
+
+void
+HLAObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
+{
+    if (!_rtiObjectInstance.valid()) {
+        SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
+        return;
+    }
+    if (_attributeCallback.valid())
+        _attributeCallback->updateAttributeValues(*this, tag);
+    _rtiObjectInstance->updateAttributeValues(timeStamp, tag);
+}
+
+void
+HLAObjectInstance::reflectQueuedAttributeValues(const SGTimeStamp& timeStamp)
+{
+    if (!_rtiObjectInstance.valid()) {
+        SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
+        return;
+    }
+    _rtiObjectInstance->reflectQueuedAttributeValues(timeStamp);
+}
+
+void
+HLAObjectInstance::removeInstance(const RTIData& tag)
+{
+    SGSharedPtr<HLAObjectClass> objectClass = _objectClass.lock();
+    if (!objectClass.valid())
+        return;
+    objectClass->removeInstanceCallback(*this, tag);
+}
+
+void
+HLAObjectInstance::reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag)
+{
+    if (!_attributeCallback.valid())
+        return;
+    _attributeCallback->reflectAttributeValues(*this, dataPairList, tag);
+}
+
+void
+HLAObjectInstance::reflectAttributeValues(const RTIIndexDataPairList& dataPairList,
+                                          const SGTimeStamp& timeStamp, const RTIData& tag)
+{
+    if (!_attributeCallback.valid())
+        return;
+    _attributeCallback->reflectAttributeValues(*this, dataPairList, timeStamp, tag);
+}
+
+} // namespace simgear
diff --git a/simgear/hla/HLAObjectInstance.hxx b/simgear/hla/HLAObjectInstance.hxx
new file mode 100644 (file)
index 0000000..c042027
--- /dev/null
@@ -0,0 +1,111 @@
+// Copyright (C) 2009 - 2010  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 HLAObjectInstance_hxx
+#define HLAObjectInstance_hxx
+
+#include <simgear/structure/SGWeakPtr.hxx>
+
+#include "HLADataElement.hxx"
+
+class SGTimeStamp;
+
+namespace simgear {
+
+class RTIObjectInstance;
+class HLAObjectClass;
+
+class HLAObjectInstance : public SGWeakReferenced {
+public:
+    HLAObjectInstance(HLAObjectClass* objectClass);
+    HLAObjectInstance(HLAObjectClass* objectClass, RTIObjectInstance* rtiObjectInstance);
+    virtual ~HLAObjectInstance();
+
+    const std::string& getName() const
+    { return _name; }
+
+    SGSharedPtr<HLAObjectClass> getObjectClass() const;
+
+    unsigned getNumAttributes() const;
+    unsigned getAttributeIndex(const std::string& name) const;
+    std::string getAttributeName(unsigned index) const;
+
+    const HLADataType* getAttributeDataType(unsigned index) const;
+
+    void setAttributeDataElement(unsigned index, SGSharedPtr<HLADataElement> dataElement);
+    HLADataElement* getAttributeDataElement(unsigned index);
+    const HLADataElement* getAttributeDataElement(unsigned index) const;
+    void setAttribute(unsigned index, const HLAPathElementMap& pathElementMap);
+    void setAttributes(const HLAAttributePathElementMap& attributePathElementMap);
+
+    // Ask the rti to provide the attribute at index
+    void requestAttributeUpdate(unsigned index);
+    void requestAttributeUpdate();
+
+    void registerInstance();
+    void deleteInstance(const RTIData& tag);
+    void localDeleteInstance();
+
+    class AttributeCallback : public SGReferenced {
+    public:
+        virtual ~AttributeCallback() {}
+        // Notification about reflect and whatever TBD
+        // Hmm, don't know yet how this should look like
+        virtual void updateAttributeValues(HLAObjectInstance& objectInstance, const RTIData& tag)
+        { }
+
+        virtual void reflectAttributeValues(HLAObjectInstance& objectInstance,
+                                            const RTIIndexDataPairList& dataPairList, const RTIData& tag)
+        { }
+        virtual void reflectAttributeValues(HLAObjectInstance& objectInstance, const RTIIndexDataPairList& dataPairList,
+                                            const SGTimeStamp& timeStamp, const RTIData& tag)
+        { reflectAttributeValues(objectInstance, dataPairList, tag); }
+    };
+
+    void setAttributeCallback(const SGSharedPtr<AttributeCallback>& attributeCallback)
+    { _attributeCallback = attributeCallback; }
+    const SGSharedPtr<AttributeCallback>& getAttributeCallback() const
+    { return _attributeCallback; }
+
+    // Push the current values into the RTI
+    void updateAttributeValues(const RTIData& tag);
+    void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag);
+
+    // Retrieve queued up updates up to and including timestamp,
+    // Note that this only applies to timestamped updates.
+    // The unordered updates are reflected as they arrive
+    void reflectQueuedAttributeValues(const SGTimeStamp& timeStamp);
+
+private:
+    void removeInstance(const RTIData& tag);
+    void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag);
+    void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const SGTimeStamp& timeStamp, const RTIData& tag);
+    friend class RTIObjectInstance;
+    friend class HLAObjectClass;
+
+    class DataElementFactoryVisitor;
+
+    std::string _name;
+
+    SGWeakPtr<HLAObjectClass> _objectClass;
+    SGSharedPtr<RTIObjectInstance> _rtiObjectInstance;
+    SGSharedPtr<AttributeCallback> _attributeCallback;
+};
+
+} // namespace simgear
+
+#endif
diff --git a/simgear/hla/HLAPropertyDataElement.cxx b/simgear/hla/HLAPropertyDataElement.cxx
new file mode 100644 (file)
index 0000000..db4f00b
--- /dev/null
@@ -0,0 +1,269 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "HLAPropertyDataElement.hxx"
+
+#include "HLADataTypeVisitor.hxx"
+
+namespace simgear {
+
+class HLAPropertyDataElement::DecodeVisitor : public HLADataTypeDecodeVisitor {
+public:
+    DecodeVisitor(HLADecodeStream& stream, HLAPropertyReference& propertyReference) :
+        HLADataTypeDecodeVisitor(stream),
+        _propertyReference(propertyReference)
+    { }
+
+    virtual void apply(const HLAInt8DataType& dataType)
+    {
+        int8_t value = 0;
+        dataType.decode(_stream, value);
+        _propertyReference.setIntValue(value);
+    }
+    virtual void apply(const HLAUInt8DataType& dataType)
+    {
+        uint8_t value = 0;
+        dataType.decode(_stream, value);
+        _propertyReference.setIntValue(value);
+    }
+    virtual void apply(const HLAInt16DataType& dataType)
+    {
+        int16_t value = 0;
+        dataType.decode(_stream, value);
+        _propertyReference.setIntValue(value);
+    }
+    virtual void apply(const HLAUInt16DataType& dataType)
+    {
+        uint16_t value = 0;
+        dataType.decode(_stream, value);
+        _propertyReference.setIntValue(value);
+    }
+    virtual void apply(const HLAInt32DataType& dataType)
+    {
+        int32_t value = 0;
+        dataType.decode(_stream, value);
+        _propertyReference.setIntValue(value);
+    }
+    virtual void apply(const HLAUInt32DataType& dataType)
+    {
+        uint32_t value = 0;
+        dataType.decode(_stream, value);
+        _propertyReference.setIntValue(value);
+    }
+    virtual void apply(const HLAInt64DataType& dataType)
+    {
+        int64_t value = 0;
+        dataType.decode(_stream, value);
+        _propertyReference.setLongValue(value);
+    }
+    virtual void apply(const HLAUInt64DataType& dataType)
+    {
+        uint64_t value = 0;
+        dataType.decode(_stream, value);
+        _propertyReference.setLongValue(value);
+    }
+    virtual void apply(const HLAFloat32DataType& dataType)
+    {
+        float value = 0;
+        dataType.decode(_stream, value);
+        _propertyReference.setFloatValue(value);
+    }
+    virtual void apply(const HLAFloat64DataType& dataType)
+    {
+        double value = 0;
+        dataType.decode(_stream, value);
+        _propertyReference.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());
+        }
+        _propertyReference.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());
+        }
+        _propertyReference.setStringValue(value);
+    }
+
+protected:
+    HLAPropertyReference& _propertyReference;
+};
+
+class HLAPropertyDataElement::EncodeVisitor : public HLADataTypeEncodeVisitor {
+public:
+    EncodeVisitor(HLAEncodeStream& stream, const HLAPropertyReference& propertyReference) :
+        HLADataTypeEncodeVisitor(stream),
+        _propertyReference(propertyReference)
+    { }
+
+    virtual void apply(const HLAInt8DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyReference.getIntValue());
+    }
+    virtual void apply(const HLAUInt8DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyReference.getIntValue());
+    }
+    virtual void apply(const HLAInt16DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyReference.getIntValue());
+    }
+    virtual void apply(const HLAUInt16DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyReference.getIntValue());
+    }
+    virtual void apply(const HLAInt32DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyReference.getIntValue());
+    }
+    virtual void apply(const HLAUInt32DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyReference.getIntValue());
+    }
+    virtual void apply(const HLAInt64DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyReference.getLongValue());
+    }
+    virtual void apply(const HLAUInt64DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyReference.getLongValue());
+    }
+    virtual void apply(const HLAFloat32DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyReference.getFloatValue());
+    }
+    virtual void apply(const HLAFloat64DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyReference.getDoubleValue());
+    }
+
+    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<char> 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 = _propertyReference.getStringValue();
+        HLATemplateEncodeVisitor<std::string::size_type> numElementsVisitor(_stream, value.size());
+        dataType.getSizeDataType()->accept(numElementsVisitor);
+        for (unsigned i = 0; i < value.size(); ++i) {
+            HLATemplateEncodeVisitor<char> visitor(_stream, value[i]);
+            dataType.getElementDataType()->accept(visitor);
+        }
+    }
+
+protected:
+    const HLAPropertyReference& _propertyReference;
+};
+
+HLAPropertyDataElement::HLAPropertyDataElement(HLAPropertyReference* propertyReference) :
+    _propertyReference(propertyReference)
+{
+}
+
+HLAPropertyDataElement::HLAPropertyDataElement(const simgear::HLADataType* dataType, HLAPropertyReference* propertyReference) :
+    _dataType(dataType),
+    _propertyReference(propertyReference)
+{
+}
+
+HLAPropertyDataElement::~HLAPropertyDataElement()
+{
+}
+
+bool
+HLAPropertyDataElement::encode(HLAEncodeStream& stream) const
+{
+    if (!_dataType.valid())
+        return false;
+    if (_propertyReference.valid()) {
+        EncodeVisitor visitor(stream, *_propertyReference);
+        _dataType->accept(visitor);
+    } else {
+        HLADataTypeEncodeVisitor visitor(stream);
+        _dataType->accept(visitor);
+    }
+    return true;
+}
+
+bool
+HLAPropertyDataElement::decode(HLADecodeStream& stream)
+{
+    if (!_dataType.valid())
+        return false;
+    if (_propertyReference.valid()) {
+        DecodeVisitor visitor(stream, *_propertyReference);
+        _dataType->accept(visitor);
+    } else {
+        HLADataTypeDecodeVisitor visitor(stream);
+        _dataType->accept(visitor);
+    }
+    return true;
+}
+
+const HLADataType*
+HLAPropertyDataElement::getDataType() const
+{
+    return _dataType.get();
+}
+
+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;
+}
+
+} // namespace simgear
diff --git a/simgear/hla/HLAPropertyDataElement.hxx b/simgear/hla/HLAPropertyDataElement.hxx
new file mode 100644 (file)
index 0000000..4441584
--- /dev/null
@@ -0,0 +1,172 @@
+// Copyright (C) 2009 - 2010  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 HLAPropertyDataElement_hxx
+#define HLAPropertyDataElement_hxx
+
+#include <set>
+#include <simgear/props/props.hxx>
+#include "HLADataElement.hxx"
+
+namespace simgear {
+
+class HLAPropertyReference : public SGReferenced {
+public:
+    HLAPropertyReference()
+    { }
+    HLAPropertyReference(const std::string& relativePath) :
+        _relativePath(relativePath)
+    { }
+
+    void setIntValue(int value)
+    {
+        if (!_propertyNode.valid())
+            return;
+        _propertyNode->setIntValue(value);
+    }
+    int getIntValue() const
+    {
+        if (!_propertyNode.valid())
+            return 0;
+        return _propertyNode->getIntValue();
+    }
+
+    void setLongValue(long value)
+    {
+        if (!_propertyNode.valid())
+            return;
+        _propertyNode->setLongValue(value);
+    }
+    long getLongValue() const
+    {
+        if (!_propertyNode.valid())
+            return 0;
+        return _propertyNode->getLongValue();
+    }
+
+    void setFloatValue(float value)
+    {
+        if (!_propertyNode.valid())
+            return;
+        _propertyNode->setFloatValue(value);
+    }
+    float getFloatValue() const
+    {
+        if (!_propertyNode.valid())
+            return 0;
+        return _propertyNode->getFloatValue();
+    }
+
+    void setDoubleValue(double value)
+    {
+        if (!_propertyNode.valid())
+            return;
+        _propertyNode->setDoubleValue(value);
+    }
+    double getDoubleValue() const
+    {
+        if (!_propertyNode.valid())
+            return 0;
+        return _propertyNode->getDoubleValue();
+    }
+
+    void setStringValue(const std::string& value)
+    {
+        if (!_propertyNode.valid())
+            return;
+        _propertyNode->setStringValue(value);
+    }
+    std::string getStringValue() const
+    {
+        if (!_propertyNode.valid())
+            return std::string();
+        return _propertyNode->getStringValue();
+    }
+
+    SGPropertyNode* getPropertyNode()
+    { return _propertyNode.get(); }
+
+    void setRootNode(SGPropertyNode* rootNode)
+    {
+        if (!rootNode)
+            _propertyNode.clear();
+        else
+            _propertyNode = rootNode->getNode(_relativePath, true);
+    }
+
+private:
+    std::string _relativePath;
+    SGSharedPtr<SGPropertyNode> _propertyNode;
+};
+
+class HLAPropertyReferenceSet : public SGReferenced {
+public:
+    void insert(const SGSharedPtr<HLAPropertyReference>& propertyReference)
+    {
+        _propertyReferenceSet.insert(propertyReference);
+        propertyReference->setRootNode(_rootNode.get());
+    }
+    void remove(const SGSharedPtr<HLAPropertyReference>& propertyReference)
+    {
+        PropertyReferenceSet::iterator i = _propertyReferenceSet.find(propertyReference);
+        if (i == _propertyReferenceSet.end())
+            return;
+        _propertyReferenceSet.erase(i);
+        propertyReference->setRootNode(0);
+    }
+
+    void setRootNode(SGPropertyNode* rootNode)
+    {
+        _rootNode = rootNode;
+        for (PropertyReferenceSet::iterator i = _propertyReferenceSet.begin();
+             i != _propertyReferenceSet.end(); ++i) {
+            (*i)->setRootNode(_rootNode.get());
+        }
+    }
+    SGPropertyNode* getRootNode()
+    { return _rootNode.get(); }
+
+private:
+    SGSharedPtr<SGPropertyNode> _rootNode;
+
+    typedef std::set<SGSharedPtr<HLAPropertyReference> > PropertyReferenceSet;
+    PropertyReferenceSet _propertyReferenceSet;
+};
+
+class HLAPropertyDataElement : public HLADataElement {
+public:
+    HLAPropertyDataElement(HLAPropertyReference* propertyReference);
+    HLAPropertyDataElement(const simgear::HLADataType* dataType, HLAPropertyReference* propertyReference);
+    ~HLAPropertyDataElement();
+
+    virtual bool encode(HLAEncodeStream& stream) const;
+    virtual bool decode(HLADecodeStream& stream);
+
+    virtual const HLADataType* getDataType() const;
+    virtual bool setDataType(const HLADataType* dataType);
+
+private:
+    class DecodeVisitor;
+    class EncodeVisitor;
+
+    SGSharedPtr<const HLADataType> _dataType;
+    SGSharedPtr<HLAPropertyReference> _propertyReference;
+};
+
+} // namespace simgear
+
+#endif
diff --git a/simgear/hla/HLARawDataElement.cxx b/simgear/hla/HLARawDataElement.cxx
new file mode 100644 (file)
index 0000000..14dd3ea
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "HLARawDataElement.hxx"
+
+namespace simgear {
+
+HLARawDataElement::HLARawDataElement(const HLADataType* dataType) :
+    _dataType(dataType)
+{
+}
+
+HLARawDataElement::~HLARawDataElement()
+{
+}
+
+bool
+HLARawDataElement::encode(HLAEncodeStream& stream) const
+{
+    stream.setData(_rtiData);
+    stream.skip(_rtiData.size());
+    return true;
+}
+
+bool
+HLARawDataElement::decode(HLADecodeStream& stream)
+{
+    _rtiData = stream.getData();
+    stream.skip(_rtiData.size());
+    return true;
+}
+
+const HLADataType*
+HLARawDataElement::getDataType() const
+{
+    return _dataType.get();
+}
+
+bool
+HLARawDataElement::setDataType(const HLADataType* dataType)
+{
+    _dataType = dataType;
+    return true;
+}
+
+}
diff --git a/simgear/hla/HLARawDataElement.hxx b/simgear/hla/HLARawDataElement.hxx
new file mode 100644 (file)
index 0000000..ac6bbf6
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright (C) 2009 - 2010  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 HLARawDataElement_hxx
+#define HLARawDataElement_hxx
+
+#include "RTIData.hxx"
+#include "HLADataElement.hxx"
+#include "HLADataType.hxx"
+
+namespace simgear {
+
+class HLARawDataElement : public HLADataElement {
+public:
+    HLARawDataElement(const HLADataType* dataType);
+    virtual ~HLARawDataElement();
+
+    virtual bool encode(HLAEncodeStream& stream) const;
+    virtual bool decode(HLADecodeStream& stream);
+
+    virtual const HLADataType* getDataType() const;
+    virtual bool setDataType(const HLADataType* dataType);
+
+    const RTIData& getData() const
+    { return _rtiData; }
+    RTIData& getData()
+    { return _rtiData; }
+    void setData(const RTIData& rtiData)
+    { _rtiData = rtiData; }
+
+protected:
+    SGSharedPtr<const HLADataType> _dataType;
+    RTIData _rtiData;
+};
+
+}
+
+#endif
diff --git a/simgear/hla/HLAVariantDataElement.cxx b/simgear/hla/HLAVariantDataElement.cxx
new file mode 100644 (file)
index 0000000..98c22f7
--- /dev/null
@@ -0,0 +1,155 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "HLAVariantDataElement.hxx"
+
+#include <simgear/debug/logstream.hxx>
+
+namespace simgear {
+
+HLAAbstractVariantDataElement::HLAAbstractVariantDataElement(const HLAVariantDataType* dataType) :
+    _dataType(dataType)
+{
+}
+
+HLAAbstractVariantDataElement::~HLAAbstractVariantDataElement()
+{
+}
+
+bool
+HLAAbstractVariantDataElement::decode(HLADecodeStream& stream)
+{
+    if (!_dataType.valid())
+        return false;
+    return _dataType->decode(stream, *this);
+}
+
+bool
+HLAAbstractVariantDataElement::encode(HLAEncodeStream& stream) const
+{
+    if (!_dataType.valid())
+        return false;
+    return _dataType->encode(stream, *this);
+}
+
+const HLAVariantDataType*
+HLAAbstractVariantDataElement::getDataType() const
+{
+    return _dataType.get();
+}
+
+bool
+HLAAbstractVariantDataElement::setDataType(const HLADataType* dataType)
+{
+    const HLAVariantDataType* variantDataType = dataType->toVariantDataType();
+    if (!variantDataType) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLAVariantDataType: unable to set data type!");
+        return false;
+    }
+    setDataType(variantDataType);
+    return true;
+}
+
+void
+HLAAbstractVariantDataElement::setDataType(const HLAVariantDataType* dataType)
+{
+    _dataType = dataType;
+}
+
+std::string
+HLAAbstractVariantDataElement::getAlternativeName() const
+{
+    if (!_dataType.valid())
+        return std::string();
+    return _dataType->getAlternativeName(getAlternativeIndex());
+}
+
+const HLADataType*
+HLAAbstractVariantDataElement::getAlternativeDataType() const
+{
+    if (!_dataType.valid())
+        return 0;
+    return _dataType->getAlternativeDataType(getAlternativeIndex());
+}
+
+
+HLAVariantDataElement::DataElementFactory::~DataElementFactory()
+{
+}
+
+HLAVariantDataElement::HLAVariantDataElement(const HLAVariantDataType* dataType) :
+    HLAAbstractVariantDataElement(dataType),
+    _alternativeIndex(~0u)
+{
+}
+
+HLAVariantDataElement::~HLAVariantDataElement()
+{
+}
+
+bool
+HLAVariantDataElement::setAlternativeIndex(unsigned index)
+{
+    if (_alternativeIndex == index)
+        return true;
+    SGSharedPtr<HLADataElement> dataElement = newElement(index);
+    if (!dataElement.valid())
+        return false;
+    _dataElement.swap(dataElement);
+    _alternativeIndex = index;
+    return true;
+}
+
+bool
+HLAVariantDataElement::decodeAlternative(HLADecodeStream& stream)
+{
+    return _dataElement->decode(stream);
+}
+
+unsigned
+HLAVariantDataElement::getAlternativeIndex() const
+{
+    return _alternativeIndex;
+}
+
+bool
+HLAVariantDataElement::encodeAlternative(HLAEncodeStream& stream) const
+{
+    return _dataElement->encode(stream);
+}
+
+void
+HLAVariantDataElement::setDataElementFactory(HLAVariantDataElement::DataElementFactory* dataElementFactory)
+{
+    _dataElementFactory = dataElementFactory;
+}
+
+HLAVariantDataElement::DataElementFactory*
+HLAVariantDataElement::getDataElementFactory()
+{
+    return _dataElementFactory;
+}
+
+HLADataElement*
+HLAVariantDataElement::newElement(unsigned index)
+{
+    if (!_dataElementFactory.valid())
+        return 0;
+    return _dataElementFactory->createElement(*this, index);
+}
+
+}
diff --git a/simgear/hla/HLAVariantDataElement.hxx b/simgear/hla/HLAVariantDataElement.hxx
new file mode 100644 (file)
index 0000000..b3ced7c
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright (C) 2009 - 2010  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 HLAVariantDataElement_hxx
+#define HLAVariantDataElement_hxx
+
+#include <string>
+#include <simgear/structure/SGSharedPtr.hxx>
+#include "HLADataElement.hxx"
+#include "HLAVariantDataType.hxx"
+
+namespace simgear {
+
+class HLAAbstractVariantDataElement : public HLADataElement {
+public:
+    HLAAbstractVariantDataElement(const HLAVariantDataType* dataType);
+    virtual ~HLAAbstractVariantDataElement();
+
+    virtual bool decode(HLADecodeStream& stream);
+    virtual bool encode(HLAEncodeStream& stream) const;
+
+    virtual const HLAVariantDataType* getDataType() const;
+    virtual bool setDataType(const HLADataType* dataType);
+    void setDataType(const HLAVariantDataType* dataType);
+
+    std::string getAlternativeName() const;
+    const HLADataType* getAlternativeDataType() const;
+
+    virtual bool setAlternativeIndex(unsigned index) = 0;
+    virtual bool decodeAlternative(HLADecodeStream& stream) = 0;
+    virtual unsigned getAlternativeIndex() const = 0;
+    virtual bool encodeAlternative(HLAEncodeStream& stream) const = 0;
+
+private:
+    SGSharedPtr<const HLAVariantDataType> _dataType;
+};
+
+class HLAVariantDataElement : public HLAAbstractVariantDataElement {
+public:
+    HLAVariantDataElement(const HLAVariantDataType* dataType);
+    virtual ~HLAVariantDataElement();
+
+    virtual bool setAlternativeIndex(unsigned index);
+    virtual bool decodeAlternative(HLADecodeStream& stream);
+    virtual unsigned getAlternativeIndex() const;
+    virtual bool encodeAlternative(HLAEncodeStream& stream) const;
+
+    class DataElementFactory : public SGReferenced {
+    public:
+        virtual ~DataElementFactory();
+        virtual HLADataElement* createElement(const HLAVariantDataElement&, unsigned) = 0;
+    };
+
+    void setDataElementFactory(DataElementFactory* dataElementFactory);
+    DataElementFactory* getDataElementFactory();
+
+private:
+    HLADataElement* newElement(unsigned index);
+
+    SGSharedPtr<HLADataElement> _dataElement;
+    unsigned _alternativeIndex;
+
+    SGSharedPtr<DataElementFactory> _dataElementFactory;
+};
+
+}
+
+#endif
diff --git a/simgear/hla/HLAVariantDataType.cxx b/simgear/hla/HLAVariantDataType.cxx
new file mode 100644 (file)
index 0000000..45e20db
--- /dev/null
@@ -0,0 +1,101 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "HLAVariantDataType.hxx"
+
+#include "HLADataTypeVisitor.hxx"
+#include "HLAVariantDataElement.hxx"
+
+namespace simgear {
+
+HLAVariantDataType::HLAVariantDataType(const std::string& name) :
+    HLADataType(name)
+{
+}
+
+HLAVariantDataType::~HLAVariantDataType()
+{
+}
+
+void
+HLAVariantDataType::accept(HLADataTypeVisitor& visitor) const
+{
+    visitor.apply(*this);
+}
+
+const HLAVariantDataType*
+HLAVariantDataType::toVariantDataType() const
+{
+    return this;
+}
+
+bool
+HLAVariantDataType::decode(HLADecodeStream& stream, HLAAbstractVariantDataElement& value) const
+{
+    if (!stream.alignOffsetForSize(getAlignment()))
+        return false;
+    if (!_enumeratedDataType.valid())
+        return false;
+    unsigned index = ~0u;
+    if (!_enumeratedDataType->decode(stream, index))
+        return false;
+    if (!value.setAlternativeIndex(index))
+        return false;
+    if (!value.decodeAlternative(stream))
+        return false;
+    return true;
+}
+
+bool
+HLAVariantDataType::encode(HLAEncodeStream& stream, const HLAAbstractVariantDataElement& value) const
+{
+    if (!stream.alignOffsetForSize(getAlignment()))
+        return false;
+    if (!_enumeratedDataType.valid())
+        return false;
+    unsigned index = value.getAlternativeIndex();
+    if (!_enumeratedDataType->encode(stream, index))
+        return false;
+    if (!value.encodeAlternative(stream))
+        return false;
+    return true;
+}
+
+void
+HLAVariantDataType::setEnumeratedDataType(HLAEnumeratedDataType* dataType)
+{
+    _enumeratedDataType = dataType;
+}
+
+bool
+HLAVariantDataType::addAlternative(const std::string& name, const std::string& enumerator,
+                                   const HLADataType* dataType, const std::string& semantics)
+{
+    if (!_enumeratedDataType.valid())
+        return false;
+    unsigned index = _enumeratedDataType->getIndex(enumerator);
+    if (_enumeratedDataType->getNumEnumerators() <= index)
+        return false;
+    _alternativeList.resize(_enumeratedDataType->getNumEnumerators());
+    _alternativeList[index]._name = name;
+    _alternativeList[index]._dataType = dataType;
+    _alternativeList[index]._semantics = semantics;
+    setAlignment(SGMisc<unsigned>::max(getAlignment(), dataType->getAlignment()));
+    return true;
+}
+
+} // namespace simgear
diff --git a/simgear/hla/HLAVariantDataType.hxx b/simgear/hla/HLAVariantDataType.hxx
new file mode 100644 (file)
index 0000000..59b4aac
--- /dev/null
@@ -0,0 +1,102 @@
+// Copyright (C) 2009 - 2010  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 HLAVariantDataType_hxx
+#define HLAVariantDataType_hxx
+
+#include <string>
+#include <vector>
+#include "simgear/structure/SGSharedPtr.hxx"
+#include "HLADataType.hxx"
+#include "HLAEnumeratedDataType.hxx"
+
+namespace simgear {
+
+class HLAAbstractVariantDataElement;
+
+class HLAVariantDataType : public HLADataType {
+public:
+    HLAVariantDataType(const std::string& name = "HLAVariantDataType");
+    virtual ~HLAVariantDataType();
+
+    virtual void accept(HLADataTypeVisitor& visitor) const;
+
+    virtual const HLAVariantDataType* toVariantDataType() const;
+
+    virtual bool decode(HLADecodeStream& stream, HLAAbstractVariantDataElement& value) const;
+    virtual bool encode(HLAEncodeStream& stream, const HLAAbstractVariantDataElement& value) const;
+
+    const HLAEnumeratedDataType* getEnumeratedDataType() const
+    { return _enumeratedDataType.get(); }
+    void setEnumeratedDataType(HLAEnumeratedDataType* dataType);
+
+    bool addAlternative(const std::string& name, const std::string& enumerator,
+                        const HLADataType* dataType, const std::string& semantics);
+
+    unsigned getNumAlternatives() const
+    { return _alternativeList.size(); }
+
+    unsigned getAlternativeIndex(const std::string& enumerator) const
+    {
+        if (!_enumeratedDataType.valid())
+            return ~unsigned(0);
+        return _enumeratedDataType->getIndex(enumerator);
+    }
+
+    const HLADataType* getAlternativeDataType(unsigned index) const
+    {
+        if (_alternativeList.size() <= index)
+            return 0;
+        return _alternativeList[index]._dataType.get();
+    }
+    const HLADataType* getAlternativeDataType(const std::string& enumerator) const
+    { return getAlternativeDataType(getAlternativeIndex(enumerator)); }
+
+    std::string getAlternativeName(unsigned index) const
+    {
+        if (_alternativeList.size() <= index)
+            return std::string();
+        return _alternativeList[index]._name;
+    }
+    std::string getAlternativeName(const std::string& enumerator) const
+    { return getAlternativeName(getAlternativeIndex(enumerator)); }
+
+    std::string getAlternativeSemantics(unsigned index) const
+    {
+        if (_alternativeList.size() <= index)
+            return std::string();
+        return _alternativeList[index]._semantics;
+    }
+    std::string getAlternativeSemantics(const std::string& enumerator) const
+    { return getAlternativeSemantics(getAlternativeIndex(enumerator)); }
+
+private:
+    SGSharedPtr<HLAEnumeratedDataType> _enumeratedDataType;
+
+    struct Alternative {
+        std::string _name;
+        SGSharedPtr<const HLADataType> _dataType;
+        std::string _semantics;
+    };
+
+    typedef std::vector<Alternative> AlternativeList;
+    AlternativeList _alternativeList;
+};
+
+} // namespace simgear
+
+#endif
index 32ba395355fef166910bff04c6309025df561cfc..e4af153109319ef5aeab332e9d3774008c62d7e8 100644 (file)
@@ -1,3 +1,69 @@
-includedir = @includedir@/hla
-
 INCLUDES = -I$(top_srcdir)
+
+lib_LIBRARIES = libsghla.a
+
+libsghla_adir = @includedir@/hla
+
+libsghla_a_HEADERS = \
+       RTIData.hxx \
+       HLAArrayDataElement.hxx \
+       HLAArrayDataType.hxx \
+       HLABasicDataElement.hxx \
+       HLABasicDataType.hxx \
+       HLADataElement.hxx \
+       HLADataType.hxx \
+       HLADataTypeVisitor.hxx \
+       HLAEnumeratedDataElement.hxx \
+       HLAEnumeratedDataType.hxx \
+       HLAFixedRecordDataElement.hxx \
+       HLAFixedRecordDataType.hxx \
+       HLAFederate.hxx \
+       HLAInteractionClass.hxx \
+       HLALocation.hxx \
+       HLAObjectClass.hxx \
+       HLAObjectInstance.hxx \
+       HLAOMTXmlVisitor.hxx \
+       HLAPropertyDataElement.hxx \
+       HLARawDataElement.hxx \
+       HLAVariantDataElement.hxx \
+       HLAVariantDataType.hxx
+
+libsghla_a_SOURCES = \
+       RTIObjectClass.cxx \
+       RTIObjectInstance.cxx \
+       RTIFederate.cxx \
+       HLAArrayDataElement.cxx \
+       HLAArrayDataType.cxx \
+       HLABasicDataElement.cxx \
+       HLABasicDataType.cxx \
+       HLADataElement.cxx \
+       HLADataType.cxx \
+       HLAEnumeratedDataElement.cxx \
+       HLAEnumeratedDataType.cxx \
+       HLAFederate.cxx \
+       HLAFixedRecordDataElement.cxx \
+       HLAFixedRecordDataType.cxx \
+       HLAObjectClass.cxx \
+       HLAObjectInstance.cxx \
+       HLAOMTXmlVisitor.cxx \
+       HLAPropertyDataElement.cxx \
+       HLARawDataElement.cxx \
+       HLAVariantDataElement.cxx \
+       HLAVariantDataType.cxx
+
+if ENABLE_HLA13
+
+lib_LIBRARIES += libsghla13.a
+
+libsghla13_adir = @includedir@/hla
+
+libsghla13_a_HEADERS = \
+       HLA13Federate.hxx
+
+libsghla13_a_SOURCES = \
+       RTI13ObjectClass.cxx \
+       RTI13ObjectInstance.cxx \
+       RTI13Federate.cxx \
+       HLA13Federate.cxx
+
+endif
diff --git a/simgear/hla/RTI13Ambassador.hxx b/simgear/hla/RTI13Ambassador.hxx
new file mode 100644 (file)
index 0000000..0415c4a
--- /dev/null
@@ -0,0 +1,1115 @@
+// Copyright (C) 2009 - 2010  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 RTIAmbassador_hxx
+#define RTIAmbassador_hxx
+
+#include <cstdlib>
+#include <list>
+#include <memory>
+#include <vector>
+#include <map>
+#include <set>
+
+#ifndef RTI_USES_STD_FSTREAM
+#define RTI_USES_STD_FSTREAM
+#endif
+
+#include <RTI.hh>
+#include <fedtime.hh>
+
+#include <simgear/debug/logstream.hxx>
+#include <simgear/structure/SGWeakReferenced.hxx>
+#include <simgear/structure/SGSharedPtr.hxx>
+#include <simgear/structure/SGWeakPtr.hxx>
+#include <simgear/timing/timestamp.hxx>
+
+#include "RTIObjectClass.hxx"
+#include "RTIData.hxx"
+#include "RTI13Federate.hxx"
+#include "RTI13ObjectInstance.hxx"
+
+namespace simgear {
+
+class RTI13Ambassador : public SGWeakReferenced {
+public:
+    RTI13Ambassador() :
+        _federateAmbassador(*this),
+        _timeRegulationEnabled(false),
+        _timeConstrainedEnabled(false),
+        _timeAdvancePending(false)
+    { }
+    virtual ~RTI13Ambassador()
+    { }
+
+    // processes the queues that filled up during the past
+    void processQueues()
+    {
+        while (!_queueCallbackList.empty()) {
+            (*_queueCallbackList.front())();
+            _queueCallbackList.pop_front();
+        }
+
+        while (!_objectInstancePendingCallbackList.empty()) {
+            (*_objectInstancePendingCallbackList.begin())->flushPendingRequests();
+            _objectInstancePendingCallbackList.erase(_objectInstancePendingCallbackList.begin());
+        }
+    }
+
+    bool getTimeRegulationEnabled() const
+    { return _timeRegulationEnabled; }
+    bool getTimeConstrainedEnabled() const
+    { return _timeConstrainedEnabled; }
+    bool getTimeAdvancePending() const
+    { return _timeAdvancePending; }
+    const SGTimeStamp& getCurrentLogicalTime() const
+    { return _federateTime; }
+
+    bool getFederationSynchronizationPointAnnounced(const std::string& label)
+    { return _pendingSyncLabels.find(label) != _pendingSyncLabels.end(); }
+    bool getFederationSynchronized(const std::string& label)
+    {
+        std::set<std::string>::iterator i = _syncronizedSyncLabels.find(label);
+        if (i == _syncronizedSyncLabels.end())
+            return false;
+        _syncronizedSyncLabels.erase(i);
+        return true;
+    }
+
+    void createFederationExecution(const std::string& name, const std::string& objectModel)
+    { _rtiAmbassador.createFederationExecution(name.c_str(), objectModel.c_str()); }
+    void destroyFederationExecution(const std::string& name)
+    { _rtiAmbassador.destroyFederationExecution(name.c_str()); }
+
+    RTI::FederateHandle joinFederationExecution(const std::string& federate, const std::string& federation)
+    { return _rtiAmbassador.joinFederationExecution(federate.c_str(), federation.c_str(), &_federateAmbassador); }
+    void resignFederationExecution()
+    { _rtiAmbassador.resignFederationExecution(RTI::DELETE_OBJECTS_AND_RELEASE_ATTRIBUTES); }
+
+    void registerFederationSynchronizationPoint(const std::string& label, const RTIData& tag)
+    { _rtiAmbassador.registerFederationSynchronizationPoint(label.c_str(), tag.data()); }
+    void synchronizationPointAchieved(const std::string& label)
+    { _rtiAmbassador.synchronizationPointAchieved(label.c_str()); }
+
+    void publishObjectClass(const RTI::ObjectClassHandle& handle, const RTI::AttributeHandleSet& attributeHandleSet)
+    { _rtiAmbassador.publishObjectClass(handle, attributeHandleSet); }
+    void unpublishObjectClass(const RTI::ObjectClassHandle& handle)
+    { _rtiAmbassador.unpublishObjectClass(handle); }
+    void subscribeObjectClassAttributes(const RTI::ObjectClassHandle& handle, const RTI::AttributeHandleSet& attributeHandleSet, bool active)
+    { _rtiAmbassador.subscribeObjectClassAttributes(handle, attributeHandleSet, active ? RTI::RTI_TRUE : RTI::RTI_FALSE); }
+    void unsubscribeObjectClass(const RTI::ObjectClassHandle& handle)
+    { _rtiAmbassador.unsubscribeObjectClass(handle); }
+
+    RTI13ObjectInstance* registerObjectInstance(const RTI13ObjectClass* objectClass, HLAObjectInstance* hlaObjectInstance)
+    {
+        RTI::ObjectHandle objectHandle = _rtiAmbassador.registerObjectInstance(objectClass->getHandle());
+        RTI13ObjectInstance* objectInstance = new RTI13ObjectInstance(objectHandle, hlaObjectInstance, objectClass, this, true);
+        _objectInstanceMap[objectHandle] = objectInstance;
+        return objectInstance;
+    }
+    void updateAttributeValues(const RTI::ObjectHandle& objectHandle, const RTI::AttributeHandleValuePairSet& attributeValues,
+                               const SGTimeStamp& timeStamp, const RTIData& tag)
+    { _rtiAmbassador.updateAttributeValues(objectHandle, attributeValues, toFedTime(timeStamp), tag.data()); }
+    void updateAttributeValues(const RTI::ObjectHandle& objectHandle, const RTI::AttributeHandleValuePairSet& attributeValues, const RTIData& tag)
+    { _rtiAmbassador.updateAttributeValues(objectHandle, attributeValues, tag.data()); }
+
+    // RTI::EventRetractionHandle sendInteraction(RTI::InteractionClassHandle interactionClassHandle, const RTI::ParameterHandleValuePairSet& parameters, const RTI::FedTime& fedTime, const RTIData& tag)
+    // { return _rtiAmbassador.sendInteraction(interactionClassHandle, parameters, fedTime, tag.data()); }
+    // void sendInteraction(RTI::InteractionClassHandle interactionClassHandle, const RTI::ParameterHandleValuePairSet& parameters, const RTIData& tag)
+    // { _rtiAmbassador.sendInteraction(interactionClassHandle, parameters, tag.data()); }
+
+    void deleteObjectInstance(const RTI::ObjectHandle& objectHandle, const SGTimeStamp& timeStamp, const RTIData& tag)
+    {
+        RTI::EventRetractionHandle h = _rtiAmbassador.deleteObjectInstance(objectHandle, toFedTime(timeStamp), tag.data());
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end()) {
+            SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: ObjectInstance not found.");
+            return;
+        }
+        _objectInstancePendingCallbackList.erase(i->second);
+        _objectInstanceMap.erase(i);
+    }
+    void deleteObjectInstance(const RTI::ObjectHandle& objectHandle, const RTIData& tag)
+    {
+        _rtiAmbassador.deleteObjectInstance(objectHandle, tag.data());
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end()) {
+            SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: ObjectInstance not found.");
+            return;
+        }
+        _objectInstancePendingCallbackList.erase(i->second);
+        _objectInstanceMap.erase(i);
+    }
+    void localDeleteObjectInstance(const RTI::ObjectHandle& objectHandle)
+    {
+        _rtiAmbassador.localDeleteObjectInstance(objectHandle);
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end()) {
+            SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: ObjectInstance not found.");
+            return;
+        }
+        _objectInstancePendingCallbackList.erase(i->second);
+        _objectInstanceMap.erase(i);
+    }
+
+    void requestObjectAttributeValueUpdate(const RTI::ObjectHandle& handle, const RTI::AttributeHandleSet& attributeHandleSet)
+    { _rtiAmbassador.requestObjectAttributeValueUpdate(handle, attributeHandleSet); }
+    void requestClassAttributeValueUpdate(const RTI::ObjectClassHandle& handle, const RTI::AttributeHandleSet& attributeHandleSet)
+    { _rtiAmbassador.requestClassAttributeValueUpdate(handle, attributeHandleSet); }
+
+    // Ownership Management -------------------
+
+    // bool unconditionalAttributeOwnershipDivestiture(const RTIHandle& objectHandle, const RTIHandleSet& attributeHandles)
+    // {
+    //     try {
+    //         std::auto_ptr<RTI::AttributeHandleSet> attributeHandleSet(RTI::AttributeHandleSetFactory::create(attributeHandles.size()));
+    //         for (RTIHandleSet::const_iterator i = attributeHandles.begin(); i != attributeHandles.end(); ++i)
+    //             attributeHandleSet->add(*i);
+    //         _rtiAmbassador.unconditionalAttributeOwnershipDivestiture(objectHandle, *attributeHandleSet);
+    //         return true;
+    //     } catch (RTI::ObjectNotKnown& e) {
+    //     } catch (RTI::AttributeNotDefined& e) {
+    //     } catch (RTI::AttributeNotOwned& e) {
+    //     } catch (RTI::FederateNotExecutionMember& e) {
+    //     } catch (RTI::ConcurrentAccessAttempted& e) {
+    //     } catch (RTI::SaveInProgress& e) {
+    //     } catch (RTI::RestoreInProgress& e) {
+    //     } catch (RTI::RTIinternalError& e) {
+    //     }
+    //     return false;
+    // }
+    // bool negotiatedAttributeOwnershipDivestiture(const RTIHandle& objectHandle, const RTIHandleSet& attributeHandles, const RTIData& tag)
+    // {
+    //     try {
+    //         std::auto_ptr<RTI::AttributeHandleSet> attributeHandleSet(RTI::AttributeHandleSetFactory::create(attributeHandles.size()));
+    //         for (RTIHandleSet::const_iterator i = attributeHandles.begin(); i != attributeHandles.end(); ++i)
+    //             attributeHandleSet->add(*i);
+    //         _rtiAmbassador.negotiatedAttributeOwnershipDivestiture(objectHandle, *attributeHandleSet, tag.data());
+    //         return true;
+    //     } catch (RTI::ObjectNotKnown& e) {
+    //     } catch (RTI::AttributeNotDefined& e) {
+    //     } catch (RTI::AttributeNotOwned& e) {
+    //     } catch (RTI::AttributeAlreadyBeingDivested& e) {
+    //     } catch (RTI::FederateNotExecutionMember& e) {
+    //     } catch (RTI::ConcurrentAccessAttempted& e) {
+    //     } catch (RTI::SaveInProgress& e) {
+    //     } catch (RTI::RestoreInProgress& e) {
+    //     } catch (RTI::RTIinternalError& e) {
+    //     }
+    //     return false;
+    // }
+    // bool attributeOwnershipAcquisition(const RTIHandle& objectHandle, const RTIHandleSet& attributeHandles, const RTIData& tag)
+    // {
+    //     try {
+    //         std::auto_ptr<RTI::AttributeHandleSet> attributeHandleSet(RTI::AttributeHandleSetFactory::create(attributeHandles.size()));
+    //         for (RTIHandleSet::const_iterator i = attributeHandles.begin(); i != attributeHandles.end(); ++i)
+    //             attributeHandleSet->add(*i);
+    //         _rtiAmbassador.attributeOwnershipAcquisition(objectHandle, *attributeHandleSet, tag.data());
+    //         return true;
+    //     } catch (RTI::ObjectNotKnown& e) {
+    //     } catch (RTI::ObjectClassNotPublished& e) {
+    //     } catch (RTI::AttributeNotDefined& e) {
+    //     } catch (RTI::AttributeNotPublished& e) {
+    //     } catch (RTI::FederateOwnsAttributes& e) {
+    //     } catch (RTI::FederateNotExecutionMember& e) {
+    //     } catch (RTI::ConcurrentAccessAttempted& e) {
+    //     } catch (RTI::SaveInProgress& e) {
+    //     } catch (RTI::RestoreInProgress& e) {
+    //     } catch (RTI::RTIinternalError& e) {
+    //     }
+    //     return false;
+    // }
+    // bool attributeOwnershipAcquisitionIfAvailable(const RTIHandle& objectHandle, const RTIHandleSet& attributeHandles)
+    // {
+    //     try {
+    //         std::auto_ptr<RTI::AttributeHandleSet> attributeHandleSet(RTI::AttributeHandleSetFactory::create(attributeHandles.size()));
+    //         for (RTIHandleSet::const_iterator i = attributeHandles.begin(); i != attributeHandles.end(); ++i)
+    //             attributeHandleSet->add(*i);
+    //         _rtiAmbassador.attributeOwnershipAcquisitionIfAvailable(objectHandle, *attributeHandleSet);
+    //         return true;
+    //     } catch (RTI::ObjectNotKnown& e) {
+    //     } catch (RTI::ObjectClassNotPublished& e) {
+    //     } catch (RTI::AttributeNotDefined& e) {
+    //     } catch (RTI::AttributeNotPublished& e) {
+    //     } catch (RTI::FederateOwnsAttributes& e) {
+    //     } catch (RTI::AttributeAlreadyBeingAcquired& e) {
+    //     } catch (RTI::FederateNotExecutionMember& e) {
+    //     } catch (RTI::ConcurrentAccessAttempted& e) {
+    //     } catch (RTI::SaveInProgress& e) {
+    //     } catch (RTI::RestoreInProgress& e) {
+    //     } catch (RTI::RTIinternalError& e) {
+    //     }
+    //     return false;
+    // }
+    // RTIHandleSet attributeOwnershipReleaseResponse(const RTIHandle& objectHandle, const RTIHandleSet& attributeHandles)
+    // {
+    //     try {
+    //         std::auto_ptr<RTI::AttributeHandleSet> attributeHandleSet(RTI::AttributeHandleSetFactory::create(attributeHandles.size()));
+    //         for (RTIHandleSet::const_iterator i = attributeHandles.begin(); i != attributeHandles.end(); ++i)
+    //             attributeHandleSet->add(*i);
+    //         attributeHandleSet.reset(_rtiAmbassador.attributeOwnershipReleaseResponse(objectHandle, *attributeHandleSet));
+    //         RTIHandleSet handleSet;
+    //         RTI::ULong numAttribs = attributeHandleSet->size();
+    //         for (RTI::ULong i = 0; i < numAttribs; ++i)
+    //             handleSet.insert(attributeHandleSet->getHandle(i));
+    //         return handleSet;
+    //     } catch (RTI::ObjectNotKnown& e) {
+    //     } catch (RTI::AttributeNotDefined& e) {
+    //     } catch (RTI::AttributeNotOwned& e) {
+    //     } catch (RTI::FederateWasNotAskedToReleaseAttribute& e) {
+    //     } catch (RTI::FederateNotExecutionMember& e) {
+    //     } catch (RTI::ConcurrentAccessAttempted& e) {
+    //     } catch (RTI::SaveInProgress& e) {
+    //     } catch (RTI::RestoreInProgress& e) {
+    //     } catch (RTI::RTIinternalError& e) {
+    //     }
+    //     return RTIHandleSet();
+    // }
+    // bool cancelNegotiatedAttributeOwnershipDivestiture(const RTIHandle& objectHandle, const RTIHandleSet& attributeHandles)
+    // {
+    //     try {
+    //         std::auto_ptr<RTI::AttributeHandleSet> attributeHandleSet(RTI::AttributeHandleSetFactory::create(attributeHandles.size()));
+    //         for (RTIHandleSet::const_iterator i = attributeHandles.begin(); i != attributeHandles.end(); ++i)
+    //             attributeHandleSet->add(*i);
+    //         _rtiAmbassador.cancelNegotiatedAttributeOwnershipDivestiture(objectHandle, *attributeHandleSet);
+    //         return true;
+    //     } catch (RTI::ObjectNotKnown& e) {
+    //     } catch (RTI::AttributeNotDefined& e) {
+    //     } catch (RTI::AttributeNotOwned& e) {
+    //     } catch (RTI::AttributeDivestitureWasNotRequested& e) {
+    //     } catch (RTI::FederateNotExecutionMember& e) {
+    //     } catch (RTI::ConcurrentAccessAttempted& e) {
+    //     } catch (RTI::SaveInProgress& e) {
+    //     } catch (RTI::RestoreInProgress& e) {
+    //     } catch (RTI::RTIinternalError& e) {
+    //     }
+    //     return false;
+    // }
+    // bool cancelAttributeOwnershipAcquisition(const RTIHandle& objectHandle, const RTIHandleSet& attributeHandles)
+    // {
+    //     try {
+    //         std::auto_ptr<RTI::AttributeHandleSet> attributeHandleSet(RTI::AttributeHandleSetFactory::create(attributeHandles.size()));
+    //         for (RTIHandleSet::const_iterator i = attributeHandles.begin(); i != attributeHandles.end(); ++i)
+    //             attributeHandleSet->add(*i);
+    //         _rtiAmbassador.cancelAttributeOwnershipAcquisition(objectHandle, *attributeHandleSet);
+    //         return true;
+    //     } catch (RTI::ObjectNotKnown& e) {
+    //     } catch (RTI::AttributeNotDefined& e) {
+    //     } catch (RTI::AttributeAlreadyOwned& e) {
+    //     } catch (RTI::AttributeAcquisitionWasNotRequested& e) {
+    //     } catch (RTI::FederateNotExecutionMember& e) {
+    //     } catch (RTI::ConcurrentAccessAttempted& e) {
+    //     } catch (RTI::SaveInProgress& e) {
+    //     } catch (RTI::RestoreInProgress& e) {
+    //     } catch (RTI::RTIinternalError& e) {
+    //     }
+    //     return false;
+    // }
+    // bool queryAttributeOwnership(const RTIHandle& objectHandle, const RTIHandle& attributeHandle)
+    // {
+    //     try {
+    //         _rtiAmbassador.queryAttributeOwnership(objectHandle, attributeHandle);
+    //         return true;
+    //     } catch (RTI::ObjectNotKnown& e) {
+    //     } catch (RTI::AttributeNotDefined& e) {
+    //     } catch (RTI::FederateNotExecutionMember& e) {
+    //     } catch (RTI::ConcurrentAccessAttempted& e) {
+    //     } catch (RTI::SaveInProgress& e) {
+    //     } catch (RTI::RestoreInProgress& e) {
+    //     } catch (RTI::RTIinternalError& e) {
+    //     }
+    //     return false;
+    // }
+    // bool isAttributeOwnedByFederate(const RTIHandle& objectHandle, const RTIHandle& attributeHandle)
+    // {
+    //     try {
+    //         return _rtiAmbassador.isAttributeOwnedByFederate(objectHandle, attributeHandle);
+    //     } catch (RTI::ObjectNotKnown& e) {
+    //     } catch (RTI::AttributeNotDefined& e) {
+    //     } catch (RTI::FederateNotExecutionMember& e) {
+    //     } catch (RTI::ConcurrentAccessAttempted& e) {
+    //     } catch (RTI::SaveInProgress& e) {
+    //     } catch (RTI::RestoreInProgress& e) {
+    //     } catch (RTI::RTIinternalError& e) {
+    //     }
+    //     return false;
+    // }
+
+    /// Time Management
+
+    void enableTimeRegulation(const SGTimeStamp& federateTime, const SGTimeStamp& lookahead)
+    { _rtiAmbassador.enableTimeRegulation(toFedTime(federateTime), toFedTime(lookahead)); }
+    void disableTimeRegulation()
+    { _rtiAmbassador.disableTimeRegulation(); _timeRegulationEnabled = false; }
+
+    void enableTimeConstrained()
+    { _rtiAmbassador.enableTimeConstrained(); }
+    void disableTimeConstrained()
+    { _rtiAmbassador.disableTimeConstrained(); _timeConstrainedEnabled = false; }
+
+    void timeAdvanceRequest(const SGTimeStamp& time)
+    { _rtiAmbassador.timeAdvanceRequest(toFedTime(time)); _timeAdvancePending = true; }
+    void timeAdvanceRequestAvailable(const SGTimeStamp& time)
+    { _rtiAmbassador.timeAdvanceRequestAvailable(toFedTime(time)); _timeAdvancePending = true; }
+
+    // bool queryLBTS(double& time)
+    // {
+    //     try {
+    //         RTIfedTime fedTime;
+    //         _rtiAmbassador.queryLBTS(fedTime);
+    //         time = fedTime.getTime();
+    //         return true;
+    //     } catch (RTI::FederateNotExecutionMember& e) {
+    //     } catch (RTI::ConcurrentAccessAttempted& e) {
+    //     } catch (RTI::SaveInProgress& e) {
+    //     } catch (RTI::RestoreInProgress& e) {
+    //     } catch (RTI::RTIinternalError& e) {
+    //     }
+    //     return false;
+    // }
+    // bool queryFederateTime(double& time)
+    // {
+    //     try {
+    //         RTIfedTime fedTime;
+    //         _rtiAmbassador.queryFederateTime(fedTime);
+    //         time = fedTime.getTime();
+    //         return true;
+    //     } catch (RTI::FederateNotExecutionMember& e) {
+    //     } catch (RTI::ConcurrentAccessAttempted& e) {
+    //     } catch (RTI::SaveInProgress& e) {
+    //     } catch (RTI::RestoreInProgress& e) {
+    //     } catch (RTI::RTIinternalError& e) {
+    //     }
+    //     return false;
+    // }
+
+    // bool queryLookahead(double& time)
+    // {
+    //     try {
+    //         RTIfedTime fedTime;
+    //         _rtiAmbassador.queryLookahead(fedTime);
+    //         time = fedTime.getTime();
+    //         return true;
+    //     } catch (RTI::FederateNotExecutionMember& e) {
+    //     } catch (RTI::ConcurrentAccessAttempted& e) {
+    //     } catch (RTI::SaveInProgress& e) {
+    //     } catch (RTI::RestoreInProgress& e) {
+    //     } catch (RTI::RTIinternalError& e) {
+    //     }
+    //     return false;
+    // }
+
+    RTI13ObjectClass* createObjectClass(const std::string& name, HLAObjectClass* hlaObjectClass)
+    {
+        RTI::ObjectClassHandle objectClassHandle;
+        objectClassHandle = getObjectClassHandle(name);
+        if (_objectClassMap.find(objectClassHandle) != _objectClassMap.end()) {
+            SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not create object class, object class already exists!");
+            return 0;
+        }
+        RTI13ObjectClass* rtiObjectClass;
+        rtiObjectClass = new RTI13ObjectClass(hlaObjectClass, objectClassHandle, this);
+        _objectClassMap[objectClassHandle] = rtiObjectClass;
+        return rtiObjectClass;
+    }
+    RTI::ObjectClassHandle getObjectClassHandle(const std::string& name)
+    { return _rtiAmbassador.getObjectClassHandle(name.c_str()); }
+    std::string getObjectClassName(const RTI::ObjectClassHandle& handle)
+    { return rtiToStdString(_rtiAmbassador.getObjectClassName(handle)); }
+
+    RTI::AttributeHandle getAttributeHandle(const std::string& attributeName, const RTI::ObjectClassHandle& objectClassHandle)
+    { return _rtiAmbassador.getAttributeHandle(attributeName.c_str(), objectClassHandle); }
+    std::string getAttributeName(const RTI::AttributeHandle& attributeHandle, const RTI::ObjectClassHandle& objectClassHandle)
+    { return rtiToStdString(_rtiAmbassador.getAttributeName(attributeHandle, objectClassHandle)); }
+
+    // RTIHandle getInteractionClassHandle(const std::string& name)
+    // {
+    //     try {
+    //         return _rtiAmbassador.getInteractionClassHandle(name.c_str());
+    //     } catch (RTI::NameNotFound& e) {
+    //     } catch (RTI::FederateNotExecutionMember& e) {
+    //     } catch (RTI::ConcurrentAccessAttempted& e) {
+    //     } catch (RTI::RTIinternalError& e) {
+    //     }
+    //     return RTIHandle(-1);
+    // }
+    // std::string getInteractionClassName(const RTIHandle& handle)
+    // {
+    //     std::string name;
+    //     try {
+    //         rtiToStdString(name, _rtiAmbassador.getInteractionClassName(handle));
+    //     } catch (RTI::InteractionClassNotDefined& e) {
+    //     } catch (RTI::FederateNotExecutionMember& e) {
+    //     } catch (RTI::ConcurrentAccessAttempted& e) {
+    //     } catch (RTI::RTIinternalError& e) {
+    //     }
+    //     return name;
+    // }
+
+    // RTIHandle getParameterHandle(const std::string& parameterName, const RTIHandle& interactionClassHandle)
+    // {
+    //     try {
+    //         return _rtiAmbassador.getParameterHandle(parameterName.c_str(), interactionClassHandle);
+    //     } catch (RTI::InteractionClassNotDefined& e) {
+    //     } catch (RTI::NameNotFound& e) {
+    //     } catch (RTI::FederateNotExecutionMember& e) {
+    //     } catch (RTI::ConcurrentAccessAttempted& e) {
+    //     } catch (RTI::RTIinternalError& e) {
+    //     }
+    //     return RTIHandle(-1);
+    // }
+    // std::string getParameterName(const RTIHandle& parameterHandle, const RTIHandle& interactionClassHandle)
+    // {
+    //     std::string parameterName;
+    //     try {
+    //         rtiToStdString(parameterName, _rtiAmbassador.getParameterName(parameterHandle, interactionClassHandle));
+    //     } catch (RTI::InteractionClassNotDefined& e) {
+    //     } catch (RTI::InteractionParameterNotDefined& e) {
+    //     } catch (RTI::FederateNotExecutionMember& e) {
+    //     } catch (RTI::ConcurrentAccessAttempted& e) {
+    //     } catch (RTI::RTIinternalError& e) {
+    //     }
+    //     return parameterName;
+    // }
+
+    RTI13ObjectInstance* getObjectInstance(const std::string& name)
+    {
+        RTI::ObjectHandle objectHandle;
+        objectHandle = getObjectInstanceHandle(name);
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end()) {
+            SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: ObjectInstance not found.");
+            return 0;
+        }
+        return i->second;
+    }
+    RTI::ObjectHandle getObjectInstanceHandle(const std::string& name)
+    { return _rtiAmbassador.getObjectInstanceHandle(name.c_str()); }
+    std::string getObjectInstanceName(const RTI::ObjectHandle& objectHandle)
+    { return rtiToStdString(_rtiAmbassador.getObjectInstanceName(objectHandle)); }
+
+    // RTIHandle getRoutingSpaceHandle(const std::string& routingSpaceName)
+    // {
+    //     try {
+    //         return _rtiAmbassador.getRoutingSpaceHandle(routingSpaceName.c_str());
+    //     } catch (RTI::NameNotFound& e) {
+    //     } catch (RTI::FederateNotExecutionMember& e) {
+    //     } catch (RTI::ConcurrentAccessAttempted& e) {
+    //     } catch (RTI::RTIinternalError& e) {
+    //     }
+    //     return RTIHandle(-1);
+    // }
+    // std::string getRoutingSpaceName(const RTIHandle& routingSpaceHandle)
+    // {
+    //     std::string routingSpaceName;
+    //     try {
+    //         rtiToStdString(routingSpaceName, _rtiAmbassador.wgetRoutingSpaceName(routingSpaceHandle));
+    //     } catch (RTI::SpaceNotDefined& e) {
+    //     } catch (RTI::FederateNotExecutionMember& e) {
+    //     } catch (RTI::ConcurrentAccessAttempted& e) {
+    //     } catch (RTI::RTIinternalError& e) {
+    //     }
+    //     return routingSpaceName;
+    // }
+
+    void enableClassRelevanceAdvisorySwitch()
+    { _rtiAmbassador.enableClassRelevanceAdvisorySwitch(); }
+    void disableClassRelevanceAdvisorySwitch()
+    { _rtiAmbassador.disableClassRelevanceAdvisorySwitch(); }
+
+    void enableAttributeRelevanceAdvisorySwitch()
+    { _rtiAmbassador.enableAttributeRelevanceAdvisorySwitch(); }
+    void disableAttributeRelevanceAdvisorySwitch()
+    { _rtiAmbassador.disableAttributeRelevanceAdvisorySwitch(); }
+
+    void enableAttributeScopeAdvisorySwitch()
+    { _rtiAmbassador.enableAttributeScopeAdvisorySwitch(); }
+    void disableAttributeScopeAdvisorySwitch()
+    { _rtiAmbassador.disableAttributeScopeAdvisorySwitch(); }
+
+    void enableInteractionRelevanceAdvisorySwitch()
+    { _rtiAmbassador.enableInteractionRelevanceAdvisorySwitch(); }
+    void disableInteractionRelevanceAdvisorySwitch()
+    { _rtiAmbassador.disableInteractionRelevanceAdvisorySwitch(); }
+
+
+    bool tick()
+    { return _rtiAmbassador.tick(); }
+    bool tick(double minimum, double maximum)
+    { return _rtiAmbassador.tick(minimum, maximum); }
+
+    void addObjectInstanceForCallback(RTIObjectInstance* objectIntance)
+    { _objectInstancePendingCallbackList.insert(objectIntance); }
+
+private:
+    /// Generic callback to execute some notification on objects in a way that they are not prone to
+    /// ConcurrentAccess exceptions.
+    class QueueCallback : public SGReferenced {
+    public:
+        virtual ~QueueCallback() {}
+        virtual void operator()() = 0;
+    };
+
+    class RemoveObjectCallback : public QueueCallback {
+    public:
+        RemoveObjectCallback(SGSharedPtr<RTIObjectInstance> objectInstance, const RTIData& tag) :
+            _objectInstance(objectInstance),
+            _tag(tag)
+        { }
+        virtual void operator()()
+        {
+            _objectInstance->removeInstance(_tag);
+        }
+    private:
+        SGSharedPtr<RTIObjectInstance> _objectInstance;
+        RTIData _tag;
+    };
+
+    /// Just the interface class doing the callbacks into the parent class
+    struct FederateAmbassador : public RTI::FederateAmbassador {
+        FederateAmbassador(RTI13Ambassador& rtiAmbassador) :
+            _rtiAmbassador(rtiAmbassador)
+        {
+        }
+        virtual ~FederateAmbassador()
+        throw (RTI::FederateInternalError)
+        {
+        }
+
+        /// RTI federate ambassador callback functions.
+        virtual void synchronizationPointRegistrationSucceeded(const char* label)
+            throw (RTI::FederateInternalError)
+        {
+        }
+
+        virtual void synchronizationPointRegistrationFailed(const char* label)
+            throw (RTI::FederateInternalError)
+        {
+        }
+
+        virtual void announceSynchronizationPoint(const char* label, const char* tag)
+            throw (RTI::FederateInternalError)
+        {
+            _rtiAmbassador._pendingSyncLabels.insert(toStdString(label));
+        }
+
+        virtual void federationSynchronized(const char* label)
+            throw (RTI::FederateInternalError)
+        {
+            std::string s = toStdString(label);
+            _rtiAmbassador._pendingSyncLabels.erase(s);
+            _rtiAmbassador._syncronizedSyncLabels.insert(s);
+        }
+
+        virtual void initiateFederateSave(const char* label)
+            throw (RTI::UnableToPerformSave,
+                   RTI::FederateInternalError)
+        {
+        }
+
+        virtual void federationSaved()
+            throw (RTI::FederateInternalError)
+        {
+        }
+
+        virtual void federationNotSaved()
+            throw (RTI::FederateInternalError)
+        {
+        }
+
+        virtual void requestFederationRestoreSucceeded(const char* label)
+            throw (RTI::FederateInternalError)
+        {
+        }
+
+        virtual void requestFederationRestoreFailed(const char* label, const char* reason)
+            throw (RTI::FederateInternalError)
+        {
+        }
+
+        virtual void federationRestoreBegun()
+            throw (RTI::FederateInternalError)
+        {
+        }
+
+        virtual void initiateFederateRestore(const char* label, RTI::FederateHandle federateHandle)
+            throw (RTI::SpecifiedSaveLabelDoesNotExist,
+                   RTI::CouldNotRestore,
+                   RTI::FederateInternalError)
+        {
+        }
+
+        virtual void federationRestored()
+            throw (RTI::FederateInternalError)
+        {
+        }
+
+        virtual void federationNotRestored()
+            throw (RTI::FederateInternalError)
+        {
+        }
+
+        // Declaration Management
+        virtual void startRegistrationForObjectClass(RTI::ObjectClassHandle objectClassHandle)
+            throw (RTI::ObjectClassNotPublished,
+                   RTI::FederateInternalError)
+        {
+            ObjectClassMap::iterator i = _rtiAmbassador._objectClassMap.find(objectClassHandle);
+            if (i == _rtiAmbassador._objectClassMap.end())
+                return;
+            if (!i->second.valid())
+                return;
+            i->second->startRegistration();
+        }
+
+        virtual void stopRegistrationForObjectClass(RTI::ObjectClassHandle objectClassHandle)
+            throw (RTI::ObjectClassNotPublished,
+                   RTI::FederateInternalError)
+        {
+            ObjectClassMap::iterator i = _rtiAmbassador._objectClassMap.find(objectClassHandle);
+            if (i == _rtiAmbassador._objectClassMap.end())
+                return;
+            if (!i->second.valid())
+                return;
+            i->second->stopRegistration();
+        }
+
+        virtual void turnInteractionsOn(RTI::InteractionClassHandle interactionClassHandle)
+            throw (RTI::InteractionClassNotPublished,
+                   RTI::FederateInternalError)
+        {
+        }
+
+        virtual void turnInteractionsOff(RTI::InteractionClassHandle interactionClassHandle)
+            throw (RTI::InteractionClassNotPublished,
+                   RTI::FederateInternalError)
+        {
+        }
+
+
+        // Object Management
+        virtual void discoverObjectInstance(RTI::ObjectHandle objectHandle, RTI::ObjectClassHandle objectClassHandle, const char* tag)
+            throw (RTI::CouldNotDiscover,
+                   RTI::ObjectClassNotKnown,
+                   RTI::FederateInternalError)
+        {
+            ObjectClassMap::iterator i = _rtiAmbassador._objectClassMap.find(objectClassHandle);
+            if (i == _rtiAmbassador._objectClassMap.end())
+                throw RTI::ObjectClassNotKnown("Federate: discoverObjectInstance()!");
+            if (!i->second.valid())
+                return;
+            SGSharedPtr<RTI13ObjectInstance> objectInstance = new RTI13ObjectInstance(objectHandle, 0, i->second, &_rtiAmbassador, false);
+            _rtiAmbassador._objectInstanceMap[objectHandle] = objectInstance;
+            _rtiAmbassador._objectInstancePendingCallbackList.insert(objectInstance);
+            i->second->discoverInstance(objectInstance.get(), tagToData(tag));
+        }
+
+        virtual void reflectAttributeValues(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleValuePairSet& attributeValuePairSet,
+                                            const RTI::FedTime& fedTime, const char* tag, RTI::EventRetractionHandle eventRetractionHandle)
+            throw (RTI::ObjectNotKnown,
+                   RTI::AttributeNotKnown,
+                   RTI::FederateOwnsAttributes,
+                   RTI::InvalidFederationTime,
+                   RTI::FederateInternalError)
+        {
+            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
+            if (i == _rtiAmbassador._objectInstanceMap.end())
+                throw RTI::ObjectNotKnown("Reflect attributes for unknown object!");
+            if (!i->second.valid())
+                return;
+            i->second->reflectAttributeValues(attributeValuePairSet, toTimeStamp(fedTime), tagToData(tag));
+        }
+
+        virtual void reflectAttributeValues(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleValuePairSet& attributeValuePairSet,
+                                            const char* tag)
+            throw (RTI::ObjectNotKnown,
+                   RTI::AttributeNotKnown,
+                   RTI::FederateOwnsAttributes,
+                   RTI::FederateInternalError)
+        {
+            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
+            if (i == _rtiAmbassador._objectInstanceMap.end())
+                throw RTI::ObjectNotKnown("Reflect attributes for unknown object!");
+            if (!i->second.valid())
+                return;
+            i->second->reflectAttributeValues(attributeValuePairSet, tagToData(tag));
+        }
+
+        virtual void receiveInteraction(RTI::InteractionClassHandle interactionClassHandle, const RTI::ParameterHandleValuePairSet& parameters,
+                                        const RTI::FedTime& fedTime, const char* tag, RTI::EventRetractionHandle eventRetractionHandle)
+            throw (RTI::InteractionClassNotKnown,
+                   RTI::InteractionParameterNotKnown,
+                   RTI::InvalidFederationTime,
+                   RTI::FederateInternalError)
+        {
+        }
+
+        virtual void receiveInteraction(RTI::InteractionClassHandle interactionClassHandle,
+                                        const RTI::ParameterHandleValuePairSet& parameters, const char* tag)
+            throw (RTI::InteractionClassNotKnown,
+                   RTI::InteractionParameterNotKnown,
+                   RTI::FederateInternalError)
+        {
+        }
+
+        virtual void removeObjectInstance(RTI::ObjectHandle objectHandle, const RTI::FedTime& fedTime,
+                                          const char* tag, RTI::EventRetractionHandle eventRetractionHandle)
+            throw (RTI::ObjectNotKnown,
+                   RTI::InvalidFederationTime,
+                   RTI::FederateInternalError)
+        {
+            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
+            if (i == _rtiAmbassador._objectInstanceMap.end())
+                throw RTI::ObjectNotKnown("Federate: removeObjectInstance()!");
+            if (i->second.valid())
+                _rtiAmbassador._queueCallbackList.push_back(new RemoveObjectCallback(i->second, tagToData(tag)));
+            _rtiAmbassador._objectInstancePendingCallbackList.erase(i->second);
+            _rtiAmbassador._objectInstanceMap.erase(i);
+        }
+
+        virtual void removeObjectInstance(RTI::ObjectHandle objectHandle, const char* tag)
+            throw (RTI::ObjectNotKnown,
+                   RTI::FederateInternalError)
+        {
+            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
+            if (i == _rtiAmbassador._objectInstanceMap.end())
+                throw RTI::ObjectNotKnown("Federate: removeObjectInstance()!");
+            if (i->second.valid())
+                _rtiAmbassador._queueCallbackList.push_back(new RemoveObjectCallback(i->second, tagToData(tag)));
+            _rtiAmbassador._objectInstancePendingCallbackList.erase(i->second);
+            _rtiAmbassador._objectInstanceMap.erase(i);
+        }
+
+        virtual void attributesInScope(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+            throw (RTI::ObjectNotKnown,
+                   RTI::AttributeNotKnown,
+                   RTI::FederateInternalError)
+        {
+            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
+            if (i == _rtiAmbassador._objectInstanceMap.end())
+                throw RTI::ObjectNotKnown("Attributes in scope for unknown object!");
+            if (!i->second.valid())
+                return;
+            i->second->attributesInScope(attributes);
+        }
+
+        virtual void attributesOutOfScope(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+            throw (RTI::ObjectNotKnown,
+                   RTI::AttributeNotKnown,
+                   RTI::FederateInternalError)
+        {
+            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
+            if (i == _rtiAmbassador._objectInstanceMap.end())
+                throw RTI::ObjectNotKnown("Attributes in scope for unknown object!");
+            if (!i->second.valid())
+                return;
+            i->second->attributesOutOfScope(attributes);
+        }
+
+        virtual void provideAttributeValueUpdate(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+            throw (RTI::ObjectNotKnown,
+                   RTI::AttributeNotKnown,
+                   RTI::AttributeNotOwned,
+                   RTI::FederateInternalError)
+        {
+            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
+            if (i == _rtiAmbassador._objectInstanceMap.end())
+                throw RTI::ObjectNotKnown("Reflect attributes for unknown object!");
+            if (!i->second.valid())
+                return;
+            i->second->provideAttributeValueUpdate(attributes);
+        }
+
+        virtual void turnUpdatesOnForObjectInstance(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+            throw (RTI::ObjectNotKnown,
+                   RTI::AttributeNotOwned,
+                   RTI::FederateInternalError)
+        {
+            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
+            if (i == _rtiAmbassador._objectInstanceMap.end())
+                throw RTI::ObjectNotKnown("Turn on attributes for unknown object!");
+            if (!i->second.valid())
+                return;
+            i->second->turnUpdatesOnForObjectInstance(attributes);
+        }
+
+        virtual void turnUpdatesOffForObjectInstance(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+            throw (RTI::ObjectNotKnown,
+                   RTI::AttributeNotOwned,
+                   RTI::FederateInternalError)
+        {
+            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
+            if (i == _rtiAmbassador._objectInstanceMap.end())
+                throw RTI::ObjectNotKnown("Turn off attributes for unknown object!");
+            if (!i->second.valid())
+                return;
+            i->second->turnUpdatesOffForObjectInstance(attributes);
+        }
+
+        // Ownership Management
+        virtual void requestAttributeOwnershipAssumption(RTI::ObjectHandle objectHandle,
+                                                         const RTI::AttributeHandleSet& attributes, const char* tag)
+            throw (RTI::ObjectNotKnown,
+                   RTI::AttributeNotKnown,
+                   RTI::AttributeAlreadyOwned,
+                   RTI::AttributeNotPublished,
+                   RTI::FederateInternalError)
+        {
+            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
+            if (i == _rtiAmbassador._objectInstanceMap.end())
+                throw RTI::ObjectNotKnown("requestAttributeOwnershipAssumption for unknown object!");
+            if (!i->second.valid())
+                return;
+            i->second->requestAttributeOwnershipAssumption(attributes, tagToData(tag));
+        }
+
+        virtual void attributeOwnershipDivestitureNotification(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+            throw (RTI::ObjectNotKnown,
+                   RTI::AttributeNotKnown,
+                   RTI::AttributeNotOwned,
+                   RTI::AttributeDivestitureWasNotRequested,
+                   RTI::FederateInternalError)
+        {
+            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
+            if (i == _rtiAmbassador._objectInstanceMap.end())
+                throw RTI::ObjectNotKnown("attributeOwnershipDivestitureNotification for unknown object!");
+            if (!i->second.valid())
+                return;
+            i->second->attributeOwnershipDivestitureNotification(attributes);
+        }
+
+        virtual void attributeOwnershipAcquisitionNotification(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+            throw (RTI::ObjectNotKnown,
+                   RTI::AttributeNotKnown,
+                   RTI::AttributeAcquisitionWasNotRequested,
+                   RTI::AttributeAlreadyOwned,
+                   RTI::AttributeNotPublished,
+                   RTI::FederateInternalError)
+        {
+            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
+            if (i == _rtiAmbassador._objectInstanceMap.end())
+                throw RTI::ObjectNotKnown("attributeOwnershipAcquisitionNotification for unknown object!");
+            if (!i->second.valid())
+                return;
+            i->second->attributeOwnershipAcquisitionNotification(attributes);
+        }
+
+        virtual void attributeOwnershipUnavailable(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+            throw (RTI::ObjectNotKnown,
+                   RTI::AttributeNotKnown,
+                   RTI::AttributeAlreadyOwned,
+                   RTI::AttributeAcquisitionWasNotRequested,
+                   RTI::FederateInternalError)
+        {
+            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
+            if (i == _rtiAmbassador._objectInstanceMap.end())
+                throw RTI::ObjectNotKnown("attributeOwnershipUnavailable for unknown object!");
+            if (!i->second.valid())
+                return;
+            i->second->attributeOwnershipUnavailable(attributes);
+        }
+
+        virtual void requestAttributeOwnershipRelease(RTI::ObjectHandle objectHandle,
+                                                      const RTI::AttributeHandleSet& attributes, const char* tag)
+            throw (RTI::ObjectNotKnown,
+                   RTI::AttributeNotKnown,
+                   RTI::AttributeNotOwned,
+                   RTI::FederateInternalError)
+        {
+            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
+            if (i == _rtiAmbassador._objectInstanceMap.end())
+                throw RTI::ObjectNotKnown("requestAttributeOwnershipRelease for unknown object!");
+            if (!i->second.valid())
+                return;
+            i->second->requestAttributeOwnershipRelease(attributes, tagToData(tag));
+        }
+
+        virtual void confirmAttributeOwnershipAcquisitionCancellation(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+            throw (RTI::ObjectNotKnown,
+                   RTI::AttributeNotKnown,
+                   RTI::AttributeAlreadyOwned,
+                   RTI::AttributeAcquisitionWasNotCanceled,
+                   RTI::FederateInternalError)
+        {
+            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
+            if (i == _rtiAmbassador._objectInstanceMap.end())
+                throw RTI::ObjectNotKnown("confirmAttributeOwnershipAcquisitionCancellation for unknown object!");
+            if (!i->second.valid())
+                return;
+            i->second->confirmAttributeOwnershipAcquisitionCancellation(attributes);
+        }
+
+        virtual void informAttributeOwnership(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle,
+                                              RTI::FederateHandle federateHandle)
+            throw (RTI::ObjectNotKnown,
+                   RTI::AttributeNotKnown,
+                   RTI::FederateInternalError)
+        {
+            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
+            if (i == _rtiAmbassador._objectInstanceMap.end())
+                throw RTI::ObjectNotKnown("informAttributeOwnership for unknown object!");
+            if (!i->second.valid())
+                return;
+            i->second->informAttributeOwnership(attributeHandle, federateHandle);
+        }
+
+        virtual void attributeIsNotOwned(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle)
+            throw (RTI::ObjectNotKnown,
+                   RTI::AttributeNotKnown,
+                   RTI::FederateInternalError)
+        {
+            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
+            if (i == _rtiAmbassador._objectInstanceMap.end())
+                throw RTI::ObjectNotKnown("attributeIsNotOwned for unknown object!");
+            if (!i->second.valid())
+                return;
+            i->second->attributeIsNotOwned(attributeHandle);
+        }
+
+        virtual void attributeOwnedByRTI(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle)
+            throw (RTI::ObjectNotKnown,
+                   RTI::AttributeNotKnown,
+                   RTI::FederateInternalError)
+        {
+            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
+            if (i == _rtiAmbassador._objectInstanceMap.end())
+                throw RTI::ObjectNotKnown("attributeOwnedByRTI for unknown object!");
+            if (!i->second.valid())
+                return;
+            i->second->attributeOwnedByRTI(attributeHandle);
+        }
+
+        // Time Management
+        virtual void timeRegulationEnabled(const RTI::FedTime& fedTime)
+            throw (RTI::InvalidFederationTime,
+                   RTI::EnableTimeRegulationWasNotPending,
+                   RTI::FederateInternalError)
+        {
+            _rtiAmbassador._timeRegulationEnabled = true;
+            _rtiAmbassador._federateTime = toTimeStamp(fedTime);
+            SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeRegulationEnabled: " << _rtiAmbassador._federateTime);
+        }
+
+        virtual void timeConstrainedEnabled(const RTI::FedTime& fedTime)
+            throw (RTI::InvalidFederationTime,
+                   RTI::EnableTimeConstrainedWasNotPending,
+                   RTI::FederateInternalError)
+        {
+            _rtiAmbassador._timeConstrainedEnabled = true;
+            _rtiAmbassador._federateTime = toTimeStamp(fedTime);
+            SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeConstrainedEnabled: " << _rtiAmbassador._federateTime);
+        }
+
+        virtual void timeAdvanceGrant(const RTI::FedTime& fedTime)
+            throw (RTI::InvalidFederationTime,
+                   RTI::TimeAdvanceWasNotInProgress,
+                   RTI::FederateInternalError)
+        {
+            _rtiAmbassador._federateTime = toTimeStamp(fedTime);
+            _rtiAmbassador._timeAdvancePending = false;
+            SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeAdvanceGrant: " << _rtiAmbassador._federateTime);
+        }
+
+        virtual void requestRetraction(RTI::EventRetractionHandle eventRetractionHandle)
+            throw (RTI::EventNotKnown,
+                   RTI::FederateInternalError)
+        {
+            // No retraction concept yet
+        }
+
+    private:
+        const RTIData& tagToData(const char* tag)
+        {
+            if (tag)
+                _cachedTag.setData(tag, std::strlen(tag) + 1);
+            else
+                _cachedTag.setData("", 1);
+            return _cachedTag;
+        }
+        RTIData _cachedTag;
+
+        RTI13Ambassador& _rtiAmbassador;
+    };
+
+    static SGTimeStamp toTimeStamp(const RTI::FedTime& fedTime)
+    {
+        RTIfedTime referenceTime(fedTime);
+        return SGTimeStamp::fromSec(referenceTime.getTime() + 0.5e-9);
+    }
+
+    static RTIfedTime toFedTime(const SGTimeStamp& timeStamp)
+    {
+        RTIfedTime referenceTime;
+        referenceTime.setZero();
+        referenceTime += timeStamp.toSecs();
+        return referenceTime;
+    }
+
+    static std::string rtiToStdString(char* n)
+    {
+        if (!n)
+            return std::string();
+        std::string s;
+        s.assign(n);
+        delete[] n;
+        return s;
+    }
+
+    static std::string toStdString(const char* n)
+    {
+        if (!n)
+            return std::string();
+        return std::string(n);
+    }
+
+    // The connection class
+    RTI::RTIambassador _rtiAmbassador;
+
+    // The class with all the callbacks.
+    FederateAmbassador _federateAmbassador;
+
+    // All the sync labels we got an announcement for
+    std::set<std::string> _pendingSyncLabels;
+    std::set<std::string> _syncronizedSyncLabels;
+
+    // All that calls back into user code is just queued.
+    // That is to make sure we do not call recursively into the RTI
+    typedef std::list<SGSharedPtr<QueueCallback> > QueueCallbackList;
+    QueueCallbackList _queueCallbackList;
+    // All object instances that need to be called due to some event are noted here
+    // That is to make sure we do not call recursively into the RTI
+    typedef std::set<SGSharedPtr<RTIObjectInstance> > ObjectInstanceSet;
+    ObjectInstanceSet _objectInstancePendingCallbackList;
+
+    // Top level information for dispatching federate object attribute updates
+    typedef std::map<RTI::ObjectHandle, SGSharedPtr<RTI13ObjectInstance> > ObjectInstanceMap;
+    // Map of all available objects
+    ObjectInstanceMap _objectInstanceMap;
+
+    // Top level information for dispatching creation of federate objects
+    typedef std::map<RTI::ObjectClassHandle, SGSharedPtr<RTI13ObjectClass> > ObjectClassMap;
+    ObjectClassMap _objectClassMap;
+
+    bool _timeRegulationEnabled;
+    bool _timeConstrainedEnabled;
+    bool _timeAdvancePending;
+    SGTimeStamp _federateTime;
+};
+
+} // namespace simgear
+
+#endif
diff --git a/simgear/hla/RTI13Federate.cxx b/simgear/hla/RTI13Federate.cxx
new file mode 100644 (file)
index 0000000..8dad336
--- /dev/null
@@ -0,0 +1,510 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "RTI13Federate.hxx"
+
+#include "RTI13Ambassador.hxx"
+
+namespace simgear {
+
+RTI13Federate::RTI13Federate() :
+    _tickTimeout(10),
+    _ambassador(new RTI13Ambassador)
+{
+}
+
+RTI13Federate::~RTI13Federate()
+{
+}
+
+bool
+RTI13Federate::createFederationExecution(const std::string& federationName, const std::string& objectModel)
+{
+    try {
+        _ambassador->createFederationExecution(federationName, objectModel);
+        return true;
+    } catch (RTI::FederationExecutionAlreadyExists& e) {
+        return true;
+    } catch (RTI::CouldNotOpenFED& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not create federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ErrorReadingFED& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not create federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not create federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not create federation execution: " << e._name << " " << e._reason);
+        return false;
+    }
+}
+
+bool
+RTI13Federate::destroyFederationExecution(const std::string& federation)
+{
+    try {
+        _ambassador->destroyFederationExecution(federation);
+        return true;
+    } catch (RTI::FederatesCurrentlyJoined& e) {
+        return true;
+    } catch (RTI::FederationExecutionDoesNotExist& e) {
+        return true;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not destroy federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not destroy federation execution: " << e._name << " " << e._reason);
+        return false;
+    }
+}
+
+bool
+RTI13Federate::join(const std::string& federateType, const std::string& federationName)
+{
+    try {
+        _federateHandle = _ambassador->joinFederationExecution(federateType, federationName);
+        SG_LOG(SG_NETWORK, SG_INFO, "RTI: Joined federation \""
+               << federationName << "\" as \"" << federateType << "\"");
+        setFederateType(federateType);
+        setFederationName(federationName);
+        return true;
+    } catch (RTI::FederateAlreadyExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::FederationExecutionDoesNotExist& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::CouldNotOpenFED& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ErrorReadingFED& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason);
+        return false;
+    }
+}
+
+bool
+RTI13Federate::resign()
+{
+    try {
+        _ambassador->resignFederationExecution();
+        SG_LOG(SG_NETWORK, SG_INFO, "RTI: Resigned from federation.");
+        _federateHandle = -1;
+        return true;
+    } catch (RTI::FederateOwnsAttributes& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::InvalidResignAction& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    }
+}
+
+bool
+RTI13Federate::registerFederationSynchronizationPoint(const std::string& label, const RTIData& tag)
+{
+    try {
+        _ambassador->registerFederationSynchronizationPoint(label, tag);
+        SG_LOG(SG_NETWORK, SG_INFO, "RTI: registerFederationSynchronizationPoint(" << label << ", tag )");
+        return true;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register federation synchronization point: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register federation synchronization point: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register federation synchronization point: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register federation synchronization point: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register federation synchronization point: " << e._name << " " << e._reason);
+        return false;
+    }
+}
+
+bool
+RTI13Federate::waitForFederationSynchronizationPointAnnounced(const std::string& label)
+{
+    while (!_ambassador->getFederationSynchronizationPointAnnounced(label)) {
+        _ambassador->tick(_tickTimeout, 0);
+        _ambassador->processQueues();
+    }
+    return true;
+}
+
+bool
+RTI13Federate::synchronizationPointAchieved(const std::string& label)
+{
+    try {
+        _ambassador->synchronizationPointAchieved(label);
+        SG_LOG(SG_NETWORK, SG_INFO, "RTI: synchronizationPointAchieved(" << label << ")");
+        return true;
+    } catch (RTI::SynchronizationPointLabelWasNotAnnounced& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not signal synchronization point: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not signal synchronization point: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not signal synchronization point: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not signal synchronization point: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not signal synchronization point: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not signal synchronization point: " << e._name << " " << e._reason);
+        return false;
+    }
+}
+
+bool
+RTI13Federate::waitForFederationSynchronized(const std::string& label)
+{
+    while (!_ambassador->getFederationSynchronized(label)) {
+        _ambassador->tick(_tickTimeout, 0);
+        _ambassador->processQueues();
+    }
+    return true;
+}
+
+bool
+RTI13Federate::enableTimeConstrained()
+{
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time constrained at unconnected federate.");
+        return false;
+    }
+
+    if (_ambassador->getTimeConstrainedEnabled()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Time constrained is already enabled.");
+        return false;
+    }
+
+    try {
+        _ambassador->enableTimeConstrained();
+    } catch (RTI::TimeConstrainedAlreadyEnabled& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::EnableTimeConstrainedPending& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::TimeAdvanceAlreadyInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    }
+
+    while (!_ambassador->getTimeConstrainedEnabled()) {
+        _ambassador->tick(_tickTimeout, 0);
+        _ambassador->processQueues();
+    }
+
+    return true;
+}
+
+bool
+RTI13Federate::disableTimeConstrained()
+{
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time constrained at unconnected federate.");
+        return false;
+    }
+
+    if (!_ambassador->getTimeConstrainedEnabled()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Time constrained is not enabled.");
+        return false;
+    }
+
+    try {
+        _ambassador->disableTimeConstrained();
+    } catch (RTI::TimeConstrainedWasNotEnabled& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    }
+
+    return true;
+}
+
+bool
+RTI13Federate::enableTimeRegulation(const SGTimeStamp& lookahead)
+{
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time regulation at unconnected federate.");
+        return false;
+    }
+
+    if (_ambassador->getTimeRegulationEnabled()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Time regulation already enabled.");
+        return false;
+    }
+
+    try {
+        _ambassador->enableTimeRegulation(SGTimeStamp(), lookahead);
+    } catch (RTI::TimeRegulationAlreadyEnabled& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::EnableTimeRegulationPending& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::TimeAdvanceAlreadyInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::InvalidFederationTime& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::InvalidLookahead& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    }
+
+    while (!_ambassador->getTimeRegulationEnabled()) {
+        _ambassador->tick(_tickTimeout, 0);
+        _ambassador->processQueues();
+    }
+
+    return true;
+}
+
+bool
+RTI13Federate::disableTimeRegulation()
+{
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time regulation at unconnected federate.");
+        return false;
+    }
+
+    if (!_ambassador->getTimeRegulationEnabled()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Time regulation is not enabled.");
+        return false;
+    }
+
+    try {
+        _ambassador->disableTimeRegulation();
+    } catch (RTI::TimeRegulationWasNotEnabled& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    }
+
+    return true;
+}
+
+bool
+RTI13Federate::timeAdvanceRequestBy(const SGTimeStamp& dt)
+{
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time regulation at unconnected federate.");
+        return false;
+    }
+
+    SGTimeStamp fedTime = _ambassador->getCurrentLogicalTime() + dt;
+    return timeAdvanceRequest(fedTime);
+}
+
+bool
+RTI13Federate::timeAdvanceRequest(const SGTimeStamp& fedTime)
+{
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time regulation at unconnected federate.");
+        return false;
+    }
+
+    try {
+        _ambassador->timeAdvanceRequest(fedTime);
+    } catch (RTI::InvalidFederationTime& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::FederationTimeAlreadyPassed& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::TimeAdvanceAlreadyInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::EnableTimeRegulationPending& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::EnableTimeConstrainedPending& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        return false;
+    }
+
+    while (_ambassador->getTimeAdvancePending()) {
+        _ambassador->tick(_tickTimeout, 0);
+        _ambassador->processQueues();
+    }
+
+    return true;
+}
+
+bool
+RTI13Federate::tick()
+{
+    bool result = _ambassador->tick();
+    _ambassador->processQueues();
+    return result;
+}
+
+bool
+RTI13Federate::tick(const double& minimum, const double& maximum)
+{
+    bool result = _ambassador->tick(minimum, maximum);
+    _ambassador->processQueues();
+    return result;
+}
+
+RTI13ObjectClass*
+RTI13Federate::createObjectClass(const std::string& objectClassName, HLAObjectClass* hlaObjectClass)
+{
+    try {
+        return _ambassador->createObjectClass(objectClassName, hlaObjectClass);
+    } catch (RTI::NameNotFound& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason);
+        return 0;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason);
+        return 0;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason);
+        return 0;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason);
+        return 0;
+    }
+}
+
+RTI13ObjectInstance*
+RTI13Federate::getObjectInstance(const std::string& objectInstanceName)
+{
+    try {
+        return _ambassador->getObjectInstance(objectInstanceName);
+    } catch (RTI::ObjectNotKnown& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason);
+        return 0;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason);
+        return 0;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason);
+        return 0;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason);
+        return 0;
+    }
+}
+
+}
diff --git a/simgear/hla/RTI13Federate.hxx b/simgear/hla/RTI13Federate.hxx
new file mode 100644 (file)
index 0000000..3aa32aa
--- /dev/null
@@ -0,0 +1,88 @@
+// Copyright (C) 2009 - 2010  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 RTI13Federate_hxx
+#define RTI13Federate_hxx
+
+#ifndef RTI_USES_STD_FSTREAM
+#define RTI_USES_STD_FSTREAM
+#endif
+
+#include <RTI.hh>
+
+#include "RTIFederate.hxx"
+#include "RTI13ObjectClass.hxx"
+#include "RTI13ObjectInstance.hxx"
+
+namespace simgear {
+
+class RTI13Ambassador;
+
+class RTI13Federate : public RTIFederate {
+public:
+    RTI13Federate();
+    virtual ~RTI13Federate();
+
+    virtual bool createFederationExecution(const std::string& federation, const std::string& objectModel);
+    virtual bool destroyFederationExecution(const std::string& federation);
+
+    /// Join with federateName the federation execution federation
+    virtual bool join(const std::string& federateType, const std::string& federation);
+    virtual bool resign();
+
+    /// Synchronization Point handling
+    virtual bool registerFederationSynchronizationPoint(const std::string& label, const RTIData& tag);
+    virtual bool waitForFederationSynchronizationPointAnnounced(const std::string& label);
+    virtual bool synchronizationPointAchieved(const std::string& label);
+    virtual bool waitForFederationSynchronized(const std::string& label);
+
+    /// Time management
+    virtual bool enableTimeConstrained();
+    virtual bool disableTimeConstrained();
+
+    virtual bool enableTimeRegulation(const SGTimeStamp& lookahead);
+    virtual bool disableTimeRegulation();
+
+    virtual bool timeAdvanceRequestBy(const SGTimeStamp& dt);
+    virtual bool timeAdvanceRequest(const SGTimeStamp& fedTime);
+
+    /// Process messages
+    virtual bool tick();
+    virtual bool tick(const double& minimum, const double& maximum);
+
+    virtual RTI13ObjectClass* createObjectClass(const std::string& name, HLAObjectClass* hlaObjectClass);
+
+    virtual RTI13ObjectInstance* getObjectInstance(const std::string& name);
+
+private:
+    RTI13Federate(const RTI13Federate&);
+    RTI13Federate& operator=(const RTI13Federate&);
+
+    /// The federate handle
+    RTI::FederateHandle _federateHandle;
+
+    /// The timeout for the single callback tick function in
+    /// syncronous operations that need to wait for a callback
+    double _tickTimeout;
+
+    /// RTI connection
+    SGSharedPtr<RTI13Ambassador> _ambassador;
+};
+
+}
+
+#endif
diff --git a/simgear/hla/RTI13ObjectClass.cxx b/simgear/hla/RTI13ObjectClass.cxx
new file mode 100644 (file)
index 0000000..e2ccd49
--- /dev/null
@@ -0,0 +1,405 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "RTI13ObjectClass.hxx"
+#include "RTI13Ambassador.hxx"
+
+namespace simgear {
+
+RTI13ObjectClass::RTI13ObjectClass(HLAObjectClass* hlaObjectClass, RTI::ObjectClassHandle& handle, RTI13Ambassador* ambassador) :
+    RTIObjectClass(hlaObjectClass),
+    _handle(handle),
+    _ambassador(ambassador)
+{
+    if (0 != getOrCreateAttributeIndex("privilegeToDelete") &&
+        0 != getOrCreateAttributeIndex("HLAprivilegeToDeleteObject"))
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI13ObjectClass: Cannot find object root attribute.");
+}
+
+RTI13ObjectClass::~RTI13ObjectClass()
+{
+}
+
+std::string
+RTI13ObjectClass::getName() const
+{
+    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
+    if (!ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return std::string();
+    }
+    return ambassador->getObjectClassName(_handle);
+}
+
+unsigned
+RTI13ObjectClass::getNumAttributes() const
+{
+    return _attributeHandleVector.size();
+}
+
+unsigned
+RTI13ObjectClass::getAttributeIndex(const std::string& name) const
+{
+    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
+    if (!ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return ~0u;
+    }
+
+    try {
+        RTI::AttributeHandle attributeHandle = ambassador->getAttributeHandle(name, _handle);
+
+        AttributeHandleIndexMap::const_iterator i = _attributeHandleIndexMap.find(attributeHandle);
+        if (i !=  _attributeHandleIndexMap.end())
+            return i->second;
+
+        return ~0u;
+
+    } catch (RTI::ObjectClassNotDefined& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason);
+        return ~0u;
+    } catch (RTI::NameNotFound& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason);
+        return ~0u;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason);
+        return ~0u;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason);
+        return ~0u;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason);
+        return ~0u;
+    } catch (...) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute.");
+        return ~0u;
+    }
+}
+
+unsigned
+RTI13ObjectClass::getOrCreateAttributeIndex(const std::string& name)
+{
+    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
+    if (!ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return ~0u;
+    }
+
+    try {
+        RTI::AttributeHandle attributeHandle = ambassador->getAttributeHandle(name, _handle);
+
+        AttributeHandleIndexMap::const_iterator i = _attributeHandleIndexMap.find(attributeHandle);
+        if (i !=  _attributeHandleIndexMap.end())
+            return i->second;
+
+        unsigned index = _attributeHandleVector.size();
+        _attributeHandleIndexMap[attributeHandle] = index;
+        _attributeHandleVector.push_back(attributeHandle);
+        _attributeDataVector.push_back(name);
+
+        return index;
+
+    } catch (RTI::ObjectClassNotDefined& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason);
+        return ~0u;
+    } catch (RTI::NameNotFound& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason);
+        return ~0u;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason);
+        return ~0u;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason);
+        return ~0u;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason);
+        return ~0u;
+    } catch (...) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute.");
+        return ~0u;
+    }
+}
+
+// std::string
+// RTI13ObjectClass::getAttributeName(unsigned index) const
+// {
+//     SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
+//     if (!ambassador.valid()) {
+//         SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+//         return std::string();
+//     }
+
+//     try {
+//         return ambassador->getAttributeName(getAttributeHandle(index), _handle);
+//     } catch (RTI::ObjectClassNotDefined& e) {
+//         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute name: " << e._name << " " << e._reason);
+//         return std::string();
+//     } catch (RTI::AttributeNotDefined& e) {
+//         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute name: " << e._name << " " << e._reason);
+//         return std::string();
+//     } catch (RTI::FederateNotExecutionMember& e) {
+//         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute name: " << e._name << " " << e._reason);
+//         return std::string();
+//     } catch (RTI::ConcurrentAccessAttempted& e) {
+//         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute name: " << e._name << " " << e._reason);
+//         return std::string();
+//     } catch (RTI::RTIinternalError& e) {
+//         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute name: " << e._name << " " << e._reason);
+//         return std::string();
+//     } catch (...) {
+//         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute name.");
+//         return std::string();
+//     }
+// }
+
+bool
+RTI13ObjectClass::publish(const std::set<unsigned>& indexSet)
+{
+    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
+    if (!ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return false;
+    }
+
+    try {
+        std::auto_ptr<RTI::AttributeHandleSet> attributeHandleSet(RTI::AttributeHandleSetFactory::create(indexSet.size()));
+        for (std::set<unsigned>::const_iterator i = indexSet.begin(); i != indexSet.end(); ++i) {
+            if (_attributeHandleVector.size() <= *i) {
+                SG_LOG(SG_NETWORK, SG_WARN, "RTI13ObjectClass::publish(): Invalid attribute index!");
+                continue;
+            }
+            attributeHandleSet->add(_attributeHandleVector[*i]);
+        }
+
+        ambassador->publishObjectClass(_handle, *attributeHandleSet);
+
+        for (unsigned i = 0; i < getNumAttributes(); ++i) {
+            _attributeDataVector[i]._published = true;
+        }
+
+        return true;
+    } catch (RTI::ObjectClassNotDefined& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::AttributeNotDefined& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::OwnershipAcquisitionPending& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (...) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish object class.");
+        return false;
+    }
+}
+
+bool
+RTI13ObjectClass::unpublish()
+{
+    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
+    if (!ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return false;
+    }
+
+    try {
+        ambassador->unpublishObjectClass(_handle);
+
+        for (unsigned i = 0; i < getNumAttributes(); ++i) {
+            _attributeDataVector[i]._published = false;
+        }
+
+        return true;
+    } catch (RTI::ObjectClassNotDefined& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ObjectClassNotPublished& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::OwnershipAcquisitionPending& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (...) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish object class.");
+        return false;
+    }
+}
+
+bool
+RTI13ObjectClass::subscribe(const std::set<unsigned>& indexSet, bool active)
+{
+    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
+    if (!ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return false;
+    }
+
+    try {
+        std::auto_ptr<RTI::AttributeHandleSet> attributeHandleSet(RTI::AttributeHandleSetFactory::create(indexSet.size()));
+        for (std::set<unsigned>::const_iterator i = indexSet.begin();
+             i != indexSet.end(); ++i) {
+            if (_attributeHandleVector.size() <= *i) {
+                SG_LOG(SG_NETWORK, SG_WARN, "RTI13ObjectClass::subscribe(): Invalid attribute index!");
+                continue;
+            }
+            attributeHandleSet->add(_attributeHandleVector[*i]);
+        }
+
+        ambassador->subscribeObjectClassAttributes(_handle, *attributeHandleSet, active);
+
+        for (unsigned i = 0; i < getNumAttributes(); ++i) {
+            _attributeDataVector[i]._subscribed = true;
+        }
+
+        return true;
+    } catch (RTI::ObjectClassNotDefined& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::AttributeNotDefined& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (...) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe object class.");
+        return false;
+    }
+}
+
+bool
+RTI13ObjectClass::unsubscribe()
+{
+    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
+    if (!ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return 0;
+    }
+
+    try {
+        ambassador->unsubscribeObjectClass(_handle);
+
+        for (unsigned i = 0; i < getNumAttributes(); ++i) {
+            _attributeDataVector[i]._subscribed = false;
+        }
+
+        return true;
+    } catch (RTI::ObjectClassNotDefined& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ObjectClassNotSubscribed& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe object class: " << e._name << " " << e._reason);
+        return false;
+    } catch (...) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe object class.");
+        return false;
+    }
+}
+
+RTIObjectInstance*
+RTI13ObjectClass::registerObjectInstance(HLAObjectInstance* hlaObjectInstance)
+{
+    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
+    if (!ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return 0;
+    }
+
+    try {
+        return ambassador->registerObjectInstance(this, hlaObjectInstance);
+    } catch (RTI::ObjectClassNotDefined& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register object instance: " << e._name << " " << e._reason);
+        return 0;
+    } catch (RTI::ObjectClassNotPublished& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register object instance: " << e._name << " " << e._reason);
+        return 0;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register object instance: " << e._name << " " << e._reason);
+        return 0;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register object instance: " << e._name << " " << e._reason);
+        return 0;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register object instance: " << e._name << " " << e._reason);
+        return 0;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register object instance: " << e._name << " " << e._reason);
+        return 0;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register object instance: " << e._name << " " << e._reason);
+        return 0;
+    }
+}
+
+}
diff --git a/simgear/hla/RTI13ObjectClass.hxx b/simgear/hla/RTI13ObjectClass.hxx
new file mode 100644 (file)
index 0000000..e8c25cd
--- /dev/null
@@ -0,0 +1,87 @@
+// Copyright (C) 2009 - 2010  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 RTI13ObjectClass_hxx
+#define RTI13ObjectClass_hxx
+
+#include <map>
+
+#ifndef RTI_USES_STD_FSTREAM
+#define RTI_USES_STD_FSTREAM
+#endif
+
+#include <RTI.hh>
+
+#include <simgear/structure/SGWeakPtr.hxx>
+
+#include "RTIObjectClass.hxx"
+
+namespace simgear {
+
+class RTI13Ambassador;
+class RTIObjectInstance;
+
+class RTI13ObjectClass : public RTIObjectClass {
+public:
+    RTI13ObjectClass(HLAObjectClass* hlaObjectClass, RTI::ObjectClassHandle& handle, RTI13Ambassador* ambassador);
+    virtual ~RTI13ObjectClass();
+
+    const RTI::ObjectClassHandle& getHandle() const
+    { return _handle; }
+
+    virtual std::string getName() const;
+
+    virtual unsigned getNumAttributes() const;
+    virtual unsigned getAttributeIndex(const std::string& name) const;
+    virtual unsigned getOrCreateAttributeIndex(const std::string& name);
+
+    unsigned getAttributeIndex(const RTI::AttributeHandle& handle) const
+    {
+        AttributeHandleIndexMap::const_iterator i = _attributeHandleIndexMap.find(handle);
+        if (i == _attributeHandleIndexMap.end())
+            return ~0u;
+        return i->second;
+    }
+    RTI::AttributeHandle getAttributeHandle(unsigned index) const
+    {
+        if (_attributeHandleVector.size() <= index)
+            return -1;
+        return _attributeHandleVector[index];
+    }
+
+    virtual bool publish(const std::set<unsigned>& indexSet);
+    virtual bool unpublish();
+
+    virtual bool subscribe(const std::set<unsigned>& indexSet, bool);
+    virtual bool unsubscribe();
+
+    virtual RTIObjectInstance* registerObjectInstance(HLAObjectInstance* hlaObjectInstance);
+
+private:
+    RTI::ObjectClassHandle _handle;
+    SGWeakPtr<RTI13Ambassador> _ambassador;
+
+    typedef std::map<RTI::AttributeHandle, unsigned> AttributeHandleIndexMap;
+    AttributeHandleIndexMap _attributeHandleIndexMap;
+
+    typedef std::vector<RTI::AttributeHandle> AttributeHandleVector;
+    AttributeHandleVector _attributeHandleVector;
+};
+
+}
+
+#endif
diff --git a/simgear/hla/RTI13ObjectInstance.cxx b/simgear/hla/RTI13ObjectInstance.cxx
new file mode 100644 (file)
index 0000000..8fefc88
--- /dev/null
@@ -0,0 +1,488 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "RTIObjectInstance.hxx"
+#include "RTI13Ambassador.hxx"
+
+namespace simgear {
+
+RTI13ObjectInstance::RTI13ObjectInstance(const RTI::ObjectHandle& handle, HLAObjectInstance* hlaObjectInstance,
+                                         const RTI13ObjectClass* objectClass, RTI13Ambassador* ambassador, bool owned) :
+    RTIObjectInstance(hlaObjectInstance),
+    _handle(handle),
+    _objectClass(objectClass),
+    _ambassador(ambassador),
+    _attributeValuePairSet(RTI::AttributeSetFactory::create(objectClass->getNumAttributes()))
+{
+    updateAttributesFromClass(owned);
+}
+
+RTI13ObjectInstance::~RTI13ObjectInstance()
+{
+}
+
+const RTIObjectClass*
+RTI13ObjectInstance::getObjectClass() const
+{
+    return _objectClass.get();
+}
+
+const RTI13ObjectClass*
+RTI13ObjectInstance::get13ObjectClass() const
+{
+    return _objectClass.get();
+}
+
+std::string
+RTI13ObjectInstance::getName() const
+{
+    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
+    if (!ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return std::string();
+    }
+
+    try {
+        return ambassador->getObjectInstanceName(_handle);
+    } catch (RTI::ObjectNotKnown& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object name: " << e._name << " " << e._reason);
+        return std::string();
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object name: " << e._name << " " << e._reason);
+        return std::string();
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object name: " << e._name << " " << e._reason);
+        return std::string();
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object name: " << e._name << " " << e._reason);
+        return std::string();
+    } catch (...) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object name.");
+        return std::string();
+    }
+}
+
+void
+RTI13ObjectInstance::addToRequestQueue()
+{
+    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
+    if (!ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return;
+    }
+
+    ambassador->addObjectInstanceForCallback(this);
+}
+
+void
+RTI13ObjectInstance::deleteObjectInstance(const RTIData& tag)
+{
+    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
+    if (!ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return;
+    }
+
+    try {
+        ambassador->deleteObjectInstance(_handle, tag);
+    } catch (RTI::ObjectNotKnown& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::DeletePrivilegeNotHeld& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    }
+}
+
+void
+RTI13ObjectInstance::deleteObjectInstance(const SGTimeStamp& timeStamp, const RTIData& tag)
+{
+    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
+    if (!ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return;
+    }
+
+    try {
+        ambassador->deleteObjectInstance(_handle, timeStamp, tag);
+    } catch (RTI::ObjectNotKnown& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::DeletePrivilegeNotHeld& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::InvalidFederationTime& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    }
+}
+
+void
+RTI13ObjectInstance::localDeleteObjectInstance()
+{
+    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
+    if (!ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return;
+    }
+
+    try {
+        ambassador->localDeleteObjectInstance(_handle);
+    } catch (RTI::ObjectNotKnown& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::FederateOwnsAttributes& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    }
+}
+
+void
+RTI13ObjectInstance::reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const RTIData& tag)
+{
+    // Retrieve an empty update struct from the memory pool
+    UpdateList updateList;
+    getUpdateFromPool(updateList);
+
+    RTI::ULong numAttribs = attributeValuePairSet.size();
+    for (RTI::ULong i = 0; i < numAttribs; ++i) {
+        unsigned index = getAttributeIndex(attributeValuePairSet.getHandle(i));
+        // Get a RTIData from the data pool
+        getDataFromPool(index, updateList.back()._indexDataPairList);
+        RTI::ULong length = attributeValuePairSet.getValueLength(i);
+        updateList.back()._indexDataPairList.back().second.resize(length);
+        attributeValuePairSet.getValue(i, updateList.back()._indexDataPairList.back().second.data(), length);
+        updateList.back()._tag = tag;
+    }
+
+    RTIObjectInstance::reflectAttributeValues(updateList.front()._indexDataPairList, tag);
+    // Return the update data back to the pool
+    putUpdateToPool(updateList);
+}
+
+void
+RTI13ObjectInstance::reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const SGTimeStamp& timeStamp, const RTIData& tag)
+{
+    // Retrieve an empty update struct from the memory pool
+    UpdateList updateList;
+    getUpdateFromPool(updateList);
+
+    RTI::ULong numAttribs = attributeValuePairSet.size();
+    for (RTI::ULong i = 0; i < numAttribs; ++i) {
+        unsigned index = getAttributeIndex(attributeValuePairSet.getHandle(i));
+        // Get a RTIData from the data pool
+        getDataFromPool(index, updateList.back()._indexDataPairList);
+        RTI::ULong length = attributeValuePairSet.getValueLength(i);
+        updateList.back()._indexDataPairList.back().second.resize(length);
+        attributeValuePairSet.getValue(i, updateList.back()._indexDataPairList.back().second.data(), length);
+        updateList.back()._tag = tag;
+    }
+
+    scheduleUpdates(timeStamp, updateList);
+}
+
+void
+RTI13ObjectInstance::requestObjectAttributeValueUpdate()
+{
+    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
+    if (!ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return;
+    }
+
+    try {
+        unsigned numAttributes = getNumAttributes();
+        std::auto_ptr<RTI::AttributeHandleSet> attributeHandleSet(RTI::AttributeHandleSetFactory::create(numAttributes));
+        for (unsigned i = 0; i < numAttributes; ++i) {
+            if (!getRequestAttributeUpdate(i))
+                continue;
+            attributeHandleSet->add(getAttributeHandle(i));
+        }
+        if (!attributeHandleSet->size())
+            return;
+
+        ambassador->requestObjectAttributeValueUpdate(_handle, *attributeHandleSet);
+
+        for (unsigned i = 0; i < numAttributes; ++i)
+            setRequestAttributeUpdate(i, false);
+
+        return;
+    } catch (RTI::ObjectNotKnown& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not request attribute update for object instance: " << e._name << " " << e._reason);
+        return;
+    } catch (RTI::AttributeNotDefined& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not request attribute update for object instance: " << e._name << " " << e._reason);
+        return;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not request attribute update for object instance: " << e._name << " " << e._reason);
+        return;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not request attribute update for object instance: " << e._name << " " << e._reason);
+        return;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not request attribute update for object instance: " << e._name << " " << e._reason);
+        return;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not request attribute update for object instance: " << e._name << " " << e._reason);
+        return;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not request attribute update for object instance: " << e._name << " " << e._reason);
+        return;
+    } catch (...) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not request attribute update for object instance.");
+        return;
+    }
+}
+
+void
+RTI13ObjectInstance::provideAttributeValueUpdate(const RTI::AttributeHandleSet& attributes)
+{
+    // Called from the ambassador. Just marks some instance attributes dirty so that they are sent with the next update
+    RTI::ULong numAttribs = attributes.size();
+    for (RTI::ULong i = 0; i < numAttribs; ++i) {
+        unsigned index = getAttributeIndex(attributes.getHandle(i));
+        setAttributeForceUpdate(index);
+    }
+}
+
+void
+RTI13ObjectInstance::updateAttributeValues(const RTIData& tag)
+{
+    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
+    if (!ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return;
+    }
+
+    try {
+        // That means clear()
+        _attributeValuePairSet->empty();
+
+        unsigned numAttributes = getNumAttributes();
+        for (unsigned i = 0; i < numAttributes; ++i) {
+            if (!getAttributeEffectiveUpdateEnabled(i))
+                continue;
+            const HLADataElement* dataElement = getDataElement(i);
+            if (!dataElement)
+                continue;
+            // FIXME cache somewhere
+            RTIData data;
+            HLAEncodeStream stream(data);
+            dataElement->encode(stream);
+            _attributeValuePairSet->add(getAttributeHandle(i), data.data(), data.size());
+        }
+
+        if (!_attributeValuePairSet->size())
+            return;
+
+        ambassador->updateAttributeValues(_handle, *_attributeValuePairSet, tag);
+
+        for (unsigned i = 0; i < numAttributes; ++i) {
+            setAttributeUpdated(i);
+        }
+
+    } catch (RTI::ObjectNotKnown& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::AttributeNotDefined& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::AttributeNotOwned& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    }
+
+    // That means clear()
+    _attributeValuePairSet->empty();
+}
+
+void
+RTI13ObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
+{
+    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
+    if (!ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return;
+    }
+
+    try {
+        // That means clear()
+        _attributeValuePairSet->empty();
+
+        unsigned numAttributes = getNumAttributes();
+        for (unsigned i = 0; i < numAttributes; ++i) {
+            if (!getAttributeEffectiveUpdateEnabled(i))
+                continue;
+            const HLADataElement* dataElement = getDataElement(i);
+            if (!dataElement)
+                continue;
+            // FIXME cache somewhere
+            RTIData data;
+            HLAEncodeStream stream(data);
+            dataElement->encode(stream);
+            _attributeValuePairSet->add(getAttributeHandle(i), data.data(), data.size());
+        }
+
+        if (!_attributeValuePairSet->size())
+            return;
+
+        ambassador->updateAttributeValues(_handle, *_attributeValuePairSet, timeStamp, tag);
+
+        for (unsigned i = 0; i < numAttributes; ++i) {
+            setAttributeUpdated(i);
+        }
+
+    } catch (RTI::ObjectNotKnown& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::AttributeNotDefined& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::AttributeNotOwned& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::InvalidFederationTime& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+    }
+
+    // That means clear()
+    _attributeValuePairSet->empty();
+}
+
+void
+RTI13ObjectInstance::attributesInScope(const RTI::AttributeHandleSet& attributeHandleSet)
+{
+    RTI::ULong numAttribs = attributeHandleSet.size();
+    for (RTI::ULong i = 0; i < numAttribs; ++i) {
+        RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i);
+        setAttributeInScope(getAttributeIndex(attributeHandle), true);
+    }
+}
+
+void
+RTI13ObjectInstance::attributesOutOfScope(const RTI::AttributeHandleSet& attributeHandleSet)
+{
+    RTI::ULong numAttribs = attributeHandleSet.size();
+    for (RTI::ULong i = 0; i < numAttribs; ++i) {
+        RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i);
+        setAttributeInScope(getAttributeIndex(attributeHandle), false);
+    }
+}
+
+void
+RTI13ObjectInstance::turnUpdatesOnForObjectInstance(const RTI::AttributeHandleSet& attributeHandleSet)
+{
+    RTI::ULong numAttribs = attributeHandleSet.size();
+    for (RTI::ULong i = 0; i < numAttribs; ++i) {
+        RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i);
+        setAttributeUpdateEnabled(getAttributeIndex(attributeHandle), true);
+    }
+}
+
+void
+RTI13ObjectInstance::turnUpdatesOffForObjectInstance(const RTI::AttributeHandleSet& attributeHandleSet)
+{
+    RTI::ULong numAttribs = attributeHandleSet.size();
+    for (RTI::ULong i = 0; i < numAttribs; ++i) {
+        RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i);
+        setAttributeUpdateEnabled(getAttributeIndex(attributeHandle), false);
+    }
+}
+
+void
+RTI13ObjectInstance::requestAttributeOwnershipAssumption(const RTI::AttributeHandleSet& attributes, const RTIData& tag)
+{
+}
+
+void
+RTI13ObjectInstance::attributeOwnershipDivestitureNotification(const RTI::AttributeHandleSet& attributes)
+{
+}
+
+void
+RTI13ObjectInstance::attributeOwnershipAcquisitionNotification(const RTI::AttributeHandleSet& attributes)
+{
+}
+
+void
+RTI13ObjectInstance::attributeOwnershipUnavailable(const RTI::AttributeHandleSet& attributes)
+{
+}
+
+void
+RTI13ObjectInstance::requestAttributeOwnershipRelease(const RTI::AttributeHandleSet& attributes, const RTIData& tag)
+{
+}
+
+void
+RTI13ObjectInstance::confirmAttributeOwnershipAcquisitionCancellation(const RTI::AttributeHandleSet& attributes)
+{
+}
+
+void
+RTI13ObjectInstance::informAttributeOwnership(RTI::AttributeHandle attributeHandle, RTI::FederateHandle federateHandle)
+{
+}
+
+void
+RTI13ObjectInstance::attributeIsNotOwned(RTI::AttributeHandle attributeHandle)
+{
+}
+
+void
+RTI13ObjectInstance::attributeOwnedByRTI(RTI::AttributeHandle attributeHandle)
+{
+}
+
+}
diff --git a/simgear/hla/RTI13ObjectInstance.hxx b/simgear/hla/RTI13ObjectInstance.hxx
new file mode 100644 (file)
index 0000000..ed73aa0
--- /dev/null
@@ -0,0 +1,106 @@
+// Copyright (C) 2009 - 2010  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 RTI13ObjectInstance_hxx
+#define RTI13ObjectInstance_hxx
+
+#include <map>
+#include <memory>
+
+#ifndef RTI_USES_STD_FSTREAM
+#define RTI_USES_STD_FSTREAM
+#endif
+
+#include <RTI.hh>
+
+#include <simgear/structure/SGWeakPtr.hxx>
+
+#include "RTIObjectInstance.hxx"
+#include "RTI13ObjectClass.hxx"
+
+namespace simgear {
+
+class RTI13Ambassador;
+class RTI13ObjectClass;
+
+class RTI13ObjectInstance : public RTIObjectInstance {
+public:
+    RTI13ObjectInstance(const RTI::ObjectHandle& handle, HLAObjectInstance* hlaObjectInstance, const RTI13ObjectClass* objectClass, RTI13Ambassador* ambassador, bool owned);
+    virtual ~RTI13ObjectInstance();
+
+    const RTI::ObjectHandle& getHandle() const
+    { return _handle; }
+    void setHandle(const RTI::ObjectHandle& handle)
+    { _handle = handle; }
+
+    virtual const RTIObjectClass* getObjectClass() const;
+    const RTI13ObjectClass* get13ObjectClass() const;
+
+    unsigned getNumAttributes() const
+    { return get13ObjectClass()->getNumAttributes(); }
+    unsigned getAttributeIndex(const std::string& name) const
+    { return get13ObjectClass()->getAttributeIndex(name); }
+    unsigned getAttributeIndex(const RTI::AttributeHandle& handle) const
+    { return get13ObjectClass()->getAttributeIndex(handle); }
+    RTI::AttributeHandle getAttributeHandle(unsigned index) const
+    { return get13ObjectClass()->getAttributeHandle(index); }
+
+    virtual std::string getName() const;
+
+    virtual void addToRequestQueue();
+
+    virtual void deleteObjectInstance(const RTIData& tag);
+    virtual void deleteObjectInstance(const SGTimeStamp& timeStamp, const RTIData& tag);
+    virtual void localDeleteObjectInstance();
+
+    void reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const RTIData& tag);
+    void reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const SGTimeStamp& timeStamp, const RTIData& tag);
+    virtual void requestObjectAttributeValueUpdate();
+    void provideAttributeValueUpdate(const RTI::AttributeHandleSet& attributes);
+
+    virtual void updateAttributeValues(const RTIData& tag);
+    virtual void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag);
+
+    void attributesInScope(const RTI::AttributeHandleSet& attributes);
+    void attributesOutOfScope(const RTI::AttributeHandleSet& attributes);
+
+    void turnUpdatesOnForObjectInstance(const RTI::AttributeHandleSet& attributes);
+    void turnUpdatesOffForObjectInstance(const RTI::AttributeHandleSet& attributes);
+
+    // Not yet sure what to do here. But the dispatch functions are already there
+    void requestAttributeOwnershipAssumption(const RTI::AttributeHandleSet& attributes, const RTIData& tag);
+    void attributeOwnershipDivestitureNotification(const RTI::AttributeHandleSet& attributes);
+    void attributeOwnershipAcquisitionNotification(const RTI::AttributeHandleSet& attributes);
+    void attributeOwnershipUnavailable(const RTI::AttributeHandleSet& attributes);
+    void requestAttributeOwnershipRelease(const RTI::AttributeHandleSet& attributes, const RTIData& tag);
+    void confirmAttributeOwnershipAcquisitionCancellation(const RTI::AttributeHandleSet& attributes);
+    void informAttributeOwnership(RTI::AttributeHandle attributeHandle, RTI::FederateHandle federateHandle);
+    void attributeIsNotOwned(RTI::AttributeHandle attributeHandle);
+    void attributeOwnedByRTI(RTI::AttributeHandle attributeHandle);
+
+private:
+    RTI::ObjectHandle _handle;
+    SGSharedPtr<const RTI13ObjectClass> _objectClass;
+    SGWeakPtr<RTI13Ambassador> _ambassador;
+
+    // cached storage for updates
+    std::auto_ptr<RTI::AttributeHandleValuePairSet> _attributeValuePairSet;
+};
+
+}
+
+#endif
diff --git a/simgear/hla/RTIData.hxx b/simgear/hla/RTIData.hxx
new file mode 100644 (file)
index 0000000..dff66db
--- /dev/null
@@ -0,0 +1,573 @@
+// Copyright (C) 2009 - 2010  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 RTIData_hxx
+#define RTIData_hxx
+
+#include <cstring>
+#include <list>
+#include <simgear/misc/stdint.hxx>
+
+namespace simgear {
+
+/// Sigh, this is std::vector<char>, except that
+/// you could feed that with external pointers without copying ...
+/// Note on alignment: the c++ standard garantees (5.3.4.10) that
+/// new (unsigned) char returns sufficiently aligned memory
+/// for all relevant cases
+class RTIData {
+public:
+    RTIData() :
+        _data(0),
+        _size(0),
+        _capacity(0)
+    { }
+    RTIData(unsigned size) :
+        _data(0),
+        _size(0),
+        _capacity(0)
+    { resize(size); }
+    RTIData(char* data, unsigned size) :
+        _data(data),
+        _size(size),
+        _capacity(0)
+    { }
+    RTIData(const char* data, unsigned size) :
+        _data(0),
+        _size(0),
+        _capacity(0)
+    { setData(data, size); }
+    RTIData(const char* data) :
+        _data(0),
+        _size(0),
+        _capacity(0)
+    { setData(data); }
+    RTIData(const RTIData& data) :
+        _data(0),
+        _size(0),
+        _capacity(0)
+    {
+        unsigned size = data.size();
+        if (size) {
+            resize(size);
+            memcpy(_data, data.data(), size);
+        }
+    }
+    ~RTIData()
+    {
+        if (_capacity)
+            delete [] _data;
+        _data = 0;
+    }
+
+    const char* data() const
+    { return _data; }
+    char* data()
+    { return _data; }
+
+    unsigned size() const
+    { return _size; }
+
+    bool empty() const
+    { return _size == 0; }
+
+    void clear()
+    {
+        if (_capacity == 0) {
+            _data = 0;
+            _size = 0;
+        } else
+            resize(0);
+    }
+
+    void resize(unsigned size)
+    {
+        if (size == _size)
+            return;
+        if (_capacity < size) {
+            unsigned capacity = 2*_capacity;
+            if (size < capacity)
+                ensureCapacity(capacity);
+            else
+                ensureCapacity(size);
+        }
+        _size = size;
+    }
+
+    void reserve(unsigned capacity)
+    {
+        if (capacity <= _capacity)
+            return;
+        ensureCapacity(capacity);
+    }
+
+    void setData(char* data, unsigned size)
+    {
+        if (_capacity)
+            delete [] _data;
+        _data = data;
+        _size = size;
+        _capacity = 0;
+    }
+    void setData(const char* data, unsigned size)
+    {
+        resize(size);
+        if (!size)
+            return;
+        memcpy(_data, data, size);
+    }
+    void setData(const char* data)
+    {
+        if (!data) {
+            setData("", 1);
+        } else {
+            size_t size = strlen(data) + 1;
+            setData(data, size);
+        }
+    }
+
+    RTIData& operator=(const RTIData& data)
+    {
+        unsigned size = data.size();
+        if (size) {
+            resize(size);
+            memcpy(_data, data.data(), size);
+        }
+        return *this;
+    }
+
+    void getData8(char data[1], unsigned offset = 0) const
+    {
+        data[0] = _data[offset];
+    }
+
+    void setData8(const char data[1], unsigned offset = 0)
+    {
+        _data[offset] = data[0];
+    }
+
+    void getData16LE(char data[2], unsigned offset = 0) const
+    {
+        if (hostIsLittleEndian()) {
+            data[0] = _data[offset];
+            data[1] = _data[offset+1];
+        } else {
+            data[1] = _data[offset];
+            data[0] = _data[offset+1];
+        }
+    }
+    void setData16LE(const char data[2], unsigned offset = 0)
+    {
+        if (hostIsLittleEndian()) {
+            _data[offset] = data[0];
+            _data[offset+1] = data[1];
+        } else {
+            _data[offset] = data[1];
+            _data[offset+1] = data[0];
+        }
+    }
+
+    void getData16BE(char data[2], unsigned offset = 0) const
+    {
+        if (hostIsLittleEndian()) {
+            data[1] = _data[offset];
+            data[0] = _data[offset+1];
+        } else {
+            data[0] = _data[offset];
+            data[1] = _data[offset+1];
+        }
+    }
+    void setData16BE(const char data[2], unsigned offset = 0)
+    {
+        if (hostIsLittleEndian()) {
+            _data[offset] = data[1];
+            _data[offset+1] = data[0];
+        } else {
+            _data[offset] = data[0];
+            _data[offset+1] = data[1];
+        }
+    }
+
+
+    void getData32LE(char data[4], unsigned offset = 0) const
+    {
+        if (hostIsLittleEndian()) {
+            data[0] = _data[offset];
+            data[1] = _data[offset+1];
+            data[2] = _data[offset+2];
+            data[3] = _data[offset+3];
+        } else {
+            data[3] = _data[offset];
+            data[2] = _data[offset+1];
+            data[1] = _data[offset+2];
+            data[0] = _data[offset+3];
+        }
+    }
+    void setData32LE(const char data[4], unsigned offset = 0)
+    {
+        if (hostIsLittleEndian()) {
+            _data[offset] = data[0];
+            _data[offset+1] = data[1];
+            _data[offset+2] = data[2];
+            _data[offset+3] = data[3];
+        } else {
+            _data[offset] = data[3];
+            _data[offset+1] = data[2];
+            _data[offset+2] = data[1];
+            _data[offset+3] = data[0];
+        }
+    }
+
+    void getData32BE(char data[4], unsigned offset = 0) const
+    {
+        if (hostIsLittleEndian()) {
+            data[3] = _data[offset];
+            data[2] = _data[offset+1];
+            data[1] = _data[offset+2];
+            data[0] = _data[offset+3];
+        } else {
+            data[0] = _data[offset];
+            data[1] = _data[offset+1];
+            data[2] = _data[offset+2];
+            data[3] = _data[offset+3];
+        }
+    }
+    void setData32BE(const char data[4], unsigned offset = 0)
+    {
+        if (hostIsLittleEndian()) {
+            _data[offset] = data[3];
+            _data[offset+1] = data[2];
+            _data[offset+2] = data[1];
+            _data[offset+3] = data[0];
+        } else {
+            _data[offset] = data[0];
+            _data[offset+1] = data[1];
+            _data[offset+2] = data[2];
+            _data[offset+3] = data[3];
+        }
+    }
+
+
+    void getData64LE(char data[8], unsigned offset = 0) const
+    {
+        if (hostIsLittleEndian()) {
+            data[0] = _data[offset];
+            data[1] = _data[offset+1];
+            data[2] = _data[offset+2];
+            data[3] = _data[offset+3];
+            data[4] = _data[offset+4];
+            data[5] = _data[offset+5];
+            data[6] = _data[offset+6];
+            data[7] = _data[offset+7];
+        } else {
+            data[7] = _data[offset];
+            data[6] = _data[offset+1];
+            data[5] = _data[offset+2];
+            data[4] = _data[offset+3];
+            data[3] = _data[offset+4];
+            data[2] = _data[offset+5];
+            data[1] = _data[offset+6];
+            data[0] = _data[offset+7];
+        }
+    }
+    void setData64LE(const char data[8], unsigned offset = 0)
+    {
+        if (hostIsLittleEndian()) {
+            _data[offset] = data[0];
+            _data[offset+1] = data[1];
+            _data[offset+2] = data[2];
+            _data[offset+3] = data[3];
+            _data[offset+4] = data[4];
+            _data[offset+5] = data[5];
+            _data[offset+6] = data[6];
+            _data[offset+7] = data[7];
+        } else {
+            _data[offset] = data[7];
+            _data[offset+1] = data[6];
+            _data[offset+2] = data[5];
+            _data[offset+3] = data[4];
+            _data[offset+4] = data[3];
+            _data[offset+5] = data[2];
+            _data[offset+6] = data[1];
+            _data[offset+7] = data[0];
+        }
+    }
+
+    void getData64BE(char data[8], unsigned offset = 0) const
+    {
+        if (hostIsLittleEndian()) {
+            data[7] = _data[offset];
+            data[6] = _data[offset+1];
+            data[5] = _data[offset+2];
+            data[4] = _data[offset+3];
+            data[3] = _data[offset+4];
+            data[2] = _data[offset+5];
+            data[1] = _data[offset+6];
+            data[0] = _data[offset+7];
+        } else {
+            data[0] = _data[offset];
+            data[1] = _data[offset+1];
+            data[2] = _data[offset+2];
+            data[3] = _data[offset+3];
+            data[4] = _data[offset+4];
+            data[5] = _data[offset+5];
+            data[6] = _data[offset+6];
+            data[7] = _data[offset+7];
+        }
+    }
+    void setData64BE(const char data[8], unsigned offset = 0)
+    {
+        if (hostIsLittleEndian()) {
+            _data[offset] = data[7];
+            _data[offset+1] = data[6];
+            _data[offset+2] = data[5];
+            _data[offset+3] = data[4];
+            _data[offset+4] = data[3];
+            _data[offset+5] = data[2];
+            _data[offset+6] = data[1];
+            _data[offset+7] = data[0];
+        } else {
+            _data[offset] = data[0];
+            _data[offset+1] = data[1];
+            _data[offset+2] = data[2];
+            _data[offset+3] = data[3];
+            _data[offset+4] = data[4];
+            _data[offset+5] = data[5];
+            _data[offset+6] = data[6];
+            _data[offset+7] = data[7];
+        }
+    }
+
+
+#define TYPED_GETSET_IMPLEMENTATION(type, base, suffix)         \
+    type get##base##suffix(unsigned offset = 0) const           \
+    {                                                           \
+        union {                                                 \
+            type t;                                             \
+            char u8[sizeof(type)];                              \
+        } u;                                                    \
+        getData##suffix(u.u8, offset);                          \
+        return u.t;                                             \
+    }                                                           \
+    void set##base##suffix(type value, unsigned offset = 0)     \
+    {                                                           \
+        union {                                                 \
+            type t;                                             \
+            char u8[sizeof(type)];                              \
+        } u;                                                    \
+        u.t = value;                                            \
+        setData##suffix(u.u8, offset);                          \
+    }
+
+    TYPED_GETSET_IMPLEMENTATION(uint8_t, UInt, 8)
+    TYPED_GETSET_IMPLEMENTATION(int8_t, Int, 8)
+    TYPED_GETSET_IMPLEMENTATION(uint16_t, UInt, 16LE)
+    TYPED_GETSET_IMPLEMENTATION(uint16_t, UInt, 16BE)
+    TYPED_GETSET_IMPLEMENTATION(int16_t, Int, 16LE)
+    TYPED_GETSET_IMPLEMENTATION(int16_t, Int, 16BE)
+    TYPED_GETSET_IMPLEMENTATION(uint32_t, UInt, 32LE)
+    TYPED_GETSET_IMPLEMENTATION(uint32_t, UInt, 32BE)
+    TYPED_GETSET_IMPLEMENTATION(int32_t, Int, 32LE)
+    TYPED_GETSET_IMPLEMENTATION(int32_t, Int, 32BE)
+    TYPED_GETSET_IMPLEMENTATION(uint64_t, UInt, 64LE)
+    TYPED_GETSET_IMPLEMENTATION(uint64_t, UInt, 64BE)
+    TYPED_GETSET_IMPLEMENTATION(int64_t, Int, 64LE)
+    TYPED_GETSET_IMPLEMENTATION(int64_t, Int, 64BE)
+
+    TYPED_GETSET_IMPLEMENTATION(float, Float, 32LE)
+    TYPED_GETSET_IMPLEMENTATION(float, Float, 32BE)
+    TYPED_GETSET_IMPLEMENTATION(double, Float, 64LE)
+    TYPED_GETSET_IMPLEMENTATION(double, Float, 64BE)
+
+#undef TYPED_GETSET_IMPLEMENTATION
+
+private:
+    static inline bool hostIsLittleEndian()
+    {
+        union {
+            uint16_t u16;
+            uint8_t u8[2];
+        } u;
+        u.u16 = 1;
+        return u.u8[0] == 1;
+    }
+
+    void ensureCapacity(unsigned capacity)
+    {
+        if (capacity < 32)
+            capacity = 32;
+        char* data = new char[capacity];
+        if (_size)
+            memcpy(data, _data, _size);
+        if (_capacity)
+            delete [] _data;
+        _data = data;
+        _capacity = capacity;
+    }
+
+    char* _data;
+    unsigned _size;
+    unsigned _capacity;
+};
+
+// A single attribute/parameter update blob
+typedef std::pair<unsigned, RTIData> RTIIndexDataPair;
+
+// A complete set of updates we received in one reflect/receive call
+typedef std::list<RTIIndexDataPair> RTIIndexDataPairList;
+
+/// Gets an own header at some time
+
+class RTIBasicDataStream {
+public:
+    RTIBasicDataStream() : _offset(0) {}
+
+    /// Get aligned offset that aligns to a multiple of size
+    static inline unsigned getAlignedOffset(unsigned offset, unsigned size)
+    {
+        return ((offset + size - 1)/size) * size;
+    }
+
+protected:
+    unsigned _offset;
+};
+
+class HLADecodeStream : public RTIBasicDataStream {
+public:
+    HLADecodeStream(const RTIData& value) :
+        _value(value)
+    { }
+
+    bool alignOffsetForSize(unsigned size)
+    {
+        _offset = getAlignedOffset(_offset, size);
+        return _offset <= _value.size();
+    }
+
+    bool skip(unsigned size)
+    {
+        _offset += size;
+        return _offset <= _value.size();
+    }
+
+    bool eof() const
+    { return _value.size() <= _offset; }
+
+    const RTIData& getData() const
+    { return _value; }
+
+#define TYPED_READ_IMPLEMENTATION(type, base, suffix)           \
+    bool decode##base##suffix(type& value)                      \
+    {                                                           \
+        if (_value.size() < _offset + sizeof(type))             \
+            return false;                                       \
+        value = _value.get##base##suffix(_offset);              \
+        _offset += sizeof(type);                                \
+        return true;                                            \
+    }
+
+    TYPED_READ_IMPLEMENTATION(uint8_t, UInt, 8)
+    TYPED_READ_IMPLEMENTATION(int8_t, Int, 8)
+    TYPED_READ_IMPLEMENTATION(uint16_t, UInt, 16LE)
+    TYPED_READ_IMPLEMENTATION(uint16_t, UInt, 16BE)
+    TYPED_READ_IMPLEMENTATION(int16_t, Int, 16LE)
+    TYPED_READ_IMPLEMENTATION(int16_t, Int, 16BE)
+    TYPED_READ_IMPLEMENTATION(uint32_t, UInt, 32LE)
+    TYPED_READ_IMPLEMENTATION(uint32_t, UInt, 32BE)
+    TYPED_READ_IMPLEMENTATION(int32_t, Int, 32LE)
+    TYPED_READ_IMPLEMENTATION(int32_t, Int, 32BE)
+    TYPED_READ_IMPLEMENTATION(uint64_t, UInt, 64LE)
+    TYPED_READ_IMPLEMENTATION(uint64_t, UInt, 64BE)
+    TYPED_READ_IMPLEMENTATION(int64_t, Int, 64LE)
+    TYPED_READ_IMPLEMENTATION(int64_t, Int, 64BE)
+
+    TYPED_READ_IMPLEMENTATION(float, Float, 32LE)
+    TYPED_READ_IMPLEMENTATION(float, Float, 32BE)
+    TYPED_READ_IMPLEMENTATION(double, Float, 64LE)
+    TYPED_READ_IMPLEMENTATION(double, Float, 64BE)
+
+#undef TYPED_READ_IMPLEMENTATION
+
+private:
+    const RTIData& _value;
+};
+
+class HLAEncodeStream : public RTIBasicDataStream {
+public:
+    HLAEncodeStream(RTIData& value) :
+        _value(value)
+    { }
+
+    bool alignOffsetForSize(unsigned size)
+    {
+        _offset = getAlignedOffset(_offset, size);
+        _value.resize(_offset);
+        return true;
+    }
+
+    bool skip(unsigned size)
+    {
+        _offset += size;
+        _value.resize(_offset);
+        return true;
+    }
+
+    bool eof() const
+    { return _value.size() <= _offset; }
+
+    void setData(const RTIData& data)
+    { _value = data; }
+
+#define TYPED_WRITE_IMPLEMENTATION(type, base, suffix)                  \
+    bool encode##base##suffix(type value)                               \
+    {                                                                   \
+        unsigned nextOffset = _offset + sizeof(type);                   \
+        _value.resize(nextOffset);                                      \
+        _value.set##base##suffix(value, _offset);                       \
+        _offset = nextOffset;                                           \
+        return true;                                                    \
+    }
+
+    TYPED_WRITE_IMPLEMENTATION(uint8_t, UInt, 8)
+    TYPED_WRITE_IMPLEMENTATION(int8_t, Int, 8)
+    TYPED_WRITE_IMPLEMENTATION(uint16_t, UInt, 16LE)
+    TYPED_WRITE_IMPLEMENTATION(uint16_t, UInt, 16BE)
+    TYPED_WRITE_IMPLEMENTATION(int16_t, Int, 16LE)
+    TYPED_WRITE_IMPLEMENTATION(int16_t, Int, 16BE)
+    TYPED_WRITE_IMPLEMENTATION(uint32_t, UInt, 32LE)
+    TYPED_WRITE_IMPLEMENTATION(uint32_t, UInt, 32BE)
+    TYPED_WRITE_IMPLEMENTATION(int32_t, Int, 32LE)
+    TYPED_WRITE_IMPLEMENTATION(int32_t, Int, 32BE)
+    TYPED_WRITE_IMPLEMENTATION(uint64_t, UInt, 64LE)
+    TYPED_WRITE_IMPLEMENTATION(uint64_t, UInt, 64BE)
+    TYPED_WRITE_IMPLEMENTATION(int64_t, Int, 64LE)
+    TYPED_WRITE_IMPLEMENTATION(int64_t, Int, 64BE)
+
+    TYPED_WRITE_IMPLEMENTATION(float, Float, 32LE)
+    TYPED_WRITE_IMPLEMENTATION(float, Float, 32BE)
+    TYPED_WRITE_IMPLEMENTATION(double, Float, 64LE)
+    TYPED_WRITE_IMPLEMENTATION(double, Float, 64BE)
+
+#undef TYPED_WRITE_IMPLEMENTATION
+
+private:
+    RTIData& _value;
+};
+
+} // namespace simgear
+
+#endif
diff --git a/simgear/hla/RTIFederate.cxx b/simgear/hla/RTIFederate.cxx
new file mode 100644 (file)
index 0000000..5d754fb
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "RTIFederate.hxx"
+
+namespace simgear {
+
+RTIFederate::RTIFederate()
+{
+}
+
+RTIFederate::~RTIFederate()
+{
+}
+
+}
diff --git a/simgear/hla/RTIFederate.hxx b/simgear/hla/RTIFederate.hxx
new file mode 100644 (file)
index 0000000..4b5d2d8
--- /dev/null
@@ -0,0 +1,96 @@
+// Copyright (C) 2009 - 2010  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 RTIFederate_hxx
+#define RTIFederate_hxx
+
+#include <string>
+#include "simgear/structure/SGWeakReferenced.hxx"
+#include "RTIObjectClass.hxx"
+#include "RTIObjectInstance.hxx"
+
+class SGTimeStamp;
+
+namespace simgear {
+
+class RTIFederate : public SGWeakReferenced {
+public:
+    RTIFederate();
+    virtual ~RTIFederate();
+
+    /// Get the name of the joined federate/federation
+    const std::string& getFederateType() const
+    { return _federateType; }
+    const std::string& getFederationName() const
+    { return _federationName; }
+
+    /// Create a federation execution
+    /// Semantically this methods should be static,
+    /// but the nonstatic case could reuse the connection to the server
+    /// FIXME: cannot determine from the return value if we created the execution
+    virtual bool createFederationExecution(const std::string& federation, const std::string& objectModel) = 0;
+    virtual bool destroyFederationExecution(const std::string& federation) = 0;
+
+    /// Join with federateName the federation execution federation
+    virtual bool join(const std::string& federateType, const std::string& federation) = 0;
+    virtual bool resign() = 0;
+
+    /// Synchronization Point handling
+    virtual bool registerFederationSynchronizationPoint(const std::string& label, const RTIData& tag) = 0;
+    virtual bool waitForFederationSynchronizationPointAnnounced(const std::string& label) = 0;
+    virtual bool synchronizationPointAchieved(const std::string& label) = 0;
+    virtual bool waitForFederationSynchronized(const std::string& label) = 0;
+
+    /// Time management
+    virtual bool enableTimeConstrained() = 0;
+    virtual bool disableTimeConstrained() = 0;
+
+    virtual bool enableTimeRegulation(const SGTimeStamp& lookahead) = 0;
+    virtual bool disableTimeRegulation() = 0;
+
+    virtual bool timeAdvanceRequestBy(const SGTimeStamp& dt) = 0;
+    virtual bool timeAdvanceRequest(const SGTimeStamp& fedTime) = 0;
+
+    /// Process messages
+    virtual bool tick() = 0;
+    virtual bool tick(const double& minimum, const double& maximum) = 0;
+
+    virtual RTIObjectClass* createObjectClass(const std::string& name, HLAObjectClass* hlaObjectClass) = 0;
+    // virtual RTIInteractionClass* createInteractionClass(const std::string& name) = 0;
+
+    virtual RTIObjectInstance* getObjectInstance(const std::string& name) = 0;
+
+protected:
+    void setFederateType(const std::string& federateType)
+    { _federateType = federateType; }
+    void setFederationName(const std::string& federationName)
+    { _federationName = federationName; }
+
+private:
+    RTIFederate(const RTIFederate&);
+    RTIFederate& operator=(const RTIFederate&);
+
+    /// The federates name
+    std::string _federateType;
+
+    /// The federation execution name
+    std::string _federationName;
+};
+
+}
+
+#endif
diff --git a/simgear/hla/RTIInteractionClass.hxx b/simgear/hla/RTIInteractionClass.hxx
new file mode 100644 (file)
index 0000000..9cfafbd
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright (C) 2009 - 2010  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 RTIInteractionClass_hxx
+#define RTIInteractionClass_hxx
+
+#include <set>
+#include <string>
+#include <vector>
+#include "simgear/structure/SGReferenced.hxx"
+#include "simgear/structure/SGSharedPtr.hxx"
+#include "simgear/structure/SGReferenced.hxx"
+#include "RTIData.hxx"
+
+namespace simgear {
+
+class RTIInteractionClass : public SGReferenced {
+public:
+    RTIInteractionClass(const std::string& name);
+    virtual ~RTIInteractionClass();
+
+    const std::string& getName() const
+    { return _name; }
+
+    virtual unsigned getNumParameters() const = 0;
+    virtual unsigned getParameterIndex(const std::string& name) const = 0;
+    virtual unsigned getOrCreateParameterIndex(const std::string& name) = 0;
+
+    virtual bool publish(const std::set<unsigned>& indexSet) = 0;
+    virtual bool unpublish() = 0;
+
+    virtual bool subscribe(const std::set<unsigned>& indexSet, bool) = 0;
+    virtual bool unsubscribe() = 0;
+
+    virtual void send(const RTIData& tag) = 0;
+    virtual void send(const SGTimeStamp& timeStamp, const RTIData& tag) = 0;
+
+    class ReceiveCallback : public SGReferenced {
+    public:
+        virtual ~ReceiveCallback() {}
+    };
+
+private:
+    std::string _name;
+};
+
+}
+
+#endif
diff --git a/simgear/hla/RTIObjectClass.cxx b/simgear/hla/RTIObjectClass.cxx
new file mode 100644 (file)
index 0000000..98618cf
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "RTIObjectClass.hxx"
+
+#include "RTIObjectInstance.hxx"
+
+namespace simgear {
+
+RTIObjectClass::RTIObjectClass(HLAObjectClass* hlaObjectClass) :
+    _hlaObjectClass(hlaObjectClass)
+{
+}
+
+RTIObjectClass::~RTIObjectClass()
+{
+}
+
+void
+RTIObjectClass::discoverInstance(RTIObjectInstance* objectInstance, const RTIData& tag) const
+{
+    SGSharedPtr<HLAObjectClass> hlaObjectClass = _hlaObjectClass.lock();
+    if (!hlaObjectClass.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid hla object class pointer in RTIObjectClass::discoverInstance().");
+        return;
+    }
+    hlaObjectClass->discoverInstance(objectInstance, tag);
+}
+
+void
+RTIObjectClass::startRegistration() const
+{
+    SGSharedPtr<HLAObjectClass> hlaObjectClass = _hlaObjectClass.lock();
+    if (!hlaObjectClass.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid hla object class pointer in RTIObjectClass::startRegstration().");
+        return;
+    }
+    hlaObjectClass->startRegistrationCallback();
+}
+
+void
+RTIObjectClass::stopRegistration() const
+{
+    SGSharedPtr<HLAObjectClass> hlaObjectClass = _hlaObjectClass.lock();
+    if (!hlaObjectClass.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid hla object class pointer in RTIObjectClass::stopRegistration().");
+        return;
+    }
+    hlaObjectClass->stopRegistrationCallback();
+}
+
+}
diff --git a/simgear/hla/RTIObjectClass.hxx b/simgear/hla/RTIObjectClass.hxx
new file mode 100644 (file)
index 0000000..e659b98
--- /dev/null
@@ -0,0 +1,122 @@
+// Copyright (C) 2009 - 2010  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 RTIObjectClass_hxx
+#define RTIObjectClass_hxx
+
+#include <string>
+#include <vector>
+#include "simgear/structure/SGReferenced.hxx"
+#include "simgear/structure/SGSharedPtr.hxx"
+#include "simgear/structure/SGWeakPtr.hxx"
+#include "RTIData.hxx"
+#include "HLAObjectClass.hxx"
+
+namespace simgear {
+
+class RTIObjectInstance;
+class HLAObjectClass;
+
+class RTIObjectClass : public SGReferenced {
+public:
+    RTIObjectClass(HLAObjectClass* hlaObjectClass);
+    virtual ~RTIObjectClass();
+
+    virtual std::string getName() const = 0;
+
+    virtual unsigned getNumAttributes() const = 0;
+    virtual unsigned getAttributeIndex(const std::string& name) const = 0;
+    virtual unsigned getOrCreateAttributeIndex(const std::string& name) = 0;
+
+    virtual bool publish(const std::set<unsigned>& indexSet) = 0;
+    virtual bool unpublish() = 0;
+
+    virtual bool subscribe(const std::set<unsigned>& indexSet, bool) = 0;
+    virtual bool unsubscribe() = 0;
+
+    // Factory to create an object instance that can be used in this current federate
+    virtual RTIObjectInstance* registerObjectInstance(HLAObjectInstance*) = 0;
+
+    void discoverInstance(RTIObjectInstance* objectInstance, const RTIData& tag) const;
+
+    void startRegistration() const;
+    void stopRegistration() const;
+
+    void setAttributeDataType(unsigned index, SGSharedPtr<const HLADataType> dataType)
+    {
+        if (_attributeDataVector.size() <= index)
+            return;
+        _attributeDataVector[index]._dataType = dataType;
+    }
+    const HLADataType* getAttributeDataType(unsigned index) const
+    {
+        if (_attributeDataVector.size() <= index)
+            return 0;
+        return _attributeDataVector[index]._dataType.get();
+    }
+
+    HLAUpdateType getAttributeUpdateType(unsigned index) const
+    {
+        if (_attributeDataVector.size() <= index)
+            return HLAUndefinedUpdate;
+        return _attributeDataVector[index]._updateType;
+    }
+    void setAttributeUpdateType(unsigned index, HLAUpdateType updateType)
+    {
+        if (_attributeDataVector.size() <= index)
+            return;
+        _attributeDataVector[index]._updateType = updateType;
+    }
+
+    bool getAttributeSubscribed(unsigned index) const
+    {
+        if (_attributeDataVector.size() <= index)
+            return false;
+        return _attributeDataVector[index]._subscribed;
+    }
+    bool getAttributePublished(unsigned index) const
+    {
+        if (_attributeDataVector.size() <= index)
+            return false;
+        return _attributeDataVector[index]._published;
+    }
+    std::string getAttributeName(unsigned index) const
+    {
+        if (_attributeDataVector.size() <= index)
+            return std::string();
+        return _attributeDataVector[index]._name;
+    }
+
+protected:
+    struct AttributeData {
+        AttributeData(const std::string& name) : _name(name), _subscribed(false), _published(false), _updateType(HLAUndefinedUpdate) {}
+        std::string _name;
+        SGSharedPtr<const HLADataType> _dataType;
+        bool _subscribed;
+        bool _published;
+        HLAUpdateType _updateType;
+    };
+    typedef std::vector<AttributeData> AttributeDataVector;
+    AttributeDataVector _attributeDataVector;
+
+private:
+    SGWeakPtr<HLAObjectClass> _hlaObjectClass;
+};
+
+}
+
+#endif
diff --git a/simgear/hla/RTIObjectInstance.cxx b/simgear/hla/RTIObjectInstance.cxx
new file mode 100644 (file)
index 0000000..7454414
--- /dev/null
@@ -0,0 +1,90 @@
+// Copyright (C) 2009 - 2010  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.
+//
+
+#include "RTIObjectInstance.hxx"
+#include "RTIObjectClass.hxx"
+#include "HLAObjectInstance.hxx"
+
+namespace simgear {
+
+RTIObjectInstance::RTIObjectInstance(HLAObjectInstance* hlaObjectInstance) :
+    _hlaObjectInstance(hlaObjectInstance),
+    _pendingAttributeUpdateRequest(false)
+{
+}
+
+RTIObjectInstance::~RTIObjectInstance()
+{
+}
+
+unsigned
+RTIObjectInstance::getNumAttributes() const
+{
+    return getObjectClass()->getNumAttributes();
+}
+
+unsigned
+RTIObjectInstance::getAttributeIndex(const std::string& name) const
+{
+    return getObjectClass()->getAttributeIndex(name);
+}
+
+std::string
+RTIObjectInstance::getAttributeName(unsigned index) const
+{
+    return getObjectClass()->getAttributeName(index);
+}
+
+void
+RTIObjectInstance::removeInstance(const RTIData& tag)
+{
+    SGSharedPtr<HLAObjectInstance> hlaObjectInstance =  _hlaObjectInstance.lock();
+    if (!hlaObjectInstance.valid())
+        return;
+    hlaObjectInstance->removeInstance(tag);
+}
+
+void
+RTIObjectInstance::reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag)
+{
+    for (RTIIndexDataPairList::const_iterator i = dataPairList.begin();
+         i != dataPairList.end(); ++i) {
+        reflectAttributeValue(i->first, i->second);
+    }
+
+    SGSharedPtr<HLAObjectInstance> hlaObjectInstance =  _hlaObjectInstance.lock();
+    if (!hlaObjectInstance.valid())
+        return;
+    hlaObjectInstance->reflectAttributeValues(dataPairList, tag);
+}
+
+void
+RTIObjectInstance::reflectAttributeValues(const RTIIndexDataPairList& dataPairList,
+                                          const SGTimeStamp& timeStamp, const RTIData& tag)
+{
+    for (RTIIndexDataPairList::const_iterator i = dataPairList.begin();
+         i != dataPairList.end(); ++i) {
+        reflectAttributeValue(i->first, i->second);
+    }
+
+    SGSharedPtr<HLAObjectInstance> hlaObjectInstance =  _hlaObjectInstance.lock();
+    if (!hlaObjectInstance.valid())
+        return;
+    hlaObjectInstance->reflectAttributeValues(dataPairList, timeStamp, tag);
+}
+
+}
diff --git a/simgear/hla/RTIObjectInstance.hxx b/simgear/hla/RTIObjectInstance.hxx
new file mode 100644 (file)
index 0000000..fb8f096
--- /dev/null
@@ -0,0 +1,354 @@
+// Copyright (C) 2009 - 2010  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 RTIObjectInstance_hxx
+#define RTIObjectInstance_hxx
+
+#include <list>
+#include <map>
+#include <string>
+#include <vector>
+#include "simgear/debug/logstream.hxx"
+#include "simgear/structure/SGReferenced.hxx"
+#include "simgear/structure/SGWeakPtr.hxx"
+#include "simgear/timing/timestamp.hxx"
+#include "RTIData.hxx"
+#include "RTIObjectClass.hxx"
+#include "HLADataElement.hxx"
+
+class SGTimeStamp;
+
+namespace simgear {
+
+class RTIObjectClass;
+class HLAObjectInstance;
+
+class RTIObjectInstance : public SGReferenced {
+public:
+    RTIObjectInstance(HLAObjectInstance* hlaObjectInstance);
+    virtual ~RTIObjectInstance();
+
+    virtual const RTIObjectClass* getObjectClass() const = 0;
+
+    virtual std::string getName() const = 0;
+
+    unsigned getNumAttributes() const;
+    unsigned getAttributeIndex(const std::string& name) const;
+    std::string getAttributeName(unsigned index) const;
+
+    // FIXME: factor out an ambassador base
+    virtual void addToRequestQueue() = 0;
+
+    virtual void deleteObjectInstance(const RTIData& tag) = 0;
+    virtual void deleteObjectInstance(const SGTimeStamp& timeStamp, const RTIData& tag) = 0;
+    virtual void localDeleteObjectInstance() = 0;
+
+    virtual void requestObjectAttributeValueUpdate() = 0;
+
+    virtual void updateAttributeValues(const RTIData& tag) = 0;
+    virtual void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag) = 0;
+
+    void removeInstance(const RTIData& tag);
+    // Call this if you want to roll up the queued timestamed updates
+    // and reflect that into the attached data elements.
+    void reflectQueuedAttributeValues(const SGTimeStamp& timeStamp)
+    {
+        // replay all updates up to the given timestamp
+        UpdateListMap::iterator last = _updateListMap.upper_bound(timeStamp);
+        for (UpdateListMap::iterator i = _updateListMap.begin(); i != last; ++i) {
+            for (UpdateList::iterator j = i->second.begin(); j != i->second.end(); ++j) {
+                // FIXME have a variant that takes the timestamp?
+                reflectAttributeValues(j->_indexDataPairList, j->_tag);
+            }
+            putUpdateToPool(i->second);
+        }
+    }
+    void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag);
+    void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const SGTimeStamp& timeStamp, const RTIData& tag);
+    void reflectAttributeValue(unsigned i, const RTIData& data)
+    {
+        if (_attributeData.size() <= i)
+            return;
+        HLADataElement* dataElement = _attributeData[i]._dataElement.get();
+        if (!dataElement)
+            return;
+        HLADecodeStream stream(data);
+        dataElement->decode(stream);
+    }
+
+    const HLADataType* getAttributeDataType(unsigned i) const
+    {
+        return getObjectClass()->getAttributeDataType(i);
+    }
+    HLAUpdateType getAttributeUpdateType(unsigned i) const
+    {
+        return getObjectClass()->getAttributeUpdateType(i);
+    }
+    bool getAttributeSubscribed(unsigned i) const
+    {
+        return getObjectClass()->getAttributeSubscribed(i);
+    }
+    bool getAttributePublished(unsigned i) const
+    {
+        return getObjectClass()->getAttributePublished(i);
+    }
+
+    HLADataElement* getDataElement(unsigned i)
+    {
+        if (_attributeData.size() <= i)
+            return 0;
+        return _attributeData[i]._dataElement.get();
+    }
+    const HLADataElement* getDataElement(unsigned i) const
+    {
+        if (_attributeData.size() <= i)
+            return 0;
+        return _attributeData[i]._dataElement.get();
+    }
+    void setDataElement(unsigned i, HLADataElement* dataElement)
+    {
+        if (_attributeData.size() <= i)
+            return;
+        _attributeData[i]._dataElement = dataElement;
+    }
+
+    void updateAttributesFromClass(bool owned)
+    {
+        // FIXME: rethink that!!!
+        unsigned numAttributes = getNumAttributes();
+        unsigned i = 0;
+        for (; i < _attributeData.size(); ++i) {
+            if (getAttributePublished(i)) {
+            } else {
+                _attributeData[i].setUpdateEnabled(false);
+                _attributeData[i].setOwned(false);
+            }
+        }
+        _attributeData.resize(numAttributes);
+        for (; i < numAttributes; ++i) {
+            if (getAttributePublished(i)) {
+                _attributeData[i].setUpdateEnabled(true);
+                _attributeData[i].setOwned(owned);
+            } else {
+                _attributeData[i].setUpdateEnabled(false);
+                _attributeData[i].setOwned(false);
+            }
+        }
+    }
+
+    void setAttributeForceUpdate(unsigned i)
+    {
+        if (_attributeData.size() <= i)
+            return;
+        _attributeData[i].setForceUpdate(true);
+    }
+    void setAttributeInScope(unsigned i, bool inScope)
+    {
+        if (_attributeData.size() <= i)
+            return;
+        _attributeData[i].setInScope(inScope);
+    }
+    void setAttributeUpdateEnabled(unsigned i, bool enabled)
+    {
+        if (_attributeData.size() <= i)
+            return;
+        _attributeData[i].setUpdateEnabled(enabled);
+    }
+    void setAttributeUpdated(unsigned i)
+    {
+        if (_attributeData.size() <= i)
+            return;
+        _attributeData[i].setForceUpdate(false);
+    }
+    bool getAttributeEffectiveUpdateEnabled(unsigned i)
+    {
+        if (_attributeData.size() <= i)
+            return false;
+        if (!getAttributePublished(i))
+            return false;
+        if (!_attributeData[i]._updateEnabled)
+            return false;
+        if (!_attributeData[i]._inScope)
+            return false;
+        if (_attributeData[i]._forceUpdate)
+            return true;
+        switch (getAttributeUpdateType(i)) {
+        case HLAPeriodicUpdate:
+            return true;
+        case HLAConditionalUpdate:
+            return true; // FIXME
+        case HLAStaticUpdate:
+            return false;
+        default:
+            return false;
+        }
+    }
+    void setRequestAttributeUpdate(bool request)
+    {
+        for (unsigned i = 0; i < getNumAttributes(); ++i) {
+            if (getAttributeUpdateType(i) == HLAPeriodicUpdate)
+                continue;
+            setRequestAttributeUpdate(i, request);
+        }
+    }
+    void setRequestAttributeUpdate(unsigned i, bool request)
+    {
+        if (_attributeData.size() <= i)
+            return;
+        _attributeData[i].setRequestUpdate(request);
+        if (request) {
+            if (!_pendingAttributeUpdateRequest) {
+                _pendingAttributeUpdateRequest = true;
+                addToRequestQueue();
+            }
+        }
+    }
+    bool getRequestAttributeUpdate(unsigned i) const
+    {
+        if (_attributeData.size() <= i)
+            return false;
+        return _attributeData[i]._requestUpdate;
+    }
+
+    void flushPendingRequests()
+    {
+        if (_pendingAttributeUpdateRequest) {
+            requestObjectAttributeValueUpdate();
+            _pendingAttributeUpdateRequest = false;
+        }
+    }
+
+protected:
+    // The backward reference to the user visible object
+    SGWeakPtr<HLAObjectInstance> _hlaObjectInstance;
+
+    // Is true if we should emit a requestattr
+    bool _pendingAttributeUpdateRequest;
+
+    // Contains a full update as it came in from the RTI
+    struct Update {
+        RTIIndexDataPairList _indexDataPairList;
+        RTIData _tag;
+    };
+    // A bunch of updates for the same timestamp
+    typedef std::list<Update> UpdateList;
+    // The timestamp sorted list of updates
+    typedef std::map<SGTimeStamp, UpdateList> UpdateListMap;
+
+    // The timestamped updates sorted by timestamp
+    UpdateListMap _updateListMap;
+
+    // The pool of unused updates so that we do not need to malloc/free each time
+    UpdateList _updateList;
+
+    void getUpdateFromPool(UpdateList& updateList)
+    {
+        if (_updateList.empty())
+            updateList.push_back(Update());
+        else
+            updateList.splice(updateList.end(), _updateList, _updateList.begin());
+    }
+    void putUpdateToPool(UpdateList& updateList)
+    {
+        for (UpdateList::iterator i = updateList.begin(); i != updateList.end(); ++i)
+            putDataToPool(i->_indexDataPairList);
+        _updateList.splice(_updateList.end(), updateList);
+    }
+
+    // Appends the updates in the list to the given timestamps updates
+    void scheduleUpdates(const SGTimeStamp& timeStamp, UpdateList& updateList)
+    {
+        UpdateListMap::iterator i = _updateListMap.find(timeStamp);
+        if (i == _updateListMap.end())
+            i = _updateListMap.insert(UpdateListMap::value_type(timeStamp, UpdateList())).first;
+        i->second.splice(i->second.end(), updateList);
+    }
+
+    // This adds raw storage for attribute index i to the end of the dataPairList.
+    void getDataFromPool(unsigned i, RTIIndexDataPairList& dataPairList)
+    {
+        if (_attributeData.size() <= i) {
+            SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid object attribute index!");
+            return;
+        }
+
+        // Nothing left in the pool - so allocate something
+        if (_attributeData[i]._indexDataPairList.empty()) {
+            dataPairList.push_back(RTIIndexDataPairList::value_type());
+            dataPairList.back().first = i;
+            return;
+        }
+
+        // Take one from the pool
+        dataPairList.splice(dataPairList.end(),
+                            _attributeData[i]._indexDataPairList,
+                            _attributeData[i]._indexDataPairList.begin());
+    }
+
+    void putDataToPool(RTIIndexDataPairList& dataPairList)
+    {
+        while (!dataPairList.empty()) {
+            // Put back into the pool
+            unsigned i = dataPairList.front().first;
+            if (_attributeData.size() <= i) {
+                // should not happen!!!
+                SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid object attribute index!");
+                dataPairList.pop_front();
+            } else {
+                _attributeData[i]._indexDataPairList.splice(_attributeData[i]._indexDataPairList.begin(),
+                                                            dataPairList, dataPairList.begin());
+            }
+        }
+    }
+
+    struct AttributeData {
+        AttributeData() : _owned(false), _inScope(true), _updateEnabled(true), _forceUpdate(false), _requestUpdate(false)
+        { }
+
+        // The hla level data element with tha actual local program
+        // accessible data.
+        SGSharedPtr<HLADataElement> _dataElement;
+        // SGSharedPtr<HLADataElement::TimeStamp> _timeStamp;
+
+        // Pool of already allocated raw data used for reflection of updates
+        RTIIndexDataPairList _indexDataPairList;
+
+        void setOwned(bool owned)
+        { _owned = owned; }
+        void setInScope(bool inScope)
+        { _inScope = inScope; }
+        void setUpdateEnabled(bool updateEnabled)
+        { _updateEnabled = updateEnabled; }
+        void setForceUpdate(bool forceUpdate)
+        { _forceUpdate = forceUpdate; }
+        void setRequestUpdate(bool requestUpdate)
+        { _requestUpdate = requestUpdate; }
+
+        bool _owned;
+        bool _inScope;
+        bool _updateEnabled;
+        bool _forceUpdate;
+        bool _requestUpdate;
+    };
+    std::vector<AttributeData> _attributeData;
+
+    friend class HLAObjectInstance;
+};
+
+}
+
+#endif