]> git.mxchange.org Git - simgear.git/blob - simgear/hla/HLAOMTXmlVisitor.cxx
hla: Fix buffer overrun in SGMath vector types.
[simgear.git] / simgear / hla / HLAOMTXmlVisitor.cxx
1 // Copyright (C) 2009 - 2012  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 "HLAOMTXmlVisitor.hxx"
19
20 #include <map>
21 #include <string>
22 #include <sstream>
23
24 #include <simgear/structure/exception.hxx>
25 #include <simgear/xml/easyxml.hxx>
26 #include "HLAArrayDataType.hxx"
27 #include "HLABasicDataType.hxx"
28 #include "HLADataTypeVisitor.hxx"
29 #include "HLAEnumeratedDataType.hxx"
30 #include "HLAFederate.hxx"
31 #include "HLAFixedRecordDataType.hxx"
32 #include "HLAVariantRecordDataType.hxx"
33
34 namespace simgear {
35
36 HLAOMTXmlVisitor::ObjectClass::ObjectClass(const std::string& name, const std::string& sharing) :
37     _name(name),
38     _sharing(sharing)
39 {
40 }
41
42 HLAOMTXmlVisitor::ObjectClass::~ObjectClass()
43 {
44 }
45
46 const std::string&
47 HLAOMTXmlVisitor::ObjectClass::getName() const
48 {
49     return _name;
50 }
51
52 const std::string&
53 HLAOMTXmlVisitor::ObjectClass::getSharing() const
54 {
55     return _sharing;
56 }
57
58 unsigned
59 HLAOMTXmlVisitor::ObjectClass::getNumAttributes() const
60 {
61     return _attributes.size();
62 }
63
64 const HLAOMTXmlVisitor::Attribute*
65 HLAOMTXmlVisitor::ObjectClass::getAttribute(unsigned index) const
66 {
67     if (_attributes.size() <= index)
68         return 0;
69     return _attributes[index];
70 }
71
72 const HLAOMTXmlVisitor::ObjectClass*
73 HLAOMTXmlVisitor::ObjectClass::getParentObjectClass() const
74 {
75     return _parentObjectClass.get();
76 }
77
78 HLAOMTXmlVisitor::InteractionClass::InteractionClass(const std::string& name) :
79     _name(name)
80 {
81 }
82
83 HLAOMTXmlVisitor::InteractionClass::~InteractionClass()
84 {
85 }
86
87 const std::string&
88 HLAOMTXmlVisitor::InteractionClass::getName() const
89 {
90     return _name;
91 }
92
93 const std::string&
94 HLAOMTXmlVisitor::InteractionClass::getDimensions() const
95 {
96     return _dimensions;
97 }
98
99 const std::string&
100 HLAOMTXmlVisitor::InteractionClass::getSharing() const
101 {
102     return _sharing;
103 }
104
105 const std::string&
106 HLAOMTXmlVisitor::InteractionClass::getTransportation() const
107 {
108     return _transportation;
109 }
110
111 const std::string&
112 HLAOMTXmlVisitor::InteractionClass::getOrder() const
113 {
114     return _order;
115 }
116
117 unsigned
118 HLAOMTXmlVisitor::InteractionClass::getNumParameters() const
119 {
120     return _parameters.size();
121 }
122
123 const HLAOMTXmlVisitor::Parameter*
124 HLAOMTXmlVisitor::InteractionClass::getParameter(unsigned index) const
125 {
126     if (_parameters.size() <= index)
127         return 0;
128     return _parameters[index];
129 }
130
131 const HLAOMTXmlVisitor::InteractionClass*
132 HLAOMTXmlVisitor::InteractionClass::getParentInteractionClass() const
133 {
134     return _parentInteractionClass.get();
135 }
136
137 HLAOMTXmlVisitor::HLAOMTXmlVisitor()
138 {
139 }
140
141 HLAOMTXmlVisitor::~HLAOMTXmlVisitor()
142 {
143 }
144
145 void
146 HLAOMTXmlVisitor::setDataTypesToFederate(HLAFederate& federate)
147 {
148     // Provide all the data types
149     for (BasicDataMap::iterator i = _basicDataMap.begin(); i != _basicDataMap.end(); ++i)
150         federate.insertDataType(i->first, getDataType(i->first));
151     for (SimpleDataMap::iterator i = _simpleDataMap.begin(); i != _simpleDataMap.end(); ++i)
152         federate.insertDataType(i->first, getDataType(i->first));
153     for (EnumeratedDataMap::iterator i = _enumeratedDataMap.begin(); i != _enumeratedDataMap.end(); ++i)
154         federate.insertDataType(i->first, getDataType(i->first));
155     for (ArrayDataMap::iterator i = _arrayDataMap.begin(); i != _arrayDataMap.end(); ++i)
156         federate.insertDataType(i->first, getDataType(i->first));
157     for (FixedRecordDataMap::iterator i = _fixedRecordDataMap.begin(); i != _fixedRecordDataMap.end(); ++i)
158         federate.insertDataType(i->first, getDataType(i->first));
159     for (VariantRecordDataMap::iterator i = _variantRecordDataMap.begin(); i != _variantRecordDataMap.end(); ++i)
160         federate.insertDataType(i->first, getDataType(i->first));
161
162     // Finish alignment computations
163     federate.recomputeDataTypeAlignment();
164 }
165
166 void
167 HLAOMTXmlVisitor::setToFederate(HLAFederate& federate)
168 {
169     setDataTypesToFederate(federate);
170
171     // Provide all interaction classes
172     unsigned numInteractionClasses = getNumInteractionClasses();
173     for (unsigned i = 0; i < numInteractionClasses; ++i) {
174         const InteractionClass* interactionClass = getInteractionClass(i);
175
176         SGSharedPtr<HLAInteractionClass> hlaInteractionClass;
177         hlaInteractionClass = federate.createInteractionClass(interactionClass->getName());
178         if (!hlaInteractionClass.valid()) {
179             SG_LOG(SG_IO, SG_INFO, "Ignoring Interaction class \"" << interactionClass->getName() << "\".");
180             continue;
181         }
182
183         hlaInteractionClass->setSubscriptionType(interactionClass->getSubscriptionType());
184         hlaInteractionClass->setPublicationType(interactionClass->getPublicationType());
185
186         // process the parameters
187         for (unsigned j = 0; j < interactionClass->getNumParameters(); ++j) {
188             const Parameter* parameter = interactionClass->getParameter(j);
189             unsigned index = hlaInteractionClass->addParameter(parameter->getName());
190             hlaInteractionClass->setParameterDataType(index, federate.getDataType(parameter->getDataType()));
191         }
192     }
193
194     // Provide all object classes
195     unsigned numObjectClasses = getNumObjectClasses();
196     for (unsigned i = 0; i < numObjectClasses; ++i) {
197         const ObjectClass* objectClass = getObjectClass(i);
198
199         SGSharedPtr<HLAObjectClass> hlaObjectClass;
200         hlaObjectClass = federate.createObjectClass(objectClass->getName());
201         if (!hlaObjectClass.valid()) {
202             SG_LOG(SG_IO, SG_INFO, "Ignoring Object class \"" << objectClass->getName() << "\".");
203             continue;
204         }
205
206         // process the attributes
207         for (unsigned j = 0; j < objectClass->getNumAttributes(); ++j) {
208             const Attribute* attribute = objectClass->getAttribute(j);
209
210             unsigned index = hlaObjectClass->addAttribute(attribute->getName());
211             hlaObjectClass->setAttributeDataType(index, federate.getDataType(attribute->getDataType()));
212
213             hlaObjectClass->setAttributeSubscriptionType(index, attribute->getSubscriptionType());
214             hlaObjectClass->setAttributePublicationType(index, attribute->getPublicationType());
215             hlaObjectClass->setAttributeUpdateType(index, attribute->getUpdateType());
216         }
217     }
218 }
219
220 unsigned
221 HLAOMTXmlVisitor::getNumObjectClasses() const
222 {
223     return _objectClassList.size();
224 }
225
226 const HLAOMTXmlVisitor::ObjectClass*
227 HLAOMTXmlVisitor::getObjectClass(unsigned i) const
228 {
229     if (_objectClassList.size() <= i)
230         return 0;
231     return _objectClassList[i];
232 }
233
234 unsigned
235 HLAOMTXmlVisitor::getNumInteractionClasses() const
236 {
237     return _interactionClassList.size();
238 }
239
240 const HLAOMTXmlVisitor::InteractionClass*
241 HLAOMTXmlVisitor::getInteractionClass(unsigned i) const
242 {
243     if (_interactionClassList.size() <= i)
244         return 0;
245     return _interactionClassList[i];
246 }
247
248 SGSharedPtr<HLADataType>
249 HLAOMTXmlVisitor::getDataType(const std::string& dataTypeName)
250 {
251     StringDataTypeMap::const_iterator i = _dataTypeMap.find(dataTypeName);
252     if (i != _dataTypeMap.end())
253         return i->second;
254
255     SGSharedPtr<HLADataType> dataType;
256     dataType = getBasicDataType(dataTypeName);
257     if (dataType.valid()) {
258         _dataTypeMap[dataTypeName] = dataType;
259         return dataType;
260     }
261
262     dataType = getSimpleDataType(dataTypeName);
263     if (dataType.valid())
264         return dataType;
265
266     dataType = getEnumeratedDataType(dataTypeName);
267     if (dataType.valid())
268         return dataType;
269
270     dataType = getArrayDataType(dataTypeName);
271     if (dataType.valid())
272         return dataType;
273
274     dataType = getFixedRecordDataType(dataTypeName);
275     if (dataType.valid())
276         return dataType;
277
278     dataType = getVariantRecordDataType(dataTypeName);
279     if (dataType.valid())
280         return dataType;
281
282     SG_LOG(SG_IO, SG_WARN, "Could not resolve dataType \"" << dataTypeName << "\".");
283     return 0;
284 }
285
286 SGSharedPtr<HLABasicDataType>
287 HLAOMTXmlVisitor::getBasicDataType(const std::string& dataTypeName)
288 {
289     BasicDataMap::const_iterator i = _basicDataMap.find(dataTypeName);
290     if (i == _basicDataMap.end())
291         return 0;
292     if (i->second._size == "8") {
293         return new HLAUInt8DataType(dataTypeName);
294     } else if (i->second._size == "16") {
295         if (i->first.find("Unsigned") != std::string::npos) {
296             if (i->second._endian == "Little") {
297                 return new HLAUInt16LEDataType(dataTypeName);
298             } else {
299                 return new HLAUInt16BEDataType(dataTypeName);
300             }
301         } else if (i->first.find("octetPair") != std::string::npos) {
302             if (i->second._endian == "Little") {
303                 return new HLAUInt16LEDataType(dataTypeName);
304             } else {
305                 return new HLAUInt16BEDataType(dataTypeName);
306             }
307         } else {
308             if (i->second._endian == "Little") {
309                 return new HLAInt16LEDataType(dataTypeName);
310             } else {
311                 return new HLAInt16BEDataType(dataTypeName);
312             }
313         }
314     } else if (i->second._size == "32") {
315         if (i->first.find("Unsigned") != std::string::npos) {
316             if (i->second._endian == "Little") {
317                 return new HLAUInt32LEDataType(dataTypeName);
318             } else {
319                 return new HLAUInt32BEDataType(dataTypeName);
320             }
321         } else if (i->first.find("float") != std::string::npos) {
322             if (i->second._endian == "Little") {
323                 return new HLAFloat32LEDataType(dataTypeName);
324             } else {
325                 return new HLAFloat32BEDataType(dataTypeName);
326             }
327         } else {
328             if (i->second._endian == "Little") {
329                 return new HLAInt32LEDataType(dataTypeName);
330             } else {
331                 return new HLAInt32BEDataType(dataTypeName);
332             }
333         }
334     } else if (i->second._size == "64") {
335         if (i->first.find("Unsigned") != std::string::npos) {
336             if (i->second._endian == "Little") {
337                 return new HLAUInt64LEDataType(dataTypeName);
338             } else {
339                 return new HLAUInt64BEDataType(dataTypeName);
340             }
341         } else if (i->first.find("float") != std::string::npos) {
342             if (i->second._endian == "Little") {
343                 return new HLAFloat64LEDataType(dataTypeName);
344             } else {
345                 return new HLAFloat64BEDataType(dataTypeName);
346             }
347         } else {
348             if (i->second._endian == "Little") {
349                 return new HLAInt64LEDataType(dataTypeName);
350             } else {
351                 return new HLAInt64BEDataType(dataTypeName);
352             }
353         }
354     }
355
356     return 0;
357 }
358
359 SGSharedPtr<HLADataType>
360 HLAOMTXmlVisitor::getSimpleDataType(const std::string& dataTypeName)
361 {
362     SimpleDataMap::const_iterator i = _simpleDataMap.find(dataTypeName);
363     if (i == _simpleDataMap.end())
364         return 0;
365     return getDataType(i->second._representation);
366 }
367
368 SGSharedPtr<HLAEnumeratedDataType>
369 HLAOMTXmlVisitor::getEnumeratedDataType(const std::string& dataTypeName)
370 {
371     EnumeratedDataMap::const_iterator i = _enumeratedDataMap.find(dataTypeName);
372     if (i == _enumeratedDataMap.end())
373         return 0;
374
375     SGSharedPtr<HLAEnumeratedDataType> enumeratedDataType = new HLAEnumeratedDataType(dataTypeName);
376     _dataTypeMap[dataTypeName] = enumeratedDataType;
377     enumeratedDataType->setRepresentation(getBasicDataType(i->second._representation));
378
379     for (EnumeratorList::const_iterator j = i->second._enumeratorList.begin();
380          j != i->second._enumeratorList.end(); ++j) {
381         if (!enumeratedDataType->addEnumerator(j->_name, j->_values)) {
382             SG_LOG(SG_IO, SG_ALERT, "Could not add enumerator \"" << j->_name
383                    << "\" to find enumerated data type \"" << dataTypeName << "\".");
384             return 0;
385         }
386     }
387
388     return enumeratedDataType;
389 }
390
391 SGSharedPtr<HLADataType>
392 HLAOMTXmlVisitor::getArrayDataType(const std::string& dataTypeName)
393 {
394     ArrayDataMap::const_iterator i = _arrayDataMap.find(dataTypeName);
395     if (i == _arrayDataMap.end())
396         return 0;
397     SGSharedPtr<HLAArrayDataType> arrayDataType;
398     if (i->second._encoding == "HLAvariableArray") {
399         arrayDataType = new HLAVariableArrayDataType(dataTypeName);
400     } else if (i->second._encoding == "HLAfixedArray") {
401         std::stringstream ss(i->second._cardinality);
402         unsigned cardinality;
403         ss >> cardinality;
404         if (ss.fail()) {
405             SG_LOG(SG_IO, SG_ALERT, "Could not interpret cardinality \""
406                    << i->second._cardinality << "\" for dataType \""
407                    << dataTypeName << "\".");
408             return 0;
409         }
410         SGSharedPtr<HLAFixedArrayDataType> dataType = new HLAFixedArrayDataType(dataTypeName);
411         dataType->setNumElements(cardinality);
412         arrayDataType = dataType;
413     } else {
414         SG_LOG(SG_IO, SG_ALERT, "Can not interpret encoding \""
415                << i->second._encoding << "\" for dataType \""
416                << dataTypeName << "\".");
417         return 0;
418     }
419
420     _dataTypeMap[dataTypeName] = arrayDataType;
421     SGSharedPtr<HLADataType> elementDataType = getDataType(i->second._dataType);
422     if (!elementDataType.valid()) {
423         SG_LOG(SG_IO, SG_ALERT, "Could not interpret dataType \""
424                << i->second._dataType << "\" for array data type \""
425                << dataTypeName << "\".");
426         _dataTypeMap.erase(dataTypeName);
427         return 0;
428     }
429     arrayDataType->setElementDataType(elementDataType.get());
430
431     // Check if this should be a string data type
432     if (elementDataType->toBasicDataType()) {
433         if (dataTypeName == "HLAopaqueData") {
434             arrayDataType->setIsOpaque(true);
435         } else if (dataTypeName.find("String") != std::string::npos || dataTypeName.find("string") != std::string::npos) {
436             arrayDataType->setIsString(true);
437         }
438     }
439
440     return arrayDataType;
441 }
442
443 SGSharedPtr<HLAFixedRecordDataType>
444 HLAOMTXmlVisitor::getFixedRecordDataType(const std::string& dataTypeName)
445 {
446     FixedRecordDataMap::const_iterator i = _fixedRecordDataMap.find(dataTypeName);
447     if (i == _fixedRecordDataMap.end())
448         return 0;
449
450     SGSharedPtr<HLAFixedRecordDataType> dataType = new HLAFixedRecordDataType(dataTypeName);
451     _dataTypeMap[dataTypeName] = dataType;
452     for (FieldList::size_type j = 0; j < i->second._fieldList.size(); ++j) {
453         SGSharedPtr<HLADataType> fieldDataType = getDataType(i->second._fieldList[j]._dataType);
454         if (!fieldDataType.valid()) {
455             SG_LOG(SG_IO, SG_ALERT, "Could not get data type \"" << i->second._fieldList[j]._dataType
456                    << "\" for field " << j << "of fixed record data type \"" << dataTypeName << "\".");
457             _dataTypeMap.erase(dataTypeName);
458             return 0;
459         }
460         dataType->addField(i->second._fieldList[j]._name, fieldDataType.get());
461     }
462     return dataType;
463 }
464
465 SGSharedPtr<HLAVariantRecordDataType>
466 HLAOMTXmlVisitor::getVariantRecordDataType(const std::string& dataTypeName)
467 {
468     VariantRecordDataMap::const_iterator i = _variantRecordDataMap.find(dataTypeName);
469     if (i == _variantRecordDataMap.end())
470         return 0;
471     SGSharedPtr<HLAVariantRecordDataType> dataType = new HLAVariantRecordDataType(dataTypeName);
472     _dataTypeMap[dataTypeName] = dataType;
473
474     SGSharedPtr<HLAEnumeratedDataType> enumeratedDataType = getEnumeratedDataType(i->second._dataType);
475     if (!enumeratedDataType.valid()) {
476         SG_LOG(SG_IO, SG_ALERT, "Could not find enumerted data type \"" << i->second._dataType
477                << "\" for variant data type \"" << dataTypeName << "\".");
478         return 0;
479     }
480     dataType->setEnumeratedDataType(enumeratedDataType);
481
482     for (AlternativeList::const_iterator j = i->second._alternativeList.begin();
483          j != i->second._alternativeList.end(); ++j) {
484         SGSharedPtr<HLADataType> alternativeDataType = getDataType(j->_dataType);
485         if (!alternativeDataType.valid()) {
486             SG_LOG(SG_IO, SG_ALERT, "Could not resolve alternative dataType \"" << j->_dataType
487                    << "\" for alternative \"" << j->_name << "\".");
488             _dataTypeMap.erase(dataTypeName);
489             return 0;
490         }
491         if (!dataType->addAlternative(j->_name, j->_enumerator, alternativeDataType.get(), j->_semantics)) {
492             SG_LOG(SG_IO, SG_ALERT, "Could not add alternative \"" << j->_name << "\".");
493             return 0;
494         }
495     }
496     return dataType;
497 }
498
499 HLAOMTXmlVisitor::Mode
500 HLAOMTXmlVisitor::getCurrentMode()
501 {
502     if (_modeStack.empty())
503         return UnknownMode;
504     return _modeStack.back();
505 }
506
507 void
508 HLAOMTXmlVisitor::pushMode(HLAOMTXmlVisitor::Mode mode)
509 {
510     _modeStack.push_back(mode);
511 }
512
513 void
514 HLAOMTXmlVisitor::popMode()
515 {
516     _modeStack.pop_back();
517 }
518
519 void
520 HLAOMTXmlVisitor::startXML()
521 {
522     _modeStack.clear();
523 }
524
525 void
526 HLAOMTXmlVisitor::endXML()
527 {
528     if (!_modeStack.empty())
529         throw sg_exception("Internal parse error!");
530
531     // propagate parent attributes to the derived classes
532     // Note that this preserves the order og the attributes starting from the root object
533     for (ObjectClassList::const_iterator i = _objectClassList.begin(); i != _objectClassList.end(); ++i) {
534         SGSharedPtr<const ObjectClass> objectClass = (*i)->_parentObjectClass;
535         while (objectClass) {
536             for (AttributeList::const_reverse_iterator j = objectClass->_attributes.rbegin();
537                  j != objectClass->_attributes.rend(); ++j) {
538                 (*i)->_attributes.insert((*i)->_attributes.begin(), *j);
539             }
540             objectClass = objectClass->_parentObjectClass;
541         }
542     }
543
544     // propagate parent parameter to the derived interactions
545     // Note that this preserves the order og the parameters starting from the root object
546     for (InteractionClassList::const_iterator i = _interactionClassList.begin(); i != _interactionClassList.end(); ++i) {
547         SGSharedPtr<const InteractionClass> interactionClass = (*i)->_parentInteractionClass;
548         while (interactionClass) {
549             for (ParameterList::const_reverse_iterator j = interactionClass->_parameters.rbegin();
550                  j != interactionClass->_parameters.rend(); ++j) {
551                 (*i)->_parameters.insert((*i)->_parameters.begin(), *j);
552             }
553             interactionClass = interactionClass->_parentInteractionClass;
554         }
555     }
556 }
557
558 void
559 HLAOMTXmlVisitor::startElement(const char* name, const XMLAttributes& atts)
560 {
561     if (strcmp(name, "attribute") == 0) {
562         if (getCurrentMode() != ObjectClassMode)
563             throw sg_exception("attribute tag outside objectClass!");
564         pushMode(AttributeMode);
565
566         if (_objectClassList.empty())
567             throw sg_exception("attribute tag outside of an objectClass");
568
569         std::string name = getAttribute("name", atts);
570         if (name.empty())
571             throw sg_exception("attribute tag without name attribute");
572
573         SGSharedPtr<Attribute> attribute = new Attribute(name);
574
575         attribute->_dataType = getAttribute("dataType", atts);
576         attribute->_updateType = getAttribute("updateType", atts);
577         attribute->_updateCondition = getAttribute("updateCondition", atts);
578         attribute->_ownership = getAttribute("ownership", atts);
579         attribute->_sharing = getAttribute("sharing", atts);
580         attribute->_dimensions = getAttribute("dimensions", atts);
581         attribute->_transportation = getAttribute("transportation", atts);
582         attribute->_order = getAttribute("order", atts);
583
584         _objectClassStack.back()->_attributes.push_back(attribute);
585
586     } else if (strcmp(name, "objectClass") == 0) {
587         if (getCurrentMode() != ObjectsMode && getCurrentMode() != ObjectClassMode)
588             throw sg_exception("objectClass tag outside objectClass or objects!");
589         pushMode(ObjectClassMode);
590
591         std::string name = getAttribute("name", atts);
592         if (name.empty())
593             throw sg_exception("objectClass tag without name attribute");
594
595         std::string sharing = getAttribute("sharing", atts);
596
597         // The new ObjectClass
598         ObjectClass* objectClass = new ObjectClass(name, sharing);
599
600         // Inherit all previous attributes
601         if (!_objectClassStack.empty())
602             objectClass->_parentObjectClass = _objectClassStack.back();
603
604         _objectClassStack.push_back(objectClass);
605         _objectClassList.push_back(objectClass);
606
607     } else if (strcmp(name, "objects") == 0) {
608         if (getCurrentMode() != ObjectModelMode)
609             throw sg_exception("objects tag outside objectModel!");
610         pushMode(ObjectsMode);
611
612     } else if (strcmp(name, "parameter") == 0) {
613         if (getCurrentMode() != InteractionClassMode)
614             throw sg_exception("parameter tag outside interactionClass!");
615         pushMode(ParameterMode);
616
617         if (_interactionClassList.empty())
618             throw sg_exception("parameter tag outside of an interactionClass");
619
620         std::string name = getAttribute("name", atts);
621         if (name.empty())
622             throw sg_exception("parameter tag without name parameter");
623
624         SGSharedPtr<Parameter> parameter = new Parameter(name);
625         parameter->_dataType = getAttribute("dataType", atts);
626
627         _interactionClassStack.back()->_parameters.push_back(parameter);
628
629     } else if (strcmp(name, "interactionClass") == 0) {
630         if (getCurrentMode() != InteractionsMode && getCurrentMode() != InteractionClassMode)
631             throw sg_exception("interactionClass tag outside interactions or interactionClass!");
632         pushMode(InteractionClassMode);
633
634         std::string name = getAttribute("name", atts);
635         if (name.empty())
636             throw sg_exception("interactionClass tag without name attribute");
637
638         // The new ObjectClass
639         InteractionClass* interactionClass = new InteractionClass(name);
640         interactionClass->_dimensions = getAttribute("dimensions", atts);
641         interactionClass->_transportation = getAttribute("transportation", atts);
642         interactionClass->_order = getAttribute("order", atts);
643
644         // Inherit all previous attributes
645         if (!_interactionClassStack.empty())
646             interactionClass->_parentInteractionClass = _interactionClassStack.back();
647
648         _interactionClassStack.push_back(interactionClass);
649         _interactionClassList.push_back(interactionClass);
650
651     } else if (strcmp(name, "interactions") == 0) {
652         if (getCurrentMode() != ObjectModelMode)
653             throw sg_exception("interactions tag outside objectModel!");
654         pushMode(InteractionsMode);
655
656     } else if (strcmp(name, "basicData") == 0) {
657         if (getCurrentMode() != BasicDataRepresentationsMode)
658             throw sg_exception("basicData tag outside basicDataRepresentations!");
659         pushMode(BasicDataMode);
660
661         std::string name = getAttribute("name", atts);
662         if (name.empty())
663             throw sg_exception("basicData tag without name attribute");
664
665         _basicDataMap[name]._size = getAttribute("size", atts);
666         _basicDataMap[name]._endian = getAttribute("endian", atts);
667
668     } else if (strcmp(name, "basicDataRepresentations") == 0) {
669         if (getCurrentMode() != DataTypesMode)
670             throw sg_exception("basicDataRepresentations tag outside dataTypes!");
671         pushMode(BasicDataRepresentationsMode);
672
673     } else if (strcmp(name, "simpleData") == 0) {
674         if (getCurrentMode() != SimpleDataTypesMode)
675             throw sg_exception("simpleData tag outside simpleDataTypes!");
676         pushMode(SimpleDataMode);
677
678         std::string name = getAttribute("name", atts);
679         if (name.empty())
680             throw sg_exception("simpleData tag without name attribute");
681
682         _simpleDataMap[name]._representation = getAttribute("representation", atts);
683         _simpleDataMap[name]._units = getAttribute("units", atts);
684         _simpleDataMap[name]._resolution = getAttribute("resolution", atts);
685         _simpleDataMap[name]._accuracy = getAttribute("accuracy", atts);
686
687     } else if (strcmp(name, "simpleDataTypes") == 0) {
688         if (getCurrentMode() != DataTypesMode)
689             throw sg_exception("simpleDataTypes tag outside dataTypes!");
690         pushMode(SimpleDataTypesMode);
691
692     } else if (strcmp(name, "enumerator") == 0) {
693         if (getCurrentMode() != EnumeratedDataMode)
694             throw sg_exception("enumerator tag outside enumeratedData!");
695         pushMode(EnumeratorMode);
696
697         std::string name = getAttribute("name", atts);
698         if (name.empty())
699             throw sg_exception("enumerator tag without name attribute");
700
701         Enumerator enumerator;
702         enumerator._name = name;
703         enumerator._values = getAttribute("values", atts);
704         _enumeratedDataMap[_enumeratedDataName]._enumeratorList.push_back(enumerator);
705
706     } else if (strcmp(name, "enumeratedData") == 0) {
707         if (getCurrentMode() != EnumeratedDataTypesMode)
708             throw sg_exception("enumeratedData tag outside enumeratedDataTypes!");
709         pushMode(EnumeratedDataMode);
710
711         std::string name = getAttribute("name", atts);
712         if (name.empty())
713             throw sg_exception("enumeratedData tag without name attribute");
714
715         _enumeratedDataName = name;
716         _enumeratedDataMap[_enumeratedDataName]._representation = getAttribute("representation", atts);
717
718     } else if (strcmp(name, "enumeratedDataTypes") == 0) {
719         if (getCurrentMode() != DataTypesMode)
720             throw sg_exception("enumeratedDataTypes tag outside dataTypes!");
721         pushMode(EnumeratedDataTypesMode);
722
723     } else if (strcmp(name, "arrayData") == 0) {
724         if (getCurrentMode() != ArrayDataTypesMode)
725             throw sg_exception("arrayData tag outside arrayDataTypes!");
726         pushMode(ArrayDataMode);
727
728         std::string name = getAttribute("name", atts);
729         if (name.empty())
730             throw sg_exception("arrayData tag without name attribute");
731
732         _arrayDataMap[name]._dataType = getAttribute("dataType", atts);
733         _arrayDataMap[name]._cardinality = getAttribute("cardinality", atts);
734         _arrayDataMap[name]._encoding = getAttribute("encoding", atts);
735
736     } else if (strcmp(name, "arrayDataTypes") == 0) {
737         if (getCurrentMode() != DataTypesMode)
738             throw sg_exception("arrayDataTypes tag outside dataTypes!");
739         pushMode(ArrayDataTypesMode);
740
741     } else if (strcmp(name, "field") == 0) {
742         if (getCurrentMode() != FixedRecordDataMode)
743             throw sg_exception("field tag outside fixedRecordData!");
744         pushMode(FieldMode);
745
746         std::string name = getAttribute("name", atts);
747         if (name.empty())
748             throw sg_exception("field tag without name attribute");
749
750         Field field;
751         field._name = name;
752         field._dataType = getAttribute("dataType", atts);
753         _fixedRecordDataMap[_fixedRecordDataName]._fieldList.push_back(field);
754
755     } else if (strcmp(name, "fixedRecordData") == 0) {
756         if (getCurrentMode() != FixedRecordDataTypesMode)
757             throw sg_exception("fixedRecordData tag outside fixedRecordDataTypes!");
758         pushMode(FixedRecordDataMode);
759
760         std::string name = getAttribute("name", atts);
761         if (name.empty())
762             throw sg_exception("fixedRecordData tag without name attribute");
763
764         _fixedRecordDataName = name;
765         _fixedRecordDataMap[name]._encoding = getAttribute("encoding", atts);
766
767     } else if (strcmp(name, "fixedRecordDataTypes") == 0) {
768         if (getCurrentMode() != DataTypesMode)
769             throw sg_exception("fixedRecordDataTypes tag outside dataTypes!");
770         pushMode(FixedRecordDataTypesMode);
771
772     } else if (strcmp(name, "alternative") == 0) {
773
774         if (getCurrentMode() != VariantRecordDataMode)
775             throw sg_exception("alternative tag outside variantRecordData!");
776         pushMode(AlternativeDataMode);
777
778         std::string name = getAttribute("name", atts);
779         if (name.empty())
780             throw sg_exception("alternative tag without name attribute");
781
782         Alternative alternative;
783         alternative._name = name;
784         alternative._dataType = getAttribute("dataType", atts);
785         alternative._semantics = getAttribute("semantics", atts);
786         alternative._enumerator = getAttribute("enumerator", atts);
787         _variantRecordDataMap[_variantRecordDataName]._alternativeList.push_back(alternative);
788
789     } else if (strcmp(name, "variantRecordData") == 0) {
790         if (getCurrentMode() != VariantRecordDataTypesMode)
791             throw sg_exception("variantRecordData tag outside variantRecordDataTypes!");
792         pushMode(VariantRecordDataMode);
793
794         std::string name = getAttribute("name", atts);
795         if (name.empty())
796             throw sg_exception("fixedRecordData tag without name attribute");
797
798         _variantRecordDataName = name;
799         _variantRecordDataMap[name]._encoding = getAttribute("encoding", atts);
800         _variantRecordDataMap[name]._dataType = getAttribute("dataType", atts);
801         _variantRecordDataMap[name]._semantics = getAttribute("semantics", atts);
802         _variantRecordDataMap[name]._discriminant = getAttribute("discriminant", atts);
803
804     } else if (strcmp(name, "variantRecordDataTypes") == 0) {
805         if (getCurrentMode() != DataTypesMode)
806             throw sg_exception("variantRecordDataTypes tag outside dataTypes!");
807         pushMode(VariantRecordDataTypesMode);
808
809     } else if (strcmp(name, "dataTypes") == 0) {
810         if (getCurrentMode() != ObjectModelMode)
811             throw sg_exception("dataTypes tag outside objectModel!");
812         pushMode(DataTypesMode);
813
814     } else if (strcmp(name, "objectModel") == 0) {
815         if (!_modeStack.empty())
816             throw sg_exception("objectModel tag not at top level!");
817         pushMode(ObjectModelMode);
818
819     } else {
820         _modeStack.push_back(UnknownMode);
821     }
822 }
823
824 void
825 HLAOMTXmlVisitor::endElement(const char* name)
826 {
827     if (strcmp(name, "objectClass") == 0) {
828         _objectClassStack.pop_back();
829     } else if (strcmp(name, "interactionClass") == 0) {
830         _interactionClassStack.pop_back();
831     } else if (strcmp(name, "enumeratedData") == 0) {
832         _enumeratedDataName.clear();
833     } else if (strcmp(name, "fixedRecordData") == 0) {
834         _fixedRecordDataName.clear();
835     } else if (strcmp(name, "variantRecordData") == 0) {
836         _variantRecordDataName.clear();
837     }
838
839     _modeStack.pop_back();
840 }
841
842 std::string
843 HLAOMTXmlVisitor::getAttribute(const char* name, const XMLAttributes& atts)
844 {
845     int index = atts.findAttribute(name);
846     if (index < 0 || atts.size() <= index)
847         return std::string();
848     return std::string(atts.getValue(index));
849 }
850
851 std::string
852 HLAOMTXmlVisitor::getAttribute(const std::string& name, const XMLAttributes& atts)
853 {
854     int index = atts.findAttribute(name.c_str());
855     if (index < 0 || atts.size() <= index)
856         return std::string();
857     return std::string(atts.getValue(index));
858 }
859
860 } // namespace simgear