Libosmium  2.15.5
Fast and flexible C++ library for working with OpenStreetMap data
attr.hpp
Go to the documentation of this file.
1 #ifndef OSMIUM_BUILDER_ATTR_HPP
2 #define OSMIUM_BUILDER_ATTR_HPP
3 
4 /*
5 
6 This file is part of Osmium (https://osmcode.org/libosmium).
7 
8 Copyright 2013-2020 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 
38 #include <osmium/memory/buffer.hpp>
39 #include <osmium/osm/changeset.hpp>
40 #include <osmium/osm/item_type.hpp>
41 #include <osmium/osm/location.hpp>
42 #include <osmium/osm/node.hpp>
43 #include <osmium/osm/node_ref.hpp>
44 #include <osmium/osm/object.hpp>
45 #include <osmium/osm/relation.hpp>
46 #include <osmium/osm/timestamp.hpp>
47 #include <osmium/osm/types.hpp>
48 #include <osmium/util/string.hpp>
49 
50 #include <cstddef>
51 #include <cstdint>
52 #include <ctime>
53 #include <initializer_list>
54 #include <iterator>
55 #include <string>
56 #include <tuple>
57 #include <type_traits>
58 #include <utility>
59 
60 namespace osmium {
61 
62  namespace builder {
63 
64  namespace detail {
65 
66 #ifdef _MSC_VER
67  // workaround for bug in MSVC
68 
69  template <typename THandler, typename... TTypes>
70  struct is_handled_by;
71 
72  template <typename THandler>
73  struct is_handled_by<THandler> {
74  static constexpr bool value = false;
75  };
76 
77  template <typename THandler, typename T, typename... TRest>
78  struct is_handled_by<THandler, T, TRest...> {
79  static constexpr bool value = std::is_base_of<typename T::handler, THandler>::value ||
80  is_handled_by<THandler, TRest...>::value;
81  };
82 
83  template <typename THandler, typename... TTypes>
84  struct are_all_handled_by;
85 
86  template <typename THandler, typename T>
87  struct are_all_handled_by<THandler, T> {
88  static constexpr bool value = std::is_base_of<typename T::handler, THandler>::value;
89  };
90 
91  template <typename THandler, typename T, typename... TRest>
92  struct are_all_handled_by<THandler, T, TRest...> {
93  static constexpr bool value = std::is_base_of<typename T::handler, THandler>::value &&
94  are_all_handled_by<THandler, TRest...>::value;
95  };
96 #else
97  // True if Predicate matches for none of the types Ts
98  template <template <typename> class Predicate, typename... Ts>
99  struct static_none_of : std::is_same<std::tuple<std::false_type, typename Predicate<Ts>::type...>,
100  std::tuple<typename Predicate<Ts>::type..., std::false_type>>
101  {};
102 
103  // True if Predicate matches for all of the types Ts
104  template <template <typename> class Predicate, typename... Ts>
105  struct static_all_of : std::is_same<std::tuple<std::true_type, typename Predicate<Ts>::type...>,
106  std::tuple<typename Predicate<Ts>::type..., std::true_type>>
107  {};
108 
109  // True if THandler is derived from the handler for at least one of the types in TTypes
110  template <typename THandler, typename... TTypes>
111  struct is_handled_by {
112  template <typename T>
113  using HasHandler = std::is_base_of<typename T::handler, THandler>;
114 
115  static constexpr bool value = !static_none_of<HasHandler, TTypes...>::value;
116  };
117 
118  // True if THandler is derived from the handlers of all the types in TTypes
119  template <typename THandler, typename... TTypes>
120  struct are_all_handled_by {
121  template <typename T>
122  using HasHandler = std::is_base_of<typename T::handler, THandler>;
123 
124  static constexpr bool value = static_all_of<HasHandler, TTypes...>::value;
125  };
126 #endif
127 
128 
129  // Wraps any type, so that we can derive from it
130  template <typename TType>
131  struct type_wrapper {
132 
133  using type = TType;
134 
135  TType value;
136 
137  constexpr explicit type_wrapper(const TType& v) :
138  value(v) {
139  }
140 
141  }; // struct type_wrapper
142 
143  // Small wrapper for begin/end iterator
144  template <typename TType>
145  struct iterator_wrapper {
146 
147  using type = TType;
148 
149  TType first;
150  TType last;
151 
152  constexpr iterator_wrapper(TType begin, TType end) :
153  first(begin),
154  last(end) {}
155 
156  constexpr TType begin() const {
157  return first;
158  }
159 
160  constexpr TType end() const {
161  return last;
162  }
163 
164  }; // struct iterator_wrapper
165 
166 
167  struct entity_handler {};
168  struct object_handler;
169  struct node_handler;
170  struct tags_handler;
171  struct nodes_handler;
172  struct members_handler;
173  struct changeset_handler;
174  struct discussion_handler;
175  struct ring_handler;
176 
177  } // namespace detail
178 
179 #define OSMIUM_ATTRIBUTE(_handler, _name, _type) \
180  struct _name : public osmium::builder::detail::type_wrapper<_type> { \
181  using handler = osmium::builder::detail::_handler;
182 
183 #define OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR(_handler, _name, _type) \
184  OSMIUM_ATTRIBUTE(_handler, _name, _type) \
185  constexpr explicit _name(std::add_const<_type>::type& value) : \
186  type_wrapper(value) {} \
187  }
188 
189 #define OSMIUM_ATTRIBUTE_ITER(_handler, _name) \
190  template <typename TIterator> \
191  struct _name : public osmium::builder::detail::iterator_wrapper<TIterator> { \
192  using handler = osmium::builder::detail::_handler; \
193  constexpr _name(TIterator first, TIterator last) : \
194  osmium::builder::detail::iterator_wrapper<TIterator>(first, last) {} \
195  }
196 
197  namespace attr {
198 
203 
204  OSMIUM_ATTRIBUTE(object_handler, _deleted, bool)
205  constexpr explicit _deleted(bool value = true) noexcept :
206  type_wrapper(value) {}
207  };
208 
209  OSMIUM_ATTRIBUTE(object_handler, _visible, bool)
210  constexpr explicit _visible(bool value = true) noexcept :
211  type_wrapper(value) {}
212  };
213 
215  constexpr explicit _timestamp(const osmium::Timestamp& value) noexcept :
216  type_wrapper(value) {}
217  constexpr explicit _timestamp(time_t value) noexcept :
218  type_wrapper(osmium::Timestamp{value}) {}
219  constexpr explicit _timestamp(uint32_t value) noexcept :
220  type_wrapper(osmium::Timestamp{value}) {}
221  explicit _timestamp(const char* value) :
222  type_wrapper(osmium::Timestamp{value}) {}
223  explicit _timestamp(const std::string& value) :
224  type_wrapper(osmium::Timestamp{value}) {}
225  };
226 
228  constexpr explicit _location(const osmium::Location& value) noexcept :
229  type_wrapper(value) {}
230  explicit _location(double lon, double lat) :
231  type_wrapper(osmium::Location{lon, lat}) {}
232  };
233 
234  OSMIUM_ATTRIBUTE(entity_handler, _user, const char*)
235  constexpr explicit _user(const char* val) noexcept :
236  type_wrapper(val) {}
237  explicit _user(const std::string& val) noexcept :
238  type_wrapper(val.c_str()) {}
239  };
240 
241  using pair_of_cstrings = std::pair<const char* const, const char* const>;
242  using pair_of_strings = std::pair<const std::string&, const std::string&>;
243 
244  class member_type {
245 
248  const char* m_role;
249 
250  public:
251 
252  constexpr member_type(osmium::item_type type, osmium::object_id_type ref, const char* role = "") noexcept :
253  m_type(type),
254  m_ref(ref),
255  m_role(role) {
256  }
257 
258  member_type(char type, osmium::object_id_type ref, const char* role = "") noexcept :
260  }
261 
262  constexpr osmium::item_type type() const noexcept {
263  return m_type;
264  }
265 
266  constexpr osmium::object_id_type ref() const noexcept {
267  return m_ref;
268  }
269 
270  constexpr const char* role() const noexcept {
271  return m_role;
272  }
273 
274  }; // class member_type
275 
277 
280  std::string m_role;
281 
282  public:
283 
285  m_type(type),
286  m_ref(ref),
287  m_role(std::move(role)) {
288  }
289 
290  member_type_string(char type, osmium::object_id_type ref, std::string&& role) noexcept :
291  member_type_string(osmium::char_to_item_type(type), ref, std::forward<std::string>(role)) {
292  }
293 
294  osmium::item_type type() const noexcept {
295  return m_type;
296  }
297 
298  osmium::object_id_type ref() const noexcept {
299  return m_ref;
300  }
301 
302  const char* role() const noexcept {
303  return m_role.c_str();
304  }
305 
306  }; // class member_type_string
307 
308  class comment_type {
309 
312  const char* m_user;
313  const char* m_text;
314 
315  public:
316 
317  constexpr comment_type(osmium::Timestamp date, osmium::user_id_type uid, const char* user, const char* text) noexcept :
318  m_date(date),
319  m_uid(uid),
320  m_user(user),
321  m_text(text) {
322  }
323 
324  constexpr osmium::Timestamp date() const noexcept {
325  return m_date;
326  }
327 
328  constexpr osmium::user_id_type uid() const noexcept {
329  return m_uid;
330  }
331 
332  constexpr const char* user() const noexcept {
333  return m_user;
334  }
335 
336  constexpr const char* text() const noexcept {
337  return m_text;
338  }
339 
340  }; // class comment_type
341 
342  namespace detail {
343 
344  OSMIUM_ATTRIBUTE_ITER(tags_handler, tags_from_iterator_pair);
345 
346  OSMIUM_ATTRIBUTE_ITER(nodes_handler, nodes_from_iterator_pair);
347 
348  OSMIUM_ATTRIBUTE_ITER(members_handler, members_from_iterator_pair);
349 
350  OSMIUM_ATTRIBUTE_ITER(discussion_handler, comments_from_iterator_pair);
351 
352  OSMIUM_ATTRIBUTE_ITER(ring_handler, outer_ring_from_iterator_pair);
353  OSMIUM_ATTRIBUTE_ITER(ring_handler, inner_ring_from_iterator_pair);
354 
355  } // namespace detail
356 
357  OSMIUM_ATTRIBUTE(tags_handler, _tag, pair_of_cstrings)
358  explicit _tag(const pair_of_cstrings& value) noexcept :
359  type_wrapper(value) {}
360  explicit _tag(const std::pair<const char* const, const char*>& value) :
361  type_wrapper(pair_of_cstrings{value.first, value.second}) {}
362  explicit _tag(const std::pair<const char*, const char* const>& value) :
363  type_wrapper(pair_of_cstrings{value.first, value.second}) {}
364  explicit _tag(const std::pair<const char*, const char*>& value) :
365  type_wrapper(pair_of_cstrings{value.first, value.second}) {}
366  explicit _tag(const pair_of_strings& value) :
367  type_wrapper(std::make_pair(value.first.c_str(), value.second.c_str())) {}
368  explicit _tag(const char* key, const char* val) :
369  type_wrapper(std::make_pair(key, val)) {}
370  explicit _tag(const std::string& key, const std::string& val) :
371  type_wrapper(std::make_pair(key.c_str(), val.c_str())) {}
372  explicit _tag(const char* const key_value) :
373  type_wrapper(pair_of_cstrings{key_value, nullptr}) {}
374  explicit _tag(const std::string& key_value) :
375  type_wrapper(pair_of_cstrings{key_value.c_str(), nullptr}) {}
376  };
377 
378  OSMIUM_ATTRIBUTE(tags_handler, _t, const char*)
379  explicit _t(const char *tags) :
380  type_wrapper(tags) {}
381  };
382 
383  template <typename TTagIterator>
384  inline constexpr detail::tags_from_iterator_pair<TTagIterator> _tags(TTagIterator first, TTagIterator last) {
385  return {first, last};
386  }
387 
388  template <typename TContainer>
389  inline detail::tags_from_iterator_pair<typename TContainer::const_iterator> _tags(const TContainer& container) {
390  using std::begin;
391  using std::end;
392  return {begin(container), end(container)};
393  }
394 
395  using tag_ilist = std::initializer_list<std::pair<const char*, const char*>>;
396  inline detail::tags_from_iterator_pair<tag_ilist::const_iterator> _tags(const tag_ilist& container) {
397  using std::begin;
398  using std::end;
399  return {begin(container), end(container)};
400  }
401 
402 
403 
404  OSMIUM_ATTRIBUTE(nodes_handler, _node, osmium::NodeRef)
405  constexpr explicit _node(osmium::object_id_type value) noexcept :
406  type_wrapper(NodeRef{value}) {}
407  constexpr explicit _node(const NodeRef& value) noexcept :
408  type_wrapper(value) {}
409  };
410 
411  template <typename TIdIterator>
412  inline constexpr detail::nodes_from_iterator_pair<TIdIterator> _nodes(TIdIterator first, TIdIterator last) {
413  return {first, last};
414  }
415 
416  template <typename TContainer>
417  inline detail::nodes_from_iterator_pair<typename TContainer::const_iterator> _nodes(const TContainer& container) {
418  using std::begin;
419  using std::end;
420  return {begin(container), end(container)};
421  }
422 
423  using object_id_ilist = std::initializer_list<osmium::object_id_type>;
424  inline detail::nodes_from_iterator_pair<object_id_ilist::const_iterator> _nodes(const object_id_ilist& container) {
425  using std::begin;
426  using std::end;
427  return {begin(container), end(container)};
428  }
429 
430  using node_ref_ilist = std::initializer_list<osmium::NodeRef>;
431  inline detail::nodes_from_iterator_pair<node_ref_ilist::const_iterator> _nodes(const node_ref_ilist& container) {
432  using std::begin;
433  using std::end;
434  return {begin(container), end(container)};
435  }
436 
437 
438  OSMIUM_ATTRIBUTE(members_handler, _member, member_type)
439  constexpr explicit _member(const member_type& value) noexcept :
440  type_wrapper(value) {}
441  constexpr explicit _member(osmium::item_type type, osmium::object_id_type id) noexcept :
442  type_wrapper({type, id}) {}
443  constexpr explicit _member(osmium::item_type type, osmium::object_id_type id, const char* role) noexcept :
444  type_wrapper({type, id, role}) {}
445  explicit _member(osmium::item_type type, osmium::object_id_type id, const std::string& role) noexcept :
446  type_wrapper({type, id, role.c_str()}) {}
447  explicit _member(const osmium::RelationMember& member) noexcept :
448  type_wrapper({member.type(), member.ref(), member.role()}) {}
449  };
450 
451  template <typename TMemberIterator>
452  inline constexpr detail::members_from_iterator_pair<TMemberIterator> _members(TMemberIterator first, TMemberIterator last) {
453  return {first, last};
454  }
455 
456  template <typename TContainer>
457  inline detail::members_from_iterator_pair<typename TContainer::const_iterator> _members(const TContainer& container) {
458  using std::begin;
459  using std::end;
460  return {begin(container), end(container)};
461  }
462 
463  using member_ilist = std::initializer_list<member_type>;
464  inline detail::members_from_iterator_pair<member_ilist::const_iterator> _members(const member_ilist& container) {
465  using std::begin;
466  using std::end;
467  return {begin(container), end(container)};
468  }
469 
470 
471  OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR(changeset_handler, _num_changes, osmium::num_changes_type);
472  OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR(changeset_handler, _num_comments, osmium::num_comments_type);
473  OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR(changeset_handler, _created_at, osmium::Timestamp);
474  OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR(changeset_handler, _closed_at, osmium::Timestamp);
475 
476  OSMIUM_ATTRIBUTE(discussion_handler, _comment, comment_type)
477  constexpr explicit _comment(const comment_type& value) noexcept :
478  type_wrapper(value) {}
479  explicit _comment(const osmium::ChangesetComment& comment) noexcept :
480  type_wrapper({comment.date(), comment.uid(), comment.user(), comment.text()}) {}
481  };
482 
483  template <typename TCommentIterator>
484  inline constexpr detail::comments_from_iterator_pair<TCommentIterator> _comments(TCommentIterator first, TCommentIterator last) {
485  return {first, last};
486  }
487 
488  template <typename TContainer>
489  inline detail::comments_from_iterator_pair<typename TContainer::const_iterator> _comments(const TContainer& container) {
490  using std::begin;
491  using std::end;
492  return {begin(container), end(container)};
493  }
494 
495  using comment_ilist = std::initializer_list<comment_type>;
496  inline detail::comments_from_iterator_pair<comment_ilist::const_iterator> _comments(const comment_ilist& container) {
497  using std::begin;
498  using std::end;
499  return {begin(container), end(container)};
500  }
501 
502 
503  template <typename TIdIterator>
504  inline constexpr detail::outer_ring_from_iterator_pair<TIdIterator> _outer_ring(TIdIterator first, TIdIterator last) {
505  return {first, last};
506  }
507 
508  template <typename TContainer>
509  inline detail::outer_ring_from_iterator_pair<typename TContainer::const_iterator> _outer_ring(const TContainer& container) {
510  using std::begin;
511  using std::end;
512  return {begin(container), end(container)};
513  }
514 
515  using object_id_ilist = std::initializer_list<osmium::object_id_type>;
516  inline detail::outer_ring_from_iterator_pair<object_id_ilist::const_iterator> _outer_ring(const object_id_ilist& container) {
517  using std::begin;
518  using std::end;
519  return {begin(container), end(container)};
520  }
521 
522  using node_ref_ilist = std::initializer_list<osmium::NodeRef>;
523  inline detail::outer_ring_from_iterator_pair<node_ref_ilist::const_iterator> _outer_ring(const node_ref_ilist& container) {
524  using std::begin;
525  using std::end;
526  return {begin(container), end(container)};
527  }
528 
529  template <typename TIdIterator>
530  inline constexpr detail::inner_ring_from_iterator_pair<TIdIterator> _inner_ring(TIdIterator first, TIdIterator last) {
531  return {first, last};
532  }
533 
534  template <typename TContainer>
535  inline detail::inner_ring_from_iterator_pair<typename TContainer::const_iterator> _inner_ring(const TContainer& container) {
536  using std::begin;
537  using std::end;
538  return {begin(container), end(container)};
539  }
540 
541  using object_id_ilist = std::initializer_list<osmium::object_id_type>;
542  inline detail::inner_ring_from_iterator_pair<object_id_ilist::const_iterator> _inner_ring(const object_id_ilist& container) {
543  using std::begin;
544  using std::end;
545  return {begin(container), end(container)};
546  }
547 
548  using node_ref_ilist = std::initializer_list<osmium::NodeRef>;
549  inline detail::inner_ring_from_iterator_pair<node_ref_ilist::const_iterator> _inner_ring(const node_ref_ilist& container) {
550  using std::begin;
551  using std::end;
552  return {begin(container), end(container)};
553  }
554 
555 
556  } // namespace attr
557 
558 #undef OSMIUM_ATTRIBUTE_ITER
559 #undef OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR
560 #undef OSMIUM_ATTRIBUTE
561 
562  namespace detail {
563 
564  struct changeset_handler : public entity_handler {
565 
566  template <typename TDummy>
567  static void set_value(osmium::Changeset& /*changeset*/, const TDummy& /*dummy*/) noexcept {
568  }
569 
570  static void set_value(osmium::Changeset& changeset, attr::_cid id) noexcept {
571  changeset.set_id(id.value);
572  }
573 
574  static void set_value(osmium::Changeset& changeset, attr::_num_changes num_changes) noexcept {
575  changeset.set_num_changes(num_changes.value);
576  }
577 
578  static void set_value(osmium::Changeset& changeset, attr::_num_comments num_comments) noexcept {
579  changeset.set_num_comments(num_comments.value);
580  }
581 
582  static void set_value(osmium::Changeset& changeset, attr::_created_at created_at) noexcept {
583  changeset.set_created_at(created_at.value);
584  }
585 
586  static void set_value(osmium::Changeset& changeset, attr::_closed_at closed_at) noexcept {
587  changeset.set_closed_at(closed_at.value);
588  }
589 
590  static void set_value(osmium::Changeset& changeset, attr::_uid uid) noexcept {
591  changeset.set_uid(uid.value);
592  }
593 
594  };
595 
596  struct object_handler : public entity_handler {
597 
598  template <typename TDummy>
599  static void set_value(osmium::OSMObject& /*object*/, const TDummy& /*dummy*/) noexcept {
600  }
601 
602  static void set_value(osmium::OSMObject& object, attr::_id id) noexcept {
603  object.set_id(id.value);
604  }
605 
606  static void set_value(osmium::OSMObject& object, attr::_version version) noexcept {
607  object.set_version(version.value);
608  }
609 
610  static void set_value(osmium::OSMObject& object, attr::_visible visible) noexcept {
611  object.set_visible(visible.value);
612  }
613 
614  static void set_value(osmium::OSMObject& object, attr::_deleted deleted) noexcept {
615  object.set_deleted(deleted.value);
616  }
617 
618  static void set_value(osmium::OSMObject& object, attr::_timestamp timestamp) noexcept {
619  object.set_timestamp(timestamp.value);
620  }
621 
622  static void set_value(osmium::OSMObject& object, attr::_cid changeset) noexcept {
623  object.set_changeset(changeset.value);
624  }
625 
626  static void set_value(osmium::OSMObject& object, attr::_uid uid) noexcept {
627  object.set_uid(uid.value);
628  }
629 
630  }; // object_handler
631 
632  struct node_handler : public object_handler {
633 
635 
636  static void set_value(osmium::Node& node, attr::_location location) noexcept {
637  node.set_location(location.value);
638  }
639 
640  }; // node_handler
641 
642  template <typename THandler, typename TBuilder, typename... TArgs>
643  inline void add_basic(TBuilder& builder, const TArgs&... args) noexcept {
644  (void)std::initializer_list<int>{
645  (THandler::set_value(builder.object(), args), 0)...
646  };
647  }
648 
649  // ==============================================================
650 
651  template <typename... TArgs>
652  inline constexpr const char* get_user(const attr::_user& user, const TArgs&... /*args*/) noexcept {
653  return user.value;
654  }
655 
656  inline constexpr const char* get_user() noexcept {
657  return "";
658  }
659 
660  template <typename TFirst, typename... TRest>
661  inline constexpr typename std::enable_if<!std::is_same<attr::_user, TFirst>::value, const char*>::type
662  get_user(const TFirst& /*first*/, const TRest&... args) noexcept {
663  return get_user(args...);
664  }
665 
666  template <typename TBuilder, typename... TArgs>
667  inline void add_user(TBuilder& builder, const TArgs&... args) {
668  builder.set_user(get_user(args...));
669  }
670 
671  // ==============================================================
672 
673  struct tags_handler {
674 
675  template <typename TDummy>
676  static void set_value(TagListBuilder& /*tlb*/, const TDummy& /*dummy*/) noexcept {
677  }
678 
679  static void set_value(TagListBuilder& builder, const attr::_tag& tag) {
680  if (tag.value.second != nullptr) {
681  builder.add_tag(tag.value);
682  return;
683  }
684  const char* key = tag.value.first;
685  auto const equal_sign = std::strchr(key, '=');
686  if (!equal_sign) {
687  builder.add_tag(key, "");
688  return;
689  }
690  const char* value = equal_sign + 1;
691  builder.add_tag(key, equal_sign - key,
692  value, std::strlen(value));
693  }
694 
695  template <typename TIterator>
696  static void set_value(TagListBuilder& builder, const attr::detail::tags_from_iterator_pair<TIterator>& tags) {
697  for (const auto& tag : tags) {
698  builder.add_tag(tag);
699  }
700  }
701 
702  static void set_value(TagListBuilder& builder, const attr::_t& tags) {
703  const auto taglist = osmium::split_string(tags.value, ',', true);
704  for (const auto& tag : taglist) {
705  const std::size_t pos = tag.find_first_of('=');
706  if (pos == std::string::npos) {
707  builder.add_tag(tag, "");
708  } else {
709  const char* value = tag.c_str() + pos + 1;
710  builder.add_tag(tag.c_str(), pos,
711  value, tag.size() - pos - 1);
712  }
713 
714  }
715  }
716 
717  }; // struct tags_handler
718 
719  struct nodes_handler {
720 
721  template <typename TDummy>
722  static void set_value(WayNodeListBuilder& /*wnlb*/, const TDummy& /*dummy*/) noexcept {
723  }
724 
725  static void set_value(WayNodeListBuilder& builder, const attr::_node& node_ref) {
726  builder.add_node_ref(node_ref.value);
727  }
728 
729  template <typename TIterator>
730  static void set_value(WayNodeListBuilder& builder, const attr::detail::nodes_from_iterator_pair<TIterator>& nodes) {
731  for (const auto& ref : nodes) {
732  builder.add_node_ref(ref);
733  }
734  }
735 
736  }; // struct nodes_handler
737 
739 
740  template <typename TDummy>
741  static void set_value(RelationMemberListBuilder& /*rmlb*/, const TDummy& /*dummy*/) noexcept {
742  }
743 
744  static void set_value(RelationMemberListBuilder& builder, const attr::_member& member) {
745  builder.add_member(member.value.type(), member.value.ref(), member.value.role());
746  }
747 
748  template <typename TIterator>
749  static void set_value(RelationMemberListBuilder& builder, const attr::detail::members_from_iterator_pair<TIterator>& members) {
750  for (const auto& member : members) {
751  builder.add_member(member.type(), member.ref(), member.role());
752  }
753  }
754 
755  }; // struct members_handler
756 
758 
759  template <typename TDummy>
760  static void set_value(ChangesetDiscussionBuilder& /*cdb*/, const TDummy& /*dummy*/) noexcept {
761  }
762 
763  static void set_value(ChangesetDiscussionBuilder& builder, const attr::_comment& comment) {
764  builder.add_comment(comment.value.date(), comment.value.uid(), comment.value.user());
765  builder.add_comment_text(comment.value.text());
766  }
767 
768  template <typename TIterator>
769  static void set_value(ChangesetDiscussionBuilder& builder, const attr::detail::comments_from_iterator_pair<TIterator>& comments) {
770  for (const auto& comment : comments) {
771  builder.add_comment(comment.date(), comment.uid(), comment.user());
772  builder.add_comment_text(comment.text());
773  }
774  }
775 
776  }; // struct discussion_handler
777 
778  struct ring_handler {
779 
780  template <typename TDummy>
781  static void set_value(AreaBuilder& /*ab*/, const TDummy& /*dummy*/) noexcept {
782  }
783 
784  template <typename TIterator>
785  static void set_value(AreaBuilder& parent, const attr::detail::outer_ring_from_iterator_pair<TIterator>& nodes) {
786  OuterRingBuilder builder(parent.buffer(), &parent);
787  for (const auto& ref : nodes) {
788  builder.add_node_ref(ref);
789  }
790  }
791 
792  template <typename TIterator>
793  static void set_value(AreaBuilder& parent, const attr::detail::inner_ring_from_iterator_pair<TIterator>& nodes) {
794  InnerRingBuilder builder(parent.buffer(), &parent);
795  for (const auto& ref : nodes) {
796  builder.add_node_ref(ref);
797  }
798  }
799 
800  }; // struct ring_handler
801 
802  // ==============================================================
803 
804  template <typename TBuilder, typename THandler, typename... TArgs>
805  inline typename std::enable_if<!is_handled_by<THandler, TArgs...>::value>::type
806  add_list(osmium::builder::Builder& /*parent*/, const TArgs&... /*args*/) noexcept {
807  }
808 
809  template <typename TBuilder, typename THandler, typename... TArgs>
810  inline typename std::enable_if<is_handled_by<THandler, TArgs...>::value>::type
811  add_list(osmium::builder::Builder& parent, const TArgs&... args) {
812  TBuilder builder{parent.buffer(), &parent};
813  (void)std::initializer_list<int>{
814  (THandler::set_value(builder, args), 0)...
815  };
816  }
817 
818  struct any_node_handlers : public node_handler, public tags_handler {};
819  struct any_way_handlers : public object_handler, public tags_handler, public nodes_handler {};
821  struct any_area_handlers : public object_handler, public tags_handler, public ring_handler {};
823 
824  } // namespace detail
825 
826 
834  template <typename... TArgs>
835  inline size_t add_node(osmium::memory::Buffer& buffer, const TArgs&... args) {
836 
837  {
838  NodeBuilder builder{buffer};
839 
840  detail::add_basic<detail::node_handler>(builder, args...);
841  detail::add_user(builder, args...);
842  detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
843  }
844 
845  return buffer.commit();
846  }
847 
855  template <typename... TArgs>
856  inline size_t add_way(osmium::memory::Buffer& buffer, const TArgs&... args) {
857 
858  {
859  WayBuilder builder{buffer};
860 
861  detail::add_basic<detail::object_handler>(builder, args...);
862  detail::add_user(builder, args...);
863  detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
864  detail::add_list<WayNodeListBuilder, detail::nodes_handler>(builder, args...);
865  }
866 
867  return buffer.commit();
868  }
869 
877  template <typename... TArgs>
878  inline size_t add_relation(osmium::memory::Buffer& buffer, const TArgs&... args) {
879 
880  {
881  RelationBuilder builder{buffer};
882 
883  detail::add_basic<detail::object_handler>(builder, args...);
884  detail::add_user(builder, args...);
885  detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
886  detail::add_list<RelationMemberListBuilder, detail::members_handler>(builder, args...);
887  }
888 
889  return buffer.commit();
890  }
891 
899  template <typename... TArgs>
900  inline size_t add_changeset(osmium::memory::Buffer& buffer, const TArgs&... args) {
901 
902  {
903  ChangesetBuilder builder{buffer};
904 
905  detail::add_basic<detail::changeset_handler>(builder, args...);
906  detail::add_user(builder, args...);
907  detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
908  detail::add_list<ChangesetDiscussionBuilder, detail::discussion_handler>(builder, args...);
909  }
910 
911  return buffer.commit();
912  }
913 
921  template <typename... TArgs>
922  inline size_t add_area(osmium::memory::Buffer& buffer, const TArgs&... args) {
923 
924  {
925  AreaBuilder builder{buffer};
926 
927  detail::add_basic<detail::object_handler>(builder, args...);
928  detail::add_user(builder, args...);
929  detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
930 
931  (void)std::initializer_list<int>{
932  (detail::ring_handler::set_value(builder, args), 0)...
933  };
934  }
935 
936  return buffer.commit();
937  }
938 
946  template <typename... TArgs>
947  inline size_t add_way_node_list(osmium::memory::Buffer& buffer, const TArgs&... args) {
948 
949  {
950  WayNodeListBuilder builder{buffer};
951  (void)std::initializer_list<int>{
952  (detail::nodes_handler::set_value(builder, args), 0)...
953  };
954  }
955 
956  return buffer.commit();
957  }
958 
966  template <typename... TArgs>
967  inline size_t add_tag_list(osmium::memory::Buffer& buffer, const TArgs&... args) {
968 
969  {
970  TagListBuilder builder{buffer};
971  (void)std::initializer_list<int>{
972  (detail::tags_handler::set_value(builder, args), 0)...
973  };
974  }
975 
976  return buffer.commit();
977  }
978 
979  } // namespace builder
980 
981 } // namespace osmium
982 
983 #endif // OSMIUM_BUILDER_ATTR_HPP
pair_of_strings
std::pair< const std::string &, const std::string & > pair_of_strings
Definition: attr.hpp:242
detail::changeset_handler
Definition: attr.hpp:564
comment_type::m_uid
osmium::user_id_type m_uid
Definition: attr.hpp:311
detail::object_handler::set_value
static void set_value(osmium::OSMObject &object, attr::_deleted deleted) noexcept
Definition: attr.hpp:614
detail::members_handler::set_value
static void set_value(RelationMemberListBuilder &builder, const attr::detail::members_from_iterator_pair< TIterator > &members)
Definition: attr.hpp:749
OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR
#define OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR(_handler, _name, _type)
Definition: attr.hpp:183
tag_ilist
std::initializer_list< std::pair< const char *, const char * > > tag_ilist
Definition: attr.hpp:395
changeset.hpp
relation.hpp
detail::object_handler::set_value
static void set_value(osmium::OSMObject &object, attr::_cid changeset) noexcept
Definition: attr.hpp:622
object_id_ilist
std::initializer_list< osmium::object_id_type > object_id_ilist
Definition: attr.hpp:423
comment_ilist
std::initializer_list< comment_type > comment_ilist
Definition: attr.hpp:495
osmium::OSMObject
Definition: object.hpp:64
detail::add_basic
void add_basic(TBuilder &builder, const TArgs &... args) noexcept
Definition: attr.hpp:643
detail::members_handler
Definition: attr.hpp:738
comment_type::m_date
osmium::Timestamp m_date
Definition: attr.hpp:310
detail::any_node_handlers
Definition: attr.hpp:818
member_type::member_type
member_type(char type, osmium::object_id_type ref, const char *role="") noexcept
Definition: attr.hpp:258
comment_type::m_text
const char * m_text
Definition: attr.hpp:313
detail::members_handler::set_value
static void set_value(RelationMemberListBuilder &, const TDummy &) noexcept
Definition: attr.hpp:741
osmium::num_changes_type
uint32_t num_changes_type
Type for changeset num_changes.
Definition: types.hpp:51
detail::tags_handler::set_value
static void set_value(TagListBuilder &, const TDummy &) noexcept
Definition: attr.hpp:676
detail::members_handler::set_value
static void set_value(RelationMemberListBuilder &builder, const attr::_member &member)
Definition: attr.hpp:744
osmium::_timestamp
_timestamp(const std::string &value)
Definition: attr.hpp:223
types.hpp
node.hpp
osmium::user_id_type
uint32_t user_id_type
Type for OSM user IDs.
Definition: types.hpp:49
osmium::builder::_visible
constexpr _visible(bool value=true) noexcept
Definition: attr.hpp:210
member_type_string::role
const char * role() const noexcept
Definition: attr.hpp:302
osmium::changeset_id_type
uint32_t changeset_id_type
Type for OSM changeset IDs.
Definition: types.hpp:48
osmium::object_id_type
int64_t object_id_type
Type for OSM object (node, way, or relation) IDs.
Definition: types.hpp:45
add_way
size_t add_way(osmium::memory::Buffer &buffer, const TArgs &... args)
Definition: attr.hpp:856
comment_type
Definition: attr.hpp:308
detail
Definition: attr.hpp:342
_nodes
constexpr detail::nodes_from_iterator_pair< TIdIterator > _nodes(TIdIterator first, TIdIterator last)
Definition: attr.hpp:412
detail::changeset_handler::set_value
static void set_value(osmium::Changeset &changeset, attr::_num_comments num_comments) noexcept
Definition: attr.hpp:578
member_type::type
constexpr osmium::item_type type() const noexcept
Definition: attr.hpp:262
osmium::Node
Definition: node.hpp:48
member_type_string::type
osmium::item_type type() const noexcept
Definition: attr.hpp:294
osmium::builder::InnerRingBuilder
NodeRefListBuilder< InnerRing > InnerRingBuilder
Definition: osm_object_builder.hpp:227
member_type::role
constexpr const char * role() const noexcept
Definition: attr.hpp:270
detail::changeset_handler::set_value
static void set_value(osmium::Changeset &changeset, attr::_uid uid) noexcept
Definition: attr.hpp:590
detail::object_handler::set_value
static void set_value(osmium::OSMObject &object, attr::_visible visible) noexcept
Definition: attr.hpp:610
_tags
constexpr detail::tags_from_iterator_pair< TTagIterator > _tags(TTagIterator first, TTagIterator last)
Definition: attr.hpp:384
detail::object_handler
Definition: attr.hpp:596
detail::object_handler::set_value
static void set_value(osmium::OSMObject &object, attr::_id id) noexcept
Definition: attr.hpp:602
detail::nodes_handler
Definition: attr.hpp:719
_node
constexpr _node(osmium::object_id_type value) noexcept
Definition: attr.hpp:405
detail::OSMIUM_ATTRIBUTE_ITER
OSMIUM_ATTRIBUTE_ITER(tags_handler, tags_from_iterator_pair)
add_node
size_t add_node(osmium::memory::Buffer &buffer, const TArgs &... args)
Definition: attr.hpp:835
comment_type::comment_type
constexpr comment_type(osmium::Timestamp date, osmium::user_id_type uid, const char *user, const char *text) noexcept
Definition: attr.hpp:317
osmium::builder::Builder::buffer
osmium::memory::Buffer & buffer() noexcept
Return the buffer this builder is using.
Definition: builder.hpp:207
_location
constexpr _location(const osmium::Location &value) noexcept
Definition: attr.hpp:228
_outer_ring
constexpr detail::outer_ring_from_iterator_pair< TIdIterator > _outer_ring(TIdIterator first, TIdIterator last)
Definition: attr.hpp:504
comment_type::text
constexpr const char * text() const noexcept
Definition: attr.hpp:336
string.hpp
node_ref.hpp
detail::nodes_handler::set_value
static void set_value(WayNodeListBuilder &, const TDummy &) noexcept
Definition: attr.hpp:722
detail::nodes_handler::set_value
static void set_value(WayNodeListBuilder &builder, const attr::_node &node_ref)
Definition: attr.hpp:725
member_type::ref
constexpr osmium::object_id_type ref() const noexcept
Definition: attr.hpp:266
add_area
size_t add_area(osmium::memory::Buffer &buffer, const TArgs &... args)
Definition: attr.hpp:922
osmium::memory::Buffer
Definition: buffer.hpp:97
osmium::builder::attr::_deleted
constexpr _deleted(bool value=true) noexcept
Definition: attr.hpp:205
detail::ring_handler
Definition: attr.hpp:778
comment_type::date
constexpr osmium::Timestamp date() const noexcept
Definition: attr.hpp:324
detail::any_relation_handlers
Definition: attr.hpp:820
add_way_node_list
size_t add_way_node_list(osmium::memory::Buffer &buffer, const TArgs &... args)
Definition: attr.hpp:947
osmium::io::begin
InputIterator< Reader > begin(Reader &reader)
Definition: reader_iterator.hpp:43
member_ilist
std::initializer_list< member_type > member_ilist
Definition: attr.hpp:463
add_tag_list
size_t add_tag_list(osmium::memory::Buffer &buffer, const TArgs &... args)
Definition: attr.hpp:967
detail::changeset_handler::set_value
static void set_value(osmium::Changeset &changeset, attr::_created_at created_at) noexcept
Definition: attr.hpp:582
osmium
Namespace for everything in the Osmium library.
Definition: assembler.hpp:53
detail::node_handler::set_value
static void set_value(osmium::Node &node, attr::_location location) noexcept
Definition: attr.hpp:636
detail::tags_handler
Definition: attr.hpp:673
_member
constexpr _member(const member_type &value) noexcept
Definition: attr.hpp:439
detail::node_handler
Definition: attr.hpp:632
_t
_t(const char *tags)
Definition: attr.hpp:379
detail::discussion_handler::set_value
static void set_value(ChangesetDiscussionBuilder &builder, const attr::detail::comments_from_iterator_pair< TIterator > &comments)
Definition: attr.hpp:769
detail::changeset_handler::set_value
static void set_value(osmium::Changeset &, const TDummy &) noexcept
Definition: attr.hpp:567
member_type_string::m_ref
osmium::object_id_type m_ref
Definition: attr.hpp:279
member_type_string::ref
osmium::object_id_type ref() const noexcept
Definition: attr.hpp:298
detail::changeset_handler::set_value
static void set_value(osmium::Changeset &changeset, attr::_closed_at closed_at) noexcept
Definition: attr.hpp:586
detail::add_list
std::enable_if<!is_handled_by< THandler, TArgs... >::value >::type add_list(osmium::builder::Builder &, const TArgs &...) noexcept
Definition: attr.hpp:806
node_ref_ilist
std::initializer_list< osmium::NodeRef > node_ref_ilist
Definition: attr.hpp:430
detail::tags_handler::set_value
static void set_value(TagListBuilder &builder, const attr::detail::tags_from_iterator_pair< TIterator > &tags)
Definition: attr.hpp:696
osmium::Timestamp
Definition: timestamp.hpp:147
detail::nodes_handler::set_value
static void set_value(WayNodeListBuilder &builder, const attr::detail::nodes_from_iterator_pair< TIterator > &nodes)
Definition: attr.hpp:730
osmium::_timestamp
constexpr _timestamp(const osmium::Timestamp &value) noexcept
Definition: attr.hpp:215
osmium::ChangesetComment
Definition: changeset.hpp:59
detail::any_changeset_handlers
Definition: attr.hpp:822
osmium::char_to_item_type
item_type char_to_item_type(const char c) noexcept
Definition: item_type.hpp:88
location.hpp
member_type_string::member_type_string
member_type_string(char type, osmium::object_id_type ref, std::string &&role) noexcept
Definition: attr.hpp:290
comment_type::user
constexpr const char * user() const noexcept
Definition: attr.hpp:332
osmium::RelationMember
Definition: relation.hpp:57
comment_type::m_user
const char * m_user
Definition: attr.hpp:312
member_type
Definition: attr.hpp:244
detail::object_handler::set_value
static void set_value(osmium::OSMObject &object, attr::_version version) noexcept
Definition: attr.hpp:606
member_type_string::m_role
std::string m_role
Definition: attr.hpp:280
detail::ring_handler::set_value
static void set_value(AreaBuilder &parent, const attr::detail::outer_ring_from_iterator_pair< TIterator > &nodes)
Definition: attr.hpp:785
detail::ring_handler::set_value
static void set_value(AreaBuilder &, const TDummy &) noexcept
Definition: attr.hpp:781
detail::object_handler::set_value
static void set_value(osmium::OSMObject &object, attr::_uid uid) noexcept
Definition: attr.hpp:626
osmium::builder::WayNodeListBuilder
NodeRefListBuilder< WayNodeList > WayNodeListBuilder
Definition: osm_object_builder.hpp:225
member_type::member_type
constexpr member_type(osmium::item_type type, osmium::object_id_type ref, const char *role="") noexcept
Definition: attr.hpp:252
osmium::memory::Buffer::commit
std::size_t commit()
Definition: buffer.hpp:468
pair_of_cstrings
std::pair< const char *const, const char *const > pair_of_cstrings
Definition: attr.hpp:241
osmium::num_comments_type
uint32_t num_comments_type
Type for changeset num_comments.
Definition: types.hpp:52
osmium::Location
Definition: location.hpp:271
member_type::m_type
osmium::item_type m_type
Definition: attr.hpp:246
detail::ring_handler::set_value
static void set_value(AreaBuilder &parent, const attr::detail::inner_ring_from_iterator_pair< TIterator > &nodes)
Definition: attr.hpp:793
member_type_string::member_type_string
member_type_string(osmium::item_type type, osmium::object_id_type ref, std::string &&role)
Definition: attr.hpp:284
osmium::builder::attr::OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR
OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR(object_handler, _id, osmium::object_id_type)
std
Definition: location.hpp:551
osmium::object_version_type
uint32_t object_version_type
Type for OSM object version number.
Definition: types.hpp:47
member_type::m_ref
osmium::object_id_type m_ref
Definition: attr.hpp:247
_comment
constexpr _comment(const comment_type &value) noexcept
Definition: attr.hpp:477
add_relation
size_t add_relation(osmium::memory::Buffer &buffer, const TArgs &... args)
Definition: attr.hpp:878
_inner_ring
constexpr detail::inner_ring_from_iterator_pair< TIdIterator > _inner_ring(TIdIterator first, TIdIterator last)
Definition: attr.hpp:530
detail::any_area_handlers
Definition: attr.hpp:821
detail::discussion_handler::set_value
static void set_value(ChangesetDiscussionBuilder &builder, const attr::_comment &comment)
Definition: attr.hpp:763
osmium::builder::Builder
Definition: builder.hpp:57
member_type_string::m_type
osmium::item_type m_type
Definition: attr.hpp:278
_members
constexpr detail::members_from_iterator_pair< TMemberIterator > _members(TMemberIterator first, TMemberIterator last)
Definition: attr.hpp:452
comment_type::uid
constexpr osmium::user_id_type uid() const noexcept
Definition: attr.hpp:328
timestamp.hpp
member_type_string
Definition: attr.hpp:276
buffer.hpp
OSMIUM_ATTRIBUTE
#define OSMIUM_ATTRIBUTE(_handler, _name, _type)
Definition: attr.hpp:179
detail::object_handler::set_value
static void set_value(osmium::OSMObject &, const TDummy &) noexcept
Definition: attr.hpp:599
builder.hpp
detail::discussion_handler::set_value
static void set_value(ChangesetDiscussionBuilder &, const TDummy &) noexcept
Definition: attr.hpp:760
_user
constexpr _user(const char *val) noexcept
Definition: attr.hpp:235
osm_object_builder.hpp
detail::get_user
constexpr const char * get_user(const attr::_user &user, const TArgs &...) noexcept
Definition: attr.hpp:652
osmium::builder::OuterRingBuilder
NodeRefListBuilder< OuterRing > OuterRingBuilder
Definition: osm_object_builder.hpp:226
detail::changeset_handler::set_value
static void set_value(osmium::Changeset &changeset, attr::_num_changes num_changes) noexcept
Definition: attr.hpp:574
detail::tags_handler::set_value
static void set_value(TagListBuilder &builder, const attr::_t &tags)
Definition: attr.hpp:702
detail::discussion_handler
Definition: attr.hpp:757
detail::tags_handler::set_value
static void set_value(TagListBuilder &builder, const attr::_tag &tag)
Definition: attr.hpp:679
object.hpp
_comments
constexpr detail::comments_from_iterator_pair< TCommentIterator > _comments(TCommentIterator first, TCommentIterator last)
Definition: attr.hpp:484
item_type.hpp
detail::object_handler::set_value
static void set_value(osmium::OSMObject &object, attr::_timestamp timestamp) noexcept
Definition: attr.hpp:618
osmium::io::end
InputIterator< Reader > end(Reader &)
Definition: reader_iterator.hpp:47
detail::changeset_handler::set_value
static void set_value(osmium::Changeset &changeset, attr::_cid id) noexcept
Definition: attr.hpp:570
add_changeset
size_t add_changeset(osmium::memory::Buffer &buffer, const TArgs &... args)
Definition: attr.hpp:900
member_type::m_role
const char * m_role
Definition: attr.hpp:248
osmium::NodeRef
Definition: node_ref.hpp:50
detail::any_way_handlers
Definition: attr.hpp:819
_tag
_tag(const pair_of_cstrings &value) noexcept
Definition: attr.hpp:358
osmium::osm_entity_bits::type
type
Definition: entity_bits.hpp:63
osmium::item_type
item_type
Definition: item_type.hpp:43
osmium::Changeset
An OSM Changeset, a group of changes made by a single user over a short period of time.
Definition: changeset.hpp:148
detail::add_user
void add_user(TBuilder &builder, const TArgs &... args)
Definition: attr.hpp:667
osmium::split_string
std::vector< std::string > split_string(const std::string &str, const char sep, bool compact=false)
Definition: string.hpp:50