Skip to content

Commit 29c52d6

Browse files
committed
add support for --extra-attributes to Gazetteer output
1 parent 29a923c commit 29c52d6

File tree

3 files changed

+65
-1
lines changed

3 files changed

+65
-1
lines changed

gazetteer-style.cpp

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ void gazetteer_style_t::clear()
4242
m_main.clear();
4343
m_names.clear();
4444
m_extra.clear();
45+
m_metadata.clear();
4546
m_address.clear();
4647
m_operator = nullptr;
4748
m_admin_level = MAX_ADMINLEVEL;
@@ -72,6 +73,11 @@ void gazetteer_style_t::load_style(std::string const &filename)
7273
}
7374
}
7475

76+
void gazetteer_style_t::set_metadata(const bool enabled)
77+
{
78+
m_metadata_enabled = enabled;
79+
}
80+
7581
gazetteer_style_t::flag_t gazetteer_style_t::parse_flags(std::string const &str)
7682
{
7783
flag_t out = 0;
@@ -349,6 +355,45 @@ void gazetteer_style_t::process_tags(osmium::OSMObject const &o)
349355
} else if (postcode_fallback && postcode) {
350356
m_main.emplace_back("place", "postcode", SF_MAIN | SF_MAIN_FALLBACK);
351357
}
358+
359+
// add metadata fields as tags if enabled
360+
if (m_metadata_enabled) {
361+
if (o.version()) {
362+
add_metadata_field_num<osmium::object_version_type>("osm_version", o.version());
363+
}
364+
if (o.uid()) {
365+
add_metadata_field_num<osmium::user_id_type>("osm_uid", o.uid());
366+
}
367+
368+
if (o.user() && *(o.user()) != '\0') {
369+
std::string username = o.user();
370+
add_metadata_field("osm_user", std::move(username));
371+
}
372+
373+
if (o.changeset()) {
374+
add_metadata_field_num<osmium::changeset_id_type>("osm_changeset", o.changeset());
375+
}
376+
377+
if (o.timestamp()) {
378+
add_metadata_field("osm_timestamp", std::move(o.timestamp().to_iso()));
379+
}
380+
}
381+
}
382+
383+
void gazetteer_style_t::add_metadata_field(const std::string&& field, const std::string&& value) {
384+
// We have to work with std::string, not char* because metadata fields converted to char*
385+
// would require an allocation on heap and a cleanup at the end.
386+
flag_t flag = find_flag(field.c_str(), value.c_str());
387+
if (flag & SF_EXTRA) {
388+
m_metadata.emplace_back(std::move(field), std::move(value));
389+
}
390+
}
391+
392+
template <typename T>
393+
void gazetteer_style_t::add_metadata_field_num(const std::string&& field, const T value) {
394+
// This method is not linked to from outside this class. Therefore, it can stay in the source file.
395+
std::string value_str = std::to_string(value);
396+
add_metadata_field(std::move(field), std::move(value_str));
352397
}
353398

354399
void gazetteer_style_t::copy_out(osmium::OSMObject const &o,
@@ -456,13 +501,16 @@ bool gazetteer_style_t::copy_out_maintag(pmaintag_t const &tag,
456501
buffer.finish_hash();
457502
}
458503
// extra tags
459-
if (m_extra.empty()) {
504+
if (m_extra.empty() && m_metadata.empty()) {
460505
buffer.add_null_column();
461506
} else {
462507
buffer.new_hash();
463508
for (auto const &entry : m_extra) {
464509
buffer.add_hash_elem(entry.first, entry.second);
465510
}
511+
for (auto const &entry : m_metadata) {
512+
buffer.add_hash_elem(entry.first, entry.second);
513+
}
466514
buffer.finish_hash();
467515
}
468516
// add the geometry - encoding it to hex along the way

gazetteer-style.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class gazetteer_style_t
1414
{
1515
using flag_t = uint16_t;
1616
using ptag_t = std::pair<char const *, char const *>;
17+
using ptag_str_t = std::pair<const std::string, const std::string>;
1718
using pmaintag_t = std::tuple<char const *, char const *, flag_t>;
1819

1920
enum style_flags
@@ -66,11 +67,17 @@ class gazetteer_style_t
6667

6768
bool has_data() const { return !m_main.empty(); }
6869

70+
void set_metadata(const bool enabled);
71+
6972
private:
7073
void add_style_entry(std::string const &key, std::string const &value,
7174
flag_t flags);
7275
flag_t parse_flags(std::string const &str);
7376
flag_t find_flag(char const *k, char const *v) const;
77+
void add_metadata_field(const std::string&& field, const std::string&& value);
78+
79+
template <typename T>
80+
void add_metadata_field_num(const std::string&& field, const T value);
7481
bool copy_out_maintag(pmaintag_t const &tag, osmium::OSMObject const &o,
7582
std::string const &geom, db_copy_mgr_t &buffer);
7683
void clear();
@@ -88,6 +95,8 @@ class gazetteer_style_t
8895
std::vector<ptag_t> m_names;
8996
/// extratags to include
9097
std::vector<ptag_t> m_extra;
98+
/// metadata fields to include
99+
std::vector<ptag_str_t> m_metadata;
91100
/// addresstags to include
92101
std::vector<ptag_t> m_address;
93102
/// value of operator tag
@@ -96,6 +105,11 @@ class gazetteer_style_t
96105
int m_admin_level;
97106
/// True if there is an actual name to the object (not a ref).
98107
bool m_is_named;
108+
109+
/// enable writing of metadata as tags (osm_version, osm_timestamp, osm_uid, osm_user, osm_changeset)
110+
bool m_metadata_enabled {false};
111+
112+
boost::format m_single_fmt{"%1%\t"};
99113
};
100114

101115
#endif

output-gazetteer.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "pgsql.hpp"
1616
#include "util.hpp"
1717

18+
1819
class output_gazetteer_t : public output_t
1920
{
2021
output_gazetteer_t(output_gazetteer_t const *other,
@@ -37,6 +38,7 @@ class output_gazetteer_t : public output_t
3738
osmium_buffer(PLACE_BUFFER_SIZE, osmium::memory::Buffer::auto_grow::yes)
3839
{
3940
m_style.load_style(options.style);
41+
m_style.set_metadata(options.extra_attributes);
4042
}
4143

4244
virtual ~output_gazetteer_t();

0 commit comments

Comments
 (0)