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