1 #ifndef OSMIUM_BUILDER_ATTR_HPP
2 #define OSMIUM_BUILDER_ATTR_HPP
53 #include <initializer_list>
57 #include <type_traits>
69 template <
typename THandler,
typename... TTypes>
72 template <
typename THandler>
73 struct is_handled_by<THandler> {
74 static constexpr
bool value =
false;
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;
83 template <
typename THandler,
typename... TTypes>
84 struct are_all_handled_by;
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;
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;
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>>
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>>
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>;
115 static constexpr
bool value = !static_none_of<HasHandler, TTypes...>::value;
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>;
124 static constexpr
bool value = static_all_of<HasHandler, TTypes...>::value;
130 template <
typename TType>
131 struct type_wrapper {
137 constexpr
explicit type_wrapper(
const TType& v) :
144 template <
typename TType>
145 struct iterator_wrapper {
152 constexpr iterator_wrapper(TType
begin, TType
end) :
156 constexpr TType
begin()
const {
160 constexpr TType
end()
const {
167 struct entity_handler {};
168 struct object_handler;
171 struct nodes_handler;
172 struct members_handler;
173 struct changeset_handler;
174 struct discussion_handler;
179 #define OSMIUM_ATTRIBUTE(_handler, _name, _type) \
180 struct _name : public osmium::builder::detail::type_wrapper<_type> { \
181 using handler = osmium::builder::detail::_handler;
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) {} \
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) {} \
205 constexpr explicit
_deleted(
bool value = true) noexcept :
206 type_wrapper(value) {}
210 constexpr explicit
_visible(
bool value = true) noexcept :
211 type_wrapper(value) {}
216 type_wrapper(value) {}
229 type_wrapper(value) {}
231 type_wrapper(
osmium::Location{lon, lat}) {}
235 constexpr explicit
_user(const
char* val) noexcept :
237 explicit _user(
const std::string& val) noexcept :
238 type_wrapper(val.c_str()) {}
270 constexpr
const char*
role() const noexcept {
302 const char*
role() const noexcept {
332 constexpr
const char*
user() const noexcept {
336 constexpr
const char*
text() const noexcept {
359 type_wrapper(value) {}
360 explicit _tag(
const std::pair<const char* const, const char*>& value) :
362 explicit _tag(
const std::pair<const char*, const char* const>& value) :
364 explicit _tag(
const std::pair<const char*, const char*>& 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) :
374 explicit _tag(
const std::string& key_value) :
379 explicit
_t(const
char *tags) :
380 type_wrapper(tags) {}
383 template <
typename TTagIterator>
384 inline constexpr detail::tags_from_iterator_pair<TTagIterator>
_tags(TTagIterator first, TTagIterator last) {
385 return {first, last};
388 template <
typename TContainer>
389 inline detail::tags_from_iterator_pair<typename TContainer::const_iterator>
_tags(
const TContainer& container) {
392 return {
begin(container),
end(container)};
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) {
399 return {
begin(container),
end(container)};
406 type_wrapper(NodeRef{value}) {}
407 constexpr
explicit _node(
const NodeRef& value) noexcept :
408 type_wrapper(value) {}
411 template <
typename TIdIterator>
412 inline constexpr detail::nodes_from_iterator_pair<TIdIterator>
_nodes(TIdIterator first, TIdIterator last) {
413 return {first, last};
416 template <
typename TContainer>
417 inline detail::nodes_from_iterator_pair<typename TContainer::const_iterator>
_nodes(
const TContainer& container) {
420 return {
begin(container),
end(container)};
427 return {
begin(container),
end(container)};
431 inline detail::nodes_from_iterator_pair<node_ref_ilist::const_iterator>
_nodes(
const node_ref_ilist& container) {
434 return {
begin(container),
end(container)};
440 type_wrapper(value) {}
442 type_wrapper({
type,
id}) {}
444 type_wrapper({
type, id, role}) {}
446 type_wrapper({
type, id, role.c_str()}) {}
448 type_wrapper({member.type(), member.ref(), member.role()}) {}
451 template <
typename TMemberIterator>
452 inline constexpr detail::members_from_iterator_pair<TMemberIterator>
_members(TMemberIterator first, TMemberIterator last) {
453 return {first, last};
456 template <
typename TContainer>
457 inline detail::members_from_iterator_pair<typename TContainer::const_iterator>
_members(
const TContainer& container) {
460 return {
begin(container),
end(container)};
464 inline detail::members_from_iterator_pair<member_ilist::const_iterator>
_members(
const member_ilist& container) {
467 return {
begin(container),
end(container)};
478 type_wrapper(value) {}
480 type_wrapper({comment.date(), comment.uid(), comment.user(), comment.text()}) {}
483 template <
typename TCommentIterator>
484 inline constexpr detail::comments_from_iterator_pair<TCommentIterator>
_comments(TCommentIterator first, TCommentIterator last) {
485 return {first, last};
488 template <
typename TContainer>
489 inline detail::comments_from_iterator_pair<typename TContainer::const_iterator>
_comments(
const TContainer& container) {
492 return {
begin(container),
end(container)};
499 return {
begin(container),
end(container)};
503 template <
typename TIdIterator>
504 inline constexpr detail::outer_ring_from_iterator_pair<TIdIterator>
_outer_ring(TIdIterator first, TIdIterator last) {
505 return {first, last};
508 template <
typename TContainer>
509 inline detail::outer_ring_from_iterator_pair<typename TContainer::const_iterator>
_outer_ring(
const TContainer& container) {
512 return {
begin(container),
end(container)};
519 return {
begin(container),
end(container)};
526 return {
begin(container),
end(container)};
529 template <
typename TIdIterator>
530 inline constexpr detail::inner_ring_from_iterator_pair<TIdIterator>
_inner_ring(TIdIterator first, TIdIterator last) {
531 return {first, last};
534 template <
typename TContainer>
535 inline detail::inner_ring_from_iterator_pair<typename TContainer::const_iterator>
_inner_ring(
const TContainer& container) {
538 return {
begin(container),
end(container)};
545 return {
begin(container),
end(container)};
552 return {
begin(container),
end(container)};
558 #undef OSMIUM_ATTRIBUTE_ITER
559 #undef OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR
560 #undef OSMIUM_ATTRIBUTE
566 template <
typename TDummy>
575 changeset.set_num_changes(num_changes.value);
579 changeset.set_num_comments(num_comments.value);
583 changeset.set_created_at(created_at.value);
587 changeset.set_closed_at(closed_at.value);
598 template <
typename TDummy>
603 object.set_id(
id.value);
607 object.set_version(version.value);
611 object.set_visible(visible.value);
615 object.set_deleted(deleted.value);
619 object.set_timestamp(timestamp.value);
627 object.set_uid(uid.value);
637 node.set_location(location.value);
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)...
651 template <
typename... TArgs>
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& ,
const TRest&... args) noexcept {
666 template <
typename TBuilder,
typename... TArgs>
667 inline void add_user(TBuilder& builder,
const TArgs&... args) {
668 builder.set_user(
get_user(args...));
675 template <
typename TDummy>
676 static void set_value(TagListBuilder& ,
const TDummy& ) noexcept {
680 if (tag.value.second !=
nullptr) {
681 builder.add_tag(tag.value);
684 const char* key = tag.value.first;
685 const char*
const equal_sign = std::strchr(key,
'=');
687 builder.add_tag(key,
"");
690 const char* value = equal_sign + 1;
691 builder.add_tag(key, equal_sign - key,
692 value, std::strlen(value));
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);
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,
"");
709 const char* value = tag.c_str() + pos + 1;
710 builder.add_tag(tag.c_str(), pos,
711 value, tag.size() - pos - 1);
721 template <
typename TDummy>
726 builder.add_node_ref(node_ref.value);
729 template <
typename TIterator>
731 for (
const auto& ref : nodes) {
732 builder.add_node_ref(ref);
740 template <
typename TDummy>
741 static void set_value(RelationMemberListBuilder& ,
const TDummy& ) noexcept {
745 builder.add_member(member.value.type(), member.value.ref(), member.value.role());
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());
759 template <
typename TDummy>
760 static void set_value(ChangesetDiscussionBuilder& ,
const TDummy& ) noexcept {
764 builder.add_comment(comment.value.date(), comment.value.uid(), comment.value.user());
765 builder.add_comment_text(comment.value.text());
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());
780 template <
typename TDummy>
781 static void set_value(AreaBuilder& ,
const TDummy& ) noexcept {
784 template <
typename TIterator>
785 static void set_value(AreaBuilder& parent,
const attr::detail::outer_ring_from_iterator_pair<TIterator>& nodes) {
787 for (
const auto& ref : nodes) {
788 builder.add_node_ref(ref);
792 template <
typename TIterator>
793 static void set_value(AreaBuilder& parent,
const attr::detail::inner_ring_from_iterator_pair<TIterator>& nodes) {
795 for (
const auto& ref : nodes) {
796 builder.add_node_ref(ref);
804 template <
typename TBuilder,
typename THandler,
typename... TArgs>
805 inline typename std::enable_if<!is_handled_by<THandler, TArgs...>::value>
::type
809 template <
typename TBuilder,
typename THandler,
typename... TArgs>
810 inline typename std::enable_if<is_handled_by<THandler, TArgs...>::value>
::type
812 TBuilder builder{parent.
buffer(), &parent};
813 (void)std::initializer_list<int>{
814 (THandler::set_value(builder, args), 0)...
834 template <
typename... TArgs>
838 NodeBuilder builder{buffer};
840 detail::add_basic<detail::node_handler>(builder, args...);
842 detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
855 template <
typename... TArgs>
859 WayBuilder builder{buffer};
861 detail::add_basic<detail::object_handler>(builder, args...);
863 detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
864 detail::add_list<WayNodeListBuilder, detail::nodes_handler>(builder, args...);
877 template <
typename... TArgs>
881 RelationBuilder builder{buffer};
883 detail::add_basic<detail::object_handler>(builder, args...);
885 detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
886 detail::add_list<RelationMemberListBuilder, detail::members_handler>(builder, args...);
899 template <
typename... TArgs>
903 ChangesetBuilder builder{buffer};
905 detail::add_basic<detail::changeset_handler>(builder, args...);
907 detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
908 detail::add_list<ChangesetDiscussionBuilder, detail::discussion_handler>(builder, args...);
921 template <
typename... TArgs>
925 AreaBuilder builder{buffer};
927 detail::add_basic<detail::object_handler>(builder, args...);
929 detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
931 (void)std::initializer_list<int>{
946 template <
typename... TArgs>
951 (void)std::initializer_list<int>{
966 template <
typename... TArgs>
970 TagListBuilder builder{buffer};
971 (void)std::initializer_list<int>{
983 #endif // OSMIUM_BUILDER_ATTR_HPP