Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor idlist #2151

Merged
merged 8 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ target_sources(osm2pgsql_lib PRIVATE
geom-from-osm.cpp
geom-functions.cpp
geom-pole-of-inaccessibility.cpp
idlist.cpp
input.cpp
logging.cpp
middle.cpp
Expand Down
44 changes: 6 additions & 38 deletions src/dependency-manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@

void full_dependency_manager_t::node_changed(osmid_t id)
{
m_changed_nodes.set(id);
m_changed_nodes.push_back(id);
}

void full_dependency_manager_t::way_changed(osmid_t id)
{
m_changed_ways.set(id);
m_changed_ways.push_back(id);
}

void full_dependency_manager_t::relation_changed(osmid_t id)
{
m_changed_relations.set(id);
m_changed_relations.push_back(id);
}

void full_dependency_manager_t::after_nodes()
Expand All @@ -39,29 +39,13 @@ void full_dependency_manager_t::after_nodes()
m_changed_nodes.clear();
}

static osmium::index::IdSetSmall<osmid_t>
set_diff(osmium::index::IdSetSmall<osmid_t> const &set,
osmium::index::IdSetSmall<osmid_t> const &to_be_removed)
{
osmium::index::IdSetSmall<osmid_t> new_set;

for (auto const id : set) {
if (!to_be_removed.get_binary_search(id)) {
new_set.set(id);
}
}

return new_set;
}

void full_dependency_manager_t::after_ways()
{
if (!m_changed_ways.empty()) {
if (!m_ways_pending_tracker.empty()) {
// Remove ids from changed ways in the input data from
// m_ways_pending_tracker, because they have already been processed.
m_ways_pending_tracker =
set_diff(m_ways_pending_tracker, m_changed_ways);
m_ways_pending_tracker.remove_ids_if_in(m_changed_ways);

// Add the list of pending way ids to the list of changed ways,
// because we need the parents for them, too.
Expand All @@ -85,14 +69,13 @@ void full_dependency_manager_t::after_relations()
{
// Remove ids from changed relations in the input data from
// m_rels_pending_tracker, because they have already been processed.
m_rels_pending_tracker =
set_diff(m_rels_pending_tracker, m_changed_relations);
m_rels_pending_tracker.remove_ids_if_in(m_changed_relations);

m_changed_relations.clear();
}

void full_dependency_manager_t::mark_parent_relations_as_pending(
osmium::index::IdSetSmall<osmid_t> const &way_ids)
idlist_t const &way_ids)
{
assert(m_rels_pending_tracker.empty());
m_object_store->get_way_parents(way_ids, &m_rels_pending_tracker);
Expand All @@ -102,18 +85,3 @@ bool full_dependency_manager_t::has_pending() const noexcept
{
return !m_ways_pending_tracker.empty() || !m_rels_pending_tracker.empty();
}

idlist_t
full_dependency_manager_t::get_ids(osmium::index::IdSetSmall<osmid_t> *tracker)
{
tracker->sort_unique();

idlist_t list;
list.reserve(tracker->size());

std::copy(tracker->cbegin(), tracker->cend(), std::back_inserter(list));

tracker->clear();

return list;
}
33 changes: 18 additions & 15 deletions src/dependency-manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@
* For a full list of authors see the git log.
*/

#include "idlist.hpp"
#include "osmtypes.hpp"

#include <osmium/index/id_set.hpp>

#include <cassert>
#include <memory>
#include <utility>
Expand Down Expand Up @@ -58,8 +57,7 @@ class dependency_manager_t
virtual void after_ways() {}
virtual void after_relations() {}

virtual void mark_parent_relations_as_pending(
osmium::index::IdSetSmall<osmid_t> const & /*way_ids*/)
virtual void mark_parent_relations_as_pending(idlist_t const & /*way_ids*/)
{
}

Expand Down Expand Up @@ -111,24 +109,29 @@ class full_dependency_manager_t : public dependency_manager_t
void after_ways() override;
void after_relations() override;

void mark_parent_relations_as_pending(
osmium::index::IdSetSmall<osmid_t> const &ids) override;
void mark_parent_relations_as_pending(idlist_t const &ids) override;

bool has_pending() const noexcept override;

idlist_t get_pending_way_ids() override
{
return get_ids(&m_ways_pending_tracker);
idlist_t list;
using std::swap;
swap(list, m_ways_pending_tracker);
list.sort_unique();
return list;
}

idlist_t get_pending_relation_ids() override
{
return get_ids(&m_rels_pending_tracker);
idlist_t list;
using std::swap;
swap(list, m_rels_pending_tracker);
list.sort_unique();
return list;
}

private:
static idlist_t get_ids(osmium::index::IdSetSmall<osmid_t> *tracker);

std::shared_ptr<middle_t> m_object_store;

/**
Expand All @@ -139,7 +142,7 @@ class full_dependency_manager_t : public dependency_manager_t
* the change file, too, and so we don't have to find out which ones they
* are.
*/
osmium::index::IdSetSmall<osmid_t> m_changed_nodes;
idlist_t m_changed_nodes;

/**
* In append mode all new and changed ways will be added to this. After
Expand All @@ -148,17 +151,17 @@ class full_dependency_manager_t : public dependency_manager_t
* relations that referenced deleted ways must be in the change file, too,
* and so we don't have to find out which ones they are.
*/
osmium::index::IdSetSmall<osmid_t> m_changed_ways;
idlist_t m_changed_ways;

/**
* In append mode all new and changed relations will be added to this.
* This is then used to remove already processed relations from the
* pending list.
*/
osmium::index::IdSetSmall<osmid_t> m_changed_relations;
idlist_t m_changed_relations;

osmium::index::IdSetSmall<osmid_t> m_ways_pending_tracker;
osmium::index::IdSetSmall<osmid_t> m_rels_pending_tracker;
idlist_t m_ways_pending_tracker;
idlist_t m_rels_pending_tracker;
};

#endif // OSM2PGSQL_DEPENDENCY_MANAGER_HPP
54 changes: 54 additions & 0 deletions src/idlist.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* SPDX-License-Identifier: GPL-2.0-or-later
*
* This file is part of osm2pgsql (https://osm2pgsql.org/).
*
* Copyright (C) 2006-2023 by the osm2pgsql developer community.
* For a full list of authors see the git log.
*/

#include "idlist.hpp"

#include <algorithm>
#include <cassert>
#include <iterator>
#include <utility>

osmid_t idlist_t::pop_id()
{
assert(!m_list.empty());
auto const id = m_list.back();
m_list.pop_back();
return id;
}

void idlist_t::sort_unique()
{
std::sort(m_list.begin(), m_list.end());
const auto last = std::unique(m_list.begin(), m_list.end());
m_list.erase(last, m_list.end());
}

void idlist_t::merge_sorted(idlist_t const &other)
{
std::vector<osmid_t> new_list;

new_list.reserve(m_list.size() + other.m_list.size());
std::set_union(m_list.cbegin(), m_list.cend(), other.m_list.cbegin(),
other.m_list.cend(), std::back_inserter(new_list));

using std::swap;
swap(new_list, m_list);
}

void idlist_t::remove_ids_if_in(idlist_t const &other)
{
std::vector<osmid_t> new_list;

new_list.reserve(m_list.size());
std::set_difference(m_list.cbegin(), m_list.cend(), other.m_list.cbegin(),
other.m_list.cend(), std::back_inserter(new_list));

using std::swap;
swap(new_list, m_list);
}
107 changes: 107 additions & 0 deletions src/idlist.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#ifndef OSM2PGSQL_IDLIST_HPP
#define OSM2PGSQL_IDLIST_HPP

/**
* SPDX-License-Identifier: GPL-2.0-or-later
*
* This file is part of osm2pgsql (https://osm2pgsql.org/).
*
* Copyright (C) 2006-2023 by the osm2pgsql developer community.
* For a full list of authors see the git log.
*/

/**
* \file
*
* This file contains the definition of the idlist_t class.
*/

#include "osmtypes.hpp"

#include <vector>

/**
* A list of OSM object ids. Internally this is a vector of ids.
*
* Some operations are only allowed when the list of ids is sorted and
* without duplicates. Call sort_unique() to achieve this.
*/
class idlist_t
{
public:
using value_type = osmid_t;

idlist_t() = default;
~idlist_t() noexcept = default;

idlist_t(std::initializer_list<osmid_t> ids) : m_list(ids) {}

idlist_t(idlist_t const &) = delete;
idlist_t &operator=(idlist_t const &) = delete;

idlist_t(idlist_t &&) = default;
idlist_t &operator=(idlist_t &&) = default;

bool empty() const noexcept { return m_list.empty(); }

std::size_t size() const noexcept { return m_list.size(); }

auto begin() const noexcept { return m_list.begin(); }

auto end() const noexcept { return m_list.end(); }

auto cbegin() const noexcept { return m_list.cbegin(); }

auto cend() const noexcept { return m_list.cend(); }

osmid_t operator[](std::size_t n) const noexcept { return m_list[n]; }

void clear() noexcept { m_list.clear(); }

void push_back(osmid_t id) { m_list.push_back(id); }

void reserve(std::size_t size) { m_list.reserve(size); }

/**
* Remove id at the end of the list and return it.
*
* \pre \code !m_list.empty()) \endcode
*/
osmid_t pop_id();

/// List are equal if they contain the same ids in the same order.
friend bool operator==(idlist_t const &lhs, idlist_t const &rhs) noexcept
{
return lhs.m_list == rhs.m_list;
}

friend bool operator!=(idlist_t const &lhs, idlist_t const &rhs) noexcept
{
return !(lhs == rhs);
}

/**
* Sort this list and remove duplicates.
*/
void sort_unique();

/**
* Merge other list into this one.
*
* \pre Both lists must be sorted and without duplicates.
*/
void merge_sorted(idlist_t const &other);

/**
* Remove all ids in this list that are also in the other list.
*
* \pre Both lists must be sorted and without duplicates.
*/
void remove_ids_if_in(idlist_t const &other);

private:
std::vector<osmid_t> m_list;

}; // class idlist_t

#endif // OSM2PGSQL_IDLIST_HPP
Loading