]> git.mxchange.org Git - simgear.git/blob - simgear/hla/HLAPropertyDataElement.cxx
hla: Initially request update for subscribed unowned attributes.
[simgear.git] / simgear / hla / HLAPropertyDataElement.cxx
1 // Copyright (C) 2009 - 2011  Mathias Froehlich - Mathias.Froehlich@web.de
2 //
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.
7 //
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.
12 //
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.
16 //
17
18 #include "HLAPropertyDataElement.hxx"
19
20 #include "HLAArrayDataElement.hxx"
21 #include "HLADataTypeVisitor.hxx"
22 #include "HLAFixedRecordDataElement.hxx"
23 #include "HLAVariantDataElement.hxx"
24
25 namespace simgear {
26
27 class HLAPropertyDataElement::ScalarDecodeVisitor : public HLADataTypeDecodeVisitor {
28 public:
29     ScalarDecodeVisitor(HLADecodeStream& stream, SGPropertyNode& propertyNode) :
30         HLADataTypeDecodeVisitor(stream),
31         _propertyNode(propertyNode)
32     { }
33     virtual ~ScalarDecodeVisitor()
34     { }
35
36     virtual void apply(const HLAInt8DataType& dataType)
37     {
38         int8_t value = 0;
39         dataType.decode(_stream, value);
40         _propertyNode.setIntValue(value);
41     }
42     virtual void apply(const HLAUInt8DataType& dataType)
43     {
44         uint8_t value = 0;
45         dataType.decode(_stream, value);
46         _propertyNode.setIntValue(value);
47     }
48     virtual void apply(const HLAInt16DataType& dataType)
49     {
50         int16_t value = 0;
51         dataType.decode(_stream, value);
52         _propertyNode.setIntValue(value);
53     }
54     virtual void apply(const HLAUInt16DataType& dataType)
55     {
56         uint16_t value = 0;
57         dataType.decode(_stream, value);
58         _propertyNode.setIntValue(value);
59     }
60     virtual void apply(const HLAInt32DataType& dataType)
61     {
62         int32_t value = 0;
63         dataType.decode(_stream, value);
64         _propertyNode.setIntValue(value);
65     }
66     virtual void apply(const HLAUInt32DataType& dataType)
67     {
68         uint32_t value = 0;
69         dataType.decode(_stream, value);
70         _propertyNode.setIntValue(value);
71     }
72     virtual void apply(const HLAInt64DataType& dataType)
73     {
74         int64_t value = 0;
75         dataType.decode(_stream, value);
76         _propertyNode.setLongValue(value);
77     }
78     virtual void apply(const HLAUInt64DataType& dataType)
79     {
80         uint64_t value = 0;
81         dataType.decode(_stream, value);
82         _propertyNode.setLongValue(value);
83     }
84     virtual void apply(const HLAFloat32DataType& dataType)
85     {
86         float value = 0;
87         dataType.decode(_stream, value);
88         _propertyNode.setFloatValue(value);
89     }
90     virtual void apply(const HLAFloat64DataType& dataType)
91     {
92         double value = 0;
93         dataType.decode(_stream, value);
94         _propertyNode.setDoubleValue(value);
95     }
96
97 protected:
98     SGPropertyNode& _propertyNode;
99 };
100
101 class HLAPropertyDataElement::ScalarEncodeVisitor : public HLADataTypeEncodeVisitor {
102 public:
103     ScalarEncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) :
104         HLADataTypeEncodeVisitor(stream),
105         _propertyNode(propertyNode)
106     { }
107     virtual ~ScalarEncodeVisitor()
108     { }
109
110     virtual void apply(const HLAInt8DataType& dataType)
111     {
112         dataType.encode(_stream, _propertyNode.getIntValue());
113     }
114     virtual void apply(const HLAUInt8DataType& dataType)
115     {
116         dataType.encode(_stream, _propertyNode.getIntValue());
117     }
118     virtual void apply(const HLAInt16DataType& dataType)
119     {
120         dataType.encode(_stream, _propertyNode.getIntValue());
121     }
122     virtual void apply(const HLAUInt16DataType& dataType)
123     {
124         dataType.encode(_stream, _propertyNode.getIntValue());
125     }
126     virtual void apply(const HLAInt32DataType& dataType)
127     {
128         dataType.encode(_stream, _propertyNode.getIntValue());
129     }
130     virtual void apply(const HLAUInt32DataType& dataType)
131     {
132         dataType.encode(_stream, _propertyNode.getIntValue());
133     }
134     virtual void apply(const HLAInt64DataType& dataType)
135     {
136         dataType.encode(_stream, _propertyNode.getLongValue());
137     }
138     virtual void apply(const HLAUInt64DataType& dataType)
139     {
140         dataType.encode(_stream, _propertyNode.getLongValue());
141     }
142     virtual void apply(const HLAFloat32DataType& dataType)
143     {
144         dataType.encode(_stream, _propertyNode.getFloatValue());
145     }
146     virtual void apply(const HLAFloat64DataType& dataType)
147     {
148         dataType.encode(_stream, _propertyNode.getDoubleValue());
149     }
150
151 protected:
152     const SGPropertyNode& _propertyNode;
153 };
154
155 class HLAPropertyDataElement::ScalarDataElement : public HLADataElement {
156 public:
157     ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode);
158     virtual ~ScalarDataElement();
159
160     virtual bool encode(HLAEncodeStream& stream) const;
161     virtual bool decode(HLADecodeStream& stream);
162
163     virtual const HLADataType* getDataType() const;
164     virtual bool setDataType(const HLADataType* dataType);
165
166 private:
167     SGSharedPtr<const HLABasicDataType> _dataType;
168     SGSharedPtr<SGPropertyNode> _propertyNode;
169 };
170
171 HLAPropertyDataElement::ScalarDataElement::ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode) :
172     _dataType(dataType),
173     _propertyNode(propertyNode)
174 {
175 }
176
177 HLAPropertyDataElement::ScalarDataElement::~ScalarDataElement()
178 {
179 }
180
181 bool
182 HLAPropertyDataElement::ScalarDataElement::encode(HLAEncodeStream& stream) const
183 {
184     ScalarEncodeVisitor visitor(stream, *_propertyNode);
185     _dataType->accept(visitor);
186     return true;
187 }
188
189 bool
190 HLAPropertyDataElement::ScalarDataElement::decode(HLADecodeStream& stream)
191 {
192     ScalarDecodeVisitor visitor(stream, *_propertyNode);
193     _dataType->accept(visitor);
194     return true;
195 }
196
197 const HLADataType*
198 HLAPropertyDataElement::ScalarDataElement::getDataType() const
199 {
200     return _dataType.get();
201 }
202
203 bool
204 HLAPropertyDataElement::ScalarDataElement::setDataType(const HLADataType* dataType)
205 {
206     if (!dataType)
207         return false;
208     const HLABasicDataType* basicDataType = dataType->toBasicDataType();
209     if (!basicDataType)
210         return false;
211     _dataType = basicDataType;
212     return true;
213 }
214
215
216 class HLAPropertyDataElement::StringDecodeVisitor : public HLADataTypeDecodeVisitor {
217 public:
218     StringDecodeVisitor(HLADecodeStream& stream, SGPropertyNode& propertyNode) :
219         HLADataTypeDecodeVisitor(stream),
220         _propertyNode(propertyNode)
221     { }
222
223     virtual void apply(const HLAFixedArrayDataType& dataType)
224     {
225         unsigned numElements = dataType.getNumElements();
226         std::string value;
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());
232         }
233         _propertyNode.setStringValue(value);
234     }
235     virtual void apply(const HLAVariableArrayDataType& dataType)
236     {
237         HLATemplateDecodeVisitor<std::string::size_type> numElementsVisitor(_stream);
238         dataType.getSizeDataType()->accept(numElementsVisitor);
239         std::string::size_type numElements = numElementsVisitor.getValue();
240         std::string value;
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());
246         }
247         _propertyNode.setStringValue(value);
248     }
249
250 protected:
251     SGPropertyNode& _propertyNode;
252 };
253
254 class HLAPropertyDataElement::StringEncodeVisitor : public HLADataTypeEncodeVisitor {
255 public:
256     StringEncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) :
257         HLADataTypeEncodeVisitor(stream),
258         _propertyNode(propertyNode)
259     { }
260
261     virtual void apply(const HLAFixedArrayDataType& dataType)
262     {
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);
269             } else {
270                 HLADataTypeEncodeVisitor visitor(_stream);
271                 dataType.getElementDataType()->accept(visitor);
272             }
273         }
274     }
275
276     virtual void apply(const HLAVariableArrayDataType& dataType)
277     {
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);
284         }
285     }
286
287 protected:
288     const SGPropertyNode& _propertyNode;
289 };
290
291 class HLAPropertyDataElement::StringDataElement : public HLADataElement {
292 public:
293     StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode);
294     virtual ~StringDataElement();
295
296     virtual bool encode(HLAEncodeStream& stream) const;
297     virtual bool decode(HLADecodeStream& stream);
298
299     virtual const HLADataType* getDataType() const;
300     virtual bool setDataType(const HLADataType* dataType);
301
302 private:
303     SGSharedPtr<const HLAArrayDataType> _dataType;
304     SGSharedPtr<SGPropertyNode> _propertyNode;
305 };
306
307 HLAPropertyDataElement::StringDataElement::StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode) :
308     _dataType(dataType),
309     _propertyNode(propertyNode)
310 {
311 }
312
313 HLAPropertyDataElement::StringDataElement::~StringDataElement()
314 {
315 }
316
317 bool
318 HLAPropertyDataElement::StringDataElement::encode(HLAEncodeStream& stream) const
319 {
320     StringEncodeVisitor visitor(stream, *_propertyNode);
321     _dataType->accept(visitor);
322     return true;
323 }
324
325 bool
326 HLAPropertyDataElement::StringDataElement::decode(HLADecodeStream& stream)
327 {
328     StringDecodeVisitor visitor(stream, *_propertyNode);
329     _dataType->accept(visitor);
330     return true;
331 }
332
333 const HLADataType*
334 HLAPropertyDataElement::StringDataElement::getDataType() const
335 {
336     return _dataType.get();
337 }
338
339 bool
340 HLAPropertyDataElement::StringDataElement::setDataType(const HLADataType* dataType)
341 {
342     if (!dataType)
343         return false;
344     const HLAArrayDataType* arrayDataType = dataType->toArrayDataType();
345     if (!arrayDataType)
346         return false;
347     const HLADataType* elementDataType = arrayDataType->getElementDataType();
348     if (!elementDataType)
349         return false;
350     if (!elementDataType->toBasicDataType())
351         return false;
352     _dataType = arrayDataType;
353     return true;
354 }
355
356 class HLAPropertyDataElement::DataElementFactoryVisitor : public HLADataTypeVisitor {
357 public:
358     DataElementFactoryVisitor(SGPropertyNode* propertyNode) :
359         _propertyNode(propertyNode)
360     { }
361     virtual ~DataElementFactoryVisitor()
362     { }
363
364     virtual void apply(const HLADataType& dataType)
365     {
366         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \""
367                << dataType.getName() << "\"");
368     }
369
370     virtual void apply(const HLAInt8DataType& dataType)
371     {
372         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
373     }
374     virtual void apply(const HLAUInt8DataType& dataType)
375     {
376         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
377     }
378     virtual void apply(const HLAInt16DataType& dataType)
379     {
380         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
381     }
382     virtual void apply(const HLAUInt16DataType& dataType)
383     {
384         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
385     }
386     virtual void apply(const HLAInt32DataType& dataType)
387     {
388         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
389     }
390     virtual void apply(const HLAUInt32DataType& dataType)
391     {
392         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
393     }
394     virtual void apply(const HLAInt64DataType& dataType)
395     {
396         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
397     }
398     virtual void apply(const HLAUInt64DataType& dataType)
399     {
400         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
401     }
402     virtual void apply(const HLAFloat32DataType& dataType)
403     {
404         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
405     }
406     virtual void apply(const HLAFloat64DataType& dataType)
407     {
408         _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
409     }
410
411     class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
412     public:
413         ArrayDataElementFactory(SGPropertyNode* propertyNode) :
414             _propertyNode(propertyNode)
415         { }
416         virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index)
417         {
418             const HLADataType* dataType = element.getElementDataType();
419             if (!dataType)
420                 return 0;
421
422             SGPropertyNode* parent = _propertyNode->getParent();
423             DataElementFactoryVisitor visitor(parent->getChild(_propertyNode->getNameString(), index, true));
424             dataType->accept(visitor);
425             return visitor.getDataElement();
426         }
427     private:
428         SGSharedPtr<SGPropertyNode> _propertyNode;
429     };
430
431     virtual void apply(const HLAFixedArrayDataType& dataType)
432     {
433         if (dataType.getIsString()) {
434             _dataElement = new StringDataElement(&dataType, _propertyNode.get());
435         } else {
436             SGSharedPtr<HLAArrayDataElement> arrayDataElement;
437             arrayDataElement = new HLAArrayDataElement(&dataType);
438             arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get()));
439             arrayDataElement->setNumElements(dataType.getNumElements());
440             _dataElement = arrayDataElement;
441         }
442     }
443
444     virtual void apply(const HLAVariableArrayDataType& dataType)
445     {
446         if (dataType.getIsString()) {
447             _dataElement = new StringDataElement(&dataType, _propertyNode.get());
448         } else {
449             SGSharedPtr<HLAArrayDataElement> arrayDataElement;
450             arrayDataElement = new HLAArrayDataElement(&dataType);
451             arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get()));
452             _dataElement = arrayDataElement;
453         }
454     }
455
456     virtual void apply(const HLAEnumeratedDataType& dataType)
457     {
458         _dataElement = new ScalarDataElement(dataType.getRepresentation(), _propertyNode.get());
459     }
460
461     virtual void apply(const HLAFixedRecordDataType& dataType)
462     {
463         SGSharedPtr<HLAFixedRecordDataElement> recordDataElement;
464         recordDataElement = new HLAFixedRecordDataElement(&dataType);
465
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());
471         }
472
473         _dataElement = recordDataElement;
474     }
475
476     class VariantDataElementFactory : public HLAVariantDataElement::DataElementFactory {
477     public:
478         VariantDataElementFactory(SGPropertyNode* propertyNode) :
479             _propertyNode(propertyNode)
480         { }
481         virtual HLADataElement* createElement(const HLAVariantDataElement& element, unsigned index)
482         {
483             const HLAVariantDataType* dataType = element.getDataType();
484             if (!dataType)
485                 return 0;
486             const HLADataType* alternativeDataType = element.getAlternativeDataType();
487             if (!alternativeDataType)
488                 return 0;
489             DataElementFactoryVisitor visitor(_propertyNode->getChild(dataType->getAlternativeName(index), 0, true));
490             alternativeDataType->accept(visitor);
491             return visitor.getDataElement();
492         }
493     private:
494         SGSharedPtr<SGPropertyNode> _propertyNode;
495     };
496
497     virtual void apply(const HLAVariantDataType& dataType)
498     {
499         SGSharedPtr<HLAVariantDataElement> variantDataElement;
500         variantDataElement = new HLAVariantDataElement(&dataType);
501         variantDataElement->setDataElementFactory(new VariantDataElementFactory(_propertyNode.get()));
502         _dataElement = variantDataElement;
503     }
504
505     HLADataElement* getDataElement()
506     { return _dataElement.release(); }
507
508 private:
509     SGSharedPtr<SGPropertyNode> _propertyNode;
510     SGSharedPtr<HLADataElement> _dataElement;
511 };
512
513 HLAPropertyDataElement::HLAPropertyDataElement()
514 {
515 }
516
517 HLAPropertyDataElement::HLAPropertyDataElement(SGPropertyNode* propertyNode)
518 {
519     setPropertyNode(propertyNode);
520 }
521
522 HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType, SGPropertyNode* propertyNode) :
523     _dataType(dataType)
524 {
525     setPropertyNode(propertyNode);
526 }
527
528 HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType) :
529     _dataType(dataType)
530 {
531 }
532
533 HLAPropertyDataElement::~HLAPropertyDataElement()
534 {
535 }
536
537 bool
538 HLAPropertyDataElement::encode(HLAEncodeStream& stream) const
539 {
540     if (_dataElement.valid()) {
541         return _dataElement->encode(stream);
542     } else {
543         if (!_dataType.valid())
544             return false;
545         HLADataTypeEncodeVisitor visitor(stream);
546         _dataType->accept(visitor);
547         return true;
548     }
549 }
550
551 bool
552 HLAPropertyDataElement::decode(HLADecodeStream& stream)
553 {
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
558         return false;
559     } else {
560         HLADataElementFactoryVisitor visitor;
561         _dataType->accept(visitor);
562         _dataElement = visitor.getDataElement();
563         if (_dataElement.valid()) {
564             return _dataElement->decode(stream);
565         } else {
566             HLADataTypeDecodeVisitor visitor(stream);
567             _dataType->accept(visitor);
568             return true;
569         }
570     }
571 }
572
573 const HLADataType*
574 HLAPropertyDataElement::getDataType() const
575 {
576     return _dataType.get();
577 }
578
579 bool
580 HLAPropertyDataElement::setDataType(const HLADataType* dataType)
581 {
582     _dataType = dataType;
583     if (_dataType.valid() && _propertyNode.valid())
584         _dataElement = createDataElement(_dataType, _propertyNode);
585     return true;
586 }
587
588 void
589 HLAPropertyDataElement::setPropertyNode(SGPropertyNode* propertyNode)
590 {
591     _propertyNode = propertyNode;
592     if (_dataType.valid() && _propertyNode.valid())
593         _dataElement = createDataElement(_dataType, _propertyNode);
594 }
595
596 SGPropertyNode*
597 HLAPropertyDataElement::getPropertyNode()
598 {
599     return _propertyNode.get();
600 }
601
602 const SGPropertyNode*
603 HLAPropertyDataElement::getPropertyNode() const
604 {
605     return _propertyNode.get();
606 }
607
608 HLADataElement*
609 HLAPropertyDataElement::createDataElement(const SGSharedPtr<const HLADataType>& dataType,
610                                           const SGSharedPtr<SGPropertyNode>& propertyNode)
611 {
612     DataElementFactoryVisitor visitor(propertyNode);
613     dataType->accept(visitor);
614     SGSharedPtr<HLADataElement> dataElement = visitor.getDataElement();
615
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??
619         RTIData data;
620         HLAEncodeStream encodeStream(data);
621         if (_dataElement->encode(encodeStream)) {
622             HLADecodeStream decodeStream(data);
623             dataElement->decode(decodeStream);
624         }
625     }
626
627     return dataElement.release();
628 }
629
630 } // namespace simgear