]> git.mxchange.org Git - flightgear.git/commitdiff
apt.dat parser: separately handle the first two lines; fix line counting
authorFlorent Rougon <f.rougon@free.fr>
Sun, 24 Apr 2016 16:57:36 +0000 (18:57 +0200)
committerFlorent Rougon <f.rougon@free.fr>
Wed, 27 Apr 2016 08:39:21 +0000 (10:39 +0200)
- The first two lines of apt.dat have their own special syntax -> handle
  them separately. Before this commit, the test "is the first character
  an 'I' or an 'A'?" was done for *every* line of apt.dat, while it is
  only relevant for the first one.

- Fix counting of the current line number (it was most of the time
  0-based so far, which could be seen in error messages, because the
  second line of apt.dat was absorbed without going through the common
  code path where lines are normally read at the top of the while loop).
  With this commit, line numbers in apt.dat are consistently counted
  starting from 1.

src/Airports/apt_loader.cxx

index 67b1a6ee3b788144c488082c4fddd576deca7587..a7ad198ace55486fdfde008156ce9fb92763ccac 100644 (file)
@@ -50,6 +50,7 @@
 #include <ATC/CommStation.hxx>
 
 #include <iostream>
+#include <sstream>              // std::istringstream
 
 using namespace std;
 
@@ -103,6 +104,30 @@ public:
     unsigned int line_id = 0;
     unsigned int line_num = 0;
 
+    // Read the apt.dat header (two lines)
+    while ( line_num < 2 && std::getline(in, line) ) {
+      // 'line' may end with an \r character (tested on Linux, only \n was
+      // stripped: std::getline() only discards the _native_ line terminator)
+      line_num++;
+
+      if ( line_num == 1 ) {
+        std::string stripped_line = simgear::strutils::strip(line);
+        // First line indicates IBM ("I") or Macintosh ("A") line endings.
+        if ( stripped_line != "I" && stripped_line != "A" ) {
+          std::string pb = "invalid first line (neither 'I' nor 'A')";
+          SG_LOG( SG_GENERAL, SG_ALERT, apt_dat << ": " << pb);
+          throw sg_format_exception("cannot parse apt.dat file: " + pb,
+                                    apt_dat);
+        }
+      } else {     // second line of the file
+        std::istringstream s(line);
+        int apt_dat_format_version;
+        s >> apt_dat_format_version;
+        SG_LOG( SG_GENERAL, SG_INFO,
+                "apt.dat format version: " << apt_dat_format_version );
+      }
+    } // end of the apt.dat header
+
     while ( ! in.eof() ) {
       in.getline(tmp, 2048);
       line = tmp; // string copy, ack
@@ -119,21 +144,8 @@ public:
         }
 
       line_id = atoi(tmp);
-      if ( tmp[0] == 'I' || tmp[0] == 'A' ) {
-        // First line, indicates IBM ("I") or Macintosh ("A")
-        // line endings.
-
-        // move past this line and read and discard the next line
-        // which is the version and copyright information
-        in.getline(tmp, 2048);
-
-        if ( strlen(tmp) > 5 ) {
-           char *p = (char *)memchr(tmp, ' ', 5);
-           if ( p )
-              *p = 0;
-        }
-        SG_LOG( SG_GENERAL, SG_INFO, "Data file version = " << tmp );
-      } else if ( line_id == 1 /* Airport */ ||
+
+      if ( line_id == 1 /* Airport */ ||
                     line_id == 16 /* Seaplane base */ ||
                     line_id == 17 /* Heliport */ ) {
         parseAirportLine(simgear::strutils::split(line));