Libosmium  2.9.0
Fast and flexible C++ library for working with OpenStreetMap data
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 <cstring>
38 #include <initializer_list>
39 #include <limits>
40 #include <new>
41 #include <stdexcept>
42 #include <string>
43 #include <utility>
44 
46 #include <osmium/osm/item_type.hpp>
47 #include <osmium/osm/location.hpp>
48 #include <osmium/osm/node_ref.hpp>
49 #include <osmium/osm/object.hpp>
50 #include <osmium/osm/tag.hpp>
51 #include <osmium/osm/types.hpp>
52 #include <osmium/memory/item.hpp>
53 #include <osmium/osm/area.hpp>
54 #include <osmium/osm/changeset.hpp>
55 #include <osmium/osm/relation.hpp>
56 #include <osmium/osm/timestamp.hpp>
57 #include <osmium/osm/way.hpp>
58 
59 namespace osmium {
60 
61  class Node;
62 
63  namespace memory {
64  class Buffer;
65  } // namespace memory
66 
67  namespace builder {
68 
69  class TagListBuilder : public ObjectBuilder<TagList> {
70 
71  public:
72 
73  explicit TagListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
74  ObjectBuilder<TagList>(buffer, parent) {
75  }
76 
78  add_padding();
79  }
80 
87  void add_tag(const char* key, const char* value) {
88  if (std::strlen(key) > osmium::max_osm_string_length) {
89  throw std::length_error("OSM tag key is too long");
90  }
91  if (std::strlen(value) > osmium::max_osm_string_length) {
92  throw std::length_error("OSM tag value is too long");
93  }
94  add_size(append(key) + append(value));
95  }
96 
105  void add_tag(const char* key, const size_t key_length, const char* value, const size_t value_length) {
106  if (key_length > osmium::max_osm_string_length) {
107  throw std::length_error("OSM tag key is too long");
108  }
109  if (value_length > osmium::max_osm_string_length) {
110  throw std::length_error("OSM tag value is too long");
111  }
113  append(value, osmium::memory::item_size_type(value_length)) + append_zero());
114  }
115 
122  void add_tag(const std::string& key, const std::string& value) {
123  if (key.size() > osmium::max_osm_string_length) {
124  throw std::length_error("OSM tag key is too long");
125  }
126  if (value.size() > osmium::max_osm_string_length) {
127  throw std::length_error("OSM tag value is too long");
128  }
129  add_size(append(key.data(), osmium::memory::item_size_type(key.size()) + 1) +
130  append(value.data(), osmium::memory::item_size_type(value.size()) + 1));
131  }
132 
138  void add_tag(const osmium::Tag& tag) {
139  add_size(append(tag.key()) + append(tag.value()));
140  }
141 
147  void add_tag(const std::pair<const char* const, const char* const>& tag) {
148  add_tag(tag.first, tag.second);
149  }
150  void add_tag(const std::pair<const char* const, const char*>& tag) {
151  add_tag(tag.first, tag.second);
152  }
153  void add_tag(const std::pair<const char*, const char* const>& tag) {
154  add_tag(tag.first, tag.second);
155  }
156  void add_tag(const std::pair<const char*, const char*>& tag) {
157  add_tag(tag.first, tag.second);
158  }
159 
165  void add_tag(const std::pair<const std::string&, const std::string&>& tag) {
166  add_tag(tag.first, tag.second);
167  }
168 
169  }; // class TagListBuilder
170 
171  template <typename T>
172  class NodeRefListBuilder : public ObjectBuilder<T> {
173 
174  public:
175 
176  explicit NodeRefListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
177  ObjectBuilder<T>(buffer, parent) {
178  }
179 
181  static_cast<Builder*>(this)->add_padding();
182  }
183 
184  void add_node_ref(const NodeRef& node_ref) {
185  new (static_cast<Builder*>(this)->reserve_space_for<osmium::NodeRef>()) osmium::NodeRef(node_ref);
186  static_cast<Builder*>(this)->add_size(sizeof(osmium::NodeRef));
187  }
188 
189  void add_node_ref(const object_id_type ref, const osmium::Location& location = Location{}) {
190  add_node_ref(NodeRef(ref, location));
191  }
192 
193  }; // class NodeRefListBuilder
194 
198 
199  class RelationMemberListBuilder : public ObjectBuilder<RelationMemberList> {
200 
210  void add_role(osmium::RelationMember& member, const char* role, const size_t length) {
211  if (length > osmium::max_osm_string_length) {
212  throw std::length_error("OSM relation member role is too long");
213  }
214  member.set_role_size(osmium::string_size_type(length) + 1);
216  add_padding(true);
217  }
218 
219  public:
220 
222  ObjectBuilder<RelationMemberList>(buffer, parent) {
223  }
224 
226  add_padding();
227  }
228 
242  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) {
243  osmium::RelationMember* member = reserve_space_for<osmium::RelationMember>();
244  new (member) osmium::RelationMember(ref, type, full_member != nullptr);
245  add_size(sizeof(RelationMember));
246  add_role(*member, role, role_length);
247  if (full_member) {
248  add_item(full_member);
249  }
250  }
251 
263  void add_member(osmium::item_type type, object_id_type ref, const char* role, const osmium::OSMObject* full_member = nullptr) {
264  add_member(type, ref, role, std::strlen(role), full_member);
265  }
266 
278  void add_member(osmium::item_type type, object_id_type ref, const std::string& role, const osmium::OSMObject* full_member = nullptr) {
279  add_member(type, ref, role.data(), role.size(), full_member);
280  }
281 
282  }; // class RelationMemberListBuilder
283 
284  class ChangesetDiscussionBuilder : public ObjectBuilder<ChangesetDiscussion> {
285 
287 
288  void add_user(osmium::ChangesetComment& comment, const char* user, const size_t length) {
289  if (length > osmium::max_osm_string_length) {
290  throw std::length_error("OSM user name is too long");
291  }
292  comment.set_user_size(osmium::string_size_type(length) + 1);
294  }
295 
296  void add_text(osmium::ChangesetComment& comment, const char* text, const size_t length) {
297  // XXX There is no limit on the length of a comment text. We
298  // limit it here to 2^16-2 characters, because that's all that
299  // will fit into our internal data structure. This is not ideal,
300  // and will have to be discussed and cleared up.
301  if (length > std::numeric_limits<osmium::string_size_type>::max() - 1) {
302  throw std::length_error("OSM changeset comment is too long");
303  }
304  comment.set_text_size(osmium::string_size_type(length) + 1);
306  add_padding(true);
307  }
308 
309  public:
310 
312  ObjectBuilder<ChangesetDiscussion>(buffer, parent) {
313  }
314 
316  assert(!m_comment && "You have to always call both add_comment() and then add_comment_text() in that order for each comment!");
317  add_padding();
318  }
319 
320  void add_comment(osmium::Timestamp date, osmium::user_id_type uid, const char* user) {
321  assert(!m_comment && "You have to always call both add_comment() and then add_comment_text() in that order for each comment!");
322  m_comment = reserve_space_for<osmium::ChangesetComment>();
323  new (m_comment) osmium::ChangesetComment(date, uid);
324  add_size(sizeof(ChangesetComment));
325  add_user(*m_comment, user, std::strlen(user));
326  }
327 
328  void add_comment_text(const char* 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, std::strlen(text));
331  m_comment = nullptr;
332  }
333 
334  void add_comment_text(const std::string& text) {
335  assert(m_comment && "You have to always call both add_comment() and then add_comment_text() in that order for each comment!");
336  add_text(*m_comment, text.c_str(), text.size());
337  m_comment = nullptr;
338  }
339 
340  }; // class ChangesetDiscussionBuilder
341 
342  template <typename T>
343  class OSMObjectBuilder : public ObjectBuilder<T> {
344 
345  public:
346 
347  explicit OSMObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
348  ObjectBuilder<T>(buffer, parent) {
349  static_cast<Builder*>(this)->reserve_space_for<string_size_type>();
350  static_cast<Builder*>(this)->add_size(sizeof(string_size_type));
351  }
352 
353  void add_tags(const std::initializer_list<std::pair<const char*, const char*>>& tags) {
354  osmium::builder::TagListBuilder tl_builder(static_cast<Builder*>(this)->buffer(), this);
355  for (const auto& p : tags) {
356  tl_builder.add_tag(p.first, p.second);
357  }
358  }
359 
360  }; // class OSMObjectBuilder
361 
364 
365  class WayBuilder : public OSMObjectBuilder<osmium::Way> {
366 
367  public:
368 
369  explicit WayBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
370  OSMObjectBuilder<osmium::Way>(buffer, parent) {
371  }
372 
373  void add_node_refs(const std::initializer_list<osmium::NodeRef>& nodes) {
375  for (const auto& node_ref : nodes) {
376  builder.add_node_ref(node_ref);
377  }
378  }
379 
380  }; // class WayBuilder
381 
382  class AreaBuilder : public OSMObjectBuilder<osmium::Area> {
383 
384  public:
385 
386  explicit AreaBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
387  OSMObjectBuilder<osmium::Area>(buffer, parent) {
388  }
389 
394  osmium::Area& area = object();
395  area.set_id(osmium::object_id_to_area_id(source.id(), source.type()));
396  area.set_version(source.version());
397  area.set_changeset(source.changeset());
398  area.set_timestamp(source.timestamp());
399  area.set_visible(source.visible());
400  area.set_uid(source.uid());
401 
402  add_user(source.user());
403  }
404 
405  }; // class AreaBuilder
406 
408 
409  } // namespace builder
410 
411 } // namespace osmium
412 
413 #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:147
uint32_t user_id_type
Type for OSM user IDs.
Definition: types.hpp:49
Definition: tag.hpp:48
Definition: osm_object_builder.hpp:343
~TagListBuilder()
Definition: osm_object_builder.hpp:77
Definition: changeset.hpp:130
osmium::memory::Buffer & buffer() noexcept
Return the buffer this builder is using.
Definition: builder.hpp:178
Definition: tag.hpp:105
type
Definition: entity_bits.hpp:63
osmium::memory::item_size_type append_zero()
Definition: builder.hpp:172
OSMObject & set_timestamp(const osmium::Timestamp &timestamp) noexcept
Definition: object.hpp:284
uint32_t item_size_type
Definition: item.hpp:59
const char * value() const
Definition: tag.hpp:83
WayBuilder(osmium::memory::Buffer &buffer, Builder *parent=nullptr)
Definition: osm_object_builder.hpp:369
AreaBuilder(osmium::memory::Buffer &buffer, Builder *parent=nullptr)
Definition: osm_object_builder.hpp:386
void add_user(osmium::ChangesetComment &comment, const char *user, const size_t length)
Definition: osm_object_builder.hpp:288
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:263
void initialize_from_object(const osmium::OSMObject &source)
Definition: osm_object_builder.hpp:393
void add_user(const char *user, const string_size_type length)
Definition: builder.hpp:205
item_type
Definition: item_type.hpp:43
void add_tag(const osmium::Tag &tag)
Definition: osm_object_builder.hpp:138
uint16_t string_size_type
Definition: types.hpp:59
~RelationMemberListBuilder()
Definition: osm_object_builder.hpp:225
Definition: area.hpp:116
Definition: relation.hpp:148
OSMObject & set_id(object_id_type id) noexcept
Definition: object.hpp:124
Definition: way.hpp:66
RelationMemberListBuilder(osmium::memory::Buffer &buffer, Builder *parent=nullptr)
Definition: osm_object_builder.hpp:221
Definition: changeset.hpp:59
Definition: osm_object_builder.hpp:284
osmium::object_id_type object_id_to_area_id(osmium::object_id_type id, osmium::item_type type) noexcept
Definition: area.hpp:95
void add_text(osmium::ChangesetComment &comment, const char *text, const size_t length)
Definition: osm_object_builder.hpp:296
Definition: osm_object_builder.hpp:172
void add_tag(const std::pair< const std::string &, const std::string & > &tag)
Definition: osm_object_builder.hpp:165
void add_tag(const char *key, const size_t key_length, const char *value, const size_t value_length)
Definition: osm_object_builder.hpp:105
Definition: relation.hpp:54
void add_tag(const std::pair< const char *const, const char * > &tag)
Definition: osm_object_builder.hpp:150
Namespace for everything in the Osmium library.
Definition: assembler.hpp:73
void add_tags(const std::initializer_list< std::pair< const char *, const char * >> &tags)
Definition: osm_object_builder.hpp:353
void add_node_refs(const std::initializer_list< osmium::NodeRef > &nodes)
Definition: osm_object_builder.hpp:373
void add_comment(osmium::Timestamp date, osmium::user_id_type uid, const char *user)
Definition: osm_object_builder.hpp:320
Definition: timestamp.hpp:115
OSMObjectBuilder(osmium::memory::Buffer &buffer, Builder *parent=nullptr)
Definition: osm_object_builder.hpp:347
void add_tag(const std::pair< const char *, const char * > &tag)
Definition: osm_object_builder.hpp:156
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:234
changeset_id_type changeset() const noexcept
Get changeset id of this object.
Definition: object.hpp:210
OSMObject & set_changeset(changeset_id_type changeset) noexcept
Definition: object.hpp:219
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:242
void add_tag(const std::pair< const char *, const char *const > &tag)
Definition: osm_object_builder.hpp:153
Definition: location.hpp:256
osmium::ChangesetComment * m_comment
Definition: osm_object_builder.hpp:286
Definition: osm_object_builder.hpp:365
void set_text_size(string_size_type size) noexcept
Definition: changeset.hpp:97
object_id_type id() const noexcept
Get ID of this object.
Definition: object.hpp:110
OSMObject & set_version(object_version_type version) noexcept
Definition: object.hpp:195
object_version_type version() const noexcept
Get version of this object.
Definition: object.hpp:186
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:278
NodeRefListBuilder(osmium::memory::Buffer &buffer, Builder *parent=nullptr)
Definition: osm_object_builder.hpp:176
void add_comment_text(const char *text)
Definition: osm_object_builder.hpp:328
Definition: buffer.hpp:97
const char * key() const noexcept
Definition: tag.hpp:79
Definition: builder.hpp:185
void set_user_size(string_size_type size) noexcept
Definition: changeset.hpp:93
OSMObject & set_visible(bool visible) noexcept
Definition: object.hpp:163
~NodeRefListBuilder()
Definition: osm_object_builder.hpp:180
osmium::memory::item_size_type append(const char *data, const osmium::memory::item_size_type length)
Definition: builder.hpp:151
void add_comment_text(const std::string &text)
Definition: osm_object_builder.hpp:334
bool visible() const noexcept
Is this object marked visible (ie not deleted)?
Definition: object.hpp:144
void add_role(osmium::RelationMember &member, const char *role, const size_t length)
Definition: osm_object_builder.hpp:210
void add_size(uint32_t size)
Definition: builder.hpp:115
void add_item(const osmium::memory::Item *item)
Definition: builder.hpp:126
void add_node_ref(const object_id_type ref, const osmium::Location &location=Location{})
Definition: osm_object_builder.hpp:189
~ChangesetDiscussionBuilder()
Definition: osm_object_builder.hpp:315
void add_tag(const std::string &key, const std::string &value)
Definition: osm_object_builder.hpp:122
Definition: node_ref.hpp:50
osmium::Area & object() noexcept
Definition: builder.hpp:195
const char * user() const noexcept
Get user name for this object.
Definition: object.hpp:304
item_type type() const noexcept
Definition: item.hpp:165
osmium::Timestamp timestamp() const noexcept
Get timestamp when this object last changed.
Definition: object.hpp:274
OSMObject & set_uid(user_id_type uid) noexcept
Definition: object.hpp:243
Definition: builder.hpp:56
Definition: osm_object_builder.hpp:199
constexpr const int max_osm_string_length
Definition: types.hpp:62
TagListBuilder(osmium::memory::Buffer &buffer, Builder *parent=nullptr)
Definition: osm_object_builder.hpp:73
void add_tag(const char *key, const char *value)
Definition: osm_object_builder.hpp:87
ChangesetDiscussionBuilder(osmium::memory::Buffer &buffer, Builder *parent=nullptr)
Definition: osm_object_builder.hpp:311
Definition: object.hpp:58
Definition: osm_object_builder.hpp:69
void add_node_ref(const NodeRef &node_ref)
Definition: osm_object_builder.hpp:184
Definition: osm_object_builder.hpp:382
void add_padding(bool self=false)
Definition: builder.hpp:102