From 1a17261c25bf960491b07e8bd75bef383c1f2f34 Mon Sep 17 00:00:00 2001 From: mmd-osm Date: Fri, 26 Jul 2024 13:00:00 +0200 Subject: [PATCH 1/2] std::stod -> std::from_chars --- .../cgimap/api06/changeset_upload/node.hpp | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/include/cgimap/api06/changeset_upload/node.hpp b/include/cgimap/api06/changeset_upload/node.hpp index 8fd0d2cb..76b59daa 100644 --- a/include/cgimap/api06/changeset_upload/node.hpp +++ b/include/cgimap/api06/changeset_upload/node.hpp @@ -12,9 +12,8 @@ #include "cgimap/api06/changeset_upload/osmobject.hpp" -#include +#include #include -#include namespace api06 { @@ -31,32 +30,30 @@ class Node : public OSMObject { void set_lat(const std::string &lat) { - double _lat = -200.0; + double _lat; - try { - _lat = std::stod(lat); - } catch (std::invalid_argument &e) { + auto [_, ec] = std::from_chars(lat.data(), lat.data() + lat.size(), _lat); + + if (ec == std::errc()) + set_lat(_lat); + else if (ec == std::errc::invalid_argument) throw xml_error("Latitude is not numeric"); - } catch (std::out_of_range &e) { + else if (ec == std::errc::result_out_of_range) throw xml_error("Latitude value is too large"); - } - - set_lat(_lat); } void set_lon(const std::string &lon) { - double _lon = -200.0; + double _lon; - try { - _lon = std::stod(lon); - } catch (std::invalid_argument &e) { + auto [_, ec] = std::from_chars(lon.data(), lon.data() + lon.size(), _lon); + + if (ec == std::errc()) + set_lon(_lon); + else if (ec == std::errc::invalid_argument) throw xml_error("Longitude is not numeric"); - } catch (std::out_of_range &e) { + else if (ec == std::errc::result_out_of_range) throw xml_error("Longitude value is too large"); - } - - set_lon(_lon); } void set_lat(double lat) { From b3f44420da44a62dd3c27ab00b8deb36cd3c61ed Mon Sep 17 00:00:00 2001 From: mmd-osm Date: Fri, 26 Jul 2024 13:19:46 +0200 Subject: [PATCH 2/2] Some more std::sto? -> std::from_chars --- .../api06/changeset_upload/osmobject.hpp | 90 ++++++++++--------- .../api06/changeset_upload/relation.hpp | 28 +++--- include/cgimap/api06/changeset_upload/way.hpp | 21 +++-- 3 files changed, 75 insertions(+), 64 deletions(-) diff --git a/include/cgimap/api06/changeset_upload/osmobject.hpp b/include/cgimap/api06/changeset_upload/osmobject.hpp index 7875f3fe..6ac4b31d 100644 --- a/include/cgimap/api06/changeset_upload/osmobject.hpp +++ b/include/cgimap/api06/changeset_upload/osmobject.hpp @@ -13,10 +13,12 @@ #include "cgimap/types.hpp" #include "cgimap/util.hpp" -#include +#include #include #include +#include + namespace api06 { struct xml_error : public http::bad_request { @@ -35,11 +37,32 @@ namespace api06 { virtual ~OSMObject() = default; - void set_changeset(osm_changeset_id_t changeset) { m_changeset = changeset; } + void set_changeset(osm_changeset_id_t changeset) { + + if (changeset <= 0) { + throw xml_error("Changeset must be a positive number"); + } + + m_changeset = changeset; + } + + void set_version(osm_version_t version) { + + if (version < 0) { + throw xml_error("Version may not be negative"); + } + + m_version = version; + } + + void set_id(osm_nwr_signed_id_t id) { - void set_version(osm_version_t version) { m_version = version; } + if (id == 0) { + throw xml_error("Id must be different from 0"); + } - void set_id(osm_nwr_signed_id_t id) { m_id = id; } + m_id = id; + } // Setters with string conversions @@ -47,57 +70,42 @@ namespace api06 { osm_changeset_id_t _changeset = 0; - try { - _changeset = std::stol(changeset); - } catch (std::invalid_argument& e) { - throw xml_error("Changeset is not numeric"); - } catch (std::out_of_range& e) { - throw xml_error("Changeset number is too large"); - } - - if (_changeset <= 0) { - throw xml_error("Changeset must be a positive number"); - } + auto [_, ec] = std::from_chars(changeset.data(), changeset.data() + changeset.size(), _changeset); - set_changeset(_changeset); + if (ec == std::errc()) + set_changeset(_changeset); + else if (ec == std::errc::invalid_argument) + throw xml_error("Changeset is not numeric"); + else if (ec == std::errc::result_out_of_range) + throw xml_error("Changeset number is too large"); } void set_version(const std::string &version) { int64_t _version = 0; - try { - _version = std::stoi(version); - } catch (std::invalid_argument& e) { - throw xml_error("Version is not numeric"); - } catch (std::out_of_range& e) { - throw xml_error("Version value is too large"); - } - - if (_version < 0) { - throw xml_error("Version may not be negative"); - } + auto [_, ec] = std::from_chars(version.data(), version.data() + version.size(), _version); - set_version(_version); + if (ec == std::errc()) + set_version(_version); + else if (ec == std::errc::invalid_argument) + throw xml_error("Version is not numeric"); + else if (ec == std::errc::result_out_of_range) + throw xml_error("Version value is too large"); } void set_id(const std::string &id) { osm_nwr_signed_id_t _id = 0; - try { - _id = std::stol(id); - } catch (std::invalid_argument& e) { - throw xml_error("Id is not numeric"); - } catch (std::out_of_range& e) { - throw xml_error("Id number is too large"); - } - - if (_id == 0) { - throw xml_error("Id must be different from 0"); - } + auto [_, ec] = std::from_chars(id.data(), id.data() + id.size(), _id); - set_id(_id); + if (ec == std::errc()) + set_id(_id); + else if (ec == std::errc::invalid_argument) + throw xml_error("Id is not numeric"); + else if (ec == std::errc::result_out_of_range) + throw xml_error("Id number is too large"); } osm_changeset_id_t changeset() const { return *m_changeset; } @@ -129,7 +137,7 @@ namespace api06 { fmt::format("Value has more than 255 unicode characters in {}", to_string())); } - if (!(m_tags.insert(std::pair(key, value))) + if (!(m_tags.insert({key, value})) .second) { throw xml_error( fmt::format("{} has duplicate tags with key {}", to_string(), key)); diff --git a/include/cgimap/api06/changeset_upload/relation.hpp b/include/cgimap/api06/changeset_upload/relation.hpp index 5ae2012f..973ff28d 100644 --- a/include/cgimap/api06/changeset_upload/relation.hpp +++ b/include/cgimap/api06/changeset_upload/relation.hpp @@ -53,24 +53,28 @@ class RelationMember { m_role = role; } + void set_ref(osm_nwr_signed_id_t ref) { + + if (ref == 0) { + throw xml_error("Relation member 'ref' attribute may not be 0"); + } + + m_ref = ref; + } + void set_ref(const std::string &ref) { osm_nwr_signed_id_t _ref = 0; - try { - _ref = std::stol(ref); - } catch (std::invalid_argument &e) { - throw xml_error("Relation member 'ref' attribute is not numeric"); - } catch (std::out_of_range &e) { - throw xml_error( - "Relation member 'ref' attribute value is too large"); - } + auto [_, ec] = std::from_chars(ref.data(), ref.data() + ref.size(), _ref); - if (_ref == 0) { - throw xml_error("Relation member 'ref' attribute may not be 0"); + if (ec == std::errc()) { + set_ref(_ref); } - - m_ref = _ref; + else if (ec == std::errc::invalid_argument) + throw xml_error("Relation member 'ref' attribute is not numeric"); + else if (ec == std::errc::result_out_of_range) + throw xml_error("Relation member 'ref' attribute value is too large"); } bool is_valid() const { diff --git a/include/cgimap/api06/changeset_upload/way.hpp b/include/cgimap/api06/changeset_upload/way.hpp index f89b18c2..6f277153 100644 --- a/include/cgimap/api06/changeset_upload/way.hpp +++ b/include/cgimap/api06/changeset_upload/way.hpp @@ -28,6 +28,10 @@ class Way : public OSMObject { ~Way() override = default; void add_way_node(osm_nwr_signed_id_t waynode) { + if (waynode == 0) { + throw xml_error("Way node value may not be 0"); + } + m_way_nodes.emplace_back(waynode); } @@ -35,19 +39,14 @@ class Way : public OSMObject { osm_nwr_signed_id_t _waynode = 0; - try { - _waynode = std::stol(waynode); - } catch (std::invalid_argument& e) { + auto [_, ec] = std::from_chars(waynode.data(), waynode.data() + waynode.size(), _waynode); + + if (ec == std::errc()) + add_way_node(_waynode); + else if (ec == std::errc::invalid_argument) throw xml_error("Way node is not numeric"); - } catch (std::out_of_range& e) { + else if (ec == std::errc::result_out_of_range) throw xml_error("Way node value is too large"); - } - - if (_waynode == 0) { - throw xml_error("Way node value may not be 0"); - } - - add_way_node(_waynode); } const std::vector &nodes() const { return m_way_nodes; }