clearStamp();
}
+bool
+HLAArrayDataElement::setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement)
+{
+ // Must have happened in the parent
+ if (begin == end)
+ return false;
+ unsigned index = *begin;
+ if (++begin != end) {
+ if (getNumElements() <= index && !setNumElements(index + 1))
+ return false;
+ if (!getElement(index) && getElementDataType()) {
+ HLADataElementFactoryVisitor visitor;
+ getElementDataType()->accept(visitor);
+ setElement(index, visitor.getDataElement());
+ }
+ if (!getElement(index))
+ return false;
+ return getElement(index)->setDataElement(begin, end, dataElement);
+ } else {
+ if (!dataElement->setDataType(getElementDataType()))
+ return false;
+ setElement(index, dataElement);
+ return true;
+ }
+}
+
+HLADataElement*
+HLAArrayDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end)
+{
+ if (begin == end)
+ return this;
+ HLADataElement* dataElement = getElement(*begin);
+ if (!dataElement)
+ return 0;
+ return dataElement->getDataElement(++begin, end);
+}
+
+const HLADataElement*
+HLAArrayDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const
+{
+ if (begin == end)
+ return this;
+ const HLADataElement* dataElement = getElement(*begin);
+ if (!dataElement)
+ return 0;
+ return dataElement->getDataElement(++begin, end);
+}
+
bool
HLAArrayDataElement::setNumElements(unsigned size)
{
HLAArrayDataElement(const HLAArrayDataType* dataType = 0);
virtual ~HLAArrayDataElement();
+ virtual bool setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement);
+ virtual HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end);
+ virtual const HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const;
+
virtual bool setNumElements(unsigned size);
virtual bool decodeElement(HLADecodeStream& stream, unsigned i);
virtual unsigned getNumElements() const;
{
}
+bool
+HLADataElement::setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement)
+{
+ return false;
+}
+
+HLADataElement*
+HLADataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end)
+{
+ if (begin != end)
+ return 0;
+ return this;
+}
+
+const HLADataElement*
+HLADataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const
+{
+ if (begin != end)
+ return 0;
+ return this;
+}
+
void
HLADataElement::setTimeStamp(const SGTimeStamp& timeStamp)
{
#include <simgear/timing/timestamp.hxx>
#include "RTIData.hxx"
#include "HLADataType.hxx"
+#include "HLATypes.hxx"
class SGTimeStamp;
virtual const HLADataType* getDataType() const = 0;
virtual bool setDataType(const HLADataType* dataType) = 0;
+ bool setDataElement(const HLADataElementIndex& index, HLADataElement* dataElement)
+ { return setDataElement(index.begin(), index.end(), dataElement); }
+ HLADataElement* getDataElement(const HLADataElementIndex& index)
+ { return getDataElement(index.begin(), index.end()); }
+ const HLADataElement* getDataElement(const HLADataElementIndex& index) const
+ { return getDataElement(index.begin(), index.end()); }
+
+ virtual bool setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement);
+ virtual HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end);
+ virtual const HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const;
+
/// Returns the time stamp if this data element.
/// Do not access this getter if the getTimeStampValid() method returns false.
const SGTimeStamp& getTimeStamp() const
{
}
+class HLADataType::_DataElementIndexVisitor : public HLADataTypeVisitor {
+public:
+ _DataElementIndexVisitor(HLADataElementIndex& index, const std::string& path, size_t offset) :
+ _index(index),
+ _path(path),
+ _offset(offset),
+ _success(false)
+ { }
+ virtual ~_DataElementIndexVisitor()
+ { }
+
+ virtual void apply(const HLADataType& dataType)
+ {
+ if (_path.size() == _offset)
+ _success = true;
+ }
+ virtual void apply(const HLAArrayDataType& dataType)
+ {
+ if (_path.size() <= _offset) {
+ SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+ << "Expected array subscript at the end of the path!");
+ return;
+ }
+ if (_path[_offset] != '[') {
+ SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+ << "Expected array subscript at the end of the path!");
+ return;
+ }
+ ++_offset;
+ if (_path.size() <= _offset) {
+ SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+ << "Expected closing array subscript at the end of the path!");
+ return;
+ }
+ unsigned index = 0;
+ bool closed = false;
+ while (_offset <= _path.size()) {
+ if (_path[_offset] == ']') {
+ ++_offset;
+ closed = true;
+ break;
+ }
+ unsigned v = _path[_offset] - '0';
+ // Error, no number
+ if (10 <= v) {
+ SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+ << "Array subscript is not a number!");
+ return;
+ }
+ index *= 10;
+ index += v;
+ ++_offset;
+ }
+ if (!closed) {
+ SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+ << "Expected closing array subscript at the end of the path!");
+ return;
+ }
+ if (!dataType.getElementDataType()) {
+ SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+ << "Undefined array element data type!");
+ return;
+ }
+ _index.push_back(index);
+ _success = dataType.getElementDataType()->getDataElementIndex(_index, _path, _offset);
+ }
+
+ virtual void apply(const HLAFixedRecordDataType& dataType)
+ {
+ if (_path.size() <= _offset) {
+ SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+ << "Expected field name at the end of the path!");
+ return;
+ }
+ if (_path[_offset] == '.')
+ ++_offset;
+ if (_path.size() <= _offset) {
+ SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+ << "Expected field name at the end of the path!");
+ return;
+ }
+ size_t len = _path.find_first_of("[.", _offset) - _offset;
+ unsigned index = 0;
+ while (index < dataType.getNumFields()) {
+ if (_path.compare(_offset, len, dataType.getFieldName(index)) == 0)
+ break;
+ ++index;
+ }
+ if (dataType.getNumFields() <= index) {
+ SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+ << "Field \"" << _path.substr(_offset, len) << "\" not found in fixed record data type \""
+ << dataType.getName() << "\"!");
+ return;
+ }
+ if (!dataType.getFieldDataType(index)) {
+ SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+ << "Undefined field data type in variant record data type \""
+ << dataType.getName() << "\" at field \"" << dataType.getFieldName(index) << "\"!");
+ return;
+ }
+ _index.push_back(index);
+ _success = dataType.getFieldDataType(index)->getDataElementIndex(_index, _path, _offset + len);
+ }
+
+ virtual void apply(const HLAVariantRecordDataType& dataType)
+ {
+ if (_path.size() <= _offset) {
+ SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+ << "Expected alternative name at the end of the path!");
+ return;
+ }
+ if (_path[_offset] == '.')
+ ++_offset;
+ if (_path.size() <= _offset) {
+ SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+ << "Expected alternative name at the end of the path!");
+ return;
+ }
+ size_t len = _path.find_first_of("[.", _offset) - _offset;
+ unsigned index = 0;
+ while (index < dataType.getNumAlternatives()) {
+ if (_path.compare(_offset, len, dataType.getAlternativeName(index)) == 0)
+ break;
+ ++index;
+ }
+ if (dataType.getNumAlternatives() <= index) {
+ SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+ << "Alternative \"" << _path.substr(_offset, len) << "\" not found in variant record data type \""
+ << dataType.getName() << "\"!");
+ return;
+ }
+ if (!dataType.getAlternativeDataType(index)) {
+ SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
+ << "Undefined alternative data type in variant record data type \""
+ << dataType.getName() << "\" at alternative \"" << dataType.getAlternativeName(index) << "\"!");
+ return;
+ }
+ _index.push_back(index);
+ _success = dataType.getAlternativeDataType(index)->getDataElementIndex(_index, _path, _offset + len);
+ }
+
+ HLADataElementIndex& _index;
+ const std::string& _path;
+ size_t _offset;
+ bool _success;
+};
+
+bool
+HLADataType::getDataElementIndex(HLADataElementIndex& index, const std::string& path, size_t offset) const
+{
+ _DataElementIndexVisitor visitor(index, path, offset);
+ accept(visitor);
+ return visitor._success;
+}
+
void
HLADataType::setAlignment(unsigned alignment)
{
#include <simgear/structure/SGWeakPtr.hxx>
#include <simgear/structure/SGWeakReferenced.hxx>
#include "RTIData.hxx"
+#include "HLATypes.hxx"
namespace simgear {
/// required for propper feeing of memory.
virtual void releaseDataTypeReferences();
+ bool getDataElementIndex(HLADataElementIndex& index, const std::string& path, size_t offset) const;
+
protected:
HLADataType(const std::string& name, unsigned alignment = 1);
void setAlignment(unsigned alignment);
virtual void _recomputeAlignmentImplementation();
private:
+ class _DataElementIndexVisitor;
+
std::string _name;
std::string _semantics;
unsigned _alignment;
return true;
}
+bool
+HLAFixedRecordDataElement::setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement)
+{
+ // Must have happened in the parent
+ if (begin == end)
+ return false;
+ unsigned index = *begin;
+ if (++begin != end) {
+ if (getNumFields() <= index)
+ return false;
+ if (!getField(index) && getFieldDataType(index)) {
+ HLADataElementFactoryVisitor visitor;
+ getFieldDataType(index)->accept(visitor);
+ setField(index, visitor.getDataElement());
+ }
+ if (!getField(index))
+ return false;
+ return getField(index)->setDataElement(begin, end, dataElement);
+ } else {
+ if (!dataElement->setDataType(getFieldDataType(index)))
+ return false;
+ setField(index, dataElement);
+ return true;
+ }
+}
+
+HLADataElement*
+HLAFixedRecordDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end)
+{
+ if (begin == end)
+ return this;
+ HLADataElement* dataElement = getField(*begin);
+ if (!dataElement)
+ return 0;
+ return dataElement->getDataElement(++begin, end);
+}
+
+const HLADataElement*
+HLAFixedRecordDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const
+{
+ if (begin == end)
+ return this;
+ const HLADataElement* dataElement = getField(*begin);
+ if (!dataElement)
+ return 0;
+ return dataElement->getDataElement(++begin, end);
+}
+
bool
HLAFixedRecordDataElement::decodeField(HLADecodeStream& stream, unsigned i)
{
virtual bool setDataType(const HLADataType* dataType);
+ virtual bool setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement);
+ virtual HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end);
+ virtual const HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const;
+
virtual bool decodeField(HLADecodeStream& stream, unsigned i);
virtual bool encodeField(HLAEncodeStream& stream, unsigned i) const;
return getIndexPathPair(HLADataElement::toStringPathPair(path));
}
+bool
+HLAObjectClass::getAttributeIndex(HLADataElementIndex& dataElementIndex, const std::string& path) const
+{
+ if (path.empty()) {
+ SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: failed to parse empty element path!");
+ return false;
+ }
+ size_t len = path.find_first_of("[.");
+ unsigned index = 0;
+ while (index < getNumAttributes()) {
+ if (path.compare(0, len, getAttributeName(index)) == 0)
+ break;
+ ++index;
+ }
+ if (getNumAttributes() <= index) {
+ SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: faild to parse data element index \"" << path << "\":\n"
+ << "Attribute \"" << path.substr(0, len) << "\" not found in object class \""
+ << getName() << "\"!");
+ return false;
+ }
+ if (!getAttributeDataType(index)) {
+ SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: faild to parse data element index \"" << path << "\":\n"
+ << "Undefined attribute data type in variant record data type \""
+ << getAttributeName(index) << "\"!");
+ return false;
+ }
+ dataElementIndex.push_back(index);
+ return getAttributeDataType(index)->getDataElementIndex(dataElementIndex, path, len);
+}
+
bool
HLAObjectClass::subscribe()
{
/// Return the index, path pair for the given string path
HLADataElement::IndexPathPair getIndexPathPair(const std::string& path) const;
+ /// Get the attribute data element index for the given path, return true if successful
+ bool getAttributeIndex(HLADataElementIndex& dataElementIndex, const std::string& path) const;
+
virtual bool subscribe();
virtual bool unsubscribe();
}
}
+bool
+HLAObjectInstance::getAttributeIndex(HLADataElementIndex& index, const std::string& path) const
+{
+ HLAObjectClass* objectClass = getObjectClass().get();
+ if (!objectClass) {
+ SG_LOG(SG_IO, SG_ALERT, "Could not get the data element index of an object instance with unknown class!");
+ return false;
+ }
+ return objectClass->getAttributeIndex(index, path);
+}
+
+HLADataElement*
+HLAObjectInstance::getAttributeDataElement(const HLADataElementIndex& index)
+{
+ if (index.empty())
+ return 0;
+ HLADataElement* dataElement = getAttributeDataElement(index[0]);
+ if (!dataElement)
+ return 0;
+ return dataElement->getDataElement(index.begin() + 1, index.end());
+}
+
+const HLADataElement*
+HLAObjectInstance::getAttributeDataElement(const HLADataElementIndex& index) const
+{
+ if (index.empty())
+ return 0;
+ const HLADataElement* dataElement = getAttributeDataElement(index[0]);
+ if (!dataElement)
+ return 0;
+ return dataElement->getDataElement(index.begin() + 1, index.end());
+}
+
+void
+HLAObjectInstance::setAttributeDataElement(const HLADataElementIndex& index, const SGSharedPtr<HLADataElement>& dataElement)
+{
+ if (index.empty())
+ return;
+ if (index.size() == 1) {
+ if (!getAttributeDataType(index[0]))
+ return;
+ if (dataElement.valid() && !dataElement->setDataType(getAttributeDataType(index[0])))
+ return;
+ setAttributeDataElement(index[0], dataElement);
+ } else {
+ SGSharedPtr<HLADataElement> attributeDataElement = getAttributeDataElement(index[0]);
+ if (!attributeDataElement.valid())
+ attributeDataElement = createAttributeDataElement(index[0]);
+ if (!attributeDataElement.valid())
+ return;
+ attributeDataElement->setDataElement(index.begin() + 1, index.end(), dataElement.get());
+ }
+}
+
+HLADataElement*
+HLAObjectInstance::getAttributeDataElement(const std::string& path)
+{
+ HLADataElementIndex index;
+ if (!getAttributeIndex(index, path))
+ return 0;
+ return getAttributeDataElement(index);
+}
+
+const HLADataElement*
+HLAObjectInstance::getAttributeDataElement(const std::string& path) const
+{
+ HLADataElementIndex index;
+ if (!getAttributeIndex(index, path))
+ return 0;
+ return getAttributeDataElement(index);
+}
+
+void
+HLAObjectInstance::setAttributeDataElement(const std::string& path, const SGSharedPtr<HLADataElement>& dataElement)
+{
+ HLADataElementIndex index;
+ if (!getAttributeIndex(index, path))
+ return;
+ setAttributeDataElement(index, dataElement);
+}
+
void
HLAObjectInstance::discoverInstance(const RTIData& tag)
{
void setAttribute(unsigned index, const HLAPathElementMap& pathElementMap);
void setAttributes(const HLAAttributePathElementMap& attributePathElementMap);
+ /// Retrieve the data element index for the given path.
+ bool getAttributeIndex(HLADataElementIndex& index, const std::string& path) const;
+
+ /// Return the data element of the attribute with the given index
+ HLADataElement* getAttributeDataElement(const HLADataElementIndex& index);
+ const HLADataElement* getAttributeDataElement(const HLADataElementIndex& index) const;
+ /// Set the data element of the attribute with the given index
+ void setAttributeDataElement(const HLADataElementIndex& index, const SGSharedPtr<HLADataElement>& dataElement);
+
+ /// Return the data element of the attribute with the given path.
+ /// The method is only for convenience as parsing the path is expensive.
+ /// Precompute the index and use the index instead if you use this method more often.
+ HLADataElement* getAttributeDataElement(const std::string& path);
+ const HLADataElement* getAttributeDataElement(const std::string& path) const;
+ /// Set the data element of the attribute with the given path
+ /// The method is only for convenience as parsing the path is expensive.
+ /// Precompute the index and use the index instead if you use this method more often.
+ void setAttributeDataElement(const std::string& path, const SGSharedPtr<HLADataElement>& dataElement);
+
/// Gets called on discovering this object instance.
virtual void discoverInstance(const RTIData& tag);
/// Gets called on remove this object instance.
#define HLATypes_hxx
#include <list>
+#include <vector>
namespace simgear {
typedef std::list<unsigned> HLAIndexList;
+typedef std::vector<unsigned> HLADataElementIndex;
+
} // namespace simgear
#endif
#include <simgear/debug/logstream.hxx>
#include "HLADataElementVisitor.hxx"
+#include "HLADataTypeVisitor.hxx"
namespace simgear {
clearStamp();
}
+bool
+HLAVariantRecordDataElement::setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement)
+{
+ // Must have happened in the parent
+ if (begin == end)
+ return false;
+ unsigned index = *begin;
+ if (++begin != end) {
+ if (!setAlternativeIndex(index))
+ return false;
+ if (!_dataElement.valid() && getAlternativeDataType()) {
+ HLADataElementFactoryVisitor visitor;
+ getAlternativeDataType()->accept(visitor);
+ _dataElement = visitor.getDataElement();
+ }
+ if (!_dataElement.valid())
+ return false;
+ return _dataElement->setDataElement(begin, end, dataElement);
+ } else {
+ if (!setAlternativeIndex(index))
+ return false;
+ if (!dataElement->setDataType(getAlternativeDataType()))
+ return false;
+ _dataElement = dataElement;
+ return true;
+ }
+}
+
+HLADataElement*
+HLAVariantRecordDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end)
+{
+ if (begin == end)
+ return this;
+ if (getAlternativeIndex() != *begin)
+ return 0;
+ if (!_dataElement.valid())
+ return 0;
+ return _dataElement->getDataElement(++begin, end);
+}
+
+const HLADataElement*
+HLAVariantRecordDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const
+{
+ if (begin == end)
+ return this;
+ if (getAlternativeIndex() != *begin)
+ return 0;
+ if (!_dataElement.valid())
+ return 0;
+ return _dataElement->getDataElement(++begin, end);
+}
+
bool
HLAVariantRecordDataElement::setAlternativeIndex(unsigned index)
{
HLAVariantRecordDataElement(const HLAVariantRecordDataType* dataType);
virtual ~HLAVariantRecordDataElement();
+ virtual bool setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement);
+ virtual HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end);
+ virtual const HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const;
+
virtual bool setAlternativeIndex(unsigned index);
virtual bool decodeAlternative(HLADecodeStream& stream);
virtual unsigned getAlternativeIndex() const;