]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/input_output/FGXMLElement.h
Fix for bug 1304 - crash loading XML route
[flightgear.git] / src / FDM / JSBSim / input_output / FGXMLElement.h
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  File:         FGXMLElement.h
4  Author:       Jon S. Berndt
5  Date started: 9/28/04
6
7  ------------- Copyright (C) 2004  Jon S. Berndt (jon@jsbsim.org) -------------
8
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU Lesser General Public License as published by the Free Software
11  Foundation; either version 2 of the License, or (at your option) any later
12  version.
13
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
17  details.
18
19  You should have received a copy of the GNU Lesser General Public License along with
20  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21  Place - Suite 330, Boston, MA  02111-1307, USA.
22
23  Further information about the GNU Lesser General Public License can also be found on
24  the world wide web at http://www.gnu.org.
25
26 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
27 SENTRY
28 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
29
30 #ifndef XMLELEMENT_H
31 #define XMLELEMENT_H
32
33 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34 INCLUDES
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
36
37 #include <string>
38 #include <map>
39 #include <vector>
40
41 #include "FGJSBBase.h"
42 #include "math/FGColumnVector3.h"
43
44 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
45 DEFINITIONS
46 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
47
48 #define ID_XMLELEMENT "$Id: FGXMLElement.h,v 1.20 2014/01/13 10:46:02 ehofman Exp $"
49
50 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
51 FORWARD DECLARATIONS
52 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
53
54 namespace JSBSim {
55
56 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57 CLASS DOCUMENTATION
58 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
59
60 /** Encapsulates an XML element.
61     This class handles the creation, storage, and manipulation of XML elements.
62     This class also can convert supplied values as follows:
63
64     convert ["from"]["to"] = factor, so: from * factor = to
65     - convert["M"]["FT"] = 3.2808399;
66     - convert["FT"]["M"] = 1.0/convert["M"]["FT"];
67     - convert["M2"]["FT2"] = convert["M"]["FT"]*convert["M"]["FT"];
68     - convert["FT2"]["M2"] = 1.0/convert["M2"]["FT2"];
69     - convert["FT"]["IN"] = 12.0;
70     - convert["IN"]["FT"] = 1.0/convert["FT"]["IN"];
71     - convert["LBS"]["KG"] = 0.45359237;
72     - convert["KG"]["LBS"] = 1.0/convert["LBS"]["KG"];
73     - convert["SLUG*FT2"]["KG*M2"] = 1.35594;
74     - convert["KG*M2"]["SLUG*FT2"] = 1.0/convert["SLUG*FT2"]["KG*M2"];
75     - convert["RAD"]["DEG"] = 360.0/(2.0*3.1415926);
76     - convert["DEG"]["RAD"] = 1.0/convert["RAD"]["DEG"];
77     - convert["LBS/FT"]["N/M"] = 14.5939;
78     - convert["LBS/FT/SEC"]["N/M/SEC"] = 14.5939;
79     - convert["N/M"]["LBS/FT"] = 1.0/convert["LBS/FT"]["N/M"];
80     - convert["N/M/SEC"]["LBS/FT/SEC"] = 1.0/convert["LBS/FT/SEC"]["N/M/SEC"];
81     - convert["WATTS"]["HP"] = 0.001341022;
82     - convert["HP"]["WATTS"] = 1.0/convert["WATTS"]["HP"];
83     - convert["N"]["LBS"] = 0.22482;
84     - convert["LBS"]["N"] = 1.0/convert["N"]["LBS"];
85     - convert["KTS"]["FT/SEC"] = ktstofps;
86     - convert["KG/MIN"]["LBS/MIN"] = convert["KG"]["LBS"];
87     - convert["LBS/HP*HR"]["KG/KW*HR"] = 0.6083;
88     - convert["KG/KW*HR"]["LBS/HP*HR"] = 1/convert["LBS/HP*HR"]["KG/KW*HR"];
89     - convert["KG/L"]["LBS/GAL"] = 8.3454045;
90
91     - convert["M"]["M"] = 1.00;
92     - convert["FT"]["FT"] = 1.00;
93     - convert["IN"]["IN"] = 1.00;
94     - convert["DEG"]["DEG"] = 1.00;
95     - convert["RAD"]["RAD"] = 1.00;
96     - convert["M2"]["M2"] = 1.00;
97     - convert["FT2"]["FT2"] = 1.00;
98     - convert["KG*M2"]["KG*M2"] = 1.00;
99     - convert["SLUG*FT2"]["SLUG*FT2"] = 1.00;
100     - convert["KG"]["KG"] = 1.00;
101     - convert["LBS"]["LBS"] = 1.00;
102     - convert["LBS/FT"]["LBS/FT"] = 1.00;
103     - convert["N/M"]["N/M"] = 1.00;
104     - convert["LBS/FT/SEC"]["LBS/FT/SEC"] = 1.00;
105     - convert["N/M/SEC"]["N/M/SEC"] = 1.00;
106     - convert["PSI"]["PSI"] = 1.00;
107     - convert["INHG"]["INHG"] = 1.00;
108     - convert["HP"]["HP"] = 1.00;
109     - convert["N"]["N"] = 1.00;
110     - convert["WATTS"]["WATTS"] = 1.00;
111     - convert["KTS"]["KTS"] = 1.0;
112     - convert["FT/SEC"]["FT/SEC"] = 1.0;
113     - convert["KG/MIN"]["KG/MIN"] = 1.0;
114     - convert["LBS/MIN"]["LBS/MIN"] = 1.0;
115     - convert["LBS/HP*HR"]["LBS/HP*HR"] = 1.0;
116     - convert["KG/KW*HR"]["KG/KW*HR"] = 1.0;
117     - convert["KG/L"]["KG/L"] = 1.0;
118     - convert["LBS/GAL"]["LBS/GAL"] = 1.0;
119
120     Where:
121     - N = newtons
122     - M = meters
123     - M2 = meters squared
124     - KG = kilograms
125     - LBS = pounds force
126     - FT = feet
127     - FT2 = feet squared
128     - SEC = seconds
129     - MIN = minutes
130     - SLUG = slug
131     - DEG = degrees
132     - RAD = radians
133     - WATTS = watts
134     - HP = horsepower
135     - HR = hour
136     - L = liter
137     - GAL = gallon (U.S. liquid) 
138
139     @author Jon S. Berndt
140     @version $Id: FGXMLElement.h,v 1.20 2014/01/13 10:46:02 ehofman Exp $
141 */
142
143 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
144 CLASS DECLARATION
145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
146
147 class Element {
148 public:
149   /** Constructor
150       @param nm the name of this element (if given)
151       */
152   Element(const std::string& nm);
153   /// Destructor
154   ~Element(void);
155
156   /** Determines if an element has the supplied attribute.
157       @param key specifies the attribute key to retrieve the value of.
158       @return true or false. */
159   bool HasAttribute(const std::string& key);
160
161   /** Retrieves an attribute.
162       @param key specifies the attribute key to retrieve the value of.
163       @return the key value (as a string), or the empty string if no such
164               attribute exists. */
165   std::string GetAttributeValue(const std::string& key);
166
167   /** Retrieves an attribute value as a double precision real number.
168       @param key specifies the attribute key to retrieve the value of.
169       @return the key value (as a number), or the HUGE_VAL if no such
170               attribute exists. */
171   double GetAttributeValueAsNumber(const std::string& key);
172
173   /** Retrieves the element name.
174       @return the element name, or the empty string if no name has been set.*/
175   const std::string& GetName(void) const {return name;}
176
177   /** Gets a line of data belonging to an element.
178       @param i the index of the data line to return (0 by default).
179       @return a string representing the data line requested, or the empty string
180               if none exists.*/
181   std::string GetDataLine(unsigned int i=0);
182
183   /// Returns the number of lines of data stored
184   unsigned int GetNumDataLines(void) {return (unsigned int)data_lines.size();}
185
186   /// Returns the number of child elements for this element.
187   unsigned int GetNumElements(void) {return (unsigned int)children.size();}
188
189   /// Returns the number of named child elements for this element.
190   unsigned int GetNumElements(const std::string& element_name);
191
192   /** Converts the element data to a number.
193       This function attempts to convert the first (and presumably only) line of
194       data "owned" by the element into a real number. If there is not exactly one
195       line of data owned by the element, then HUGE_VAL is returned.
196       @return the numeric value of the data owned by the element.*/
197   double GetDataAsNumber(void);
198
199   /** Returns a pointer to the element requested by index.
200       This function also resets an internal counter to the index, so that
201       subsequent calls to GetNextElement() will return the following
202       elements sequentially, until the last element is reached. At that point,
203       GetNextElement() will return NULL.
204       @param el the index of the requested element (0 by default)
205       @return a pointer to the Element, or 0 if no valid element exists. */
206   Element* GetElement(unsigned int el=0);
207
208   /** Returns a pointer to the next element in the list.
209       The function GetElement() must be called first to be sure that this
210       function will return the correct element. The call to GetElement() resets
211       the internal counter to zero. Subsequent calls to GetNextElement() return
212       a pointer to subsequent elements in the list. When the final element is
213       reached, 0 is returned.
214       @return a pointer to the next Element in the sequence, or 0 if no valid
215               Element is present. */
216   Element* GetNextElement(void);
217
218   /** Returns a pointer to the parent of an element.
219       @return a pointer to the parent Element, or 0 if this is the top level Element. */
220   Element* GetParent(void) {return parent;}
221
222   /** Returns the line number at which the element has been defined.
223       @return the line number
224    */
225   int GetLineNumber(void) const { return line_number; }
226
227   /** Returns the name of the file in which the element has been read.
228       @return the file name
229   */
230   const std::string& GetFileName(void) const { return file_name; }
231
232   /** Searches for a specified element.
233       Finds the first element that matches the supplied string, or simply the first
234       element if no search string is supplied. This function call resets the internal
235       element counter to the first element.
236       @param el the search string (empty string by default).
237       @return a pointer to the first element that matches the supplied search string. */
238   Element* FindElement(const std::string& el="");
239
240   /** Searches for the next element as specified.
241       This function would be called after FindElement() is first called (in order to
242       reset the internal counter). If no argument is supplied (or the empty string)
243       a pointer to the very next element is returned. Otherwise, the next occurence
244       of the named element is returned. If the end of the list is reached, 0 is
245       returned.
246       @param el the name of the next element to find.
247       @return the pointer to the found element, or 0 if no appropriate element us
248               found.*/
249   Element* FindNextElement(const std::string& el="");
250
251   /** Searches for the named element and returns the string data belonging to it.
252       This function allows the data belonging to a named element to be returned
253       as a string. If no element is found, the empty string is returned. If no
254       argument is supplied, the data string for the first element is returned.
255       @param el the name of the element being searched for (the empty string by
256       default)
257       @return the data value for the named element as a string, or the empty
258               string if the element cannot be found. */
259   std::string FindElementValue(const std::string& el="");
260
261   /** Searches for the named element and returns the data belonging to it as a number.
262       This function allows the data belonging to a named element to be returned
263       as a double. If no element is found, HUGE_VAL is returned. If no
264       argument is supplied, the data for the first element is returned.
265       @param el the name of the element being searched for (the empty string by
266       default)
267       @return the data value for the named element as a double, or HUGE_VAL if the
268               data is missing. */
269   double FindElementValueAsNumber(const std::string& el="");
270
271   /** Searches for the named element and converts and returns the data belonging to it.
272       This function allows the data belonging to a named element to be returned
273       as a double. If no element is found, HUGE_VAL is returned. If no
274       argument is supplied, the data for the first element is returned. Additionally,
275       this function converts the value from the units specified in the config file (via
276       the UNITS="" attribute in the element definition) to the native units used by
277       JSBSim itself, as specified by the target_units parameter. The currently
278       allowable unit conversions are seen in the source file FGXMLElement.cpp.
279       Also, see above in the main documentation for this class.
280       @param el the name of the element being searched for (the empty string by
281       default)
282       @param target_units the string representing the native units used by JSBSim
283              to which the value returned will be converted.
284       @return the unit-converted data value for the named element as a double,
285               or HUGE_VAL if the data is missing. */
286   double FindElementValueAsNumberConvertTo(const std::string& el, const std::string& target_units);
287
288   /** Searches for the named element and converts and returns the data belonging to it.
289       This function allows the data belonging to a named element to be returned
290       as a double. If no element is found, HUGE_VAL is returned. If no
291       argument is supplied, the data for the first element is returned. Additionally,
292       this function converts the value from the units specified in the supplied_units
293       parameter to the units specified in the target_units parameter. JSBSim itself,
294       as specified by the target_units parameter. The currently allowable unit
295       conversions are seen in the source file FGXMLElement.cpp. Also, see above
296       in the main documentation for this class.
297       @param el the name of the element being searched for (the empty string by
298       default)
299       @param supplied_units the string representing the units of the value as
300              supplied by the config file.
301       @param target_units the string representing the native units used by JSBSim
302              to which the value returned will be converted.
303       @return the unit-converted data value for the named element as a double,
304               or HUGE_VAL if the data is missing. */
305   double FindElementValueAsNumberConvertFromTo( const std::string& el,
306                                                 const std::string& supplied_units,
307                                                 const std::string& target_units);
308
309   /** Composes a 3-element column vector for the supplied location or orientation.
310       This function processes a LOCATION or ORIENTATION construct, returning a
311       filled-out 3-element column vector containing the X, Y, Z or ROLL, PITCH,
312       YAW elements found in the supplied element. If one of the mentioned components
313       is not found, that component is set to zero and a warning message is printed.
314       All three elements should be supplied.
315       @param target_units the string representing the native units used by JSBSim
316              to which the value returned will be converted.
317       @return a column vector object built from the LOCATION or ORIENT components. */
318   FGColumnVector3 FindElementTripletConvertTo( const std::string& target_units);
319
320   double DisperseValue(Element *e, double val, const std::string supplied_units="", const std::string target_units="");
321
322   /** This function sets the value of the parent class attribute to the supplied
323       Element pointer.
324       @param p pointer to the parent Element. */
325   void SetParent(Element* p) {parent = p;}
326
327   /** Adds a child element to the list of children stored for this element.
328   *   @param el Child element to add. */
329   void AddChildElement(Element* el) {children.push_back(el);}
330
331   /** Stores an attribute belonging to this element.
332   *   @param name The string name of the attribute.
333   *   @param value The string value of the attribute. */
334   void AddAttribute(const std::string& name, const std::string& value);
335
336   /** Stores data belonging to this element.
337   *   @param d the data to store. */
338   void AddData(std::string d);
339
340   /** Prints the element.
341   *   Prints this element and calls the Print routine for child elements.
342   *   @param d The tab level. A level corresponds to a single space. */
343   void Print(unsigned int level=0);
344
345   /** Set the line number at which the element has been read.
346    *  @param line line number.
347    */
348   void SetLineNumber(int line) { line_number = line; }
349
350   /** Set the name of the file in which the element has been read.
351    *  @param name file name
352    */
353   void SetFileName(const std::string& name) { file_name = name; }
354
355   /** Return a string that contains a description of the location where the
356    *  current XML element was read from.
357    *  @return a string describing the file name and line number where the
358    *          element was read.
359    */
360   std::string ReadFrom(void) const;
361
362 private:
363   std::string name;
364   std::map <std::string, std::string> attributes;
365   std::vector <std::string> data_lines;
366   std::vector <Element*> children;
367   Element *parent;
368   unsigned int element_index;
369   std::string file_name;
370   int line_number;
371   typedef std::map <std::string, std::map <std::string, double> > tMapConvert;
372   static tMapConvert convert;
373   static bool converterIsInitialized;
374   double GaussianRandomNumber(void);
375 };
376
377 } // namespace JSBSim
378
379 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
380
381 #endif