Libosmium  2.15.6
Fast and flexible C++ library for working with OpenStreetMap data
visitor.hpp
Go to the documentation of this file.
1 #ifndef OSMIUM_VISITOR_HPP
2 #define OSMIUM_VISITOR_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 
36 #include <osmium/fwd.hpp>
37 #include <osmium/handler.hpp>
38 #include <osmium/io/reader_iterator.hpp> // IWYU pragma: keep
39 #include <osmium/memory/buffer.hpp>
40 #include <osmium/osm.hpp>
41 #include <osmium/osm/entity.hpp>
42 #include <osmium/osm/item_type.hpp>
43 
44 #include <type_traits>
45 #include <utility>
46 
47 namespace osmium {
48 
49  namespace detail {
50 
51  template <typename T, typename U>
52  using ConstIfConst = typename std::conditional<std::is_const<T>::value, typename std::add_const<U>::type, U>::type;
53 
54  template <typename THandler, typename TItem>
55  inline void apply_item_impl(TItem& item, THandler&& handler) {
56  switch (item.type()) {
58  break;
60  std::forward<THandler>(handler).osm_object(static_cast<ConstIfConst<TItem, osmium::OSMObject>&>(item));
61  std::forward<THandler>(handler).node(static_cast<ConstIfConst<TItem, osmium::Node>&>(item));
62  break;
64  std::forward<THandler>(handler).osm_object(static_cast<ConstIfConst<TItem, osmium::OSMObject>&>(item));
65  std::forward<THandler>(handler).way(static_cast<ConstIfConst<TItem, osmium::Way>&>(item));
66  break;
68  std::forward<THandler>(handler).osm_object(static_cast<ConstIfConst<TItem, osmium::OSMObject>&>(item));
69  std::forward<THandler>(handler).relation(static_cast<ConstIfConst<TItem, osmium::Relation>&>(item));
70  break;
72  std::forward<THandler>(handler).osm_object(static_cast<ConstIfConst<TItem, osmium::OSMObject>&>(item));
73  std::forward<THandler>(handler).area(static_cast<ConstIfConst<TItem, osmium::Area>&>(item));
74  break;
76  std::forward<THandler>(handler).changeset(static_cast<ConstIfConst<TItem, osmium::Changeset>&>(item));
77  break;
79  std::forward<THandler>(handler).tag_list(static_cast<ConstIfConst<TItem, osmium::TagList>&>(item));
80  break;
82  std::forward<THandler>(handler).way_node_list(static_cast<ConstIfConst<TItem, osmium::WayNodeList>&>(item));
83  break;
86  std::forward<THandler>(handler).relation_member_list(static_cast<ConstIfConst<TItem, osmium::RelationMemberList>&>(item));
87  break;
89  std::forward<THandler>(handler).outer_ring(static_cast<ConstIfConst<TItem, osmium::OuterRing>&>(item));
90  break;
92  std::forward<THandler>(handler).inner_ring(static_cast<ConstIfConst<TItem, osmium::InnerRing>&>(item));
93  break;
95  std::forward<THandler>(handler).changeset_discussion(static_cast<ConstIfConst<TItem, osmium::ChangesetDiscussion>&>(item));
96  break;
97  }
98  }
99 
100  template <typename THandler>
101  inline void apply_item_impl(const osmium::OSMEntity& item, THandler&& handler) {
102  switch (item.type()) {
104  std::forward<THandler>(handler).osm_object(static_cast<const osmium::OSMObject&>(item));
105  std::forward<THandler>(handler).node(static_cast<const osmium::Node&>(item));
106  break;
108  std::forward<THandler>(handler).osm_object(static_cast<const osmium::OSMObject&>(item));
109  std::forward<THandler>(handler).way(static_cast<const osmium::Way&>(item));
110  break;
112  std::forward<THandler>(handler).osm_object(static_cast<const osmium::OSMObject&>(item));
113  std::forward<THandler>(handler).relation(static_cast<const osmium::Relation&>(item));
114  break;
116  std::forward<THandler>(handler).osm_object(static_cast<const osmium::OSMObject&>(item));
117  std::forward<THandler>(handler).area(static_cast<const osmium::Area&>(item));
118  break;
120  std::forward<THandler>(handler).changeset(static_cast<const osmium::Changeset&>(item));
121  break;
122  default:
123  throw osmium::unknown_type{};
124  }
125  }
126 
127  template <typename THandler>
128  inline void apply_item_impl(osmium::OSMEntity& item, THandler&& handler) {
129  switch (item.type()) {
131  std::forward<THandler>(handler).osm_object(static_cast<osmium::OSMObject&>(item));
132  std::forward<THandler>(handler).node(static_cast<osmium::Node&>(item));
133  break;
135  std::forward<THandler>(handler).osm_object(static_cast<osmium::OSMObject&>(item));
136  std::forward<THandler>(handler).way(static_cast<osmium::Way&>(item));
137  break;
139  std::forward<THandler>(handler).osm_object(static_cast<osmium::OSMObject&>(item));
140  std::forward<THandler>(handler).relation(static_cast<osmium::Relation&>(item));
141  break;
143  std::forward<THandler>(handler).osm_object(static_cast<osmium::OSMObject&>(item));
144  std::forward<THandler>(handler).area(static_cast<osmium::Area&>(item));
145  break;
147  std::forward<THandler>(handler).changeset(static_cast<osmium::Changeset&>(item));
148  break;
149  default:
150  throw osmium::unknown_type{};
151  }
152  }
153 
154  template <typename THandler>
155  inline void apply_item_impl(const osmium::OSMObject& item, THandler&& handler) {
156  switch (item.type()) {
158  std::forward<THandler>(handler).osm_object(item);
159  std::forward<THandler>(handler).node(static_cast<const osmium::Node&>(item));
160  break;
162  std::forward<THandler>(handler).osm_object(item);
163  std::forward<THandler>(handler).way(static_cast<const osmium::Way&>(item));
164  break;
166  std::forward<THandler>(handler).osm_object(item);
167  std::forward<THandler>(handler).relation(static_cast<const osmium::Relation&>(item));
168  break;
170  std::forward<THandler>(handler).osm_object(item);
171  std::forward<THandler>(handler).area(static_cast<const osmium::Area&>(item));
172  break;
173  default:
174  throw osmium::unknown_type{};
175  }
176  }
177 
178  template <typename THandler>
179  inline void apply_item_impl(osmium::OSMObject& item, THandler&& handler) {
180  switch (item.type()) {
182  std::forward<THandler>(handler).osm_object(item);
183  std::forward<THandler>(handler).node(static_cast<osmium::Node&>(item));
184  break;
186  std::forward<THandler>(handler).osm_object(item);
187  std::forward<THandler>(handler).way(static_cast<osmium::Way&>(item));
188  break;
190  std::forward<THandler>(handler).osm_object(item);
191  std::forward<THandler>(handler).relation(static_cast<osmium::Relation&>(item));
192  break;
194  std::forward<THandler>(handler).osm_object(item);
195  std::forward<THandler>(handler).area(static_cast<osmium::Area&>(item));
196  break;
197  default:
198  throw osmium::unknown_type{};
199  }
200  }
201 
202  template <typename TFunc>
203  struct wrapper_handler : TFunc {
204 
205  template<typename T>
206  explicit wrapper_handler(T&& func) : TFunc(std::forward<T>(func)) { // NOLINT(bugprone-forwarding-reference-overload)
207  }
208 
209  // Fallback that always matches.
210  void operator()(const osmium::memory::Item& /*item*/) const noexcept {
211  }
212 
213  // The function we are wrapping.
214  using TFunc::operator();
215 
216  void osm_object(const osmium::OSMObject& /*osm_object*/) const noexcept {
217  }
218 
219  void node(const osmium::Node& node) const {
220  operator()(node);
221  }
222 
223  void node(osmium::Node& node) const {
224  operator()(node);
225  }
226 
227  void way(const osmium::Way& way) const {
228  operator()(way);
229  }
230 
231  void way(osmium::Way& way) const {
232  operator()(way);
233  }
234 
235  void relation(const osmium::Relation& relation) const {
236  operator()(relation);
237  }
238 
239  void relation(osmium::Relation& relation) const {
240  operator()(relation);
241  }
242 
243  void area(const osmium::Area& area) const {
244  operator()(area);
245  }
246 
247  void area(osmium::Area& area) const {
248  operator()(area);
249  }
250 
251  void changeset(const osmium::Changeset& changeset) const {
252  operator()(changeset);
253  }
254 
255  void changeset(osmium::Changeset& changeset) const {
256  operator()(changeset);
257  }
258 
259  void tag_list(const osmium::TagList& /*tag_list*/) const noexcept {
260  }
261 
262  void way_node_list(const osmium::WayNodeList& /*way_node_list*/) const noexcept {
263  }
264 
265  void relation_member_list(const osmium::RelationMemberList& /*relation_member_list*/) const noexcept {
266  }
267 
268  void outer_ring(const osmium::OuterRing& /*outer_ring*/) const noexcept {
269  }
270 
271  void inner_ring(const osmium::InnerRing& /*inner_ring*/) const noexcept {
272  }
273 
274  void changeset_discussion(const osmium::ChangesetDiscussion& /*changeset_discussion*/) const noexcept {
275  }
276 
277  void flush() const noexcept {
278  }
279 
280  }; // struct wrapper_handler
281 
282  // Is the class T derived from osmium::handler::Handler?
283  template <typename T>
285 
286  // This is already a handler, use it as it is.
287  template <typename T, typename = typename std::enable_if<is_handler<T>::value>::type>
288  T make_handler(T&& func) {
289  return std::forward<T>(func);
290  }
291 
292  // This is not a handler, but a functor. Wrap a handler around it.
293  template <typename T, typename = typename std::enable_if<!is_handler<T>::value>::type>
294  wrapper_handler<typename std::decay<T>::type> make_handler(T&& func) {
295  return wrapper_handler<typename std::decay<T>::type>(std::forward<T>(func));
296  }
297 
298  } // namespace detail
299 
300  template <typename TItem, typename... THandlers>
301  inline void apply_item(TItem& item, THandlers&&... handlers) {
302  (void)std::initializer_list<int>{
303  (detail::apply_item_impl(item, std::forward<THandlers>(handlers)), 0)...
304  };
305  }
306 
307  template <typename... THandlers>
308  inline void apply_flush(THandlers&&... handlers) {
309  (void)std::initializer_list<int>{
310  (std::forward<THandlers>(handlers).flush(), 0)...
311  };
312  }
313 
314  template <typename TIterator, typename... THandlers>
315  inline void apply_impl(TIterator it, TIterator end, THandlers&&... handlers) {
316  for (; it != end; ++it) {
317  apply_item(*it, std::forward<THandlers>(handlers)...);
318  }
319  apply_flush(std::forward<THandlers>(handlers)...);
320  }
321 
322  template <typename TIterator, typename... THandlers>
323  inline void apply(TIterator it, TIterator end, THandlers&&... handlers) {
324  apply_impl(it, end, detail::make_handler<THandlers>(std::forward<THandlers>(handlers))...);
325  }
326 
327  template <typename TContainer, typename... THandlers>
328  inline void apply(TContainer& c, THandlers&&... handlers) {
329  using std::begin;
330  using std::end;
331  apply(begin(c), end(c), std::forward<THandlers>(handlers)...);
332  }
333 
334  template <typename... THandlers>
335  inline void apply(const osmium::memory::Buffer& buffer, THandlers&&... handlers) {
336  apply(buffer.cbegin(), buffer.cend(), std::forward<THandlers>(handlers)...);
337  }
338 
339 } // namespace osmium
340 
341 #endif // OSMIUM_VISITOR_HPP
osmium::geom::direction::forward
@ forward
Linestring has same direction as way.
reader_iterator.hpp
osmium::apply
void apply(TIterator it, TIterator end, THandlers &&... handlers)
Definition: visitor.hpp:323
osmium::osm_entity_bits::node
@ node
Definition: entity_bits.hpp:68
osmium::OSMObject
Definition: object.hpp:64
osmium::item_type::outer_ring
@ outer_ring
osmium::InnerRing
Definition: area.hpp:81
fwd.hpp
detail
Definition: attr.hpp:342
osmium::Node
Definition: node.hpp:48
osmium::item_type::tag_list
@ tag_list
osmium::item_type::way_node_list
@ way_node_list
osmium::item_type::relation_member_list
@ relation_member_list
osmium::memory::Buffer::cend
t_const_iterator< T > cend() const
Definition: buffer.hpp:789
osmium::apply_item
void apply_item(TItem &item, THandlers &&... handlers)
Definition: visitor.hpp:301
osmium::item_type::area
@ area
osmium::item_type::relation_member_list_with_full_members
@ relation_member_list_with_full_members
osmium::memory::Buffer
Definition: buffer.hpp:97
osmium::memory::Buffer::cbegin
t_const_iterator< T > cbegin() const
Definition: buffer.hpp:765
osmium::io::begin
InputIterator< Reader > begin(Reader &reader)
Definition: reader_iterator.hpp:43
osmium::unknown_type
Definition: item_type.hpp:195
osmium
Namespace for everything in the Osmium library.
Definition: assembler.hpp:53
osmium::item_type::node
@ node
osmium::memory::Item
Definition: item.hpp:105
osmium::item_type::undefined
@ undefined
osmium::osm_entity_bits::area
@ area
Definition: entity_bits.hpp:72
osmium::WayNodeList
Definition: way.hpp:55
osmium::osm_entity_bits::relation
@ relation
Definition: entity_bits.hpp:70
osmium::Way
Definition: way.hpp:72
entity.hpp
osmium::apply_flush
void apply_flush(THandlers &&... handlers)
Definition: visitor.hpp:308
osmium::Relation
Definition: relation.hpp:168
osmium::item_type::changeset_discussion
@ changeset_discussion
osmium::item_type::changeset
@ changeset
osmium::memory::Item::type
item_type type() const noexcept
Definition: item.hpp:171
handler.hpp
std
Definition: location.hpp:551
osmium::ChangesetDiscussion
Definition: changeset.hpp:132
osmium::Area
Definition: area.hpp:126
osmium::osm_entity_bits::way
@ way
Definition: entity_bits.hpp:69
osmium::TagList
Definition: tag.hpp:119
osm.hpp
osmium::item_type::way
@ way
buffer.hpp
osmium::OuterRing
Definition: area.hpp:61
osmium::osm_entity_bits::changeset
@ changeset
Definition: entity_bits.hpp:75
osmium::item_type::relation
@ relation
item_type.hpp
osmium::io::end
InputIterator< Reader > end(Reader &)
Definition: reader_iterator.hpp:47
osmium::RelationMemberList
Definition: relation.hpp:154
osmium::osm_entity_bits::type
type
Definition: entity_bits.hpp:63
osmium::OSMEntity
OSMEntity is the abstract base class for the OSMObject and Changeset classes.
Definition: entity.hpp:64
osmium::Changeset
An OSM Changeset, a group of changes made by a single user over a short period of time.
Definition: changeset.hpp:148
osmium::item_type::inner_ring
@ inner_ring
osmium::apply_impl
void apply_impl(TIterator it, TIterator end, THandlers &&... handlers)
Definition: visitor.hpp:315