]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGConfigFile.cpp
Fix for X-15 crash.
[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       if (CurrentLine.find_first_not_of(" ") == string::npos) {
92         CurrentLine.erase();
93       }
94     } else if ( start_comment && !end_comment) {                       //  <!-- ...
95       CommentsOn = true;
96       comment_length = line_length - comment_starts_at;
97       CommentStringTemp = CurrentLine.substr(comment_starts_at+4, comment_length-4);
98       CommentString = CommentStringTemp + "\r\n";
99       CurrentLine.erase(comment_starts_at, comment_length);
100     } else if (!start_comment && end_comment) {                       //  ... -->
101       CommentsOn = false;
102       comment_length = comment_ends_at + 2 + 1;
103       CommentStringTemp = CurrentLine.substr(0, comment_length-4);
104       CommentString += CommentStringTemp + "\r\n";
105       CurrentLine.erase(0, comment_length);
106     } else if (start_comment && comment_ends_at < comment_starts_at) { //  --> command <!--
107       cerr << "Old comment ends and new one starts - bad JSBSim config file form." << endl;
108       CommentsOn = false;
109       comment_length = comment_ends_at + 2 + 1;
110       CommentStringTemp = CurrentLine.substr(0, comment_length-4);
111       CommentString += CommentStringTemp + "\r\n";
112       CurrentLine.erase(0, comment_length);
113     }
114   } while (CommentsOn);
115
116   CurrentIndex = 0;
117   if (CurrentLine.length() == 0) {
118     GetNextConfigLine();
119   }
120   return CurrentLine;
121 }
122
123 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
124
125 string FGConfigFile::GetValue(string val)
126 {
127   string::size_type pos, p1, p2, ptest;
128
129   if (val == "") {    // this call is to return the tag value
130     pos = CurrentLine.find("<");
131     if (pos != CurrentLine.npos) { // beginning brace found "<"
132       p1 = CurrentLine.find_first_not_of(" ",pos+1);
133       if (p1 != CurrentLine.npos) { // found first character of tag
134         p2 = CurrentLine.find_first_of(" >",p1+1);
135         if (p2 == CurrentLine.npos) p2 = p1+1;
136         return CurrentLine.substr(p1,p2-p1);
137       }
138     } else {   // beginning brace "<" not found; this is a regular data line
139       pos = CurrentLine.find_first_not_of(" ");
140       if (pos != CurrentLine.npos) {  // first character in line found
141         p2 = CurrentLine.find_first_of(" ",pos+1);
142         if (p2 != CurrentLine.npos) {
143           return CurrentLine.substr(pos,p2-pos);
144         } else {
145           return CurrentLine.substr(pos,CurrentLine.length()-pos);
146         }
147       }
148     }
149   } else { // return a value for a specific tag
150     pos = CurrentLine.find(val);
151     if (pos != CurrentLine.npos) {
152       pos = CurrentLine.find("=",pos);
153       if (pos != CurrentLine.npos) {
154         ptest = CurrentLine.find_first_not_of(" ",pos+1);
155         if (ptest != CurrentLine.npos) {
156           p1 = ptest + 1;
157           if (CurrentLine[ptest] == '"') { // quoted
158             p2 = CurrentLine.find_first_of("\"",p1);
159           } else { // not quoted
160             p2 = CurrentLine.find_first_of(" ",p1);
161           }
162           if (p2 != CurrentLine.npos) {
163             return CurrentLine.substr(p1,p2-p1);
164           }
165         }
166       } else {   // "=" not found
167         pos = CurrentLine.find(val);
168         pos = CurrentLine.find_first_of(" ",pos+1);
169         ptest = CurrentLine.find_first_not_of(" ",pos+1);
170         if (ptest != CurrentLine.npos) {
171           if (CurrentLine[ptest] == '"') { // quoted
172             p1 = ptest + 1;
173             p2 = CurrentLine.find_first_of("\"",p1);
174           } else { // not quoted
175             p1 = ptest;
176             p2 = CurrentLine.find_first_of(" ",p1);
177           }
178           if (p2 != CurrentLine.npos) {
179             return CurrentLine.substr(p1,p2-p1);
180           } else {
181             p2 = CurrentLine.length();
182             return CurrentLine.substr(p1,p2-p1);
183           }
184         }
185       }
186     }
187   }
188
189   return string("");
190 }
191
192 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
193
194 string FGConfigFile::GetValue(void)
195 {
196   return GetValue("");
197 }
198
199 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
200
201 string FGConfigFile::GetLine(void)
202 {
203   string scratch = "";
204   int test;
205
206   while ((test = cfgfile.get()) != EOF) {
207     if (test >= 0x20 || test == 0x09) {
208       if (test == 0x09) {
209         scratch += (char)0x20;
210       } else {
211         scratch += (char)test;
212       }
213     } else {
214       if ((test = cfgfile.get()) != EOF) { // get *next* character
215 #if defined ( sgi ) && !defined( __GNUC__ )
216         if (test >= 0x20 || test == 0x09) cfgfile.putback(test);
217 #else
218         if (test >= 0x20 || test == 0x09) cfgfile.unget();
219 #endif
220         break;
221       }
222     }
223   }
224   if (cfgfile.eof() && scratch.empty()) return string("EOF");
225   return scratch;
226 }
227
228 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
229
230 FGConfigFile& FGConfigFile::operator>>(double& val)
231 {
232   string::size_type pos, end;
233
234   pos = CurrentLine.find_first_not_of(", ",CurrentIndex);
235   if (pos == CurrentLine.npos) pos = CurrentLine.length();
236   end = CurrentLine.find_first_of(", ",pos+1);
237   if (end == CurrentLine.npos) end = CurrentLine.length();
238   string str = CurrentLine.substr(pos, end - pos);
239   val = strtod(str.c_str(),NULL);
240   CurrentIndex = end+1;
241   if (end == pos) {
242     GetNextConfigLine();
243     *this >> val;
244   } else {
245     if (CurrentIndex >= CurrentLine.length()) GetNextConfigLine();
246   }
247   return *this;
248 }
249
250 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
251
252 FGConfigFile& FGConfigFile::operator>>(int& val)
253 {
254   string::size_type pos, end;
255
256   pos = CurrentLine.find_first_not_of(", ",CurrentIndex);
257   if (pos == CurrentLine.npos) pos = CurrentLine.length();
258   end = CurrentLine.find_first_of(", ",pos+1);
259   if (end == CurrentLine.npos) end = CurrentLine.length();
260   string str = CurrentLine.substr(pos, end - pos);
261   val = atoi(str.c_str());
262   CurrentIndex = end+1;
263   if (end == pos) {
264     GetNextConfigLine();
265     *this >> val;
266   } else {
267     if (CurrentIndex >= CurrentLine.length()) GetNextConfigLine();
268   }
269   return *this;
270 }
271
272 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
273
274 FGConfigFile& FGConfigFile::operator>>(string& str)
275 {
276   string::size_type pos, end;
277
278   pos = CurrentLine.find_first_not_of(", ",CurrentIndex);
279   if (pos == CurrentLine.npos) pos = CurrentLine.length();
280   end = CurrentLine.find_first_of(", ",pos+1);
281   if (end == CurrentLine.npos) end = CurrentLine.length();
282   str = CurrentLine.substr(pos, end - pos);
283   CurrentIndex = end+1;
284   if (end == pos) {
285     GetNextConfigLine();
286     *this >> str;
287   } else {
288     if (CurrentIndex >= CurrentLine.length()) GetNextConfigLine();
289   }
290   return *this;
291 }
292
293 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
294
295 void FGConfigFile::ResetLineIndexToZero(void)
296 {
297   CurrentIndex = 0;
298 }
299
300 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
301 //    The bitmasked value choices are as follows:
302 //    unset: In this case (the default) JSBSim would only print
303 //       out the normally expected messages, essentially echoing
304 //       the config files as they are read. If the environment
305 //       variable is not set, debug_lvl is set to 1 internally
306 //    0: This requests JSBSim not to output any messages
307 //       whatsoever.
308 //    1: This value explicity requests the normal JSBSim
309 //       startup messages
310 //    2: This value asks for a message to be printed out when
311 //       a class is instantiated
312 //    4: When this value is set, a message is displayed when a
313 //       FGModel object executes its Run() method
314 //    8: When this value is set, various runtime state variables
315 //       are printed out periodically
316 //    16: When set various parameters are sanity checked and
317 //       a message is printed out when they go out of bounds
318
319 void FGConfigFile::Debug(int from)
320 {
321   if (debug_lvl <= 0) return;
322
323   if (debug_lvl & 1) { // Standard console startup message output
324   }
325   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
326     if (from == 0) cout << "Instantiated: FGConfigFile" << endl;
327     if (from == 1) cout << "Destroyed:    FGConfigFile" << endl;
328   }
329   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
330   }
331   if (debug_lvl & 8 ) { // Runtime state variables
332   }
333   if (debug_lvl & 16) { // Sanity checking
334   }
335   if (debug_lvl & 64) {
336     if (from == 0) { // Constructor
337       cout << IdSrc << endl;
338       cout << IdHdr << endl;
339     }
340   }
341 }
342