1 #ifndef OSMIUM_BUILDER_ATTR_HPP
2 #define OSMIUM_BUILDER_ATTR_HPP
52 #include <initializer_list>
56 #include <type_traits>
68 template <
typename THandler,
typename... TTypes>
71 template <
typename THandler>
72 struct is_handled_by<THandler> {
73 static constexpr
bool value =
false;
76 template <
typename THandler,
typename T,
typename... TRest>
77 struct is_handled_by<THandler, T, TRest...> {
78 static constexpr
bool value = std::is_base_of<typename T::handler, THandler>::value ||
79 is_handled_by<THandler, TRest...>::value;
82 template <
typename THandler,
typename... TTypes>
83 struct are_all_handled_by;
85 template <
typename THandler,
typename T>
86 struct are_all_handled_by<THandler, T> {
87 static constexpr
bool value = std::is_base_of<typename T::handler, THandler>::value;
90 template <
typename THandler,
typename T,
typename... TRest>
91 struct are_all_handled_by<THandler, T, TRest...> {
92 static constexpr
bool value = std::is_base_of<typename T::handler, THandler>::value &&
93 are_all_handled_by<THandler, TRest...>::value;
97 template <
template <
typename>
class Predicate,
typename... Ts>
98 struct static_none_of : std::is_same<std::tuple<std::false_type, typename Predicate<Ts>::type...>,
99 std::tuple<typename Predicate<Ts>::type..., std::false_type>>
103 template <
template <
typename>
class Predicate,
typename... Ts>
104 struct static_all_of : std::is_same<std::tuple<std::true_type, typename Predicate<Ts>::type...>,
105 std::tuple<typename Predicate<Ts>::type..., std::true_type>>
109 template <
typename THandler,
typename... TTypes>
110 struct is_handled_by {
111 template <
typename T>
112 using HasHandler = std::is_base_of<typename T::handler, THandler>;
114 static constexpr
bool value = !static_none_of<HasHandler, TTypes...>::value;
118 template <
typename THandler,
typename... TTypes>
119 struct are_all_handled_by {
120 template <
typename T>
121 using HasHandler = std::is_base_of<typename T::handler, THandler>;
123 static constexpr
bool value = static_all_of<HasHandler, TTypes...>::value;
129 template <
typename TType>
130 struct type_wrapper {
136 constexpr
explicit type_wrapper(
const TType& v) :
143 template <
typename TType>
144 struct iterator_wrapper {
151 constexpr iterator_wrapper(TType
begin, TType
end) :
155 constexpr TType
begin()
const {
159 constexpr TType
end()
const {
166 struct entity_handler {};
167 struct object_handler;
170 struct nodes_handler;
171 struct members_handler;
172 struct changeset_handler;
173 struct discussion_handler;
178 #define OSMIUM_ATTRIBUTE(_handler, _name, _type) \
179 struct _name : public osmium::builder::detail::type_wrapper<_type> { \
180 using handler = osmium::builder::detail::_handler;
182 #define OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR(_handler, _name, _type) \
183 OSMIUM_ATTRIBUTE(_handler, _name, _type) \
184 constexpr explicit _name(std::add_const<_type>::type& value) : \
185 type_wrapper(value) {} \
188 #define OSMIUM_ATTRIBUTE_ITER(_handler, _name) \
189 template <typename TIterator> \
190 struct _name : public osmium::builder::detail::iterator_wrapper<TIterator> { \
191 using handler = osmium::builder::detail::_handler; \
192 constexpr _name(TIterator first, TIterator last) : \
193 osmium::builder::detail::iterator_wrapper<TIterator>(first, last) {} \
204 constexpr explicit
_deleted(
bool value = true) noexcept :
205 type_wrapper(value) {}
209 constexpr explicit
_visible(
bool value = true) noexcept :
210 type_wrapper(value) {}
215 type_wrapper(value) {}
228 type_wrapper(value) {}
230 type_wrapper(
osmium::Location{lat, lon}) {}
234 constexpr explicit
_user(const
char* val) noexcept :
236 explicit _user(
const std::string& val) noexcept :
237 type_wrapper(val.c_str()) {}
265 constexpr
const char*
role() const noexcept {
293 const char*
role() const noexcept {
323 constexpr
const char*
user() const noexcept {
327 constexpr
const char*
text() const noexcept {
350 type_wrapper(value) {}
351 explicit _tag(
const std::pair<const char* const, const char*>& value) :
353 explicit _tag(
const std::pair<const char*, const char* const>& value) :
355 explicit _tag(
const std::pair<const char*, const char*>& value) :
358 type_wrapper(
std::make_pair(value.first.c_str(), value.second.c_str())) {}
359 explicit _tag(
const char* key,
const char* val) :
360 type_wrapper(
std::make_pair(key, val)) {}
361 explicit _tag(
const std::string& key,
const std::string& val) :
362 type_wrapper(
std::make_pair(key.c_str(), val.c_str())) {}
365 template <
typename TTagIterator>
366 inline constexpr detail::tags_from_iterator_pair<TTagIterator>
_tags(TTagIterator first, TTagIterator last) {
367 return {first, last};
370 template <
typename TContainer>
371 inline detail::tags_from_iterator_pair<typename TContainer::const_iterator>
_tags(
const TContainer& container) {
374 return {
begin(container),
end(container)};
377 using tag_ilist = std::initializer_list<std::pair<const char*, const char*>>;
378 inline detail::tags_from_iterator_pair<tag_ilist::const_iterator>
_tags(
const tag_ilist& container) {
381 return {
begin(container),
end(container)};
388 type_wrapper(NodeRef{value}) {}
389 constexpr
explicit _node(
const NodeRef& value) noexcept :
390 type_wrapper(value) {}
393 template <
typename TIdIterator>
394 inline constexpr detail::nodes_from_iterator_pair<TIdIterator>
_nodes(TIdIterator first, TIdIterator last) {
395 return {first, last};
398 template <
typename TContainer>
399 inline detail::nodes_from_iterator_pair<typename TContainer::const_iterator>
_nodes(
const TContainer& container) {
402 return {
begin(container),
end(container)};
409 return {
begin(container),
end(container)};
413 inline detail::nodes_from_iterator_pair<node_ref_ilist::const_iterator>
_nodes(
const node_ref_ilist& container) {
416 return {
begin(container),
end(container)};
422 type_wrapper(value) {}
424 type_wrapper({
type,
id}) {}
426 type_wrapper({
type, id, role}) {}
428 type_wrapper({
type, id, role.c_str()}) {}
430 type_wrapper({member.type(), member.ref(), member.role()}) {}
433 template <
typename TMemberIterator>
434 inline constexpr detail::members_from_iterator_pair<TMemberIterator>
_members(TMemberIterator first, TMemberIterator last) {
435 return {first, last};
438 template <
typename TContainer>
439 inline detail::members_from_iterator_pair<typename TContainer::const_iterator>
_members(
const TContainer& container) {
442 return {
begin(container),
end(container)};
446 inline detail::members_from_iterator_pair<member_ilist::const_iterator>
_members(
const member_ilist& container) {
449 return {
begin(container),
end(container)};
460 type_wrapper(value) {}
462 type_wrapper({comment.date(), comment.uid(), comment.user(), comment.text()}) {}
465 template <
typename TCommentIterator>
466 inline constexpr detail::comments_from_iterator_pair<TCommentIterator>
_comments(TCommentIterator first, TCommentIterator last) {
467 return {first, last};
470 template <
typename TContainer>
471 inline detail::comments_from_iterator_pair<typename TContainer::const_iterator>
_comments(
const TContainer& container) {
474 return {
begin(container),
end(container)};
481 return {
begin(container),
end(container)};
485 template <
typename TIdIterator>
486 inline constexpr detail::outer_ring_from_iterator_pair<TIdIterator>
_outer_ring(TIdIterator first, TIdIterator last) {
487 return {first, last};
490 template <
typename TContainer>
491 inline detail::outer_ring_from_iterator_pair<typename TContainer::const_iterator>
_outer_ring(
const TContainer& container) {
494 return {
begin(container),
end(container)};
501 return {
begin(container),
end(container)};
508 return {
begin(container),
end(container)};
511 template <
typename TIdIterator>
512 inline constexpr detail::inner_ring_from_iterator_pair<TIdIterator>
_inner_ring(TIdIterator first, TIdIterator last) {
513 return {first, last};
516 template <
typename TContainer>
517 inline detail::inner_ring_from_iterator_pair<typename TContainer::const_iterator>
_inner_ring(
const TContainer& container) {
520 return {
begin(container),
end(container)};
527 return {
begin(container),
end(container)};
534 return {
begin(container),
end(container)};
540 #undef OSMIUM_ATTRIBUTE_ITER
541 #undef OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR
542 #undef OSMIUM_ATTRIBUTE
548 template <
typename TDummy>
553 changeset.set_id(
id.value);
557 changeset.set_num_changes(num_changes.value);
561 changeset.set_num_comments(num_comments.value);
565 changeset.set_created_at(created_at.value);
569 changeset.set_closed_at(closed_at.value);
573 changeset.set_uid(uid.value);
580 template <
typename TDummy>
585 object.set_id(
id.value);
589 object.set_version(version.value);
593 object.set_visible(visible.value);
597 object.set_deleted(deleted.value);
601 object.set_timestamp(timestamp.value);
605 object.set_changeset(changeset.value);
609 object.set_uid(uid.value);
619 node.set_location(location.value);
624 template <
typename THandler,
typename TBuilder,
typename... TArgs>
625 inline void add_basic(TBuilder& builder,
const TArgs&... args) noexcept {
626 (void)std::initializer_list<int>{
627 (THandler::set_value(builder.object(), args), 0)...
633 template <
typename... TArgs>
642 template <
typename TFirst,
typename... TRest>
643 inline constexpr
typename std::enable_if<!std::is_same<attr::_user, TFirst>::value,
const char*>
::type
644 get_user(
const TFirst& ,
const TRest&... args) noexcept {
648 template <
typename TBuilder,
typename... TArgs>
649 inline void add_user(TBuilder& builder,
const TArgs&... args) {
650 builder.set_user(
get_user(args...));
657 template <
typename TDummy>
658 static void set_value(TagListBuilder& ,
const TDummy& ) noexcept {
662 builder.add_tag(tag.value);
665 template <
typename TIterator>
666 static void set_value(TagListBuilder& builder,
const attr::detail::tags_from_iterator_pair<TIterator>& tags) {
667 for (
const auto& tag : tags) {
668 builder.add_tag(tag);
676 template <
typename TDummy>
681 builder.add_node_ref(node_ref.value);
684 template <
typename TIterator>
686 for (
const auto& ref : nodes) {
687 builder.add_node_ref(ref);
695 template <
typename TDummy>
696 static void set_value(RelationMemberListBuilder& ,
const TDummy& ) noexcept {
700 builder.add_member(member.value.type(), member.value.ref(), member.value.role());
703 template <
typename TIterator>
704 static void set_value(RelationMemberListBuilder& builder,
const attr::detail::members_from_iterator_pair<TIterator>& members) {
705 for (
const auto& member : members) {
706 builder.add_member(member.type(), member.ref(), member.role());
714 template <
typename TDummy>
715 static void set_value(ChangesetDiscussionBuilder& ,
const TDummy& ) noexcept {
719 builder.add_comment(comment.value.date(), comment.value.uid(), comment.value.user());
720 builder.add_comment_text(comment.value.text());
723 template <
typename TIterator>
724 static void set_value(ChangesetDiscussionBuilder& builder,
const attr::detail::comments_from_iterator_pair<TIterator>& comments) {
725 for (
const auto& comment : comments) {
726 builder.add_comment(comment.date(), comment.uid(), comment.user());
727 builder.add_comment_text(comment.text());
735 template <
typename TDummy>
736 static void set_value(AreaBuilder& ,
const TDummy& ) noexcept {
739 template <
typename TIterator>
740 static void set_value(AreaBuilder& parent,
const attr::detail::outer_ring_from_iterator_pair<TIterator>& nodes) {
742 for (
const auto& ref : nodes) {
743 builder.add_node_ref(ref);
747 template <
typename TIterator>
748 static void set_value(AreaBuilder& parent,
const attr::detail::inner_ring_from_iterator_pair<TIterator>& nodes) {
750 for (
const auto& ref : nodes) {
751 builder.add_node_ref(ref);
759 template <
typename TBuilder,
typename THandler,
typename... TArgs>
760 inline typename std::enable_if<!is_handled_by<THandler, TArgs...>::value>
::type
764 template <
typename TBuilder,
typename THandler,
typename... TArgs>
765 inline typename std::enable_if<is_handled_by<THandler, TArgs...>::value>
::type
767 TBuilder builder{parent.
buffer(), &parent};
768 (void)std::initializer_list<int>{
769 (THandler::set_value(builder, args), 0)...
789 template <
typename... TArgs>
793 NodeBuilder builder{buffer};
795 detail::add_basic<detail::node_handler>(builder, args...);
797 detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
810 template <
typename... TArgs>
814 WayBuilder builder{buffer};
816 detail::add_basic<detail::object_handler>(builder, args...);
818 detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
819 detail::add_list<WayNodeListBuilder, detail::nodes_handler>(builder, args...);
832 template <
typename... TArgs>
836 RelationBuilder builder{buffer};
838 detail::add_basic<detail::object_handler>(builder, args...);
840 detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
841 detail::add_list<RelationMemberListBuilder, detail::members_handler>(builder, args...);
854 template <
typename... TArgs>
858 ChangesetBuilder builder{buffer};
860 detail::add_basic<detail::changeset_handler>(builder, args...);
862 detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
863 detail::add_list<ChangesetDiscussionBuilder, detail::discussion_handler>(builder, args...);
876 template <
typename... TArgs>
880 AreaBuilder builder{buffer};
882 detail::add_basic<detail::object_handler>(builder, args...);
884 detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
886 (void)std::initializer_list<int>{
901 template <
typename... TArgs>
906 (void)std::initializer_list<int>{
921 template <
typename... TArgs>
925 TagListBuilder builder{buffer};
926 (void)std::initializer_list<int>{
938 #endif // OSMIUM_BUILDER_ATTR_HPP