1 // Copyright (C) 2009 - 2011 Mathias Froehlich - Mathias.Froehlich@web.de
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Library General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 #include "HLAPropertyDataElement.hxx"
20 #include "HLAArrayDataElement.hxx"
21 #include "HLADataTypeVisitor.hxx"
22 #include "HLAFixedRecordDataElement.hxx"
23 #include "HLAVariantDataElement.hxx"
27 class HLAPropertyDataElement::ScalarDecodeVisitor : public HLADataTypeDecodeVisitor {
29 ScalarDecodeVisitor(HLADecodeStream& stream, SGPropertyNode& propertyNode) :
30 HLADataTypeDecodeVisitor(stream),
31 _propertyNode(propertyNode)
33 virtual ~ScalarDecodeVisitor()
36 virtual void apply(const HLAInt8DataType& dataType)
39 dataType.decode(_stream, value);
40 _propertyNode.setIntValue(value);
42 virtual void apply(const HLAUInt8DataType& dataType)
45 dataType.decode(_stream, value);
46 _propertyNode.setIntValue(value);
48 virtual void apply(const HLAInt16DataType& dataType)
51 dataType.decode(_stream, value);
52 _propertyNode.setIntValue(value);
54 virtual void apply(const HLAUInt16DataType& dataType)
57 dataType.decode(_stream, value);
58 _propertyNode.setIntValue(value);
60 virtual void apply(const HLAInt32DataType& dataType)
63 dataType.decode(_stream, value);
64 _propertyNode.setIntValue(value);
66 virtual void apply(const HLAUInt32DataType& dataType)
69 dataType.decode(_stream, value);
70 _propertyNode.setIntValue(value);
72 virtual void apply(const HLAInt64DataType& dataType)
75 dataType.decode(_stream, value);
76 _propertyNode.setLongValue(value);
78 virtual void apply(const HLAUInt64DataType& dataType)
81 dataType.decode(_stream, value);
82 _propertyNode.setLongValue(value);
84 virtual void apply(const HLAFloat32DataType& dataType)
87 dataType.decode(_stream, value);
88 _propertyNode.setFloatValue(value);
90 virtual void apply(const HLAFloat64DataType& dataType)
93 dataType.decode(_stream, value);
94 _propertyNode.setDoubleValue(value);
98 SGPropertyNode& _propertyNode;
101 class HLAPropertyDataElement::ScalarEncodeVisitor : public HLADataTypeEncodeVisitor {
103 ScalarEncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) :
104 HLADataTypeEncodeVisitor(stream),
105 _propertyNode(propertyNode)
107 virtual ~ScalarEncodeVisitor()
110 virtual void apply(const HLAInt8DataType& dataType)
112 dataType.encode(_stream, _propertyNode.getIntValue());
114 virtual void apply(const HLAUInt8DataType& dataType)
116 dataType.encode(_stream, _propertyNode.getIntValue());
118 virtual void apply(const HLAInt16DataType& dataType)
120 dataType.encode(_stream, _propertyNode.getIntValue());
122 virtual void apply(const HLAUInt16DataType& dataType)
124 dataType.encode(_stream, _propertyNode.getIntValue());
126 virtual void apply(const HLAInt32DataType& dataType)
128 dataType.encode(_stream, _propertyNode.getIntValue());
130 virtual void apply(const HLAUInt32DataType& dataType)
132 dataType.encode(_stream, _propertyNode.getIntValue());
134 virtual void apply(const HLAInt64DataType& dataType)
136 dataType.encode(_stream, _propertyNode.getLongValue());
138 virtual void apply(const HLAUInt64DataType& dataType)
140 dataType.encode(_stream, _propertyNode.getLongValue());
142 virtual void apply(const HLAFloat32DataType& dataType)
144 dataType.encode(_stream, _propertyNode.getFloatValue());
146 virtual void apply(const HLAFloat64DataType& dataType)
148 dataType.encode(_stream, _propertyNode.getDoubleValue());
152 const SGPropertyNode& _propertyNode;
155 class HLAPropertyDataElement::ScalarDataElement : public HLADataElement {
157 ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode);
158 virtual ~ScalarDataElement();
160 virtual bool encode(HLAEncodeStream& stream) const;
161 virtual bool decode(HLADecodeStream& stream);
163 virtual const HLADataType* getDataType() const;
164 virtual bool setDataType(const HLADataType* dataType);
167 SGSharedPtr<const HLABasicDataType> _dataType;
168 SGSharedPtr<SGPropertyNode> _propertyNode;
171 HLAPropertyDataElement::ScalarDataElement::ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode) :
173 _propertyNode(propertyNode)
177 HLAPropertyDataElement::ScalarDataElement::~ScalarDataElement()
182 HLAPropertyDataElement::ScalarDataElement::encode(HLAEncodeStream& stream) const
184 ScalarEncodeVisitor visitor(stream, *_propertyNode);
185 _dataType->accept(visitor);
190 HLAPropertyDataElement::ScalarDataElement::decode(HLADecodeStream& stream)
192 ScalarDecodeVisitor visitor(stream, *_propertyNode);
193 _dataType->accept(visitor);
198 HLAPropertyDataElement::ScalarDataElement::getDataType() const
200 return _dataType.get();
204 HLAPropertyDataElement::ScalarDataElement::setDataType(const HLADataType* dataType)
208 const HLABasicDataType* basicDataType = dataType->toBasicDataType();
211 _dataType = basicDataType;
216 class HLAPropertyDataElement::StringDecodeVisitor : public HLADataTypeDecodeVisitor {
218 StringDecodeVisitor(HLADecodeStream& stream, SGPropertyNode& propertyNode) :
219 HLADataTypeDecodeVisitor(stream),
220 _propertyNode(propertyNode)
223 virtual void apply(const HLAFixedArrayDataType& dataType)
225 unsigned numElements = dataType.getNumElements();
227 value.reserve(numElements);
228 for (unsigned i = 0; i < numElements; ++i) {
229 HLATemplateDecodeVisitor<char> visitor(_stream);
230 dataType.getElementDataType()->accept(visitor);
231 value.push_back(visitor.getValue());
233 _propertyNode.setStringValue(value);
235 virtual void apply(const HLAVariableArrayDataType& dataType)
237 HLATemplateDecodeVisitor<std::string::size_type> numElementsVisitor(_stream);
238 dataType.getSizeDataType()->accept(numElementsVisitor);
239 std::string::size_type numElements = numElementsVisitor.getValue();
241 value.reserve(numElements);
242 for (std::string::size_type i = 0; i < numElements; ++i) {
243 HLATemplateDecodeVisitor<char> visitor(_stream);
244 dataType.getElementDataType()->accept(visitor);
245 value.push_back(visitor.getValue());
247 _propertyNode.setStringValue(value);
251 SGPropertyNode& _propertyNode;
254 class HLAPropertyDataElement::StringEncodeVisitor : public HLADataTypeEncodeVisitor {
256 StringEncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) :
257 HLADataTypeEncodeVisitor(stream),
258 _propertyNode(propertyNode)
261 virtual void apply(const HLAFixedArrayDataType& dataType)
263 unsigned numElements = dataType.getNumElements();
264 std::string value = _propertyNode.getStringValue();
265 for (unsigned i = 0; i < numElements; ++i) {
266 if (i < value.size()) {
267 HLATemplateEncodeVisitor<char> visitor(_stream, value[i]);
268 dataType.getElementDataType()->accept(visitor);
270 HLADataTypeEncodeVisitor visitor(_stream);
271 dataType.getElementDataType()->accept(visitor);
276 virtual void apply(const HLAVariableArrayDataType& dataType)
278 std::string value = _propertyNode.getStringValue();
279 HLATemplateEncodeVisitor<std::string::size_type> numElementsVisitor(_stream, value.size());
280 dataType.getSizeDataType()->accept(numElementsVisitor);
281 for (unsigned i = 0; i < value.size(); ++i) {
282 HLATemplateEncodeVisitor<char> visitor(_stream, value[i]);
283 dataType.getElementDataType()->accept(visitor);
288 const SGPropertyNode& _propertyNode;
291 class HLAPropertyDataElement::StringDataElement : public HLADataElement {
293 StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode);
294 virtual ~StringDataElement();
296 virtual bool encode(HLAEncodeStream& stream) const;
297 virtual bool decode(HLADecodeStream& stream);
299 virtual const HLADataType* getDataType() const;
300 virtual bool setDataType(const HLADataType* dataType);
303 SGSharedPtr<const HLAArrayDataType> _dataType;
304 SGSharedPtr<SGPropertyNode> _propertyNode;
307 HLAPropertyDataElement::StringDataElement::StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode) :
309 _propertyNode(propertyNode)
313 HLAPropertyDataElement::StringDataElement::~StringDataElement()
318 HLAPropertyDataElement::StringDataElement::encode(HLAEncodeStream& stream) const
320 StringEncodeVisitor visitor(stream, *_propertyNode);
321 _dataType->accept(visitor);
326 HLAPropertyDataElement::StringDataElement::decode(HLADecodeStream& stream)
328 StringDecodeVisitor visitor(stream, *_propertyNode);
329 _dataType->accept(visitor);
334 HLAPropertyDataElement::StringDataElement::getDataType() const
336 return _dataType.get();
340 HLAPropertyDataElement::StringDataElement::setDataType(const HLADataType* dataType)
344 const HLAArrayDataType* arrayDataType = dataType->toArrayDataType();
347 const HLADataType* elementDataType = arrayDataType->getElementDataType();
348 if (!elementDataType)
350 if (!elementDataType->toBasicDataType())
352 _dataType = arrayDataType;
356 class HLAPropertyDataElement::DataElementFactoryVisitor : public HLADataTypeVisitor {
358 DataElementFactoryVisitor(SGPropertyNode* propertyNode) :
359 _propertyNode(propertyNode)
361 virtual ~DataElementFactoryVisitor()
364 virtual void apply(const HLADataType& dataType)
366 SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \""
367 << dataType.getName() << "\"");
370 virtual void apply(const HLAInt8DataType& dataType)
372 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
374 virtual void apply(const HLAUInt8DataType& dataType)
376 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
378 virtual void apply(const HLAInt16DataType& dataType)
380 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
382 virtual void apply(const HLAUInt16DataType& dataType)
384 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
386 virtual void apply(const HLAInt32DataType& dataType)
388 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
390 virtual void apply(const HLAUInt32DataType& dataType)
392 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
394 virtual void apply(const HLAInt64DataType& dataType)
396 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
398 virtual void apply(const HLAUInt64DataType& dataType)
400 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
402 virtual void apply(const HLAFloat32DataType& dataType)
404 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
406 virtual void apply(const HLAFloat64DataType& dataType)
408 _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
411 class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
413 ArrayDataElementFactory(SGPropertyNode* propertyNode) :
414 _propertyNode(propertyNode)
416 virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index)
418 const HLADataType* dataType = element.getElementDataType();
422 SGPropertyNode* parent = _propertyNode->getParent();
423 DataElementFactoryVisitor visitor(parent->getChild(_propertyNode->getNameString(), index, true));
424 dataType->accept(visitor);
425 return visitor.getDataElement();
428 SGSharedPtr<SGPropertyNode> _propertyNode;
431 virtual void apply(const HLAFixedArrayDataType& dataType)
433 if (dataType.getIsString()) {
434 _dataElement = new StringDataElement(&dataType, _propertyNode.get());
436 SGSharedPtr<HLAArrayDataElement> arrayDataElement;
437 arrayDataElement = new HLAArrayDataElement(&dataType);
438 arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get()));
439 arrayDataElement->setNumElements(dataType.getNumElements());
440 _dataElement = arrayDataElement;
444 virtual void apply(const HLAVariableArrayDataType& dataType)
446 if (dataType.getIsString()) {
447 _dataElement = new StringDataElement(&dataType, _propertyNode.get());
449 SGSharedPtr<HLAArrayDataElement> arrayDataElement;
450 arrayDataElement = new HLAArrayDataElement(&dataType);
451 arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get()));
452 _dataElement = arrayDataElement;
456 virtual void apply(const HLAEnumeratedDataType& dataType)
458 _dataElement = new ScalarDataElement(dataType.getRepresentation(), _propertyNode.get());
461 virtual void apply(const HLAFixedRecordDataType& dataType)
463 SGSharedPtr<HLAFixedRecordDataElement> recordDataElement;
464 recordDataElement = new HLAFixedRecordDataElement(&dataType);
466 unsigned numFields = dataType.getNumFields();
467 for (unsigned i = 0; i < numFields; ++i) {
468 DataElementFactoryVisitor visitor(_propertyNode->getChild(dataType.getFieldName(i), 0, true));
469 dataType.getFieldDataType(i)->accept(visitor);
470 recordDataElement->setField(i, visitor._dataElement.get());
473 _dataElement = recordDataElement;
476 class VariantDataElementFactory : public HLAVariantDataElement::DataElementFactory {
478 VariantDataElementFactory(SGPropertyNode* propertyNode) :
479 _propertyNode(propertyNode)
481 virtual HLADataElement* createElement(const HLAVariantDataElement& element, unsigned index)
483 const HLAVariantDataType* dataType = element.getDataType();
486 const HLADataType* alternativeDataType = element.getAlternativeDataType();
487 if (!alternativeDataType)
489 DataElementFactoryVisitor visitor(_propertyNode->getChild(dataType->getAlternativeName(index), 0, true));
490 alternativeDataType->accept(visitor);
491 return visitor.getDataElement();
494 SGSharedPtr<SGPropertyNode> _propertyNode;
497 virtual void apply(const HLAVariantDataType& dataType)
499 SGSharedPtr<HLAVariantDataElement> variantDataElement;
500 variantDataElement = new HLAVariantDataElement(&dataType);
501 variantDataElement->setDataElementFactory(new VariantDataElementFactory(_propertyNode.get()));
502 _dataElement = variantDataElement;
505 HLADataElement* getDataElement()
506 { return _dataElement.release(); }
509 SGSharedPtr<SGPropertyNode> _propertyNode;
510 SGSharedPtr<HLADataElement> _dataElement;
513 HLAPropertyDataElement::HLAPropertyDataElement()
517 HLAPropertyDataElement::HLAPropertyDataElement(SGPropertyNode* propertyNode)
519 setPropertyNode(propertyNode);
522 HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType, SGPropertyNode* propertyNode) :
525 setPropertyNode(propertyNode);
528 HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType) :
533 HLAPropertyDataElement::~HLAPropertyDataElement()
538 HLAPropertyDataElement::encode(HLAEncodeStream& stream) const
540 if (_dataElement.valid()) {
541 return _dataElement->encode(stream);
543 if (!_dataType.valid())
545 HLADataTypeEncodeVisitor visitor(stream);
546 _dataType->accept(visitor);
552 HLAPropertyDataElement::decode(HLADecodeStream& stream)
554 if (_dataElement.valid()) {
555 return _dataElement->decode(stream);
556 } else if (!_dataType.valid()) {
557 // We cant do anything if the data type is not valid
560 HLADataElementFactoryVisitor visitor;
561 _dataType->accept(visitor);
562 _dataElement = visitor.getDataElement();
563 if (_dataElement.valid()) {
564 return _dataElement->decode(stream);
566 HLADataTypeDecodeVisitor visitor(stream);
567 _dataType->accept(visitor);
574 HLAPropertyDataElement::getDataType() const
576 return _dataType.get();
580 HLAPropertyDataElement::setDataType(const HLADataType* dataType)
582 _dataType = dataType;
583 if (_dataType.valid() && _propertyNode.valid())
584 _dataElement = createDataElement(_dataType, _propertyNode);
589 HLAPropertyDataElement::setPropertyNode(SGPropertyNode* propertyNode)
591 _propertyNode = propertyNode;
592 if (_dataType.valid() && _propertyNode.valid())
593 _dataElement = createDataElement(_dataType, _propertyNode);
597 HLAPropertyDataElement::getPropertyNode()
599 return _propertyNode.get();
602 const SGPropertyNode*
603 HLAPropertyDataElement::getPropertyNode() const
605 return _propertyNode.get();
609 HLAPropertyDataElement::createDataElement(const SGSharedPtr<const HLADataType>& dataType,
610 const SGSharedPtr<SGPropertyNode>& propertyNode)
612 DataElementFactoryVisitor visitor(propertyNode);
613 dataType->accept(visitor);
614 SGSharedPtr<HLADataElement> dataElement = visitor.getDataElement();
616 // Copy over the content of the previous data element if there is any.
617 if (_dataElement.valid()) {
618 // FIXME is encode/decode the right tool here??
620 HLAEncodeStream encodeStream(data);
621 if (_dataElement->encode(encodeStream)) {
622 HLADecodeStream decodeStream(data);
623 dataElement->decode(decodeStream);
627 return dataElement.release();
630 } // namespace simgear