1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 Purpose: Config file read-in class
10 --------------------------------------------------------------------------------
13 --------------------------------------------------------------------------------
14 03/16/2000 JSB Created
16 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
18 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
24 #include "FGConfigFile.h"
30 static const char *IdSrc = "$Id$";
31 static const char *IdHdr = ID_CONFIGFILE;
33 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
37 FGConfigFile::FGConfigFile(string cfgFileName)
39 #if defined ( sgi ) && !defined( __GNUC__ ) && (_COMPILER_VERSION < 740)
40 cfgfile.open(cfgFileName.c_str(), ios::in );
42 cfgfile.open(cfgFileName.c_str(), ios::in | ios::binary );
47 #if defined ( sgi ) && !defined( __GNUC__ ) && (_COMPILER_VERSION < 740)
48 if (!cfgfile.fail() && !cfgfile.eof()) GetNextConfigLine();
50 if (cfgfile.is_open()) GetNextConfigLine();
57 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
59 FGConfigFile::~FGConfigFile()
65 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
67 string FGConfigFile::GetNextConfigLine(void)
69 int comment_starts_at;
73 bool start_comment, end_comment;
74 string CommentStringTemp;
77 CurrentLine = GetLine();
78 line_length = CurrentLine.length();
79 comment_starts_at = CurrentLine.find("<!--");
81 if (comment_starts_at >= 0) start_comment = true;
82 else start_comment = false;
84 comment_ends_at = CurrentLine.find("-->");
86 if (comment_ends_at >= 0) end_comment = true;
87 else end_comment = false;
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) { // <!-- ... -->
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) {
100 } else if ( start_comment && !end_comment) { // <!-- ...
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) { // ... -->
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;
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);
120 } while (CommentsOn);
123 if (CurrentLine.length() == 0) {
129 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
131 string FGConfigFile::GetValue(string val)
133 string::size_type pos, p1, p2, ptest;
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);
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);
151 return CurrentLine.substr(pos,CurrentLine.length()-pos);
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) {
163 if (CurrentLine[ptest] == '"') { // quoted
164 p2 = CurrentLine.find_first_of("\"",p1);
165 } else { // not quoted
166 p2 = CurrentLine.find_first_of(" ",p1);
168 if (p2 != CurrentLine.npos) {
169 return CurrentLine.substr(p1,p2-p1);
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
179 p2 = CurrentLine.find_first_of("\"",p1);
180 } else { // not quoted
182 p2 = CurrentLine.find_first_of(" ",p1);
184 if (p2 != CurrentLine.npos) {
185 return CurrentLine.substr(p1,p2-p1);
187 p2 = CurrentLine.length();
188 return CurrentLine.substr(p1,p2-p1);
198 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
200 string FGConfigFile::GetValue(void)
205 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
207 string FGConfigFile::GetLine(void)
212 while ((test = cfgfile.get()) != EOF) {
213 if (test >= 0x20 || test == 0x09) {
215 scratch += (char)0x20;
217 scratch += (char)test;
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);
224 if (test >= 0x20 || test == 0x09) cfgfile.unget();
231 int index = scratch.find_last_not_of(" ");
232 if (index != string::npos && index < (scratch.size()-1)) {
233 scratch = scratch.substr(0,index+1);
236 if (cfgfile.eof() && scratch.empty()) return string("EOF");
240 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242 FGConfigFile& FGConfigFile::operator>>(double& val)
244 string::size_type pos, end;
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;
257 if (CurrentIndex >= CurrentLine.length()) GetNextConfigLine();
262 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
264 FGConfigFile& FGConfigFile::operator>>(int& val)
266 string::size_type pos, end;
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;
279 if (CurrentIndex >= CurrentLine.length()) GetNextConfigLine();
284 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
286 FGConfigFile& FGConfigFile::operator>>(string& str)
288 string::size_type pos, end;
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;
300 if (CurrentIndex >= CurrentLine.length()) GetNextConfigLine();
305 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307 void FGConfigFile::ResetLineIndexToZero(void)
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
320 // 1: This value explicity requests the normal JSBSim
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
331 void FGConfigFile::Debug(int from)
333 if (debug_lvl <= 0) return;
335 if (debug_lvl & 1) { // Standard console startup message output
337 if (debug_lvl & 2 ) { // Instantiation/Destruction notification
338 if (from == 0) cout << "Instantiated: FGConfigFile" << endl;
339 if (from == 1) cout << "Destroyed: FGConfigFile" << endl;
341 if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
343 if (debug_lvl & 8 ) { // Runtime state variables
345 if (debug_lvl & 16) { // Sanity checking
347 if (debug_lvl & 64) {
348 if (from == 0) { // Constructor
349 cout << IdSrc << endl;
350 cout << IdHdr << endl;