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