Skip to content

Commit b280c9e

Browse files
committed
remove necessity of --extra-attributes, use style only
1 parent 29c52d6 commit b280c9e

File tree

4 files changed

+84
-59
lines changed

4 files changed

+84
-59
lines changed

db-copy.hpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,41 @@ class db_copy_mgr_t
290290
m_current->buffer += "\",";
291291
}
292292

293+
/**
294+
* Add a key/value pair to a hash column without escaping.
295+
*
296+
* Key and value must be strings and will NOT be appropriately escaped.
297+
* A separator for the next pair is added at the end.
298+
*/
299+
void add_hash_elem_noescape(char const *k, char const *v)
300+
{
301+
m_current->buffer += '"';
302+
m_current->buffer += k;
303+
m_current->buffer += "\"=>\"";
304+
m_current->buffer += v;
305+
m_current->buffer += "\",";
306+
}
307+
308+
/**
309+
* Add a key (unescaped) and a numeric value to a hash column.
310+
*
311+
* Key must be string and come from a safe source because it will NOT be
312+
* escaped! The value should be convertible using std::to_string.
313+
* A separator for the next pair is added at the end.
314+
*
315+
* This method is suitable to insert safe input, e.g. numeric OSM metadata
316+
* (eg. uid) but not unsafe input like user names.
317+
*/
318+
template <typename T>
319+
void add_hstore_num_noescape(char const *k, T const value)
320+
{
321+
m_current->buffer += '"';
322+
m_current->buffer += k;
323+
m_current->buffer += "\"=>\"";
324+
m_current->buffer += std::to_string(value);
325+
m_current->buffer += "\",";
326+
}
327+
293328
/**
294329
* Close a hash previously started with new_hash().
295330
*

gazetteer-style.cpp

Lines changed: 44 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ void gazetteer_style_t::clear()
4242
m_main.clear();
4343
m_names.clear();
4444
m_extra.clear();
45-
m_metadata.clear();
4645
m_address.clear();
4746
m_operator = nullptr;
4847
m_admin_level = MAX_ADMINLEVEL;
@@ -73,11 +72,6 @@ void gazetteer_style_t::load_style(std::string const &filename)
7372
}
7473
}
7574

76-
void gazetteer_style_t::set_metadata(const bool enabled)
77-
{
78-
m_metadata_enabled = enabled;
79-
}
80-
8175
gazetteer_style_t::flag_t gazetteer_style_t::parse_flags(std::string const &str)
8276
{
8377
flag_t out = 0;
@@ -134,6 +128,25 @@ gazetteer_style_t::flag_t gazetteer_style_t::parse_flags(std::string const &str)
134128
return out;
135129
}
136130

131+
bool gazetteer_style_t::add_metadata_style_entry(std::string const &key,
132+
std::string const &value)
133+
{
134+
if (key == "osm_version") {
135+
m_metadata_fields.set_version(true);
136+
} else if (key == "osm_timestamp") {
137+
m_metadata_fields.set_timestamp(true);
138+
} else if (key == "osm_changeset") {
139+
m_metadata_fields.set_changeset(true);
140+
} else if (key == "osm_uid") {
141+
m_metadata_fields.set_uid(true);
142+
} else if (key == "osm_user") {
143+
m_metadata_fields.set_user(true);
144+
} else {
145+
return false;
146+
}
147+
return true;
148+
}
149+
137150
void gazetteer_style_t::add_style_entry(std::string const &key,
138151
std::string const &value,
139152
gazetteer_style_t::flag_t flags)
@@ -177,6 +190,13 @@ void gazetteer_style_t::add_style_entry(std::string const &key,
177190
}
178191
}
179192

193+
if (add_metadata_style_entry(key, value)) {
194+
if (!value.empty()) {
195+
throw std::runtime_error("Style error. Rules for OSM metadata "
196+
"attributes must have an empty value.\n");
197+
}
198+
return;
199+
}
180200
if (value.empty()) {
181201
m_matcher.emplace_back(key, flags, matcher_t::MT_KEY);
182202
} else {
@@ -355,45 +375,6 @@ void gazetteer_style_t::process_tags(osmium::OSMObject const &o)
355375
} else if (postcode_fallback && postcode) {
356376
m_main.emplace_back("place", "postcode", SF_MAIN | SF_MAIN_FALLBACK);
357377
}
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));
397378
}
398379

399380
void gazetteer_style_t::copy_out(osmium::OSMObject const &o,
@@ -501,15 +482,30 @@ bool gazetteer_style_t::copy_out_maintag(pmaintag_t const &tag,
501482
buffer.finish_hash();
502483
}
503484
// extra tags
504-
if (m_extra.empty() && m_metadata.empty()) {
485+
if (m_extra.empty() && m_metadata_fields.none()) {
505486
buffer.add_null_column();
506487
} else {
507488
buffer.new_hash();
508489
for (auto const &entry : m_extra) {
509490
buffer.add_hash_elem(entry.first, entry.second);
510491
}
511-
for (auto const &entry : m_metadata) {
512-
buffer.add_hash_elem(entry.first, entry.second);
492+
if (m_metadata_fields.version() && o.version()) {
493+
buffer.add_hstore_num_noescape<osmium::object_version_type>(
494+
"osm_version", o.version());
495+
}
496+
if (m_metadata_fields.uid() && o.uid()) {
497+
buffer.add_hstore_num_noescape<osmium::user_id_type>("osm_uid", o.uid());
498+
}
499+
if (m_metadata_fields.user() && o.user() && *(o.user()) != '\0') {
500+
buffer.add_hash_elem("osm_user", o.user());
501+
}
502+
if (m_metadata_fields.changeset() && o.changeset()) {
503+
buffer.add_hstore_num_noescape<osmium::changeset_id_type>(
504+
"osm_changeset", o.changeset());
505+
}
506+
if (m_metadata_fields.timestamp() && o.timestamp()) {
507+
std::string timestamp = o.timestamp().to_iso();
508+
buffer.add_hash_elem_noescape("osm_timestamp", timestamp.c_str());
513509
}
514510
buffer.finish_hash();
515511
}

gazetteer-style.hpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
#include <vector>
88

99
#include <boost/format.hpp>
10+
#include <osmium/osm/metadata_options.hpp>
1011

1112
#include "db-copy.hpp"
1213

1314
class gazetteer_style_t
1415
{
1516
using flag_t = uint16_t;
1617
using ptag_t = std::pair<char const *, char const *>;
17-
using ptag_str_t = std::pair<const std::string, const std::string>;
1818
using pmaintag_t = std::tuple<char const *, char const *, flag_t>;
1919

2020
enum style_flags
@@ -67,17 +67,14 @@ class gazetteer_style_t
6767

6868
bool has_data() const { return !m_main.empty(); }
6969

70-
void set_metadata(const bool enabled);
71-
7270
private:
71+
bool add_metadata_style_entry(std::string const &key,
72+
std::string const &value);
7373
void add_style_entry(std::string const &key, std::string const &value,
7474
flag_t flags);
7575
flag_t parse_flags(std::string const &str);
7676
flag_t find_flag(char const *k, char const *v) const;
77-
void add_metadata_field(const std::string&& field, const std::string&& value);
7877

79-
template <typename T>
80-
void add_metadata_field_num(const std::string&& field, const T value);
8178
bool copy_out_maintag(pmaintag_t const &tag, osmium::OSMObject const &o,
8279
std::string const &geom, db_copy_mgr_t &buffer);
8380
void clear();
@@ -95,8 +92,6 @@ class gazetteer_style_t
9592
std::vector<ptag_t> m_names;
9693
/// extratags to include
9794
std::vector<ptag_t> m_extra;
98-
/// metadata fields to include
99-
std::vector<ptag_str_t> m_metadata;
10095
/// addresstags to include
10196
std::vector<ptag_t> m_address;
10297
/// value of operator tag
@@ -106,8 +101,8 @@ class gazetteer_style_t
106101
/// True if there is an actual name to the object (not a ref).
107102
bool m_is_named;
108103

109-
/// enable writing of metadata as tags (osm_version, osm_timestamp, osm_uid, osm_user, osm_changeset)
110-
bool m_metadata_enabled {false};
104+
/// which metadata fields of the OSM objects should be written to the output
105+
osmium::metadata_options m_metadata_fields{"none"};
111106

112107
boost::format m_single_fmt{"%1%\t"};
113108
};

output-gazetteer.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ class output_gazetteer_t : public output_t
3838
osmium_buffer(PLACE_BUFFER_SIZE, osmium::memory::Buffer::auto_grow::yes)
3939
{
4040
m_style.load_style(options.style);
41-
m_style.set_metadata(options.extra_attributes);
4241
}
4342

4443
virtual ~output_gazetteer_t();

0 commit comments

Comments
 (0)