1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 Purpose: Config file read-in class
10 --------------------------------------------------------------------------------
13 --------------------------------------------------------------------------------
14 03/16/2000 JSB Created
16 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
18 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
20 #include "FGConfigFile.h"
24 static const char *IdSrc = "$Id$";
25 static const char *IdHdr = ID_CONFIGFILE;
27 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
29 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
31 FGConfigFile::FGConfigFile(string cfgFileName)
33 #if defined ( sgi ) && !defined( __GNUC__ )
34 cfgfile.open(cfgFileName.c_str(), ios::in );
36 cfgfile.open(cfgFileName.c_str(), ios::in | ios::binary );
41 #if defined ( sgi ) && !defined( __GNUC__ )
42 if (!cfgfile.fail() && !cfgfile.eof()) GetNextConfigLine();
44 if (cfgfile.is_open()) GetNextConfigLine();
51 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
53 FGConfigFile::~FGConfigFile()
59 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
61 string FGConfigFile::GetNextConfigLine(void)
63 int comment_starts_at;
67 bool start_comment, end_comment;
68 string CommentStringTemp;
71 CurrentLine = GetLine();
72 line_length = CurrentLine.length();
73 comment_starts_at = CurrentLine.find("<!--");
75 if (comment_starts_at >= 0) start_comment = true;
76 else start_comment = false;
78 comment_ends_at = CurrentLine.find("-->");
80 if (comment_ends_at >= 0) end_comment = true;
81 else end_comment = false;
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) { // <!-- ... -->
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) {
94 } else if ( start_comment && !end_comment) { // <!-- ...
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) { // ... -->
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;
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);
114 } while (CommentsOn);
117 if (CurrentLine.length() == 0) {
123 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
125 string FGConfigFile::GetValue(string val)
127 string::size_type pos, p1, p2, ptest;
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);
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);
145 return CurrentLine.substr(pos,CurrentLine.length()-pos);
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) {
157 if (CurrentLine[ptest] == '"') { // quoted
158 p2 = CurrentLine.find_first_of("\"",p1);
159 } else { // not quoted
160 p2 = CurrentLine.find_first_of(" ",p1);
162 if (p2 != CurrentLine.npos) {
163 return CurrentLine.substr(p1,p2-p1);
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
173 p2 = CurrentLine.find_first_of("\"",p1);
174 } else { // not quoted
176 p2 = CurrentLine.find_first_of(" ",p1);
178 if (p2 != CurrentLine.npos) {
179 return CurrentLine.substr(p1,p2-p1);
181 p2 = CurrentLine.length();
182 return CurrentLine.substr(p1,p2-p1);
192 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
194 string FGConfigFile::GetValue(void)
199 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
201 string FGConfigFile::GetLine(void)
206 while ((test = cfgfile.get()) != EOF) {
207 if (test >= 0x20 || test == 0x09) {
209 scratch += (char)0x20;
211 scratch += (char)test;
214 if ((test = cfgfile.get()) != EOF) { // get *next* character
215 #if defined ( sgi ) && !defined( __GNUC__ )
216 if (test >= 0x20 || test == 0x09) cfgfile.putback(test);
218 if (test >= 0x20 || test == 0x09) cfgfile.unget();
224 if (cfgfile.eof() && scratch.empty()) return string("EOF");
228 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
230 FGConfigFile& FGConfigFile::operator>>(double& val)
232 string::size_type pos, end;
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;
245 if (CurrentIndex >= CurrentLine.length()) GetNextConfigLine();
250 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252 FGConfigFile& FGConfigFile::operator>>(int& val)
254 string::size_type pos, end;
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;
267 if (CurrentIndex >= CurrentLine.length()) GetNextConfigLine();
272 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274 FGConfigFile& FGConfigFile::operator>>(eParam& val)
276 string::size_type pos, end;
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 string str = CurrentLine.substr(pos, end - pos);
283 val = (eParam)atoi(str.c_str());
284 CurrentIndex = end+1;
289 if (CurrentIndex >= CurrentLine.length()) GetNextConfigLine();
294 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296 FGConfigFile& FGConfigFile::operator>>(string& str)
298 string::size_type pos, end;
300 pos = CurrentLine.find_first_not_of(", ",CurrentIndex);
301 if (pos == CurrentLine.npos) pos = CurrentLine.length();
302 end = CurrentLine.find_first_of(", ",pos+1);
303 if (end == CurrentLine.npos) end = CurrentLine.length();
304 str = CurrentLine.substr(pos, end - pos);
305 CurrentIndex = end+1;
310 if (CurrentIndex >= CurrentLine.length()) GetNextConfigLine();
315 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
317 void FGConfigFile::ResetLineIndexToZero(void)
322 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
323 // The bitmasked value choices are as follows:
324 // unset: In this case (the default) JSBSim would only print
325 // out the normally expected messages, essentially echoing
326 // the config files as they are read. If the environment
327 // variable is not set, debug_lvl is set to 1 internally
328 // 0: This requests JSBSim not to output any messages
330 // 1: This value explicity requests the normal JSBSim
332 // 2: This value asks for a message to be printed out when
333 // a class is instantiated
334 // 4: When this value is set, a message is displayed when a
335 // FGModel object executes its Run() method
336 // 8: When this value is set, various runtime state variables
337 // are printed out periodically
338 // 16: When set various parameters are sanity checked and
339 // a message is printed out when they go out of bounds
341 void FGConfigFile::Debug(int from)
343 if (debug_lvl <= 0) return;
345 if (debug_lvl & 1) { // Standard console startup message output
347 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
348 if (from == 0) cout << "Instantiated: FGConfigFile" << endl;
349 if (from == 1) cout << "Destroyed: FGConfigFile" << endl;
351 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
353 if (debug_lvl & 8 ) { // Runtime state variables
355 if (debug_lvl & 16) { // Sanity checking
357 if (debug_lvl & 64) {
358 if (from == 0) { // Constructor
359 cout << IdSrc << endl;
360 cout << IdHdr << endl;