hla: Introduce HLADataElementIndex.

This commit is contained in:
Mathias Froehlich 2012-11-08 21:31:16 +01:00
parent 8c57a77d7e
commit 6d045a9403
15 changed files with 491 additions and 0 deletions

View File

@ -108,6 +108,54 @@ HLAArrayDataElement::~HLAArrayDataElement()
clearStamp();
}
bool
HLAArrayDataElement::setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement)
{
// Must have happened in the parent
if (begin == end)
return false;
unsigned index = *begin;
if (++begin != end) {
if (getNumElements() <= index && !setNumElements(index + 1))
return false;
if (!getElement(index) && getElementDataType()) {
HLADataElementFactoryVisitor visitor;
getElementDataType()->accept(visitor);
setElement(index, visitor.getDataElement());
}
if (!getElement(index))
return false;
return getElement(index)->setDataElement(begin, end, dataElement);
} else {
if (!dataElement->setDataType(getElementDataType()))
return false;
setElement(index, dataElement);
return true;
}
}
HLADataElement*
HLAArrayDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end)
{
if (begin == end)
return this;
HLADataElement* dataElement = getElement(*begin);
if (!dataElement)
return 0;
return dataElement->getDataElement(++begin, end);
}
const HLADataElement*
HLAArrayDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const
{
if (begin == end)
return this;
const HLADataElement* dataElement = getElement(*begin);
if (!dataElement)
return 0;
return dataElement->getDataElement(++begin, end);
}
bool
HLAArrayDataElement::setNumElements(unsigned size)
{

View File

@ -59,6 +59,10 @@ public:
HLAArrayDataElement(const HLAArrayDataType* dataType = 0);
virtual ~HLAArrayDataElement();
virtual bool setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement);
virtual HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end);
virtual const HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const;
virtual bool setNumElements(unsigned size);
virtual bool decodeElement(HLADecodeStream& stream, unsigned i);
virtual unsigned getNumElements() const;

View File

@ -137,6 +137,28 @@ HLADataElement::~HLADataElement()
{
}
bool
HLADataElement::setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement)
{
return false;
}
HLADataElement*
HLADataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end)
{
if (begin != end)
return 0;
return this;
}
const HLADataElement*
HLADataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const
{
if (begin != end)
return 0;
return this;
}
void
HLADataElement::setTimeStamp(const SGTimeStamp& timeStamp)
{

View File

@ -25,6 +25,7 @@
#include <simgear/timing/timestamp.hxx>
#include "RTIData.hxx"
#include "HLADataType.hxx"
#include "HLATypes.hxx"
class SGTimeStamp;
@ -46,6 +47,17 @@ public:
virtual const HLADataType* getDataType() const = 0;
virtual bool setDataType(const HLADataType* dataType) = 0;
bool setDataElement(const HLADataElementIndex& index, HLADataElement* dataElement)
{ return setDataElement(index.begin(), index.end(), dataElement); }
HLADataElement* getDataElement(const HLADataElementIndex& index)
{ return getDataElement(index.begin(), index.end()); }
const HLADataElement* getDataElement(const HLADataElementIndex& index) const
{ return getDataElement(index.begin(), index.end()); }
virtual bool setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement);
virtual HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end);
virtual const HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const;
/// Returns the time stamp if this data element.
/// Do not access this getter if the getTimeStampValid() method returns false.
const SGTimeStamp& getTimeStamp() const

View File

@ -88,6 +88,161 @@ HLADataType::releaseDataTypeReferences()
{
}
class HLADataType::_DataElementIndexVisitor : public HLADataTypeVisitor {
public:
_DataElementIndexVisitor(HLADataElementIndex& index, const std::string& path, size_t offset) :
_index(index),
_path(path),
_offset(offset),
_success(false)
{ }
virtual ~_DataElementIndexVisitor()
{ }
virtual void apply(const HLADataType& dataType)
{
if (_path.size() == _offset)
_success = true;
}
virtual void apply(const HLAArrayDataType& dataType)
{
if (_path.size() <= _offset) {
SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
<< "Expected array subscript at the end of the path!");
return;
}
if (_path[_offset] != '[') {
SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
<< "Expected array subscript at the end of the path!");
return;
}
++_offset;
if (_path.size() <= _offset) {
SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
<< "Expected closing array subscript at the end of the path!");
return;
}
unsigned index = 0;
bool closed = false;
while (_offset <= _path.size()) {
if (_path[_offset] == ']') {
++_offset;
closed = true;
break;
}
unsigned v = _path[_offset] - '0';
// Error, no number
if (10 <= v) {
SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
<< "Array subscript is not a number!");
return;
}
index *= 10;
index += v;
++_offset;
}
if (!closed) {
SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
<< "Expected closing array subscript at the end of the path!");
return;
}
if (!dataType.getElementDataType()) {
SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
<< "Undefined array element data type!");
return;
}
_index.push_back(index);
_success = dataType.getElementDataType()->getDataElementIndex(_index, _path, _offset);
}
virtual void apply(const HLAFixedRecordDataType& dataType)
{
if (_path.size() <= _offset) {
SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
<< "Expected field name at the end of the path!");
return;
}
if (_path[_offset] == '.')
++_offset;
if (_path.size() <= _offset) {
SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
<< "Expected field name at the end of the path!");
return;
}
size_t len = _path.find_first_of("[.", _offset) - _offset;
unsigned index = 0;
while (index < dataType.getNumFields()) {
if (_path.compare(_offset, len, dataType.getFieldName(index)) == 0)
break;
++index;
}
if (dataType.getNumFields() <= index) {
SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
<< "Field \"" << _path.substr(_offset, len) << "\" not found in fixed record data type \""
<< dataType.getName() << "\"!");
return;
}
if (!dataType.getFieldDataType(index)) {
SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
<< "Undefined field data type in variant record data type \""
<< dataType.getName() << "\" at field \"" << dataType.getFieldName(index) << "\"!");
return;
}
_index.push_back(index);
_success = dataType.getFieldDataType(index)->getDataElementIndex(_index, _path, _offset + len);
}
virtual void apply(const HLAVariantRecordDataType& dataType)
{
if (_path.size() <= _offset) {
SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
<< "Expected alternative name at the end of the path!");
return;
}
if (_path[_offset] == '.')
++_offset;
if (_path.size() <= _offset) {
SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
<< "Expected alternative name at the end of the path!");
return;
}
size_t len = _path.find_first_of("[.", _offset) - _offset;
unsigned index = 0;
while (index < dataType.getNumAlternatives()) {
if (_path.compare(_offset, len, dataType.getAlternativeName(index)) == 0)
break;
++index;
}
if (dataType.getNumAlternatives() <= index) {
SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
<< "Alternative \"" << _path.substr(_offset, len) << "\" not found in variant record data type \""
<< dataType.getName() << "\"!");
return;
}
if (!dataType.getAlternativeDataType(index)) {
SG_LOG(SG_NETWORK, SG_ALERT, "HLADataType: faild to parse data element index \"" << _path << "\":\n"
<< "Undefined alternative data type in variant record data type \""
<< dataType.getName() << "\" at alternative \"" << dataType.getAlternativeName(index) << "\"!");
return;
}
_index.push_back(index);
_success = dataType.getAlternativeDataType(index)->getDataElementIndex(_index, _path, _offset + len);
}
HLADataElementIndex& _index;
const std::string& _path;
size_t _offset;
bool _success;
};
bool
HLADataType::getDataElementIndex(HLADataElementIndex& index, const std::string& path, size_t offset) const
{
_DataElementIndexVisitor visitor(index, path, offset);
accept(visitor);
return visitor._success;
}
void
HLADataType::setAlignment(unsigned alignment)
{

View File

@ -22,6 +22,7 @@
#include <simgear/structure/SGWeakPtr.hxx>
#include <simgear/structure/SGWeakReferenced.hxx>
#include "RTIData.hxx"
#include "HLATypes.hxx"
namespace simgear {
@ -63,6 +64,8 @@ public:
/// required for propper feeing of memory.
virtual void releaseDataTypeReferences();
bool getDataElementIndex(HLADataElementIndex& index, const std::string& path, size_t offset) const;
protected:
HLADataType(const std::string& name, unsigned alignment = 1);
void setAlignment(unsigned alignment);
@ -70,6 +73,8 @@ protected:
virtual void _recomputeAlignmentImplementation();
private:
class _DataElementIndexVisitor;
std::string _name;
std::string _semantics;
unsigned _alignment;

View File

@ -146,6 +146,54 @@ HLAFixedRecordDataElement::setDataType(const HLADataType* dataType)
return true;
}
bool
HLAFixedRecordDataElement::setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement)
{
// Must have happened in the parent
if (begin == end)
return false;
unsigned index = *begin;
if (++begin != end) {
if (getNumFields() <= index)
return false;
if (!getField(index) && getFieldDataType(index)) {
HLADataElementFactoryVisitor visitor;
getFieldDataType(index)->accept(visitor);
setField(index, visitor.getDataElement());
}
if (!getField(index))
return false;
return getField(index)->setDataElement(begin, end, dataElement);
} else {
if (!dataElement->setDataType(getFieldDataType(index)))
return false;
setField(index, dataElement);
return true;
}
}
HLADataElement*
HLAFixedRecordDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end)
{
if (begin == end)
return this;
HLADataElement* dataElement = getField(*begin);
if (!dataElement)
return 0;
return dataElement->getDataElement(++begin, end);
}
const HLADataElement*
HLAFixedRecordDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const
{
if (begin == end)
return this;
const HLADataElement* dataElement = getField(*begin);
if (!dataElement)
return 0;
return dataElement->getDataElement(++begin, end);
}
bool
HLAFixedRecordDataElement::decodeField(HLADecodeStream& stream, unsigned i)
{

View File

@ -60,6 +60,10 @@ public:
virtual bool setDataType(const HLADataType* dataType);
virtual bool setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement);
virtual HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end);
virtual const HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const;
virtual bool decodeField(HLADecodeStream& stream, unsigned i);
virtual bool encodeField(HLAEncodeStream& stream, unsigned i) const;

View File

@ -210,6 +210,36 @@ HLAObjectClass::getIndexPathPair(const std::string& path) const
return getIndexPathPair(HLADataElement::toStringPathPair(path));
}
bool
HLAObjectClass::getAttributeIndex(HLADataElementIndex& dataElementIndex, const std::string& path) const
{
if (path.empty()) {
SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: failed to parse empty element path!");
return false;
}
size_t len = path.find_first_of("[.");
unsigned index = 0;
while (index < getNumAttributes()) {
if (path.compare(0, len, getAttributeName(index)) == 0)
break;
++index;
}
if (getNumAttributes() <= index) {
SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: faild to parse data element index \"" << path << "\":\n"
<< "Attribute \"" << path.substr(0, len) << "\" not found in object class \""
<< getName() << "\"!");
return false;
}
if (!getAttributeDataType(index)) {
SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: faild to parse data element index \"" << path << "\":\n"
<< "Undefined attribute data type in variant record data type \""
<< getAttributeName(index) << "\"!");
return false;
}
dataElementIndex.push_back(index);
return getAttributeDataType(index)->getDataElementIndex(dataElementIndex, path, len);
}
bool
HLAObjectClass::subscribe()
{

View File

@ -77,6 +77,9 @@ public:
/// Return the index, path pair for the given string path
HLADataElement::IndexPathPair getIndexPathPair(const std::string& path) const;
/// Get the attribute data element index for the given path, return true if successful
bool getAttributeIndex(HLADataElementIndex& dataElementIndex, const std::string& path) const;
virtual bool subscribe();
virtual bool unsubscribe();

View File

@ -442,6 +442,87 @@ HLAObjectInstance::setAttributes(const HLAAttributePathElementMap& attributePath
}
}
bool
HLAObjectInstance::getAttributeIndex(HLADataElementIndex& index, const std::string& path) const
{
HLAObjectClass* objectClass = getObjectClass().get();
if (!objectClass) {
SG_LOG(SG_IO, SG_ALERT, "Could not get the data element index of an object instance with unknown class!");
return false;
}
return objectClass->getAttributeIndex(index, path);
}
HLADataElement*
HLAObjectInstance::getAttributeDataElement(const HLADataElementIndex& index)
{
if (index.empty())
return 0;
HLADataElement* dataElement = getAttributeDataElement(index[0]);
if (!dataElement)
return 0;
return dataElement->getDataElement(index.begin() + 1, index.end());
}
const HLADataElement*
HLAObjectInstance::getAttributeDataElement(const HLADataElementIndex& index) const
{
if (index.empty())
return 0;
const HLADataElement* dataElement = getAttributeDataElement(index[0]);
if (!dataElement)
return 0;
return dataElement->getDataElement(index.begin() + 1, index.end());
}
void
HLAObjectInstance::setAttributeDataElement(const HLADataElementIndex& index, const SGSharedPtr<HLADataElement>& dataElement)
{
if (index.empty())
return;
if (index.size() == 1) {
if (!getAttributeDataType(index[0]))
return;
if (dataElement.valid() && !dataElement->setDataType(getAttributeDataType(index[0])))
return;
setAttributeDataElement(index[0], dataElement);
} else {
SGSharedPtr<HLADataElement> attributeDataElement = getAttributeDataElement(index[0]);
if (!attributeDataElement.valid())
attributeDataElement = createAttributeDataElement(index[0]);
if (!attributeDataElement.valid())
return;
attributeDataElement->setDataElement(index.begin() + 1, index.end(), dataElement.get());
}
}
HLADataElement*
HLAObjectInstance::getAttributeDataElement(const std::string& path)
{
HLADataElementIndex index;
if (!getAttributeIndex(index, path))
return 0;
return getAttributeDataElement(index);
}
const HLADataElement*
HLAObjectInstance::getAttributeDataElement(const std::string& path) const
{
HLADataElementIndex index;
if (!getAttributeIndex(index, path))
return 0;
return getAttributeDataElement(index);
}
void
HLAObjectInstance::setAttributeDataElement(const std::string& path, const SGSharedPtr<HLADataElement>& dataElement)
{
HLADataElementIndex index;
if (!getAttributeIndex(index, path))
return;
setAttributeDataElement(index, dataElement);
}
void
HLAObjectInstance::discoverInstance(const RTIData& tag)
{

View File

@ -77,6 +77,25 @@ public:
void setAttribute(unsigned index, const HLAPathElementMap& pathElementMap);
void setAttributes(const HLAAttributePathElementMap& attributePathElementMap);
/// Retrieve the data element index for the given path.
bool getAttributeIndex(HLADataElementIndex& index, const std::string& path) const;
/// Return the data element of the attribute with the given index
HLADataElement* getAttributeDataElement(const HLADataElementIndex& index);
const HLADataElement* getAttributeDataElement(const HLADataElementIndex& index) const;
/// Set the data element of the attribute with the given index
void setAttributeDataElement(const HLADataElementIndex& index, const SGSharedPtr<HLADataElement>& dataElement);
/// Return the data element of the attribute with the given path.
/// The method is only for convenience as parsing the path is expensive.
/// Precompute the index and use the index instead if you use this method more often.
HLADataElement* getAttributeDataElement(const std::string& path);
const HLADataElement* getAttributeDataElement(const std::string& path) const;
/// Set the data element of the attribute with the given path
/// The method is only for convenience as parsing the path is expensive.
/// Precompute the index and use the index instead if you use this method more often.
void setAttributeDataElement(const std::string& path, const SGSharedPtr<HLADataElement>& dataElement);
/// Gets called on discovering this object instance.
virtual void discoverInstance(const RTIData& tag);
/// Gets called on remove this object instance.

View File

@ -19,6 +19,7 @@
#define HLATypes_hxx
#include <list>
#include <vector>
namespace simgear {
@ -42,6 +43,8 @@ enum HLAUpdateType {
typedef std::list<unsigned> HLAIndexList;
typedef std::vector<unsigned> HLADataElementIndex;
} // namespace simgear
#endif

View File

@ -26,6 +26,7 @@
#include <simgear/debug/logstream.hxx>
#include "HLADataElementVisitor.hxx"
#include "HLADataTypeVisitor.hxx"
namespace simgear {
@ -122,6 +123,58 @@ HLAVariantRecordDataElement::~HLAVariantRecordDataElement()
clearStamp();
}
bool
HLAVariantRecordDataElement::setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement)
{
// Must have happened in the parent
if (begin == end)
return false;
unsigned index = *begin;
if (++begin != end) {
if (!setAlternativeIndex(index))
return false;
if (!_dataElement.valid() && getAlternativeDataType()) {
HLADataElementFactoryVisitor visitor;
getAlternativeDataType()->accept(visitor);
_dataElement = visitor.getDataElement();
}
if (!_dataElement.valid())
return false;
return _dataElement->setDataElement(begin, end, dataElement);
} else {
if (!setAlternativeIndex(index))
return false;
if (!dataElement->setDataType(getAlternativeDataType()))
return false;
_dataElement = dataElement;
return true;
}
}
HLADataElement*
HLAVariantRecordDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end)
{
if (begin == end)
return this;
if (getAlternativeIndex() != *begin)
return 0;
if (!_dataElement.valid())
return 0;
return _dataElement->getDataElement(++begin, end);
}
const HLADataElement*
HLAVariantRecordDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const
{
if (begin == end)
return this;
if (getAlternativeIndex() != *begin)
return 0;
if (!_dataElement.valid())
return 0;
return _dataElement->getDataElement(++begin, end);
}
bool
HLAVariantRecordDataElement::setAlternativeIndex(unsigned index)
{

View File

@ -57,6 +57,10 @@ public:
HLAVariantRecordDataElement(const HLAVariantRecordDataType* dataType);
virtual ~HLAVariantRecordDataElement();
virtual bool setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement);
virtual HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end);
virtual const HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const;
virtual bool setAlternativeIndex(unsigned index);
virtual bool decodeAlternative(HLADecodeStream& stream);
virtual unsigned getAlternativeIndex() const;