File indexing completed on 2024-11-24 04:15:37
0001 /* 0002 SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "levelparser_p.h" 0008 #include "logging.h" 0009 0010 #include <osm/element.h> 0011 0012 // ### ugly workaround for locale-ignoring string to float conversion 0013 // std::from_chars offers that with C++17, but isn't actually implemented yet for floats/doubles... 0014 #include <private/qlocale_tools_p.h> 0015 0016 #include <cstdlib> 0017 #include <limits> 0018 0019 using namespace KOSMIndoorMap; 0020 0021 // NOTE string to float conversion in here must be done ignoring the locale! 0022 void LevelParser::parse(QByteArray &&level, OSM::Element e, const std::function<void(int, OSM::Element)> &callback) 0023 { 0024 int rangeBegin = std::numeric_limits<int>::max(); 0025 int numStartIdx = -1; 0026 0027 for (int i = 0; i < level.size(); ++i) { 0028 auto &c = level[i]; 0029 0030 if (c == ',') { // fix decimal separator errors 0031 qCDebug(Log) << "syntax error in level tag:" << level << e.url(); 0032 c = '.'; 0033 } 0034 0035 if (std::isdigit(static_cast<unsigned char>(c)) || c == '.') { 0036 if (numStartIdx < 0) { 0037 numStartIdx = i; 0038 } 0039 continue; 0040 } 0041 0042 if (c == ';') { 0043 const int l = std::round(qstrtod(level.constData() + numStartIdx, nullptr, nullptr) * 10.0); // ### waiting for std::from_chars 0044 if (rangeBegin <= l) { 0045 for (int j = rangeBegin; j <= l; j += 10) { 0046 callback(j, e); 0047 } 0048 rangeBegin = std::numeric_limits<int>::max(); 0049 } else { 0050 callback(l, e); 0051 } 0052 numStartIdx = -1; 0053 continue; 0054 } 0055 0056 if (c == QLatin1Char('-')) { 0057 if (numStartIdx < 0) { 0058 numStartIdx = i; 0059 } else { 0060 rangeBegin = std::round(qstrtod(level.constData() + numStartIdx, nullptr, nullptr) * 10.0); // ### waiting for std::from_chars 0061 numStartIdx = -1; 0062 } 0063 } 0064 } 0065 0066 if (numStartIdx >= level.size() || numStartIdx < 0) { 0067 return; 0068 } 0069 const int l = std::round(qstrtod(level.constData() + numStartIdx, nullptr, nullptr) * 10.0); // ### waiting for std::from_chars 0070 if (rangeBegin <= l) { 0071 for (int j = rangeBegin; j <= l; j += 10) { 0072 callback(j, e); 0073 } 0074 } else { 0075 callback(l, e); 0076 } 0077 }