Fixed error line reporting in CSV-based files
[GPXSee.git] / src / data / cupparser.cpp
blob1abd80c60fc4d0af449341135dcac30b8c8526ad
1 #include <cmath>
2 #include <QStringList>
3 #include "common/csv.h"
4 #include "cupparser.h"
7 enum SegmentType {
8 Header, Waypoints, Tasks
9 };
11 static double latitude(const QString &str)
13 bool ok;
15 if (str.length() != 9)
16 return NAN;
17 int deg = str.left(2).toInt(&ok);
18 if (!ok || deg > 90)
19 return NAN;
20 double min = str.mid(2, 6).toDouble(&ok);
21 if (!ok || min > 60)
22 return NAN;
24 double dd = deg + min/60.0;
25 return (str.right(1) == "S") ? -dd : dd;
28 static double longitude(const QString &str)
30 bool ok;
32 if (str.length() != 10)
33 return NAN;
34 int deg = str.left(3).toInt(&ok);
35 if (!ok || deg > 180)
36 return NAN;
37 double min = str.mid(3, 6).toDouble(&ok);
38 if (!ok || min > 60)
39 return NAN;
41 double dd = deg + min/60.0;
42 return (str.right(1) == "W") ? -dd : dd;
45 static double elevation(const QString &str)
47 bool ok;
48 double ele;
50 if (str.right(2) == "ft")
51 ele = str.left(str.length() - 2).toDouble(&ok) * 0.3048;
52 else if (str.right(1) == "m")
53 ele = str.left(str.length() - 1).toDouble(&ok);
54 else
55 return NAN;
57 return ok ? ele : NAN;
61 bool CUPParser::waypoint(const QByteArrayList &entry,
62 QVector<Waypoint> &waypoints)
64 if (entry.size() < 11) {
65 _errorString = "Invalid number of fields";
66 return false;
69 double lon = longitude(entry.at(4));
70 if (std::isnan(lon)) {
71 _errorString = "Invalid longitude";
72 return false;
74 double lat = latitude(entry.at(3));
75 if (std::isnan(lat)) {
76 _errorString = "Invalid latitude";
77 return false;
80 Waypoint wp(Coordinates(lon, lat));
81 wp.setName(entry.at(0));
82 wp.setDescription(entry.at(10));
83 wp.setElevation(elevation(entry.at(5)));
84 waypoints.append(wp);
86 return true;
89 bool CUPParser::task(const QByteArrayList &entry,
90 const QVector<Waypoint> &waypoints, QList<RouteData> &routes)
92 if (entry.size() < 3) {
93 _errorString = "Invalid number of fields";
94 return false;
97 RouteData r;
98 r.setName(entry.at(0));
99 for (int i = 1; i < entry.size(); i++) {
100 if (entry.at(i) == "???")
101 continue;
103 Waypoint w;
104 for (int j = 0; j < waypoints.size(); j++) {
105 if (waypoints.at(j).name() == entry.at(i)) {
106 w = waypoints.at(j);
107 break;
110 if (w.coordinates().isNull()) {
111 _errorString = entry.at(i) + ": unknown turnpoint";
112 return false;
114 r.append(w);
117 routes.append(r);
119 return true;
122 bool CUPParser::parse(QFile *file, QList<TrackData> &tracks,
123 QList<RouteData> &routes, QList<Area> &polygons,
124 QVector<Waypoint> &waypoints)
126 Q_UNUSED(tracks);
127 Q_UNUSED(polygons);
128 CSV csv(file);
129 QByteArrayList entry;
130 SegmentType segment = Header;
132 while (!csv.atEnd()) {
133 if (!csv.readEntry(entry)) {
134 _errorString = "CSV parse error";
135 _errorLine = csv.line();
136 return false;
139 if (segment == Header) {
140 segment = Waypoints;
141 if (entry.size() >= 11 && entry.at(3) == "lat"
142 && entry.at(4) == "lon") {
143 entry.clear();
144 continue;
146 } else if (segment == Waypoints && entry.size() == 1
147 && entry.at(0) == "-----Related Tasks-----") {
148 segment = Tasks;
149 entry.clear();
150 continue;
153 if (segment == Waypoints) {
154 if (!waypoint(entry, waypoints))
155 return false;
156 } else if (segment == Tasks) {
157 if (entry.at(0) != "Options" && !entry.at(0).startsWith("ObsZone=")
158 && !task(entry, waypoints, routes))
159 return false;
162 _errorLine = csv.line() - 1;
165 return true;