1 /**
2 * SPDX-License-Identifier: GPL-2.0-or-later
3 *
4 * This file is part of osm2pgsql (https://osm2pgsql.org/).
5 *
6 * Copyright (C) 2006-2021 by the osm2pgsql developer community.
7 * For a full list of authors see the git log.
8 */
9
10 #include "node-locations.hpp"
11
12 // Workaround: This must be included before buffer_string.hpp due to a missing
13 // include in the upstream code. https://github.com/mapbox/protozero/pull/104
14 #include <protozero/config.hpp>
15
16 #include <protozero/buffer_string.hpp>
17 #include <protozero/varint.hpp>
18
19 #include <cassert>
20
set(osmid_t id,osmium::Location location)21 bool node_locations_t::set(osmid_t id, osmium::Location location)
22 {
23 if (used_memory() >= m_max_size && will_resize()) {
24 return false;
25 }
26
27 if (first_entry_in_block()) {
28 m_did.clear();
29 m_dx.clear();
30 m_dy.clear();
31 m_index.add(id, m_data.size());
32 }
33
34 auto const delta = m_did.update(id);
35 // Always true because ids in input must be unique and ordered
36 assert(delta > 0);
37 protozero::add_varint_to_buffer(&m_data, static_cast<uint64_t>(delta));
38
39 protozero::add_varint_to_buffer(
40 &m_data, protozero::encode_zigzag64(m_dx.update(location.x())));
41 protozero::add_varint_to_buffer(
42 &m_data, protozero::encode_zigzag64(m_dy.update(location.y())));
43
44 ++m_count;
45
46 return true;
47 }
48
get(osmid_t id) const49 osmium::Location node_locations_t::get(osmid_t id) const
50 {
51 auto const offset = m_index.get_block(id);
52 if (offset == ordered_index_t::not_found_value()) {
53 return osmium::Location{};
54 }
55
56 assert(offset < m_data.size());
57
58 char const *begin = m_data.data() + offset;
59 char const *const end = m_data.data() + m_data.size();
60
61 osmium::DeltaDecode<osmid_t> did;
62 osmium::DeltaDecode<int64_t> dx;
63 osmium::DeltaDecode<int64_t> dy;
64
65 for (std::size_t n = 0; n < block_size && begin != end; ++n) {
66 auto const bid = did.update(
67 static_cast<int64_t>(protozero::decode_varint(&begin, end)));
68 int32_t const x = dx.update(
69 protozero::decode_zigzag64(protozero::decode_varint(&begin, end)));
70 int32_t const y = dy.update(
71 protozero::decode_zigzag64(protozero::decode_varint(&begin, end)));
72 if (bid == id) {
73 return osmium::Location{x, y};
74 }
75 if (bid > id) {
76 break;
77 }
78 }
79 return osmium::Location{};
80 }
81
clear()82 void node_locations_t::clear()
83 {
84 m_data.clear();
85 m_data.shrink_to_fit();
86 m_index.clear();
87 m_count = 0;
88 }
89