From d6f0bc6fb5132d4645682e8577a543fca47efbf6 Mon Sep 17 00:00:00 2001 From: Florent Rougon Date: Sun, 24 Apr 2016 18:57:36 +0200 Subject: [PATCH] apt.dat parser: separately handle the first two lines; fix line counting - 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 | 42 ++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/src/Airports/apt_loader.cxx b/src/Airports/apt_loader.cxx index 67b1a6ee3..a7ad198ac 100644 --- a/src/Airports/apt_loader.cxx +++ b/src/Airports/apt_loader.cxx @@ -50,6 +50,7 @@ #include #include +#include // 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)); -- 2.39.5