Loading...
Searching...
No Matches
members_database.hpp
Go to the documentation of this file.
#ifndef OSMIUM_RELATIONS_MEMBERS_DATABASE_HPP
#define OSMIUM_RELATIONS_MEMBERS_DATABASE_HPP
/*
This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2025 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <osmium/osm/object.hpp>
#include <osmium/osm/relation.hpp>
#include <osmium/osm/types.hpp>
#include <osmium/relations/relations_database.hpp>
#include <osmium/storage/item_stash.hpp>
#include <osmium/util/iterator.hpp>
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <limits>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
namespace osmium {
namespace relations {
class MembersDatabaseCommon {
struct element {
enum {
removed_value = std::numeric_limits<std::size_t>::max()
};
osmium::object_id_type member_id;
std::size_t member_num;
std::size_t relation_pos;
osmium::ItemStash::handle_type object_handle;
explicit element(std::size_t rel_pos, osmium::object_id_type memb_id, std::size_t memb_num) noexcept :
member_id(memb_id),
member_num(memb_num),
relation_pos(rel_pos) {
}
explicit element(osmium::object_id_type m_id) noexcept :
member_id(m_id),
member_num(0),
relation_pos(0) {
}
bool is_removed() const noexcept {
return member_num == removed_value;
}
void remove() noexcept {
member_num = removed_value;
}
bool operator<(const element& other) const noexcept {
return std::tie(member_id, member_num, relation_pos) <
std::tie(other.member_id, other.member_num, other.relation_pos);
}
}; // struct element
// comparison function only comparing member_id.
struct compare_member_id {
bool operator()(const element& a, const element& b) const noexcept {
return a.member_id < b.member_id;
}
};
std::vector<element> m_elements;
protected:
osmium::ItemStash& m_stash;
osmium::relations::RelationsDatabase& m_relations_db;
#ifndef NDEBUG
// This is used only in debug builds to make sure the
// prepare_for_lookup() function is called at the right place.
bool m_init_phase = true;
#endif
using iterator = std::vector<element>::iterator;
using const_iterator = std::vector<element>::const_iterator;
iterator_range<iterator> find(osmium::object_id_type id) {
return make_range(std::equal_range(m_elements.begin(), m_elements.end(), element{id}, compare_member_id{}));
}
iterator_range<const_iterator> find(osmium::object_id_type id) const {
return make_range(std::equal_range(m_elements.cbegin(), m_elements.cend(), element{id}, compare_member_id{}));
}
static typename std::iterator_traits<iterator>::difference_type count_not_removed(const iterator_range<iterator>& range) noexcept {
return std::count_if(range.begin(), range.end(), [](const element& elem) {
return !elem.is_removed();
});
}
void add_object(const osmium::OSMObject& object, iterator_range<iterator>& range) {
const auto handle = m_stash.add_item(object);
for (auto& elem : range) {
elem.object_handle = handle;
}
}
MembersDatabaseCommon(osmium::ItemStash& stash, osmium::relations::RelationsDatabase& relations_db) :
m_stash(stash),
m_relations_db(relations_db) {
}
public:
std::size_t used_memory() const noexcept {
return (sizeof(element) * m_elements.capacity()) +
sizeof(MembersDatabaseCommon);
}
std::size_t size() const noexcept {
return m_elements.size();
}
struct counts {
std::size_t tracked = 0;
std::size_t available = 0;
std::size_t removed = 0;
};
counts count() const noexcept {
counts c;
for (const auto& elem : m_elements) {
if (elem.is_removed()) {
++c.removed;
} else if (elem.object_handle.valid()) {
++c.available;
} else {
++c.tracked;
}
}
return c;
}
void track(RelationHandle& rel_handle, osmium::object_id_type member_id, std::size_t member_num) {
assert(m_init_phase && "Can not call MembersDatabase::track() after MembersDatabase::prepare_for_lookup().");
assert(rel_handle.relation_database() == &m_relations_db);
m_elements.emplace_back(rel_handle.pos(), member_id, member_num);
rel_handle.increment_members();
}
void prepare_for_lookup() {
assert(m_init_phase && "Can not call MembersDatabase::prepare_for_lookup() twice.");
std::sort(m_elements.begin(), m_elements.end());
#ifndef NDEBUG
m_init_phase = false;
#endif
}
void remove(osmium::object_id_type member_id, osmium::object_id_type relation_id) {
assert(!m_init_phase && "Call MembersDatabase::prepare_for_lookup() before calling remove().");
const auto range = find(member_id);
if (range.empty()) {
return;
}
// If this is the last time this object was needed, remove it
// from the stash.
if (count_not_removed(range) == 1) {
m_stash.remove_item(range.begin()->object_handle);
}
for (auto& elem : range) {
if (!elem.is_removed() && relation_id == m_relations_db[elem.relation_pos]->id()) {
elem.remove();
break;
}
}
}
const osmium::OSMObject* get_object(osmium::object_id_type id) const {
assert(!m_init_phase && "Call MembersDatabase::prepare_for_lookup() before calling get_object().");
const auto range = find(id);
if (range.empty()) {
return nullptr;
}
const auto handle = range.begin()->object_handle;
if (handle.valid()) {
return &m_stash.get<osmium::OSMObject>(handle);
}
return nullptr;
}
}; // class MembersDatabaseCommon
template <typename TObject>
class MembersDatabase : public MembersDatabaseCommon {
public:
MembersDatabase(osmium::ItemStash& stash, osmium::relations::RelationsDatabase& relation_db) :
MembersDatabaseCommon(stash, relation_db) {
}
template <typename TFunc>
bool add(const TObject& object, TFunc&& func) {
assert(!m_init_phase && "Call MembersDatabase::prepare_for_lookup() before calling add().");
auto range = find(object.id());
if (range.empty()) {
// No relation needs this object.
return false;
}
// At least one relation needs this object. Store it and
// "tell" all relations.
add_object(object, range);
for (auto& elem : range) {
assert(!elem.is_removed());
assert(elem.member_id == object.id());
auto rel_handle = m_relations_db[elem.relation_pos];
assert(elem.member_num < rel_handle->members().size());
rel_handle.decrement_members();
if (rel_handle.has_all_members()) {
std::forward<TFunc>(func)(rel_handle);
}
}
return true;
}
const TObject* get(osmium::object_id_type id) const {
assert(!m_init_phase && "Call MembersDatabase::prepare_for_lookup() before calling get().");
return static_cast<const TObject*>(get_object(id));
}
}; // class MembersDatabase
} // namespace relations
} // namespace osmium
#endif // OSMIUM_RELATIONS_MEMBERS_DATABASE_HPP
osmium::ItemStash::handle_type
Definition item_stash.hpp:71
osmium::ItemStash
Definition item_stash.hpp:57
osmium::OSMObject
Definition object.hpp:64
osmium::relations::MembersDatabaseCommon::prepare_for_lookup
void prepare_for_lookup()
Definition members_database.hpp:260
osmium::relations::MembersDatabaseCommon::m_elements
std::vector< element > m_elements
Definition members_database.hpp:139
osmium::relations::MembersDatabaseCommon::size
std::size_t size() const noexcept
Definition members_database.hpp:200
osmium::relations::MembersDatabaseCommon::track
void track(RelationHandle &rel_handle, osmium::object_id_type member_id, std::size_t member_num)
Definition members_database.hpp:247
osmium::relations::MembersDatabaseCommon::const_iterator
std::vector< element >::const_iterator const_iterator
Definition members_database.hpp:153
osmium::relations::MembersDatabaseCommon::m_init_phase
bool m_init_phase
Definition members_database.hpp:149
osmium::relations::MembersDatabaseCommon::count_not_removed
static std::iterator_traits< iterator >::difference_type count_not_removed(const iterator_range< iterator > &range) noexcept
Definition members_database.hpp:163
osmium::relations::MembersDatabaseCommon::get_object
const osmium::OSMObject * get_object(osmium::object_id_type id) const
Definition members_database.hpp:306
osmium::relations::MembersDatabaseCommon::m_relations_db
osmium::relations::RelationsDatabase & m_relations_db
Definition members_database.hpp:144
osmium::relations::MembersDatabaseCommon::remove
void remove(osmium::object_id_type member_id, osmium::object_id_type relation_id)
Definition members_database.hpp:274
osmium::relations::MembersDatabaseCommon::m_stash
osmium::ItemStash & m_stash
Definition members_database.hpp:143
osmium::relations::MembersDatabaseCommon::iterator
std::vector< element >::iterator iterator
Definition members_database.hpp:152
osmium::relations::MembersDatabaseCommon::MembersDatabaseCommon
MembersDatabaseCommon(osmium::ItemStash &stash, osmium::relations::RelationsDatabase &relations_db)
Definition members_database.hpp:176
osmium::relations::MembersDatabaseCommon::count
counts count() const noexcept
Definition members_database.hpp:222
osmium::relations::MembersDatabaseCommon::used_memory
std::size_t used_memory() const noexcept
Definition members_database.hpp:188
osmium::relations::MembersDatabaseCommon::add_object
void add_object(const osmium::OSMObject &object, iterator_range< iterator > &range)
Definition members_database.hpp:169
osmium::relations::MembersDatabaseCommon::find
iterator_range< const_iterator > find(osmium::object_id_type id) const
Definition members_database.hpp:159
osmium::relations::MembersDatabaseCommon::find
iterator_range< iterator > find(osmium::object_id_type id)
Definition members_database.hpp:155
osmium::relations::MembersDatabase::MembersDatabase
MembersDatabase(osmium::ItemStash &stash, osmium::relations::RelationsDatabase &relation_db)
Definition members_database.hpp:349
osmium::relations::MembersDatabase::get
const TObject * get(osmium::object_id_type id) const
Definition members_database.hpp:404
osmium::relations::MembersDatabase::add
bool add(const TObject &object, TFunc &&func)
Definition members_database.hpp:365
osmium::relations::RelationHandle
Definition relations_database.hpp:208
osmium::relations::RelationHandle::pos
std::size_t pos() const noexcept
Definition relations_database.hpp:238
osmium::relations::RelationHandle::relation_database
RelationsDatabase * relation_database() const noexcept
Definition relations_database.hpp:225
osmium::relations::RelationHandle::increment_members
void increment_members() noexcept
Definition relations_database.hpp:288
osmium::relations::RelationsDatabase
Definition relations_database.hpp:82
item_stash.hpp
iterator.hpp
osmium::relations
Code related to the assembly of OSM relations.
Definition multipolygon_collector.hpp:53
osmium
Namespace for everything in the Osmium library.
Definition assembler.hpp:53
osmium::make_range
iterator_range< It > make_range(P &&p) noexcept
Definition iterator.hpp:68
osmium::object_id_type
int64_t object_id_type
Type for OSM object (node, way, or relation) IDs.
Definition types.hpp:45
object.hpp
relation.hpp
relations_database.hpp
osmium::iterator_range
Definition iterator.hpp:42
osmium::relations::MembersDatabaseCommon::compare_member_id
Definition members_database.hpp:133
osmium::relations::MembersDatabaseCommon::compare_member_id::operator()
bool operator()(const element &a, const element &b) const noexcept
Definition members_database.hpp:134
osmium::relations::MembersDatabaseCommon::counts
Definition members_database.hpp:207
osmium::relations::MembersDatabaseCommon::counts::available
std::size_t available
The number of members tracked and found already.
Definition members_database.hpp:211
osmium::relations::MembersDatabaseCommon::counts::tracked
std::size_t tracked
The number of members tracked and not found yet.
Definition members_database.hpp:209
osmium::relations::MembersDatabaseCommon::counts::removed
std::size_t removed
The number of members that were tracked, found and then removed because of a completed relation.
Definition members_database.hpp:213
osmium::relations::MembersDatabaseCommon::element
Definition members_database.hpp:65
osmium::relations::MembersDatabaseCommon::element::is_removed
bool is_removed() const noexcept
Definition members_database.hpp:117
osmium::relations::MembersDatabaseCommon::element::remove
void remove() noexcept
Definition members_database.hpp:121
osmium::relations::MembersDatabaseCommon::element::element
element(std::size_t rel_pos, osmium::object_id_type memb_id, std::size_t memb_num) noexcept
Definition members_database.hpp:100
osmium::relations::MembersDatabaseCommon::element::element
element(osmium::object_id_type m_id) noexcept
Definition members_database.hpp:111
osmium::relations::MembersDatabaseCommon::element::relation_pos
std::size_t relation_pos
Definition members_database.hpp:90
osmium::relations::MembersDatabaseCommon::element::member_id
osmium::object_id_type member_id
Definition members_database.hpp:80
osmium::relations::MembersDatabaseCommon::element::operator<
bool operator<(const element &other) const noexcept
Definition members_database.hpp:125
osmium::relations::MembersDatabaseCommon::element::member_num
std::size_t member_num
Definition members_database.hpp:85
osmium::relations::MembersDatabaseCommon::element::removed_value
@ removed_value
Definition members_database.hpp:72
osmium::relations::MembersDatabaseCommon::element::object_handle
osmium::ItemStash::handle_type object_handle
Definition members_database.hpp:98
types.hpp