From 0e4ef195c690056671cc1f6c43882837886431a1 Mon Sep 17 00:00:00 2001 From: Jochen Topf Date: Mon, 18 May 2026 09:38:00 +0200 Subject: [PATCH] Update included libosmium to version 2.23.1 --- contrib/libosmium/README.contrib | 2 +- contrib/libosmium/README.md | 3 +- .../include/osmium/handler/check_order.hpp | 48 +++++++++++++++++-- .../osmium/io/detail/pbf_input_format.hpp | 14 +++--- .../include/osmium/io/detail/string_util.hpp | 46 ++++++++++++++++++ .../osmium/io/detail/xml_output_format.hpp | 17 +++++-- .../include/osmium/osm/object_comparisons.hpp | 10 ++-- contrib/libosmium/include/osmium/version.hpp | 4 +- 8 files changed, 119 insertions(+), 25 deletions(-) diff --git a/contrib/libosmium/README.contrib b/contrib/libosmium/README.contrib index 7026807c1..da69018f6 100644 --- a/contrib/libosmium/README.contrib +++ b/contrib/libosmium/README.contrib @@ -1,2 +1,2 @@ Source: https://github.com/osmcode/libosmium -Revision: v2.23.0 +Revision: v2.23.1 diff --git a/contrib/libosmium/README.md b/contrib/libosmium/README.md index 29b86f4a4..156c20f7d 100644 --- a/contrib/libosmium/README.md +++ b/contrib/libosmium/README.md @@ -4,7 +4,8 @@ https://osmcode.org/libosmium A fast and flexible C++ library for working with OpenStreetMap data. -Libosmium works on Linux, macOS and Windows. +Libosmium works on Linux, macOS and Windows. You need a 64bit system, 32bit +systems are not supported. [![Build Status](https://github.com/osmcode/libosmium/actions/workflows/ci.yml/badge.svg)](https://github.com/osmcode/libosmium/actions) [![Packaging status](https://repology.org/badge/tiny-repos/libosmium.svg)](https://repology.org/metapackage/libosmium) diff --git a/contrib/libosmium/include/osmium/handler/check_order.hpp b/contrib/libosmium/include/osmium/handler/check_order.hpp index c05652d6a..44dea19fc 100644 --- a/contrib/libosmium/include/osmium/handler/check_order.hpp +++ b/contrib/libosmium/include/osmium/handler/check_order.hpp @@ -76,8 +76,11 @@ namespace osmium { * IDs are ordered first then positive IDs, both ordered by absolute * value. * - * IDs have to be unique for each type. This check will fail for - * history files. + * Constructor has a single bool parameter. If this is false (default) + * the check is done for normal OSM data files, i.e. IDs have to be + * unique for each type. If this is true, the check is done for OSM + * history files, the combination ID/version has to be unique and the + * versions need to be in order. * * To use this, add a CheckOrder member variable to your handler and * call the node(), way(), and relation() methods from your node(), @@ -89,12 +92,17 @@ namespace osmium { osmium::object_id_type m_max_node_id = 0; osmium::object_id_type m_max_way_id = 0; osmium::object_id_type m_max_relation_id = 0; + osmium::object_version_type m_last_version = 0; bool m_has_node = false; bool m_has_way = false; bool m_has_relation = false; + bool m_with_history; public: + CheckOrder(bool with_history = false) : m_with_history(with_history) { + } + void node(const osmium::Node& node) { if (m_has_way) { throw out_of_order_error{"Found a node after a way.", node.id()}; @@ -105,7 +113,13 @@ namespace osmium { if (m_has_node) { if (m_max_node_id == node.id()) { - throw out_of_order_error{"Node ID twice in input. Maybe you are using a history or change file?", node.id()}; + if (m_with_history) { + if (node.version() <= m_last_version) { + throw out_of_order_error{"Versions out of order", node.id()}; + } + } else { + throw out_of_order_error{"Node ID twice in input. Maybe you are using a history or change file?", node.id()}; + } } if (id_order{}(node.id(), m_max_node_id)) { throw out_of_order_error{"Node IDs out of order: " + std::to_string(node.id()), node.id()}; @@ -115,6 +129,10 @@ namespace osmium { m_max_node_id = node.id(); m_has_node = true; } + + if (m_with_history) { + m_last_version = node.version(); + } } void way(const osmium::Way& way) { @@ -124,7 +142,13 @@ namespace osmium { if (m_has_way) { if (m_max_way_id == way.id()) { - throw out_of_order_error{"Way ID twice in input. Maybe you are using a history or change file?", way.id()}; + if (m_with_history) { + if (way.version() <= m_last_version) { + throw out_of_order_error{"Versions out of order", way.id()}; + } + } else { + throw out_of_order_error{"Way ID twice in input. Maybe you are using a history or change file?", way.id()}; + } } if (id_order{}(way.id(), m_max_way_id)) { throw out_of_order_error{"Way IDs out of order: " + std::to_string(way.id()), way.id()}; @@ -134,12 +158,22 @@ namespace osmium { m_max_way_id = way.id(); m_has_way = true; } + + if (m_with_history) { + m_last_version = way.version(); + } } void relation(const osmium::Relation& relation) { if (m_has_relation) { if (m_max_relation_id == relation.id()) { - throw out_of_order_error{"Relation ID twice in input. Maybe you are using a history or change file?", relation.id()}; + if (m_with_history) { + if (relation.version() <= m_last_version) { + throw out_of_order_error{"Versions out of order", relation.id()}; + } + } else { + throw out_of_order_error{"Relation ID twice in input. Maybe you are using a history or change file?", relation.id()}; + } } if (id_order{}(relation.id(), m_max_relation_id)) { throw out_of_order_error{"Relation IDs out of order: " + std::to_string(relation.id()), relation.id()}; @@ -149,6 +183,10 @@ namespace osmium { m_max_relation_id = relation.id(); m_has_relation = true; } + + if (m_with_history) { + m_last_version = relation.version(); + } } osmium::object_id_type max_node_id() const noexcept { diff --git a/contrib/libosmium/include/osmium/io/detail/pbf_input_format.hpp b/contrib/libosmium/include/osmium/io/detail/pbf_input_format.hpp index abac957c7..36fe336ca 100644 --- a/contrib/libosmium/include/osmium/io/detail/pbf_input_format.hpp +++ b/contrib/libosmium/include/osmium/io/detail/pbf_input_format.hpp @@ -100,13 +100,6 @@ namespace osmium { m_input_buffer.erase(0, size); } - static uint32_t get_size_in_network_byte_order(const char* d) noexcept { - return (static_cast(d[3])) | - (static_cast(d[2]) << 8U) | - (static_cast(d[1]) << 16U) | - (static_cast(d[0]) << 24U); - } - static uint32_t check_size(uint32_t size) { if (size > static_cast(max_blob_header_size)) { throw osmium::pbf_error{"invalid BlobHeader size (> max_blob_header_size)"}; @@ -256,6 +249,13 @@ namespace osmium { public: + static uint32_t get_size_in_network_byte_order(const char* d) noexcept { + return (static_cast(static_cast(d[3]))) | + (static_cast(static_cast(d[2])) << 8U) | + (static_cast(static_cast(d[1])) << 16U) | + (static_cast(static_cast(d[0])) << 24U); + } + explicit PBFParser(parser_arguments& args) : Parser(args), m_offset_ptr(args.offset_ptr), diff --git a/contrib/libosmium/include/osmium/io/detail/string_util.hpp b/contrib/libosmium/include/osmium/io/detail/string_util.hpp index 038a5194f..e726567df 100644 --- a/contrib/libosmium/include/osmium/io/detail/string_util.hpp +++ b/contrib/libosmium/include/osmium/io/detail/string_util.hpp @@ -142,6 +142,52 @@ namespace osmium { return 0; } + /** + * Check that a string contains only valid UTF-8. Returns nullptr + * if the string is valid, otherwise it returns a pointer to the + * first invalid character. + * + * Based on https://www.cl.cam.ac.uk/~mgk25/ucs/utf8_check.c + * License: http://www.cl.cam.ac.uk/~mgk25/short-license.html + */ + inline char const* utf8_check(char const* str) noexcept { + auto* s = reinterpret_cast(str); + while (*s) { + if (*s < 0x80) { + /* 0xxxxxxx */ + s++; + } else if ((s[0] & 0xe0) == 0xc0) { + /* 110XXXXx 10xxxxxx */ + if ((s[1] & 0xc0) != 0x80 || (s[0] & 0xfe) == 0xc0) /* overlong? */ { + return reinterpret_cast(s); + } + s += 2; + } else if ((s[0] & 0xf0) == 0xe0) { + /* 1110XXXX 10Xxxxxx 10xxxxxx */ + if ((s[1] & 0xc0) != 0x80 || (s[2] & 0xc0) != 0x80 || + (s[0] == 0xe0 && (s[1] & 0xe0) == 0x80) || /* overlong? */ + (s[0] == 0xed && (s[1] & 0xe0) == 0xa0) || /* surrogate? */ + (s[0] == 0xef && s[1] == 0xbf && + (s[2] & 0xfe) == 0xbe)) /* U+FFFE or U+FFFF? */ { + return reinterpret_cast(s); + } + s += 3; + } else if ((s[0] & 0xf8) == 0xf0) { + /* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */ + if ((s[1] & 0xc0) != 0x80 || (s[2] & 0xc0) != 0x80 || + (s[3] & 0xc0) != 0x80 || + (s[0] == 0xf0 && (s[1] & 0xf0) == 0x80) || /* overlong? */ + (s[0] == 0xf4 && s[1] > 0x8f) || s[0] > 0xf4) /* > U+10FFFF? */ { + return reinterpret_cast(s); + } + s += 4; + } else { + return reinterpret_cast(s); + } + } + return nullptr; + } + inline uint32_t next_utf8_codepoint(char const** begin, const char* end) { const auto* it = reinterpret_cast(*begin); uint32_t cp = 0xffU & *it; diff --git a/contrib/libosmium/include/osmium/io/detail/xml_output_format.hpp b/contrib/libosmium/include/osmium/io/detail/xml_output_format.hpp index 1ba57f2fe..359ca9014 100644 --- a/contrib/libosmium/include/osmium/io/detail/xml_output_format.hpp +++ b/contrib/libosmium/include/osmium/io/detail/xml_output_format.hpp @@ -109,7 +109,7 @@ namespace osmium { class XMLOutputBlock : public OutputBlock { // operation (create, modify, delete) for osc files - enum class operation { + enum class operation : std::uint8_t { op_none = 0, op_create = 1, op_modify = 2, @@ -243,6 +243,15 @@ namespace osmium { m_last_op = op; } + static operation get_operation(const osmium::OSMObject &object) noexcept { + if (object.deleted()) { + return operation::op_delete; + } + + return object.version() == 1 ? operation::op_create + : operation::op_modify; + } + public: XMLOutputBlock(osmium::memory::Buffer&& buffer, const xml_output_options& options) : @@ -266,7 +275,7 @@ namespace osmium { void node(const osmium::Node& node) { if (m_options.use_change_ops) { - open_close_op_tag(node.visible() ? (node.version() == 1 ? operation::op_create : operation::op_modify) : operation::op_delete); + open_close_op_tag(get_operation(node)); } write_prefix(); @@ -293,7 +302,7 @@ namespace osmium { void way(const osmium::Way& way) { if (m_options.use_change_ops) { - open_close_op_tag(way.visible() ? (way.version() == 1 ? operation::op_create : operation::op_modify) : operation::op_delete); + open_close_op_tag(get_operation(way)); } write_prefix(); @@ -334,7 +343,7 @@ namespace osmium { void relation(const osmium::Relation& relation) { if (m_options.use_change_ops) { - open_close_op_tag(relation.visible() ? (relation.version() == 1 ? operation::op_create : operation::op_modify) : operation::op_delete); + open_close_op_tag(get_operation(relation)); } write_prefix(); diff --git a/contrib/libosmium/include/osmium/osm/object_comparisons.hpp b/contrib/libosmium/include/osmium/osm/object_comparisons.hpp index 96a5ca7ef..a24e53d2c 100644 --- a/contrib/libosmium/include/osmium/osm/object_comparisons.hpp +++ b/contrib/libosmium/include/osmium/osm/object_comparisons.hpp @@ -154,17 +154,17 @@ namespace osmium { * (negative IDs first, then positive IDs, both in the order of their * absolute values), but later versions of an object are ordered before * earlier versions of the same object. This is useful when the last - * version of an object needs to be used. + * version of an object needs to be used. Object visibility is not taken + * into account, so objects with different visibilities keep their order. */ struct object_order_type_id_reverse_version { bool operator()(const osmium::OSMObject& lhs, const osmium::OSMObject& rhs) const noexcept { + const bool tsvalid = lhs.timestamp().valid() && rhs.timestamp().valid(); return const_tie(lhs.type(), lhs.id() > 0, lhs.positive_id(), rhs.version(), - ((lhs.timestamp().valid() && rhs.timestamp().valid()) ? rhs.timestamp() : osmium::Timestamp()), - rhs.visible()) < + (tsvalid ? rhs.timestamp() : osmium::Timestamp())) < const_tie(rhs.type(), rhs.id() > 0, rhs.positive_id(), lhs.version(), - ((lhs.timestamp().valid() && rhs.timestamp().valid()) ? lhs.timestamp() : osmium::Timestamp()), - lhs.visible()); + (tsvalid ? lhs.timestamp() : osmium::Timestamp())); } /// @pre lhs and rhs must not be nullptr diff --git a/contrib/libosmium/include/osmium/version.hpp b/contrib/libosmium/include/osmium/version.hpp index 549cca1b0..855ca1d1c 100644 --- a/contrib/libosmium/include/osmium/version.hpp +++ b/contrib/libosmium/include/osmium/version.hpp @@ -40,8 +40,8 @@ DEALINGS IN THE SOFTWARE. #define LIBOSMIUM_VERSION_MINOR 23 // NOLINTNEXTLINE(modernize-macro-to-enum) -#define LIBOSMIUM_VERSION_PATCH 0 +#define LIBOSMIUM_VERSION_PATCH 1 -#define LIBOSMIUM_VERSION_STRING "2.23.0" +#define LIBOSMIUM_VERSION_STRING "2.23.1" #endif // OSMIUM_VERSION_HPP