diff --git a/gpxsee.pro b/gpxsee.pro index c310f181..f06be256 100644 --- a/gpxsee.pro +++ b/gpxsee.pro @@ -45,6 +45,7 @@ HEADERS += src/common/config.h \ src/common/downloader.h \ src/common/polygon.h \ src/common/color.h \ + src/common/csv.h \ src/GUI/authenticationwidget.h \ src/GUI/axislabelitem.h \ src/GUI/dirselectwidget.h \ @@ -253,7 +254,6 @@ HEADERS += src/common/config.h \ src/data/demloader.h \ src/data/area.h \ src/data/exifparser.h \ - src/data/csv.h \ src/data/cupparser.h \ src/data/gpiparser.h \ src/data/address.h \ @@ -274,6 +274,7 @@ SOURCES += src/main.cpp \ src/common/programpaths.cpp \ src/common/tifffile.cpp \ src/common/downloader.cpp \ + src/common/csv.cpp \ src/GUI/authenticationwidget.cpp \ src/GUI/axislabelitem.cpp \ src/GUI/dirselectwidget.cpp \ @@ -448,7 +449,6 @@ SOURCES += src/main.cpp \ src/data/dem.cpp \ src/data/demloader.cpp \ src/data/exifparser.cpp \ - src/data/csv.cpp \ src/data/cupparser.cpp \ src/data/gpiparser.cpp \ src/data/smlparser.cpp \ diff --git a/src/data/csv.cpp b/src/common/csv.cpp similarity index 93% rename from src/data/csv.cpp rename to src/common/csv.cpp index ad0842d0..f2e1cb32 100644 --- a/src/data/csv.cpp +++ b/src/common/csv.cpp @@ -1,4 +1,4 @@ -#include +#include #include "csv.h" /* @@ -7,12 +7,14 @@ RFC 4180 parser with the following enchancements: - allows LF line ends in addition to CRLF line ends */ -bool CSV::readEntry(QStringList &list) +bool CSV::readEntry(QByteArrayList &list) { int state = 0; char c; QByteArray field; + list.clear(); + while (_device->getChar(&c)) { switch (state) { case 0: diff --git a/src/data/csv.h b/src/common/csv.h similarity index 89% rename from src/data/csv.h rename to src/common/csv.h index fa947b2a..a80e715f 100644 --- a/src/data/csv.h +++ b/src/common/csv.h @@ -9,7 +9,7 @@ public: CSV(QIODevice *device, char delimiter = ',') : _device(device), _delimiter(delimiter), _line(1) {} - bool readEntry(QStringList &list); + bool readEntry(QByteArrayList &list); bool atEnd() const {return _device->atEnd();} int line() const {return _line;} diff --git a/src/data/csvparser.cpp b/src/data/csvparser.cpp index cefaeed6..c26fbb7f 100644 --- a/src/data/csvparser.cpp +++ b/src/data/csvparser.cpp @@ -1,5 +1,5 @@ -#include -#include "csv.h" +#include +#include "common/csv.h" #include "csvparser.h" bool CSVParser::parse(QFile *file, QList &tracks, @@ -10,10 +10,9 @@ bool CSVParser::parse(QFile *file, QList &tracks, Q_UNUSED(routes); Q_UNUSED(polygons); CSV csv(file); - QStringList entry; + QByteArrayList entry; bool ok; - while (!csv.atEnd()) { if (!csv.readEntry(entry) || entry.size() < 3) { _errorString = "Parse error"; @@ -21,26 +20,24 @@ bool CSVParser::parse(QFile *file, QList &tracks, return false; } - double lon = entry.at(0).trimmed().toDouble(&ok); + double lon = entry.at(0).toDouble(&ok); if (!ok || (lon < -180.0 || lon > 180.0)) { _errorString = "Invalid longitude"; _errorLine = csv.line(); return false; } - double lat = entry.at(1).trimmed().toDouble(&ok); + double lat = entry.at(1).toDouble(&ok); if (!ok || (lat < -90.0 || lat > 90.0)) { _errorString = "Invalid latitude"; _errorLine = csv.line(); return false; } Waypoint wp(Coordinates(lon, lat)); - wp.setName(entry.at(2).trimmed()); + wp.setName(entry.at(2)); if (entry.size() > 3) - wp.setDescription(entry.at(3).trimmed()); + wp.setDescription(entry.at(3)); waypoints.append(wp); - - entry.clear(); } return true; diff --git a/src/data/cupparser.cpp b/src/data/cupparser.cpp index c6f5979f..87867ff5 100644 --- a/src/data/cupparser.cpp +++ b/src/data/cupparser.cpp @@ -1,6 +1,6 @@ #include #include -#include "csv.h" +#include "common/csv.h" #include "cupparser.h" @@ -58,7 +58,8 @@ static double elevation(const QString &str) } -bool CUPParser::waypoint(const QStringList &entry, QVector &waypoints) +bool CUPParser::waypoint(const QByteArrayList &entry, + QVector &waypoints) { if (entry.size() < 11) { _errorString = "Invalid number of fields"; @@ -85,7 +86,7 @@ bool CUPParser::waypoint(const QStringList &entry, QVector &waypoints) return true; } -bool CUPParser::task(const QStringList &entry, +bool CUPParser::task(const QByteArrayList &entry, const QVector &waypoints, QList &routes) { if (entry.size() < 3) { @@ -125,10 +126,9 @@ bool CUPParser::parse(QFile *file, QList &tracks, Q_UNUSED(tracks); Q_UNUSED(polygons); CSV csv(file); - QStringList entry; + QByteArrayList entry; SegmentType segment = Header; - while (!csv.atEnd()) { if (!csv.readEntry(entry)) { _errorString = "CSV parse error"; @@ -159,7 +159,6 @@ bool CUPParser::parse(QFile *file, QList &tracks, return false; } - entry.clear(); _errorLine = csv.line(); } diff --git a/src/data/cupparser.h b/src/data/cupparser.h index 0fe6f411..24649c3c 100644 --- a/src/data/cupparser.h +++ b/src/data/cupparser.h @@ -14,8 +14,8 @@ public: int errorLine() const {return _errorLine;} private: - bool waypoint(const QStringList &entry, QVector &waypoints); - bool task(const QStringList &entry, const QVector &waypoints, + bool waypoint(const QByteArrayList &entry, QVector &waypoints); + bool task(const QByteArrayList &entry, const QVector &waypoints, QList &routes); QString _errorString; diff --git a/src/map/conversion.cpp b/src/map/conversion.cpp index 0a520475..054f5db6 100644 --- a/src/map/conversion.cpp +++ b/src/map/conversion.cpp @@ -1,4 +1,5 @@ #include +#include "common/csv.h" #include "conversion.h" static bool parameter(int key, double val, int units, Projection::Setup &setup) @@ -64,19 +65,18 @@ static bool parameter(int key, double val, int units, Projection::Setup &setup) } } -static int projectionSetup(const QList &list, - Projection::Setup &setup) +static int projectionSetup(const QByteArrayList &list, Projection::Setup &setup) { bool r1, r2, r3; for (int i = 5; i < 26; i += 3) { - QString ks = list[i].trimmed(); + const QByteArray &ks = list.at(i); if (ks.isEmpty()) break; int key = ks.toInt(&r1); - double val = list[i+1].trimmed().toDouble(&r2); - int un = list[i+2].trimmed().toInt(&r3); + double val = list.at(i+1).toDouble(&r2); + int un = list.at(i+2).toInt(&r3); if (!r1 || !r2 || !r3) return (i - 5)/3 + 1; @@ -109,77 +109,79 @@ Conversion Conversion::conversion(int id) } } -void Conversion::loadList(const QString &path) +bool Conversion::loadList(const QString &path) { QFile file(path); + CSV csv(&file); + QByteArrayList entry; bool res; - int ln = 0, pn; - if (!file.open(QFile::ReadOnly)) { qWarning("Error opening projections file: %s: %s", qPrintable(path), qPrintable(file.errorString())); - return; + return false; } - while (!file.atEnd()) { - ln++; - - QByteArray line = file.readLine(4096); - QList list = line.split(','); - if (list.size() != 26) { - qWarning("%s:%d: Format error", qPrintable(path), ln); - continue; + while (!csv.atEnd()) { + if (!csv.readEntry(entry) || entry.size() < 26) { + qWarning("%s:%d: Parse error", qPrintable(path), csv.line()); + return false; } - QString name(list.at(0).trimmed()); - int proj = list.at(1).trimmed().toInt(&res); + QString name(entry.at(0)); + int proj = entry.at(1).toInt(&res); if (!res) { - qWarning("%s:%d: Invalid projection code", qPrintable(path), ln); + qWarning("%s:%d: Invalid projection code", qPrintable(path), + csv.line()); continue; } - int units = list.at(2).trimmed().toInt(&res); + int units = entry.at(2).toInt(&res); if (!res) { - qWarning("%s:%d: Invalid linear units code", qPrintable(path), ln); + qWarning("%s:%d: Invalid linear units code", qPrintable(path), + csv.line()); continue; } - int transform = list.at(3).trimmed().toInt(&res); + int transform = entry.at(3).toInt(&res); if (!res) { qWarning("%s:%d: Invalid coordinate transformation code", - qPrintable(path), ln); + qPrintable(path), csv.line()); continue; } - int cs = list.at(4).trimmed().toInt(&res); + int cs = entry.at(4).toInt(&res); if (!res) { qWarning("%s:%d: Invalid coordinate system code", - qPrintable(path), ln); + qPrintable(path), csv.line()); continue; } if (!LinearUnits(units).isValid()) { - qWarning("%s:%d: Unknown linear units code", qPrintable(path), ln); + qWarning("%s:%d: Unknown linear units code", qPrintable(path), + csv.line()); continue; } if (!Projection::Method(transform).isValid()) { qWarning("%s:%d: Unknown coordinate transformation code", - qPrintable(path), ln); + qPrintable(path), csv.line()); continue; } if (!CoordinateSystem(cs).isValid()) { qWarning("%s:%d: Unknown coordinate system code", qPrintable(path), - ln); + csv.line()); continue; } Projection::Setup setup; - if ((pn = projectionSetup(list, setup))) { + int pn = projectionSetup(entry, setup); + if (pn) { qWarning("%s: %d: Invalid projection parameter #%d", - qPrintable(path), ln, pn); + qPrintable(path), csv.line(), pn); continue; } _conversions.insert(proj, Entry(name, transform, setup, units, cs)); } + + return true; } QList > Conversion::list() diff --git a/src/map/conversion.h b/src/map/conversion.h index bb5260f9..51057812 100644 --- a/src/map/conversion.h +++ b/src/map/conversion.h @@ -27,7 +27,7 @@ public: return (_units.isValid() && _method.isValid()); } - static void loadList(const QString &path); + static bool loadList(const QString &path); static Conversion conversion(int id); static QList > list(); diff --git a/src/map/ellipsoid.cpp b/src/map/ellipsoid.cpp index a20fdaec..95ff3473 100644 --- a/src/map/ellipsoid.cpp +++ b/src/map/ellipsoid.cpp @@ -1,6 +1,7 @@ #include #include #include "common/wgs84.h" +#include "common/csv.h" #include "ellipsoid.h" QMap Ellipsoid::_ellipsoids = defaults(); @@ -29,48 +30,47 @@ const Ellipsoid &Ellipsoid::ellipsoid(int id) return it.value(); } -void Ellipsoid::loadList(const QString &path) +bool Ellipsoid::loadList(const QString &path) { QFile file(path); + CSV csv(&file); + QByteArrayList entry; bool res; - int ln = 0; - if (!file.open(QFile::ReadOnly)) { qWarning("Error opening ellipsoids file: %s: %s", qPrintable(path), qPrintable(file.errorString())); - return; + return false; } - while (!file.atEnd()) { - ln++; - - QByteArray line = file.readLine(4096); - QList list = line.split(','); - if (list.size() != 4) { - qWarning("%s: %d: Format error", qPrintable(path), ln); - continue; + while (!csv.atEnd()) { + if (!csv.readEntry(entry) || entry.size() < 4) { + qWarning("%s:%d: Parse error", qPrintable(path), csv.line()); + return false; } - int id = list.at(1).trimmed().toInt(&res); + int id = entry.at(1).toInt(&res); if (!res) { - qWarning("%s: %d: Invalid ellipsoid code", qPrintable(path), ln); + qWarning("%s: %d: Invalid ellipsoid code", qPrintable(path), + csv.line()); continue; } - double radius = list.at(2).trimmed().toDouble(&res); + double radius = entry.at(2).toDouble(&res); if (!res) { - qWarning("%s: %d: Invalid radius", qPrintable(path), ln); + qWarning("%s: %d: Invalid radius", qPrintable(path), csv.line()); continue; } - double flattening = list.at(3).trimmed().toDouble(&res); + double flattening = entry.at(3).toDouble(&res); if (!res) { - qWarning("%s: %d: Invalid flattening", qPrintable(path), ln); + qWarning("%s: %d: Invalid flattening", qPrintable(path), csv.line()); continue; } Ellipsoid e(radius, 1.0/flattening); _ellipsoids.insert(id, e); } + + return true; } Ellipsoid::Ellipsoid(double radius, double flattening) diff --git a/src/map/ellipsoid.h b/src/map/ellipsoid.h index 9822e514..f41a4dff 100644 --- a/src/map/ellipsoid.h +++ b/src/map/ellipsoid.h @@ -25,7 +25,7 @@ public: static const Ellipsoid &WGS84(); static const Ellipsoid &ellipsoid(int id); - static void loadList(const QString &path); + static bool loadList(const QString &path); private: double _radius; diff --git a/src/map/gcs.cpp b/src/map/gcs.cpp index fd542d1a..88271da8 100644 --- a/src/map/gcs.cpp +++ b/src/map/gcs.cpp @@ -1,5 +1,6 @@ #include #include "common/wgs84.h" +#include "common/csv.h" #include "gcs.h" @@ -19,26 +20,24 @@ private: GCS _gcs; }; -static int parameter(const QString &str, bool *res) +static int parameter(const QByteArray &str, bool *res) { - QString field = str.trimmed(); - if (field.isEmpty()) { + if (str.isEmpty()) { *res = true; return 0; } - return field.toInt(res); + return str.toInt(res); } -static double parameterd(const QString &str, bool *res) +static double parameterd(const QByteArray &str, bool *res) { - QString field = str.trimmed(); - if (field.isEmpty()) { + if (str.isEmpty()) { *res = true; return NAN; } - return field.toDouble(res); + return str.toDouble(res); } @@ -89,102 +88,100 @@ GCS GCS::gcs(const QString &name) return GCS(); } -void GCS::loadList(const QString &path) +bool GCS::loadList(const QString &path) { QFile file(path); + CSV csv(&file); + QByteArrayList entry; bool res; - int ln = 0; - if (!file.open(QFile::ReadOnly)) { - qWarning("Error opening PCS file: %s: %s", qPrintable(path), + qWarning("Error opening GCS file: %s: %s", qPrintable(path), qPrintable(file.errorString())); - return; + return false; } - while (!file.atEnd()) { - ln++; - - QByteArray line = file.readLine(4096); - QList list = line.split(','); - if (list.size() != 14) { - qWarning("%s:%d: Format error", qPrintable(path), ln); - continue; + while (!csv.atEnd()) { + if (!csv.readEntry(entry) || entry.size() < 14) { + qWarning("%s:%d: Parse error", qPrintable(path), csv.line()); + return false; } - int id = parameter(list[1], &res); + int id = parameter(entry.at(1), &res); if (!res) { - qWarning("%s:%d: Invalid GCS code", qPrintable(path), ln); + qWarning("%s:%d: Invalid GCS code", qPrintable(path), csv.line()); continue; } - int gd = parameter(list[2], &res); + int gd = parameter(entry.at(2), &res); if (!res) { qWarning("%s:%d: Invalid geodetic datum code", qPrintable(path), - ln); + csv.line()); continue; } - int au = list[3].trimmed().toInt(&res); + int au = entry.at(3).toInt(&res); if (!res) { qWarning("%s:%d: Invalid angular units code", qPrintable(path), - ln); + csv.line()); continue; } - int el = list[4].trimmed().toInt(&res); + int el = entry.at(4).toInt(&res); if (!res) { - qWarning("%s:%d: Invalid ellipsoid code", qPrintable(path), ln); + qWarning("%s:%d: Invalid ellipsoid code", qPrintable(path), + csv.line()); continue; } - int pm = list[5].trimmed().toInt(&res); + int pm = entry.at(5).toInt(&res); if (!res) { qWarning("%s:%d: Invalid prime meridian code", qPrintable(path), - ln); + csv.line()); continue; } - int ct = list[6].trimmed().toInt(&res); + int ct = entry.at(6).toInt(&res); if (!res) { qWarning("%s:%d: Invalid coordinates transformation code", - qPrintable(path), ln); + qPrintable(path), csv.line()); continue; } - double dx = list[7].trimmed().toDouble(&res); + double dx = entry.at(7).toDouble(&res); if (!res) { - qWarning("%s:%d: Invalid dx", qPrintable(path), ln); + qWarning("%s:%d: Invalid dx", qPrintable(path), csv.line()); continue; } - double dy = list[8].trimmed().toDouble(&res); + double dy = entry.at(8).toDouble(&res); if (!res) { - qWarning("%s:%d: Invalid dy", qPrintable(path), ln); + qWarning("%s:%d: Invalid dy", qPrintable(path), csv.line()); continue; } - double dz = list[9].trimmed().toDouble(&res); + double dz = entry.at(9).toDouble(&res); if (!res) { - qWarning("%s:%d: Invalid dz", qPrintable(path), ln); + qWarning("%s:%d: Invalid dz", qPrintable(path), csv.line()); continue; } - double rx = parameterd(list[10], &res); + double rx = parameterd(entry.at(10), &res); if (!res) { - qWarning("%s:%d: Invalid rx", qPrintable(path), ln); + qWarning("%s:%d: Invalid rx", qPrintable(path), csv.line()); continue; } - double ry = parameterd(list[11], &res); + double ry = parameterd(entry.at(11), &res); if (!res) { - qWarning("%s:%d: Invalid ry", qPrintable(path), ln); + qWarning("%s:%d: Invalid ry", qPrintable(path), csv.line()); continue; } - double rz = parameterd(list[12], &res); + double rz = parameterd(entry.at(12), &res); if (!res) { - qWarning("%s:%d: Invalid rz", qPrintable(path), ln); + qWarning("%s:%d: Invalid rz", qPrintable(path), csv.line()); continue; } - double ds = parameterd(list[13], &res); + double ds = parameterd(entry.at(13), &res); if (!res) { - qWarning("%s:%d: Invalid ds", qPrintable(path), ln); + qWarning("%s:%d: Invalid ds", qPrintable(path), csv.line()); continue; } const Ellipsoid &e = Ellipsoid::ellipsoid(el); if (e.isNull()) { - qWarning("%s:%d: Unknown ellipsoid code", qPrintable(path), ln); + qWarning("%s:%d: Unknown ellipsoid code", qPrintable(path), + csv.line()); continue; } @@ -201,22 +198,24 @@ void GCS::loadList(const QString &path) break; default: qWarning("%s:%d: Unknown coordinates transformation method", - qPrintable(path), ln); + qPrintable(path), csv.line()); continue; } if (!datum.isValid()) { qWarning("%s:%d: Invalid coordinates transformation parameters", - qPrintable(path), ln); + qPrintable(path), csv.line()); continue; } GCS gcs(datum, pm, au); if (gcs.isValid()) - _gcss.append(Entry(id, gd, list[0].trimmed(), gcs)); + _gcss.append(Entry(id, gd, entry.at(0), gcs)); else qWarning("%s:%d: Unknown prime meridian/angular units code", - qPrintable(path), ln); + qPrintable(path), csv.line()); } + + return true; } Coordinates GCS::toWGS84(const Coordinates &c) const diff --git a/src/map/gcs.h b/src/map/gcs.h index 1182ca1d..6fa383f1 100644 --- a/src/map/gcs.h +++ b/src/map/gcs.h @@ -37,7 +37,7 @@ public: static GCS gcs(const QString &name); static const GCS &WGS84(); - static void loadList(const QString &path); + static bool loadList(const QString &path); static QList > list(); static QList > WGS84List(); diff --git a/src/map/pcs.cpp b/src/map/pcs.cpp index 29bf80f8..d9210499 100644 --- a/src/map/pcs.cpp +++ b/src/map/pcs.cpp @@ -1,4 +1,5 @@ #include +#include "common/csv.h" #include "angularunits.h" #include "pcs.h" @@ -23,52 +24,51 @@ PCS PCS::pcs(int id) } } -void PCS::loadList(const QString &path) +bool PCS::loadList(const QString &path) { QFile file(path); + CSV csv(&file); + QByteArrayList entry; bool res; - int ln = 0; if (!file.open(QFile::ReadOnly)) { qWarning("Error opening PCS file: %s: %s", qPrintable(path), qPrintable(file.errorString())); - return; + return false; } - while (!file.atEnd()) { - ln++; - - QByteArray line = file.readLine(4096); - QList list = line.split(','); - if (list.size() != 4) { - qWarning("%s:%d: Format error", qPrintable(path), ln); + while (!csv.atEnd()) { + if (!csv.readEntry(entry) || entry.size() < 4) { + qWarning("%s:%d: Parse error", qPrintable(path), csv.line()); + return false; + } + QString name(entry.at(0)); + int id = entry.at(1).toInt(&res); + if (!res) { + qWarning("%s:%d: Invalid PCS code", qPrintable(path), csv.line()); continue; } - - QString name(list.at(0).trimmed()); - int id = list.at(1).trimmed().toInt(&res); + int gcs = entry.at(2).toInt(&res); if (!res) { - qWarning("%s:%d: Invalid PCS code", qPrintable(path), ln); + qWarning("%s:%d: Invalid GCS code", qPrintable(path), csv.line()); continue; } - int gcs = list.at(2).trimmed().toInt(&res); + int proj = entry.at(3).toInt(&res); if (!res) { - qWarning("%s:%d: Invalid GCS code", qPrintable(path), ln); - continue; - } - int proj = list.at(3).trimmed().toInt(&res); - if (!res) { - qWarning("%s:%d: Invalid projection code", qPrintable(path), ln); + qWarning("%s:%d: Invalid projection code", qPrintable(path), + csv.line()); continue; } if (GCS::gcs(gcs).isNull()) { - qWarning("%s:%d: Unknown GCS code", qPrintable(path), ln); + qWarning("%s:%d: Unknown GCS code", qPrintable(path), csv.line()); continue; } _pcss.insert(id, Entry(name, gcs, proj)); } + + return true; } QList > PCS::list() diff --git a/src/map/pcs.h b/src/map/pcs.h index c6f0938f..e084687c 100644 --- a/src/map/pcs.h +++ b/src/map/pcs.h @@ -22,7 +22,7 @@ public: bool isNull() const {return (_gcs.isNull() && _conversion.isNull());} bool isValid() const {return (_gcs.isValid() && _conversion.isValid());} - static void loadList(const QString &path); + static bool loadList(const QString &path); static PCS pcs(int id); static QList > list();