Libosmium  2.7.1
Fast and flexible C++ library for working with OpenStreetMap data
osm_object_builder.hpp
Go to the documentation of this file.
1 #ifndef OSMIUM_BUILDER_OSM_OBJECT_BUILDER_HPP
2 #define OSMIUM_BUILDER_OSM_OBJECT_BUILDER_HPP
3 
4 /*
5 
6 This file is part of Osmium (http://osmcode.org/libosmium).
7 
8 Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
9 
10 Boost Software License - Version 1.0 - August 17th, 2003
11 
12 Permission is hereby granted, free of charge, to any person or organization
13 obtaining a copy of the software and accompanying documentation covered by
14 this license (the "Software") to use, reproduce, display, distribute,
15 execute, and transmit the Software, and to prepare derivative works of the
16 Software, and to permit third-parties to whom the Software is furnished to
17 do so, all subject to the following:
18 
19 The copyright notices in the Software and this entire statement, including
20 the above license grant, this restriction and the following disclaimer,
21 must be included in all copies of the Software, in whole or in part, and
22 all derivative works of the Software, unless such copies or derivative
23 works are solely in the form of machine-executable object code generated by
24 a source language processor.
25 
26 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
29 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
30 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
31 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
32 DEALINGS IN THE SOFTWARE.
33 
34 */
35 
36 #include <cassert>
37 #include <cstddef>
38 #include <cstring>
39 #include <initializer_list>
40 #include <limits>
41 #include <new>
42 #include <stdexcept>
43 #include <string>
44 #include <utility>
45 
47 #include <osmium/osm.hpp>
48 #include <osmium/osm/item_type.hpp>
49 #include <osmium/osm/location.hpp>
50 #include <osmium/osm/node_ref.hpp>
51 #include <osmium/osm/object.hpp>
52 #include <osmium/osm/tag.hpp>
53 #include <osmium/osm/types.hpp>
54 
55 namespace osmium {
56 
57  namespace memory {
58  class Buffer;
59  } // namespace memory
60 
61  namespace builder {
62 
63  class TagListBuilder : public ObjectBuilder<TagList> {
64 
65  public:
66 
67  explicit TagListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
68  ObjectBuilder<TagList>(buffer, parent) {
69  }
70 
72  add_padding();
73  }
74 
81  void add_tag(const char* key, const char* value) {
82  if (std::strlen(key) > osmium::max_osm_string_length) {
83  throw std::length_error("OSM tag key is too long");
84  }
85  if (std::strlen(value) > osmium::max_osm_string_length) {
86  throw std::length_error("OSM tag value is too long");
87  }
88  add_size(append(key) + append(value));
89  }
90 
99  void add_tag(const char* key, const size_t key_length, const char* value, const size_t value_length) {
100  if (key_length > osmium::max_osm_string_length) {
101  throw std::length_error("OSM tag key is too long");
102  }
103  if (value_length > osmium::max_osm_string_length) {
104  throw std::length_error("OSM tag value is too long");
105  }
106  add_size(append(key, osmium::memory::item_size_type(key_length)) + append_zero() +
107  append(value, osmium::memory::item_size_type(value_length)) + append_zero());
108  }
109 
116  void add_tag(const std::string& key, const std::string& value) {
117  if (key.size() > osmium::max_osm_string_length) {
118  throw std::length_error("OSM tag key is too long");
119  }
120  if (value.size() > osmium::max_osm_string_length) {
121  throw std::length_error("OSM tag value is too long");
122  }
123  add_size(append(key.data(), osmium::memory::item_size_type(key.size()) + 1) +
124  append(value.data(), osmium::memory::item_size_type(value.size()) + 1));
125  }
126 
132  void add_tag(const osmium::Tag& tag) {
133  add_size(append(tag.key()) + append(tag.value()));
134  }
135 
141  void add_tag(const std::pair<const char* const, const char* const>& tag) {
142  add_tag(tag.first, tag.second);
143  }
144  void add_tag(const std::pair<const char* const, const char*>& tag) {
145  add_tag(tag.first, tag.second);
146  }
147  void add_tag(const std::pair<const char*, const char* const>& tag) {
148  add_tag(tag.first, tag.second);
149  }
150  void add_tag(const std::pair<const char*, const char*>& tag) {
151  add_tag(tag.first, tag.second);
152  }
153 
159  void add_tag(const std::pair<const std::string&, const std::string&>& tag) {
160  add_tag(tag.first, tag.second);
161  }
162 
163  }; // class TagListBuilder
164 
165  template <typename T>
166  class NodeRefListBuilder : public ObjectBuilder<T> {
167 
168  public:
169 
170  explicit NodeRefListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
171  ObjectBuilder<T>(buffer, parent) {
172  }
173 
175  static_cast<Builder*>(this)->add_padding();
176  }
177 
178  void add_node_ref(const NodeRef& node_ref) {
179  new (static_cast<Builder*>(this)->reserve_space_for<osmium::NodeRef>()) osmium::NodeRef(node_ref);
180  static_cast<Builder*>(this)->add_size(sizeof(osmium::NodeRef));
181  }
182 
183  void add_node_ref(const object_id_type ref, const osmium::Location& location = Location{}) {
184  add_node_ref(NodeRef(ref, location));
185  }
186 
187  }; // class NodeRefListBuilder
188 
192 
193  class RelationMemberListBuilder : public ObjectBuilder<RelationMemberList> {
194 
204  void add_role(osmium::RelationMember& member, const char* role, const size_t length) {
205  if (length > osmium::max_osm_string_length) {
206  throw std::length_error("OSM relation member role is too long");
207  }
208  member.set_role_size(osmium::string_size_type(length) + 1);
209  add_size(append(role, osmium::memory::item_size_type(length)) + append_zero());
210  add_padding(true);
211  }
212 
213  public:
214 
215  explicit RelationMemberListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
216  ObjectBuilder<RelationMemberList>(buffer, parent) {
217  }
218 
220  add_padding();
221  }
222 
236  void add_member(osmium::item_type type, object_id_type ref, const char* role, const size_t role_length, const osmium::OSMObject* full_member = nullptr) {
237  osmium::RelationMember* member = reserve_space_for<osmium::RelationMember>();
238  new (member) osmium::RelationMember(ref, type, full_member != nullptr);
239  add_size(sizeof(RelationMember));
240  add_role(*member, role, role_length);
241  if (full_member) {
242  add_item(full_member);
243  }
244  }
245 
257  void add_member(osmium::item_type type, object_id_type ref, const char* role, const osmium::OSMObject* full_member = nullptr) {
258  add_member(type, ref, role, std::strlen(role), full_member);
259  }
260 
272  void add_member(osmium::item_type type, object_id_type ref, const std::string& role, const osmium::OSMObject* full_member = nullptr) {
273  add_member(type, ref, role.data(), role.size(), full_member);
274  }
275 
276  }; // class RelationMemberListBuilder
277 
278  class ChangesetDiscussionBuilder : public ObjectBuilder<ChangesetDiscussion> {
279 
280  osmium::ChangesetComment* m_comment = nullptr;
281 
282  void add_user(osmium::ChangesetComment& comment, const char* user, const size_t length) {
283  if (length > osmium::max_osm_string_length) {
284  throw std::length_error("OSM user name is too long");
285  }
286  comment.set_user_size(osmium::string_size_type(length) + 1);
287  add_size(append(user, osmium::memory::item_size_type(length)) + append_zero());
288  }
289 
290  void add_text(osmium::ChangesetComment& comment, const char* text, const size_t length) {
291  // XXX There is no limit on the length of a comment text. We
292  // limit it here to 2^16-2 characters, because that's all that
293  // will fit into our internal data structure. This is not ideal,
294  // and will have to be discussed and cleared up.
295  if (length > std::numeric_limits<osmium::string_size_type>::max() - 1) {
296  throw std::length_error("OSM changeset comment is too long");
297  }
298  comment.set_text_size(osmium::string_size_type(length) + 1);
299  add_size(append(text, osmium::memory::item_size_type(length)) + append_zero());
300  add_padding(true);
301  }
302 
303  public:
304 
305  explicit ChangesetDiscussionBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
306  ObjectBuilder<ChangesetDiscussion>(buffer, parent) {
307  }
308 
310  assert(!m_comment && "You have to always call both add_comment() and then add_comment_text() in that order for each comment!");
311  add_padding();
312  }
313 
314  void add_comment(osmium::Timestamp date, osmium::user_id_type uid, const char* user) {
315  assert(!m_comment && "You have to always call both add_comment() and then add_comment_text() in that order for each comment!");
316  m_comment = reserve_space_for<osmium::ChangesetComment>();
317  new (m_comment) osmium::ChangesetComment(date, uid);
318  add_size(sizeof(ChangesetComment));
319  add_user(*m_comment, user, std::strlen(user));
320  }
321 
322  void add_comment_text(const char* text) {
323  assert(m_comment && "You have to always call both add_comment() and then add_comment_text() in that order for each comment!");
324  add_text(*m_comment, text, std::strlen(text));
325  m_comment = nullptr;
326  }
327 
328  void add_comment_text(const std::string& text) {
329  assert(m_comment && "You have to always call both add_comment() and then add_comment_text() in that order for each comment!");
330  add_text(*m_comment, text.c_str(), text.size());
331  m_comment = nullptr;
332  }
333 
334  }; // class ChangesetDiscussionBuilder
335 
336  template <typename T>
337  class OSMObjectBuilder : public ObjectBuilder<T> {
338 
339  public:
340 
341  explicit OSMObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
342  ObjectBuilder<T>(buffer, parent) {
343  static_cast<Builder*>(this)->reserve_space_for<string_size_type>();
344  static_cast<Builder*>(this)->add_size(sizeof(string_size_type));
345  }
346 
347  void add_tags(const std::initializer_list<std::pair<const char*, const char*>>& tags) {
348  osmium::builder::TagListBuilder tl_builder(static_cast<Builder*>(this)->buffer(), this);
349  for (const auto& p : tags) {
350  tl_builder.add_tag(p.first, p.second);
351  }
352  }
353 
354  }; // class OSMObjectBuilder
355 
358 
359  class WayBuilder : public OSMObjectBuilder<osmium::Way> {
360 
361  public:
362 
363  explicit WayBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
364  OSMObjectBuilder<osmium::Way>(buffer, parent) {
365  }
366 
367  void add_node_refs(const std::initializer_list<osmium::NodeRef>& nodes) {
368  osmium::builder::WayNodeListBuilder builder(buffer(), this);
369  for (const auto& node_ref : nodes) {
370  builder.add_node_ref(node_ref);
371  }
372  }
373 
374  }; // class WayBuilder
375 
376  class AreaBuilder : public OSMObjectBuilder<osmium::Area> {
377 
378  public:
379 
380  explicit AreaBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
381  OSMObjectBuilder<osmium::Area>(buffer, parent) {
382  }
383 
388  osmium::Area& area = object();
389  area.set_id(osmium::object_id_to_area_id(source.id(), source.type()));
390  area.set_version(source.version());
391  area.set_changeset(source.changeset());
392  area.set_timestamp(source.timestamp());
393  area.set_visible(source.visible());
394  area.set_uid(source.uid());
395 
396  add_user(source.user());
397  }
398 
399  }; // class AreaBuilder
400 
402 
403  } // namespace builder
404 
405 } // namespace osmium
406 
407 #endif // OSMIUM_BUILDER_OSM_OBJECT_BUILDER_HPP
void add_tag(const std::pair< const char *const, const char *const > &tag)
Definition: osm_object_builder.hpp:141
uint32_t user_id_type
Type for OSM user IDs.
Definition: types.hpp:49
Definition: tag.hpp:49
Definition: osm_object_builder.hpp:337
~TagListBuilder()
Definition: osm_object_builder.hpp:71
Definition: changeset.hpp:128
Definition: tag.hpp:106
type
Definition: entity_bits.hpp:63
OSMObject & set_timestamp(const osmium::Timestamp &timestamp) noexcept
Definition: object.hpp:286
uint32_t item_size_type
Definition: item.hpp:50
const char * value() const
Definition: tag.hpp:84
WayBuilder(osmium::memory::Buffer &buffer, Builder *parent=nullptr)
Definition: osm_object_builder.hpp:363
AreaBuilder(osmium::memory::Buffer &buffer, Builder *parent=nullptr)
Definition: osm_object_builder.hpp:380
void add_user(osmium::ChangesetComment &comment, const char *user, const size_t length)
Definition: osm_object_builder.hpp:282
void add_member(osmium::item_type type, object_id_type ref, const char *role, const osmium::OSMObject *full_member=nullptr)
Definition: osm_object_builder.hpp:257
void initialize_from_object(const osmium::OSMObject &source)
Definition: osm_object_builder.hpp:387
item_type
Definition: item_type.hpp:43
void add_tag(const osmium::Tag &tag)
Definition: osm_object_builder.hpp:132
uint16_t string_size_type
Definition: types.hpp:59
~RelationMemberListBuilder()
Definition: osm_object_builder.hpp:219
Definition: area.hpp:114
Definition: relation.hpp:148
OSMObject & set_id(object_id_type id) noexcept
Definition: object.hpp:126
Definition: way.hpp:65
RelationMemberListBuilder(osmium::memory::Buffer &buffer, Builder *parent=nullptr)
Definition: osm_object_builder.hpp:215
Definition: changeset.hpp:57
Definition: osm_object_builder.hpp:278
osmium::object_id_type object_id_to_area_id(osmium::object_id_type id, osmium::item_type type) noexcept
Definition: area.hpp:93
void add_text(osmium::ChangesetComment &comment, const char *text, const size_t length)
Definition: osm_object_builder.hpp:290
Definition: osm_object_builder.hpp:166
void add_tag(const std::pair< const std::string &, const std::string & > &tag)
Definition: osm_object_builder.hpp:159
void add_tag(const char *key, const size_t key_length, const char *value, const size_t value_length)
Definition: osm_object_builder.hpp:99
Definition: relation.hpp:54
void add_tag(const std::pair< const char *const, const char * > &tag)
Definition: osm_object_builder.hpp:144
Namespace for everything in the Osmium library.
Definition: assembler.hpp:66
void add_tags(const std::initializer_list< std::pair< const char *, const char * >> &tags)
Definition: osm_object_builder.hpp:347
void add_node_refs(const std::initializer_list< osmium::NodeRef > &nodes)
Definition: osm_object_builder.hpp:367
void add_comment(osmium::Timestamp date, osmium::user_id_type uid, const char *user)
Definition: osm_object_builder.hpp:314
Definition: timestamp.hpp:56
OSMObjectBuilder(osmium::memory::Buffer &buffer, Builder *parent=nullptr)
Definition: osm_object_builder.hpp:341
void add_tag(const std::pair< const char *, const char * > &tag)
Definition: osm_object_builder.hpp:150
int64_t object_id_type
Type for OSM object (node, way, or relation) IDs.
Definition: types.hpp:45
user_id_type uid() const noexcept
Get user id of this object.
Definition: object.hpp:236
changeset_id_type changeset() const noexcept
Get changeset id of this object.
Definition: object.hpp:212
OSMObject & set_changeset(changeset_id_type changeset) noexcept
Definition: object.hpp:221
void add_member(osmium::item_type type, object_id_type ref, const char *role, const size_t role_length, const osmium::OSMObject *full_member=nullptr)
Definition: osm_object_builder.hpp:236
void add_tag(const std::pair< const char *, const char *const > &tag)
Definition: osm_object_builder.hpp:147
Definition: location.hpp:80
Definition: osm_object_builder.hpp:359
void set_text_size(string_size_type size) noexcept
Definition: changeset.hpp:95
object_id_type id() const noexcept
Get ID of this object.
Definition: object.hpp:112
OSMObject & set_version(object_version_type version) noexcept
Definition: object.hpp:197
object_version_type version() const noexcept
Get version of this object.
Definition: object.hpp:188
void set_role_size(string_size_type size) noexcept
Definition: relation.hpp:94
void add_member(osmium::item_type type, object_id_type ref, const std::string &role, const osmium::OSMObject *full_member=nullptr)
Definition: osm_object_builder.hpp:272
void add_user(TBuilder &builder, const TArgs &...args)
Definition: attr.hpp:584
NodeRefListBuilder(osmium::memory::Buffer &buffer, Builder *parent=nullptr)
Definition: osm_object_builder.hpp:170
void add_comment_text(const char *text)
Definition: osm_object_builder.hpp:322
Definition: buffer.hpp:97
const char * key() const noexcept
Definition: tag.hpp:80
Definition: builder.hpp:186
void set_user_size(string_size_type size) noexcept
Definition: changeset.hpp:91
OSMObject & set_visible(bool visible) noexcept
Definition: object.hpp:165
~NodeRefListBuilder()
Definition: osm_object_builder.hpp:174
void add_comment_text(const std::string &text)
Definition: osm_object_builder.hpp:328
bool visible() const noexcept
Is this object marked visible (ie not deleted)?
Definition: object.hpp:146
void add_role(osmium::RelationMember &member, const char *role, const size_t length)
Definition: osm_object_builder.hpp:204
void add_node_ref(const object_id_type ref, const osmium::Location &location=Location{})
Definition: osm_object_builder.hpp:183
~ChangesetDiscussionBuilder()
Definition: osm_object_builder.hpp:309
void add_tag(const std::string &key, const std::string &value)
Definition: osm_object_builder.hpp:116
node, way, relation, or area object
Definition: entity_bits.hpp:72
Definition: node_ref.hpp:50
const char * user() const noexcept
Get user name for this object.
Definition: object.hpp:292
item_type type() const noexcept
Definition: item.hpp:155
osmium::Timestamp timestamp() const noexcept
Get timestamp when this object last changed.
Definition: object.hpp:276
OSMObject & set_uid(user_id_type uid) noexcept
Definition: object.hpp:245
Definition: builder.hpp:57
Definition: osm_object_builder.hpp:193
constexpr const int max_osm_string_length
Definition: types.hpp:62
TagListBuilder(osmium::memory::Buffer &buffer, Builder *parent=nullptr)
Definition: osm_object_builder.hpp:67
void add_tag(const char *key, const char *value)
Definition: osm_object_builder.hpp:81
ChangesetDiscussionBuilder(osmium::memory::Buffer &buffer, Builder *parent=nullptr)
Definition: osm_object_builder.hpp:305
Definition: object.hpp:60
Definition: osm_object_builder.hpp:63
void add_node_ref(const NodeRef &node_ref)
Definition: osm_object_builder.hpp:178
Definition: osm_object_builder.hpp:376