]> git.mxchange.org Git - simgear.git/blob - simgear/hla/HLADataElement.hxx
hla: Use HLADataElementIndices for HLAInteractionClass.
[simgear.git] / simgear / hla / HLADataElement.hxx
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 #ifndef HLADataElement_hxx
19 #define HLADataElement_hxx
20
21 #include <list>
22 #include <map>
23 #include <simgear/structure/SGReferenced.hxx>
24 #include <simgear/structure/SGSharedPtr.hxx>
25 #include <simgear/timing/timestamp.hxx>
26 #include "RTIData.hxx"
27 #include "HLADataType.hxx"
28 #include "HLATypes.hxx"
29
30 class SGTimeStamp;
31
32 namespace simgear {
33
34 class HLADataElementVisitor;
35 class HLAConstDataElementVisitor;
36
37 class HLADataElement : public SGReferenced {
38 public:
39     virtual ~HLADataElement();
40
41     virtual void accept(HLADataElementVisitor& visitor) = 0;
42     virtual void accept(HLAConstDataElementVisitor& visitor) const = 0;
43
44     virtual bool encode(HLAEncodeStream& stream) const = 0;
45     virtual bool decode(HLADecodeStream& stream) = 0;
46
47     virtual const HLADataType* getDataType() const = 0;
48     virtual bool setDataType(const HLADataType* dataType) = 0;
49
50     bool setDataElement(const HLADataElementIndex& index, HLADataElement* dataElement)
51     { return setDataElement(index.begin(), index.end(), dataElement); }
52     HLADataElement* getDataElement(const HLADataElementIndex& index)
53     { return getDataElement(index.begin(), index.end()); }
54     const HLADataElement* getDataElement(const HLADataElementIndex& index) const
55     { return getDataElement(index.begin(), index.end()); }
56
57     virtual bool setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement);
58     virtual HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end);
59     virtual const HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const;
60
61     /// Returns the time stamp if this data element.
62     /// Do not access this getter if the getTimeStampValid() method returns false.
63     const SGTimeStamp& getTimeStamp() const
64     { return _stamp->getTimeStamp(); }
65     void setTimeStamp(const SGTimeStamp& timeStamp);
66
67     bool getTimeStampValid() const
68     { if (!_stamp.valid()) return false; return _stamp->getTimeStampValid(); }
69     void setTimeStampValid(bool timeStampValid);
70
71     /// Convenience function that gives the time difference in seconds to a given timestamp
72     /// This function returns 0 if the timestamp is not valid.
73     double getTimeDifference(const SGTimeStamp& timeStamp) const;
74
75     /// Dirty tracking of the attribute/parameter that this data element belongs to
76     bool getDirty() const
77     { if (!_stamp.valid()) return true; return _stamp->getDirty(); }
78     void setDirty(bool dirty)
79     { if (!_stamp.valid()) return; _stamp->setDirty(dirty); }
80
81     /// Stamp handling
82     void createStamp();
83     void attachStamp(HLADataElement& dataElement);
84     void clearStamp();
85
86     /// HLADataElements could be identified by path
87     /// These paths are composed of structure field names and array indices in the
88     /// order they appear while walking to the data element.
89     /// So provide here some tool functions to access these elements
90     /// Note that these functions are relatively expensive in execution time.
91     /// So only use them once at object creation time and store direct references to the values
92
93     class PathElement {
94     public:
95         PathElement(unsigned index) : _data(new IndexData(index)) {}
96         PathElement(const std::string& name) : _data(new FieldData(name)) {}
97
98         bool isFieldValue() const
99         { return _data->toFieldData(); }
100         bool isIndexValue() const
101         { return _data->toIndexData(); }
102
103         unsigned getIndexValue() const
104         {
105             const IndexData* indexData = _data->toIndexData();
106             if (!indexData)
107                 return ~unsigned(0);
108             return indexData->_index;
109         }
110
111         std::string getFieldValue() const
112         {
113             const FieldData* fieldData = _data->toFieldData();
114             if (!fieldData)
115                 return std::string();
116             return fieldData->_name;
117         }
118
119         // Want to be able to use that in std::map and std::set
120         bool operator<(const PathElement& pathElement) const
121         { return _data->less(pathElement._data.get()); }
122         bool operator==(const PathElement& pathElement) const
123         { return _data->equal(pathElement._data.get()); }
124
125         void append(std::string& s) const
126         { _data->append(s); }
127
128     private:
129         struct FieldData;
130         struct IndexData;
131         struct Data : public SGReferenced {
132             virtual ~Data();
133             virtual const FieldData* toFieldData() const;
134             virtual const IndexData* toIndexData() const;
135             virtual bool less(const Data*) const = 0;
136             virtual bool equal(const Data*) const = 0;
137             virtual void append(std::string&) const = 0;
138         };
139         struct FieldData : public Data {
140             FieldData(const std::string& name);
141             virtual ~FieldData();
142             virtual const FieldData* toFieldData() const;
143             virtual bool less(const Data* data) const;
144             virtual bool equal(const Data* data) const;
145             virtual void append(std::string& s) const;
146             std::string _name;
147         };
148         struct IndexData : public Data {
149             IndexData(unsigned index);
150             virtual ~IndexData();
151             virtual const IndexData* toIndexData() const;
152             virtual bool less(const Data* data) const;
153             virtual bool equal(const Data* data) const;
154             virtual void append(std::string& s) const;
155             unsigned _index;
156         };
157
158         SGSharedPtr<Data> _data;
159     };
160     typedef std::list<PathElement> Path;
161     typedef std::pair<std::string, Path> StringPathPair;
162     typedef std::pair<unsigned, Path> IndexPathPair;
163
164     static std::string toString(const Path& path);
165     static std::string toString(const StringPathPair& path)
166     { return path.first + toString(path.second); }
167     static StringPathPair toStringPathPair(const std::string& s);
168     static Path toPath(const std::string& s)
169     { return toStringPathPair(s).second; }
170
171 protected:
172     // Container for the timestamp the originating attribute was last updated for
173     class Stamp : public SGReferenced {
174     public:
175         Stamp() : _timeStampValid(false), _dirty(true)
176         { }
177
178         const SGTimeStamp& getTimeStamp() const
179         { return _timeStamp; }
180         void setTimeStamp(const SGTimeStamp& timeStamp)
181         { _timeStamp = timeStamp; }
182
183         bool getTimeStampValid() const
184         { return _timeStampValid; }
185         void setTimeStampValid(bool timeStampValid)
186         { _timeStampValid = timeStampValid; }
187
188         bool getDirty() const
189         { return _dirty; }
190         void setDirty(bool dirty)
191         { _dirty = dirty; }
192
193     private:
194         SGTimeStamp _timeStamp;
195         bool _timeStampValid;
196         bool _dirty;
197     };
198
199     /// get the stamp
200     Stamp* _getStamp() const
201     { return _stamp.get(); }
202     /// Set the stamp
203     virtual void _setStamp(Stamp* stamp);
204
205 private:
206     SGSharedPtr<Stamp> _stamp;
207 };
208
209 class HLADataElementProvider {
210 public:
211     class AbstractProvider : public SGReferenced {
212     public:
213         virtual ~AbstractProvider() { }
214         virtual HLADataElement* getDataElement(const HLADataElement::Path& path) = 0;
215         // virtual HLADataElement* getDataElement(const HLADataElement::Path& path, const HLADataType* dataType)
216         // {
217         //     SGSharedPtr<HLADataElement> dataElement = getDataElement(path);
218         //     if (!dataElement.valid())
219         //         return 0;
220         //     if (!dataElement->setDataType(dataType))
221         //         return 0;
222         //     return dataElement.release();
223         // }
224     };
225
226     HLADataElementProvider()
227     { }
228     HLADataElementProvider(HLADataElement* dataElement) :
229         _provider(new ConcreteProvider(dataElement))
230     { }
231     HLADataElementProvider(const SGSharedPtr<HLADataElement>& dataElement) :
232         _provider(new ConcreteProvider(dataElement))
233     { }
234     HLADataElementProvider(AbstractProvider* provider) :
235         _provider(provider)
236     { }
237
238     HLADataElement* getDataElement(const HLADataElement::Path& path) const
239     {
240         if (!_provider.valid())
241             return 0;
242         return _provider->getDataElement(path);
243     }
244
245 private:
246     class ConcreteProvider : public AbstractProvider {
247     public:
248         ConcreteProvider(const SGSharedPtr<HLADataElement>& dataElement) :
249             _dataElement(dataElement)
250         { }
251         virtual HLADataElement* getDataElement(const HLADataElement::Path&)
252         { return _dataElement.get(); }
253     private:
254         SGSharedPtr<HLADataElement> _dataElement;
255     };
256
257     SGSharedPtr<AbstractProvider> _provider;
258 };
259
260 typedef std::map<HLADataElement::Path, HLADataElementProvider> HLAPathElementMap;
261 typedef std::map<unsigned, HLAPathElementMap> HLAAttributePathElementMap;
262
263 }
264
265 #endif