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