]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGConfigFile.cpp
Updated to latest JSBSim, including preliminary support for
[flightgear.git] / src / FDM / JSBSim / FGConfigFile.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Header:       FGConfigFile.h
4  Author:       Jon Berndt
5  Date started: 03/29/00
6  Purpose:      Config file read-in class
7  Called by:    FGAircraft
8
9 FUNCTIONAL DESCRIPTION
10 --------------------------------------------------------------------------------
11
12 HISTORY
13 --------------------------------------------------------------------------------
14 03/16/2000 JSB  Created
15
16 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
17 INCLUDES
18 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
19
20 #include "FGConfigFile.h"
21 #include <stdlib.h>
22 #include <math.h>
23
24 static const char *IdSrc = "$Id$";
25 static const char *IdHdr = ID_CONFIGFILE;
26
27 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
28 CLASS IMPLEMENTATION
29 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
30
31 FGConfigFile::FGConfigFile(string cfgFileName)
32 {
33 #if defined ( sgi ) && !defined( __GNUC__ )
34   cfgfile.open(cfgFileName.c_str(), ios::in );
35 #else
36   cfgfile.open(cfgFileName.c_str(), ios::in | ios::binary );
37 #endif
38   CommentsOn = false;
39   CurrentIndex = 0;
40   Opened = true;
41 #if defined ( sgi ) && !defined( __GNUC__ )
42    if (!cfgfile.fail() && !cfgfile.eof())  GetNextConfigLine();
43 #else
44   if (cfgfile.is_open()) GetNextConfigLine();
45 #endif
46   else Opened = false;
47
48   Debug(0);
49 }
50
51 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
52
53 FGConfigFile::~FGConfigFile()
54 {
55   cfgfile.close();
56   Debug(1);
57 }
58
59 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
60
61 string FGConfigFile::GetNextConfigLine(void)
62 {
63   int comment_starts_at;
64   int comment_ends_at;
65   int comment_length;
66   int line_length;
67   bool start_comment, end_comment;
68   string CommentStringTemp;
69
70   do {
71     CurrentLine = GetLine();
72     line_length = CurrentLine.length();
73     comment_starts_at = CurrentLine.find("<!--");
74     
75     if (comment_starts_at >= 0) start_comment = true;
76     else start_comment = false;
77     
78     comment_ends_at = CurrentLine.find("-->");
79     
80     if (comment_ends_at >= 0) end_comment = true;
81     else end_comment = false;
82
83     if (!start_comment && !end_comment) {                              //  command comment
84       if (CommentsOn) CommentStringTemp = CurrentLine;
85       CommentString += CommentStringTemp + "\r\n";
86     } else if (start_comment && comment_ends_at > comment_starts_at) { //  <!-- ... -->
87       CommentsOn = false;
88       comment_length = comment_ends_at + 2 - comment_starts_at + 1;
89       LineComment = CurrentLine.substr(comment_starts_at+4, comment_length-4-3);
90       CurrentLine.erase(comment_starts_at, comment_length);
91     } else if ( start_comment && !end_comment) {                       //  <!-- ...
92       CommentsOn = true;
93       comment_length = line_length - comment_starts_at;
94       CommentStringTemp = CurrentLine.substr(comment_starts_at+4, comment_length-4);
95       CommentString = CommentStringTemp + "\r\n";
96       CurrentLine.erase(comment_starts_at, comment_length);
97     } else if (!start_comment && end_comment) {                       //  ... -->
98       CommentsOn = false;
99       comment_length = comment_ends_at + 2 + 1;
100       CommentStringTemp = CurrentLine.substr(0, comment_length-4);
101       CommentString += CommentStringTemp + "\r\n";
102       CurrentLine.erase(0, comment_length);
103     } else if (start_comment && comment_ends_at < comment_starts_at) { //  --> command <!--
104       cerr << "Old comment ends and new one starts - bad JSBSim config file form." << endl;
105       CommentsOn = false;
106       comment_length = comment_ends_at + 2 + 1;
107       CommentStringTemp = CurrentLine.substr(0, comment_length-4);
108       CommentString += CommentStringTemp + "\r\n";
109       CurrentLine.erase(0, comment_length);
110     }
111     
112   } while (CommentsOn);
113
114   if (CurrentLine.length() == 0) GetNextConfigLine();
115   CurrentIndex = 0;
116   return CurrentLine;
117 }
118
119 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
120
121 string FGConfigFile::GetValue(string val)
122 {
123   unsigned int pos, p1, p2, ptest;
124
125   if (val == "") {    // this call is to return the tag value
126     pos = CurrentLine.find("<");
127     if (pos != CurrentLine.npos) { // beginning brace found "<"
128       p1 = CurrentLine.find_first_not_of(" ",pos+1);
129       if (p1 != CurrentLine.npos) { // found first character of tag
130         p2 = CurrentLine.find_first_of(" >",p1+1);
131         if (p2 == CurrentLine.npos) p2 = p1+1;
132         return CurrentLine.substr(p1,p2-p1);
133       }
134     } else {   // beginning brace "<" not found; this is a regular data line
135       pos = CurrentLine.find_first_not_of(" ");
136       if (pos != CurrentLine.npos) {  // first character in line found
137         p2 = CurrentLine.find_first_of(" ",pos+1);
138         if (p2 != CurrentLine.npos) {
139           return CurrentLine.substr(pos,p2-pos);
140         } else {
141           return CurrentLine.substr(pos,CurrentLine.length()-pos);
142         }
143       }
144     }
145   } else { // return a value for a specific tag
146     pos = CurrentLine.find(val);
147     if (pos != CurrentLine.npos) {
148       pos = CurrentLine.find("=",pos);
149       if (pos != CurrentLine.npos) {
150         ptest = CurrentLine.find_first_not_of(" ",pos+1);
151         if (ptest != CurrentLine.npos) {
152           p1 = ptest + 1;
153           if (CurrentLine[ptest] == '"') { // quoted
154             p2 = CurrentLine.find_first_of("\"",p1);
155           } else { // not quoted
156             p2 = CurrentLine.find_first_of(" ",p1);
157           }
158           if (p2 != CurrentLine.npos) {
159             return CurrentLine.substr(p1,p2-p1);
160           }
161         }
162       } else {   // "=" not found
163         pos = CurrentLine.find(val);
164         pos = CurrentLine.find_first_of(" ",pos+1);
165         ptest = CurrentLine.find_first_not_of(" ",pos+1);
166         if (ptest != CurrentLine.npos) {
167           if (CurrentLine[ptest] == '"') { // quoted
168             p1 = ptest + 1;
169             p2 = CurrentLine.find_first_of("\"",p1);
170           } else { // not quoted
171             p1 = ptest;
172             p2 = CurrentLine.find_first_of(" ",p1);
173           }
174           if (p2 != CurrentLine.npos) {
175             return CurrentLine.substr(p1,p2-p1);
176           } else {
177             p2 = CurrentLine.length();
178             return CurrentLine.substr(p1,p2-p1);
179           }
180         }
181       }
182     }
183   }
184
185   return string("");
186 }
187
188 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
189
190 string FGConfigFile::GetValue(void)
191 {
192   return GetValue("");
193 }
194
195 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
196
197 string FGConfigFile::GetLine(void)
198 {
199   string scratch = "";
200   int test;
201
202   while ((test = cfgfile.get()) != EOF) {
203     if (test >= 0x20 || test == 0x09) {
204       if (test == 0x09) {
205         scratch += (char)0x20;
206       } else {
207         scratch += (char)test;
208       }
209     } else {
210       if ((test = cfgfile.get()) != EOF) { // get *next* character
211 #if defined ( sgi ) && !defined( __GNUC__ )
212         if (test >= 0x20 || test == 0x09) cfgfile.putback(test);
213 #else
214         if (test >= 0x20 || test == 0x09) cfgfile.unget();
215 #endif
216         break;
217       }
218     }
219   }
220   if (cfgfile.eof() && scratch.empty()) return string("EOF");
221   return scratch;
222 }
223
224 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
225
226 FGConfigFile& FGConfigFile::operator>>(double& val)
227 {
228   unsigned int pos, end;
229
230   pos = CurrentLine.find_first_not_of(", ",CurrentIndex);
231   if (pos == CurrentLine.npos) pos = CurrentLine.length();
232   end = CurrentLine.find_first_of(", ",pos+1);
233   if (end == CurrentLine.npos) end = CurrentLine.length();
234   string str = CurrentLine.substr(pos, end - pos);
235   val = strtod(str.c_str(),NULL);
236   CurrentIndex = end+1;
237   if (end == pos) {
238     GetNextConfigLine();
239     *this >> val;
240   } else {
241     if (CurrentIndex >= CurrentLine.length()) GetNextConfigLine();
242   }
243   return *this;
244 }
245
246 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
247
248 FGConfigFile& FGConfigFile::operator>>(int& val)
249 {
250   unsigned int pos, end;
251
252   pos = CurrentLine.find_first_not_of(", ",CurrentIndex);
253   if (pos == CurrentLine.npos) pos = CurrentLine.length();
254   end = CurrentLine.find_first_of(", ",pos+1);
255   if (end == CurrentLine.npos) end = CurrentLine.length();
256   string str = CurrentLine.substr(pos, end - pos);
257   val = atoi(str.c_str());
258   CurrentIndex = end+1;
259   if (end == pos) {
260     GetNextConfigLine();
261     *this >> val;
262   } else {
263     if (CurrentIndex >= CurrentLine.length()) GetNextConfigLine();
264   }
265   return *this;
266 }
267
268 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
269
270 FGConfigFile& FGConfigFile::operator>>(eParam& val)
271 {
272   unsigned int pos, end;
273
274   pos = CurrentLine.find_first_not_of(", ",CurrentIndex);
275   if (pos == CurrentLine.npos) pos = CurrentLine.length();
276   end = CurrentLine.find_first_of(", ",pos+1);
277   if (end == CurrentLine.npos) end = CurrentLine.length();
278   string str = CurrentLine.substr(pos, end - pos);
279   val = (eParam)atoi(str.c_str());
280   CurrentIndex = end+1;
281   if (end == pos) {
282     GetNextConfigLine();
283     *this >> val;
284   } else {
285     if (CurrentIndex >= CurrentLine.length()) GetNextConfigLine();
286   }
287   return *this;
288 }
289
290 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
291
292 FGConfigFile& FGConfigFile::operator>>(string& str)
293 {
294   unsigned int pos, end;
295
296   pos = CurrentLine.find_first_not_of(", ",CurrentIndex);
297   if (pos == CurrentLine.npos) pos = CurrentLine.length();
298   end = CurrentLine.find_first_of(", ",pos+1);
299   if (end == CurrentLine.npos) end = CurrentLine.length();
300   str = CurrentLine.substr(pos, end - pos);
301   CurrentIndex = end+1;
302   if (end == pos) {
303     GetNextConfigLine();
304     *this >> str;
305   } else {
306     if (CurrentIndex >= CurrentLine.length()) GetNextConfigLine();
307   }
308   return *this;
309 }
310
311 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
312
313 void FGConfigFile::ResetLineIndexToZero(void)
314 {
315   CurrentIndex = 0;
316 }
317
318 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
319 //    The bitmasked value choices are as follows:
320 //    unset: In this case (the default) JSBSim would only print
321 //       out the normally expected messages, essentially echoing
322 //       the config files as they are read. If the environment
323 //       variable is not set, debug_lvl is set to 1 internally
324 //    0: This requests JSBSim not to output any messages
325 //       whatsoever.
326 //    1: This value explicity requests the normal JSBSim
327 //       startup messages
328 //    2: This value asks for a message to be printed out when
329 //       a class is instantiated
330 //    4: When this value is set, a message is displayed when a
331 //       FGModel object executes its Run() method
332 //    8: When this value is set, various runtime state variables
333 //       are printed out periodically
334 //    16: When set various parameters are sanity checked and
335 //       a message is printed out when they go out of bounds
336
337 void FGConfigFile::Debug(int from)
338 {
339   if (debug_lvl <= 0) return;
340
341   if (debug_lvl & 1) { // Standard console startup message output
342   }
343   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
344     if (from == 0) cout << "Instantiated: FGConfigFile" << endl;
345     if (from == 1) cout << "Destroyed:    FGConfigFile" << endl;
346   }
347   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
348   }
349   if (debug_lvl & 8 ) { // Runtime state variables
350   }
351   if (debug_lvl & 16) { // Sanity checking
352   }
353   if (debug_lvl & 64) {
354     if (from == 0) { // Constructor
355       cout << IdSrc << endl;
356       cout << IdHdr << endl;
357     }
358   }
359 }
360